Merge branch 'master' into webremote
38
3rdparty/chromaprint/.gitignore
vendored
@ -1,38 +0,0 @@
|
|||||||
CMakeFiles
|
|
||||||
CMakeCache.txt
|
|
||||||
Makefile
|
|
||||||
cmake_install.cmake
|
|
||||||
config.h
|
|
||||||
tests/all_tests
|
|
||||||
tools/fpgen
|
|
||||||
tools/fpcollect
|
|
||||||
*.exe
|
|
||||||
*.dll
|
|
||||||
*.so
|
|
||||||
*.a
|
|
||||||
tools/fpeval
|
|
||||||
tools/learn_filters
|
|
||||||
tools/decode
|
|
||||||
tools/chromagram
|
|
||||||
tools/resample
|
|
||||||
libchromaprint.pc
|
|
||||||
install_manifest.txt
|
|
||||||
tools/spectrogram
|
|
||||||
src/libchromaprint.so.*
|
|
||||||
*.vcxproj
|
|
||||||
*.vcxproj.*
|
|
||||||
*.dir
|
|
||||||
*.sln
|
|
||||||
*.suo
|
|
||||||
Debug
|
|
||||||
src/Debug
|
|
||||||
*.dll
|
|
||||||
*.lib
|
|
||||||
*.pdb
|
|
||||||
*.dll.manifest
|
|
||||||
*.exp
|
|
||||||
*.dylib
|
|
||||||
*.vcproj
|
|
||||||
*.user
|
|
||||||
*.ncb
|
|
||||||
src/Release
|
|
2
3rdparty/chromaprint/CMakeLists.txt
vendored
@ -103,7 +103,7 @@ if(WITH_FFTW3)
|
|||||||
message(STATUS "Using FFTW3 for FFT calculations")
|
message(STATUS "Using FFTW3 for FFT calculations")
|
||||||
endif(WITH_FFTW3)
|
endif(WITH_FFTW3)
|
||||||
|
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/chromaprint_config.h)
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
* modification -- Lennart */
|
* modification -- Lennart */
|
||||||
|
|
||||||
#if defined(HAVE_CONFIG_H)
|
#if defined(HAVE_CONFIG_H)
|
||||||
#include <config.h>
|
#include <chromaprint_config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
2
3rdparty/chromaprint/src/fft_lib.h
vendored
@ -22,7 +22,7 @@
|
|||||||
#define CHROMAPRINT_FFT_LIB_H_
|
#define CHROMAPRINT_FFT_LIB_H_
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
#include <chromaprint_config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_AVFFT
|
#ifdef WITH_AVFFT
|
||||||
|
4
3rdparty/chromaprint/src/fft_lib_avfft.cpp
vendored
@ -18,6 +18,10 @@
|
|||||||
* USA
|
* USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <libavutil/mem.h>
|
||||||
|
}
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "fft_lib_avfft.h"
|
#include "fft_lib_avfft.h"
|
||||||
|
|
||||||
|
2
3rdparty/chromaprint/src/fft_lib_avfft.h
vendored
@ -21,9 +21,7 @@
|
|||||||
#ifndef CHROMAPRINT_FFT_LIB_AVFFT_H_
|
#ifndef CHROMAPRINT_FFT_LIB_AVFFT_H_
|
||||||
#define CHROMAPRINT_FFT_LIB_AVFFT_H_
|
#define CHROMAPRINT_FFT_LIB_AVFFT_H_
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <libavcodec/avcodec.h>
|
|
||||||
#include <libavcodec/avfft.h>
|
#include <libavcodec/avfft.h>
|
||||||
}
|
}
|
||||||
#include "combined_buffer.h"
|
#include "combined_buffer.h"
|
||||||
|
0
3rdparty/chromaprint/src/foo.cpp
vendored
2
3rdparty/chromaprint/src/utils.h
vendored
@ -22,7 +22,7 @@
|
|||||||
#define CHROMAPRINT_UTILS_H_
|
#define CHROMAPRINT_UTILS_H_
|
||||||
|
|
||||||
#if defined(HAVE_CONFIG_H)
|
#if defined(HAVE_CONFIG_H)
|
||||||
#include <config.h>
|
#include <chromaprint_config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
4
3rdparty/qtsingleapplication/qtlocalpeer.cpp
vendored
@ -107,6 +107,7 @@ QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId)
|
|||||||
+ QLatin1Char('/') + socketName
|
+ QLatin1Char('/') + socketName
|
||||||
+ QLatin1String("-lockfile");
|
+ QLatin1String("-lockfile");
|
||||||
lockFile.setFileName(lockName);
|
lockFile.setFileName(lockName);
|
||||||
|
lockFileCreated = !lockFile.exists();
|
||||||
lockFile.open(QIODevice::ReadWrite);
|
lockFile.open(QIODevice::ReadWrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,5 +213,6 @@ void QtLocalPeer::receiveConnection()
|
|||||||
|
|
||||||
QtLocalPeer::~QtLocalPeer ()
|
QtLocalPeer::~QtLocalPeer ()
|
||||||
{
|
{
|
||||||
lockFile.remove();
|
if (lockFileCreated)
|
||||||
|
lockFile.remove();
|
||||||
}
|
}
|
||||||
|
1
3rdparty/qtsingleapplication/qtlocalpeer.h
vendored
@ -81,4 +81,5 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static const char* ack;
|
static const char* ack;
|
||||||
|
bool lockFileCreated;
|
||||||
};
|
};
|
||||||
|
483
3rdparty/sha2/sha2.cpp
vendored
@ -126,8 +126,6 @@ typedef u_int64_t sha2_word64; /* Exactly 8 bytes */
|
|||||||
/*** SHA-256/384/512 Various Length Definitions ***********************/
|
/*** SHA-256/384/512 Various Length Definitions ***********************/
|
||||||
/* NOTE: Most of these are in sha2.h */
|
/* NOTE: Most of these are in sha2.h */
|
||||||
#define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8)
|
#define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8)
|
||||||
#define SHA384_SHORT_BLOCK_LENGTH (SHA384_BLOCK_LENGTH - 16)
|
|
||||||
#define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16)
|
|
||||||
|
|
||||||
|
|
||||||
/*** ENDIAN REVERSAL MACROS *******************************************/
|
/*** ENDIAN REVERSAL MACROS *******************************************/
|
||||||
@ -200,8 +198,6 @@ typedef u_int64_t sha2_word64; /* Exactly 8 bytes */
|
|||||||
#define R(b,x) ((x) >> (b))
|
#define R(b,x) ((x) >> (b))
|
||||||
/* 32-bit Rotate-right (used in SHA-256): */
|
/* 32-bit Rotate-right (used in SHA-256): */
|
||||||
#define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b))))
|
#define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b))))
|
||||||
/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */
|
|
||||||
#define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b))))
|
|
||||||
|
|
||||||
/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */
|
/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */
|
||||||
#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
|
#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
|
||||||
@ -213,20 +209,12 @@ typedef u_int64_t sha2_word64; /* Exactly 8 bytes */
|
|||||||
#define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x)))
|
#define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x)))
|
||||||
#define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x)))
|
#define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x)))
|
||||||
|
|
||||||
/* Four of six logical functions used in SHA-384 and SHA-512: */
|
|
||||||
#define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x)))
|
|
||||||
#define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x)))
|
|
||||||
#define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x)))
|
|
||||||
#define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x)))
|
|
||||||
|
|
||||||
/*** INTERNAL FUNCTION PROTOTYPES *************************************/
|
/*** INTERNAL FUNCTION PROTOTYPES *************************************/
|
||||||
/* NOTE: These should not be accessed directly from outside this
|
/* NOTE: These should not be accessed directly from outside this
|
||||||
* library -- they are intended for private internal visibility/use
|
* library -- they are intended for private internal visibility/use
|
||||||
* only.
|
* only.
|
||||||
*/
|
*/
|
||||||
void SHA512_Last(SHA512_CTX*);
|
|
||||||
void SHA256_Transform(SHA256_CTX*, const sha2_word32*);
|
void SHA256_Transform(SHA256_CTX*, const sha2_word32*);
|
||||||
void SHA512_Transform(SHA512_CTX*, const sha2_word64*);
|
|
||||||
|
|
||||||
|
|
||||||
/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
|
/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
|
||||||
@ -262,73 +250,6 @@ const static sha2_word32 sha256_initial_hash_value[8] = {
|
|||||||
0x5be0cd19UL
|
0x5be0cd19UL
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Hash constant words K for SHA-384 and SHA-512: */
|
|
||||||
const static sha2_word64 K512[80] = {
|
|
||||||
0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
|
|
||||||
0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
|
|
||||||
0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
|
|
||||||
0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
|
|
||||||
0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
|
|
||||||
0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
|
|
||||||
0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
|
|
||||||
0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
|
|
||||||
0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
|
|
||||||
0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
|
|
||||||
0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
|
|
||||||
0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
|
|
||||||
0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
|
|
||||||
0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
|
|
||||||
0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
|
|
||||||
0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
|
|
||||||
0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
|
|
||||||
0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
|
|
||||||
0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
|
|
||||||
0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
|
|
||||||
0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
|
|
||||||
0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
|
|
||||||
0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
|
|
||||||
0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
|
|
||||||
0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
|
|
||||||
0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
|
|
||||||
0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
|
|
||||||
0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
|
|
||||||
0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
|
|
||||||
0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
|
|
||||||
0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
|
|
||||||
0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
|
|
||||||
0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
|
|
||||||
0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
|
|
||||||
0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
|
|
||||||
0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
|
|
||||||
0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
|
|
||||||
0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
|
|
||||||
0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
|
|
||||||
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Initial hash value H for SHA-384 */
|
|
||||||
const static sha2_word64 sha384_initial_hash_value[8] = {
|
|
||||||
0xcbbb9d5dc1059ed8ULL,
|
|
||||||
0x629a292a367cd507ULL,
|
|
||||||
0x9159015a3070dd17ULL,
|
|
||||||
0x152fecd8f70e5939ULL,
|
|
||||||
0x67332667ffc00b31ULL,
|
|
||||||
0x8eb44a8768581511ULL,
|
|
||||||
0xdb0c2e0d64f98fa7ULL,
|
|
||||||
0x47b5481dbefa4fa4ULL
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Initial hash value H for SHA-512 */
|
|
||||||
const static sha2_word64 sha512_initial_hash_value[8] = {
|
|
||||||
0x6a09e667f3bcc908ULL,
|
|
||||||
0xbb67ae8584caa73bULL,
|
|
||||||
0x3c6ef372fe94f82bULL,
|
|
||||||
0xa54ff53a5f1d36f1ULL,
|
|
||||||
0x510e527fade682d1ULL,
|
|
||||||
0x9b05688c2b3e6c1fULL,
|
|
||||||
0x1f83d9abfb41bd6bULL,
|
|
||||||
0x5be0cd19137e2179ULL
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Constant used by SHA256/384/512_End() functions for converting the
|
* Constant used by SHA256/384/512_End() functions for converting the
|
||||||
@ -664,408 +585,4 @@ char* SHA256_Data(const sha2_byte* data, size_t len, char digest[SHA256_DIGEST_S
|
|||||||
return SHA256_End(&context, digest);
|
return SHA256_End(&context, digest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*** SHA-512: *********************************************************/
|
|
||||||
void SHA512_Init(SHA512_CTX* context) {
|
|
||||||
if (context == (SHA512_CTX*)0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
MEMCPY_BCOPY(context->state, sha512_initial_hash_value, SHA512_DIGEST_LENGTH);
|
|
||||||
MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH);
|
|
||||||
context->bitcount[0] = context->bitcount[1] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SHA2_UNROLL_TRANSFORM
|
|
||||||
|
|
||||||
/* Unrolled SHA-512 round macros: */
|
|
||||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
|
||||||
|
|
||||||
#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \
|
|
||||||
REVERSE64(*data++, W512[j]); \
|
|
||||||
T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
|
|
||||||
K512[j] + W512[j]; \
|
|
||||||
(d) += T1, \
|
|
||||||
(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \
|
|
||||||
j++
|
|
||||||
|
|
||||||
|
|
||||||
#else /* BYTE_ORDER == LITTLE_ENDIAN */
|
|
||||||
|
|
||||||
#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \
|
|
||||||
T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
|
|
||||||
K512[j] + (W512[j] = *data++); \
|
|
||||||
(d) += T1; \
|
|
||||||
(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
|
|
||||||
j++
|
|
||||||
|
|
||||||
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
|
|
||||||
|
|
||||||
#define ROUND512(a,b,c,d,e,f,g,h) \
|
|
||||||
s0 = W512[(j+1)&0x0f]; \
|
|
||||||
s0 = sigma0_512(s0); \
|
|
||||||
s1 = W512[(j+14)&0x0f]; \
|
|
||||||
s1 = sigma1_512(s1); \
|
|
||||||
T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \
|
|
||||||
(W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \
|
|
||||||
(d) += T1; \
|
|
||||||
(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
|
|
||||||
j++
|
|
||||||
|
|
||||||
void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
|
|
||||||
sha2_word64 a, b, c, d, e, f, g, h, s0, s1;
|
|
||||||
sha2_word64 T1, *W512 = (sha2_word64*)context->buffer;
|
|
||||||
int j;
|
|
||||||
|
|
||||||
/* Initialize registers with the prev. intermediate value */
|
|
||||||
a = context->state[0];
|
|
||||||
b = context->state[1];
|
|
||||||
c = context->state[2];
|
|
||||||
d = context->state[3];
|
|
||||||
e = context->state[4];
|
|
||||||
f = context->state[5];
|
|
||||||
g = context->state[6];
|
|
||||||
h = context->state[7];
|
|
||||||
|
|
||||||
j = 0;
|
|
||||||
do {
|
|
||||||
ROUND512_0_TO_15(a,b,c,d,e,f,g,h);
|
|
||||||
ROUND512_0_TO_15(h,a,b,c,d,e,f,g);
|
|
||||||
ROUND512_0_TO_15(g,h,a,b,c,d,e,f);
|
|
||||||
ROUND512_0_TO_15(f,g,h,a,b,c,d,e);
|
|
||||||
ROUND512_0_TO_15(e,f,g,h,a,b,c,d);
|
|
||||||
ROUND512_0_TO_15(d,e,f,g,h,a,b,c);
|
|
||||||
ROUND512_0_TO_15(c,d,e,f,g,h,a,b);
|
|
||||||
ROUND512_0_TO_15(b,c,d,e,f,g,h,a);
|
|
||||||
} while (j < 16);
|
|
||||||
|
|
||||||
/* Now for the remaining rounds up to 79: */
|
|
||||||
do {
|
|
||||||
ROUND512(a,b,c,d,e,f,g,h);
|
|
||||||
ROUND512(h,a,b,c,d,e,f,g);
|
|
||||||
ROUND512(g,h,a,b,c,d,e,f);
|
|
||||||
ROUND512(f,g,h,a,b,c,d,e);
|
|
||||||
ROUND512(e,f,g,h,a,b,c,d);
|
|
||||||
ROUND512(d,e,f,g,h,a,b,c);
|
|
||||||
ROUND512(c,d,e,f,g,h,a,b);
|
|
||||||
ROUND512(b,c,d,e,f,g,h,a);
|
|
||||||
} while (j < 80);
|
|
||||||
|
|
||||||
/* Compute the current intermediate hash value */
|
|
||||||
context->state[0] += a;
|
|
||||||
context->state[1] += b;
|
|
||||||
context->state[2] += c;
|
|
||||||
context->state[3] += d;
|
|
||||||
context->state[4] += e;
|
|
||||||
context->state[5] += f;
|
|
||||||
context->state[6] += g;
|
|
||||||
context->state[7] += h;
|
|
||||||
|
|
||||||
/* Clean up */
|
|
||||||
a = b = c = d = e = f = g = h = T1 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* SHA2_UNROLL_TRANSFORM */
|
|
||||||
|
|
||||||
void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
|
|
||||||
sha2_word64 a, b, c, d, e, f, g, h, s0, s1;
|
|
||||||
sha2_word64 T1, T2, *W512 = (sha2_word64*)context->buffer;
|
|
||||||
int j;
|
|
||||||
|
|
||||||
/* Initialize registers with the prev. intermediate value */
|
|
||||||
a = context->state[0];
|
|
||||||
b = context->state[1];
|
|
||||||
c = context->state[2];
|
|
||||||
d = context->state[3];
|
|
||||||
e = context->state[4];
|
|
||||||
f = context->state[5];
|
|
||||||
g = context->state[6];
|
|
||||||
h = context->state[7];
|
|
||||||
|
|
||||||
j = 0;
|
|
||||||
do {
|
|
||||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
|
||||||
/* Convert TO host byte order */
|
|
||||||
REVERSE64(*data++, W512[j]);
|
|
||||||
/* Apply the SHA-512 compression function to update a..h */
|
|
||||||
T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
|
|
||||||
#else /* BYTE_ORDER == LITTLE_ENDIAN */
|
|
||||||
/* Apply the SHA-512 compression function to update a..h with copy */
|
|
||||||
T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++);
|
|
||||||
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
|
|
||||||
T2 = Sigma0_512(a) + Maj(a, b, c);
|
|
||||||
h = g;
|
|
||||||
g = f;
|
|
||||||
f = e;
|
|
||||||
e = d + T1;
|
|
||||||
d = c;
|
|
||||||
c = b;
|
|
||||||
b = a;
|
|
||||||
a = T1 + T2;
|
|
||||||
|
|
||||||
j++;
|
|
||||||
} while (j < 16);
|
|
||||||
|
|
||||||
do {
|
|
||||||
/* Part of the message block expansion: */
|
|
||||||
s0 = W512[(j+1)&0x0f];
|
|
||||||
s0 = sigma0_512(s0);
|
|
||||||
s1 = W512[(j+14)&0x0f];
|
|
||||||
s1 = sigma1_512(s1);
|
|
||||||
|
|
||||||
/* Apply the SHA-512 compression function to update a..h */
|
|
||||||
T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] +
|
|
||||||
(W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);
|
|
||||||
T2 = Sigma0_512(a) + Maj(a, b, c);
|
|
||||||
h = g;
|
|
||||||
g = f;
|
|
||||||
f = e;
|
|
||||||
e = d + T1;
|
|
||||||
d = c;
|
|
||||||
c = b;
|
|
||||||
b = a;
|
|
||||||
a = T1 + T2;
|
|
||||||
|
|
||||||
j++;
|
|
||||||
} while (j < 80);
|
|
||||||
|
|
||||||
/* Compute the current intermediate hash value */
|
|
||||||
context->state[0] += a;
|
|
||||||
context->state[1] += b;
|
|
||||||
context->state[2] += c;
|
|
||||||
context->state[3] += d;
|
|
||||||
context->state[4] += e;
|
|
||||||
context->state[5] += f;
|
|
||||||
context->state[6] += g;
|
|
||||||
context->state[7] += h;
|
|
||||||
|
|
||||||
/* Clean up */
|
|
||||||
a = b = c = d = e = f = g = h = T1 = T2 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* SHA2_UNROLL_TRANSFORM */
|
|
||||||
|
|
||||||
void SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) {
|
|
||||||
unsigned int freespace, usedspace;
|
|
||||||
|
|
||||||
if (len == 0) {
|
|
||||||
/* Calling with no data is valid - we do nothing */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sanity check: */
|
|
||||||
assert(context != (SHA512_CTX*)0 && data != (sha2_byte*)0);
|
|
||||||
|
|
||||||
usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
|
|
||||||
if (usedspace > 0) {
|
|
||||||
/* Calculate how much free space is available in the buffer */
|
|
||||||
freespace = SHA512_BLOCK_LENGTH - usedspace;
|
|
||||||
|
|
||||||
if (len >= freespace) {
|
|
||||||
/* Fill the buffer completely and process it */
|
|
||||||
MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace);
|
|
||||||
ADDINC128(context->bitcount, freespace << 3);
|
|
||||||
len -= freespace;
|
|
||||||
data += freespace;
|
|
||||||
SHA512_Transform(context, (sha2_word64*)context->buffer);
|
|
||||||
} else {
|
|
||||||
/* The buffer is not yet full */
|
|
||||||
MEMCPY_BCOPY(&context->buffer[usedspace], data, len);
|
|
||||||
ADDINC128(context->bitcount, len << 3);
|
|
||||||
/* Clean up: */
|
|
||||||
usedspace = freespace = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (len >= SHA512_BLOCK_LENGTH) {
|
|
||||||
/* Process as many complete blocks as we can */
|
|
||||||
SHA512_Transform(context, (sha2_word64*)data);
|
|
||||||
ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3);
|
|
||||||
len -= SHA512_BLOCK_LENGTH;
|
|
||||||
data += SHA512_BLOCK_LENGTH;
|
|
||||||
}
|
|
||||||
if (len > 0) {
|
|
||||||
/* There's left-overs, so save 'em */
|
|
||||||
MEMCPY_BCOPY(context->buffer, data, len);
|
|
||||||
ADDINC128(context->bitcount, len << 3);
|
|
||||||
}
|
|
||||||
/* Clean up: */
|
|
||||||
usedspace = freespace = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHA512_Last(SHA512_CTX* context) {
|
|
||||||
unsigned int usedspace;
|
|
||||||
|
|
||||||
usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
|
|
||||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
|
||||||
/* Convert FROM host byte order */
|
|
||||||
REVERSE64(context->bitcount[0],context->bitcount[0]);
|
|
||||||
REVERSE64(context->bitcount[1],context->bitcount[1]);
|
|
||||||
#endif
|
|
||||||
if (usedspace > 0) {
|
|
||||||
/* Begin padding with a 1 bit: */
|
|
||||||
context->buffer[usedspace++] = 0x80;
|
|
||||||
|
|
||||||
if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) {
|
|
||||||
/* Set-up for the last transform: */
|
|
||||||
MEMSET_BZERO(&context->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH - usedspace);
|
|
||||||
} else {
|
|
||||||
if (usedspace < SHA512_BLOCK_LENGTH) {
|
|
||||||
MEMSET_BZERO(&context->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace);
|
|
||||||
}
|
|
||||||
/* Do second-to-last transform: */
|
|
||||||
SHA512_Transform(context, (sha2_word64*)context->buffer);
|
|
||||||
|
|
||||||
/* And set-up for the last transform: */
|
|
||||||
MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH - 2);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Prepare for final transform: */
|
|
||||||
MEMSET_BZERO(context->buffer, SHA512_SHORT_BLOCK_LENGTH);
|
|
||||||
|
|
||||||
/* Begin padding with a 1 bit: */
|
|
||||||
*context->buffer = 0x80;
|
|
||||||
}
|
|
||||||
/* Store the length of input data (in bits): */
|
|
||||||
*(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH] = context->bitcount[1];
|
|
||||||
*(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH+8] = context->bitcount[0];
|
|
||||||
|
|
||||||
/* Final transform: */
|
|
||||||
SHA512_Transform(context, (sha2_word64*)context->buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) {
|
|
||||||
sha2_word64 *d = (sha2_word64*)digest;
|
|
||||||
|
|
||||||
/* Sanity check: */
|
|
||||||
assert(context != (SHA512_CTX*)0);
|
|
||||||
|
|
||||||
/* If no digest buffer is passed, we don't bother doing this: */
|
|
||||||
if (digest != (sha2_byte*)0) {
|
|
||||||
SHA512_Last(context);
|
|
||||||
|
|
||||||
/* Save the hash data for output: */
|
|
||||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
|
||||||
{
|
|
||||||
/* Convert TO host byte order */
|
|
||||||
int j;
|
|
||||||
for (j = 0; j < 8; j++) {
|
|
||||||
REVERSE64(context->state[j],context->state[j]);
|
|
||||||
*d++ = context->state[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
MEMCPY_BCOPY(d, context->state, SHA512_DIGEST_LENGTH);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Zero out state data */
|
|
||||||
MEMSET_BZERO(context, sizeof(SHA512_CTX));
|
|
||||||
}
|
|
||||||
|
|
||||||
char *SHA512_End(SHA512_CTX* context, char buffer[]) {
|
|
||||||
sha2_byte digest[SHA512_DIGEST_LENGTH], *d = digest;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* Sanity check: */
|
|
||||||
assert(context != (SHA512_CTX*)0);
|
|
||||||
|
|
||||||
if (buffer != (char*)0) {
|
|
||||||
SHA512_Final(digest, context);
|
|
||||||
|
|
||||||
for (i = 0; i < SHA512_DIGEST_LENGTH; i++) {
|
|
||||||
*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
|
|
||||||
*buffer++ = sha2_hex_digits[*d & 0x0f];
|
|
||||||
d++;
|
|
||||||
}
|
|
||||||
*buffer = (char)0;
|
|
||||||
} else {
|
|
||||||
MEMSET_BZERO(context, sizeof(SHA512_CTX));
|
|
||||||
}
|
|
||||||
MEMSET_BZERO(digest, SHA512_DIGEST_LENGTH);
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* SHA512_Data(const sha2_byte* data, size_t len, char digest[SHA512_DIGEST_STRING_LENGTH]) {
|
|
||||||
SHA512_CTX context;
|
|
||||||
|
|
||||||
SHA512_Init(&context);
|
|
||||||
SHA512_Update(&context, data, len);
|
|
||||||
return SHA512_End(&context, digest);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*** SHA-384: *********************************************************/
|
|
||||||
void SHA384_Init(SHA384_CTX* context) {
|
|
||||||
if (context == (SHA384_CTX*)0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
MEMCPY_BCOPY(context->state, sha384_initial_hash_value, SHA512_DIGEST_LENGTH);
|
|
||||||
MEMSET_BZERO(context->buffer, SHA384_BLOCK_LENGTH);
|
|
||||||
context->bitcount[0] = context->bitcount[1] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHA384_Update(SHA384_CTX* context, const sha2_byte* data, size_t len) {
|
|
||||||
SHA512_Update((SHA512_CTX*)context, data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) {
|
|
||||||
sha2_word64 *d = (sha2_word64*)digest;
|
|
||||||
|
|
||||||
/* Sanity check: */
|
|
||||||
assert(context != (SHA384_CTX*)0);
|
|
||||||
|
|
||||||
/* If no digest buffer is passed, we don't bother doing this: */
|
|
||||||
if (digest != (sha2_byte*)0) {
|
|
||||||
SHA512_Last((SHA512_CTX*)context);
|
|
||||||
|
|
||||||
/* Save the hash data for output: */
|
|
||||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
|
||||||
{
|
|
||||||
/* Convert TO host byte order */
|
|
||||||
int j;
|
|
||||||
for (j = 0; j < 6; j++) {
|
|
||||||
REVERSE64(context->state[j],context->state[j]);
|
|
||||||
*d++ = context->state[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
MEMCPY_BCOPY(d, context->state, SHA384_DIGEST_LENGTH);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Zero out state data */
|
|
||||||
MEMSET_BZERO(context, sizeof(SHA384_CTX));
|
|
||||||
}
|
|
||||||
|
|
||||||
char *SHA384_End(SHA384_CTX* context, char buffer[]) {
|
|
||||||
sha2_byte digest[SHA384_DIGEST_LENGTH], *d = digest;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* Sanity check: */
|
|
||||||
assert(context != (SHA384_CTX*)0);
|
|
||||||
|
|
||||||
if (buffer != (char*)0) {
|
|
||||||
SHA384_Final(digest, context);
|
|
||||||
|
|
||||||
for (i = 0; i < SHA384_DIGEST_LENGTH; i++) {
|
|
||||||
*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
|
|
||||||
*buffer++ = sha2_hex_digits[*d & 0x0f];
|
|
||||||
d++;
|
|
||||||
}
|
|
||||||
*buffer = (char)0;
|
|
||||||
} else {
|
|
||||||
MEMSET_BZERO(context, sizeof(SHA384_CTX));
|
|
||||||
}
|
|
||||||
MEMSET_BZERO(digest, SHA384_DIGEST_LENGTH);
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* SHA384_Data(const sha2_byte* data, size_t len, char digest[SHA384_DIGEST_STRING_LENGTH]) {
|
|
||||||
SHA384_CTX context;
|
|
||||||
|
|
||||||
SHA384_Init(&context);
|
|
||||||
SHA384_Update(&context, data, len);
|
|
||||||
return SHA384_End(&context, digest);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace clementine_sha2
|
} // namespace clementine_sha2
|
||||||
|
25
3rdparty/sha2/sha2.h
vendored
@ -48,12 +48,6 @@ namespace clementine_sha2 {
|
|||||||
static const int SHA256_BLOCK_LENGTH = 64;
|
static const int SHA256_BLOCK_LENGTH = 64;
|
||||||
static const int SHA256_DIGEST_LENGTH = 32;
|
static const int SHA256_DIGEST_LENGTH = 32;
|
||||||
static const int SHA256_DIGEST_STRING_LENGTH = (SHA256_DIGEST_LENGTH * 2 + 1);
|
static const int SHA256_DIGEST_STRING_LENGTH = (SHA256_DIGEST_LENGTH * 2 + 1);
|
||||||
static const int SHA384_BLOCK_LENGTH = 128;
|
|
||||||
static const int SHA384_DIGEST_LENGTH = 48;
|
|
||||||
static const int SHA384_DIGEST_STRING_LENGTH = (SHA384_DIGEST_LENGTH * 2 + 1);
|
|
||||||
static const int SHA512_BLOCK_LENGTH = 128;
|
|
||||||
static const int SHA512_DIGEST_LENGTH = 64;
|
|
||||||
static const int SHA512_DIGEST_STRING_LENGTH = (SHA512_DIGEST_LENGTH * 2 + 1);
|
|
||||||
|
|
||||||
|
|
||||||
/*** SHA-256/384/512 Context Structures *******************************/
|
/*** SHA-256/384/512 Context Structures *******************************/
|
||||||
@ -72,13 +66,6 @@ typedef struct _SHA256_CTX {
|
|||||||
u_int64_t bitcount;
|
u_int64_t bitcount;
|
||||||
u_int8_t buffer[SHA256_BLOCK_LENGTH];
|
u_int8_t buffer[SHA256_BLOCK_LENGTH];
|
||||||
} SHA256_CTX;
|
} SHA256_CTX;
|
||||||
typedef struct _SHA512_CTX {
|
|
||||||
u_int64_t state[8];
|
|
||||||
u_int64_t bitcount[2];
|
|
||||||
u_int8_t buffer[SHA512_BLOCK_LENGTH];
|
|
||||||
} SHA512_CTX;
|
|
||||||
|
|
||||||
typedef SHA512_CTX SHA384_CTX;
|
|
||||||
|
|
||||||
|
|
||||||
void SHA256_Init(SHA256_CTX *);
|
void SHA256_Init(SHA256_CTX *);
|
||||||
@ -87,18 +74,6 @@ void SHA256_Final(u_int8_t[SHA256_DIGEST_LENGTH], SHA256_CTX*);
|
|||||||
char* SHA256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]);
|
char* SHA256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]);
|
||||||
char* SHA256_Data(const u_int8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]);
|
char* SHA256_Data(const u_int8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]);
|
||||||
|
|
||||||
void SHA384_Init(SHA384_CTX*);
|
|
||||||
void SHA384_Update(SHA384_CTX*, const u_int8_t*, size_t);
|
|
||||||
void SHA384_Final(u_int8_t[SHA384_DIGEST_LENGTH], SHA384_CTX*);
|
|
||||||
char* SHA384_End(SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]);
|
|
||||||
char* SHA384_Data(const u_int8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH]);
|
|
||||||
|
|
||||||
void SHA512_Init(SHA512_CTX*);
|
|
||||||
void SHA512_Update(SHA512_CTX*, const u_int8_t*, size_t);
|
|
||||||
void SHA512_Final(u_int8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*);
|
|
||||||
char* SHA512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]);
|
|
||||||
char* SHA512_Data(const u_int8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]);
|
|
||||||
|
|
||||||
} // namespace clementine_sha2
|
} // namespace clementine_sha2
|
||||||
|
|
||||||
#endif /* __CLEMENTINE_SHA2_H__ */
|
#endif /* __CLEMENTINE_SHA2_H__ */
|
||||||
|
31
3rdparty/taglib/mpeg/mpegfile.cpp
vendored
@ -433,9 +433,24 @@ long MPEG::File::firstFrameOffset()
|
|||||||
{
|
{
|
||||||
long position = 0;
|
long position = 0;
|
||||||
|
|
||||||
if(ID3v2Tag())
|
if(ID3v2Tag()) {
|
||||||
position = d->ID3v2Location + ID3v2Tag()->header()->completeTagSize();
|
position = d->ID3v2Location + ID3v2Tag()->header()->completeTagSize();
|
||||||
|
|
||||||
|
// Skip duplicate ID3v2 tags.
|
||||||
|
|
||||||
|
// Workaround for some faulty files that have duplicate ID3v2 tags.
|
||||||
|
// Combination of EAC and LAME creates such files when configured incorrectly.
|
||||||
|
|
||||||
|
long location;
|
||||||
|
while((location = findID3v2(position)) >= 0) {
|
||||||
|
seek(location);
|
||||||
|
const ID3v2::Header header(readBlock(ID3v2::Header::size()));
|
||||||
|
position = location + header.completeTagSize();
|
||||||
|
|
||||||
|
debug("MPEG::File::firstFrameOffset() - Duplicate ID3v2 tag found.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nextFrameOffset(position);
|
return nextFrameOffset(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -467,7 +482,7 @@ void MPEG::File::read(bool readProperties, Properties::ReadStyle propertiesStyle
|
|||||||
{
|
{
|
||||||
// Look for an ID3v2 tag
|
// Look for an ID3v2 tag
|
||||||
|
|
||||||
d->ID3v2Location = findID3v2();
|
d->ID3v2Location = findID3v2(0);
|
||||||
|
|
||||||
if(d->ID3v2Location >= 0) {
|
if(d->ID3v2Location >= 0) {
|
||||||
|
|
||||||
@ -510,7 +525,7 @@ void MPEG::File::read(bool readProperties, Properties::ReadStyle propertiesStyle
|
|||||||
ID3v1Tag(true);
|
ID3v1Tag(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
long MPEG::File::findID3v2()
|
long MPEG::File::findID3v2(long offset)
|
||||||
{
|
{
|
||||||
// This method is based on the contents of TagLib::File::find(), but because
|
// This method is based on the contents of TagLib::File::find(), but because
|
||||||
// of some subtlteies -- specifically the need to look for the bit pattern of
|
// of some subtlteies -- specifically the need to look for the bit pattern of
|
||||||
@ -534,9 +549,9 @@ long MPEG::File::findID3v2()
|
|||||||
|
|
||||||
long originalPosition = tell();
|
long originalPosition = tell();
|
||||||
|
|
||||||
// Start the search at the beginning of the file.
|
// Start the search at the offset.
|
||||||
|
|
||||||
seek(0);
|
seek(offset);
|
||||||
|
|
||||||
// This loop is the crux of the find method. There are three cases that we
|
// This loop is the crux of the find method. There are three cases that we
|
||||||
// want to account for:
|
// want to account for:
|
||||||
@ -547,7 +562,7 @@ long MPEG::File::findID3v2()
|
|||||||
// (2) The search pattern is wholly contained within the current buffer.
|
// (2) The search pattern is wholly contained within the current buffer.
|
||||||
//
|
//
|
||||||
// (3) The current buffer ends with a partial match of the pattern. We will
|
// (3) The current buffer ends with a partial match of the pattern. We will
|
||||||
// note this for use in the next itteration, where we will check for the rest
|
// note this for use in the next iteration, where we will check for the rest
|
||||||
// of the pattern.
|
// of the pattern.
|
||||||
|
|
||||||
for(buffer = readBlock(bufferSize()); buffer.size() > 0; buffer = readBlock(bufferSize())) {
|
for(buffer = readBlock(bufferSize()); buffer.size() > 0; buffer = readBlock(bufferSize())) {
|
||||||
@ -561,7 +576,7 @@ long MPEG::File::findID3v2()
|
|||||||
const int patternOffset = (bufferSize() - previousPartialMatch);
|
const int patternOffset = (bufferSize() - previousPartialMatch);
|
||||||
if(buffer.containsAt(ID3v2::Header::fileIdentifier(), 0, patternOffset)) {
|
if(buffer.containsAt(ID3v2::Header::fileIdentifier(), 0, patternOffset)) {
|
||||||
seek(originalPosition);
|
seek(originalPosition);
|
||||||
return bufferOffset - bufferSize() + previousPartialMatch;
|
return offset + bufferOffset - bufferSize() + previousPartialMatch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -570,7 +585,7 @@ long MPEG::File::findID3v2()
|
|||||||
long location = buffer.find(ID3v2::Header::fileIdentifier());
|
long location = buffer.find(ID3v2::Header::fileIdentifier());
|
||||||
if(location >= 0) {
|
if(location >= 0) {
|
||||||
seek(originalPosition);
|
seek(originalPosition);
|
||||||
return bufferOffset + location;
|
return offset + bufferOffset + location;
|
||||||
}
|
}
|
||||||
|
|
||||||
int firstSynchByte = buffer.find(char(uchar(255)));
|
int firstSynchByte = buffer.find(char(uchar(255)));
|
||||||
|
14
3rdparty/taglib/mpeg/mpegfile.h
vendored
@ -242,8 +242,8 @@ namespace TagLib {
|
|||||||
* if there is no valid ID3v2 tag. If \a create is true it will create
|
* if there is no valid ID3v2 tag. If \a create is true it will create
|
||||||
* an ID3v2 tag if one does not exist and returns a valid pointer.
|
* an ID3v2 tag if one does not exist and returns a valid pointer.
|
||||||
*
|
*
|
||||||
* \note This may return a valid pointer regardless of whether or not the
|
* \note This may return a valid pointer regardless of whether or not the
|
||||||
* file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the file
|
* file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the file
|
||||||
* on disk actually has an ID3v2 tag.
|
* on disk actually has an ID3v2 tag.
|
||||||
*
|
*
|
||||||
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
|
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
|
||||||
@ -261,8 +261,8 @@ namespace TagLib {
|
|||||||
* if there is no valid ID3v1 tag. If \a create is true it will create
|
* if there is no valid ID3v1 tag. If \a create is true it will create
|
||||||
* an ID3v1 tag if one does not exist and returns a valid pointer.
|
* an ID3v1 tag if one does not exist and returns a valid pointer.
|
||||||
*
|
*
|
||||||
* \note This may return a valid pointer regardless of whether or not the
|
* \note This may return a valid pointer regardless of whether or not the
|
||||||
* file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file
|
* file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file
|
||||||
* on disk actually has an ID3v1 tag.
|
* on disk actually has an ID3v1 tag.
|
||||||
*
|
*
|
||||||
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
|
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
|
||||||
@ -280,8 +280,8 @@ namespace TagLib {
|
|||||||
* if there is no valid APE tag. If \a create is true it will create
|
* if there is no valid APE tag. If \a create is true it will create
|
||||||
* an APE tag if one does not exist and returns a valid pointer.
|
* an APE tag if one does not exist and returns a valid pointer.
|
||||||
*
|
*
|
||||||
* \note This may return a valid pointer regardless of whether or not the
|
* \note This may return a valid pointer regardless of whether or not the
|
||||||
* file on disk has an APE tag. Use hasAPETag() to check if the file
|
* file on disk has an APE tag. Use hasAPETag() to check if the file
|
||||||
* on disk actually has an APE tag.
|
* on disk actually has an APE tag.
|
||||||
*
|
*
|
||||||
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
|
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
|
||||||
@ -370,7 +370,7 @@ namespace TagLib {
|
|||||||
File &operator=(const File &);
|
File &operator=(const File &);
|
||||||
|
|
||||||
void read(bool readProperties, Properties::ReadStyle propertiesStyle);
|
void read(bool readProperties, Properties::ReadStyle propertiesStyle);
|
||||||
long findID3v2();
|
long findID3v2(long offset);
|
||||||
long findID3v1();
|
long findID3v1();
|
||||||
void findAPE();
|
void findAPE();
|
||||||
|
|
||||||
|
3
3rdparty/vreen/vreen/cmake/CommonUtils.cmake
vendored
@ -102,9 +102,6 @@ macro(UPDATE_COMPILER_FLAGS target)
|
|||||||
elseif(${target}_TYPE STREQUAL "SHARED_LIBRARY")
|
elseif(${target}_TYPE STREQUAL "SHARED_LIBRARY")
|
||||||
update_cxx_compiler_flag(${target} "-fvisibility=hidden" HIDDEN_VISIBILITY)
|
update_cxx_compiler_flag(${target} "-fvisibility=hidden" HIDDEN_VISIBILITY)
|
||||||
endif()
|
endif()
|
||||||
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
|
||||||
update_cxx_compiler_flag(${target} "-flto" LTO)
|
|
||||||
endif()
|
|
||||||
set_target_properties(${target} PROPERTIES COMPILE_FLAGS "${COMPILER_FLAGS}")
|
set_target_properties(${target} PROPERTIES COMPILE_FLAGS "${COMPILER_FLAGS}")
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
|
23
3rdparty/vreen/vreen/src/api/audio.cpp
vendored
@ -210,6 +210,29 @@ IntReply *AudioProvider::removeFromLibrary(int aid, int oid)
|
|||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IdListReply *AudioProvider::setBroadcast(int aid, int oid, const IdList &targetIds)
|
||||||
|
{
|
||||||
|
Q_D(AudioProvider);
|
||||||
|
|
||||||
|
QVariantMap args;
|
||||||
|
args.insert("audio", QString("%1_%2").arg(oid).arg(aid));
|
||||||
|
args.insert("target_ids", join(targetIds));
|
||||||
|
|
||||||
|
auto reply = d->client->request<IdListReply>("audio.setBroadcast", args, ReplyPrivate::handleIdList);
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
IdListReply *AudioProvider::resetBroadcast(const IdList &targetIds)
|
||||||
|
{
|
||||||
|
Q_D(AudioProvider);
|
||||||
|
|
||||||
|
QVariantMap args;
|
||||||
|
args.insert("audio","");
|
||||||
|
args.insert("target_ids", join(targetIds));
|
||||||
|
auto reply = d->client->request<IdListReply>("audio.setBroadcast", args, ReplyPrivate::handleIdList);
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
AudioItemListReply *AudioProvider::getAudiosByIds(const QString &ids)
|
AudioItemListReply *AudioProvider::getAudiosByIds(const QString &ids)
|
||||||
{
|
{
|
||||||
Q_D(AudioProvider);
|
Q_D(AudioProvider);
|
||||||
|
4
3rdparty/vreen/vreen/src/api/audio.h
vendored
@ -26,6 +26,7 @@
|
|||||||
#define VK_AUDIO_H
|
#define VK_AUDIO_H
|
||||||
|
|
||||||
#include <QAbstractListModel>
|
#include <QAbstractListModel>
|
||||||
|
#include "vk_global.h"
|
||||||
#include "audioitem.h"
|
#include "audioitem.h"
|
||||||
#include "abstractlistmodel.h"
|
#include "abstractlistmodel.h"
|
||||||
#include "reply.h"
|
#include "reply.h"
|
||||||
@ -35,6 +36,7 @@ namespace Vreen {
|
|||||||
class Client;
|
class Client;
|
||||||
typedef ReplyBase<AudioItemList> AudioItemListReply;
|
typedef ReplyBase<AudioItemList> AudioItemListReply;
|
||||||
typedef ReplyBase<AudioAlbumItemList> AudioAlbumItemListReply;
|
typedef ReplyBase<AudioAlbumItemList> AudioAlbumItemListReply;
|
||||||
|
typedef ReplyBase<QList<int>> IdListReply;
|
||||||
|
|
||||||
class AudioProviderPrivate;
|
class AudioProviderPrivate;
|
||||||
class VK_SHARED_EXPORT AudioProvider : public QObject
|
class VK_SHARED_EXPORT AudioProvider : public QObject
|
||||||
@ -60,6 +62,8 @@ public:
|
|||||||
IntReply *getCount(int oid = 0);
|
IntReply *getCount(int oid = 0);
|
||||||
IntReply *addToLibrary(int aid, int oid, int gid = 0);
|
IntReply *addToLibrary(int aid, int oid, int gid = 0);
|
||||||
IntReply *removeFromLibrary(int aid, int oid);
|
IntReply *removeFromLibrary(int aid, int oid);
|
||||||
|
IdListReply *setBroadcast(int aid, int oid, const IdList& targetIds);
|
||||||
|
IdListReply *resetBroadcast(const IdList& targetIds);
|
||||||
protected:
|
protected:
|
||||||
QScopedPointer<AudioProviderPrivate> d_ptr;
|
QScopedPointer<AudioProviderPrivate> d_ptr;
|
||||||
};
|
};
|
||||||
|
10
3rdparty/vreen/vreen/src/api/reply.cpp
vendored
@ -122,6 +122,16 @@ void ReplyPrivate::_q_network_reply_error(QNetworkReply::NetworkError code)
|
|||||||
emit q->resultReady(response);
|
emit q->resultReady(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVariant ReplyPrivate::handleIdList(const QVariant &response)
|
||||||
|
{
|
||||||
|
IdList ids;
|
||||||
|
auto list = response.toList();
|
||||||
|
foreach (auto item, list) {
|
||||||
|
ids.append(item.toInt());
|
||||||
|
}
|
||||||
|
return QVariant::fromValue(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QVariant MessageListHandler::operator()(const QVariant &response)
|
QVariant MessageListHandler::operator()(const QVariant &response)
|
||||||
{
|
{
|
||||||
|
9
3rdparty/vreen/vreen/src/api/reply_p.h
vendored
@ -50,15 +50,16 @@ public:
|
|||||||
void _q_reply_finished();
|
void _q_reply_finished();
|
||||||
void _q_network_reply_error(QNetworkReply::NetworkError);
|
void _q_network_reply_error(QNetworkReply::NetworkError);
|
||||||
|
|
||||||
static QVariant handleInt(const QVariant &response) { return response.toInt(); }
|
static QVariant handleInt(const QVariant &response) { return response.toInt(); }
|
||||||
|
static QVariant handleIdList(const QVariant& response);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct MessageListHandler {
|
struct MessageListHandler {
|
||||||
MessageListHandler(int clientId) : clientId(clientId) {}
|
MessageListHandler(int clientId) : clientId(clientId) {}
|
||||||
QVariant operator()(const QVariant &response);
|
QVariant operator()(const QVariant &response);
|
||||||
|
|
||||||
int clientId;
|
int clientId;
|
||||||
};
|
};
|
||||||
|
|
||||||
} //namespace Vreen
|
} //namespace Vreen
|
||||||
|
@ -3,6 +3,7 @@ cmake_policy(SET CMP0011 OLD)
|
|||||||
|
|
||||||
include(CheckCXXCompilerFlag)
|
include(CheckCXXCompilerFlag)
|
||||||
include(FindPkgConfig)
|
include(FindPkgConfig)
|
||||||
|
include(cmake/C++11Compat.cmake)
|
||||||
include(cmake/Summary.cmake)
|
include(cmake/Summary.cmake)
|
||||||
include(cmake/Version.cmake)
|
include(cmake/Version.cmake)
|
||||||
include(cmake/Deb.cmake)
|
include(cmake/Deb.cmake)
|
||||||
@ -21,6 +22,13 @@ if (APPLE)
|
|||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --stdlib=libc++")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --stdlib=libc++")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
find_program(CCACHE_EXECUTABLE NAMES ccache)
|
||||||
|
if (CCACHE_EXECUTABLE)
|
||||||
|
message(STATUS "ccache found: will be used for compilation and linkage")
|
||||||
|
SET_PROPERTY(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_EXECUTABLE})
|
||||||
|
SET_PROPERTY(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE_EXECUTABLE})
|
||||||
|
endif ()
|
||||||
|
|
||||||
if (UNIX AND NOT APPLE)
|
if (UNIX AND NOT APPLE)
|
||||||
set(LINUX 1)
|
set(LINUX 1)
|
||||||
endif (UNIX AND NOT APPLE)
|
endif (UNIX AND NOT APPLE)
|
||||||
@ -49,11 +57,11 @@ pkg_check_modules(CHROMAPRINT libchromaprint)
|
|||||||
pkg_check_modules(GIO gio-2.0)
|
pkg_check_modules(GIO gio-2.0)
|
||||||
pkg_check_modules(GLIB glib-2.0)
|
pkg_check_modules(GLIB glib-2.0)
|
||||||
pkg_check_modules(GOBJECT gobject-2.0)
|
pkg_check_modules(GOBJECT gobject-2.0)
|
||||||
pkg_check_modules(GSTREAMER gstreamer-0.10)
|
pkg_check_modules(GSTREAMER REQUIRED gstreamer-1.0)
|
||||||
pkg_check_modules(GSTREAMER_APP gstreamer-app-0.10)
|
pkg_check_modules(GSTREAMER_APP REQUIRED gstreamer-app-1.0)
|
||||||
pkg_check_modules(GSTREAMER_BASE gstreamer-base-0.10)
|
pkg_check_modules(GSTREAMER_AUDIO REQUIRED gstreamer-audio-1.0)
|
||||||
pkg_check_modules(GSTREAMER_CDDA gstreamer-cdda-0.10)
|
pkg_check_modules(GSTREAMER_BASE REQUIRED gstreamer-base-1.0)
|
||||||
pkg_check_modules(GSTREAMER_TAG gstreamer-tag-0.10)
|
pkg_check_modules(GSTREAMER_TAG REQUIRED gstreamer-tag-1.0)
|
||||||
pkg_check_modules(INDICATEQT indicate-qt)
|
pkg_check_modules(INDICATEQT indicate-qt)
|
||||||
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)
|
||||||
@ -140,8 +148,8 @@ include_directories(${TAGLIB_INCLUDE_DIRS})
|
|||||||
include_directories(${QJSON_INCLUDE_DIRS})
|
include_directories(${QJSON_INCLUDE_DIRS})
|
||||||
include_directories(${GSTREAMER_INCLUDE_DIRS})
|
include_directories(${GSTREAMER_INCLUDE_DIRS})
|
||||||
include_directories(${GSTREAMER_APP_INCLUDE_DIRS})
|
include_directories(${GSTREAMER_APP_INCLUDE_DIRS})
|
||||||
|
include_directories(${GSTREAMER_AUDIO_INCLUDE_DIRS})
|
||||||
include_directories(${GSTREAMER_BASE_INCLUDE_DIRS})
|
include_directories(${GSTREAMER_BASE_INCLUDE_DIRS})
|
||||||
include_directories(${GSTREAMER_CDDA_INCLUDE_DIRS})
|
|
||||||
include_directories(${GSTREAMER_TAG_INCLUDE_DIRS})
|
include_directories(${GSTREAMER_TAG_INCLUDE_DIRS})
|
||||||
include_directories(${GLIB_INCLUDE_DIRS})
|
include_directories(${GLIB_INCLUDE_DIRS})
|
||||||
include_directories(${GLIBCONFIG_INCLUDE_DIRS})
|
include_directories(${GLIBCONFIG_INCLUDE_DIRS})
|
||||||
@ -199,6 +207,11 @@ optional_component(BOX ON "Box support"
|
|||||||
|
|
||||||
optional_component(VK ON "Vk.com support")
|
optional_component(VK ON "Vk.com support")
|
||||||
|
|
||||||
|
optional_component(SEAFILE ON "Seafile support"
|
||||||
|
DEPENDS "Google sparsehash" SPARSEHASH_INCLUDE_DIRS
|
||||||
|
DEPENDS "Taglib 1.8" "TAGLIB_VERSION VERSION_GREATER 1.7.999"
|
||||||
|
)
|
||||||
|
|
||||||
optional_component(AUDIOCD ON "Devices: Audio CD support"
|
optional_component(AUDIOCD ON "Devices: Audio CD support"
|
||||||
DEPENDS "libcdio" CDIO_FOUND
|
DEPENDS "libcdio" CDIO_FOUND
|
||||||
)
|
)
|
||||||
@ -368,10 +381,19 @@ if(GMOCK_INCLUDE_DIRS)
|
|||||||
endif(GTEST_INCLUDE_DIRS)
|
endif(GTEST_INCLUDE_DIRS)
|
||||||
endif(GMOCK_INCLUDE_DIRS)
|
endif(GMOCK_INCLUDE_DIRS)
|
||||||
|
|
||||||
# Never use the system's sha2.
|
# Use the system's sha2 if it's available.
|
||||||
add_subdirectory(3rdparty/sha2)
|
find_path(SHA2_INCLUDE_DIRS sha2.h)
|
||||||
set(SHA2_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/sha2)
|
find_library(SHA2_LIBRARIES sha2)
|
||||||
set(SHA2_LIBRARIES sha2)
|
if(SHA2_LIBRARIES AND SHA2_INCLUDE_DIRS)
|
||||||
|
message(STATUS "Using system sha2 library")
|
||||||
|
set(USE_SYSTEM_SHA2 ON)
|
||||||
|
else()
|
||||||
|
message(STATUS "Using builtin sha2 library")
|
||||||
|
set(USE_SYSTEM_SHA2 OFF)
|
||||||
|
add_subdirectory(3rdparty/sha2)
|
||||||
|
set(SHA2_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/sha2)
|
||||||
|
set(SHA2_LIBRARIES sha2)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Use our 3rdparty chromaprint if a system one wasn't found
|
# Use our 3rdparty chromaprint if a system one wasn't found
|
||||||
if(NOT CHROMAPRINT_FOUND)
|
if(NOT CHROMAPRINT_FOUND)
|
||||||
|
98
Changelog
@ -1,3 +1,101 @@
|
|||||||
|
Version 1.3:
|
||||||
|
Major features:
|
||||||
|
* Vk.com support
|
||||||
|
* Seafile support
|
||||||
|
* Add Ampache compatibility (through Subsonic service)
|
||||||
|
* Add new analyzer "Rainbow Dash"
|
||||||
|
* Answer to the ultimate question of life, the universe and everything
|
||||||
|
|
||||||
|
Other features:
|
||||||
|
* Add left click to fullsize cover on playing widget
|
||||||
|
* Add m4b support for non-drm files
|
||||||
|
* Ignore english articles for library sorting
|
||||||
|
* Previous track in dynamic random mix
|
||||||
|
* Improve the organize dialog
|
||||||
|
* Add playlist save preference
|
||||||
|
* Add a preference to disable the pause notification
|
||||||
|
* Add a preference tab to hide some internet services
|
||||||
|
* Add an option to disable inline song metadata editing
|
||||||
|
* Use a save dialog option instead of quick change menu
|
||||||
|
* Add ability to fetch lyrics from lololyrics.com
|
||||||
|
* Add support for monitors in portrait mode
|
||||||
|
* Add now playing widget mode
|
||||||
|
* Add icons to extra
|
||||||
|
* Add a source icon for CD tracks
|
||||||
|
* Allow user to remove directories
|
||||||
|
* Add ability to remove unavailable items from playlist
|
||||||
|
* Adds an import button to the transcode UI, allowing the user to pull in
|
||||||
|
all files in a folder heirarchy to be transcoded
|
||||||
|
* Allow user to pull in all files in a folder heirarchy to be transcoded
|
||||||
|
* Make it impossible to collapse either side of the MainWindow splitter
|
||||||
|
* Add menu items for updating and doing a full rescan of Google Drive
|
||||||
|
* Increase Soundcloud cover image size
|
||||||
|
* Ability to pause Spotify tracks
|
||||||
|
* Add the ability to add or remove a Spotify track to a Spotify playlist
|
||||||
|
through context menu
|
||||||
|
* Add Spotify tracks to Spotify playlists by drag and drop
|
||||||
|
* Add ability to get a link to share Spotify playlists and songs
|
||||||
|
* Add ability to automatically set podcast as listened after sucesfully sending
|
||||||
|
it to a device
|
||||||
|
* Add ability to order podcasts by age
|
||||||
|
* Allow user to download multiple podcasts at the same time
|
||||||
|
* Add ability to cancel podcast downloads in progress
|
||||||
|
* Allow user to hide listened podcast episodes
|
||||||
|
* Huge improvement of the speed at startup
|
||||||
|
* Improve performance of mass rating changes
|
||||||
|
* Improve ripping performance
|
||||||
|
* Persistent cache for pixmaps. Huge improvement of the performance when
|
||||||
|
scrolling the library for example
|
||||||
|
* Add AppData file for Clementine (for GNOME and KDE Software Centers)
|
||||||
|
|
||||||
|
Bugfixes:
|
||||||
|
* Fix crash when click on a SoundCloud entry in internet tab
|
||||||
|
* Fix crash when marking podcast as listened
|
||||||
|
* Fix crash after pressing OK in the device properties window
|
||||||
|
* Fix stop after track which doesn't remove now playing
|
||||||
|
* Fix play bleeding into next track after auto stop
|
||||||
|
* Fix analyzer framerate when mouseover play scrubber
|
||||||
|
* Fix issues with buffers sent to analyzer
|
||||||
|
* Fix block analyzer framerate
|
||||||
|
* Fix dbz possibility with small buffers at end of track
|
||||||
|
* Fix dbz possibility in moodbar
|
||||||
|
* Fix oversized album cover art
|
||||||
|
* Fix Grooveshark SSL errors
|
||||||
|
* Clean cover art from /tmp
|
||||||
|
* Fix the rendering of the little numbers in the boxes on queued items in
|
||||||
|
the playlist
|
||||||
|
* Fix parsing of MusicBrainz data for discid
|
||||||
|
* Fix random artifacting on nyanalyzer on startup
|
||||||
|
* Fix podcasts length issues (which caused issues with seeking for example)
|
||||||
|
* Fix too small equalizer window size
|
||||||
|
* Fix labels which don't inherit system text colors in the edit tag dialog
|
||||||
|
* Fix the mess of the queue manager after playlist re-sort
|
||||||
|
* Fix for queue ordering issue in the playlist view when using c-d to
|
||||||
|
dequeue a track
|
||||||
|
* Fix detection of parent-relative paths in playlist saving
|
||||||
|
* Fix path seperators issue when reading playlists
|
||||||
|
* Fix m3u parser issue when an artist's name has a hyphen
|
||||||
|
* Fix bug with percents when fetch the Jamendo catalogue
|
||||||
|
* Fix a little dropout when transition to next track
|
||||||
|
* Fix broken RockRadio.com for premium users
|
||||||
|
* Fix Subsonic login with + characters in the password
|
||||||
|
* Fix accents issue in when save playlist in xspf format
|
||||||
|
* Fix issues with some songs length thanks to Taglib. People with Taglib
|
||||||
|
installed on their system will have to wait a new release of Taglib
|
||||||
|
* Fix moodbars not generating correctly
|
||||||
|
* Fix socket leak in moodbar
|
||||||
|
* Fix memory leak in tagreader
|
||||||
|
* Remove Ubuntu One support
|
||||||
|
|
||||||
|
Build system changes:
|
||||||
|
* Update to gstreamer 1.0
|
||||||
|
* Don't compile vreen with link-time optimizations
|
||||||
|
* Use the system's sha2 library if it's available
|
||||||
|
* (Windows) Add libgmp-10.dll which is required by libgiognutls.dll
|
||||||
|
* (Fedora) Don't depend on libplist or usbmuxd
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Version 1.2.3:
|
Version 1.2.3:
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
* Fix compilation with GCC 4.9.
|
* Fix compilation with GCC 4.9.
|
||||||
|
9
cmake/C++11Compat.cmake
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Hacky stuff to make C++11 features work with old compilers.
|
||||||
|
|
||||||
|
if (CMAKE_COMPILER_IS_GNUCC)
|
||||||
|
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion
|
||||||
|
OUTPUT_VARIABLE GCC_VERSION)
|
||||||
|
if (GCC_VERSION VERSION_LESS 4.7)
|
||||||
|
add_definitions(-Doverride=)
|
||||||
|
endif()
|
||||||
|
endif()
|
@ -1,3 +1,3 @@
|
|||||||
# Increment this whenever the user needs to download a new blob
|
# Increment this whenever the user needs to download a new blob
|
||||||
# Remember to upload and sign the new version of the blob.
|
# Remember to upload and sign the new version of the blob.
|
||||||
set(SPOTIFY_BLOB_VERSION 14)
|
set(SPOTIFY_BLOB_VERSION 15)
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
<file>icons/22x22/edit-redo.png</file>
|
<file>icons/22x22/edit-redo.png</file>
|
||||||
<file>icons/22x22/edit-rename.png</file>
|
<file>icons/22x22/edit-rename.png</file>
|
||||||
<file>icons/22x22/edit-undo.png</file>
|
<file>icons/22x22/edit-undo.png</file>
|
||||||
|
<file>icons/22x22/enterprise.png</file>
|
||||||
<file>icons/22x22/folder-new.png</file>
|
<file>icons/22x22/folder-new.png</file>
|
||||||
<file>icons/22x22/folder.png</file>
|
<file>icons/22x22/folder.png</file>
|
||||||
<file>icons/22x22/folder-sound.png</file>
|
<file>icons/22x22/folder-sound.png</file>
|
||||||
@ -48,8 +49,10 @@
|
|||||||
<file>icons/22x22/go-up.png</file>
|
<file>icons/22x22/go-up.png</file>
|
||||||
<file>icons/22x22/help-about.png</file>
|
<file>icons/22x22/help-about.png</file>
|
||||||
<file>icons/22x22/help-hint.png</file>
|
<file>icons/22x22/help-hint.png</file>
|
||||||
|
<file>icons/22x22/hypnotoad.png</file>
|
||||||
<file>icons/22x22/input-keyboard.png</file>
|
<file>icons/22x22/input-keyboard.png</file>
|
||||||
<file>icons/22x22/ipodtouchicon.png</file>
|
<file>icons/22x22/ipodtouchicon.png</file>
|
||||||
|
<file>icons/22x22/kittens.png</file>
|
||||||
<file>icons/22x22/list-add.png</file>
|
<file>icons/22x22/list-add.png</file>
|
||||||
<file>icons/22x22/list-remove.png</file>
|
<file>icons/22x22/list-remove.png</file>
|
||||||
<file>icons/22x22/mail-message.png</file>
|
<file>icons/22x22/mail-message.png</file>
|
||||||
@ -113,6 +116,7 @@
|
|||||||
<file>icons/32x32/edit-redo.png</file>
|
<file>icons/32x32/edit-redo.png</file>
|
||||||
<file>icons/32x32/edit-rename.png</file>
|
<file>icons/32x32/edit-rename.png</file>
|
||||||
<file>icons/32x32/edit-undo.png</file>
|
<file>icons/32x32/edit-undo.png</file>
|
||||||
|
<file>icons/32x32/enterprise.png</file>
|
||||||
<file>icons/32x32/folder-new.png</file>
|
<file>icons/32x32/folder-new.png</file>
|
||||||
<file>icons/32x32/folder.png</file>
|
<file>icons/32x32/folder.png</file>
|
||||||
<file>icons/32x32/folder-sound.png</file>
|
<file>icons/32x32/folder-sound.png</file>
|
||||||
@ -124,8 +128,10 @@
|
|||||||
<file>icons/32x32/go-up.png</file>
|
<file>icons/32x32/go-up.png</file>
|
||||||
<file>icons/32x32/help-about.png</file>
|
<file>icons/32x32/help-about.png</file>
|
||||||
<file>icons/32x32/help-hint.png</file>
|
<file>icons/32x32/help-hint.png</file>
|
||||||
|
<file>icons/32x32/hypnotoad.png</file>
|
||||||
<file>icons/32x32/input-keyboard.png</file>
|
<file>icons/32x32/input-keyboard.png</file>
|
||||||
<file>icons/32x32/ipodtouchicon.png</file>
|
<file>icons/32x32/ipodtouchicon.png</file>
|
||||||
|
<file>icons/32x32/kittens.png</file>
|
||||||
<file>icons/32x32/list-add.png</file>
|
<file>icons/32x32/list-add.png</file>
|
||||||
<file>icons/32x32/list-remove.png</file>
|
<file>icons/32x32/list-remove.png</file>
|
||||||
<file>icons/32x32/mail-message.png</file>
|
<file>icons/32x32/mail-message.png</file>
|
||||||
@ -189,6 +195,7 @@
|
|||||||
<file>icons/48x48/edit-redo.png</file>
|
<file>icons/48x48/edit-redo.png</file>
|
||||||
<file>icons/48x48/edit-rename.png</file>
|
<file>icons/48x48/edit-rename.png</file>
|
||||||
<file>icons/48x48/edit-undo.png</file>
|
<file>icons/48x48/edit-undo.png</file>
|
||||||
|
<file>icons/48x48/enterprise.png</file>
|
||||||
<file>icons/48x48/folder-new.png</file>
|
<file>icons/48x48/folder-new.png</file>
|
||||||
<file>icons/48x48/folder.png</file>
|
<file>icons/48x48/folder.png</file>
|
||||||
<file>icons/48x48/folder-sound.png</file>
|
<file>icons/48x48/folder-sound.png</file>
|
||||||
@ -200,8 +207,10 @@
|
|||||||
<file>icons/48x48/go-up.png</file>
|
<file>icons/48x48/go-up.png</file>
|
||||||
<file>icons/48x48/help-about.png</file>
|
<file>icons/48x48/help-about.png</file>
|
||||||
<file>icons/48x48/help-hint.png</file>
|
<file>icons/48x48/help-hint.png</file>
|
||||||
|
<file>icons/48x48/hypnotoad.png</file>
|
||||||
<file>icons/48x48/input-keyboard.png</file>
|
<file>icons/48x48/input-keyboard.png</file>
|
||||||
<file>icons/48x48/ipodtouchicon.png</file>
|
<file>icons/48x48/ipodtouchicon.png</file>
|
||||||
|
<file>icons/48x48/kittens.png</file>
|
||||||
<file>icons/48x48/list-add.png</file>
|
<file>icons/48x48/list-add.png</file>
|
||||||
<file>icons/48x48/list-remove.png</file>
|
<file>icons/48x48/list-remove.png</file>
|
||||||
<file>icons/48x48/mail-message.png</file>
|
<file>icons/48x48/mail-message.png</file>
|
||||||
@ -325,14 +334,13 @@
|
|||||||
<file>providers/radiogfm.png</file>
|
<file>providers/radiogfm.png</file>
|
||||||
<file>providers/rockradio.png</file>
|
<file>providers/rockradio.png</file>
|
||||||
<file>providers/skydrive.png</file>
|
<file>providers/skydrive.png</file>
|
||||||
<file>providers/skyfm.png</file>
|
|
||||||
<file>providers/somafm.png</file>
|
<file>providers/somafm.png</file>
|
||||||
<file>providers/songkick.png</file>
|
<file>providers/songkick.png</file>
|
||||||
<file>providers/soundcloud.png</file>
|
<file>providers/soundcloud.png</file>
|
||||||
<file>providers/subsonic-32.png</file>
|
<file>providers/subsonic-32.png</file>
|
||||||
<file>providers/subsonic.png</file>
|
<file>providers/subsonic.png</file>
|
||||||
<file>providers/ubuntuone.png</file>
|
|
||||||
<file>providers/wikipedia.png</file>
|
<file>providers/wikipedia.png</file>
|
||||||
|
<file>rainbowdash.png</file>
|
||||||
<file>sample.mood</file>
|
<file>sample.mood</file>
|
||||||
<file>schema/device-schema.sql</file>
|
<file>schema/device-schema.sql</file>
|
||||||
<file>schema/jamendo.sql</file>
|
<file>schema/jamendo.sql</file>
|
||||||
@ -376,6 +384,7 @@
|
|||||||
<file>schema/schema-44.sql</file>
|
<file>schema/schema-44.sql</file>
|
||||||
<file>schema/schema-45.sql</file>
|
<file>schema/schema-45.sql</file>
|
||||||
<file>schema/schema-46.sql</file>
|
<file>schema/schema-46.sql</file>
|
||||||
|
<file>schema/schema-47.sql</file>
|
||||||
<file>schema/schema-4.sql</file>
|
<file>schema/schema-4.sql</file>
|
||||||
<file>schema/schema-5.sql</file>
|
<file>schema/schema-5.sql</file>
|
||||||
<file>schema/schema-6.sql</file>
|
<file>schema/schema-6.sql</file>
|
||||||
@ -414,5 +423,8 @@
|
|||||||
<file>vk/deactivated.gif</file>
|
<file>vk/deactivated.gif</file>
|
||||||
<file>providers/vk.png</file>
|
<file>providers/vk.png</file>
|
||||||
<file>vk/link.png</file>
|
<file>vk/link.png</file>
|
||||||
|
<file>providers/seafile.png</file>
|
||||||
|
<file>icons/32x32/internet-services.png</file>
|
||||||
|
<file>providers/radiotunes.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
BIN
data/icons/22x22/enterprise.png
Normal file
After Width: | Height: | Size: 881 B |
BIN
data/icons/22x22/hypnotoad.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
data/icons/22x22/kittens.png
Normal file
After Width: | Height: | Size: 1002 B |
BIN
data/icons/32x32/enterprise.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
data/icons/32x32/hypnotoad.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
data/icons/32x32/internet-services.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
BIN
data/icons/32x32/kittens.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
data/icons/48x48/enterprise.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
data/icons/48x48/hypnotoad.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
data/icons/48x48/kittens.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
@ -59,6 +59,13 @@
|
|||||||
</extract>
|
</extract>
|
||||||
<invalidIndicator value="Verifique se o nome do seu arquivo e sua"/>
|
<invalidIndicator value="Verifique se o nome do seu arquivo e sua"/>
|
||||||
</provider>
|
</provider>
|
||||||
|
<provider name="lololyrics.com" title="" charset="utf-8" url="http://api.lololyrics.com/0.5/getLyric?artist={artist}&track={title}">
|
||||||
|
<urlFormat replace="_@,;&\/"#" with="_"/>
|
||||||
|
<extract>
|
||||||
|
<item tag="<response>"/>
|
||||||
|
</extract>
|
||||||
|
<invalidIndicator value="ERROR"/>
|
||||||
|
</provider>
|
||||||
<provider name="loudson.gs" title="" charset="utf-8" url="http://www.loudson.gs/{a}/{artist}/{album}/{title}">
|
<provider name="loudson.gs" title="" charset="utf-8" url="http://www.loudson.gs/{a}/{artist}/{album}/{title}">
|
||||||
<urlFormat replace=" _@,;&\/"" with="-"/>
|
<urlFormat replace=" _@,;&\/"" with="-"/>
|
||||||
<urlFormat replace="." with=""/>
|
<urlFormat replace="." with=""/>
|
||||||
|
BIN
data/providers/radiotunes.png
Normal file
After Width: | Height: | Size: 595 B |
BIN
data/providers/seafile.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 864 B |
Before Width: | Height: | Size: 1.9 KiB |
BIN
data/rainbowdash.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
50
data/schema/schema-47.sql
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
CREATE TABLE seafile_songs(
|
||||||
|
title TEXT,
|
||||||
|
album TEXT,
|
||||||
|
artist TEXT,
|
||||||
|
albumartist TEXT,
|
||||||
|
composer TEXT,
|
||||||
|
track INTEGER,
|
||||||
|
disc INTEGER,
|
||||||
|
bpm REAL,
|
||||||
|
year INTEGER,
|
||||||
|
genre TEXT,
|
||||||
|
comment TEXT,
|
||||||
|
compilation INTEGER,
|
||||||
|
|
||||||
|
length INTEGER,
|
||||||
|
bitrate INTEGER,
|
||||||
|
samplerate INTEGER,
|
||||||
|
|
||||||
|
directory INTEGER NOT NULL,
|
||||||
|
filename TEXT NOT NULL,
|
||||||
|
mtime INTEGER NOT NULL,
|
||||||
|
ctime INTEGER NOT NULL,
|
||||||
|
filesize INTEGER NOT NULL,
|
||||||
|
sampler INTEGER NOT NULL DEFAULT 0,
|
||||||
|
art_automatic TEXT,
|
||||||
|
art_manual TEXT,
|
||||||
|
filetype INTEGER NOT NULL DEFAULT 0,
|
||||||
|
playcount INTEGER NOT NULL DEFAULT 0,
|
||||||
|
lastplayed INTEGER,
|
||||||
|
rating INTEGER,
|
||||||
|
forced_compilation_on INTEGER NOT NULL DEFAULT 0,
|
||||||
|
forced_compilation_off INTEGER NOT NULL DEFAULT 0,
|
||||||
|
effective_compilation NOT NULL DEFAULT 0,
|
||||||
|
skipcount INTEGER NOT NULL DEFAULT 0,
|
||||||
|
score INTEGER NOT NULL DEFAULT 0,
|
||||||
|
beginning INTEGER NOT NULL DEFAULT 0,
|
||||||
|
cue_path TEXT,
|
||||||
|
unavailable INTEGER DEFAULT 0,
|
||||||
|
effective_albumartist TEXT,
|
||||||
|
etag TEXT,
|
||||||
|
performer TEXT,
|
||||||
|
grouping TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE VIRTUAL TABLE seafile_songs_fts USING fts3 (
|
||||||
|
ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsperformer, ftsgrouping, ftsgenre, ftscomment,
|
||||||
|
tokenize=unicode
|
||||||
|
);
|
||||||
|
|
||||||
|
UPDATE schema_version SET version=47;
|
13
debian/control
vendored
@ -13,14 +13,15 @@ Build-Depends: debhelper (>= 7),
|
|||||||
libboost-serialization1.40-dev |
|
libboost-serialization1.40-dev |
|
||||||
libboost-serialization1.42-dev |
|
libboost-serialization1.42-dev |
|
||||||
libboost-serialization-dev,
|
libboost-serialization-dev,
|
||||||
|
libcdio-cdda1,
|
||||||
libglew1.5-dev |
|
libglew1.5-dev |
|
||||||
libglew-dev,
|
libglew-dev,
|
||||||
libqt4-dev,
|
libqt4-dev,
|
||||||
qt4-dev-tools,
|
qt4-dev-tools,
|
||||||
libqt4-opengl-dev,
|
libqt4-opengl-dev,
|
||||||
cmake,
|
cmake,
|
||||||
libgstreamer0.10-dev,
|
libgstreamer1.0-dev,
|
||||||
libgstreamer-plugins-base0.10-dev,
|
libgstreamer-plugins-base1.0-dev,
|
||||||
libgpod-dev,
|
libgpod-dev,
|
||||||
libimobiledevice-dev,
|
libimobiledevice-dev,
|
||||||
libplist-dev,
|
libplist-dev,
|
||||||
@ -43,10 +44,10 @@ Package: clementine
|
|||||||
Architecture: any
|
Architecture: any
|
||||||
Depends: ${shlibs:Depends}, ${misc:Depends},
|
Depends: ${shlibs:Depends}, ${misc:Depends},
|
||||||
libsqlite3-0,
|
libsqlite3-0,
|
||||||
gstreamer0.10-plugins-base,
|
gstreamer1.0-plugins-base,
|
||||||
gstreamer0.10-plugins-good,
|
gstreamer1.0-plugins-good,
|
||||||
gstreamer0.10-alsa | gstreamer0.10-audiosink,
|
gstreamer1.0-plugins-ugly,
|
||||||
gstreamer0.10-plugins-ugly,
|
gstreamer1.0-pulseaudio,
|
||||||
libprojectm-data | projectm-data,
|
libprojectm-data | projectm-data,
|
||||||
libqca2-plugin-ossl
|
libqca2-plugin-ossl
|
||||||
Description: Modern music player and library organiser inspired by Amarok 1.4
|
Description: Modern music player and library organiser inspired by Amarok 1.4
|
||||||
|
4
dist/CMakeLists.txt
vendored
@ -60,6 +60,10 @@ if (NOT APPLE)
|
|||||||
DESTINATION share/kde4/services
|
DESTINATION share/kde4/services
|
||||||
)
|
)
|
||||||
|
|
||||||
|
install(FILES clementine.appdata.xml
|
||||||
|
DESTINATION share/appdata
|
||||||
|
)
|
||||||
|
|
||||||
if(INSTALL_UBUNTU_ICONS)
|
if(INSTALL_UBUNTU_ICONS)
|
||||||
foreach(icon clementine-panel.png clementine-panel-grey.png)
|
foreach(icon clementine-panel.png clementine-panel-grey.png)
|
||||||
foreach(theme ubuntu-mono-dark ubuntu-mono-light)
|
foreach(theme ubuntu-mono-dark ubuntu-mono-light)
|
||||||
|
3894
dist/cacert.pem
vendored
Normal file
35
dist/clementine.appdata.xml
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- Copyright 2014 David Sansome <me@davidsansome.com> -->
|
||||||
|
<application>
|
||||||
|
<id type="desktop">clementine.desktop</id>
|
||||||
|
<metadata_license>CC0-1.0</metadata_license>
|
||||||
|
<project_license>GPL-3.0+</project_license>
|
||||||
|
<name>Clementine Music Player</name>
|
||||||
|
<summary>Plays music files and internet radio</summary>
|
||||||
|
<description>
|
||||||
|
<p>
|
||||||
|
Clementine is a multiplatform music player focusing on a fast and
|
||||||
|
easy-to-use interface for searching and playing your music.
|
||||||
|
</p>
|
||||||
|
<p>Summary of included features:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Search and play your local music library</li>
|
||||||
|
<li>Listen to internet radio from Last.fm, SomaFM and Magnatune</li>
|
||||||
|
<li>Tabbed playlists, import and export M3U, XSPF, PLS and ASX</li>
|
||||||
|
<li>Visualisations from projectM</li>
|
||||||
|
<li>Transcode music into MP3, Ogg Vorbis, Ogg Speex, FLAC or AA</li>
|
||||||
|
<li>Edit tags on MP3 and OGG files, organise your music</li>
|
||||||
|
<li>Download missing album cover art from Last.fm</li>
|
||||||
|
<li>Native desktop notifications using libnotify</li>
|
||||||
|
<li>Supports MPRIS, or remote control using the command-line</li>
|
||||||
|
<li>Remote control using a Wii Remote, MPRIS or the command-line</li>
|
||||||
|
<li>Copy music to your iPod, iPhone, MTP or mass-storage USB player</li>
|
||||||
|
</ul>
|
||||||
|
</description>
|
||||||
|
<screenshots>
|
||||||
|
<screenshot type="default" width="1139" height="724">https://clementine-player.github.io/pages/images/screenshots/clementine-1.2-1.png</screenshot>
|
||||||
|
<screenshot width="1080" height="724">https://clementine-player.github.io/pages/images/screenshots/clementine-1.2-2.png</screenshot>
|
||||||
|
</screenshots>
|
||||||
|
<url type="homepage">https://www.clementine-player.org</url>
|
||||||
|
<updatecontact>me@davidsansome.com</updatecontact>
|
||||||
|
</application>
|
22
dist/clementine.spec.in
vendored
@ -11,8 +11,7 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
|||||||
|
|
||||||
BuildRequires: desktop-file-utils liblastfm-devel taglib-devel gettext
|
BuildRequires: desktop-file-utils liblastfm-devel taglib-devel gettext
|
||||||
BuildRequires: qt4-devel boost-devel gcc-c++ glew-devel libgpod-devel
|
BuildRequires: qt4-devel boost-devel gcc-c++ glew-devel libgpod-devel
|
||||||
BuildRequires: cmake gstreamer-devel gstreamer-plugins-base-devel
|
BuildRequires: cmake gstreamer1-devel gstreamer1-plugins-base-devel
|
||||||
BuildRequires: libplist-devel usbmuxd-devel
|
|
||||||
BuildRequires: libmtp-devel protobuf-devel protobuf-compiler libcdio-devel
|
BuildRequires: libmtp-devel protobuf-devel protobuf-compiler libcdio-devel
|
||||||
BuildRequires: qjson-devel qca2-devel fftw-devel sparsehash-devel
|
BuildRequires: qjson-devel qca2-devel fftw-devel sparsehash-devel
|
||||||
BuildRequires: sqlite-devel pulseaudio-libs-devel
|
BuildRequires: sqlite-devel pulseaudio-libs-devel
|
||||||
@ -20,18 +19,18 @@ BuildRequires: sqlite-devel pulseaudio-libs-devel
|
|||||||
Requires: libgpod protobuf-lite libcdio qjson qca-ossl sqlite
|
Requires: libgpod protobuf-lite libcdio qjson qca-ossl sqlite
|
||||||
|
|
||||||
# GStreamer codec dependencies
|
# GStreamer codec dependencies
|
||||||
Requires: gstreamer-plugins-ugly
|
Requires: gstreamer1-plugins-ugly
|
||||||
|
|
||||||
%ifarch x86_64
|
%ifarch x86_64
|
||||||
Requires: gstreamer0.10(decoder-audio/x-vorbis)()(64bit)
|
Requires: gstreamer1(decoder-audio/x-vorbis)()(64bit)
|
||||||
Requires: gstreamer0.10(decoder-audio/x-flac)()(64bit)
|
Requires: gstreamer1(decoder-audio/x-flac)()(64bit)
|
||||||
Requires: gstreamer0.10(decoder-audio/x-speex)()(64bit)
|
Requires: gstreamer1(decoder-audio/x-speex)()(64bit)
|
||||||
Requires: gstreamer0.10(decoder-audio/x-wav)()(64bit)
|
Requires: gstreamer1(decoder-audio/x-wav)()(64bit)
|
||||||
%else
|
%else
|
||||||
Requires: gstreamer0.10(decoder-audio/x-vorbis)
|
Requires: gstreamer1(decoder-audio/x-vorbis)
|
||||||
Requires: gstreamer0.10(decoder-audio/x-flac)
|
Requires: gstreamer1(decoder-audio/x-flac)
|
||||||
Requires: gstreamer0.10(decoder-audio/x-speex)
|
Requires: gstreamer1(decoder-audio/x-speex)
|
||||||
Requires: gstreamer0.10(decoder-audio/x-wav)
|
Requires: gstreamer1(decoder-audio/x-wav)
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
%description
|
%description
|
||||||
@ -79,6 +78,7 @@ make clean
|
|||||||
%doc
|
%doc
|
||||||
%{_bindir}/clementine
|
%{_bindir}/clementine
|
||||||
%{_bindir}/clementine-tagreader
|
%{_bindir}/clementine-tagreader
|
||||||
|
%{_datadir}/appdata/clementine.appdata.xml
|
||||||
%{_datadir}/applications/clementine.desktop
|
%{_datadir}/applications/clementine.desktop
|
||||||
%{_datadir}/clementine/projectm-presets
|
%{_datadir}/clementine/projectm-presets
|
||||||
%{_datadir}/kde4/services/clementine-itms.protocol
|
%{_datadir}/kde4/services/clementine-itms.protocol
|
||||||
|
157
dist/copyright.py
vendored
Executable file
@ -0,0 +1,157 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
from subprocess import *
|
||||||
|
from sys import *
|
||||||
|
from os import rename, remove
|
||||||
|
from datetime import *
|
||||||
|
|
||||||
|
def pretty_years(s):
|
||||||
|
|
||||||
|
l = list(s)
|
||||||
|
l.sort()
|
||||||
|
|
||||||
|
start = None
|
||||||
|
prev = None
|
||||||
|
r = []
|
||||||
|
|
||||||
|
for x in l:
|
||||||
|
if prev is None:
|
||||||
|
start = x
|
||||||
|
prev = x
|
||||||
|
continue
|
||||||
|
|
||||||
|
if x == prev + 1:
|
||||||
|
prev = x
|
||||||
|
continue
|
||||||
|
|
||||||
|
if prev == start:
|
||||||
|
r.append("%i" % prev)
|
||||||
|
else:
|
||||||
|
r.append("%i-%i" % (start, prev))
|
||||||
|
|
||||||
|
start = x
|
||||||
|
prev = x
|
||||||
|
|
||||||
|
if not prev is None:
|
||||||
|
if prev == start:
|
||||||
|
r.append("%i" % prev)
|
||||||
|
else:
|
||||||
|
r.append("%i-%i" % (start, prev))
|
||||||
|
|
||||||
|
return ", ".join(r)
|
||||||
|
|
||||||
|
def order_by_year(a, b):
|
||||||
|
|
||||||
|
la = list(a[2])
|
||||||
|
la.sort()
|
||||||
|
|
||||||
|
lb = list(b[2])
|
||||||
|
lb.sort()
|
||||||
|
|
||||||
|
if la[0] < lb[0]:
|
||||||
|
return -1
|
||||||
|
elif la[0] > lb[0]:
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def gen_copyrights(f):
|
||||||
|
|
||||||
|
commits = []
|
||||||
|
data = {}
|
||||||
|
copyrights = []
|
||||||
|
|
||||||
|
for ln in Popen(["git", "blame", "--incremental", f], stdout=PIPE).stdout:
|
||||||
|
|
||||||
|
if ln.startswith("filename "):
|
||||||
|
if len(data) > 0:
|
||||||
|
commits.append(data)
|
||||||
|
data = {}
|
||||||
|
|
||||||
|
elif ln.startswith("author "):
|
||||||
|
data["author"] = ln[7:].strip()
|
||||||
|
|
||||||
|
elif ln.startswith("author-mail <"):
|
||||||
|
data["author-mail"] = ln[12:].strip()
|
||||||
|
|
||||||
|
elif ln.startswith("author-time "):
|
||||||
|
data["author-time"] = ln[11:].strip()
|
||||||
|
|
||||||
|
elif ln.startswith("author-tz "):
|
||||||
|
data["author-tz"] = ln[9:].strip()
|
||||||
|
|
||||||
|
with open(f,'r') as fi:
|
||||||
|
fil = fi.readlines()
|
||||||
|
for i in fil:
|
||||||
|
if -1 < i.find("Original Author"):
|
||||||
|
da = i.split(" ")
|
||||||
|
print f
|
||||||
|
copyrights.append(" Copyright %s, %s %s\n" % (da[3].strip(), da[1], da[2]))
|
||||||
|
|
||||||
|
by_author = {}
|
||||||
|
|
||||||
|
for c in commits:
|
||||||
|
try:
|
||||||
|
n = by_author[c["author"]]
|
||||||
|
except KeyError:
|
||||||
|
n = (c["author"], c["author-mail"], set())
|
||||||
|
by_author[c["author"]] = n
|
||||||
|
|
||||||
|
# FIXME: Handle time zones properly
|
||||||
|
year = datetime.fromtimestamp(int(c["author-time"])).year
|
||||||
|
|
||||||
|
n[2].add(year)
|
||||||
|
|
||||||
|
for an, a in list(by_author.iteritems()):
|
||||||
|
for bn, b in list(by_author.iteritems()):
|
||||||
|
if a is b:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if a[1] == b[1]:
|
||||||
|
a[2].update(b[2])
|
||||||
|
|
||||||
|
if by_author.has_key(an) and by_author.has_key(bn):
|
||||||
|
del by_author[bn]
|
||||||
|
|
||||||
|
copyright = list(by_author.itervalues())
|
||||||
|
copyright.sort(order_by_year)
|
||||||
|
|
||||||
|
for name, mail, years in copyright:
|
||||||
|
copyrights.append(" Copyright %s, %s %s\n" % (pretty_years(years), name, mail))
|
||||||
|
return copyrights
|
||||||
|
|
||||||
|
def change_file(filename):
|
||||||
|
content=[]
|
||||||
|
out=[]
|
||||||
|
extended=0
|
||||||
|
ends=0
|
||||||
|
with open(filename, "r") as fi:
|
||||||
|
content=fi.readlines()
|
||||||
|
|
||||||
|
copyrights=gen_copyrights(filename)
|
||||||
|
|
||||||
|
if -1 == content[0].find("/* This file is part of Clementine."):
|
||||||
|
print("File {} have no Clementine copyright info".format(filename))
|
||||||
|
return 0
|
||||||
|
|
||||||
|
for i in content:
|
||||||
|
if i.find("*/") != -1:
|
||||||
|
ends = 1
|
||||||
|
if i.find("Copyright ") != -1:
|
||||||
|
if not extended:
|
||||||
|
out.extend(copyrights)
|
||||||
|
extended = 1
|
||||||
|
|
||||||
|
if not ends:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
out.append(i)
|
||||||
|
|
||||||
|
with open(filename+'_tmp', "w") as fi:
|
||||||
|
fi.writelines(out)
|
||||||
|
rename(filename+'_tmp', filename)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
for files in argv[1:]:
|
||||||
|
change_file(files)
|
2684
dist/cpplint.py
vendored
10
dist/format.py
vendored
Normal file → Executable file
@ -1,3 +1,4 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
import argparse
|
import argparse
|
||||||
import difflib
|
import difflib
|
||||||
import os
|
import os
|
||||||
@ -20,6 +21,9 @@ def main():
|
|||||||
help='file extensions to reformat')
|
help='file extensions to reformat')
|
||||||
parser.add_argument('-i', dest='inplace', action='store_true',
|
parser.add_argument('-i', dest='inplace', action='store_true',
|
||||||
help='edit files inplace instead of showing a diff')
|
help='edit files inplace instead of showing a diff')
|
||||||
|
parser.add_argument('--files', nargs='*', metavar='FIL',
|
||||||
|
default=[],
|
||||||
|
help='get files as arguments insted of git')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -35,8 +39,14 @@ def main():
|
|||||||
|
|
||||||
if not changed_files:
|
if not changed_files:
|
||||||
print >> sys.stderr, 'No changes from %s' % args.ref
|
print >> sys.stderr, 'No changes from %s' % args.ref
|
||||||
|
|
||||||
|
if not args.files and not changed_files:
|
||||||
|
print >> sys.stderr, "Use --files to select files for reformat"
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if args.files:
|
||||||
|
changed_files = args.files
|
||||||
|
|
||||||
for filename in changed_files:
|
for filename in changed_files:
|
||||||
if not os.path.splitext(filename)[1][1:] in args.extension:
|
if not os.path.splitext(filename)[1][1:] in args.extension:
|
||||||
continue
|
continue
|
||||||
|
16
dist/macdeploy.py
vendored
@ -43,10 +43,10 @@ GSTREAMER_PLUGINS=[
|
|||||||
'libgstaudioresample.so',
|
'libgstaudioresample.so',
|
||||||
'libgstautodetect.so',
|
'libgstautodetect.so',
|
||||||
'libgstcoreelements.so',
|
'libgstcoreelements.so',
|
||||||
'libgstdecodebin2.so',
|
|
||||||
'libgstequalizer.so',
|
'libgstequalizer.so',
|
||||||
'libgstgdp.so',
|
'libgstgdp.so',
|
||||||
'libgstosxaudio.so',
|
'libgstosxaudio.so',
|
||||||
|
'libgstplayback.so',
|
||||||
'libgsttcp.so',
|
'libgsttcp.so',
|
||||||
'libgsttypefindfunctions.so',
|
'libgsttypefindfunctions.so',
|
||||||
'libgstudp.so',
|
'libgstudp.so',
|
||||||
@ -55,19 +55,19 @@ GSTREAMER_PLUGINS=[
|
|||||||
# Codecs
|
# Codecs
|
||||||
'libgstapetag.so',
|
'libgstapetag.so',
|
||||||
'libgstasf.so',
|
'libgstasf.so',
|
||||||
|
'libgstaudioparsers.so',
|
||||||
'libgstfaac.so',
|
'libgstfaac.so',
|
||||||
'libgstfaad.so',
|
'libgstfaad.so',
|
||||||
'libgstffmpeg.so',
|
|
||||||
'libgstflac.so',
|
'libgstflac.so',
|
||||||
'libgstid3demux.so',
|
'libgstid3demux.so',
|
||||||
|
'libgstisomp4.so',
|
||||||
'libgstlame.so',
|
'libgstlame.so',
|
||||||
|
'libgstlibav.so',
|
||||||
'libgstmad.so',
|
'libgstmad.so',
|
||||||
'libgstmms.so',
|
'libgstmms.so',
|
||||||
'libgstmpegaudioparse.so',
|
# TODO: Bring back Musepack support.
|
||||||
'libgstmusepack.so',
|
|
||||||
'libgstogg.so',
|
'libgstogg.so',
|
||||||
'libgstopus.so',
|
'libgstopus.so',
|
||||||
'libgstqtdemux.so',
|
|
||||||
'libgstreplaygain.so',
|
'libgstreplaygain.so',
|
||||||
'libgstspeex.so',
|
'libgstspeex.so',
|
||||||
'libgsttaglib.so',
|
'libgsttaglib.so',
|
||||||
@ -90,10 +90,8 @@ GSTREAMER_PLUGINS=[
|
|||||||
]
|
]
|
||||||
|
|
||||||
GSTREAMER_SEARCH_PATH=[
|
GSTREAMER_SEARCH_PATH=[
|
||||||
'/target/lib/gstreamer-0.10',
|
'/target/lib/gstreamer-1.0',
|
||||||
'/target/libexec/gstreamer-0.10',
|
'/target/libexec/gstreamer-1.0',
|
||||||
'/sw/lib/gstreamer-0.10',
|
|
||||||
'/usr/local/lib/gstreamer-0.10',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
QT_PLUGINS = [
|
QT_PLUGINS = [
|
||||||
|
75
dist/windows/clementine.nsi.in
vendored
@ -194,20 +194,45 @@ Section "Delete old files" oldfiles
|
|||||||
Delete "$INSTDIR\libgnutls-26.dll"
|
Delete "$INSTDIR\libgnutls-26.dll"
|
||||||
Delete "$INSTDIR\libpng14-14.dll"
|
Delete "$INSTDIR\libpng14-14.dll"
|
||||||
Delete "$INSTDIR\libtasn1-3.dll"
|
Delete "$INSTDIR\libtasn1-3.dll"
|
||||||
|
|
||||||
|
; 1.2.3 Move to gstreamer-1.0
|
||||||
|
Delete "$INSTDIR\avcodec-53.dll"
|
||||||
|
Delete "$INSTDIR\avformat-53.dll"
|
||||||
|
Delete "$INSTDIR\avutil-51.dll"
|
||||||
|
Delete "$INSTDIR\libcdio-14.dll"
|
||||||
|
Delete "$INSTDIR\libgstapp-0.10-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstaudio-0.10-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstbase-0.10-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstcdda-0.10-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstcontroller-0.10-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstdataprotocol-0.10-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstfft-0.10-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstinterfaces-0.10-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstnet-0.10-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstnetbuffer-0.10-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstpbutils-0.10-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstreamer-0.10-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstriff-0.10-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstrtp-0.10-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstrtsp-0.10-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstsdp-0.10-0.dll"
|
||||||
|
Delete "$INSTDIR\libgsttag-0.10-0.dll"
|
||||||
|
Delete "$INSTDIR\libsoup-2.4-1.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstdecodebin2.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstffmpeg.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstmpegaudioparse.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstqtdemux.dll"
|
||||||
SectionEnd
|
SectionEnd
|
||||||
|
|
||||||
Section "Clementine" Clementine
|
Section "Clementine" Clementine
|
||||||
SetOutPath "$INSTDIR"
|
SetOutPath "$INSTDIR"
|
||||||
|
|
||||||
File "avcodec-53.dll"
|
|
||||||
File "avformat-53.dll"
|
|
||||||
File "avutil-51.dll"
|
|
||||||
File "clementine.exe"
|
File "clementine.exe"
|
||||||
File "clementine-tagreader.exe"
|
File "clementine-tagreader.exe"
|
||||||
File "clementine-spotifyblob.exe"
|
File "clementine-spotifyblob.exe"
|
||||||
File "clementine.ico"
|
File "clementine.ico"
|
||||||
File "glew32.dll"
|
File "glew32.dll"
|
||||||
File "libcdio-14.dll"
|
File "libcdio-16.dll"
|
||||||
File "libeay32.dll"
|
File "libeay32.dll"
|
||||||
File "libfaac.dll"
|
File "libfaac.dll"
|
||||||
File "libfaad.dll"
|
File "libfaad.dll"
|
||||||
@ -223,23 +248,20 @@ Section "Clementine" Clementine
|
|||||||
File "libgnutls-28.dll"
|
File "libgnutls-28.dll"
|
||||||
File "libgobject-2.0-0.dll"
|
File "libgobject-2.0-0.dll"
|
||||||
File "libgpg-error-0.dll"
|
File "libgpg-error-0.dll"
|
||||||
File "libgstapp-0.10-0.dll"
|
File "libgstapp-1.0-0.dll"
|
||||||
File "libgstaudio-0.10-0.dll"
|
File "libgstaudio-1.0-0.dll"
|
||||||
File "libgstbase-0.10-0.dll"
|
File "libgstbase-1.0-0.dll"
|
||||||
File "libgstcdda-0.10-0.dll"
|
File "libgstcontroller-1.0-0.dll"
|
||||||
File "libgstcontroller-0.10-0.dll"
|
File "libgstfft-1.0-0.dll"
|
||||||
File "libgstdataprotocol-0.10-0.dll"
|
File "libgstnet-1.0-0.dll"
|
||||||
File "libgstfft-0.10-0.dll"
|
File "libgstpbutils-1.0-0.dll"
|
||||||
File "libgstinterfaces-0.10-0.dll"
|
File "libgstreamer-1.0-0.dll"
|
||||||
File "libgstnet-0.10-0.dll"
|
File "libgstriff-1.0-0.dll"
|
||||||
File "libgstnetbuffer-0.10-0.dll"
|
File "libgstrtp-1.0-0.dll"
|
||||||
File "libgstpbutils-0.10-0.dll"
|
File "libgstrtsp-1.0-0.dll"
|
||||||
File "libgstreamer-0.10-0.dll"
|
File "libgstsdp-1.0-0.dll"
|
||||||
File "libgstriff-0.10-0.dll"
|
File "libgsttag-1.0-0.dll"
|
||||||
File "libgstrtp-0.10-0.dll"
|
File "libgstvideo-1.0-0.dll"
|
||||||
File "libgstrtsp-0.10-0.dll"
|
|
||||||
File "libgstsdp-0.10-0.dll"
|
|
||||||
File "libgsttag-0.10-0.dll"
|
|
||||||
File "libgthread-2.0-0.dll"
|
File "libgthread-2.0-0.dll"
|
||||||
File "libhogweed-2-4.dll"
|
File "libhogweed-2-4.dll"
|
||||||
File "libiconv-2.dll"
|
File "libiconv-2.dll"
|
||||||
@ -257,7 +279,6 @@ Section "Clementine" Clementine
|
|||||||
File "libplist.dll"
|
File "libplist.dll"
|
||||||
File "libprotobuf-8.dll"
|
File "libprotobuf-8.dll"
|
||||||
File "libqjson.dll"
|
File "libqjson.dll"
|
||||||
File "libsoup-2.4-1.dll"
|
|
||||||
File "libspeex-1.dll"
|
File "libspeex-1.dll"
|
||||||
File "libspotify.dll"
|
File "libspotify.dll"
|
||||||
File "libstdc++-6.dll"
|
File "libstdc++-6.dll"
|
||||||
@ -355,28 +376,28 @@ Section "Gstreamer plugins" gstreamer-plugins
|
|||||||
File "/oname=libgstasf.dll" "gstreamer-plugins\libgstasf.dll"
|
File "/oname=libgstasf.dll" "gstreamer-plugins\libgstasf.dll"
|
||||||
File "/oname=libgstaudioconvert.dll" "gstreamer-plugins\libgstaudioconvert.dll"
|
File "/oname=libgstaudioconvert.dll" "gstreamer-plugins\libgstaudioconvert.dll"
|
||||||
File "/oname=libgstaudiofx.dll" "gstreamer-plugins\libgstaudiofx.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=libgstaudioresample.dll" "gstreamer-plugins\libgstaudioresample.dll"
|
||||||
File "/oname=libgstaudiotestsrc.dll" "gstreamer-plugins\libgstaudiotestsrc.dll"
|
File "/oname=libgstaudiotestsrc.dll" "gstreamer-plugins\libgstaudiotestsrc.dll"
|
||||||
File "/oname=libgstautodetect.dll" "gstreamer-plugins\libgstautodetect.dll"
|
File "/oname=libgstautodetect.dll" "gstreamer-plugins\libgstautodetect.dll"
|
||||||
File "/oname=libgstcdio.dll" "gstreamer-plugins\libgstcdio.dll"
|
File "/oname=libgstcdio.dll" "gstreamer-plugins\libgstcdio.dll"
|
||||||
File "/oname=libgstcoreelements.dll" "gstreamer-plugins\libgstcoreelements.dll"
|
File "/oname=libgstcoreelements.dll" "gstreamer-plugins\libgstcoreelements.dll"
|
||||||
File "/oname=libgstdecodebin2.dll" "gstreamer-plugins\libgstdecodebin2.dll"
|
|
||||||
File "/oname=libgstdirectsoundsink.dll" "gstreamer-plugins\libgstdirectsoundsink.dll"
|
File "/oname=libgstdirectsoundsink.dll" "gstreamer-plugins\libgstdirectsoundsink.dll"
|
||||||
File "/oname=libgstequalizer.dll" "gstreamer-plugins\libgstequalizer.dll"
|
File "/oname=libgstequalizer.dll" "gstreamer-plugins\libgstequalizer.dll"
|
||||||
File "/oname=libgstfaac.dll" "gstreamer-plugins\libgstfaac.dll"
|
File "/oname=libgstfaac.dll" "gstreamer-plugins\libgstfaac.dll"
|
||||||
File "/oname=libgstfaad.dll" "gstreamer-plugins\libgstfaad.dll"
|
File "/oname=libgstfaad.dll" "gstreamer-plugins\libgstfaad.dll"
|
||||||
File "/oname=libgstffmpeg.dll" "gstreamer-plugins\libgstffmpeg.dll"
|
|
||||||
File "/oname=libgstflac.dll" "gstreamer-plugins\libgstflac.dll"
|
File "/oname=libgstflac.dll" "gstreamer-plugins\libgstflac.dll"
|
||||||
File "/oname=libgstgdp.dll" "gstreamer-plugins\libgstgdp.dll"
|
File "/oname=libgstgdp.dll" "gstreamer-plugins\libgstgdp.dll"
|
||||||
File "/oname=libgstgio.dll" "gstreamer-plugins\libgstgio.dll"
|
File "/oname=libgstgio.dll" "gstreamer-plugins\libgstgio.dll"
|
||||||
File "/oname=libgsticydemux.dll" "gstreamer-plugins\libgsticydemux.dll"
|
File "/oname=libgsticydemux.dll" "gstreamer-plugins\libgsticydemux.dll"
|
||||||
File "/oname=libgstid3demux.dll" "gstreamer-plugins\libgstid3demux.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=libgstlame.dll" "gstreamer-plugins\libgstlame.dll"
|
||||||
|
File "/oname=libgstlibav.dll" "gstreamer-plugins\libgstlibav.dll"
|
||||||
File "/oname=libgstmad.dll" "gstreamer-plugins\libgstmad.dll"
|
File "/oname=libgstmad.dll" "gstreamer-plugins\libgstmad.dll"
|
||||||
File "/oname=libgstmms.dll" "gstreamer-plugins\libgstmms.dll"
|
File "/oname=libgstmms.dll" "gstreamer-plugins\libgstmms.dll"
|
||||||
File "/oname=libgstmpegaudioparse.dll" "gstreamer-plugins\libgstmpegaudioparse.dll"
|
|
||||||
File "/oname=libgstogg.dll" "gstreamer-plugins\libgstogg.dll"
|
File "/oname=libgstogg.dll" "gstreamer-plugins\libgstogg.dll"
|
||||||
File "/oname=libgstqtdemux.dll" "gstreamer-plugins\libgstqtdemux.dll"
|
File "/oname=libgstplayback.dll" "gstreamer-plugins\libgstplayback.dll"
|
||||||
File "/oname=libgstreplaygain.dll" "gstreamer-plugins\libgstreplaygain.dll"
|
File "/oname=libgstreplaygain.dll" "gstreamer-plugins\libgstreplaygain.dll"
|
||||||
File "/oname=libgstsouphttpsrc.dll" "gstreamer-plugins\libgstsouphttpsrc.dll"
|
File "/oname=libgstsouphttpsrc.dll" "gstreamer-plugins\libgstsouphttpsrc.dll"
|
||||||
File "/oname=libgstspectrum.dll" "gstreamer-plugins\libgstspectrum.dll"
|
File "/oname=libgstspectrum.dll" "gstreamer-plugins\libgstspectrum.dll"
|
||||||
@ -1023,7 +1044,7 @@ Section "Uninstall"
|
|||||||
Delete "$INSTDIR\clementine-spotifyblob.exe"
|
Delete "$INSTDIR\clementine-spotifyblob.exe"
|
||||||
Delete "$INSTDIR\glew32.dll"
|
Delete "$INSTDIR\glew32.dll"
|
||||||
Delete "$INSTDIR\intl.dll"
|
Delete "$INSTDIR\intl.dll"
|
||||||
Delete "$INSTDIR\libcdio-14.dll"
|
Delete "$INSTDIR\libcdio-16.dll"
|
||||||
Delete "$INSTDIR\libeay32.dll"
|
Delete "$INSTDIR\libeay32.dll"
|
||||||
Delete "$INSTDIR\libexpat-1.dll"
|
Delete "$INSTDIR\libexpat-1.dll"
|
||||||
Delete "$INSTDIR\libfaac.dll"
|
Delete "$INSTDIR\libfaac.dll"
|
||||||
|
@ -100,17 +100,16 @@ bool MediaPipeline::Init(int sample_rate, int channels) {
|
|||||||
gst_app_src_set_callbacks(appsrc_, &callbacks, this, nullptr);
|
gst_app_src_set_callbacks(appsrc_, &callbacks, this, nullptr);
|
||||||
|
|
||||||
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
|
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
|
||||||
const int endianness = G_BIG_ENDIAN;
|
static const char* format = "S16BE";
|
||||||
#elif Q_BYTE_ORDER == Q_LITTLE_ENDIAN
|
#elif Q_BYTE_ORDER == Q_LITTLE_ENDIAN
|
||||||
const int endianness = G_LITTLE_ENDIAN;
|
static const char* format = "S16LE";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Set caps
|
// Set caps
|
||||||
GstCaps* caps = gst_caps_new_simple(
|
GstCaps* caps = gst_caps_new_simple(
|
||||||
"audio/x-raw-int", "endianness", G_TYPE_INT, endianness, "signed",
|
"audio/x-raw", "format", G_TYPE_STRING, format, "rate", G_TYPE_INT,
|
||||||
G_TYPE_BOOLEAN, TRUE, "width", G_TYPE_INT, 16, "depth", G_TYPE_INT, 16,
|
sample_rate, "channels", G_TYPE_INT, channels, "layout", G_TYPE_STRING,
|
||||||
"rate", G_TYPE_INT, sample_rate, "channels", G_TYPE_INT, channels,
|
"interleaved", nullptr);
|
||||||
nullptr);
|
|
||||||
|
|
||||||
gst_app_src_set_caps(appsrc_, caps);
|
gst_app_src_set_caps(appsrc_, caps);
|
||||||
gst_caps_unref(caps);
|
gst_caps_unref(caps);
|
||||||
@ -128,16 +127,18 @@ bool MediaPipeline::Init(int sample_rate, int channels) {
|
|||||||
void MediaPipeline::WriteData(const char* data, qint64 length) {
|
void MediaPipeline::WriteData(const char* data, qint64 length) {
|
||||||
if (!is_initialised()) return;
|
if (!is_initialised()) return;
|
||||||
|
|
||||||
GstBuffer* buffer = gst_buffer_new_and_alloc(length);
|
GstBuffer* buffer = gst_buffer_new_allocate(nullptr, length, nullptr);
|
||||||
|
GstMapInfo map_info;
|
||||||
|
gst_buffer_map(buffer, &map_info, GST_MAP_WRITE);
|
||||||
|
|
||||||
memcpy(GST_BUFFER_DATA(buffer), data, length);
|
memcpy(map_info.data, data, length);
|
||||||
|
|
||||||
GST_BUFFER_OFFSET(buffer) = offset_bytes_;
|
gst_buffer_unmap(buffer, &map_info);
|
||||||
GST_BUFFER_TIMESTAMP(buffer) = offset_bytes_ * kNsecPerSec / byte_rate_;
|
|
||||||
|
GST_BUFFER_PTS(buffer) = offset_bytes_ * kNsecPerSec / byte_rate_;
|
||||||
GST_BUFFER_DURATION(buffer) = length * kNsecPerSec / byte_rate_;
|
GST_BUFFER_DURATION(buffer) = length * kNsecPerSec / byte_rate_;
|
||||||
|
|
||||||
offset_bytes_ += length;
|
offset_bytes_ += length;
|
||||||
GST_BUFFER_OFFSET_END(buffer) = offset_bytes_;
|
|
||||||
|
|
||||||
gst_app_src_push_buffer(appsrc_, buffer);
|
gst_app_src_push_buffer(appsrc_, buffer);
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "spotifyclient.h"
|
#include "spotifyclient.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
@ -30,6 +31,7 @@
|
|||||||
|
|
||||||
#include "core/arraysize.h"
|
#include "core/arraysize.h"
|
||||||
#include "core/logging.h"
|
#include "core/logging.h"
|
||||||
|
#include "core/timeconstants.h"
|
||||||
#include "mediapipeline.h"
|
#include "mediapipeline.h"
|
||||||
#include "spotifykey.h"
|
#include "spotifykey.h"
|
||||||
#include "spotifymessages.pb.h"
|
#include "spotifymessages.pb.h"
|
||||||
@ -279,7 +281,7 @@ void SpotifyClient::MessageArrived(const pb::spotify::Message& message) {
|
|||||||
} else if (message.has_playback_request()) {
|
} else if (message.has_playback_request()) {
|
||||||
StartPlayback(message.playback_request());
|
StartPlayback(message.playback_request());
|
||||||
} else if (message.has_seek_request()) {
|
} else if (message.has_seek_request()) {
|
||||||
Seek(message.seek_request().offset_bytes());
|
Seek(message.seek_request().offset_nsec());
|
||||||
} else if (message.has_search_request()) {
|
} else if (message.has_search_request()) {
|
||||||
Search(message.search_request());
|
Search(message.search_request());
|
||||||
} else if (message.has_image_request()) {
|
} else if (message.has_image_request()) {
|
||||||
@ -292,6 +294,12 @@ void SpotifyClient::MessageArrived(const pb::spotify::Message& message) {
|
|||||||
SetPlaybackSettings(message.set_playback_settings_request());
|
SetPlaybackSettings(message.set_playback_settings_request());
|
||||||
} else if (message.has_browse_toplist_request()) {
|
} else if (message.has_browse_toplist_request()) {
|
||||||
BrowseToplist(message.browse_toplist_request());
|
BrowseToplist(message.browse_toplist_request());
|
||||||
|
} else if (message.has_pause_request()) {
|
||||||
|
SetPaused(message.pause_request());
|
||||||
|
} else if (message.has_add_tracks_to_playlist()) {
|
||||||
|
AddTracksToPlaylist(message.add_tracks_to_playlist());
|
||||||
|
} else if (message.has_remove_tracks_from_playlist()) {
|
||||||
|
RemoveTracksFromPlaylist(message.remove_tracks_from_playlist());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,6 +372,8 @@ void SpotifyClient::PlaylistContainerLoadedCallback(sp_playlistcontainer* pc,
|
|||||||
SpotifyClient* me = reinterpret_cast<SpotifyClient*>(userdata);
|
SpotifyClient* me = reinterpret_cast<SpotifyClient*>(userdata);
|
||||||
|
|
||||||
// Install callbacks on all the playlists
|
// Install callbacks on all the playlists
|
||||||
|
sp_playlist_add_callbacks(sp_session_starred_create(me->session_),
|
||||||
|
&me->get_playlists_callbacks_, me);
|
||||||
const int count = sp_playlistcontainer_num_playlists(pc);
|
const int count = sp_playlistcontainer_num_playlists(pc);
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
sp_playlist* playlist = sp_playlistcontainer_playlist(pc, i);
|
sp_playlist* playlist = sp_playlistcontainer_playlist(pc, i);
|
||||||
@ -432,6 +442,9 @@ void SpotifyClient::SendPlaylistList() {
|
|||||||
pb::spotify::Playlists::Playlist* msg = response->add_playlist();
|
pb::spotify::Playlists::Playlist* msg = response->add_playlist();
|
||||||
msg->set_index(i);
|
msg->set_index(i);
|
||||||
msg->set_name(sp_playlist_name(playlist));
|
msg->set_name(sp_playlist_name(playlist));
|
||||||
|
sp_user* playlist_owner = sp_playlist_owner(playlist);
|
||||||
|
msg->set_is_mine(sp_session_user(session_) == playlist_owner);
|
||||||
|
msg->set_owner(sp_user_display_name(playlist_owner));
|
||||||
|
|
||||||
sp_playlist_offline_status offline_status =
|
sp_playlist_offline_status offline_status =
|
||||||
sp_playlist_get_offline_status(session_, playlist);
|
sp_playlist_get_offline_status(session_, playlist);
|
||||||
@ -443,6 +456,13 @@ void SpotifyClient::SendPlaylistList() {
|
|||||||
} else if (offline_status == SP_PLAYLIST_OFFLINE_STATUS_WAITING) {
|
} else if (offline_status == SP_PLAYLIST_OFFLINE_STATUS_WAITING) {
|
||||||
msg->set_download_progress(0);
|
msg->set_download_progress(0);
|
||||||
}
|
}
|
||||||
|
msg->set_nb_tracks(sp_playlist_num_tracks(playlist));
|
||||||
|
// URI - Blugh
|
||||||
|
char uri[256];
|
||||||
|
sp_link* link = sp_link_create_from_playlist(playlist);
|
||||||
|
sp_link_as_string(link, uri, arraysize(uri));
|
||||||
|
sp_link_release(link);
|
||||||
|
msg->set_uri(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
SendMessage(message);
|
SendMessage(message);
|
||||||
@ -587,6 +607,77 @@ void SpotifyClient::PlaylistStateChangedForGetPlaylists(sp_playlist* pl,
|
|||||||
me->SendPlaylistList();
|
me->SendPlaylistList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SpotifyClient::AddTracksToPlaylist(
|
||||||
|
const pb::spotify::AddTracksToPlaylistRequest& req) {
|
||||||
|
// Get the playlist we want to update
|
||||||
|
sp_playlist* playlist =
|
||||||
|
GetPlaylist(req.playlist_type(), req.playlist_index());
|
||||||
|
if (!playlist) {
|
||||||
|
qLog(Error) << "Playlist " << req.playlist_type() << ","
|
||||||
|
<< req.playlist_index() << "not found";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the tracks we want to add
|
||||||
|
std::unique_ptr<sp_track* []> tracks_array(
|
||||||
|
new sp_track* [req.track_uri_size()]);
|
||||||
|
for (int i = 0; i < req.track_uri_size(); ++i) {
|
||||||
|
sp_link* track_link = sp_link_create_from_string(req.track_uri(i).c_str());
|
||||||
|
sp_track* track = sp_link_as_track(track_link);
|
||||||
|
sp_track_add_ref(track);
|
||||||
|
sp_link_release(track_link);
|
||||||
|
if (!track) {
|
||||||
|
qLog(Error) << "Track" << QString::fromStdString(req.track_uri(i))
|
||||||
|
<< "not found";
|
||||||
|
}
|
||||||
|
tracks_array[i] = track;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actually add the tracks to the playlist
|
||||||
|
if (sp_playlist_add_tracks(playlist, tracks_array.get(), req.track_uri_size(),
|
||||||
|
0 /* TODO: don't insert at a hardcoded position */,
|
||||||
|
session_) != SP_ERROR_OK) {
|
||||||
|
qLog(Error) << "Error when adding tracks!";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean everything
|
||||||
|
for (int i = 0; i < req.track_uri_size(); ++i) {
|
||||||
|
sp_track_release(tracks_array[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpotifyClient::RemoveTracksFromPlaylist(
|
||||||
|
const pb::spotify::RemoveTracksFromPlaylistRequest& req) {
|
||||||
|
// Get the playlist we want to update
|
||||||
|
sp_playlist* playlist =
|
||||||
|
GetPlaylist(req.playlist_type(), req.playlist_index());
|
||||||
|
if (!playlist) {
|
||||||
|
qLog(Error) << "Playlist " << req.playlist_type() << ","
|
||||||
|
<< req.playlist_index() << "not found";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the position of the tracks we want to remove
|
||||||
|
std::unique_ptr<int[]> tracks_indices_array(new int[req.track_index_size()]);
|
||||||
|
for (int i = 0; i < req.track_index_size(); ++i) {
|
||||||
|
tracks_indices_array[i] = req.track_index(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// WTF: sp_playlist_remove_tracks indexes start from the end for starred
|
||||||
|
// playlist, not from the beginning like other playlists: reverse them
|
||||||
|
if (req.playlist_type() == pb::spotify::Starred) {
|
||||||
|
int num_tracks = sp_playlist_num_tracks(playlist);
|
||||||
|
for (int i = 0; i < req.track_index_size(); i++) {
|
||||||
|
tracks_indices_array[i] = num_tracks - tracks_indices_array[i] - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sp_playlist_remove_tracks(playlist, tracks_indices_array.get(),
|
||||||
|
req.track_index_size()) != SP_ERROR_OK) {
|
||||||
|
qLog(Error) << "Error when removing tracks!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SpotifyClient::ConvertTrack(sp_track* track, pb::spotify::Track* pb) {
|
void SpotifyClient::ConvertTrack(sp_track* track, pb::spotify::Track* pb) {
|
||||||
sp_album* album = sp_track_album(track);
|
sp_album* album = sp_track_album(track);
|
||||||
|
|
||||||
@ -836,7 +927,7 @@ void SpotifyClient::StartPlayback(const pb::spotify::PlaybackRequest& req) {
|
|||||||
TryPlaybackAgain(pending_playback);
|
TryPlaybackAgain(pending_playback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpotifyClient::Seek(qint64 offset_bytes) {
|
void SpotifyClient::Seek(qint64 offset_nsec) {
|
||||||
// TODO
|
// TODO
|
||||||
qLog(Error) << "TODO seeking";
|
qLog(Error) << "TODO seeking";
|
||||||
}
|
}
|
||||||
@ -1014,6 +1105,10 @@ void SpotifyClient::BrowseToplist(
|
|||||||
pending_toplist_browses_[browse] = req;
|
pending_toplist_browses_[browse] = req;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SpotifyClient::SetPaused(const pb::spotify::PauseRequest& req) {
|
||||||
|
sp_session_player_play(session_, !req.paused());
|
||||||
|
}
|
||||||
|
|
||||||
void SpotifyClient::ToplistBrowseComplete(sp_toplistbrowse* result,
|
void SpotifyClient::ToplistBrowseComplete(sp_toplistbrowse* result,
|
||||||
void* userdata) {
|
void* userdata) {
|
||||||
SpotifyClient* me = reinterpret_cast<SpotifyClient*>(userdata);
|
SpotifyClient* me = reinterpret_cast<SpotifyClient*>(userdata);
|
||||||
|
@ -122,12 +122,16 @@ class SpotifyClient : public AbstractMessageHandler<pb::spotify::Message> {
|
|||||||
void Search(const pb::spotify::SearchRequest& req);
|
void Search(const pb::spotify::SearchRequest& req);
|
||||||
void LoadPlaylist(const pb::spotify::LoadPlaylistRequest& req);
|
void LoadPlaylist(const pb::spotify::LoadPlaylistRequest& req);
|
||||||
void SyncPlaylist(const pb::spotify::SyncPlaylistRequest& req);
|
void SyncPlaylist(const pb::spotify::SyncPlaylistRequest& req);
|
||||||
|
void AddTracksToPlaylist(const pb::spotify::AddTracksToPlaylistRequest& req);
|
||||||
|
void RemoveTracksFromPlaylist(
|
||||||
|
const pb::spotify::RemoveTracksFromPlaylistRequest& req);
|
||||||
void StartPlayback(const pb::spotify::PlaybackRequest& req);
|
void StartPlayback(const pb::spotify::PlaybackRequest& req);
|
||||||
void Seek(qint64 offset_bytes);
|
void Seek(qint64 offset_nsec);
|
||||||
void LoadImage(const QString& id_b64);
|
void LoadImage(const QString& id_b64);
|
||||||
void BrowseAlbum(const QString& uri);
|
void BrowseAlbum(const QString& uri);
|
||||||
void BrowseToplist(const pb::spotify::BrowseToplistRequest& req);
|
void BrowseToplist(const pb::spotify::BrowseToplistRequest& req);
|
||||||
void SetPlaybackSettings(const pb::spotify::PlaybackSettings& req);
|
void SetPlaybackSettings(const pb::spotify::PlaybackSettings& req);
|
||||||
|
void SetPaused(const pb::spotify::PauseRequest& req);
|
||||||
|
|
||||||
void SendPlaylistList();
|
void SendPlaylistList();
|
||||||
|
|
||||||
@ -191,7 +195,7 @@ class SpotifyClient : public AbstractMessageHandler<pb::spotify::Message> {
|
|||||||
QMap<sp_toplistbrowse*, pb::spotify::BrowseToplistRequest>
|
QMap<sp_toplistbrowse*, pb::spotify::BrowseToplistRequest>
|
||||||
pending_toplist_browses_;
|
pending_toplist_browses_;
|
||||||
|
|
||||||
QMap<sp_search*, QList<sp_albumbrowse*> > pending_search_album_browses_;
|
QMap<sp_search*, QList<sp_albumbrowse*>> pending_search_album_browses_;
|
||||||
QMap<sp_albumbrowse*, sp_search*> pending_search_album_browse_responses_;
|
QMap<sp_albumbrowse*, sp_search*> pending_search_album_browse_responses_;
|
||||||
|
|
||||||
QScopedPointer<MediaPipeline> media_pipeline_;
|
QScopedPointer<MediaPipeline> media_pipeline_;
|
||||||
|
@ -23,6 +23,7 @@ enum MsgType {
|
|||||||
STOP_AFTER = 17;
|
STOP_AFTER = 17;
|
||||||
GET_LIBRARY = 18;
|
GET_LIBRARY = 18;
|
||||||
RATE_SONG = 19;
|
RATE_SONG = 19;
|
||||||
|
GLOBAL_SEARCH = 100;
|
||||||
|
|
||||||
// Messages send by both
|
// Messages send by both
|
||||||
DISCONNECT = 2;
|
DISCONNECT = 2;
|
||||||
@ -53,6 +54,8 @@ enum MsgType {
|
|||||||
DOWNLOAD_QUEUE_EMPTY = 51;
|
DOWNLOAD_QUEUE_EMPTY = 51;
|
||||||
LIBRARY_CHUNK = 52;
|
LIBRARY_CHUNK = 52;
|
||||||
DOWNLOAD_TOTAL_SIZE = 53;
|
DOWNLOAD_TOTAL_SIZE = 53;
|
||||||
|
GLOBAL_SEARCH_RESULT = 54;
|
||||||
|
TRANSCODING_FILES = 55;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Valid Engine states
|
// Valid Engine states
|
||||||
@ -284,9 +287,25 @@ message ResponseDownloadTotalSize {
|
|||||||
optional int32 file_count = 2;
|
optional int32 file_count = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message RequestGlobalSearch {
|
||||||
|
optional string query = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResponseGlobalSearch {
|
||||||
|
optional int32 id = 1;
|
||||||
|
optional string query = 2;
|
||||||
|
optional string search_provider = 3;
|
||||||
|
repeated SongMetadata song_metadata = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResponseTranscoderStatus {
|
||||||
|
optional int32 processed = 1;
|
||||||
|
optional int32 total = 2;
|
||||||
|
}
|
||||||
|
|
||||||
// The message itself
|
// The message itself
|
||||||
message Message {
|
message Message {
|
||||||
optional int32 version = 1 [default=16];
|
optional int32 version = 1 [default=18];
|
||||||
optional MsgType type = 2 [default=UNKNOWN]; // What data is in the message?
|
optional MsgType type = 2 [default=UNKNOWN]; // What data is in the message?
|
||||||
|
|
||||||
optional RequestConnect request_connect = 21;
|
optional RequestConnect request_connect = 21;
|
||||||
@ -301,6 +320,7 @@ message Message {
|
|||||||
optional RequestClosePlaylist request_close_playlist = 29;
|
optional RequestClosePlaylist request_close_playlist = 29;
|
||||||
optional RequestDownloadSongs request_download_songs = 31;
|
optional RequestDownloadSongs request_download_songs = 31;
|
||||||
optional RequestRateSong request_rate_song = 35;
|
optional RequestRateSong request_rate_song = 35;
|
||||||
|
optional RequestGlobalSearch request_global_search = 37;
|
||||||
|
|
||||||
optional Repeat repeat = 13;
|
optional Repeat repeat = 13;
|
||||||
optional Shuffle shuffle = 14;
|
optional Shuffle shuffle = 14;
|
||||||
@ -318,4 +338,6 @@ message Message {
|
|||||||
optional ResponseSongOffer response_song_offer = 33;
|
optional ResponseSongOffer response_song_offer = 33;
|
||||||
optional ResponseLibraryChunk response_library_chunk = 34;
|
optional ResponseLibraryChunk response_library_chunk = 34;
|
||||||
optional ResponseDownloadTotalSize response_download_total_size = 36;
|
optional ResponseDownloadTotalSize response_download_total_size = 36;
|
||||||
|
optional ResponseGlobalSearch response_global_search = 38;
|
||||||
|
optional ResponseTranscoderStatus response_transcoder_status = 39;
|
||||||
}
|
}
|
||||||
|
@ -46,9 +46,13 @@ message Playlists {
|
|||||||
message Playlist {
|
message Playlist {
|
||||||
required int32 index = 1;
|
required int32 index = 1;
|
||||||
required string name = 2;
|
required string name = 2;
|
||||||
required bool is_offline = 3;
|
required int32 nb_tracks = 3;
|
||||||
|
required bool is_mine = 4;
|
||||||
|
required string owner= 5;
|
||||||
|
required bool is_offline = 6;
|
||||||
|
required string uri = 7;
|
||||||
// Offline sync progress between 0-100.
|
// Offline sync progress between 0-100.
|
||||||
optional int32 download_progress = 4;
|
optional int32 download_progress = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
repeated Playlist playlist = 1;
|
repeated Playlist playlist = 1;
|
||||||
@ -170,7 +174,7 @@ message BrowseToplistResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message SeekRequest {
|
message SeekRequest {
|
||||||
optional int64 offset_bytes = 1;
|
optional int64 offset_nsec = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Bitrate {
|
enum Bitrate {
|
||||||
@ -184,7 +188,23 @@ message PlaybackSettings {
|
|||||||
optional bool volume_normalisation = 2 [default = false];
|
optional bool volume_normalisation = 2 [default = false];
|
||||||
}
|
}
|
||||||
|
|
||||||
// NEXT_ID: 21
|
message PauseRequest {
|
||||||
|
optional bool paused = 1 [default = false];
|
||||||
|
}
|
||||||
|
|
||||||
|
message AddTracksToPlaylistRequest {
|
||||||
|
required PlaylistType playlist_type = 1;
|
||||||
|
optional int64 playlist_index = 2; // Used if playlist_index == UserPlaylist
|
||||||
|
repeated string track_uri = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RemoveTracksFromPlaylistRequest {
|
||||||
|
required PlaylistType playlist_type = 1;
|
||||||
|
optional int64 playlist_index = 2; // Used if playlist_index == UserPlaylist
|
||||||
|
repeated int64 track_index = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NEXT_ID: 25
|
||||||
message Message {
|
message Message {
|
||||||
// Not currently used
|
// Not currently used
|
||||||
optional int32 id = 18;
|
optional int32 id = 18;
|
||||||
@ -208,4 +228,8 @@ message Message {
|
|||||||
optional PlaybackSettings set_playback_settings_request = 17;
|
optional PlaybackSettings set_playback_settings_request = 17;
|
||||||
optional BrowseToplistRequest browse_toplist_request = 19;
|
optional BrowseToplistRequest browse_toplist_request = 19;
|
||||||
optional BrowseToplistResponse browse_toplist_response = 20;
|
optional BrowseToplistResponse browse_toplist_response = 20;
|
||||||
|
optional PauseRequest pause_request = 21;
|
||||||
|
// ID 22 unused.
|
||||||
|
optional AddTracksToPlaylistRequest add_tracks_to_playlist = 23;
|
||||||
|
optional RemoveTracksFromPlaylistRequest remove_tracks_from_playlist = 24;
|
||||||
}
|
}
|
||||||
|
@ -502,10 +502,9 @@ void TagReader::ParseOggTag(const TagLib::Ogg::FieldListMap& map,
|
|||||||
100);
|
100);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TagReader::SetVorbisComments(TagLib::Ogg::XiphComment* vorbis_comments,
|
void TagReader::SetVorbisComments(
|
||||||
const pb::tagreader::SongMetadata& song)
|
TagLib::Ogg::XiphComment* vorbis_comments,
|
||||||
const {
|
const pb::tagreader::SongMetadata& song) const {
|
||||||
|
|
||||||
vorbis_comments->addField("COMPOSER",
|
vorbis_comments->addField("COMPOSER",
|
||||||
StdStringToTaglibString(song.composer()), true);
|
StdStringToTaglibString(song.composer()), true);
|
||||||
vorbis_comments->addField("PERFORMER",
|
vorbis_comments->addField("PERFORMER",
|
||||||
@ -524,6 +523,9 @@ void TagReader::SetVorbisComments(TagLib::Ogg::XiphComment* vorbis_comments,
|
|||||||
vorbis_comments->addField(
|
vorbis_comments->addField(
|
||||||
"COMPILATION", StdStringToTaglibString(song.compilation() ? "1" : "0"),
|
"COMPILATION", StdStringToTaglibString(song.compilation() ? "1" : "0"),
|
||||||
true);
|
true);
|
||||||
|
|
||||||
|
vorbis_comments->addField("ALBUM ARTIST",
|
||||||
|
StdStringToTaglibString(song.albumartist()), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TagReader::SetFMPSStatisticsVorbisComments(
|
void TagReader::SetFMPSStatisticsVorbisComments(
|
||||||
@ -540,7 +542,6 @@ void TagReader::SetFMPSStatisticsVorbisComments(
|
|||||||
void TagReader::SetFMPSRatingVorbisComments(
|
void TagReader::SetFMPSRatingVorbisComments(
|
||||||
TagLib::Ogg::XiphComment* vorbis_comments,
|
TagLib::Ogg::XiphComment* vorbis_comments,
|
||||||
const pb::tagreader::SongMetadata& song) const {
|
const pb::tagreader::SongMetadata& song) const {
|
||||||
|
|
||||||
vorbis_comments->addField(
|
vorbis_comments->addField(
|
||||||
"FMPS_RATING", QStringToTaglibString(QString::number(song.rating())));
|
"FMPS_RATING", QStringToTaglibString(QString::number(song.rating())));
|
||||||
}
|
}
|
||||||
@ -723,6 +724,14 @@ bool TagReader::SaveSongRatingToFile(
|
|||||||
if (filename.isNull()) return false;
|
if (filename.isNull()) return false;
|
||||||
|
|
||||||
qLog(Debug) << "Saving song rating tags to" << filename;
|
qLog(Debug) << "Saving song rating tags to" << filename;
|
||||||
|
if (song.rating() < 0) {
|
||||||
|
// The FMPS spec says unrated == "tag not present". For us, no rating
|
||||||
|
// results in rating being -1, so don't write anything in that case.
|
||||||
|
// Actually, we should also remove tag set in this case, but in
|
||||||
|
// Clementine it is not possible to unset rating i.e. make a song "unrated".
|
||||||
|
qLog(Debug) << "Unrated: do nothing";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));
|
std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));
|
||||||
|
|
||||||
@ -945,38 +954,38 @@ bool TagReader::ReadCloudFile(const QUrl& download_url, const QString& title,
|
|||||||
pb::tagreader::SongMetadata* song) const {
|
pb::tagreader::SongMetadata* song) const {
|
||||||
qLog(Debug) << "Loading tags from" << title;
|
qLog(Debug) << "Loading tags from" << title;
|
||||||
|
|
||||||
CloudStream* stream = new CloudStream(download_url, title, size,
|
std::unique_ptr<CloudStream> stream(new CloudStream(
|
||||||
authorisation_header, network_);
|
download_url, title, size, authorisation_header, network_));
|
||||||
stream->Precache();
|
stream->Precache();
|
||||||
std::unique_ptr<TagLib::File> tag;
|
std::unique_ptr<TagLib::File> tag;
|
||||||
if (mime_type == "audio/mpeg" && title.endsWith(".mp3")) {
|
if (mime_type == "audio/mpeg" && title.endsWith(".mp3")) {
|
||||||
tag.reset(new TagLib::MPEG::File(stream, // Takes ownership.
|
tag.reset(new TagLib::MPEG::File(stream.get(),
|
||||||
TagLib::ID3v2::FrameFactory::instance(),
|
TagLib::ID3v2::FrameFactory::instance(),
|
||||||
TagLib::AudioProperties::Accurate));
|
TagLib::AudioProperties::Accurate));
|
||||||
} else if (mime_type == "audio/mp4" ||
|
} else if (mime_type == "audio/mp4" ||
|
||||||
(mime_type == "audio/mpeg" && title.endsWith(".m4a"))) {
|
(mime_type == "audio/mpeg" && title.endsWith(".m4a"))) {
|
||||||
tag.reset(
|
tag.reset(new TagLib::MP4::File(stream.get(), true,
|
||||||
new TagLib::MP4::File(stream, true, TagLib::AudioProperties::Accurate));
|
TagLib::AudioProperties::Accurate));
|
||||||
}
|
}
|
||||||
#ifdef TAGLIB_HAS_OPUS
|
#ifdef TAGLIB_HAS_OPUS
|
||||||
else if ((mime_type == "application/opus" || mime_type == "audio/opus" ||
|
else if ((mime_type == "application/opus" || mime_type == "audio/opus" ||
|
||||||
mime_type == "application/ogg" || mime_type == "audio/ogg") &&
|
mime_type == "application/ogg" || mime_type == "audio/ogg") &&
|
||||||
title.endsWith(".opus")) {
|
title.endsWith(".opus")) {
|
||||||
tag.reset(new TagLib::Ogg::Opus::File(stream, true,
|
tag.reset(new TagLib::Ogg::Opus::File(stream.get(), true,
|
||||||
TagLib::AudioProperties::Accurate));
|
TagLib::AudioProperties::Accurate));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else if (mime_type == "application/ogg" || mime_type == "audio/ogg") {
|
else if (mime_type == "application/ogg" || mime_type == "audio/ogg") {
|
||||||
tag.reset(new TagLib::Ogg::Vorbis::File(stream, true,
|
tag.reset(new TagLib::Ogg::Vorbis::File(stream.get(), true,
|
||||||
TagLib::AudioProperties::Accurate));
|
TagLib::AudioProperties::Accurate));
|
||||||
} else if (mime_type == "application/x-flac" || mime_type == "audio/flac" ||
|
} else if (mime_type == "application/x-flac" || mime_type == "audio/flac" ||
|
||||||
mime_type == "audio/x-flac") {
|
mime_type == "audio/x-flac") {
|
||||||
tag.reset(new TagLib::FLAC::File(stream,
|
tag.reset(new TagLib::FLAC::File(stream.get(),
|
||||||
TagLib::ID3v2::FrameFactory::instance(),
|
TagLib::ID3v2::FrameFactory::instance(),
|
||||||
true, TagLib::AudioProperties::Accurate));
|
true, TagLib::AudioProperties::Accurate));
|
||||||
} else if (mime_type == "audio/x-ms-wma") {
|
} else if (mime_type == "audio/x-ms-wma") {
|
||||||
tag.reset(
|
tag.reset(new TagLib::ASF::File(stream.get(), true,
|
||||||
new TagLib::ASF::File(stream, true, TagLib::AudioProperties::Accurate));
|
TagLib::AudioProperties::Accurate));
|
||||||
} else {
|
} else {
|
||||||
qLog(Debug) << "Unknown mime type for tagging:" << mime_type;
|
qLog(Debug) << "Unknown mime type for tagging:" << mime_type;
|
||||||
return false;
|
return false;
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
From 0b62ebc38d1cc0202c6f57c4e096fa0b68a41baf Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Sansome <me@davidsansome.com>
|
|
||||||
Date: Sun, 27 May 2012 17:00:32 +0100
|
|
||||||
Subject: [PATCH] Protect calls to fftwf_plan_dft_r2c_1d with a mutex
|
|
||||||
|
|
||||||
---
|
|
||||||
plugin/gstfftwspectrum.c | 4 ++++
|
|
||||||
1 files changed, 4 insertions(+), 0 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/plugin/gstfftwspectrum.c b/plugin/gstfftwspectrum.c
|
|
||||||
index 147e606..f6e2427 100644
|
|
||||||
--- a/plugin/gstfftwspectrum.c
|
|
||||||
+++ b/plugin/gstfftwspectrum.c
|
|
||||||
@@ -302,10 +302,14 @@ alloc_fftw_data (GstFFTWSpectrum *conv)
|
|
||||||
* outputs are the hermetian conjugates). This should be optimal for
|
|
||||||
* implementing filters.
|
|
||||||
*/
|
|
||||||
+
|
|
||||||
+ static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
|
|
||||||
+ g_static_mutex_lock(&mutex);
|
|
||||||
conv->fftw_plan
|
|
||||||
= fftwf_plan_dft_r2c_1d(conv->size, conv->fftw_in,
|
|
||||||
(fftwf_complex *) conv->fftw_out,
|
|
||||||
conv->hi_q ? FFTW_MEASURE : FFTW_ESTIMATE);
|
|
||||||
+ g_static_mutex_unlock(&mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
--
|
|
||||||
1.7.5.4
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
cmake_minimum_required(VERSION 2.6)
|
cmake_minimum_required(VERSION 2.6)
|
||||||
|
|
||||||
set(CMAKE_C_FLAGS "-Wall")
|
set(CMAKE_C_FLAGS "-Wall")
|
||||||
set(CMAKE_CXX_FLAGS "-Woverloaded-virtual -Wall")
|
set(CMAKE_CXX_FLAGS "-Woverloaded-virtual -Wall --std=c++0x")
|
||||||
|
|
||||||
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
|
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
@ -11,9 +11,8 @@ include_directories(${GSTREAMER_INCLUDE_DIRS})
|
|||||||
include_directories(${FFTW3_INCLUDE_DIR})
|
include_directories(${FFTW3_INCLUDE_DIR})
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
gstfftwspectrum.c
|
gstfastspectrum.cpp
|
||||||
gstmoodbar.c
|
plugin.cpp
|
||||||
spectrum.c
|
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(gstmoodbar STATIC
|
add_library(gstmoodbar STATIC
|
||||||
@ -24,6 +23,7 @@ target_link_libraries(gstmoodbar
|
|||||||
${GOBJECT_LIBRARIES}
|
${GOBJECT_LIBRARIES}
|
||||||
${GLIB_LIBRARIES}
|
${GLIB_LIBRARIES}
|
||||||
${GSTREAMER_LIBRARIES}
|
${GSTREAMER_LIBRARIES}
|
||||||
|
${GSTREAMER_AUDIO_LIBRARIES}
|
||||||
${GSTREAMER_BASE_LIBRARIES}
|
${GSTREAMER_BASE_LIBRARIES}
|
||||||
${FFTW3_FFTW_LIBRARY}
|
${FFTW3_FFTW_LIBRARY}
|
||||||
)
|
)
|
||||||
|
553
gst/moodbar/gstfastspectrum.cpp
Normal file
@ -0,0 +1,553 @@
|
|||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||||
|
* <2006,2011> Stefan Kost <ensonic@users.sf.net>
|
||||||
|
* <2007-2009> Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QMutexLocker>
|
||||||
|
|
||||||
|
#include "gstfastspectrum.h"
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_STATIC (gst_fastspectrum_debug);
|
||||||
|
#define GST_CAT_DEFAULT gst_fastspectrum_debug
|
||||||
|
|
||||||
|
/* elementfactory information */
|
||||||
|
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||||
|
# define FORMATS "{ S16LE, S24LE, S32LE, F32LE, F64LE }"
|
||||||
|
#else
|
||||||
|
# define FORMATS "{ S16BE, S24BE, S32BE, F32BE, F64BE }"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ALLOWED_CAPS \
|
||||||
|
GST_AUDIO_CAPS_MAKE (FORMATS) ", " \
|
||||||
|
"layout = (string) interleaved, " \
|
||||||
|
"channels = 1"
|
||||||
|
|
||||||
|
/* Spectrum properties */
|
||||||
|
#define DEFAULT_INTERVAL (GST_SECOND / 10)
|
||||||
|
#define DEFAULT_BANDS 128
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
PROP_INTERVAL,
|
||||||
|
PROP_BANDS
|
||||||
|
};
|
||||||
|
|
||||||
|
#define gst_fastspectrum_parent_class parent_class
|
||||||
|
G_DEFINE_TYPE (GstFastSpectrum, gst_fastspectrum, GST_TYPE_AUDIO_FILTER);
|
||||||
|
|
||||||
|
static void gst_fastspectrum_finalize (GObject * object);
|
||||||
|
static void gst_fastspectrum_set_property (GObject * object, guint prop_id,
|
||||||
|
const GValue * value, GParamSpec * pspec);
|
||||||
|
static void gst_fastspectrum_get_property (GObject * object, guint prop_id,
|
||||||
|
GValue * value, GParamSpec * pspec);
|
||||||
|
static gboolean gst_fastspectrum_start (GstBaseTransform * trans);
|
||||||
|
static gboolean gst_fastspectrum_stop (GstBaseTransform * trans);
|
||||||
|
static GstFlowReturn gst_fastspectrum_transform_ip (GstBaseTransform * trans,
|
||||||
|
GstBuffer * in);
|
||||||
|
static gboolean gst_fastspectrum_setup (GstAudioFilter * base,
|
||||||
|
const GstAudioInfo * info);
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_fastspectrum_class_init (GstFastSpectrumClass * klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||||
|
GstBaseTransformClass *trans_class = GST_BASE_TRANSFORM_CLASS (klass);
|
||||||
|
GstAudioFilterClass *filter_class = GST_AUDIO_FILTER_CLASS (klass);
|
||||||
|
GstCaps *caps;
|
||||||
|
|
||||||
|
gobject_class->set_property = gst_fastspectrum_set_property;
|
||||||
|
gobject_class->get_property = gst_fastspectrum_get_property;
|
||||||
|
gobject_class->finalize = gst_fastspectrum_finalize;
|
||||||
|
|
||||||
|
trans_class->start = GST_DEBUG_FUNCPTR (gst_fastspectrum_start);
|
||||||
|
trans_class->stop = GST_DEBUG_FUNCPTR (gst_fastspectrum_stop);
|
||||||
|
trans_class->transform_ip = GST_DEBUG_FUNCPTR (gst_fastspectrum_transform_ip);
|
||||||
|
trans_class->passthrough_on_same_caps = TRUE;
|
||||||
|
|
||||||
|
filter_class->setup = GST_DEBUG_FUNCPTR (gst_fastspectrum_setup);
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class, PROP_INTERVAL,
|
||||||
|
g_param_spec_uint64 ("interval", "Interval",
|
||||||
|
"Interval of time between message posts (in nanoseconds)",
|
||||||
|
1, G_MAXUINT64, DEFAULT_INTERVAL,
|
||||||
|
GParamFlags(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class, PROP_BANDS,
|
||||||
|
g_param_spec_uint ("bands", "Bands", "Number of frequency bands",
|
||||||
|
0, G_MAXUINT, DEFAULT_BANDS,
|
||||||
|
GParamFlags(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_INIT (gst_fastspectrum_debug, "spectrum", 0,
|
||||||
|
"audio spectrum analyser element");
|
||||||
|
|
||||||
|
gst_element_class_set_static_metadata (element_class, "Spectrum analyzer",
|
||||||
|
"Filter/Analyzer/Audio",
|
||||||
|
"Run an FFT on the audio signal, output spectrum data",
|
||||||
|
"Erik Walthinsen <omega@cse.ogi.edu>, "
|
||||||
|
"Stefan Kost <ensonic@users.sf.net>, "
|
||||||
|
"Sebastian Dröge <sebastian.droege@collabora.co.uk>");
|
||||||
|
|
||||||
|
caps = gst_caps_from_string (ALLOWED_CAPS);
|
||||||
|
gst_audio_filter_class_add_pad_templates (filter_class, caps);
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
|
||||||
|
klass->fftw_lock = new QMutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_fastspectrum_init (GstFastSpectrum * spectrum)
|
||||||
|
{
|
||||||
|
spectrum->interval = DEFAULT_INTERVAL;
|
||||||
|
spectrum->bands = DEFAULT_BANDS;
|
||||||
|
|
||||||
|
spectrum->channel_data_initialised = false;
|
||||||
|
|
||||||
|
g_mutex_init (&spectrum->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_fastspectrum_alloc_channel_data (GstFastSpectrum * spectrum)
|
||||||
|
{
|
||||||
|
guint bands = spectrum->bands;
|
||||||
|
guint nfft = 2 * bands - 2;
|
||||||
|
|
||||||
|
spectrum->input_ring_buffer = new double[nfft];
|
||||||
|
spectrum->fft_input = reinterpret_cast<double*>(
|
||||||
|
fftw_malloc(sizeof(double) * nfft));
|
||||||
|
spectrum->fft_output =reinterpret_cast<fftw_complex*>(
|
||||||
|
fftw_malloc(sizeof(fftw_complex) * (nfft/2+1)));
|
||||||
|
|
||||||
|
spectrum->spect_magnitude = new double[bands]{};
|
||||||
|
|
||||||
|
GstFastSpectrumClass* klass = reinterpret_cast<GstFastSpectrumClass*>(
|
||||||
|
G_OBJECT_GET_CLASS(spectrum));
|
||||||
|
{
|
||||||
|
QMutexLocker l(klass->fftw_lock);
|
||||||
|
spectrum->plan = fftw_plan_dft_r2c_1d(
|
||||||
|
nfft,
|
||||||
|
spectrum->fft_input,
|
||||||
|
spectrum->fft_output,
|
||||||
|
FFTW_ESTIMATE);
|
||||||
|
}
|
||||||
|
spectrum->channel_data_initialised = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_fastspectrum_free_channel_data (GstFastSpectrum * spectrum)
|
||||||
|
{
|
||||||
|
GstFastSpectrumClass* klass = reinterpret_cast<GstFastSpectrumClass*>(
|
||||||
|
G_OBJECT_GET_CLASS(spectrum));
|
||||||
|
if (spectrum->channel_data_initialised) {
|
||||||
|
{
|
||||||
|
QMutexLocker l(klass->fftw_lock);
|
||||||
|
fftw_destroy_plan(spectrum->plan);
|
||||||
|
}
|
||||||
|
fftw_free(spectrum->fft_input);
|
||||||
|
fftw_free(spectrum->fft_output);
|
||||||
|
delete[] spectrum->input_ring_buffer;
|
||||||
|
delete[] spectrum->spect_magnitude;
|
||||||
|
|
||||||
|
spectrum->channel_data_initialised = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_fastspectrum_flush (GstFastSpectrum * spectrum)
|
||||||
|
{
|
||||||
|
spectrum->num_frames = 0;
|
||||||
|
spectrum->num_fft = 0;
|
||||||
|
|
||||||
|
spectrum->accumulated_error = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_fastspectrum_reset_state (GstFastSpectrum * spectrum)
|
||||||
|
{
|
||||||
|
GST_DEBUG_OBJECT (spectrum, "resetting state");
|
||||||
|
|
||||||
|
gst_fastspectrum_free_channel_data (spectrum);
|
||||||
|
gst_fastspectrum_flush (spectrum);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_fastspectrum_finalize (GObject * object)
|
||||||
|
{
|
||||||
|
GstFastSpectrum *spectrum = GST_FASTSPECTRUM (object);
|
||||||
|
|
||||||
|
gst_fastspectrum_reset_state (spectrum);
|
||||||
|
g_mutex_clear (&spectrum->lock);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_fastspectrum_set_property (GObject * object, guint prop_id,
|
||||||
|
const GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
GstFastSpectrum *filter = GST_FASTSPECTRUM (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_INTERVAL:{
|
||||||
|
guint64 interval = g_value_get_uint64 (value);
|
||||||
|
g_mutex_lock (&filter->lock);
|
||||||
|
if (filter->interval != interval) {
|
||||||
|
filter->interval = interval;
|
||||||
|
gst_fastspectrum_reset_state (filter);
|
||||||
|
}
|
||||||
|
g_mutex_unlock (&filter->lock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PROP_BANDS:{
|
||||||
|
guint bands = g_value_get_uint (value);
|
||||||
|
g_mutex_lock (&filter->lock);
|
||||||
|
if (filter->bands != bands) {
|
||||||
|
filter->bands = bands;
|
||||||
|
gst_fastspectrum_reset_state (filter);
|
||||||
|
}
|
||||||
|
g_mutex_unlock (&filter->lock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_fastspectrum_get_property (GObject * object, guint prop_id,
|
||||||
|
GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
GstFastSpectrum *filter = GST_FASTSPECTRUM (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_INTERVAL:
|
||||||
|
g_value_set_uint64 (value, filter->interval);
|
||||||
|
break;
|
||||||
|
case PROP_BANDS:
|
||||||
|
g_value_set_uint (value, filter->bands);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_fastspectrum_start (GstBaseTransform * trans)
|
||||||
|
{
|
||||||
|
GstFastSpectrum *spectrum = GST_FASTSPECTRUM (trans);
|
||||||
|
|
||||||
|
gst_fastspectrum_reset_state (spectrum);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_fastspectrum_stop (GstBaseTransform * trans)
|
||||||
|
{
|
||||||
|
GstFastSpectrum *spectrum = GST_FASTSPECTRUM (trans);
|
||||||
|
|
||||||
|
gst_fastspectrum_reset_state (spectrum);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mixing data readers */
|
||||||
|
|
||||||
|
static void
|
||||||
|
input_data_mixed_float(const guint8* _in, double* out, guint len,
|
||||||
|
double max_value, guint op, guint nfft)
|
||||||
|
{
|
||||||
|
guint j, ip = 0;
|
||||||
|
gfloat *in = (gfloat *) _in;
|
||||||
|
|
||||||
|
for (j = 0; j < len; j++) {
|
||||||
|
out[op] = in[ip++];
|
||||||
|
op = (op + 1) % nfft;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
input_data_mixed_double (const guint8 * _in, double* out, guint len,
|
||||||
|
double max_value, guint op, guint nfft)
|
||||||
|
{
|
||||||
|
guint j, ip = 0;
|
||||||
|
gdouble *in = (gdouble *) _in;
|
||||||
|
|
||||||
|
for (j = 0; j < len; j++) {
|
||||||
|
out[op] = in[ip++];
|
||||||
|
op = (op + 1) % nfft;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
input_data_mixed_int32_max (const guint8 * _in, double* out, guint len,
|
||||||
|
double max_value, guint op, guint nfft)
|
||||||
|
{
|
||||||
|
guint j, ip = 0;
|
||||||
|
gint32 *in = (gint32 *) _in;
|
||||||
|
|
||||||
|
for (j = 0; j < len; j++) {
|
||||||
|
out[op] = in[ip++] / max_value;
|
||||||
|
op = (op + 1) % nfft;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
input_data_mixed_int24_max (const guint8 * _in, double* out, guint len,
|
||||||
|
double max_value, guint op, guint nfft)
|
||||||
|
{
|
||||||
|
guint j;
|
||||||
|
|
||||||
|
for (j = 0; j < len; j++) {
|
||||||
|
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||||
|
gint32 value = GST_READ_UINT24_BE (_in);
|
||||||
|
#else
|
||||||
|
gint32 value = GST_READ_UINT24_LE (_in);
|
||||||
|
#endif
|
||||||
|
if (value & 0x00800000)
|
||||||
|
value |= 0xff000000;
|
||||||
|
|
||||||
|
out[op] = value / max_value;
|
||||||
|
op = (op + 1) % nfft;
|
||||||
|
_in += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
input_data_mixed_int16_max (const guint8 * _in, double * out, guint len,
|
||||||
|
double max_value, guint op, guint nfft)
|
||||||
|
{
|
||||||
|
guint j, ip = 0;
|
||||||
|
gint16 *in = (gint16 *) _in;
|
||||||
|
|
||||||
|
for (j = 0; j < len; j++) {
|
||||||
|
out[op] = in[ip++] / max_value;
|
||||||
|
op = (op + 1) % nfft;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_fastspectrum_setup (GstAudioFilter * base, const GstAudioInfo * info)
|
||||||
|
{
|
||||||
|
GstFastSpectrum *spectrum = GST_FASTSPECTRUM (base);
|
||||||
|
GstFastSpectrumInputData input_data = NULL;
|
||||||
|
|
||||||
|
g_mutex_lock (&spectrum->lock);
|
||||||
|
switch (GST_AUDIO_INFO_FORMAT (info)) {
|
||||||
|
case GST_AUDIO_FORMAT_S16:
|
||||||
|
input_data = input_data_mixed_int16_max;
|
||||||
|
break;
|
||||||
|
case GST_AUDIO_FORMAT_S24:
|
||||||
|
input_data = input_data_mixed_int24_max;
|
||||||
|
break;
|
||||||
|
case GST_AUDIO_FORMAT_S32:
|
||||||
|
input_data = input_data_mixed_int32_max;
|
||||||
|
break;
|
||||||
|
case GST_AUDIO_FORMAT_F32:
|
||||||
|
input_data = input_data_mixed_float;
|
||||||
|
break;
|
||||||
|
case GST_AUDIO_FORMAT_F64:
|
||||||
|
input_data = input_data_mixed_double;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
spectrum->input_data = input_data;
|
||||||
|
|
||||||
|
gst_fastspectrum_reset_state (spectrum);
|
||||||
|
g_mutex_unlock (&spectrum->lock);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_fastspectrum_run_fft (GstFastSpectrum * spectrum, guint input_pos)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
guint bands = spectrum->bands;
|
||||||
|
guint nfft = 2 * bands - 2;
|
||||||
|
|
||||||
|
for (i = 0; i < nfft; i++)
|
||||||
|
spectrum->fft_input[i] =
|
||||||
|
spectrum->input_ring_buffer[(input_pos + i) % nfft];
|
||||||
|
|
||||||
|
// Should be safe to execute the same plan multiple times in parallel.
|
||||||
|
fftw_execute(spectrum->plan);
|
||||||
|
|
||||||
|
gdouble val;
|
||||||
|
/* Calculate magnitude in db */
|
||||||
|
for (i = 0; i < bands; i++) {
|
||||||
|
val = spectrum->fft_output[i][0] * spectrum->fft_output[i][0];
|
||||||
|
val += spectrum->fft_output[i][1] * spectrum->fft_output[i][1];
|
||||||
|
val /= nfft * nfft;
|
||||||
|
spectrum->spect_magnitude[i] += val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_fastspectrum_transform_ip (GstBaseTransform * trans, GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
GstFastSpectrum *spectrum = GST_FASTSPECTRUM (trans);
|
||||||
|
guint rate = GST_AUDIO_FILTER_RATE (spectrum);
|
||||||
|
guint bps = GST_AUDIO_FILTER_BPS (spectrum);
|
||||||
|
guint bpf = GST_AUDIO_FILTER_BPF (spectrum);
|
||||||
|
double max_value = (1UL << ((bps << 3) - 1)) - 1;
|
||||||
|
guint bands = spectrum->bands;
|
||||||
|
guint nfft = 2 * bands - 2;
|
||||||
|
guint input_pos;
|
||||||
|
GstMapInfo map;
|
||||||
|
const guint8 *data;
|
||||||
|
gsize size;
|
||||||
|
guint fft_todo, msg_todo, block_size;
|
||||||
|
gboolean have_full_interval;
|
||||||
|
GstFastSpectrumInputData input_data;
|
||||||
|
|
||||||
|
g_mutex_lock (&spectrum->lock);
|
||||||
|
gst_buffer_map (buffer, &map, GST_MAP_READ);
|
||||||
|
data = map.data;
|
||||||
|
size = map.size;
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (spectrum, "input size: %" G_GSIZE_FORMAT " bytes", size);
|
||||||
|
|
||||||
|
if (GST_BUFFER_IS_DISCONT (buffer)) {
|
||||||
|
GST_DEBUG_OBJECT (spectrum, "Discontinuity detected -- flushing");
|
||||||
|
gst_fastspectrum_flush (spectrum);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we don't have a FFT context yet (or it was reset due to parameter
|
||||||
|
* changes) get one and allocate memory for everything
|
||||||
|
*/
|
||||||
|
if (!spectrum->channel_data_initialised) {
|
||||||
|
GST_DEBUG_OBJECT (spectrum, "allocating for bands %u", bands);
|
||||||
|
|
||||||
|
gst_fastspectrum_alloc_channel_data (spectrum);
|
||||||
|
|
||||||
|
/* number of sample frames we process before posting a message
|
||||||
|
* interval is in ns */
|
||||||
|
spectrum->frames_per_interval =
|
||||||
|
gst_util_uint64_scale (spectrum->interval, rate, GST_SECOND);
|
||||||
|
spectrum->frames_todo = spectrum->frames_per_interval;
|
||||||
|
/* rounding error for frames_per_interval in ns,
|
||||||
|
* aggregated it in accumulated_error */
|
||||||
|
spectrum->error_per_interval = (spectrum->interval * rate) % GST_SECOND;
|
||||||
|
if (spectrum->frames_per_interval == 0)
|
||||||
|
spectrum->frames_per_interval = 1;
|
||||||
|
|
||||||
|
GST_INFO_OBJECT (spectrum, "interval %" GST_TIME_FORMAT ", fpi %"
|
||||||
|
G_GUINT64_FORMAT ", error %" GST_TIME_FORMAT,
|
||||||
|
GST_TIME_ARGS (spectrum->interval), spectrum->frames_per_interval,
|
||||||
|
GST_TIME_ARGS (spectrum->error_per_interval));
|
||||||
|
|
||||||
|
spectrum->input_pos = 0;
|
||||||
|
|
||||||
|
gst_fastspectrum_flush (spectrum);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spectrum->num_frames == 0)
|
||||||
|
spectrum->message_ts = GST_BUFFER_TIMESTAMP (buffer);
|
||||||
|
|
||||||
|
input_pos = spectrum->input_pos;
|
||||||
|
input_data = spectrum->input_data;
|
||||||
|
|
||||||
|
while (size >= bpf) {
|
||||||
|
/* run input_data for a chunk of data */
|
||||||
|
fft_todo = nfft - (spectrum->num_frames % nfft);
|
||||||
|
msg_todo = spectrum->frames_todo - spectrum->num_frames;
|
||||||
|
GST_LOG_OBJECT (spectrum,
|
||||||
|
"message frames todo: %u, fft frames todo: %u, input frames %"
|
||||||
|
G_GSIZE_FORMAT, msg_todo, fft_todo, (size / bpf));
|
||||||
|
block_size = msg_todo;
|
||||||
|
if (block_size > (size / bpf))
|
||||||
|
block_size = (size / bpf);
|
||||||
|
if (block_size > fft_todo)
|
||||||
|
block_size = fft_todo;
|
||||||
|
|
||||||
|
/* Move the current frames into our ringbuffers */
|
||||||
|
input_data(data, spectrum->input_ring_buffer, block_size, max_value, input_pos, nfft);
|
||||||
|
|
||||||
|
data += block_size * bpf;
|
||||||
|
size -= block_size * bpf;
|
||||||
|
input_pos = (input_pos + block_size) % nfft;
|
||||||
|
spectrum->num_frames += block_size;
|
||||||
|
|
||||||
|
have_full_interval = (spectrum->num_frames == spectrum->frames_todo);
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (spectrum,
|
||||||
|
"size: %" G_GSIZE_FORMAT ", do-fft = %d, do-message = %d", size,
|
||||||
|
(spectrum->num_frames % nfft == 0), have_full_interval);
|
||||||
|
|
||||||
|
/* If we have enough frames for an FFT or we have all frames required for
|
||||||
|
* the interval and we haven't run a FFT, then run an FFT */
|
||||||
|
if ((spectrum->num_frames % nfft == 0) ||
|
||||||
|
(have_full_interval && !spectrum->num_fft)) {
|
||||||
|
gst_fastspectrum_run_fft (spectrum, input_pos);
|
||||||
|
spectrum->num_fft++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do we have the FFTs for one interval? */
|
||||||
|
if (have_full_interval) {
|
||||||
|
GST_DEBUG_OBJECT (spectrum, "nfft: %u frames: %" G_GUINT64_FORMAT
|
||||||
|
" fpi: %" G_GUINT64_FORMAT " error: %" GST_TIME_FORMAT, nfft,
|
||||||
|
spectrum->num_frames, spectrum->frames_per_interval,
|
||||||
|
GST_TIME_ARGS (spectrum->accumulated_error));
|
||||||
|
|
||||||
|
spectrum->frames_todo = spectrum->frames_per_interval;
|
||||||
|
if (spectrum->accumulated_error >= GST_SECOND) {
|
||||||
|
spectrum->accumulated_error -= GST_SECOND;
|
||||||
|
spectrum->frames_todo++;
|
||||||
|
}
|
||||||
|
spectrum->accumulated_error += spectrum->error_per_interval;
|
||||||
|
|
||||||
|
if (spectrum->output_callback) {
|
||||||
|
// Calculate average
|
||||||
|
for (guint i = 0; i < spectrum->bands; i++) {
|
||||||
|
spectrum->spect_magnitude[i] /= spectrum->num_fft;
|
||||||
|
}
|
||||||
|
|
||||||
|
spectrum->output_callback(spectrum->spect_magnitude, spectrum->bands);
|
||||||
|
|
||||||
|
// Reset spectrum accumulators
|
||||||
|
memset(spectrum->spect_magnitude, 0, spectrum->bands * sizeof(double));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GST_CLOCK_TIME_IS_VALID (spectrum->message_ts))
|
||||||
|
spectrum->message_ts +=
|
||||||
|
gst_util_uint64_scale (spectrum->num_frames, GST_SECOND, rate);
|
||||||
|
|
||||||
|
spectrum->num_frames = 0;
|
||||||
|
spectrum->num_fft = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spectrum->input_pos = input_pos;
|
||||||
|
|
||||||
|
gst_buffer_unmap (buffer, &map);
|
||||||
|
g_mutex_unlock (&spectrum->lock);
|
||||||
|
|
||||||
|
g_assert (size == 0);
|
||||||
|
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
}
|
98
gst/moodbar/gstfastspectrum.h
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||||
|
* Copyright (C) <2009> Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Adapted from gstspectrum for Clementine with the following changes:
|
||||||
|
// - Uses fftw instead of kiss fft (2x faster).
|
||||||
|
// - Hardcoded to 1 channel (use an audioconvert element to do the work
|
||||||
|
// instead, simplifies this code a lot).
|
||||||
|
// - Send output via a callback instead of GST messages (less overhead).
|
||||||
|
// - Removed all properties except interval and band.
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef GST_MOODBAR_FASTSPECTRUM_H_
|
||||||
|
#define GST_MOODBAR_FASTSPECTRUM_H_
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
#include <gst/audio/gstaudiofilter.h>
|
||||||
|
#include <fftw3.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GST_TYPE_FASTSPECTRUM (gst_fastspectrum_get_type())
|
||||||
|
#define GST_FASTSPECTRUM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FASTSPECTRUM,GstFastSpectrum))
|
||||||
|
#define GST_IS_FASTSPECTRUM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FASTSPECTRUM))
|
||||||
|
#define GST_FASTSPECTRUM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_FASTSPECTRUM,GstFastSpectrumClass))
|
||||||
|
#define GST_IS_FASTSPECTRUM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_FASTSPECTRUM))
|
||||||
|
|
||||||
|
class QMutex;
|
||||||
|
|
||||||
|
typedef void (*GstFastSpectrumInputData)(const guint8* in, double* out,
|
||||||
|
guint len, double max_value, guint op, guint nfft);
|
||||||
|
|
||||||
|
typedef std::function<void(double* magnitudes, int size)> OutputCallback;
|
||||||
|
|
||||||
|
struct GstFastSpectrum {
|
||||||
|
GstAudioFilter parent;
|
||||||
|
|
||||||
|
/* properties */
|
||||||
|
guint64 interval; /* how many nanoseconds between emits */
|
||||||
|
guint64 frames_per_interval; /* how many frames per interval */
|
||||||
|
guint64 frames_todo;
|
||||||
|
guint bands; /* number of spectrum bands */
|
||||||
|
gboolean multi_channel; /* send separate channel results */
|
||||||
|
|
||||||
|
guint64 num_frames; /* frame count (1 sample per channel)
|
||||||
|
* since last emit */
|
||||||
|
guint64 num_fft; /* number of FFTs since last emit */
|
||||||
|
GstClockTime message_ts; /* starttime for next message */
|
||||||
|
|
||||||
|
/* <private> */
|
||||||
|
bool channel_data_initialised;
|
||||||
|
double* input_ring_buffer;
|
||||||
|
double* fft_input;
|
||||||
|
fftw_complex* fft_output;
|
||||||
|
double* spect_magnitude;
|
||||||
|
fftw_plan plan;
|
||||||
|
|
||||||
|
guint input_pos;
|
||||||
|
guint64 error_per_interval;
|
||||||
|
guint64 accumulated_error;
|
||||||
|
|
||||||
|
GMutex lock;
|
||||||
|
|
||||||
|
GstFastSpectrumInputData input_data;
|
||||||
|
|
||||||
|
OutputCallback output_callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GstFastSpectrumClass {
|
||||||
|
GstAudioFilterClass parent_class;
|
||||||
|
|
||||||
|
// Static lock for creating & destroying FFTW plans.
|
||||||
|
QMutex* fftw_lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gst_fastspectrum_get_type (void);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif // GST_MOODBAR_FASTSPECTRUM_H_
|
@ -1,638 +0,0 @@
|
|||||||
/* GStreamer FFTW-based signal-to-spectrum converter
|
|
||||||
* Copyright (C) 2006 Joseph Rabinoff <bobqwatson@yahoo.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* *
|
|
||||||
* This program 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 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SECTION:element-fftwspectrum
|
|
||||||
*
|
|
||||||
* <refsect2>
|
|
||||||
* <title>Example launch line</title>
|
|
||||||
* <para>
|
|
||||||
* <programlisting>
|
|
||||||
* gst-launch audiotestsrc ! audioconvert ! fftwspectrum ! fftwunspectrum ! audioconvert ! alsasink
|
|
||||||
* </programlisting>
|
|
||||||
* </para>
|
|
||||||
* </refsect2>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This is a simple plugin to take an audio signal and return its
|
|
||||||
* Fourier transform, using fftw3. It takes a specified number N of
|
|
||||||
* samples and returns the first N/2+1 (complex) Fourier transform
|
|
||||||
* values (the other half of the values being the complex conjugates
|
|
||||||
* of the first). The modulus of these values correspond to the
|
|
||||||
* strength of the signal in their various bands, and the phase gives
|
|
||||||
* information about the phase of the signal. The step by which the
|
|
||||||
* transform increments is also variable, so it can return redundant
|
|
||||||
* data (to reduce artifacts when converting back into a signal).
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include <config.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <gst/gst.h>
|
|
||||||
#include <fftw3.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include "gstfftwspectrum.h"
|
|
||||||
#include "spectrum.h"
|
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY (gst_fftwspectrum_debug);
|
|
||||||
#define GST_CAT_DEFAULT gst_fftwspectrum_debug
|
|
||||||
|
|
||||||
/* Filter signals and args */
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
/* FILL ME */
|
|
||||||
LAST_SIGNAL
|
|
||||||
};
|
|
||||||
|
|
||||||
/* The size and step arguments are actually only default values
|
|
||||||
* used to fixate the size and step properties of the source cap.
|
|
||||||
*/
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
ARG_0,
|
|
||||||
ARG_DEF_SIZE,
|
|
||||||
ARG_DEF_STEP,
|
|
||||||
ARG_HIQUALITY
|
|
||||||
};
|
|
||||||
|
|
||||||
#define DEF_SIZE_DEFAULT 1024
|
|
||||||
#define DEF_STEP_DEFAULT 512
|
|
||||||
#define HIQUALITY_DEFAULT TRUE
|
|
||||||
|
|
||||||
static GstStaticPadTemplate sink_factory
|
|
||||||
= GST_STATIC_PAD_TEMPLATE ("sink",
|
|
||||||
GST_PAD_SINK,
|
|
||||||
GST_PAD_ALWAYS,
|
|
||||||
GST_STATIC_CAPS
|
|
||||||
( SPECTRUM_SIGNAL_CAPS )
|
|
||||||
);
|
|
||||||
|
|
||||||
/* See spectrum.h for a definition of the frequency caps */
|
|
||||||
static GstStaticPadTemplate src_factory
|
|
||||||
= GST_STATIC_PAD_TEMPLATE ("src",
|
|
||||||
GST_PAD_SRC,
|
|
||||||
GST_PAD_ALWAYS,
|
|
||||||
GST_STATIC_CAPS
|
|
||||||
( SPECTRUM_FREQ_CAPS )
|
|
||||||
);
|
|
||||||
|
|
||||||
GST_BOILERPLATE (GstFFTWSpectrum, gst_fftwspectrum, GstElement,
|
|
||||||
GST_TYPE_ELEMENT);
|
|
||||||
|
|
||||||
static void gst_fftwspectrum_set_property (GObject *object, guint prop_id,
|
|
||||||
const GValue *value, GParamSpec *pspec);
|
|
||||||
static void gst_fftwspectrum_get_property (GObject *object, guint prop_id,
|
|
||||||
GValue *value, GParamSpec *pspec);
|
|
||||||
|
|
||||||
static gboolean gst_fftwspectrum_set_sink_caps (GstPad *pad, GstCaps *caps);
|
|
||||||
static gboolean gst_fftwspectrum_set_src_caps (GstPad *pad, GstCaps *caps);
|
|
||||||
static void gst_fftwspectrum_fixatecaps (GstPad *pad, GstCaps *caps);
|
|
||||||
static GstCaps *gst_fftwspectrum_getcaps (GstPad *pad);
|
|
||||||
|
|
||||||
static GstFlowReturn gst_fftwspectrum_chain (GstPad *pad, GstBuffer *buf);
|
|
||||||
static GstStateChangeReturn gst_fftwspectrum_change_state (GstElement *element,
|
|
||||||
GstStateChange transition);
|
|
||||||
|
|
||||||
|
|
||||||
#define OUTPUT_SIZE(conv) (((conv)->size/2+1)*sizeof(fftw_complex))
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************/
|
|
||||||
/* GObject boilerplate stuff */
|
|
||||||
/***************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_fftwspectrum_base_init (gpointer gclass)
|
|
||||||
{
|
|
||||||
static GstElementDetails element_details =
|
|
||||||
{
|
|
||||||
"FFTW-based Fourier transform",
|
|
||||||
"Filter/Converter/Spectrum",
|
|
||||||
"Convert a raw audio stream into a frequency spectrum",
|
|
||||||
"Joe Rabinoff <bobqwatson@yahoo.com>"
|
|
||||||
};
|
|
||||||
GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
|
|
||||||
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_static_pad_template_get (&src_factory));
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_static_pad_template_get (&sink_factory));
|
|
||||||
gst_element_class_set_details (element_class, &element_details);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* initialize the plugin's class */
|
|
||||||
static void
|
|
||||||
gst_fftwspectrum_class_init (GstFFTWSpectrumClass * klass)
|
|
||||||
{
|
|
||||||
GObjectClass *gobject_class;
|
|
||||||
GstElementClass *gstelement_class;
|
|
||||||
|
|
||||||
gobject_class = (GObjectClass *) klass;
|
|
||||||
gstelement_class = (GstElementClass *) klass;
|
|
||||||
|
|
||||||
gobject_class->set_property = gst_fftwspectrum_set_property;
|
|
||||||
gobject_class->get_property = gst_fftwspectrum_get_property;
|
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, ARG_DEF_SIZE,
|
|
||||||
g_param_spec_int ("def-size", "Default Size",
|
|
||||||
"Apply a Fourier transform to this many samples at a time (default value)",
|
|
||||||
1, G_MAXINT32, DEF_SIZE_DEFAULT, G_PARAM_READWRITE));
|
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, ARG_DEF_STEP,
|
|
||||||
g_param_spec_int ("def-step", "Default Step",
|
|
||||||
"Advance the stream this many samples each time (default value)",
|
|
||||||
1, G_MAXINT32, DEF_STEP_DEFAULT, G_PARAM_READWRITE));
|
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, ARG_HIQUALITY,
|
|
||||||
g_param_spec_boolean ("hiquality", "High Quality",
|
|
||||||
"Use a more time-consuming, higher quality algorithm chooser",
|
|
||||||
HIQUALITY_DEFAULT, G_PARAM_READWRITE));
|
|
||||||
|
|
||||||
gstelement_class->change_state
|
|
||||||
= GST_DEBUG_FUNCPTR (gst_fftwspectrum_change_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* initialize the new element
|
|
||||||
* instantiate pads and add them to element
|
|
||||||
* set functions
|
|
||||||
* initialize structure
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
gst_fftwspectrum_init (GstFFTWSpectrum * conv,
|
|
||||||
GstFFTWSpectrumClass * gclass)
|
|
||||||
{
|
|
||||||
GstElementClass *klass = GST_ELEMENT_GET_CLASS (conv);
|
|
||||||
|
|
||||||
conv->sinkpad =
|
|
||||||
gst_pad_new_from_template
|
|
||||||
(gst_element_class_get_pad_template (klass, "sink"), "sink");
|
|
||||||
gst_pad_set_setcaps_function (conv->sinkpad,
|
|
||||||
GST_DEBUG_FUNCPTR (gst_fftwspectrum_set_sink_caps));
|
|
||||||
gst_pad_set_getcaps_function (conv->sinkpad,
|
|
||||||
GST_DEBUG_FUNCPTR (gst_fftwspectrum_getcaps));
|
|
||||||
gst_pad_set_chain_function (conv->sinkpad,
|
|
||||||
GST_DEBUG_FUNCPTR (gst_fftwspectrum_chain));
|
|
||||||
|
|
||||||
conv->srcpad =
|
|
||||||
gst_pad_new_from_template
|
|
||||||
(gst_element_class_get_pad_template (klass, "src"), "src");
|
|
||||||
gst_pad_set_setcaps_function (conv->srcpad,
|
|
||||||
GST_DEBUG_FUNCPTR (gst_fftwspectrum_set_src_caps));
|
|
||||||
gst_pad_set_getcaps_function (conv->srcpad,
|
|
||||||
GST_DEBUG_FUNCPTR (gst_fftwspectrum_getcaps));
|
|
||||||
gst_pad_set_fixatecaps_function (conv->srcpad,
|
|
||||||
GST_DEBUG_FUNCPTR (gst_fftwspectrum_fixatecaps));
|
|
||||||
|
|
||||||
|
|
||||||
gst_element_add_pad (GST_ELEMENT (conv), conv->sinkpad);
|
|
||||||
gst_element_add_pad (GST_ELEMENT (conv), conv->srcpad);
|
|
||||||
|
|
||||||
/* These are set once the (source) capabilities are determined */
|
|
||||||
conv->rate = 0;
|
|
||||||
conv->size = 0;
|
|
||||||
conv->step = 0;
|
|
||||||
|
|
||||||
/* These are set when we change to READY */
|
|
||||||
conv->fftw_in = NULL;
|
|
||||||
conv->fftw_out = NULL;
|
|
||||||
conv->fftw_plan = NULL;
|
|
||||||
|
|
||||||
/* These are set when we start receiving data */
|
|
||||||
conv->samples = NULL;
|
|
||||||
conv->numsamples = 0;
|
|
||||||
conv->timestamp = 0;
|
|
||||||
conv->offset = 0;
|
|
||||||
|
|
||||||
/* Properties */
|
|
||||||
conv->def_size = DEF_SIZE_DEFAULT;
|
|
||||||
conv->def_step = DEF_STEP_DEFAULT;
|
|
||||||
conv->hi_q = HIQUALITY_DEFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_fftwspectrum_set_property (GObject * object, guint prop_id,
|
|
||||||
const GValue * value, GParamSpec * pspec)
|
|
||||||
{
|
|
||||||
GstFFTWSpectrum *conv = GST_FFTWSPECTRUM (object);
|
|
||||||
|
|
||||||
switch (prop_id)
|
|
||||||
{
|
|
||||||
case ARG_DEF_SIZE:
|
|
||||||
conv->def_size = g_value_get_int (value);
|
|
||||||
break;
|
|
||||||
case ARG_DEF_STEP:
|
|
||||||
conv->def_step = g_value_get_int (value);
|
|
||||||
break;
|
|
||||||
case ARG_HIQUALITY:
|
|
||||||
conv->hi_q = g_value_get_boolean (value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_fftwspectrum_get_property (GObject * object, guint prop_id,
|
|
||||||
GValue * value, GParamSpec * pspec)
|
|
||||||
{
|
|
||||||
GstFFTWSpectrum *conv = GST_FFTWSPECTRUM (object);
|
|
||||||
|
|
||||||
switch (prop_id)
|
|
||||||
{
|
|
||||||
case ARG_DEF_SIZE:
|
|
||||||
g_value_set_int (value, conv->def_size);
|
|
||||||
break;
|
|
||||||
case ARG_DEF_STEP:
|
|
||||||
g_value_set_int (value, conv->def_step);
|
|
||||||
break;
|
|
||||||
case ARG_HIQUALITY:
|
|
||||||
g_value_set_boolean (value, conv->hi_q);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Allocate and deallocate fftw state data */
|
|
||||||
static void
|
|
||||||
free_fftw_data (GstFFTWSpectrum *conv)
|
|
||||||
{
|
|
||||||
if(conv->fftw_plan != NULL)
|
|
||||||
fftw_destroy_plan (conv->fftw_plan);
|
|
||||||
if(conv->fftw_in != NULL)
|
|
||||||
fftw_free (conv->fftw_in);
|
|
||||||
if(conv->fftw_out != NULL)
|
|
||||||
fftw_free (conv->fftw_out);
|
|
||||||
|
|
||||||
conv->fftw_in = NULL;
|
|
||||||
conv->fftw_out = NULL;
|
|
||||||
conv->fftw_plan = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
alloc_fftw_data (GstFFTWSpectrum *conv)
|
|
||||||
{
|
|
||||||
free_fftw_data (conv);
|
|
||||||
|
|
||||||
GST_DEBUG ("Allocating data for size = %d and step = %d",
|
|
||||||
conv->size, conv->step);
|
|
||||||
|
|
||||||
conv->fftw_in = (double *) fftw_malloc (sizeof(double) * conv->size);
|
|
||||||
conv->fftw_out = (double *) fftw_malloc (OUTPUT_SIZE (conv));
|
|
||||||
|
|
||||||
/* We use the simplest real-to-complex algorithm, which takes n real
|
|
||||||
* inputs and returns floor(n/2) + 1 complex outputs (the other n/2
|
|
||||||
* outputs are the hermetian conjugates). This should be optimal for
|
|
||||||
* implementing filters.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
|
|
||||||
g_static_mutex_lock(&mutex);
|
|
||||||
conv->fftw_plan
|
|
||||||
= fftw_plan_dft_r2c_1d(conv->size, conv->fftw_in,
|
|
||||||
(fftw_complex *) conv->fftw_out,
|
|
||||||
conv->hi_q ? FFTW_MEASURE : FFTW_ESTIMATE);
|
|
||||||
g_static_mutex_unlock(&mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************/
|
|
||||||
/* Capabilities negotiation */
|
|
||||||
/***************************************************************/
|
|
||||||
|
|
||||||
/* The input and output capabilities are only related by the "rate"
|
|
||||||
* parameter, which is propagated so that an audio signal can be
|
|
||||||
* reconstructed eventually. This module does no rate conversion.
|
|
||||||
*
|
|
||||||
* The way I understand it, there are two times when caps negotiation
|
|
||||||
* takes place: (1) when a sink pad receives either its first buffer,
|
|
||||||
* or a buffer with a new caps type, and (2) when a source pad request
|
|
||||||
* a buffer from something downstream, and the returned allocated
|
|
||||||
* buffer has different caps from the ones already negotiated. In the
|
|
||||||
* first case, _set_sink_caps is called, and in the second, _set_src_caps
|
|
||||||
* is called.
|
|
||||||
* When (1) occurs, we remember the rate (the only variable parameter
|
|
||||||
* in the source) and set the source caps. Then _set_src_caps is called.
|
|
||||||
* In _set_src_caps, we check that the rate hasn't changed, and figure out
|
|
||||||
* or remember appropriate size and step attributes. If _set_src_caps is
|
|
||||||
* called from _set_sink_caps, this completes our setting up our internal
|
|
||||||
* configuration; if it is called from (2), we reconfigure just the source
|
|
||||||
* part of the internal configuration.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_fftwspectrum_set_sink_caps (GstPad * pad, GstCaps * caps)
|
|
||||||
{
|
|
||||||
GstFFTWSpectrum *conv;
|
|
||||||
GstCaps *srccaps, *newsrccaps;
|
|
||||||
GstStructure *newstruct;
|
|
||||||
gint rate;
|
|
||||||
gboolean res;
|
|
||||||
|
|
||||||
conv = GST_FFTWSPECTRUM (gst_pad_get_parent (pad));
|
|
||||||
|
|
||||||
srccaps = gst_pad_get_allowed_caps (conv->srcpad);
|
|
||||||
newsrccaps = gst_caps_copy_nth (srccaps, 0);
|
|
||||||
gst_caps_unref (srccaps);
|
|
||||||
|
|
||||||
newstruct = gst_caps_get_structure (caps, 0);
|
|
||||||
if (!gst_structure_get_int (newstruct, "rate", &rate))
|
|
||||||
{
|
|
||||||
gst_caps_unref (newsrccaps);
|
|
||||||
gst_object_unref (conv);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fixate the source caps with the given rate */
|
|
||||||
gst_caps_set_simple (newsrccaps, "rate", G_TYPE_INT, rate, NULL);
|
|
||||||
gst_pad_fixate_caps (conv->srcpad, newsrccaps);
|
|
||||||
conv->rate = rate;
|
|
||||||
res = gst_pad_set_caps (conv->srcpad, newsrccaps);
|
|
||||||
if (!res)
|
|
||||||
conv->rate = 0;
|
|
||||||
|
|
||||||
gst_caps_unref (newsrccaps);
|
|
||||||
gst_object_unref (conv);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_fftwspectrum_set_src_caps (GstPad * pad, GstCaps * caps)
|
|
||||||
{
|
|
||||||
GstFFTWSpectrum *conv;
|
|
||||||
gboolean res = FALSE;
|
|
||||||
GstStructure *newstruct;
|
|
||||||
gint rate;
|
|
||||||
|
|
||||||
conv = GST_FFTWSPECTRUM (gst_pad_get_parent (pad));
|
|
||||||
|
|
||||||
newstruct = gst_caps_get_structure (caps, 0);
|
|
||||||
if (!gst_structure_get_int (newstruct, "rate", &rate))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
/* Assume caps negotiation has already taken place */
|
|
||||||
if (rate == conv->rate)
|
|
||||||
{
|
|
||||||
gint size, step;
|
|
||||||
|
|
||||||
if (!gst_structure_get_int (newstruct, "size", &size))
|
|
||||||
goto out;
|
|
||||||
if (!gst_structure_get_int (newstruct, "step", &step))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (conv->size != size || conv->step != step)
|
|
||||||
{
|
|
||||||
conv->size = size;
|
|
||||||
conv->step = step;
|
|
||||||
|
|
||||||
/* Re-allocate the fftw data */
|
|
||||||
if (GST_STATE (GST_ELEMENT (conv)) >= GST_STATE_READY)
|
|
||||||
alloc_fftw_data (conv);
|
|
||||||
}
|
|
||||||
|
|
||||||
res = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
gst_object_unref (conv);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* The only thing that can constrain the caps is the rate. */
|
|
||||||
static GstCaps *
|
|
||||||
gst_fftwspectrum_getcaps (GstPad *pad)
|
|
||||||
{
|
|
||||||
GstFFTWSpectrum *conv;
|
|
||||||
GstCaps *tmplcaps;
|
|
||||||
|
|
||||||
conv = GST_FFTWSPECTRUM (gst_pad_get_parent (pad));
|
|
||||||
tmplcaps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
|
|
||||||
|
|
||||||
if(conv->rate != 0)
|
|
||||||
{
|
|
||||||
/* Assumes the template caps are simple */
|
|
||||||
gst_caps_set_simple (tmplcaps, "rate", G_TYPE_INT, conv->rate, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
gst_object_unref (conv);
|
|
||||||
|
|
||||||
return tmplcaps;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* This is called when the source pad needs to choose its capabilities
|
|
||||||
* when it has a choice and nobody's forcing its hand. In this case
|
|
||||||
* we take our hint from the def_size and def_step properties.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
gst_fftwspectrum_fixatecaps (GstPad *pad, GstCaps *caps)
|
|
||||||
{
|
|
||||||
GstFFTWSpectrum *conv;
|
|
||||||
GstStructure *s;
|
|
||||||
const GValue *val;
|
|
||||||
|
|
||||||
conv = GST_FFTWSPECTRUM (gst_pad_get_parent (pad));
|
|
||||||
s = gst_caps_get_structure (caps, 0);
|
|
||||||
|
|
||||||
val = gst_structure_get_value (s, "size");
|
|
||||||
if (val == NULL)
|
|
||||||
gst_caps_set_simple (caps, "size", G_TYPE_INT, conv->def_size, NULL);
|
|
||||||
else if (G_VALUE_TYPE (val) == GST_TYPE_INT_RANGE)
|
|
||||||
{
|
|
||||||
gint sizemin, sizemax;
|
|
||||||
sizemin = gst_value_get_int_range_min (val);
|
|
||||||
sizemax = gst_value_get_int_range_max (val);
|
|
||||||
gst_caps_set_simple (caps, "size", G_TYPE_INT,
|
|
||||||
CLAMP (conv->def_size, sizemin, sizemax), NULL);
|
|
||||||
}
|
|
||||||
/* else it should be already fixed */
|
|
||||||
|
|
||||||
val = gst_structure_get_value (s, "step");
|
|
||||||
if (val == NULL)
|
|
||||||
gst_caps_set_simple (caps, "step", G_TYPE_INT, conv->def_step, NULL);
|
|
||||||
else if (G_VALUE_TYPE (val) == GST_TYPE_INT_RANGE)
|
|
||||||
{
|
|
||||||
gint stepmin, stepmax;
|
|
||||||
stepmin = gst_value_get_int_range_min (val);
|
|
||||||
stepmax = gst_value_get_int_range_max (val);
|
|
||||||
gst_caps_set_simple (caps, "step", G_TYPE_INT,
|
|
||||||
CLAMP (conv->def_step, stepmin, stepmax), NULL);
|
|
||||||
}
|
|
||||||
/* else it should be already fixed */
|
|
||||||
|
|
||||||
/* Assume rate is already fixed (if not it'll be fixed by default) */
|
|
||||||
|
|
||||||
gst_object_unref (conv);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************/
|
|
||||||
/* Actual conversion */
|
|
||||||
/***************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
static GstStateChangeReturn
|
|
||||||
gst_fftwspectrum_change_state (GstElement * element,
|
|
||||||
GstStateChange transition)
|
|
||||||
{
|
|
||||||
GstFFTWSpectrum *conv = GST_FFTWSPECTRUM (element);
|
|
||||||
GstStateChangeReturn res;
|
|
||||||
|
|
||||||
switch (transition)
|
|
||||||
{
|
|
||||||
case GST_STATE_CHANGE_NULL_TO_READY:
|
|
||||||
alloc_fftw_data (conv);
|
|
||||||
break;
|
|
||||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
|
||||||
conv->samples = (gdouble *) g_malloc (sizeof(gdouble));
|
|
||||||
conv->numsamples = 0;
|
|
||||||
conv->timestamp = 0;
|
|
||||||
conv->offset = 0;
|
|
||||||
break;
|
|
||||||
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = parent_class->change_state (element, transition);
|
|
||||||
|
|
||||||
switch (transition)
|
|
||||||
{
|
|
||||||
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
|
|
||||||
break;
|
|
||||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
|
||||||
g_free(conv->samples);
|
|
||||||
conv->samples = NULL;
|
|
||||||
conv->numsamples = 0;
|
|
||||||
conv->timestamp = 0;
|
|
||||||
conv->offset = 0;
|
|
||||||
break;
|
|
||||||
case GST_STATE_CHANGE_READY_TO_NULL:
|
|
||||||
free_fftw_data (conv);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Adds the samples contained in buf to the end of conv->samples,
|
|
||||||
* updating conv->numsamples.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
push_samples (GstFFTWSpectrum *conv, GstBuffer *buf)
|
|
||||||
{
|
|
||||||
gint newsamples = GST_BUFFER_SIZE (buf) / sizeof (gdouble);
|
|
||||||
gint oldsamples = conv->numsamples;
|
|
||||||
|
|
||||||
conv->numsamples += newsamples;
|
|
||||||
conv->samples = g_realloc (conv->samples, conv->numsamples * sizeof (gdouble));
|
|
||||||
memcpy (&conv->samples[oldsamples], GST_BUFFER_DATA (buf),
|
|
||||||
newsamples * sizeof (gdouble));
|
|
||||||
|
|
||||||
/* GST_LOG ("Added %d samples", newsamples); */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This basically does the opposite of push_samples, but takes samples
|
|
||||||
* off the front.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
shift_samples (GstFFTWSpectrum *conv, gint toshift)
|
|
||||||
{
|
|
||||||
gdouble *oldsamples = conv->samples;
|
|
||||||
|
|
||||||
conv->numsamples -= toshift;
|
|
||||||
conv->samples = g_malloc (MAX (conv->numsamples, 1) * sizeof (double));
|
|
||||||
memcpy (conv->samples, &oldsamples[toshift],
|
|
||||||
conv->numsamples * sizeof (gdouble));
|
|
||||||
g_free (oldsamples);
|
|
||||||
|
|
||||||
/* Fix the timestamp and offset */
|
|
||||||
conv->timestamp
|
|
||||||
+= gst_util_uint64_scale_int (GST_SECOND, toshift, conv->rate);
|
|
||||||
conv->offset += toshift;
|
|
||||||
|
|
||||||
/* GST_LOG ("Disposed of %d samples (time: %" GST_TIME_FORMAT " offset: %llu)",
|
|
||||||
toshift, GST_TIME_ARGS(conv->timestamp), conv->offset); */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* This function queues samples until there are at least
|
|
||||||
* max (conv->size, conv->step) samples to process. We
|
|
||||||
* then process samples in chunks of conv->size and increment
|
|
||||||
* by conv->step.
|
|
||||||
*/
|
|
||||||
static GstFlowReturn
|
|
||||||
gst_fftwspectrum_chain (GstPad * pad, GstBuffer * buf)
|
|
||||||
{
|
|
||||||
GstFFTWSpectrum *conv;
|
|
||||||
GstBuffer *outbuf;
|
|
||||||
GstFlowReturn res = GST_FLOW_OK;
|
|
||||||
|
|
||||||
conv = GST_FFTWSPECTRUM (gst_pad_get_parent (pad));
|
|
||||||
|
|
||||||
push_samples (conv, buf);
|
|
||||||
gst_buffer_unref (buf);
|
|
||||||
|
|
||||||
while (conv->numsamples >= MAX (conv->size, conv->step))
|
|
||||||
{
|
|
||||||
res = gst_pad_alloc_buffer_and_set_caps
|
|
||||||
(conv->srcpad, conv->offset, OUTPUT_SIZE (conv),
|
|
||||||
GST_PAD_CAPS(conv->srcpad), &outbuf);
|
|
||||||
if (res != GST_FLOW_OK)
|
|
||||||
break;
|
|
||||||
|
|
||||||
GST_BUFFER_SIZE (outbuf) = OUTPUT_SIZE (conv);
|
|
||||||
GST_BUFFER_OFFSET (outbuf) = conv->offset;
|
|
||||||
GST_BUFFER_OFFSET_END (outbuf) = conv->offset + conv->step;
|
|
||||||
GST_BUFFER_TIMESTAMP (outbuf) = conv->timestamp;
|
|
||||||
GST_BUFFER_DURATION (outbuf)
|
|
||||||
= gst_util_uint64_scale_int (GST_SECOND, conv->step, conv->rate);
|
|
||||||
|
|
||||||
/* Do the Fourier transform */
|
|
||||||
memcpy (conv->fftw_in, conv->samples, conv->size * sizeof (double));
|
|
||||||
fftw_execute (conv->fftw_plan);
|
|
||||||
{ /* Normalize */
|
|
||||||
gint i;
|
|
||||||
gfloat root = sqrtf (conv->size);
|
|
||||||
for (i = 0; i < 2*(conv->size/2+1); ++i)
|
|
||||||
conv->fftw_out[i] /= root;
|
|
||||||
}
|
|
||||||
memcpy (GST_BUFFER_DATA (outbuf), conv->fftw_out, OUTPUT_SIZE (conv));
|
|
||||||
|
|
||||||
res = gst_pad_push (conv->srcpad, outbuf);
|
|
||||||
|
|
||||||
shift_samples (conv, conv->step);
|
|
||||||
|
|
||||||
if (res != GST_FLOW_OK)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
gst_object_unref (conv);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
|||||||
/* GStreamer FFTW-based signal-to-spectrum converter
|
|
||||||
* Copyright (C) 2006 Joseph Rabinoff <bobqwatson@yahoo.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* *
|
|
||||||
* This program 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 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __GST_FFTWSPECTRUM_H__
|
|
||||||
#define __GST_FFTWSPECTRUM_H__
|
|
||||||
|
|
||||||
#include <gst/gst.h>
|
|
||||||
#include <fftw3.h>
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
|
||||||
|
|
||||||
/* #defines don't like whitespacey bits */
|
|
||||||
#define GST_TYPE_FFTWSPECTRUM \
|
|
||||||
(gst_fftwspectrum_get_type())
|
|
||||||
#define GST_FFTWSPECTRUM(obj) \
|
|
||||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FFTWSPECTRUM,GstFFTWSpectrum))
|
|
||||||
#define GST_FFTWSPECTRUM_CLASS(klass) \
|
|
||||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FFTWSPECTRUM,GstFFTWSpectrumClass))
|
|
||||||
|
|
||||||
typedef struct _GstFFTWSpectrum GstFFTWSpectrum;
|
|
||||||
typedef struct _GstFFTWSpectrumClass GstFFTWSpectrumClass;
|
|
||||||
|
|
||||||
struct _GstFFTWSpectrum
|
|
||||||
{
|
|
||||||
GstElement element;
|
|
||||||
|
|
||||||
GstPad *sinkpad, *srcpad;
|
|
||||||
|
|
||||||
/* Stream data */
|
|
||||||
gint rate, size, step;
|
|
||||||
|
|
||||||
/* Actual queued (incoming) stream */
|
|
||||||
gdouble *samples;
|
|
||||||
gint numsamples;
|
|
||||||
GstClockTime timestamp; /* Timestamp of the first sample */
|
|
||||||
guint64 offset; /* Offset of the first sample */
|
|
||||||
|
|
||||||
/* State data for fftw */
|
|
||||||
double *fftw_in;
|
|
||||||
double *fftw_out;
|
|
||||||
fftw_plan fftw_plan;
|
|
||||||
|
|
||||||
/* Properties */
|
|
||||||
gint32 def_size, def_step;
|
|
||||||
gboolean hi_q;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _GstFFTWSpectrumClass
|
|
||||||
{
|
|
||||||
GstElementClass parent_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
GType gst_fftwspectrum_get_type (void);
|
|
||||||
|
|
||||||
G_END_DECLS
|
|
||||||
|
|
||||||
#endif /* __GST_FFTWSPECTRUM_H__ */
|
|
@ -1,673 +0,0 @@
|
|||||||
/* GStreamer spectrum analysis toy
|
|
||||||
* Copyright (C) 2006 Joseph Rabinoff <bobqwatson@yahoo.com>
|
|
||||||
* Some code copyright (C) 2005 Gav Wood
|
|
||||||
*/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* *
|
|
||||||
* This program 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 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SECTION:element-moodbar
|
|
||||||
*
|
|
||||||
* <refsect2>
|
|
||||||
* <title>Example launch line</title>
|
|
||||||
* <para>
|
|
||||||
* <programlisting>
|
|
||||||
* gst-launch filesrc location=test.mp3 ! mad ! audioconvert ! fftwspectrum ! moodbar height=50 ! pngenc ! filesink location=test.png
|
|
||||||
* </programlisting>
|
|
||||||
* </para>
|
|
||||||
* </refsect2>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This plugin is based on the Moodbar code in Amarok version 1.4.0a,
|
|
||||||
* written by Gav Wood. The algorithm is basically the same as the
|
|
||||||
* one applied there, and the normalizing code below is taken directly
|
|
||||||
* from Gav Wood's Exscalibar package.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This plugin takes a frequency-domain stream, does some simple
|
|
||||||
* analysis, and returns a string of (unsigned char) rgb triples
|
|
||||||
* that represent the magnitude of various sections of the stream.
|
|
||||||
* Since we have to perform some normalization, we queue up all
|
|
||||||
* of our analysis until we get an EOS event, at which point we
|
|
||||||
* normalize and do the output. If a max-width is specified, the
|
|
||||||
* output is scaled down to the desired width if necessary.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* More precisely, the analysis performed is as follows:
|
|
||||||
* (1) the spectrum is broken into 24 parts, called "bark bands"
|
|
||||||
* (Gav's terminology), as given in bark_bands below
|
|
||||||
* (2) we compute the size of the first 8 bark bands and store
|
|
||||||
* that as the "red" component; similarly for blue and green
|
|
||||||
* (3) after receiving an EOS, we normalize all of the analysis
|
|
||||||
* done in (1) and (2) and return a stream of rgb triples
|
|
||||||
* (application/x-raw-rgb)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include <config.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <gst/gst.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include "gstmoodbar.h"
|
|
||||||
#include "spectrum.h"
|
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY (gst_moodbar_debug);
|
|
||||||
#define GST_CAT_DEFAULT gst_moodbar_debug
|
|
||||||
|
|
||||||
/* Filter signals and args */
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
/* FILL ME */
|
|
||||||
LAST_SIGNAL
|
|
||||||
};
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
ARG_0,
|
|
||||||
ARG_HEIGHT,
|
|
||||||
ARG_MAX_WIDTH
|
|
||||||
};
|
|
||||||
|
|
||||||
static GstStaticPadTemplate sink_factory
|
|
||||||
= GST_STATIC_PAD_TEMPLATE ("sink",
|
|
||||||
GST_PAD_SINK,
|
|
||||||
GST_PAD_ALWAYS,
|
|
||||||
GST_STATIC_CAPS
|
|
||||||
( SPECTRUM_FREQ_CAPS )
|
|
||||||
);
|
|
||||||
|
|
||||||
static GstStaticPadTemplate src_factory
|
|
||||||
= GST_STATIC_PAD_TEMPLATE ("src",
|
|
||||||
GST_PAD_SRC,
|
|
||||||
GST_PAD_ALWAYS,
|
|
||||||
GST_STATIC_CAPS
|
|
||||||
( "video/x-raw-rgb, "
|
|
||||||
"bpp = (int) 24, "
|
|
||||||
"depth = (int) 24, "
|
|
||||||
"height = (int) [ 1, MAX ], "
|
|
||||||
"width = (int) [ 1, MAX ], "
|
|
||||||
"framerate = (fraction) 0/1"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
GST_BOILERPLATE (GstMoodbar, gst_moodbar, GstElement,
|
|
||||||
GST_TYPE_ELEMENT);
|
|
||||||
|
|
||||||
static void gst_moodbar_set_property (GObject *object, guint prop_id,
|
|
||||||
const GValue *value, GParamSpec *pspec);
|
|
||||||
static void gst_moodbar_get_property (GObject *object, guint prop_id,
|
|
||||||
GValue *value, GParamSpec *pspec);
|
|
||||||
|
|
||||||
static gboolean gst_moodbar_set_sink_caps (GstPad *pad, GstCaps *caps);
|
|
||||||
static gboolean gst_moodbar_sink_event (GstPad *pad, GstEvent *event);
|
|
||||||
|
|
||||||
static GstFlowReturn gst_moodbar_chain (GstPad *pad, GstBuffer *buf);
|
|
||||||
static GstStateChangeReturn gst_moodbar_change_state (GstElement *element,
|
|
||||||
GstStateChange transition);
|
|
||||||
|
|
||||||
static void gst_moodbar_finish (GstMoodbar *mood);
|
|
||||||
|
|
||||||
/* This is a failsafe so we don't eat up all of a computer's memory
|
|
||||||
* if we hit an endless stream. */
|
|
||||||
#define MAX_TRIPLES (1024*1024*4)
|
|
||||||
|
|
||||||
#define NUMFREQS(mood) ((mood)->size/2+1)
|
|
||||||
|
|
||||||
/* Allocate mood->r, mood->g, and mood->b in chunks of this many */
|
|
||||||
#define FRAME_CHUNK 1000
|
|
||||||
|
|
||||||
/* Default height of the output image */
|
|
||||||
#define HEIGHT_DEFAULT 1
|
|
||||||
|
|
||||||
/* Default max-width of the output image, or 0 for no rescaling */
|
|
||||||
#define MAX_WIDTH_DEFAULT 0
|
|
||||||
|
|
||||||
/* We use this table to break up the incoming spectrum into segments */
|
|
||||||
static const guint bark_bands[24]
|
|
||||||
= { 100, 200, 300, 400, 510, 630, 770, 920,
|
|
||||||
1080, 1270, 1480, 1720, 2000, 2320, 2700, 3150,
|
|
||||||
3700, 4400, 5300, 6400, 7700, 9500, 12000, 15500 };
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************/
|
|
||||||
/* GObject boilerplate stuff */
|
|
||||||
/***************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_moodbar_base_init (gpointer gclass)
|
|
||||||
{
|
|
||||||
static GstElementDetails element_details =
|
|
||||||
{
|
|
||||||
"Moodbar analyzer",
|
|
||||||
"Filter/Converter/Moodbar",
|
|
||||||
"Convert a spectrum into a stream of (uchar) rgb triples representing its \"mood\"",
|
|
||||||
"Joe Rabinoff <bobqwatson@yahoo.com>"
|
|
||||||
};
|
|
||||||
GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
|
|
||||||
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_static_pad_template_get (&src_factory));
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_static_pad_template_get (&sink_factory));
|
|
||||||
gst_element_class_set_details (element_class, &element_details);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* initialize the plugin's class */
|
|
||||||
static void
|
|
||||||
gst_moodbar_class_init (GstMoodbarClass * klass)
|
|
||||||
{
|
|
||||||
GObjectClass *gobject_class;
|
|
||||||
GstElementClass *gstelement_class;
|
|
||||||
|
|
||||||
gobject_class = (GObjectClass *) klass;
|
|
||||||
gstelement_class = (GstElementClass *) klass;
|
|
||||||
|
|
||||||
gobject_class->set_property = gst_moodbar_set_property;
|
|
||||||
gobject_class->get_property = gst_moodbar_get_property;
|
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, ARG_HEIGHT,
|
|
||||||
g_param_spec_int ("height", "Image height",
|
|
||||||
"The height of the resulting raw image",
|
|
||||||
1, G_MAXINT32, HEIGHT_DEFAULT, G_PARAM_READWRITE));
|
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, ARG_MAX_WIDTH,
|
|
||||||
g_param_spec_int ("max-width", "Image maximum width",
|
|
||||||
"The maximum width of the resulting raw image, or 0 for no rescaling",
|
|
||||||
0, G_MAXINT32, MAX_WIDTH_DEFAULT, G_PARAM_READWRITE));
|
|
||||||
|
|
||||||
gstelement_class->change_state
|
|
||||||
= GST_DEBUG_FUNCPTR (gst_moodbar_change_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* initialize the new element
|
|
||||||
* instantiate pads and add them to element
|
|
||||||
* set functions
|
|
||||||
* initialize structure
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
gst_moodbar_init (GstMoodbar *mood, GstMoodbarClass *gclass)
|
|
||||||
{
|
|
||||||
GstElementClass *klass = GST_ELEMENT_GET_CLASS (mood);
|
|
||||||
|
|
||||||
mood->sinkpad =
|
|
||||||
gst_pad_new_from_template
|
|
||||||
(gst_element_class_get_pad_template (klass, "sink"), "sink");
|
|
||||||
gst_pad_set_setcaps_function (mood->sinkpad,
|
|
||||||
GST_DEBUG_FUNCPTR (gst_moodbar_set_sink_caps));
|
|
||||||
gst_pad_set_event_function (mood->sinkpad,
|
|
||||||
GST_DEBUG_FUNCPTR (gst_moodbar_sink_event));
|
|
||||||
gst_pad_set_chain_function (mood->sinkpad,
|
|
||||||
GST_DEBUG_FUNCPTR (gst_moodbar_chain));
|
|
||||||
|
|
||||||
mood->srcpad =
|
|
||||||
gst_pad_new_from_template
|
|
||||||
(gst_element_class_get_pad_template (klass, "src"), "src");
|
|
||||||
|
|
||||||
|
|
||||||
gst_element_add_pad (GST_ELEMENT (mood), mood->sinkpad);
|
|
||||||
gst_element_add_pad (GST_ELEMENT (mood), mood->srcpad);
|
|
||||||
|
|
||||||
/* These are set once the (sink) capabilities are determined */
|
|
||||||
mood->rate = 0;
|
|
||||||
mood->size = 0;
|
|
||||||
mood->barkband_table = NULL;
|
|
||||||
|
|
||||||
/* These are allocated when we change to PAUSED */
|
|
||||||
mood->r = NULL;
|
|
||||||
mood->g = NULL;
|
|
||||||
mood->b = NULL;
|
|
||||||
mood->numframes = 0;
|
|
||||||
|
|
||||||
/* Property */
|
|
||||||
mood->height = HEIGHT_DEFAULT;
|
|
||||||
mood->max_width = MAX_WIDTH_DEFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void gst_moodbar_set_property (GObject *object, guint prop_id,
|
|
||||||
const GValue *value, GParamSpec *pspec)
|
|
||||||
{
|
|
||||||
GstMoodbar *mood = GST_MOODBAR (object);
|
|
||||||
|
|
||||||
switch (prop_id)
|
|
||||||
{
|
|
||||||
case ARG_HEIGHT:
|
|
||||||
mood->height = (guint) g_value_get_int (value);
|
|
||||||
break;
|
|
||||||
case ARG_MAX_WIDTH:
|
|
||||||
mood->max_width = (guint) g_value_get_int (value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void gst_moodbar_get_property (GObject *object, guint prop_id,
|
|
||||||
GValue *value, GParamSpec *pspec)
|
|
||||||
{
|
|
||||||
GstMoodbar *mood = GST_MOODBAR (object);
|
|
||||||
|
|
||||||
switch (prop_id)
|
|
||||||
{
|
|
||||||
case ARG_HEIGHT:
|
|
||||||
g_value_set_int (value, (int) mood->height);
|
|
||||||
break;
|
|
||||||
case ARG_MAX_WIDTH:
|
|
||||||
g_value_set_int (value, (int) mood->max_width);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************/
|
|
||||||
/* Pad handling */
|
|
||||||
/***************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
/* This calculates a table that caches which bark band slot each
|
|
||||||
* incoming band is supposed to go in. */
|
|
||||||
static void
|
|
||||||
calc_barkband_table (GstMoodbar *mood)
|
|
||||||
{
|
|
||||||
guint i;
|
|
||||||
guint barkband = 0;
|
|
||||||
|
|
||||||
/* Avoid divide-by-zero */
|
|
||||||
if (!mood->size || !mood->rate)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (mood->barkband_table)
|
|
||||||
g_free (mood->barkband_table);
|
|
||||||
|
|
||||||
mood->barkband_table = g_malloc (NUMFREQS (mood) * sizeof (guint));
|
|
||||||
|
|
||||||
for (i = 0; i < NUMFREQS (mood); ++i)
|
|
||||||
{
|
|
||||||
if (barkband < 23 &&
|
|
||||||
(guint) GST_SPECTRUM_BAND_FREQ (i, mood->size, mood->rate)
|
|
||||||
>= bark_bands[barkband])
|
|
||||||
barkband++;
|
|
||||||
|
|
||||||
mood->barkband_table[i] = barkband;
|
|
||||||
|
|
||||||
/*
|
|
||||||
GST_LOG ("Band %d (frequency %f) -> barkband %d (frequency %d)",
|
|
||||||
i, GST_SPECTRUM_BAND_FREQ (i, mood->size, mood->rate),
|
|
||||||
barkband, bark_bands[barkband]);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Setting the sink caps just gets the rate and size parameters.
|
|
||||||
* Note that we do not support upstream caps renegotiation, since
|
|
||||||
* we could only possibly scale the height anyway.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_moodbar_set_sink_caps (GstPad *pad, GstCaps *caps)
|
|
||||||
{
|
|
||||||
GstMoodbar *mood;
|
|
||||||
GstStructure *newstruct;
|
|
||||||
gint rate, size;
|
|
||||||
gboolean res = FALSE;
|
|
||||||
|
|
||||||
mood = GST_MOODBAR (gst_pad_get_parent (pad));
|
|
||||||
|
|
||||||
newstruct = gst_caps_get_structure (caps, 0);
|
|
||||||
if (!gst_structure_get_int (newstruct, "rate", &rate) ||
|
|
||||||
!gst_structure_get_int (newstruct, "size", &size))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
res = TRUE;
|
|
||||||
|
|
||||||
mood->rate = rate;
|
|
||||||
mood->size = (guint) size;
|
|
||||||
calc_barkband_table (mood);
|
|
||||||
|
|
||||||
out:
|
|
||||||
gst_object_unref (mood);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_moodbar_sink_event (GstPad *pad, GstEvent *event)
|
|
||||||
{
|
|
||||||
GstMoodbar *mood;
|
|
||||||
gboolean res = TRUE;
|
|
||||||
|
|
||||||
mood = GST_MOODBAR (gst_pad_get_parent (pad));
|
|
||||||
|
|
||||||
if (GST_EVENT_TYPE (event) == GST_EVENT_EOS)
|
|
||||||
gst_moodbar_finish (mood);
|
|
||||||
|
|
||||||
res = gst_pad_push_event (mood->srcpad, event);
|
|
||||||
gst_object_unref (mood);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************/
|
|
||||||
/* Actual analysis */
|
|
||||||
/***************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
static GstStateChangeReturn
|
|
||||||
gst_moodbar_change_state (GstElement *element, GstStateChange transition)
|
|
||||||
{
|
|
||||||
GstMoodbar *mood = GST_MOODBAR (element);
|
|
||||||
GstStateChangeReturn res;
|
|
||||||
|
|
||||||
switch (transition)
|
|
||||||
{
|
|
||||||
case GST_STATE_CHANGE_NULL_TO_READY:
|
|
||||||
calc_barkband_table (mood);
|
|
||||||
break;
|
|
||||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
|
||||||
mood->r = (gdouble *) g_malloc (FRAME_CHUNK * sizeof(gdouble));
|
|
||||||
mood->g = (gdouble *) g_malloc (FRAME_CHUNK * sizeof(gdouble));
|
|
||||||
mood->b = (gdouble *) g_malloc (FRAME_CHUNK * sizeof(gdouble));
|
|
||||||
mood->numframes = 0;
|
|
||||||
break;
|
|
||||||
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = parent_class->change_state (element, transition);
|
|
||||||
|
|
||||||
switch (transition)
|
|
||||||
{
|
|
||||||
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
|
|
||||||
break;
|
|
||||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
|
||||||
g_free (mood->r);
|
|
||||||
g_free (mood->g);
|
|
||||||
g_free (mood->b);
|
|
||||||
mood->r = NULL;
|
|
||||||
mood->g = NULL;
|
|
||||||
mood->b = NULL;
|
|
||||||
mood->numframes = 0;
|
|
||||||
break;
|
|
||||||
case GST_STATE_CHANGE_READY_TO_NULL:
|
|
||||||
g_free (mood->barkband_table);
|
|
||||||
mood->barkband_table = NULL;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* We allocate r, g, b frames in chunks of FRAME_CHUNK so we don't
|
|
||||||
* have to realloc every time a buffer comes in.
|
|
||||||
*/
|
|
||||||
static gboolean
|
|
||||||
allocate_another_frame (GstMoodbar *mood)
|
|
||||||
{
|
|
||||||
mood->numframes++;
|
|
||||||
|
|
||||||
/* Failsafe */
|
|
||||||
if (mood->numframes == MAX_TRIPLES)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if(mood->numframes % FRAME_CHUNK == 0)
|
|
||||||
{
|
|
||||||
guint size = (mood->numframes + FRAME_CHUNK) * sizeof (gdouble);
|
|
||||||
|
|
||||||
mood->r = (gdouble *) g_realloc (mood->r, size);
|
|
||||||
mood->g = (gdouble *) g_realloc (mood->g, size);
|
|
||||||
mood->b = (gdouble *) g_realloc (mood->b, size);
|
|
||||||
|
|
||||||
if (mood->r == NULL || mood->g == NULL || mood->b == NULL)
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* This function does most of the analysis on the spectra we
|
|
||||||
* get as input and caches them. We actually push buffers
|
|
||||||
* once we receive an EOS signal.
|
|
||||||
*/
|
|
||||||
static GstFlowReturn
|
|
||||||
gst_moodbar_chain (GstPad *pad, GstBuffer *buf)
|
|
||||||
{
|
|
||||||
GstMoodbar *mood = GST_MOODBAR (gst_pad_get_parent (pad));
|
|
||||||
guint i;
|
|
||||||
gdouble amplitudes[24], rgb[3] = {0.f, 0.f, 0.f};
|
|
||||||
gdouble *out, real, imag;
|
|
||||||
guint numfreqs = NUMFREQS (mood);
|
|
||||||
|
|
||||||
if (GST_BUFFER_SIZE (buf) != numfreqs * sizeof (gdouble) * 2)
|
|
||||||
{
|
|
||||||
gst_object_unref (mood);
|
|
||||||
return GST_FLOW_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
out = (gdouble *) GST_BUFFER_DATA (buf);
|
|
||||||
|
|
||||||
if (!allocate_another_frame (mood))
|
|
||||||
return GST_FLOW_ERROR;
|
|
||||||
|
|
||||||
/* Calculate total amplitudes for the different bark bands */
|
|
||||||
|
|
||||||
for (i = 0; i < 24; ++i)
|
|
||||||
amplitudes[i] = 0.f;
|
|
||||||
|
|
||||||
for (i = 0; i < numfreqs; ++i)
|
|
||||||
{
|
|
||||||
real = out[2*i]; imag = out[2*i + 1];
|
|
||||||
amplitudes[mood->barkband_table[i]] += sqrtf (real*real + imag*imag);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now divide the bark bands into thirds and compute their total
|
|
||||||
* amplitudes */
|
|
||||||
|
|
||||||
for (i = 0; i < 24; ++i)
|
|
||||||
rgb[i/8] += amplitudes[i] * amplitudes[i];
|
|
||||||
|
|
||||||
rgb[0] = sqrtf (rgb[0]);
|
|
||||||
rgb[1] = sqrtf (rgb[1]);
|
|
||||||
rgb[2] = sqrtf (rgb[2]);
|
|
||||||
|
|
||||||
mood->r[mood->numframes] = rgb[0];
|
|
||||||
mood->g[mood->numframes] = rgb[1];
|
|
||||||
mood->b[mood->numframes] = rgb[2];
|
|
||||||
|
|
||||||
gst_buffer_unref (buf);
|
|
||||||
gst_object_unref (mood);
|
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* The normalization code was copied from Gav Wood's Exscalibar
|
|
||||||
* library, normalise.cpp
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
normalize (gdouble *vals, guint numvals)
|
|
||||||
{
|
|
||||||
gdouble mini, maxi, tu = 0.f, tb = 0.f;
|
|
||||||
gdouble avgu = 0.f, avgb = 0.f, delta, avg = 0.f;
|
|
||||||
gdouble avguu = 0.f, avgbb = 0.f;
|
|
||||||
guint i;
|
|
||||||
gint t = 0;
|
|
||||||
|
|
||||||
if (!numvals)
|
|
||||||
return;
|
|
||||||
|
|
||||||
mini = maxi = vals[0];
|
|
||||||
|
|
||||||
for (i = 1; i < numvals; i++)
|
|
||||||
{
|
|
||||||
if (vals[i] > maxi)
|
|
||||||
maxi = vals[i];
|
|
||||||
else if (vals[i] < mini)
|
|
||||||
mini = vals[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < numvals; i++)
|
|
||||||
{
|
|
||||||
if(vals[i] != mini && vals[i] != maxi)
|
|
||||||
{
|
|
||||||
avg += vals[i] / ((gdouble) numvals);
|
|
||||||
t++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < numvals; i++)
|
|
||||||
{
|
|
||||||
if (vals[i] != mini && vals[i] != maxi)
|
|
||||||
{
|
|
||||||
if (vals[i] > avg)
|
|
||||||
{
|
|
||||||
avgu += vals[i];
|
|
||||||
tu++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
avgb += vals[i];
|
|
||||||
tb++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
avgu /= (gdouble) tu;
|
|
||||||
avgb /= (gdouble) tb;
|
|
||||||
|
|
||||||
tu = 0.f;
|
|
||||||
tb = 0.f;
|
|
||||||
for (i = 0; i < numvals; i++)
|
|
||||||
{
|
|
||||||
if (vals[i] != mini && vals[i] != maxi)
|
|
||||||
{
|
|
||||||
if (vals[i] > avgu)
|
|
||||||
{
|
|
||||||
avguu += vals[i];
|
|
||||||
tu++;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (vals[i] < avgb)
|
|
||||||
{
|
|
||||||
avgbb += vals[i];
|
|
||||||
tb++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
avguu /= (gdouble) tu;
|
|
||||||
avgbb /= (gdouble) tb;
|
|
||||||
|
|
||||||
mini = MAX (avg + (avgb - avg) * 2.f, avgbb);
|
|
||||||
maxi = MIN (avg + (avgu - avg) * 2.f, avguu);
|
|
||||||
delta = maxi - mini;
|
|
||||||
|
|
||||||
if (delta == 0.f)
|
|
||||||
delta = 1.f;
|
|
||||||
|
|
||||||
for (i = 0; i < numvals; i++)
|
|
||||||
vals[i] = isfinite (vals[i]) ? MIN(1.f, MAX(0.f, (vals[i] - mini) / delta))
|
|
||||||
: 0.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* This function normalizes all of the cached r,g,b data and
|
|
||||||
* finally pushes a monster buffer with all of our output.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
gst_moodbar_finish (GstMoodbar *mood)
|
|
||||||
{
|
|
||||||
GstBuffer *buf;
|
|
||||||
guchar *data;
|
|
||||||
guint line;
|
|
||||||
guint output_width;
|
|
||||||
|
|
||||||
if (mood->max_width == 0
|
|
||||||
|| mood->numframes <= mood->max_width)
|
|
||||||
output_width = mood->numframes;
|
|
||||||
else
|
|
||||||
output_width = mood->max_width;
|
|
||||||
|
|
||||||
normalize (mood->r, mood->numframes);
|
|
||||||
normalize (mood->g, mood->numframes);
|
|
||||||
normalize (mood->b, mood->numframes);
|
|
||||||
|
|
||||||
buf = gst_buffer_new_and_alloc
|
|
||||||
(output_width * mood->height * 3 * sizeof (guchar));
|
|
||||||
if (!buf)
|
|
||||||
return;
|
|
||||||
/* Don't set the timestamp, duration, etc. since it's irrelevant */
|
|
||||||
GST_BUFFER_OFFSET (buf) = 0;
|
|
||||||
data = (guchar *) GST_BUFFER_DATA (buf);
|
|
||||||
|
|
||||||
gdouble r, g, b;
|
|
||||||
guint i, j, n;
|
|
||||||
guint start, end;
|
|
||||||
for (line = 0; line < mood->height; ++line)
|
|
||||||
{
|
|
||||||
for (i = 0; i < output_width; ++i)
|
|
||||||
{
|
|
||||||
r = 0.f; g = 0.f; b = 0.f;
|
|
||||||
start = i * mood->numframes / output_width;
|
|
||||||
end = (i + 1) * mood->numframes / output_width;
|
|
||||||
if ( start == end )
|
|
||||||
end = start + 1;
|
|
||||||
|
|
||||||
for( j = start; j < end; j++ )
|
|
||||||
{
|
|
||||||
r += mood->r[j] * 255.f;
|
|
||||||
g += mood->g[j] * 255.f;
|
|
||||||
b += mood->b[j] * 255.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
n = end - start;
|
|
||||||
|
|
||||||
*(data++) = (guchar) (r / ((gdouble) n));
|
|
||||||
*(data++) = (guchar) (g / ((gdouble) n));
|
|
||||||
*(data++) = (guchar) (b / ((gdouble) n));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{ /* Now we (finally) know the width of the image we're pushing */
|
|
||||||
GstCaps *caps = gst_caps_copy (gst_pad_get_caps (mood->srcpad));
|
|
||||||
gboolean res;
|
|
||||||
gst_caps_set_simple (caps, "width", G_TYPE_INT, output_width, NULL);
|
|
||||||
gst_caps_set_simple (caps, "height", G_TYPE_INT, mood->height, NULL);
|
|
||||||
res = gst_pad_set_caps (mood->srcpad, caps);
|
|
||||||
if (res)
|
|
||||||
gst_buffer_set_caps (buf, caps);
|
|
||||||
gst_caps_unref (caps);
|
|
||||||
if (!res)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
gst_pad_push (mood->srcpad, buf);
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
/* GStreamer spectrum analysis toy
|
|
||||||
* Copyright (C) 2006 Joseph Rabinoff <bobqwatson@yahoo.com>
|
|
||||||
* Some code copyright (C) 2005 Gav Wood
|
|
||||||
*/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* *
|
|
||||||
* This program 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 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifndef __GST_MOODBAR_H__
|
|
||||||
#define __GST_MOODBAR_H__
|
|
||||||
|
|
||||||
#include <gst/gst.h>
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
|
||||||
|
|
||||||
/* #defines don't like whitespacey bits */
|
|
||||||
#define GST_TYPE_MOODBAR \
|
|
||||||
(gst_moodbar_get_type())
|
|
||||||
#define GST_MOODBAR(obj) \
|
|
||||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MOODBAR,GstMoodbar))
|
|
||||||
#define GST_MOODBAR_CLASS(klass) \
|
|
||||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MOODBAR,GstMoodbarClass))
|
|
||||||
|
|
||||||
typedef struct _GstMoodbar GstMoodbar;
|
|
||||||
typedef struct _GstMoodbarClass GstMoodbarClass;
|
|
||||||
|
|
||||||
struct _GstMoodbar
|
|
||||||
{
|
|
||||||
GstElement element;
|
|
||||||
|
|
||||||
GstPad *sinkpad, *srcpad;
|
|
||||||
|
|
||||||
/* Stream data */
|
|
||||||
gint rate, size;
|
|
||||||
|
|
||||||
/* Cached band -> bark band table */
|
|
||||||
guint *barkband_table;
|
|
||||||
|
|
||||||
/* Queued moodbar data */
|
|
||||||
gdouble *r, *g, *b;
|
|
||||||
guint numframes;
|
|
||||||
|
|
||||||
/* Property */
|
|
||||||
guint height;
|
|
||||||
guint max_width;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _GstMoodbarClass
|
|
||||||
{
|
|
||||||
GstElementClass parent_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
GType gst_moodbar_get_type (void);
|
|
||||||
|
|
||||||
G_END_DECLS
|
|
||||||
|
|
||||||
#endif /* __GST_MOODBAR_H__ */
|
|
48
gst/moodbar/plugin.cpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/* This file is part of Clementine.
|
||||||
|
Copyright 2014, David Sansome <me@davidsansome.com>
|
||||||
|
|
||||||
|
Clementine 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.
|
||||||
|
|
||||||
|
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
#include "gstfastspectrum.h"
|
||||||
|
#include "plugin.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
static gboolean plugin_init(GstPlugin* plugin) {
|
||||||
|
if (!gst_element_register(plugin, "fastspectrum",
|
||||||
|
GST_RANK_NONE, GST_TYPE_FASTSPECTRUM)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
int gstfastspectrum_register_static() {
|
||||||
|
return gst_plugin_register_static(
|
||||||
|
GST_VERSION_MAJOR,
|
||||||
|
GST_VERSION_MINOR,
|
||||||
|
"fastspectrum",
|
||||||
|
"Fast spectrum analyzer for generating Moodbars",
|
||||||
|
plugin_init,
|
||||||
|
"0.1",
|
||||||
|
"GPL",
|
||||||
|
"FastSpectrum",
|
||||||
|
"FastSpectrum",
|
||||||
|
"https://www.clementine-player.org");
|
||||||
|
}
|
25
gst/moodbar/plugin.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/* This file is part of Clementine.
|
||||||
|
Copyright 2014, David Sansome <me@davidsansome.com>
|
||||||
|
|
||||||
|
Clementine 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.
|
||||||
|
|
||||||
|
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GST_MOODBAR_PLUGIN_H_
|
||||||
|
#define GST_MOODBAR_PLUGIN_H_
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
int gstfastspectrum_register_static();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // GST_MOODBAR_PLUGIN_H_
|
@ -1,71 +0,0 @@
|
|||||||
/* GStreamer moodbar plugin globals
|
|
||||||
* Copyright (C) 2006 Joseph Rabinoff <bobqwatson@yahoo.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* *
|
|
||||||
* This program 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 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include <config.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <gst/gst.h>
|
|
||||||
|
|
||||||
#include "gstfftwspectrum.h"
|
|
||||||
#include "gstmoodbar.h"
|
|
||||||
#include "spectrum.h"
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************/
|
|
||||||
/* Plugin managing */
|
|
||||||
/***************************************************************/
|
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_EXTERN (gst_fftwspectrum_debug);
|
|
||||||
GST_DEBUG_CATEGORY_EXTERN (gst_moodbar_debug);
|
|
||||||
|
|
||||||
|
|
||||||
/* entry point to initialize the plug-in
|
|
||||||
* initialize the plug-in itself
|
|
||||||
* register the element factories and pad templates
|
|
||||||
* register the features
|
|
||||||
*
|
|
||||||
* exchange the string 'plugin' with your elemnt name
|
|
||||||
*/
|
|
||||||
static gboolean
|
|
||||||
plugin_init (GstPlugin * plugin)
|
|
||||||
{
|
|
||||||
if (!gst_element_register (plugin, "fftwspectrum",
|
|
||||||
GST_RANK_NONE, GST_TYPE_FFTWSPECTRUM))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (!gst_element_register (plugin, "moodbar",
|
|
||||||
GST_RANK_NONE, GST_TYPE_MOODBAR))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT (gst_fftwspectrum_debug, "fftwspectrum",
|
|
||||||
0, "FFTW Sample-to-Spectrum Converter Plugin");
|
|
||||||
GST_DEBUG_CATEGORY_INIT (gst_moodbar_debug, "moodbar",
|
|
||||||
0, "Moodbar analyzer");
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void gstmoodbar_register_static() {
|
|
||||||
gst_plugin_register_static(
|
|
||||||
GST_VERSION_MAJOR,
|
|
||||||
GST_VERSION_MINOR,
|
|
||||||
"moodbar",
|
|
||||||
"Frequency analyzer and converter plugin",
|
|
||||||
plugin_init,
|
|
||||||
"0.1.2",
|
|
||||||
"GPL",
|
|
||||||
"Moodbar",
|
|
||||||
"Moodbar",
|
|
||||||
"http://amarok.kde.org/wiki/Moodbar");
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
/* GStreamer moodbar plugin globals
|
|
||||||
* Copyright (C) 2006 Joseph Rabinoff <bobqwatson@yahoo.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* *
|
|
||||||
* This program 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 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifndef __SPECTRUM_H__
|
|
||||||
#define __SPECTRUM_H__
|
|
||||||
|
|
||||||
|
|
||||||
/* Since fftwspectrum and fftwunspectrum are supposed to be
|
|
||||||
* opposites, they'll be using the same caps: */
|
|
||||||
|
|
||||||
#define SPECTRUM_SIGNAL_CAPS "audio/x-raw-float, " \
|
|
||||||
"rate = (int) [ 1, MAX ], " \
|
|
||||||
"channels = (int) 1, " \
|
|
||||||
"endianness = (int) BYTE_ORDER, " \
|
|
||||||
"width = (int) 64, " \
|
|
||||||
"signed = (boolean) true"
|
|
||||||
|
|
||||||
/* audio/x-spectrum-complex-float is an array of complex floats. A
|
|
||||||
* complex float is just a pair (r, i) of a real float and an
|
|
||||||
* imaginary float, each with the specified width. The properties
|
|
||||||
* are as follows:
|
|
||||||
* rate: the rate of the original signal
|
|
||||||
* size: the number of signals processed to make the current buffer
|
|
||||||
* step: the number of signals advanced after the current buffer
|
|
||||||
* width: the size of the real & imaginary parts of the data
|
|
||||||
* endianness: ditto
|
|
||||||
*
|
|
||||||
* Each audio/x-spectrum-complex-float buffer represents the Fourier
|
|
||||||
* transform of size samples, and hence _must_ have exactly
|
|
||||||
* floor(size/2) + 1 complex floats in it; in other words, its
|
|
||||||
* buffer size must be (floor(size/2) + 1) * 2 * sizeof(gfloat)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define SPECTRUM_FREQ_CAPS "audio/x-spectrum-complex-float, " \
|
|
||||||
"rate = (int) [ 1, MAX ], " \
|
|
||||||
"endianness = (int) BYTE_ORDER, " \
|
|
||||||
"width = (int) 64, " \
|
|
||||||
"size = (int) [ 1, MAX ], " \
|
|
||||||
"step = (int) [ 1, MAX ]"
|
|
||||||
|
|
||||||
|
|
||||||
/* Given a band number from a spectrum made from size audio
|
|
||||||
* samples at the given rate, return the frequency that band
|
|
||||||
* corresponds to.
|
|
||||||
*/
|
|
||||||
#define GST_SPECTRUM_BAND_FREQ(band, size, rate) \
|
|
||||||
(((gfloat)(band))*((gfloat)(rate))/((gfloat)(size)))
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
void gstmoodbar_register_static();
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* __SPECTRUM_H__ */
|
|
@ -75,8 +75,10 @@ set(SOURCES
|
|||||||
analyzers/blockanalyzer.cpp
|
analyzers/blockanalyzer.cpp
|
||||||
analyzers/boomanalyzer.cpp
|
analyzers/boomanalyzer.cpp
|
||||||
analyzers/nyancatanalyzer.cpp
|
analyzers/nyancatanalyzer.cpp
|
||||||
|
analyzers/rainbowdashanalyzer.cpp
|
||||||
analyzers/sonogram.cpp
|
analyzers/sonogram.cpp
|
||||||
analyzers/turbine.cpp
|
analyzers/turbine.cpp
|
||||||
|
analyzers/fht.cpp
|
||||||
|
|
||||||
core/appearance.cpp
|
core/appearance.cpp
|
||||||
core/application.cpp
|
core/application.cpp
|
||||||
@ -87,7 +89,6 @@ set(SOURCES
|
|||||||
core/deletefiles.cpp
|
core/deletefiles.cpp
|
||||||
core/filesystemmusicstorage.cpp
|
core/filesystemmusicstorage.cpp
|
||||||
core/filesystemwatcherinterface.cpp
|
core/filesystemwatcherinterface.cpp
|
||||||
core/fht.cpp
|
|
||||||
core/globalshortcutbackend.cpp
|
core/globalshortcutbackend.cpp
|
||||||
core/globalshortcuts.cpp
|
core/globalshortcuts.cpp
|
||||||
core/gnomeglobalshortcutbackend.cpp
|
core/gnomeglobalshortcutbackend.cpp
|
||||||
@ -164,48 +165,49 @@ set(SOURCES
|
|||||||
globalsearch/suggestionwidget.cpp
|
globalsearch/suggestionwidget.cpp
|
||||||
globalsearch/urlsearchprovider.cpp
|
globalsearch/urlsearchprovider.cpp
|
||||||
|
|
||||||
internet/cloudfilesearchprovider.cpp
|
internet/core/cloudfilesearchprovider.cpp
|
||||||
internet/cloudfileservice.cpp
|
internet/core/cloudfileservice.cpp
|
||||||
internet/digitallyimportedclient.cpp
|
internet/digitally/digitallyimportedclient.cpp
|
||||||
internet/digitallyimportedservicebase.cpp
|
internet/digitally/digitallyimportedservicebase.cpp
|
||||||
internet/digitallyimportedsettingspage.cpp
|
internet/digitally/digitallyimportedsettingspage.cpp
|
||||||
internet/digitallyimportedurlhandler.cpp
|
internet/digitally/digitallyimportedurlhandler.cpp
|
||||||
internet/geolocator.cpp
|
internet/core/geolocator.cpp
|
||||||
internet/groovesharkradio.cpp
|
internet/grooveshark/groovesharkradio.cpp
|
||||||
internet/groovesharkservice.cpp
|
internet/grooveshark/groovesharkservice.cpp
|
||||||
internet/groovesharksettingspage.cpp
|
internet/grooveshark/groovesharksettingspage.cpp
|
||||||
internet/groovesharkurlhandler.cpp
|
internet/grooveshark/groovesharkurlhandler.cpp
|
||||||
internet/icecastbackend.cpp
|
internet/icecast/icecastbackend.cpp
|
||||||
internet/icecastfilterwidget.cpp
|
internet/icecast/icecastfilterwidget.cpp
|
||||||
internet/icecastmodel.cpp
|
internet/icecast/icecastmodel.cpp
|
||||||
internet/icecastservice.cpp
|
internet/icecast/icecastservice.cpp
|
||||||
internet/internetmodel.cpp
|
internet/core/internetmodel.cpp
|
||||||
internet/internetplaylistitem.cpp
|
internet/core/internetplaylistitem.cpp
|
||||||
internet/internetservice.cpp
|
internet/core/internetservice.cpp
|
||||||
internet/internetview.cpp
|
internet/core/internetshowsettingspage.cpp
|
||||||
internet/internetviewcontainer.cpp
|
internet/core/internetview.cpp
|
||||||
internet/jamendodynamicplaylist.cpp
|
internet/core/internetviewcontainer.cpp
|
||||||
internet/jamendoplaylistitem.cpp
|
internet/jamendo/jamendodynamicplaylist.cpp
|
||||||
internet/jamendoservice.cpp
|
internet/jamendo/jamendoplaylistitem.cpp
|
||||||
internet/localredirectserver.cpp
|
internet/jamendo/jamendoservice.cpp
|
||||||
internet/magnatunedownloaddialog.cpp
|
internet/core/localredirectserver.cpp
|
||||||
internet/magnatuneplaylistitem.cpp
|
internet/magnatune/magnatunedownloaddialog.cpp
|
||||||
internet/magnatuneservice.cpp
|
internet/magnatune/magnatuneplaylistitem.cpp
|
||||||
internet/magnatunesettingspage.cpp
|
internet/magnatune/magnatuneservice.cpp
|
||||||
internet/magnatuneurlhandler.cpp
|
internet/magnatune/magnatunesettingspage.cpp
|
||||||
internet/oauthenticator.cpp
|
internet/magnatune/magnatuneurlhandler.cpp
|
||||||
internet/savedradio.cpp
|
internet/core/oauthenticator.cpp
|
||||||
internet/searchboxwidget.cpp
|
internet/internetradio/savedradio.cpp
|
||||||
internet/somafmservice.cpp
|
internet/core/searchboxwidget.cpp
|
||||||
internet/somafmurlhandler.cpp
|
internet/somafm/somafmservice.cpp
|
||||||
internet/soundcloudservice.cpp
|
internet/somafm/somafmurlhandler.cpp
|
||||||
internet/soundcloudsettingspage.cpp
|
internet/soundcloud/soundcloudservice.cpp
|
||||||
internet/spotifyserver.cpp
|
internet/soundcloud/soundcloudsettingspage.cpp
|
||||||
internet/spotifyservice.cpp
|
internet/spotify/spotifyserver.cpp
|
||||||
internet/spotifysettingspage.cpp
|
internet/spotify/spotifyservice.cpp
|
||||||
internet/subsonicservice.cpp
|
internet/spotify/spotifysettingspage.cpp
|
||||||
internet/subsonicsettingspage.cpp
|
internet/subsonic/subsonicservice.cpp
|
||||||
internet/subsonicurlhandler.cpp
|
internet/subsonic/subsonicsettingspage.cpp
|
||||||
|
internet/subsonic/subsonicurlhandler.cpp
|
||||||
|
|
||||||
library/groupbydialog.cpp
|
library/groupbydialog.cpp
|
||||||
library/library.cpp
|
library/library.cpp
|
||||||
@ -232,6 +234,7 @@ set(SOURCES
|
|||||||
networkremote/networkremotehelper.cpp
|
networkremote/networkremotehelper.cpp
|
||||||
networkremote/outgoingdatacreator.cpp
|
networkremote/outgoingdatacreator.cpp
|
||||||
networkremote/remoteclient.cpp
|
networkremote/remoteclient.cpp
|
||||||
|
networkremote/songsender.cpp
|
||||||
networkremote/tcpremoteclient.cpp
|
networkremote/tcpremoteclient.cpp
|
||||||
networkremote/webremoteclient.cpp
|
networkremote/webremoteclient.cpp
|
||||||
networkremote/zeroconf.cpp
|
networkremote/zeroconf.cpp
|
||||||
@ -249,6 +252,7 @@ set(SOURCES
|
|||||||
playlist/playlistlistmodel.cpp
|
playlist/playlistlistmodel.cpp
|
||||||
playlist/playlistlistview.cpp
|
playlist/playlistlistview.cpp
|
||||||
playlist/playlistmanager.cpp
|
playlist/playlistmanager.cpp
|
||||||
|
playlist/playlistsaveoptionsdialog.cpp
|
||||||
playlist/playlistsequence.cpp
|
playlist/playlistsequence.cpp
|
||||||
playlist/playlisttabbar.cpp
|
playlist/playlisttabbar.cpp
|
||||||
playlist/playlistundocommands.cpp
|
playlist/playlistundocommands.cpp
|
||||||
@ -269,27 +273,28 @@ set(SOURCES
|
|||||||
playlistparsers/xmlparser.cpp
|
playlistparsers/xmlparser.cpp
|
||||||
playlistparsers/xspfparser.cpp
|
playlistparsers/xspfparser.cpp
|
||||||
|
|
||||||
podcasts/addpodcastbyurl.cpp
|
internet/podcasts/addpodcastbyurl.cpp
|
||||||
podcasts/addpodcastdialog.cpp
|
internet/podcasts/addpodcastdialog.cpp
|
||||||
podcasts/addpodcastpage.cpp
|
internet/podcasts/addpodcastpage.cpp
|
||||||
podcasts/fixedopmlpage.cpp
|
internet/podcasts/fixedopmlpage.cpp
|
||||||
podcasts/gpoddersearchpage.cpp
|
internet/podcasts/gpoddersearchpage.cpp
|
||||||
podcasts/gpoddersync.cpp
|
internet/podcasts/gpoddersync.cpp
|
||||||
podcasts/gpoddertoptagsmodel.cpp
|
internet/podcasts/gpoddertoptagsmodel.cpp
|
||||||
podcasts/gpoddertoptagspage.cpp
|
internet/podcasts/gpoddertoptagspage.cpp
|
||||||
podcasts/itunessearchpage.cpp
|
internet/podcasts/itunessearchpage.cpp
|
||||||
podcasts/podcast.cpp
|
internet/podcasts/podcast.cpp
|
||||||
podcasts/podcastbackend.cpp
|
internet/podcasts/podcastbackend.cpp
|
||||||
podcasts/podcastdiscoverymodel.cpp
|
internet/podcasts/podcastdiscoverymodel.cpp
|
||||||
podcasts/podcastdownloader.cpp
|
internet/podcasts/podcastdeleter.cpp
|
||||||
podcasts/podcastepisode.cpp
|
internet/podcasts/podcastdownloader.cpp
|
||||||
podcasts/podcastinfowidget.cpp
|
internet/podcasts/podcastepisode.cpp
|
||||||
podcasts/podcastservice.cpp
|
internet/podcasts/podcastinfowidget.cpp
|
||||||
podcasts/podcastservicemodel.cpp
|
internet/podcasts/podcastservice.cpp
|
||||||
podcasts/podcastsettingspage.cpp
|
internet/podcasts/podcastservicemodel.cpp
|
||||||
podcasts/podcastparser.cpp
|
internet/podcasts/podcastsettingspage.cpp
|
||||||
podcasts/podcastupdater.cpp
|
internet/podcasts/podcastparser.cpp
|
||||||
podcasts/podcasturlloader.cpp
|
internet/podcasts/podcastupdater.cpp
|
||||||
|
internet/podcasts/podcasturlloader.cpp
|
||||||
|
|
||||||
smartplaylists/generator.cpp
|
smartplaylists/generator.cpp
|
||||||
smartplaylists/generatorinserter.cpp
|
smartplaylists/generatorinserter.cpp
|
||||||
@ -410,6 +415,7 @@ set(HEADERS
|
|||||||
analyzers/blockanalyzer.h
|
analyzers/blockanalyzer.h
|
||||||
analyzers/boomanalyzer.h
|
analyzers/boomanalyzer.h
|
||||||
analyzers/nyancatanalyzer.h
|
analyzers/nyancatanalyzer.h
|
||||||
|
analyzers/rainbowdashanalyzer.h
|
||||||
analyzers/sonogram.h
|
analyzers/sonogram.h
|
||||||
analyzers/turbine.h
|
analyzers/turbine.h
|
||||||
|
|
||||||
@ -473,44 +479,45 @@ set(HEADERS
|
|||||||
globalsearch/spotifysearchprovider.h
|
globalsearch/spotifysearchprovider.h
|
||||||
globalsearch/suggestionwidget.h
|
globalsearch/suggestionwidget.h
|
||||||
|
|
||||||
internet/cloudfileservice.h
|
internet/core/cloudfileservice.h
|
||||||
internet/digitallyimportedclient.h
|
internet/digitally/digitallyimportedclient.h
|
||||||
internet/digitallyimportedservicebase.h
|
internet/digitally/digitallyimportedservicebase.h
|
||||||
internet/digitallyimportedsettingspage.h
|
internet/digitally/digitallyimportedsettingspage.h
|
||||||
internet/geolocator.h
|
internet/core/geolocator.h
|
||||||
internet/groovesharkservice.h
|
internet/grooveshark/groovesharkservice.h
|
||||||
internet/groovesharksettingspage.h
|
internet/grooveshark/groovesharksettingspage.h
|
||||||
internet/groovesharkurlhandler.h
|
internet/grooveshark/groovesharkurlhandler.h
|
||||||
internet/icecastbackend.h
|
internet/icecast/icecastbackend.h
|
||||||
internet/icecastfilterwidget.h
|
internet/icecast/icecastfilterwidget.h
|
||||||
internet/icecastmodel.h
|
internet/icecast/icecastmodel.h
|
||||||
internet/icecastservice.h
|
internet/icecast/icecastservice.h
|
||||||
internet/internetmimedata.h
|
internet/core/internetmimedata.h
|
||||||
internet/internetmodel.h
|
internet/core/internetmodel.h
|
||||||
internet/internetservice.h
|
internet/core/internetservice.h
|
||||||
internet/internetsongmimedata.h
|
internet/core/internetshowsettingspage.h
|
||||||
internet/internetview.h
|
internet/core/internetsongmimedata.h
|
||||||
internet/internetviewcontainer.h
|
internet/core/internetview.h
|
||||||
internet/jamendodynamicplaylist.h
|
internet/core/internetviewcontainer.h
|
||||||
internet/jamendoservice.h
|
internet/jamendo/jamendodynamicplaylist.h
|
||||||
internet/localredirectserver.h
|
internet/jamendo/jamendoservice.h
|
||||||
internet/magnatunedownloaddialog.h
|
internet/core/localredirectserver.h
|
||||||
internet/magnatuneservice.h
|
internet/magnatune/magnatunedownloaddialog.h
|
||||||
internet/magnatunesettingspage.h
|
internet/magnatune/magnatuneservice.h
|
||||||
internet/oauthenticator.h
|
internet/magnatune/magnatunesettingspage.h
|
||||||
internet/savedradio.h
|
internet/core/oauthenticator.h
|
||||||
internet/scrobbler.h
|
internet/internetradio/savedradio.h
|
||||||
internet/searchboxwidget.h
|
internet/core/scrobbler.h
|
||||||
internet/somafmservice.h
|
internet/core/searchboxwidget.h
|
||||||
internet/somafmurlhandler.h
|
internet/somafm/somafmservice.h
|
||||||
internet/soundcloudservice.h
|
internet/somafm/somafmurlhandler.h
|
||||||
internet/soundcloudsettingspage.h
|
internet/soundcloud/soundcloudservice.h
|
||||||
internet/spotifyserver.h
|
internet/soundcloud/soundcloudsettingspage.h
|
||||||
internet/spotifyservice.h
|
internet/spotify/spotifyserver.h
|
||||||
internet/spotifysettingspage.h
|
internet/spotify/spotifyservice.h
|
||||||
internet/subsonicservice.h
|
internet/spotify/spotifysettingspage.h
|
||||||
internet/subsonicsettingspage.h
|
internet/subsonic/subsonicservice.h
|
||||||
internet/subsonicurlhandler.h
|
internet/subsonic/subsonicsettingspage.h
|
||||||
|
internet/subsonic/subsonicurlhandler.h
|
||||||
|
|
||||||
library/groupbydialog.h
|
library/groupbydialog.h
|
||||||
library/library.h
|
library/library.h
|
||||||
@ -528,11 +535,12 @@ set(HEADERS
|
|||||||
musicbrainz/tagfetcher.h
|
musicbrainz/tagfetcher.h
|
||||||
|
|
||||||
networkremote/clementinewebpage.h
|
networkremote/clementinewebpage.h
|
||||||
networkremote/networkremotehelper.h
|
|
||||||
networkremote/networkremote.h
|
|
||||||
networkremote/incomingdataparser.h
|
networkremote/incomingdataparser.h
|
||||||
|
networkremote/networkremote.h
|
||||||
|
networkremote/networkremotehelper.h
|
||||||
networkremote/outgoingdatacreator.h
|
networkremote/outgoingdatacreator.h
|
||||||
networkremote/remoteclient.h
|
networkremote/remoteclient.h
|
||||||
|
networkremote/songsender.h
|
||||||
networkremote/tcpremoteclient.h
|
networkremote/tcpremoteclient.h
|
||||||
networkremote/webremoteclient.h
|
networkremote/webremoteclient.h
|
||||||
|
|
||||||
@ -548,6 +556,7 @@ set(HEADERS
|
|||||||
playlist/playlistlistmodel.h
|
playlist/playlistlistmodel.h
|
||||||
playlist/playlistlistview.h
|
playlist/playlistlistview.h
|
||||||
playlist/playlistmanager.h
|
playlist/playlistmanager.h
|
||||||
|
playlist/playlistsaveoptionsdialog.h
|
||||||
playlist/playlistsequence.h
|
playlist/playlistsequence.h
|
||||||
playlist/playlisttabbar.h
|
playlist/playlisttabbar.h
|
||||||
playlist/playlistview.h
|
playlist/playlistview.h
|
||||||
@ -565,24 +574,25 @@ set(HEADERS
|
|||||||
playlistparsers/plsparser.h
|
playlistparsers/plsparser.h
|
||||||
playlistparsers/xspfparser.h
|
playlistparsers/xspfparser.h
|
||||||
|
|
||||||
podcasts/addpodcastbyurl.h
|
internet/podcasts/addpodcastbyurl.h
|
||||||
podcasts/addpodcastdialog.h
|
internet/podcasts/addpodcastdialog.h
|
||||||
podcasts/addpodcastpage.h
|
internet/podcasts/addpodcastpage.h
|
||||||
podcasts/fixedopmlpage.h
|
internet/podcasts/fixedopmlpage.h
|
||||||
podcasts/gpoddersearchpage.h
|
internet/podcasts/gpoddersearchpage.h
|
||||||
podcasts/gpoddersync.h
|
internet/podcasts/gpoddersync.h
|
||||||
podcasts/gpoddertoptagsmodel.h
|
internet/podcasts/gpoddertoptagsmodel.h
|
||||||
podcasts/gpoddertoptagspage.h
|
internet/podcasts/gpoddertoptagspage.h
|
||||||
podcasts/itunessearchpage.h
|
internet/podcasts/itunessearchpage.h
|
||||||
podcasts/podcastbackend.h
|
internet/podcasts/podcastbackend.h
|
||||||
podcasts/podcastdiscoverymodel.h
|
internet/podcasts/podcastdiscoverymodel.h
|
||||||
podcasts/podcastdownloader.h
|
internet/podcasts/podcastdeleter.h
|
||||||
podcasts/podcastinfowidget.h
|
internet/podcasts/podcastdownloader.h
|
||||||
podcasts/podcastservice.h
|
internet/podcasts/podcastinfowidget.h
|
||||||
podcasts/podcastservicemodel.h
|
internet/podcasts/podcastservice.h
|
||||||
podcasts/podcastsettingspage.h
|
internet/podcasts/podcastservicemodel.h
|
||||||
podcasts/podcastupdater.h
|
internet/podcasts/podcastsettingspage.h
|
||||||
podcasts/podcasturlloader.h
|
internet/podcasts/podcastupdater.h
|
||||||
|
internet/podcasts/podcasturlloader.h
|
||||||
|
|
||||||
smartplaylists/generator.h
|
smartplaylists/generator.h
|
||||||
smartplaylists/generatorinserter.h
|
smartplaylists/generatorinserter.h
|
||||||
@ -693,16 +703,17 @@ set(UI
|
|||||||
globalsearch/searchproviderstatuswidget.ui
|
globalsearch/searchproviderstatuswidget.ui
|
||||||
globalsearch/suggestionwidget.ui
|
globalsearch/suggestionwidget.ui
|
||||||
|
|
||||||
internet/digitallyimportedsettingspage.ui
|
internet/digitally/digitallyimportedsettingspage.ui
|
||||||
internet/groovesharksettingspage.ui
|
internet/grooveshark/groovesharksettingspage.ui
|
||||||
internet/icecastfilterwidget.ui
|
internet/icecast/icecastfilterwidget.ui
|
||||||
internet/internetviewcontainer.ui
|
internet/core/internetshowsettingspage.ui
|
||||||
internet/magnatunedownloaddialog.ui
|
internet/core/internetviewcontainer.ui
|
||||||
internet/magnatunesettingspage.ui
|
internet/magnatune/magnatunedownloaddialog.ui
|
||||||
internet/searchboxwidget.ui
|
internet/magnatune/magnatunesettingspage.ui
|
||||||
internet/soundcloudsettingspage.ui
|
internet/core/searchboxwidget.ui
|
||||||
internet/spotifysettingspage.ui
|
internet/soundcloud/soundcloudsettingspage.ui
|
||||||
internet/subsonicsettingspage.ui
|
internet/spotify/spotifysettingspage.ui
|
||||||
|
internet/subsonic/subsonicsettingspage.ui
|
||||||
|
|
||||||
library/groupbydialog.ui
|
library/groupbydialog.ui
|
||||||
library/libraryfilterwidget.ui
|
library/libraryfilterwidget.ui
|
||||||
@ -711,16 +722,17 @@ set(UI
|
|||||||
|
|
||||||
playlist/dynamicplaylistcontrols.ui
|
playlist/dynamicplaylistcontrols.ui
|
||||||
playlist/playlistcontainer.ui
|
playlist/playlistcontainer.ui
|
||||||
|
playlist/playlistsaveoptionsdialog.ui
|
||||||
playlist/playlistlistcontainer.ui
|
playlist/playlistlistcontainer.ui
|
||||||
playlist/playlistsequence.ui
|
playlist/playlistsequence.ui
|
||||||
playlist/queuemanager.ui
|
playlist/queuemanager.ui
|
||||||
|
|
||||||
podcasts/addpodcastbyurl.ui
|
internet/podcasts/addpodcastbyurl.ui
|
||||||
podcasts/addpodcastdialog.ui
|
internet/podcasts/addpodcastdialog.ui
|
||||||
podcasts/gpoddersearchpage.ui
|
internet/podcasts/gpoddersearchpage.ui
|
||||||
podcasts/itunessearchpage.ui
|
internet/podcasts/itunessearchpage.ui
|
||||||
podcasts/podcastinfowidget.ui
|
internet/podcasts/podcastinfowidget.ui
|
||||||
podcasts/podcastsettingspage.ui
|
internet/podcasts/podcastsettingspage.ui
|
||||||
|
|
||||||
smartplaylists/querysearchpage.ui
|
smartplaylists/querysearchpage.ui
|
||||||
smartplaylists/querysortpage.ui
|
smartplaylists/querysortpage.ui
|
||||||
@ -826,32 +838,32 @@ optional_source(ENABLE_VISUALISATIONS
|
|||||||
optional_source(HAVE_LIBLASTFM
|
optional_source(HAVE_LIBLASTFM
|
||||||
SOURCES
|
SOURCES
|
||||||
covers/lastfmcoverprovider.cpp
|
covers/lastfmcoverprovider.cpp
|
||||||
internet/fixlastfm.cpp
|
internet/lastfm/fixlastfm.cpp
|
||||||
internet/lastfmcompat.cpp
|
internet/lastfm/lastfmcompat.cpp
|
||||||
internet/lastfmservice.cpp
|
internet/lastfm/lastfmservice.cpp
|
||||||
internet/lastfmsettingspage.cpp
|
internet/lastfm/lastfmsettingspage.cpp
|
||||||
songinfo/echonestsimilarartists.cpp
|
songinfo/echonestsimilarartists.cpp
|
||||||
songinfo/echonesttags.cpp
|
songinfo/echonesttags.cpp
|
||||||
songinfo/lastfmtrackinfoprovider.cpp
|
songinfo/lastfmtrackinfoprovider.cpp
|
||||||
songinfo/tagwidget.cpp
|
songinfo/tagwidget.cpp
|
||||||
HEADERS
|
HEADERS
|
||||||
covers/lastfmcoverprovider.h
|
covers/lastfmcoverprovider.h
|
||||||
internet/lastfmservice.h
|
internet/lastfm/lastfmservice.h
|
||||||
internet/lastfmsettingspage.h
|
internet/lastfm/lastfmsettingspage.h
|
||||||
songinfo/echonestsimilarartists.h
|
songinfo/echonestsimilarartists.h
|
||||||
songinfo/echonesttags.h
|
songinfo/echonesttags.h
|
||||||
songinfo/lastfmtrackinfoprovider.h
|
songinfo/lastfmtrackinfoprovider.h
|
||||||
songinfo/tagwidget.h
|
songinfo/tagwidget.h
|
||||||
UI
|
UI
|
||||||
internet/lastfmsettingspage.ui
|
internet/lastfm/lastfmsettingspage.ui
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
optional_source(HAVE_SPOTIFY_DOWNLOADER
|
optional_source(HAVE_SPOTIFY_DOWNLOADER
|
||||||
SOURCES
|
SOURCES
|
||||||
internet/spotifyblobdownloader.cpp
|
internet/spotify/spotifyblobdownloader.cpp
|
||||||
HEADERS
|
HEADERS
|
||||||
internet/spotifyblobdownloader.h
|
internet/spotify/spotifyblobdownloader.h
|
||||||
INCLUDE_DIRECTORIES
|
INCLUDE_DIRECTORIES
|
||||||
${QCA_INCLUDE_DIRS}
|
${QCA_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
@ -896,11 +908,6 @@ optional_source(LINUX SOURCES widgets/osd_x11.cpp)
|
|||||||
if(HAVE_DBUS)
|
if(HAVE_DBUS)
|
||||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/dbus)
|
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/dbus)
|
||||||
|
|
||||||
# Hack to get it to generate interfaces without namespaces - required
|
|
||||||
# because otherwise org::freedesktop::UDisks and
|
|
||||||
# org::freedesktop::UDisks::Device conflict.
|
|
||||||
list(APPEND QT_DBUSXML2CPP_EXECUTABLE -N)
|
|
||||||
|
|
||||||
# MPRIS DBUS interfaces
|
# MPRIS DBUS interfaces
|
||||||
qt4_add_dbus_adaptor(SOURCES
|
qt4_add_dbus_adaptor(SOURCES
|
||||||
dbus/org.freedesktop.MediaPlayer.player.xml
|
dbus/org.freedesktop.MediaPlayer.player.xml
|
||||||
@ -968,6 +975,10 @@ if(HAVE_DBUS)
|
|||||||
|
|
||||||
# DeviceKit DBUS interfaces
|
# DeviceKit DBUS interfaces
|
||||||
if(HAVE_DEVICEKIT)
|
if(HAVE_DEVICEKIT)
|
||||||
|
set_source_files_properties(dbus/org.freedesktop.UDisks.xml
|
||||||
|
PROPERTIES NO_NAMESPACE dbus/udisks)
|
||||||
|
set_source_files_properties(dbus/org.freedesktop.UDisks.Device.xml
|
||||||
|
PROPERTIES NO_NAMESPACE dbus/udisksdevice)
|
||||||
qt4_add_dbus_interface(SOURCES
|
qt4_add_dbus_interface(SOURCES
|
||||||
dbus/org.freedesktop.UDisks.xml
|
dbus/org.freedesktop.UDisks.xml
|
||||||
dbus/udisks)
|
dbus/udisks)
|
||||||
@ -1036,10 +1047,12 @@ optional_source(HAVE_AUDIOCD
|
|||||||
SOURCES
|
SOURCES
|
||||||
devices/cddadevice.cpp
|
devices/cddadevice.cpp
|
||||||
devices/cddalister.cpp
|
devices/cddalister.cpp
|
||||||
|
devices/cddasongloader.cpp
|
||||||
ui/ripcd.cpp
|
ui/ripcd.cpp
|
||||||
HEADERS
|
HEADERS
|
||||||
devices/cddadevice.h
|
devices/cddadevice.h
|
||||||
devices/cddalister.h
|
devices/cddalister.h
|
||||||
|
devices/cddasongloader.h
|
||||||
ui/ripcd.h
|
ui/ripcd.h
|
||||||
UI
|
UI
|
||||||
ui/ripcd.ui
|
ui/ripcd.ui
|
||||||
@ -1060,6 +1073,7 @@ optional_source(HAVE_LIBMTP
|
|||||||
# Moodbar support
|
# Moodbar support
|
||||||
optional_source(HAVE_MOODBAR
|
optional_source(HAVE_MOODBAR
|
||||||
SOURCES
|
SOURCES
|
||||||
|
moodbar/moodbarbuilder.cpp
|
||||||
moodbar/moodbarcontroller.cpp
|
moodbar/moodbarcontroller.cpp
|
||||||
moodbar/moodbaritemdelegate.cpp
|
moodbar/moodbaritemdelegate.cpp
|
||||||
moodbar/moodbarloader.cpp
|
moodbar/moodbarloader.cpp
|
||||||
@ -1077,61 +1091,61 @@ optional_source(HAVE_MOODBAR
|
|||||||
# Google Drive support
|
# Google Drive support
|
||||||
optional_source(HAVE_GOOGLE_DRIVE
|
optional_source(HAVE_GOOGLE_DRIVE
|
||||||
SOURCES
|
SOURCES
|
||||||
internet/googledriveclient.cpp
|
internet/googledrive/googledriveclient.cpp
|
||||||
internet/googledriveservice.cpp
|
internet/googledrive/googledriveservice.cpp
|
||||||
internet/googledrivesettingspage.cpp
|
internet/googledrive/googledrivesettingspage.cpp
|
||||||
internet/googledriveurlhandler.cpp
|
internet/googledrive/googledriveurlhandler.cpp
|
||||||
HEADERS
|
HEADERS
|
||||||
internet/googledriveclient.h
|
internet/googledrive/googledriveclient.h
|
||||||
internet/googledriveservice.h
|
internet/googledrive/googledriveservice.h
|
||||||
internet/googledrivesettingspage.h
|
internet/googledrive/googledrivesettingspage.h
|
||||||
internet/googledriveurlhandler.h
|
internet/googledrive/googledriveurlhandler.h
|
||||||
UI
|
UI
|
||||||
internet/googledrivesettingspage.ui
|
internet/googledrive/googledrivesettingspage.ui
|
||||||
)
|
)
|
||||||
|
|
||||||
# Dropbox support
|
# Dropbox support
|
||||||
optional_source(HAVE_DROPBOX
|
optional_source(HAVE_DROPBOX
|
||||||
SOURCES
|
SOURCES
|
||||||
internet/dropboxauthenticator.cpp
|
internet/dropbox/dropboxauthenticator.cpp
|
||||||
internet/dropboxservice.cpp
|
internet/dropbox/dropboxservice.cpp
|
||||||
internet/dropboxsettingspage.cpp
|
internet/dropbox/dropboxsettingspage.cpp
|
||||||
internet/dropboxurlhandler.cpp
|
internet/dropbox/dropboxurlhandler.cpp
|
||||||
HEADERS
|
HEADERS
|
||||||
internet/dropboxauthenticator.h
|
internet/dropbox/dropboxauthenticator.h
|
||||||
internet/dropboxservice.h
|
internet/dropbox/dropboxservice.h
|
||||||
internet/dropboxsettingspage.h
|
internet/dropbox/dropboxsettingspage.h
|
||||||
internet/dropboxurlhandler.h
|
internet/dropbox/dropboxurlhandler.h
|
||||||
UI
|
UI
|
||||||
internet/dropboxsettingspage.ui
|
internet/dropbox/dropboxsettingspage.ui
|
||||||
)
|
)
|
||||||
|
|
||||||
# Skydrive support
|
# Skydrive support
|
||||||
optional_source(HAVE_SKYDRIVE
|
optional_source(HAVE_SKYDRIVE
|
||||||
SOURCES
|
SOURCES
|
||||||
internet/skydriveservice.cpp
|
internet/skydrive/skydriveservice.cpp
|
||||||
internet/skydrivesettingspage.cpp
|
internet/skydrive/skydrivesettingspage.cpp
|
||||||
internet/skydriveurlhandler.cpp
|
internet/skydrive/skydriveurlhandler.cpp
|
||||||
HEADERS
|
HEADERS
|
||||||
internet/skydriveservice.h
|
internet/skydrive/skydriveservice.h
|
||||||
internet/skydrivesettingspage.h
|
internet/skydrive/skydrivesettingspage.h
|
||||||
internet/skydriveurlhandler.h
|
internet/skydrive/skydriveurlhandler.h
|
||||||
UI
|
UI
|
||||||
internet/skydrivesettingspage.ui
|
internet/skydrive/skydrivesettingspage.ui
|
||||||
)
|
)
|
||||||
|
|
||||||
# Box support
|
# Box support
|
||||||
optional_source(HAVE_BOX
|
optional_source(HAVE_BOX
|
||||||
SOURCES
|
SOURCES
|
||||||
internet/boxservice.cpp
|
internet/box/boxservice.cpp
|
||||||
internet/boxsettingspage.cpp
|
internet/box/boxsettingspage.cpp
|
||||||
internet/boxurlhandler.cpp
|
internet/box/boxurlhandler.cpp
|
||||||
HEADERS
|
HEADERS
|
||||||
internet/boxservice.h
|
internet/box/boxservice.h
|
||||||
internet/boxsettingspage.h
|
internet/box/boxsettingspage.h
|
||||||
internet/boxurlhandler.h
|
internet/box/boxurlhandler.h
|
||||||
UI
|
UI
|
||||||
internet/boxsettingspage.ui
|
internet/box/boxsettingspage.ui
|
||||||
)
|
)
|
||||||
|
|
||||||
# Vk.com support
|
# Vk.com support
|
||||||
@ -1140,25 +1154,42 @@ optional_source(HAVE_VK
|
|||||||
${VREEN_INCLUDE_DIRS}
|
${VREEN_INCLUDE_DIRS}
|
||||||
SOURCES
|
SOURCES
|
||||||
globalsearch/vksearchprovider.cpp
|
globalsearch/vksearchprovider.cpp
|
||||||
internet/vkconnection.cpp
|
internet/vk/vkconnection.cpp
|
||||||
internet/vkmusiccache.cpp
|
internet/vk/vkmusiccache.cpp
|
||||||
internet/vksearchdialog.cpp
|
internet/vk/vksearchdialog.cpp
|
||||||
internet/vkservice.cpp
|
internet/vk/vkservice.cpp
|
||||||
internet/vksettingspage.cpp
|
internet/vk/vksettingspage.cpp
|
||||||
internet/vkurlhandler.cpp
|
internet/vk/vkurlhandler.cpp
|
||||||
HEADERS
|
HEADERS
|
||||||
globalsearch/vksearchprovider.h
|
globalsearch/vksearchprovider.h
|
||||||
internet/vkconnection.h
|
internet/vk/vkconnection.h
|
||||||
internet/vkmusiccache.h
|
internet/vk/vkmusiccache.h
|
||||||
internet/vksearchdialog.h
|
internet/vk/vksearchdialog.h
|
||||||
internet/vkservice.h
|
internet/vk/vkservice.h
|
||||||
internet/vksettingspage.h
|
internet/vk/vksettingspage.h
|
||||||
internet/vkurlhandler.h
|
internet/vk/vkurlhandler.h
|
||||||
UI
|
UI
|
||||||
internet/vksearchdialog.ui
|
internet/vk/vksearchdialog.ui
|
||||||
internet/vksettingspage.ui
|
internet/vk/vksettingspage.ui
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Seafile support
|
||||||
|
optional_source(HAVE_SEAFILE
|
||||||
|
SOURCES
|
||||||
|
internet/seafile/seafileservice.cpp
|
||||||
|
internet/seafile/seafilesettingspage.cpp
|
||||||
|
internet/seafile/seafileurlhandler.cpp
|
||||||
|
internet/seafile/seafiletree.cpp
|
||||||
|
HEADERS
|
||||||
|
internet/seafile/seafileservice.h
|
||||||
|
internet/seafile/seafilesettingspage.h
|
||||||
|
internet/seafile/seafileurlhandler.h
|
||||||
|
internet/seafile/seafiletree.h
|
||||||
|
UI
|
||||||
|
internet/seafile/seafilesettingspage.ui
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Pulse audio integration
|
# Pulse audio integration
|
||||||
optional_source(HAVE_LIBPULSE
|
optional_source(HAVE_LIBPULSE
|
||||||
INCLUDE_DIRECTORIES
|
INCLUDE_DIRECTORIES
|
||||||
@ -1256,7 +1287,6 @@ endif(HAVE_GIO)
|
|||||||
|
|
||||||
if(HAVE_AUDIOCD)
|
if(HAVE_AUDIOCD)
|
||||||
target_link_libraries(clementine_lib ${CDIO_LIBRARIES})
|
target_link_libraries(clementine_lib ${CDIO_LIBRARIES})
|
||||||
target_link_libraries(clementine_lib ${GSTREAMER_CDDA_LIBRARIES})
|
|
||||||
endif(HAVE_AUDIOCD)
|
endif(HAVE_AUDIOCD)
|
||||||
|
|
||||||
if(HAVE_MOODBAR)
|
if(HAVE_MOODBAR)
|
||||||
@ -1390,6 +1420,8 @@ if (APPLE)
|
|||||||
DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Resources")
|
DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Resources")
|
||||||
install(FILES ../dist/sparkle_pub.pem
|
install(FILES ../dist/sparkle_pub.pem
|
||||||
DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Resources")
|
DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Resources")
|
||||||
|
install(FILES ../dist/cacert.pem
|
||||||
|
DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Resources")
|
||||||
|
|
||||||
install(DIRECTORY "${QT_QTGUI_LIBRARY_RELEASE}/Versions/Current/Resources/"
|
install(DIRECTORY "${QT_QTGUI_LIBRARY_RELEASE}/Versions/Current/Resources/"
|
||||||
DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Resources")
|
DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Resources")
|
||||||
@ -1399,20 +1431,22 @@ if (APPLE)
|
|||||||
DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Frameworks/Sparkle.framework")
|
DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Frameworks/Sparkle.framework")
|
||||||
endif (HAVE_SPARKLE)
|
endif (HAVE_SPARKLE)
|
||||||
|
|
||||||
install(FILES "${QT_QTCORE_LIBRARY_RELEASE}/Contents/Info.plist"
|
foreach (plist_destination Versions/4/Resources Resources)
|
||||||
DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Frameworks/QtCore.framework/Contents")
|
install(FILES "${QT_QTCORE_LIBRARY_RELEASE}/Contents/Info.plist"
|
||||||
install(FILES "${QT_QTGUI_LIBRARY_RELEASE}/Contents/Info.plist"
|
DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Frameworks/QtCore.framework/${plist_destination}")
|
||||||
DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Frameworks/QtGui.framework/Contents")
|
install(FILES "${QT_QTGUI_LIBRARY_RELEASE}/Contents/Info.plist"
|
||||||
install(FILES "${QT_QTNETWORK_LIBRARY_RELEASE}/Contents/Info.plist"
|
DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Frameworks/QtGui.framework/${plist_destination}")
|
||||||
DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Frameworks/QtNetwork.framework/Contents")
|
install(FILES "${QT_QTNETWORK_LIBRARY_RELEASE}/Contents/Info.plist"
|
||||||
install(FILES "${QT_QTOPENGL_LIBRARY_RELEASE}/Contents/Info.plist"
|
DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Frameworks/QtNetwork.framework/${plist_destination}")
|
||||||
DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Frameworks/QtOpenGL.framework/Contents")
|
install(FILES "${QT_QTOPENGL_LIBRARY_RELEASE}/Contents/Info.plist"
|
||||||
install(FILES "${QT_QTSQL_LIBRARY_RELEASE}/Contents/Info.plist"
|
DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Frameworks/QtOpenGL.framework/${plist_destination}")
|
||||||
DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Frameworks/QtSql.framework/Contents")
|
install(FILES "${QT_QTSQL_LIBRARY_RELEASE}/Contents/Info.plist"
|
||||||
install(FILES "${QT_QTSVG_LIBRARY_RELEASE}/Contents/Info.plist"
|
DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Frameworks/QtSql.framework/${plist_destination}")
|
||||||
DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Frameworks/QtSvg.framework/Contents")
|
install(FILES "${QT_QTSVG_LIBRARY_RELEASE}/Contents/Info.plist"
|
||||||
install(FILES "${QT_QTXML_LIBRARY_RELEASE}/Contents/Info.plist"
|
DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Frameworks/QtSvg.framework/${plist_destination}")
|
||||||
DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Frameworks/QtXml.framework/Contents")
|
install(FILES "${QT_QTXML_LIBRARY_RELEASE}/Contents/Info.plist"
|
||||||
|
DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Frameworks/QtXml.framework/${plist_destination}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
if (HAVE_BREAKPAD)
|
if (HAVE_BREAKPAD)
|
||||||
install(DIRECTORY
|
install(DIRECTORY
|
||||||
|
@ -1,3 +1,21 @@
|
|||||||
|
/* This file is part of Clementine.
|
||||||
|
Copyright 2010, 2014, John Maguire <john.maguire@gmail.com>
|
||||||
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
|
|
||||||
|
Clementine 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.
|
||||||
|
|
||||||
|
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
#include "analyzer.h"
|
#include "analyzer.h"
|
||||||
|
|
||||||
#include "engines/enginebase.h"
|
#include "engines/enginebase.h"
|
||||||
|
76
src/analyzers/analyzerbase.cpp
Executable file → Normal file
@ -1,25 +1,33 @@
|
|||||||
/***************************************************************************
|
/* This file is part of Clementine.
|
||||||
viswidget.cpp - description
|
Copyright 2003, Max Howell <max.howell@methylblue.com>
|
||||||
-------------------
|
Copyright 2009, 2011-2012, David Sansome <me@davidsansome.com>
|
||||||
begin : Die Jan 7 2003
|
Copyright 2010, 2012, 2014, John Maguire <john.maguire@gmail.com>
|
||||||
copyright : (C) 2003 by Max Howell
|
Copyright 2014, Mark Furneaux <mark@romaco.ca>
|
||||||
email : markey@web.de
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
* *
|
it under the terms of the GNU General Public License as published by
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
* it under the terms of the GNU General Public License as published by *
|
(at your option) any later version.
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Original Author: Max Howell <max.howell@methylblue.com> 2003
|
||||||
|
*/
|
||||||
|
|
||||||
#include "analyzerbase.h"
|
#include "analyzerbase.h"
|
||||||
|
|
||||||
#include <cmath> //interpolate()
|
#include <cmath>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
#include <QEvent> //event()
|
#include <QEvent>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QPaintEvent>
|
#include <QPaintEvent>
|
||||||
#include <QtDebug>
|
#include <QtDebug>
|
||||||
@ -34,10 +42,10 @@
|
|||||||
// 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(David Sansome): make an INSTRUCTIONS file
|
||||||
// can't mod scope in analyze you have to use transform
|
// can't mod scope in analyze you have to use transform
|
||||||
|
|
||||||
// TODO for 2D use setErasePixmap Qt function insetead of m_background
|
// TODO(John Maguire): for 2D use setErasePixmap Qt function insetead of m_background
|
||||||
|
|
||||||
// make the linker happy only for gcc < 4.0
|
// make the linker happy only for gcc < 4.0
|
||||||
#if !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 0)) && \
|
#if !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 0)) && \
|
||||||
@ -60,8 +68,7 @@ void Analyzer::Base::hideEvent(QHideEvent*) { m_timer.stop(); }
|
|||||||
|
|
||||||
void Analyzer::Base::showEvent(QShowEvent*) { m_timer.start(timeout(), this); }
|
void Analyzer::Base::showEvent(QShowEvent*) { m_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
|
||||||
|
|
||||||
@ -91,9 +98,9 @@ void Analyzer::Base::paintEvent(QPaintEvent* e) {
|
|||||||
|
|
||||||
// convert to mono here - our built in analyzers need mono, but the
|
// convert to mono here - our built in analyzers need mono, but the
|
||||||
// engines provide interleaved pcm
|
// engines provide interleaved pcm
|
||||||
for (uint x = 0; (int)x < m_fht->size(); ++x) {
|
for (uint x = 0; static_cast<int>(x) < m_fht->size(); ++x) {
|
||||||
m_lastScope[x] =
|
m_lastScope[x] =
|
||||||
double(thescope[i] + thescope[i + 1]) / (2 * (1 << 15));
|
static_cast<double>(thescope[i] + thescope[i + 1]) / (2 * (1 << 15));
|
||||||
i += 2;
|
i += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,22 +157,21 @@ int Analyzer::Base::resizeForBands(int bands) {
|
|||||||
return m_fht->size() / 2;
|
return m_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
|
||||||
|
|
||||||
if (t > 999) t = 1; // 0 = wasted calculations
|
if (t > 999) t = 1; // 0 = wasted calculations
|
||||||
if (t < 201) {
|
if (t < 201) {
|
||||||
Scope s(32);
|
Scope s(32);
|
||||||
|
|
||||||
const double dt = double(t) / 200;
|
const double dt = static_cast<double>(t) / 200;
|
||||||
for (uint i = 0; i < s.size(); ++i)
|
for (uint i = 0; i < s.size(); ++i)
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,20 +179,19 @@ void Analyzer::Base::polishEvent() {
|
|||||||
init(); // virtual
|
init(); // virtual
|
||||||
}
|
}
|
||||||
|
|
||||||
void Analyzer::interpolate(const Scope& inVec, Scope& outVec) // static
|
void Analyzer::interpolate(const Scope& inVec, Scope& outVec) {
|
||||||
{
|
|
||||||
double pos = 0.0;
|
double pos = 0.0;
|
||||||
const double step = (double)inVec.size() / outVec.size();
|
const double step = static_cast<double>(inVec.size()) / outVec.size();
|
||||||
|
|
||||||
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 = static_cast<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;
|
||||||
|
|
||||||
@ -194,8 +199,7 @@ void Analyzer::interpolate(const Scope& inVec, Scope& outVec) // static
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Analyzer::initSin(Scope& v, const uint size) // static
|
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;
|
||||||
|
|
||||||
|
54
src/analyzers/analyzerbase.h
Executable file → Normal file
@ -1,27 +1,49 @@
|
|||||||
// Maintainer: Max Howell <max.howell@methylblue.com>, (C) 2004
|
/* This file is part of Clementine.
|
||||||
// Copyright: See COPYING file that comes with this distribution
|
Copyright 2004, Max Howell <max.howell@methylblue.com>
|
||||||
|
Copyright 2009-2010, David Sansome <davidsansome@gmail.com>
|
||||||
|
Copyright 2010, 2014, John Maguire <john.maguire@gmail.com>
|
||||||
|
Copyright 2011, Arnaud Bienner <arnaud.bienner@gmail.com>
|
||||||
|
Copyright 2014, Mark Furneaux <mark@romaco.ca>
|
||||||
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
|
|
||||||
#ifndef ANALYZERBASE_H
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
#define ANALYZERBASE_H
|
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.
|
||||||
|
|
||||||
|
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Original Author: Max Howell <max.howell@methylblue.com> 2004
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ANALYZERS_ANALYZERBASE_H_
|
||||||
|
#define ANALYZERS_ANALYZERBASE_H_
|
||||||
|
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "core/fht.h" //stack allocated and convenience
|
#include "fht.h"
|
||||||
#include "engines/engine_fwd.h"
|
#include "engines/engine_fwd.h"
|
||||||
#include <QPixmap> //stack allocated and convenience
|
#include <QPixmap>
|
||||||
#include <QBasicTimer> //stack allocated
|
#include <QBasicTimer>
|
||||||
#include <QWidget> //baseclass
|
#include <QWidget>
|
||||||
#include <vector> //included for convenience
|
#include <vector>
|
||||||
|
|
||||||
#include <QGLWidget> //baseclass
|
#include <QGLWidget>
|
||||||
#ifdef Q_WS_MACX
|
#ifdef Q_WS_MACX
|
||||||
#include <OpenGL/gl.h> //included for convenience
|
#include <OpenGL/gl.h>
|
||||||
#include <OpenGL/glu.h> //included for convenience
|
#include <OpenGL/glu.h>
|
||||||
#else
|
#else
|
||||||
#include <GL/gl.h> //included for convenience
|
#include <GL/gl.h>
|
||||||
#include <GL/glu.h> //included for convenience
|
#include <GL/glu.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class QEvent;
|
class QEvent;
|
||||||
@ -53,7 +75,7 @@ class Base : public QWidget {
|
|||||||
virtual void framerateChanged() {}
|
virtual void framerateChanged() {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Base(QWidget*, uint scopeSize = 7);
|
explicit Base(QWidget*, uint scopeSize = 7);
|
||||||
|
|
||||||
void hideEvent(QHideEvent*);
|
void hideEvent(QHideEvent*);
|
||||||
void showEvent(QShowEvent*);
|
void showEvent(QShowEvent*);
|
||||||
@ -86,4 +108,4 @@ void initSin(Scope&, const uint = 6000);
|
|||||||
|
|
||||||
} // END namespace Analyzer
|
} // END namespace Analyzer
|
||||||
|
|
||||||
#endif
|
#endif // ANALYZERS_ANALYZERBASE_H_
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
/* This file is part of Clementine.
|
/* This file is part of Clementine.
|
||||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
Copyright 2010-2011, David Sansome <davidsansome@gmail.com>
|
||||||
|
Copyright 2010, 2014, John Maguire <john.maguire@gmail.com>
|
||||||
|
Copyright 2011-2012, Arnaud Bienner <arnaud.bienner@gmail.com>
|
||||||
|
Copyright 2013, Vasily Fomin <vasili.fomin@gmail.com>
|
||||||
|
Copyright 2014, Mark Furneaux <mark@romaco.ca>
|
||||||
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
|
|
||||||
Clementine is free software: you can redistribute it and/or modify
|
Clementine 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
|
||||||
@ -20,6 +25,7 @@
|
|||||||
#include "blockanalyzer.h"
|
#include "blockanalyzer.h"
|
||||||
#include "boomanalyzer.h"
|
#include "boomanalyzer.h"
|
||||||
#include "nyancatanalyzer.h"
|
#include "nyancatanalyzer.h"
|
||||||
|
#include "rainbowdashanalyzer.h"
|
||||||
#include "sonogram.h"
|
#include "sonogram.h"
|
||||||
#include "turbine.h"
|
#include "turbine.h"
|
||||||
#include "core/logging.h"
|
#include "core/logging.h"
|
||||||
@ -74,6 +80,7 @@ AnalyzerContainer::AnalyzerContainer(QWidget* parent)
|
|||||||
AddAnalyzerType<Sonogram>();
|
AddAnalyzerType<Sonogram>();
|
||||||
AddAnalyzerType<TurbineAnalyzer>();
|
AddAnalyzerType<TurbineAnalyzer>();
|
||||||
AddAnalyzerType<NyanCatAnalyzer>();
|
AddAnalyzerType<NyanCatAnalyzer>();
|
||||||
|
AddAnalyzerType<RainbowDashAnalyzer>();
|
||||||
|
|
||||||
connect(mapper_, SIGNAL(mapped(int)), SLOT(ChangeAnalyzer(int)));
|
connect(mapper_, SIGNAL(mapped(int)), SLOT(ChangeAnalyzer(int)));
|
||||||
disable_action_ = context_menu_->addAction(tr("No analyzer"), this,
|
disable_action_ = context_menu_->addAction(tr("No analyzer"), this,
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
/* This file is part of Clementine.
|
/* This file is part of Clementine.
|
||||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
Copyright 2010, David Sansome <davidsansome@gmail.com>
|
||||||
|
Copyright 2010, 2014, John Maguire <john.maguire@gmail.com>
|
||||||
|
Copyright 2011-2012, Arnaud Bienner <arnaud.bienner@gmail.com>
|
||||||
|
Copyright 2013, Vasily Fomin <vasili.fomin@gmail.com>
|
||||||
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
|
|
||||||
Clementine is free software: you can redistribute it and/or modify
|
Clementine 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
|
||||||
@ -15,8 +19,8 @@
|
|||||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ANALYZERCONTAINER_H
|
#ifndef ANALYZERS_ANALYZERCONTAINER_H_
|
||||||
#define ANALYZERCONTAINER_H
|
#define ANALYZERS_ANALYZERCONTAINER_H_
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
@ -29,15 +33,14 @@ class AnalyzerContainer : public QWidget {
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AnalyzerContainer(QWidget* parent);
|
explicit AnalyzerContainer(QWidget* parent);
|
||||||
|
|
||||||
void SetEngine(EngineBase* engine);
|
void SetEngine(EngineBase* engine);
|
||||||
void SetActions(QAction* visualisation);
|
void SetActions(QAction* visualisation);
|
||||||
|
|
||||||
static const char* kSettingsGroup;
|
static const char* kSettingsGroup;
|
||||||
static const char* kSettingsFramerate;
|
static const char* kSettingsFramerate;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void WheelEvent(int delta);
|
void WheelEvent(int delta);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -100,4 +103,4 @@ void AnalyzerContainer::AddAnalyzerType() {
|
|||||||
actions_ << action;
|
actions_ << action;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif // ANALYZERS_ANALYZERCONTAINER_H_
|
||||||
|
@ -1,18 +1,31 @@
|
|||||||
//
|
/* This file is part of Clementine.
|
||||||
//
|
Copyright 2003, Mark Kretschmann <markey@web.de>
|
||||||
// C++ Implementation: $MODULE$
|
Copyright 2009-2010, David Sansome <davidsansome@gmail.com>
|
||||||
//
|
Copyright 2014, Alibek Omarov <a1ba.omarov@gmail.com>
|
||||||
// Description:
|
Copyright 2014, Mark Furneaux <mark@romaco.ca>
|
||||||
//
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
//
|
Copyright 2014, John Maguire <john.maguire@gmail.com>
|
||||||
// Author: Mark Kretschmann <markey@web.de>, (C) 2003
|
|
||||||
//
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
// Copyright: See COPYING file that comes with this distribution
|
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.
|
||||||
|
|
||||||
|
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Original Author: Mark Kretschmann <markey@web.de> 2003
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "baranalyzer.h"
|
#include "baranalyzer.h"
|
||||||
#include <cmath> //log10(), etc.
|
#include <cmath>
|
||||||
#include <QtDebug>
|
#include <QtDebug>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
|
||||||
@ -25,17 +38,17 @@ BarAnalyzer::BarAnalyzer(QWidget* parent) : Analyzer::Base(parent, 8) {
|
|||||||
// roof pixmaps don't depend on size() so we do in the ctor
|
// roof pixmaps don't depend on size() so we do in the ctor
|
||||||
m_bg = parent->palette().color(QPalette::Background);
|
m_bg = parent->palette().color(QPalette::Background);
|
||||||
|
|
||||||
QColor fg(0xff, 0x50, 0x70);
|
QColor fg(parent->palette().color(QPalette::Highlight).lighter(150));
|
||||||
|
|
||||||
double dr = double(m_bg.red() - fg.red()) /
|
double dr = static_cast<double>(m_bg.red() - fg.red()) /
|
||||||
(NUM_ROOFS - 1); //-1 because we start loop below at 0
|
(NUM_ROOFS - 1); // -1 because we start loop below at 0
|
||||||
double dg = double(m_bg.green() - fg.green()) / (NUM_ROOFS - 1);
|
double dg = static_cast<double>(m_bg.green() - fg.green()) / (NUM_ROOFS - 1);
|
||||||
double db = double(m_bg.blue() - fg.blue()) / (NUM_ROOFS - 1);
|
double db = static_cast<double>(m_bg.blue() - fg.blue()) / (NUM_ROOFS - 1);
|
||||||
|
|
||||||
for (uint i = 0; i < NUM_ROOFS; ++i) {
|
for (uint i = 0; i < NUM_ROOFS; ++i) {
|
||||||
m_pixRoof[i] = QPixmap(COLUMN_WIDTH, 1);
|
m_pixRoof[i] = QPixmap(COLUMN_WIDTH, 1);
|
||||||
m_pixRoof[i].fill(QColor(fg.red() + int(dr * i), fg.green() + int(dg * i),
|
m_pixRoof[i].fill(QColor(fg.red() + static_cast<int>(dr * i), fg.green() + static_cast<int>(dg * i),
|
||||||
fg.blue() + int(db * i)));
|
fg.blue() + static_cast<int>(db * i)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,11 +58,11 @@ void BarAnalyzer::resizeEvent(QResizeEvent* e) { init(); }
|
|||||||
|
|
||||||
void BarAnalyzer::init() {
|
void BarAnalyzer::init() {
|
||||||
const double MAX_AMPLITUDE = 1.0;
|
const double MAX_AMPLITUDE = 1.0;
|
||||||
const double F = double(height() - 2) / (log10(255) * MAX_AMPLITUDE);
|
const double F = static_cast<double>(height() - 2) / (log10(255) * MAX_AMPLITUDE);
|
||||||
|
|
||||||
BAND_COUNT = width() / 5;
|
BAND_COUNT = width() / 5;
|
||||||
MAX_DOWN = int(0 - (qMax(1, height() / 50)));
|
MAX_DOWN = static_cast<int>(0 - (qMax(1, height() / 50)));
|
||||||
MAX_UP = int(qMax(1, height() / 25));
|
MAX_UP = static_cast<int>(qMax(1, height() / 25));
|
||||||
|
|
||||||
barVector.resize(BAND_COUNT, 0);
|
barVector.resize(BAND_COUNT, 0);
|
||||||
roofVector.resize(BAND_COUNT, height() - 5);
|
roofVector.resize(BAND_COUNT, height() - 5);
|
||||||
@ -60,7 +73,7 @@ void BarAnalyzer::init() {
|
|||||||
// generate a list of values that express amplitudes in range 0-MAX_AMP as
|
// generate a list of values that express amplitudes in range 0-MAX_AMP as
|
||||||
// ints from 0-height() on log scale
|
// ints from 0-height() on log scale
|
||||||
for (uint x = 0; x < 256; ++x) {
|
for (uint x = 0; x < 256; ++x) {
|
||||||
m_lvlMapper[x] = uint(F * log10(x + 1));
|
m_lvlMapper[x] = static_cast<uint>(F * log10(x + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pixBarGradient = QPixmap(height() * COLUMN_WIDTH, height());
|
m_pixBarGradient = QPixmap(height() * COLUMN_WIDTH, height());
|
||||||
@ -69,14 +82,16 @@ void BarAnalyzer::init() {
|
|||||||
canvas_.fill(palette().color(QPalette::Background));
|
canvas_.fill(palette().color(QPalette::Background));
|
||||||
|
|
||||||
QPainter p(&m_pixBarGradient);
|
QPainter p(&m_pixBarGradient);
|
||||||
for (int x = 0, r = 0x40, g = 0x30, b = 0xff, r2 = 255 - r; x < height();
|
QColor rgb(palette().color(QPalette::Highlight));
|
||||||
|
|
||||||
|
for (int x = 0, r = rgb.red(), g = rgb.green(), b = rgb.blue(), r2 = 255 - r; x < height();
|
||||||
++x) {
|
++x) {
|
||||||
for (int y = x; y > 0; --y) {
|
for (int y = x; y > 0; --y) {
|
||||||
const double fraction = (double)y / height();
|
const double fraction = static_cast<double>(y) / height();
|
||||||
|
|
||||||
// p.setPen( QColor( r + (int)(r2 * fraction), g, b - (int)(255 *
|
// p.setPen( QColor( r + (int)(r2 * fraction), g, b - (int)(255 *
|
||||||
// fraction) ) );
|
// fraction) ) );
|
||||||
p.setPen(QColor(r + (int)(r2 * fraction), g, b));
|
p.setPen(QColor(r + static_cast<int>(r2 * fraction), g, b));
|
||||||
p.drawLine(x * COLUMN_WIDTH, height() - y, (x + 1) * COLUMN_WIDTH,
|
p.drawLine(x * COLUMN_WIDTH, height() - y, (x + 1) * COLUMN_WIDTH,
|
||||||
height() - y);
|
height() - y);
|
||||||
}
|
}
|
||||||
@ -100,8 +115,8 @@ void BarAnalyzer::analyze(QPainter& p, const Scope& s, bool new_frame) {
|
|||||||
|
|
||||||
for (uint i = 0, x = 0, y2; i < v.size(); ++i, x += COLUMN_WIDTH + 1) {
|
for (uint i = 0, x = 0, y2; i < v.size(); ++i, x += COLUMN_WIDTH + 1) {
|
||||||
// assign pre[log10]'d value
|
// assign pre[log10]'d value
|
||||||
y2 = uint(v[i] *
|
y2 = static_cast<uint>(v[i] *
|
||||||
256); // 256 will be optimised to a bitshift //no, it's a float
|
256); // 256 will be optimised to a bitshift //no, it's a float
|
||||||
y2 = m_lvlMapper[(y2 > 255) ? 255 : y2]; // lvlMapper is array of ints with
|
y2 = m_lvlMapper[(y2 > 255) ? 255 : y2]; // lvlMapper is array of ints with
|
||||||
// values 0 to height()
|
// values 0 to height()
|
||||||
|
|
||||||
@ -122,8 +137,8 @@ void BarAnalyzer::analyze(QPainter& p, const Scope& s, bool new_frame) {
|
|||||||
MAX_DOWN)
|
MAX_DOWN)
|
||||||
y2 = barVector[i] + MAX_DOWN;
|
y2 = barVector[i] + MAX_DOWN;
|
||||||
|
|
||||||
if ((int)y2 > roofVector[i]) {
|
if (static_cast<int>(y2) > roofVector[i]) {
|
||||||
roofVector[i] = (int)y2;
|
roofVector[i] = static_cast<int>(y2);
|
||||||
roofVelocityVector[i] = 1;
|
roofVelocityVector[i] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,8 +175,9 @@ void BarAnalyzer::analyze(QPainter& p, const Scope& s, bool new_frame) {
|
|||||||
if (roofVector[i] < 0) {
|
if (roofVector[i] < 0) {
|
||||||
roofVector[i] = 0; // not strictly necessary
|
roofVector[i] = 0; // not strictly necessary
|
||||||
roofVelocityVector[i] = 0;
|
roofVelocityVector[i] = 0;
|
||||||
} else
|
} else {
|
||||||
++roofVelocityVector[i];
|
++roofVelocityVector[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,31 @@
|
|||||||
// Maintainer: Max Howell <max.howell@methylblue.com>
|
/* This file is part of Clementine.
|
||||||
// Authors: Mark Kretschmann & Max Howell (C) 2003-4
|
Copyright 2003-2005, Max Howell <max.howell@methylblue.com>
|
||||||
// Copyright: See COPYING file that comes with this distribution
|
Copyright 2005, Mark Kretschmann <markey@web.de>
|
||||||
//
|
Copyright 2009-2010, David Sansome <davidsansome@gmail.com>
|
||||||
|
Copyright 2014, Mark Furneaux <mark@romaco.ca>
|
||||||
|
Copyright 2014, Krzysztof A. Sobiecki <sobkas@gmail.com>
|
||||||
|
Copyright 2014, John Maguire <john.maguire@gmail.com>
|
||||||
|
|
||||||
#ifndef BARANALYZER_H
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
#define BARANALYZER_H
|
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.
|
||||||
|
|
||||||
|
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Original Author: Max Howell <max.howell@methylblue.com> 2003-2005
|
||||||
|
* Original Author: Mark Kretschmann <markey@web.de> 2005
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ANALYZERS_BARANALYZER_H_
|
||||||
|
#define ANALYZERS_BARANALYZER_H_
|
||||||
|
|
||||||
#include "analyzerbase.h"
|
#include "analyzerbase.h"
|
||||||
|
|
||||||
@ -12,6 +33,7 @@ typedef std::vector<uint> aroofMemVec;
|
|||||||
|
|
||||||
class BarAnalyzer : public Analyzer::Base {
|
class BarAnalyzer : public Analyzer::Base {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Q_INVOKABLE BarAnalyzer(QWidget*);
|
Q_INVOKABLE BarAnalyzer(QWidget*);
|
||||||
|
|
||||||
@ -57,4 +79,4 @@ class BarAnalyzer : public Analyzer::Base {
|
|||||||
QColor m_bg;
|
QColor m_bg;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // ANALYZERS_BARANALYZER_H_
|
||||||
|
@ -1,7 +1,28 @@
|
|||||||
// Author: Max Howell <max.howell@methylblue.com>, (C) 2003-5
|
/* This file is part of Clementine.
|
||||||
// Mark Kretschmann <markey@web.de>, (C) 2005
|
Copyright 2003-2005, Max Howell <max.howell@methylblue.com>
|
||||||
// Copyright: See COPYING file that comes with this distribution
|
Copyright 2005, Mark Kretschmann <markey@web.de>
|
||||||
//
|
Copyright 2009-2010, David Sansome <davidsansome@gmail.com>
|
||||||
|
Copyright 2010, 2014, John Maguire <john.maguire@gmail.com>
|
||||||
|
Copyright 2014, Mark Furneaux <mark@romaco.ca>
|
||||||
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
|
|
||||||
|
Clementine 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.
|
||||||
|
|
||||||
|
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Original Author: Max Howell <max.howell@methylblue.com> 2003-2005
|
||||||
|
* Original Author: Mark Kretschmann <markey@web.de> 2005
|
||||||
|
*/
|
||||||
|
|
||||||
#include "blockanalyzer.h"
|
#include "blockanalyzer.h"
|
||||||
|
|
||||||
@ -24,28 +45,19 @@ const char* BlockAnalyzer::kName =
|
|||||||
|
|
||||||
BlockAnalyzer::BlockAnalyzer(QWidget* parent)
|
BlockAnalyzer::BlockAnalyzer(QWidget* parent)
|
||||||
: Analyzer::Base(parent, 9),
|
: Analyzer::Base(parent, 9),
|
||||||
m_columns(0) // uint
|
m_columns(0),
|
||||||
,
|
m_rows(0),
|
||||||
m_rows(0) // uint
|
m_y(0),
|
||||||
,
|
m_barPixmap(1, 1),
|
||||||
m_y(0) // uint
|
|
||||||
,
|
|
||||||
m_barPixmap(1, 1) // null qpixmaps cause crashes
|
|
||||||
,
|
|
||||||
m_topBarPixmap(WIDTH, HEIGHT),
|
m_topBarPixmap(WIDTH, HEIGHT),
|
||||||
m_scope(MIN_COLUMNS) // Scope
|
m_scope(MIN_COLUMNS),
|
||||||
,
|
m_store(1 << 8, 0),
|
||||||
m_store(1 << 8, 0) // vector<uint>
|
m_fade_bars(FADE_SIZE),
|
||||||
,
|
m_fade_pos(1 << 8, 50),
|
||||||
m_fade_bars(FADE_SIZE) // vector<QPixmap>
|
m_fade_intensity(1 << 8, 32) {
|
||||||
,
|
|
||||||
m_fade_pos(1 << 8, 50) // vector<uint>
|
|
||||||
,
|
|
||||||
m_fade_intensity(1 << 8, 32) // vector<uint>
|
|
||||||
{
|
|
||||||
setMinimumSize(MIN_COLUMNS * (WIDTH + 1) - 1,
|
setMinimumSize(MIN_COLUMNS * (WIDTH + 1) - 1,
|
||||||
MIN_ROWS * (HEIGHT + 1) -
|
MIN_ROWS * (HEIGHT + 1) - 1);
|
||||||
1); //-1 is padding, no drawing takes place there
|
// -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
|
||||||
@ -63,9 +75,9 @@ void BlockAnalyzer::resizeEvent(QResizeEvent* e) {
|
|||||||
const uint oldRows = m_rows;
|
const uint oldRows = m_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);
|
m_columns = qMax(static_cast<uint>(static_cast<double>(width() + 1) / (WIDTH + 1)), MAX_COLUMNS);
|
||||||
m_rows = uint(double(height() + 1) / (HEIGHT + 1));
|
m_rows = static_cast<uint>(static_cast<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;
|
m_y = (height() - (m_rows * (HEIGHT + 1)) + 2) / 2;
|
||||||
@ -103,15 +115,14 @@ void BlockAnalyzer::determineStep() {
|
|||||||
// 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 * m_rows : 30 * m_rows;
|
||||||
|
|
||||||
m_step = double(m_rows * timeout()) / fallTime;
|
m_step = static_cast<double>(m_rows * timeout()) / fallTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockAnalyzer::framerateChanged() { // virtual
|
void BlockAnalyzer::framerateChanged() { // virtual
|
||||||
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());
|
||||||
@ -157,12 +168,12 @@ void BlockAnalyzer::analyze(QPainter& p, const Analyzer::Scope& s,
|
|||||||
for (uint y, x = 0; x < m_scope.size(); ++x) {
|
for (uint y, x = 0; x < m_scope.size(); ++x) {
|
||||||
// determine y
|
// determine y
|
||||||
for (y = 0; m_scope[x] < m_yscale[y]; ++y)
|
for (y = 0; m_scope[x] < m_yscale[y]; ++y)
|
||||||
;
|
continue;
|
||||||
|
|
||||||
// this is opposite to what you'd think, higher than y
|
// this is opposite to what you'd think, higher than y
|
||||||
// means the bar is lower than y (physically)
|
// means the bar is lower than y (physically)
|
||||||
if ((float)y > m_store[x])
|
if (static_cast<float>(y) > m_store[x])
|
||||||
y = int(m_store[x] += m_step);
|
y = static_cast<int>(m_store[x] += m_step);
|
||||||
else
|
else
|
||||||
m_store[x] = y;
|
m_store[x] = y;
|
||||||
|
|
||||||
@ -191,8 +202,9 @@ void BlockAnalyzer::analyze(QPainter& p, const Analyzer::Scope& s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (uint x = 0; x < m_store.size(); ++x)
|
for (uint x = 0; x < m_store.size(); ++x)
|
||||||
canvas_painter.drawPixmap(
|
canvas_painter.drawPixmap(x * (WIDTH + 1),
|
||||||
x * (WIDTH + 1), int(m_store[x]) * (HEIGHT + 1) + m_y, m_topBarPixmap);
|
static_cast<int>(m_store[x]) * (HEIGHT + 1) + m_y,
|
||||||
|
m_topBarPixmap);
|
||||||
|
|
||||||
p.drawPixmap(0, 0, canvas_);
|
p.drawPixmap(0, 0, canvas_);
|
||||||
}
|
}
|
||||||
@ -231,7 +243,7 @@ static inline void adjustToLimits(int& b, int& f, uint& amount) {
|
|||||||
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) {}
|
explicit 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);
|
||||||
@ -241,14 +253,6 @@ QColor ensureContrast(const QColor& bg, const QColor& fg, uint _amount = 150) {
|
|||||||
const QColor& c;
|
const QColor& c;
|
||||||
};
|
};
|
||||||
|
|
||||||
// hack so I don't have to cast everywhere
|
|
||||||
#define amount static_cast<int>(_amount)
|
|
||||||
// #define STAMP debug() << (QValueList<int>() << fh << fs << fv) << endl;
|
|
||||||
// #define STAMP1( string ) debug() << string << ": " <<
|
|
||||||
// (QValueList<int>() << fh << fs << fv) << endl;
|
|
||||||
// #define STAMP2( string, value ) debug() << string << "=" << value << ":
|
|
||||||
// " << (QValueList<int>() << fh << fs << fv) << endl;
|
|
||||||
|
|
||||||
OutputOnExit allocateOnTheStack(fg);
|
OutputOnExit allocateOnTheStack(fg);
|
||||||
|
|
||||||
int bh, bs, bv;
|
int bh, bs, bv;
|
||||||
@ -259,23 +263,17 @@ QColor ensureContrast(const QColor& bg, const QColor& fg, uint _amount = 150) {
|
|||||||
|
|
||||||
int dv = abs(bv - fv);
|
int dv = abs(bv - fv);
|
||||||
|
|
||||||
// STAMP2( "DV", dv );
|
|
||||||
|
|
||||||
// value is the best measure of contrast
|
// value is the best measure of contrast
|
||||||
// if there is enough difference in value already, return fg unchanged
|
// if there is enough difference in value already, return fg unchanged
|
||||||
if (dv > amount) return fg;
|
if (dv > static_cast<int>(_amount)) return fg;
|
||||||
|
|
||||||
int ds = abs(bs - fs);
|
int ds = abs(bs - fs);
|
||||||
|
|
||||||
// STAMP2( "DS", ds );
|
|
||||||
|
|
||||||
// saturation is good enough too. But not as good. TODO adapt this a little
|
// saturation is good enough too. But not as good. TODO adapt this a little
|
||||||
if (ds > amount) return fg;
|
if (ds > static_cast<int>(_amount)) return fg;
|
||||||
|
|
||||||
int dh = abs(bh - fh);
|
int dh = abs(bh - fh);
|
||||||
|
|
||||||
// STAMP2( "DH", dh );
|
|
||||||
|
|
||||||
if (dh > 120) {
|
if (dh > 120) {
|
||||||
// a third of the colour wheel automatically guarentees contrast
|
// a third of the colour wheel automatically guarentees contrast
|
||||||
// but only if the values are high enough and saturations significant enough
|
// but only if the values are high enough and saturations significant enough
|
||||||
@ -283,105 +281,75 @@ QColor ensureContrast(const QColor& bg, const QColor& fg, uint _amount = 150) {
|
|||||||
|
|
||||||
// check the saturation for the two colours is sufficient that hue alone can
|
// check the saturation for the two colours is sufficient that hue alone can
|
||||||
// provide sufficient contrast
|
// provide sufficient contrast
|
||||||
if (ds > amount / 2 && (bs > 125 && fs > 125))
|
if (ds > static_cast<int>(_amount) / 2 && (bs > 125 && fs > 125))
|
||||||
// STAMP1( "Sufficient saturation difference, and hues are
|
|
||||||
// compliemtary" );
|
|
||||||
return fg;
|
return fg;
|
||||||
else if (dv > amount / 2 && (bv > 125 && fv > 125))
|
else if (dv > static_cast<int>(_amount) / 2 && (bv > 125 && fv > 125))
|
||||||
// STAMP1( "Sufficient value difference, and hues are
|
|
||||||
// compliemtary" );
|
|
||||||
return fg;
|
return fg;
|
||||||
|
|
||||||
// STAMP1( "Hues are complimentary but we must modify the value or
|
|
||||||
// saturation of the contrasting colour" );
|
|
||||||
|
|
||||||
// but either the colours are two desaturated, or too dark
|
|
||||||
// so we need to adjust the system, although not as much
|
|
||||||
///_amount /= 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fs < 50 && ds < 40) {
|
if (fs < 50 && ds < 40) {
|
||||||
// low saturation on a low saturation is sad
|
// low saturation on a low saturation is sad
|
||||||
const int tmp = 50 - fs;
|
const int tmp = 50 - fs;
|
||||||
fs = 50;
|
fs = 50;
|
||||||
if (amount > tmp)
|
if (static_cast<int>(_amount) > tmp)
|
||||||
_amount -= tmp;
|
_amount -= tmp;
|
||||||
else
|
else
|
||||||
_amount = 0;
|
_amount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// test that there is available value to honor our contrast requirement
|
// test that there is available value to honor our contrast requirement
|
||||||
if (255 - dv < amount) {
|
if (255 - dv < static_cast<int>(_amount)) {
|
||||||
// we have to modify the value and saturation of fg
|
// we have to modify the value and saturation of fg
|
||||||
// adjustToLimits( bv, fv, amount );
|
// adjustToLimits( bv, fv, amount );
|
||||||
|
|
||||||
// STAMP
|
|
||||||
|
|
||||||
// see if we need to adjust the saturation
|
// see if we need to adjust the saturation
|
||||||
if (amount > 0) adjustToLimits(bs, fs, _amount);
|
if (static_cast<int>(_amount) > 0) adjustToLimits(bs, fs, _amount);
|
||||||
|
|
||||||
// STAMP
|
|
||||||
|
|
||||||
// see if we need to adjust the hue
|
// see if we need to adjust the hue
|
||||||
if (amount > 0) fh += amount; // cycles around;
|
if (static_cast<int>(_amount) > 0) fh += static_cast<int>(_amount); // cycles around;
|
||||||
|
|
||||||
// STAMP
|
|
||||||
|
|
||||||
return QColor::fromHsv(fh, fs, fv);
|
return QColor::fromHsv(fh, fs, fv);
|
||||||
}
|
}
|
||||||
|
|
||||||
// STAMP
|
if (fv > bv && bv > static_cast<int>(_amount))
|
||||||
|
return QColor::fromHsv(fh, fs, bv - static_cast<int>(_amount));
|
||||||
|
|
||||||
if (fv > bv && bv > amount) return QColor::fromHsv(fh, fs, bv - amount);
|
if (fv < bv && fv > static_cast<int>(_amount))
|
||||||
|
return QColor::fromHsv(fh, fs, fv - static_cast<int>(_amount));
|
||||||
|
|
||||||
// STAMP
|
if (fv > bv && (255 - fv > static_cast<int>(_amount)))
|
||||||
|
return QColor::fromHsv(fh, fs, fv + static_cast<int>(_amount));
|
||||||
|
|
||||||
if (fv < bv && fv > amount) return QColor::fromHsv(fh, fs, fv - amount);
|
if (fv < bv && (255 - bv > static_cast<int>(_amount)))
|
||||||
|
return QColor::fromHsv(fh, fs, bv + static_cast<int>(_amount));
|
||||||
// STAMP
|
|
||||||
|
|
||||||
if (fv > bv && (255 - fv > amount))
|
|
||||||
return QColor::fromHsv(fh, fs, fv + amount);
|
|
||||||
|
|
||||||
// STAMP
|
|
||||||
|
|
||||||
if (fv < bv && (255 - bv > amount))
|
|
||||||
return QColor::fromHsv(fh, fs, bv + amount);
|
|
||||||
|
|
||||||
// STAMP
|
|
||||||
// debug() << "Something went wrong!\n";
|
|
||||||
|
|
||||||
return Qt::blue;
|
return Qt::blue;
|
||||||
|
|
||||||
#undef amount
|
|
||||||
// #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);
|
m_topBarPixmap.fill(fg);
|
||||||
|
|
||||||
const double dr = 15 * double(bg.red() - fg.red()) / (m_rows * 16);
|
const double dr = 15 * static_cast<double>(bg.red() - fg.red()) / (m_rows * 16);
|
||||||
const double dg = 15 * double(bg.green() - fg.green()) / (m_rows * 16);
|
const double dg = 15 * static_cast<double>(bg.green() - fg.green()) / (m_rows * 16);
|
||||||
const double db = 15 * double(bg.blue() - fg.blue()) / (m_rows * 16);
|
const double db = 15 * static_cast<double>(bg.blue() - fg.blue()) / (m_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; static_cast<uint>(y) < m_rows; ++y)
|
||||||
// graduate the fg color
|
// graduate the fg color
|
||||||
p.fillRect(0, y * (HEIGHT + 1), WIDTH, HEIGHT,
|
p.fillRect(0, y * (HEIGHT + 1), WIDTH, HEIGHT,
|
||||||
QColor(r + int(dr * y), g + int(dg * y), b + int(db * y)));
|
QColor(r + static_cast<int>(dr * y), g + static_cast<int>(dg * y),
|
||||||
|
b + static_cast<int>(db * y)));
|
||||||
|
|
||||||
{
|
{
|
||||||
const QColor bg = palette().color(QPalette::Background).dark(112);
|
const QColor bg = palette().color(QPalette::Background).dark(112);
|
||||||
|
|
||||||
// make a complimentary fadebar colour
|
// make a complimentary fadebar colour
|
||||||
// TODO dark is not always correct, dumbo!
|
// TODO(John Maguire): dark is not always correct, dumbo!
|
||||||
int h, s, v;
|
int h, s, v;
|
||||||
palette().color(QPalette::Background).dark(150).getHsv(&h, &s, &v);
|
palette().color(QPalette::Background).dark(150).getHsv(&h, &s, &v);
|
||||||
const QColor fg(QColor::fromHsv(h + 120, s, v));
|
const QColor fg(QColor::fromHsv(h + 120, s, v));
|
||||||
@ -395,10 +363,10 @@ void BlockAnalyzer::paletteChange(const QPalette&) // virtual
|
|||||||
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));
|
m_fade_bars[y].fill(palette().color(QPalette::Background));
|
||||||
QPainter f(&m_fade_bars[y]);
|
QPainter f(&m_fade_bars[y]);
|
||||||
for (int z = 0; (uint)z < m_rows; ++z) {
|
for (int z = 0; static_cast<uint>(z) < m_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,
|
f.fillRect(0, z * (HEIGHT + 1), WIDTH, HEIGHT,
|
||||||
QColor(r + int(dr * Y), g + int(dg * Y), b + int(db * Y)));
|
QColor(r + static_cast<int>(dr * Y), g + static_cast<int>(dg * Y), b + static_cast<int>(db * Y)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,29 @@
|
|||||||
// Maintainer: Max Howell <mac.howell@methylblue.com>, (C) 2003-5
|
/* This file is part of Clementine.
|
||||||
// Copyright: See COPYING file that comes with this distribution
|
Copyright 2003-2005, Max Howell <max.howell@methylblue.com>
|
||||||
//
|
Copyright 2009-2010, David Sansome <davidsansome@gmail.com>
|
||||||
|
Copyright 2010, 2014, John Maguire <john.maguire@gmail.com>
|
||||||
|
Copyright 2014, Mark Furneaux <mark@romaco.ca>
|
||||||
|
Copyright 2014, Krzysztof A. Sobiecki <sobkas@gmail.com>
|
||||||
|
|
||||||
#ifndef BLOCKANALYZER_H
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
#define BLOCKANALYZER_H
|
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.
|
||||||
|
|
||||||
|
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Original Author: Max Howell <max.howell@methylblue.com> 2003-2005
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ANALYZERS_BLOCKANALYZER_H_
|
||||||
|
#define ANALYZERS_BLOCKANALYZER_H_
|
||||||
|
|
||||||
#include "analyzerbase.h"
|
#include "analyzerbase.h"
|
||||||
#include <qcolor.h>
|
#include <qcolor.h>
|
||||||
@ -12,12 +32,9 @@ class QResizeEvent;
|
|||||||
class QMouseEvent;
|
class QMouseEvent;
|
||||||
class QPalette;
|
class QPalette;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Max Howell
|
|
||||||
*/
|
|
||||||
|
|
||||||
class BlockAnalyzer : public Analyzer::Base {
|
class BlockAnalyzer : public Analyzer::Base {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Q_INVOKABLE BlockAnalyzer(QWidget*);
|
Q_INVOKABLE BlockAnalyzer(QWidget*);
|
||||||
~BlockAnalyzer();
|
~BlockAnalyzer();
|
||||||
@ -62,4 +79,4 @@ class BlockAnalyzer : public Analyzer::Base {
|
|||||||
float m_step; // rows to fall per frame
|
float m_step; // rows to fall per frame
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // ANALYZERS_BLOCKANALYZER_H_
|
||||||
|
@ -1,5 +1,26 @@
|
|||||||
// Author: Max Howell <max.howell@methylblue.com>, (C) 2004
|
/* This file is part of Clementine.
|
||||||
// Copyright: See COPYING file that comes with this distribution
|
Copyright 2004, Max Howell <max.howell@methylblue.com>
|
||||||
|
Copyright 2009-2010, David Sansome <davidsansome@gmail.com>
|
||||||
|
Copyright 2010, 2014, John Maguire <john.maguire@gmail.com>
|
||||||
|
Copyright 2014, Mark Furneaux <mark@romaco.ca>
|
||||||
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
|
|
||||||
|
Clementine 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.
|
||||||
|
|
||||||
|
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Original Author: Max Howell <max.howell@methylblue.com> 2004
|
||||||
|
*/
|
||||||
|
|
||||||
#include "boomanalyzer.h"
|
#include "boomanalyzer.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
@ -23,11 +44,11 @@ BoomAnalyzer::BoomAnalyzer(QWidget* parent)
|
|||||||
barPixmap(COLUMN_WIDTH, 50) {}
|
barPixmap(COLUMN_WIDTH, 50) {}
|
||||||
|
|
||||||
void BoomAnalyzer::changeK_barHeight(int newValue) {
|
void BoomAnalyzer::changeK_barHeight(int newValue) {
|
||||||
K_barHeight = (double)newValue / 1000;
|
K_barHeight = static_cast<double>(newValue) / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoomAnalyzer::changeF_peakSpeed(int newValue) {
|
void BoomAnalyzer::changeF_peakSpeed(int newValue) {
|
||||||
F_peakSpeed = (double)newValue / 1000;
|
F_peakSpeed = static_cast<double>(newValue) / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoomAnalyzer::resizeEvent(QResizeEvent*) { init(); }
|
void BoomAnalyzer::resizeEvent(QResizeEvent*) { init(); }
|
||||||
@ -36,7 +57,7 @@ void BoomAnalyzer::init() {
|
|||||||
const uint HEIGHT = height() - 2;
|
const uint HEIGHT = height() - 2;
|
||||||
const double h = 1.2 / HEIGHT;
|
const double h = 1.2 / HEIGHT;
|
||||||
|
|
||||||
F = double(HEIGHT) / (log10(256) * 1.1 /*<- max. amplitude*/);
|
F = static_cast<double>(HEIGHT) / (log10(256) * 1.1 /*<- max. amplitude*/);
|
||||||
|
|
||||||
barPixmap = QPixmap(COLUMN_WIDTH - 2, HEIGHT);
|
barPixmap = QPixmap(COLUMN_WIDTH - 2, HEIGHT);
|
||||||
canvas_ = QPixmap(size());
|
canvas_ = QPixmap(size());
|
||||||
@ -44,11 +65,11 @@ void BoomAnalyzer::init() {
|
|||||||
|
|
||||||
QPainter p(&barPixmap);
|
QPainter p(&barPixmap);
|
||||||
for (uint y = 0; y < HEIGHT; ++y) {
|
for (uint y = 0; y < HEIGHT; ++y) {
|
||||||
const double F = (double)y * h;
|
const double F = static_cast<double>(y) * h;
|
||||||
|
|
||||||
p.setPen(QColor(qMax(0, 255 - int(229.0 * F)),
|
p.setPen(QColor(qMax(0, 255 - static_cast<int>(229.0 * F)),
|
||||||
qMax(0, 255 - int(229.0 * F)),
|
qMax(0, 255 - static_cast<int>(229.0 * F)),
|
||||||
qMax(0, 255 - int(191.0 * F))));
|
qMax(0, 255 - static_cast<int>(191.0 * F))));
|
||||||
p.drawLine(0, y, COLUMN_WIDTH - 2, y);
|
p.drawLine(0, y, COLUMN_WIDTH - 2, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,8 +115,9 @@ void BoomAnalyzer::analyze(QPainter& p, const Scope& scope, bool new_frame) {
|
|||||||
if (h > peak_height[i]) {
|
if (h > peak_height[i]) {
|
||||||
peak_height[i] = h;
|
peak_height[i] = h;
|
||||||
peak_speed[i] = 0.01;
|
peak_speed[i] = 0.01;
|
||||||
} else
|
} else {
|
||||||
goto peak_handling;
|
goto peak_handling;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (bar_height[i] > 0.0) {
|
if (bar_height[i] > 0.0) {
|
||||||
bar_height[i] -= K_barHeight; // 1.4
|
bar_height[i] -= K_barHeight; // 1.4
|
||||||
|
@ -1,9 +1,29 @@
|
|||||||
// Author: Max Howell <max.howell@methylblue.com>, (C) 2004
|
/* This file is part of Clementine.
|
||||||
// Copyright: See COPYING file that comes with this distribution
|
Copyright 2004, Max Howell <max.howell@methylblue.com>
|
||||||
//
|
Copyright 2009-2010, David Sansome <davidsansome@gmail.com>
|
||||||
|
Copyright 2014, Mark Furneaux <mark@romaco.ca>
|
||||||
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
|
Copyright 2014, John Maguire <john.maguire@gmail.com>
|
||||||
|
|
||||||
#ifndef BOOMANALYZER_H
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
#define BOOMANALYZER_H
|
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.
|
||||||
|
|
||||||
|
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Original Author: Max Howell <max.howell@methylblue.com> 2004
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ANALYZERS_BOOMANALYZER_H_
|
||||||
|
#define ANALYZERS_BOOMANALYZER_H_
|
||||||
|
|
||||||
#include "analyzerbase.h"
|
#include "analyzerbase.h"
|
||||||
|
|
||||||
@ -13,6 +33,7 @@
|
|||||||
|
|
||||||
class BoomAnalyzer : public Analyzer::Base {
|
class BoomAnalyzer : public Analyzer::Base {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Q_INVOKABLE BoomAnalyzer(QWidget*);
|
Q_INVOKABLE BoomAnalyzer(QWidget*);
|
||||||
|
|
||||||
@ -42,4 +63,4 @@ class BoomAnalyzer : public Analyzer::Base {
|
|||||||
QPixmap canvas_;
|
QPixmap canvas_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // ANALYZERS_BOOMANALYZER_H_
|
||||||
|
@ -1,22 +1,24 @@
|
|||||||
// FHT - Fast Hartley Transform Class
|
/* This file is part of Clementine.
|
||||||
//
|
Copyright 2004, Melchior FRANZ <mfranz@kde.org>
|
||||||
// Copyright (C) 2004 Melchior FRANZ - mfranz@kde.org
|
Copyright 2010, 2014, John Maguire <john.maguire@gmail.com>
|
||||||
//
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
// This program is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU General Public License as
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
// published by the Free Software Foundation; either version 2 of the
|
it under the terms of the GNU General Public License as published by
|
||||||
// License, or (at your option) any later version.
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
//
|
(at your option) any later version.
|
||||||
// This program is distributed in the hope that it will be useful, but
|
|
||||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
Clementine is distributed in the hope that it will be useful,
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// General Public License for more details.
|
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 this program; if not, write to the Free Software
|
You should have received a copy of the GNU General Public License
|
||||||
// Foundation, 51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA
|
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
//
|
*/
|
||||||
// $Id$
|
|
||||||
|
/* Original Author: Melchior FRANZ <mfranz@kde.org> 2004
|
||||||
|
*/
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -58,11 +60,11 @@ void FHT::makeCasTable(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
float* FHT::copy(float* d, float* s) {
|
float* FHT::copy(float* d, float* s) {
|
||||||
return (float*)memcpy(d, s, m_num * sizeof(float));
|
return static_cast<float*>(memcpy(d, s, m_num * sizeof(float)));
|
||||||
}
|
}
|
||||||
|
|
||||||
float* FHT::clear(float* d) {
|
float* FHT::clear(float* d) {
|
||||||
return (float*)memset(d, 0, m_num * sizeof(float));
|
return static_cast<float*>(memset(d, 0, m_num * sizeof(float)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FHT::scale(float* p, float d) {
|
void FHT::scale(float* p, float d) {
|
||||||
@ -77,9 +79,9 @@ void FHT::logSpectrum(float* out, float* p) {
|
|||||||
int n = m_num / 2, i, j, k, *r;
|
int n = m_num / 2, i, j, k, *r;
|
||||||
if (!m_log) {
|
if (!m_log) {
|
||||||
m_log = new int[n];
|
m_log = new int[n];
|
||||||
float f = n / log10((double)n);
|
float f = n / log10(static_cast<double>(n));
|
||||||
for (i = 0, r = m_log; i < n; i++, r++) {
|
for (i = 0, r = m_log; i < n; i++, r++) {
|
||||||
j = int(rint(log10(i + 1.0) * f));
|
j = static_cast<int>(rint(log10(i + 1.0) * f));
|
||||||
*r = j >= n ? n - 1 : j;
|
*r = j >= n ? n - 1 : j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -87,9 +89,9 @@ void FHT::logSpectrum(float* out, float* p) {
|
|||||||
*out++ = *p = *p / 100;
|
*out++ = *p = *p / 100;
|
||||||
for (k = i = 1, r = m_log; i < n; i++) {
|
for (k = i = 1, r = m_log; i < n; i++) {
|
||||||
j = *r++;
|
j = *r++;
|
||||||
if (i == j)
|
if (i == j) {
|
||||||
*out++ = p[i];
|
*out++ = p[i];
|
||||||
else {
|
} else {
|
||||||
float base = p[k - 1];
|
float base = p[k - 1];
|
||||||
float step = (p[j] - base) / (j - (k - 1));
|
float step = (p[j] - base) / (j - (k - 1));
|
||||||
for (float corr = 0; k <= j; k++, corr += step) *out++ = base + corr;
|
for (float corr = 0; k <= j; k++, corr += step) *out++ = base + corr;
|
||||||
@ -108,7 +110,8 @@ void FHT::semiLogSpectrum(float* p) {
|
|||||||
|
|
||||||
void FHT::spectrum(float* p) {
|
void FHT::spectrum(float* p) {
|
||||||
power2(p);
|
power2(p);
|
||||||
for (int i = 0; i < (m_num / 2); i++, p++) *p = (float)sqrt(*p * .5);
|
for (int i = 0; i < (m_num / 2); i++, p++)
|
||||||
|
*p = static_cast<float>(sqrt(*p * .5));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FHT::power(float* p) {
|
void FHT::power(float* p) {
|
@ -1,25 +1,27 @@
|
|||||||
// FHT - Fast Hartley Transform Class
|
/* This file is part of Clementine.
|
||||||
//
|
Copyright 2004, Melchior FRANZ <mfranz@kde.org>
|
||||||
// Copyright (C) 2004 Melchior FRANZ - mfranz@kde.org
|
Copyright 2010, 2014, John Maguire <john.maguire@gmail.com>
|
||||||
//
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
// This program 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 2 of the
|
|
||||||
// License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program 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 this program; if not, write to the Free Software
|
|
||||||
// Foundation, 51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA
|
|
||||||
//
|
|
||||||
// $Id$
|
|
||||||
|
|
||||||
#ifndef FHT_H
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
#define FHT_H
|
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.
|
||||||
|
|
||||||
|
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Original Author: Melchior FRANZ <mfranz@kde.org> 2004
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ANALYZERS_FHT_H_
|
||||||
|
#define ANALYZERS_FHT_H_
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of the Hartley Transform after Bracewell's discrete
|
* Implementation of the Hartley Transform after Bracewell's discrete
|
||||||
@ -54,7 +56,7 @@ class FHT {
|
|||||||
* should be at least 3. Values of more than 3 need a trigonometry table.
|
* should be at least 3. Values of more than 3 need a trigonometry table.
|
||||||
* @see makeCasTable()
|
* @see makeCasTable()
|
||||||
*/
|
*/
|
||||||
FHT(int);
|
explicit FHT(int);
|
||||||
|
|
||||||
~FHT();
|
~FHT();
|
||||||
inline int sizeExp() const { return m_exp2; }
|
inline int sizeExp() const { return m_exp2; }
|
||||||
@ -115,4 +117,4 @@ class FHT {
|
|||||||
void transform(float*);
|
void transform(float*);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // ANALYZERS_FHT_H_
|
@ -1,19 +1,25 @@
|
|||||||
/***************************************************************************
|
/* This file is part of Clementine.
|
||||||
gloscope.cpp - description
|
Copyright 2004, Adam Pigg <adam@piggz.co.uk>
|
||||||
-------------------
|
Copyright 2009, David Sansome <davidsansome@gmail.com>
|
||||||
begin : Jan 17 2004
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
copyright : (C) 2004 by Adam Pigg
|
Copyright 2014, John Maguire <john.maguire@gmail.com>
|
||||||
email : adam@piggz.co.uk
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
* *
|
it under the terms of the GNU General Public License as published by
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
* it under the terms of the GNU General Public License as published by *
|
(at your option) any later version.
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Original Author: Adam Pigg <adam@piggz.co.uk> 2004
|
||||||
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
@ -28,8 +34,6 @@ GLAnalyzer::GLAnalyzer(QWidget* parent)
|
|||||||
|
|
||||||
GLAnalyzer::~GLAnalyzer() {}
|
GLAnalyzer::~GLAnalyzer() {}
|
||||||
|
|
||||||
// METHODS =====================================================
|
|
||||||
|
|
||||||
void GLAnalyzer::analyze(const Scope& s) {
|
void GLAnalyzer::analyze(const Scope& s) {
|
||||||
// kdDebug() << "Scope Size: " << s.size() << endl;
|
// kdDebug() << "Scope Size: " << s.size() << endl;
|
||||||
/* Scope t(32);
|
/* Scope t(32);
|
||||||
@ -66,16 +70,13 @@ void GLAnalyzer::analyze(const Scope& s) {
|
|||||||
|
|
||||||
mfactor = 20 / peak;
|
mfactor = 20 / peak;
|
||||||
for (uint i = 0; i < 32; i++) {
|
for (uint i = 0; i < 32; i++) {
|
||||||
|
|
||||||
// kdDebug() << "Scope item " << i << " value: " << s[i] << endl;
|
|
||||||
|
|
||||||
// Calculate new horizontal position (x) depending on number of samples
|
// Calculate new horizontal position (x) depending on number of samples
|
||||||
x = -16.0f + i;
|
x = -16.0f + i;
|
||||||
|
|
||||||
// Calculating new vertical position (y) depending on the data passed by
|
// Calculating new vertical position (y) depending on the data passed by
|
||||||
// amarok
|
// amarok
|
||||||
y = float(s[i + offset] * mfactor); // This make it kinda dynamically
|
y = static_cast<float>(s[i + offset] * mfactor); // This make it kinda dynamically
|
||||||
// resize depending on the data
|
// resize depending on the data
|
||||||
|
|
||||||
// Some basic bounds checking
|
// Some basic bounds checking
|
||||||
if (y > 30)
|
if (y > 30)
|
||||||
@ -83,10 +84,10 @@ void GLAnalyzer::analyze(const Scope& s) {
|
|||||||
else if (y < 0)
|
else if (y < 0)
|
||||||
y = 0;
|
y = 0;
|
||||||
|
|
||||||
if ((y - m_oldy[i]) < -0.6f) // Going Down Too Much
|
if ((y - m_oldy[i]) < -0.6f) {
|
||||||
{
|
|
||||||
y = m_oldy[i] - 0.7f;
|
y = m_oldy[i] - 0.7f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (y < 0.0f) {
|
if (y < 0.0f) {
|
||||||
y = 0.0f;
|
y = 0.0f;
|
||||||
}
|
}
|
||||||
@ -145,9 +146,6 @@ void GLAnalyzer::resizeGL(int w, int h) {
|
|||||||
|
|
||||||
void GLAnalyzer::paintGL() {
|
void GLAnalyzer::paintGL() {
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
#if 0
|
|
||||||
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
|
||||||
#else
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
|
@ -1,32 +1,34 @@
|
|||||||
/***************************************************************************
|
/* This file is part of Clementine.
|
||||||
gloscope.h - description
|
Copyright 2004, Adam Pigg <adam@piggz.co.uk>
|
||||||
-------------------
|
Copyright 2009, David Sansome <davidsansome@gmail.com>
|
||||||
begin : Jan 17 2004
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
copyright : (C) 2004 by Adam Pigg
|
Copyright 2014, John Maguire <john.maguire@gmail.com>
|
||||||
email : adam@piggz.co.uk
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
* *
|
it under the terms of the GNU General Public License as published by
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
* it under the terms of the GNU General Public License as published by *
|
(at your option) any later version.
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifndef GLOSCOPE_H
|
Clementine is distributed in the hope that it will be useful,
|
||||||
#define GLOSCOPE_H
|
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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Original Author: Adam Pigg <adam@piggz.co.uk> 2004
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ANALYZERS_GLANALYZER_H_
|
||||||
|
#define ANALYZERS_GLANALYZER_H_
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#ifdef HAVE_QGLWIDGET
|
#ifdef HAVE_QGLWIDGET
|
||||||
|
|
||||||
#include "analyzerbase.h"
|
#include "analyzerbase.h"
|
||||||
|
|
||||||
/**
|
|
||||||
*@author piggz
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float level;
|
float level;
|
||||||
uint delay;
|
uint delay;
|
||||||
@ -46,7 +48,7 @@ class GLAnalyzer : public Analyzer::Base3D {
|
|||||||
GLfloat x, y;
|
GLfloat x, y;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GLAnalyzer(QWidget*);
|
explicit GLAnalyzer(QWidget*);
|
||||||
~GLAnalyzer();
|
~GLAnalyzer();
|
||||||
void analyze(const Scope&);
|
void analyze(const Scope&);
|
||||||
|
|
||||||
@ -57,4 +59,4 @@ class GLAnalyzer : public Analyzer::Base3D {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif // ANALYZERS_GLANALYZER_H_
|
||||||
|
@ -1,19 +1,25 @@
|
|||||||
/***************************************************************************
|
/* This file is part of Clementine.
|
||||||
glanalyzer2.cpp - description
|
Copyright 2004, Enrico Ros <eros.kde@email.it>
|
||||||
-------------------
|
Copyright 2009, David Sansome <davidsansome@gmail.com>
|
||||||
begin : Feb 16 2004
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
copyright : (C) 2004 by Enrico Ros
|
Copyright 2014, John Maguire <john.maguire@gmail.com>
|
||||||
email : eros.kde@email.it
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
* *
|
it under the terms of the GNU General Public License as published by
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
* it under the terms of the GNU General Public License as published by *
|
(at your option) any later version.
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Original Author: Enrico Ros <eros.kde@email.it> 2004
|
||||||
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
@ -71,7 +77,7 @@ void GLAnalyzer2::resizeGL(int w, int h) {
|
|||||||
glOrtho(-10.0f, 10.0f, -10.0f, 10.0f, -5.0f, 5.0f);
|
glOrtho(-10.0f, 10.0f, -10.0f, 10.0f, -5.0f, 5.0f);
|
||||||
|
|
||||||
// Get the aspect ratio of the screen to draw 'cicular' particles
|
// Get the aspect ratio of the screen to draw 'cicular' particles
|
||||||
float ratio = (float)w / (float)h, eqPixH = 60, eqPixW = 80;
|
float ratio = static_cast<float>(w) / static_cast<float>(h), eqPixH = 60, eqPixW = 80;
|
||||||
if (ratio >= (4.0 / 3.0)) {
|
if (ratio >= (4.0 / 3.0)) {
|
||||||
unitX = 10.0 / (eqPixH * ratio);
|
unitX = 10.0 / (eqPixH * ratio);
|
||||||
unitY = 10.0 / eqPixH;
|
unitY = 10.0 / eqPixH;
|
||||||
@ -83,7 +89,7 @@ void GLAnalyzer2::resizeGL(int w, int h) {
|
|||||||
// Get current timestamp.
|
// Get current timestamp.
|
||||||
timeval tv;
|
timeval tv;
|
||||||
gettimeofday(&tv, nullptr);
|
gettimeofday(&tv, nullptr);
|
||||||
show.timeStamp = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
|
show.timeStamp = static_cast<double>(tv.tv_sec) + static_cast<double>(tv.tv_usec) / 1000000.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLAnalyzer2::paused() { analyze(Scope()); }
|
void GLAnalyzer2::paused() { analyze(Scope()); }
|
||||||
@ -103,19 +109,20 @@ void GLAnalyzer2::analyze(const Scope& s) {
|
|||||||
for (int i = 0; i < bands; i++) {
|
for (int i = 0; i < bands; i++) {
|
||||||
float value = s[i];
|
float value = s[i];
|
||||||
currentEnergy += value;
|
currentEnergy += value;
|
||||||
currentMeanBand += (float)i * value;
|
currentMeanBand += static_cast<float>(i) * value;
|
||||||
if (value > maxValue) maxValue = value;
|
if (value > maxValue) maxValue = value;
|
||||||
}
|
}
|
||||||
frame.silence = currentEnergy < 0.001;
|
frame.silence = currentEnergy < 0.001;
|
||||||
if (!frame.silence) {
|
if (!frame.silence) {
|
||||||
frame.meanBand = 100.0 * currentMeanBand / (currentEnergy * bands);
|
frame.meanBand = 100.0 * currentMeanBand / (currentEnergy * bands);
|
||||||
currentEnergy = 100.0 * currentEnergy / (float)bands;
|
currentEnergy = 100.0 * currentEnergy / static_cast<float>(bands);
|
||||||
frame.dEnergy = currentEnergy - frame.energy;
|
frame.dEnergy = currentEnergy - frame.energy;
|
||||||
frame.energy = currentEnergy;
|
frame.energy = currentEnergy;
|
||||||
// printf( "%d [%f :: %f ]\t%f \n", bands, frame.energy,
|
// printf( "%d [%f :: %f ]\t%f \n", bands, frame.energy,
|
||||||
// frame.meanBand, maxValue );
|
// frame.meanBand, maxValue );
|
||||||
} else
|
} else {
|
||||||
frame.energy = 0.0;
|
frame.energy = 0.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the frame
|
// update the frame
|
||||||
@ -126,7 +133,7 @@ void GLAnalyzer2::paintGL() {
|
|||||||
// Compute the dT since the last call to paintGL and update timings
|
// Compute the dT since the last call to paintGL and update timings
|
||||||
timeval tv;
|
timeval tv;
|
||||||
gettimeofday(&tv, nullptr);
|
gettimeofday(&tv, nullptr);
|
||||||
double currentTime = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
|
double currentTime = static_cast<double>(tv.tv_sec) + static_cast<double>(tv.tv_usec) / 1000000.0;
|
||||||
show.dT = currentTime - show.timeStamp;
|
show.dT = currentTime - show.timeStamp;
|
||||||
show.timeStamp = currentTime;
|
show.timeStamp = currentTime;
|
||||||
|
|
||||||
@ -202,8 +209,9 @@ void GLAnalyzer2::paintGL() {
|
|||||||
if (dotTexture) {
|
if (dotTexture) {
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
glBindTexture(GL_TEXTURE_2D, dotTexture);
|
glBindTexture(GL_TEXTURE_2D, dotTexture);
|
||||||
} else
|
} else {
|
||||||
glDisable(GL_TEXTURE_2D);
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
}
|
||||||
|
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
// glRotatef( -frame.rotDegrees, 0,0,1 );
|
// glRotatef( -frame.rotDegrees, 0,0,1 );
|
||||||
|
@ -1,22 +1,28 @@
|
|||||||
/***************************************************************************
|
/* This file is part of Clementine.
|
||||||
glanalyzer2.h - description
|
Copyright 2004, Enrico Ros <eros.kde@email.it>
|
||||||
-------------------
|
Copyright 2009, David Sansome <davidsansome@gmail.com>
|
||||||
begin : Feb 16 2004
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
copyright : (C) 2004 by Enrico Ros
|
Copyright 2014, John Maguire <john.maguire@gmail.com>
|
||||||
email : eros.kde@email.it
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
* *
|
it under the terms of the GNU General Public License as published by
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
* it under the terms of the GNU General Public License as published by *
|
(at your option) any later version.
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifndef GLSTARVIEW_H
|
Clementine is distributed in the hope that it will be useful,
|
||||||
#define GLSTARVIEW_H
|
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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Original Author: Enrico Ros <eros.kde@email.it> 2004
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ANALYZERS_GLANALYZER2_H_
|
||||||
|
#define ANALYZERS_GLANALYZER2_H_
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#ifdef HAVE_QGLWIDGET
|
#ifdef HAVE_QGLWIDGET
|
||||||
@ -27,7 +33,7 @@
|
|||||||
|
|
||||||
class GLAnalyzer2 : public Analyzer::Base3D {
|
class GLAnalyzer2 : public Analyzer::Base3D {
|
||||||
public:
|
public:
|
||||||
GLAnalyzer2(QWidget*);
|
explicit GLAnalyzer2(QWidget*);
|
||||||
~GLAnalyzer2();
|
~GLAnalyzer2();
|
||||||
void analyze(const Scope&);
|
void analyze(const Scope&);
|
||||||
void paused();
|
void paused();
|
||||||
@ -68,4 +74,4 @@ class GLAnalyzer2 : public Analyzer::Base3D {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif // ANALYZERS_GLANALYZER2_H_
|
||||||
|
@ -1,19 +1,25 @@
|
|||||||
/***************************************************************************
|
/* This file is part of Clementine.
|
||||||
glanalyzer3.cpp - Bouncing Ballzz
|
Copyright 2004, Enrico Ros <eros.kde@email.it>
|
||||||
-------------------
|
Copyright 2009, David Sansome <davidsansome@gmail.com>
|
||||||
begin : Feb 19 2004
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
copyright : (C) 2004 by Enrico Ros
|
Copyright 2014, John Maguire <john.maguire@gmail.com>
|
||||||
email : eros.kde@email.it
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
* *
|
it under the terms of the GNU General Public License as published by
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
* it under the terms of the GNU General Public License as published by *
|
(at your option) any later version.
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Original Author: Enrico Ros <eros.kde@email.it> 2004
|
||||||
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
@ -40,16 +46,8 @@ class Ball {
|
|||||||
vx(0.0),
|
vx(0.0),
|
||||||
vy(0.0),
|
vy(0.0),
|
||||||
vz(0.0),
|
vz(0.0),
|
||||||
mass(0.01 + drand48() / 10.0)
|
mass(0.01 + drand48() / 10.0),
|
||||||
//,color( (float[3]) { 0.0, drand48()*0.5, 0.7 + drand48() * 0.3 } )
|
color((float[3]) { 0.0, drand48()*0.5, 0.7 + drand48() * 0.3 }) {}
|
||||||
{
|
|
||||||
// this is because GCC < 3.3 can't compile the above line, we aren't sure
|
|
||||||
// why though
|
|
||||||
color[0] = 0.0;
|
|
||||||
color[1] = drand48() * 0.5;
|
|
||||||
color[2] = 0.7 + drand48() * 0.3;
|
|
||||||
};
|
|
||||||
|
|
||||||
float x, y, z, vx, vy, vz, mass;
|
float x, y, z, vx, vy, vz, mass;
|
||||||
float color[3];
|
float color[3];
|
||||||
|
|
||||||
@ -70,8 +68,8 @@ class Ball {
|
|||||||
|
|
||||||
class Paddle {
|
class Paddle {
|
||||||
public:
|
public:
|
||||||
Paddle(float xPos)
|
explicit Paddle(float xPos)
|
||||||
: onLeft(xPos < 0), mass(1.0), X(xPos), x(xPos), vx(0.0) {};
|
: onLeft(xPos < 0), mass(1.0), X(xPos), x(xPos), vx(0.0) {}
|
||||||
|
|
||||||
void updatePhysics(float dT) {
|
void updatePhysics(float dT) {
|
||||||
x += vx * dT; // posision
|
x += vx * dT; // posision
|
||||||
@ -165,7 +163,7 @@ void GLAnalyzer3::resizeGL(int w, int h) {
|
|||||||
glFrustum(-0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 4.5f);
|
glFrustum(-0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 4.5f);
|
||||||
|
|
||||||
// Get the aspect ratio of the screen to draw 'circular' particles
|
// Get the aspect ratio of the screen to draw 'circular' particles
|
||||||
float ratio = (float)w / (float)h;
|
float ratio = static_cast<float>(w) / static_cast<float>(h);
|
||||||
if (ratio >= 1.0) {
|
if (ratio >= 1.0) {
|
||||||
unitX = 0.34 / ratio;
|
unitX = 0.34 / ratio;
|
||||||
unitY = 0.34;
|
unitY = 0.34;
|
||||||
@ -177,7 +175,7 @@ void GLAnalyzer3::resizeGL(int w, int h) {
|
|||||||
// Get current timestamp.
|
// Get current timestamp.
|
||||||
timeval tv;
|
timeval tv;
|
||||||
gettimeofday(&tv, nullptr);
|
gettimeofday(&tv, nullptr);
|
||||||
show.timeStamp = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
|
show.timeStamp = static_cast<double>(tv.tv_sec) + static_cast<double>(tv.tv_usec) / 1000000.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLAnalyzer3::paused() { analyze(Scope()); }
|
void GLAnalyzer3::paused() { analyze(Scope()); }
|
||||||
@ -186,7 +184,7 @@ void GLAnalyzer3::analyze(const Scope& s) {
|
|||||||
// compute the dTime since the last call
|
// compute the dTime since the last call
|
||||||
timeval tv;
|
timeval tv;
|
||||||
gettimeofday(&tv, nullptr);
|
gettimeofday(&tv, nullptr);
|
||||||
double currentTime = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
|
double currentTime = static_cast<double>(tv.tv_sec) + static_cast<double>(tv.tv_usec) / 1000000.0;
|
||||||
show.dT = currentTime - show.timeStamp;
|
show.dT = currentTime - show.timeStamp;
|
||||||
show.timeStamp = currentTime;
|
show.timeStamp = currentTime;
|
||||||
|
|
||||||
@ -200,7 +198,7 @@ void GLAnalyzer3::analyze(const Scope& s) {
|
|||||||
currentEnergy += value;
|
currentEnergy += value;
|
||||||
if (value > maxValue) maxValue = value;
|
if (value > maxValue) maxValue = value;
|
||||||
}
|
}
|
||||||
currentEnergy *= 100.0 / (float)bands;
|
currentEnergy *= 100.0 / static_cast<float>(bands);
|
||||||
// emulate a peak detector: currentEnergy -> peakEnergy (3tau = 30 seconds)
|
// emulate a peak detector: currentEnergy -> peakEnergy (3tau = 30 seconds)
|
||||||
show.peakEnergy = 1.0 + (show.peakEnergy - 1.0) * exp(-show.dT / 10.0);
|
show.peakEnergy = 1.0 + (show.peakEnergy - 1.0) * exp(-show.dT / 10.0);
|
||||||
if (currentEnergy > show.peakEnergy) show.peakEnergy = currentEnergy;
|
if (currentEnergy > show.peakEnergy) show.peakEnergy = currentEnergy;
|
||||||
@ -210,8 +208,9 @@ void GLAnalyzer3::analyze(const Scope& s) {
|
|||||||
currentEnergy /= show.peakEnergy;
|
currentEnergy /= show.peakEnergy;
|
||||||
frame.dEnergy = currentEnergy - frame.energy;
|
frame.dEnergy = currentEnergy - frame.energy;
|
||||||
frame.energy = currentEnergy;
|
frame.energy = currentEnergy;
|
||||||
} else
|
} else {
|
||||||
frame.silence = true;
|
frame.silence = true;
|
||||||
|
}
|
||||||
|
|
||||||
// update the frame
|
// update the frame
|
||||||
updateGL();
|
updateGL();
|
||||||
@ -259,8 +258,10 @@ void GLAnalyzer3::paintGL() {
|
|||||||
if (ballTexture) {
|
if (ballTexture) {
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
glBindTexture(GL_TEXTURE_2D, ballTexture);
|
glBindTexture(GL_TEXTURE_2D, ballTexture);
|
||||||
} else
|
} else {
|
||||||
glDisable(GL_TEXTURE_2D);
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
}
|
||||||
|
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
Ball* ball = balls.first();
|
Ball* ball = balls.first();
|
||||||
for (; ball; ball = balls.next()) {
|
for (; ball; ball = balls.next()) {
|
||||||
|
@ -1,25 +1,31 @@
|
|||||||
/***************************************************************************
|
/* This file is part of Clementine.
|
||||||
glanalyzer3.h - description
|
Copyright 2004, Enrico Ros <eros.kde@email.it>
|
||||||
-------------------
|
Copyright 2009, David Sansome <davidsansome@gmail.com>
|
||||||
begin : Feb 16 2004
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
copyright : (C) 2004 by Enrico Ros
|
Copyright 2014, John Maguire <john.maguire@gmail.com>
|
||||||
email : eros.kde@email.it
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
* *
|
it under the terms of the GNU General Public License as published by
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
* it under the terms of the GNU General Public License as published by *
|
(at your option) any later version.
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Original Author: Enrico Ros <eros.kde@email.it> 2004
|
||||||
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#ifdef HAVE_QGLWIDGET
|
#ifdef HAVE_QGLWIDGET
|
||||||
|
|
||||||
#ifndef GLBOUNCER_H
|
#ifndef ANALYZERS_GLANALYZER3_H_
|
||||||
#define GLBOUNCER_H
|
#define ANALYZERS_GLANALYZER3_H_
|
||||||
|
|
||||||
#include "analyzerbase.h"
|
#include "analyzerbase.h"
|
||||||
#include <qstring.h>
|
#include <qstring.h>
|
||||||
@ -31,7 +37,7 @@ class Paddle;
|
|||||||
|
|
||||||
class GLAnalyzer3 : public Analyzer::Base3D {
|
class GLAnalyzer3 : public Analyzer::Base3D {
|
||||||
public:
|
public:
|
||||||
GLAnalyzer3(QWidget*);
|
explicit GLAnalyzer3(QWidget*);
|
||||||
~GLAnalyzer3();
|
~GLAnalyzer3();
|
||||||
void analyze(const Scope&);
|
void analyze(const Scope&);
|
||||||
void paused();
|
void paused();
|
||||||
@ -76,4 +82,4 @@ class GLAnalyzer3 : public Analyzer::Base3D {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif // ANALYZERS_GLANALYZER3_H_
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
/* This file is part of Clementine.
|
/* This file is part of Clementine.
|
||||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
Copyright 2011, Tyler Rhodes <tyler.s.rhodes@gmail.com>
|
||||||
|
Copyright 2011-2012, 2014, David Sansome <me@davidsansome.com>
|
||||||
|
Copyright 2014, John Maguire <john.maguire@gmail.com>
|
||||||
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
|
|
||||||
Clementine is free software: you can redistribute it and/or modify
|
Clementine 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
|
||||||
@ -40,7 +43,7 @@ NyanCatAnalyzer::NyanCatAnalyzer(QWidget* parent)
|
|||||||
px_per_frame_(0),
|
px_per_frame_(0),
|
||||||
x_offset_(0),
|
x_offset_(0),
|
||||||
background_brush_(QColor(0x0f, 0x43, 0x73)) {
|
background_brush_(QColor(0x0f, 0x43, 0x73)) {
|
||||||
memset(history_, 0, arraysize(history_));
|
memset(history_, 0, sizeof(history_));
|
||||||
|
|
||||||
for (int i = 0; i < kRainbowBands; ++i) {
|
for (int i = 0; i < kRainbowBands; ++i) {
|
||||||
colors_[i] = QPen(QColor::fromHsv(i * 255 / kRainbowBands, 255, 255),
|
colors_[i] = QPen(QColor::fromHsv(i * 255 / kRainbowBands, 255, 255),
|
||||||
@ -71,7 +74,7 @@ void NyanCatAnalyzer::resizeEvent(QResizeEvent* e) {
|
|||||||
buffer_[1] = QPixmap();
|
buffer_[1] = QPixmap();
|
||||||
|
|
||||||
available_rainbow_width_ = width() - kCatWidth + kRainbowOverlap;
|
available_rainbow_width_ = width() - kCatWidth + kRainbowOverlap;
|
||||||
px_per_frame_ = float(available_rainbow_width_) / (kHistorySize - 1) + 1;
|
px_per_frame_ = static_cast<float>(available_rainbow_width_) / (kHistorySize - 1) + 1;
|
||||||
x_offset_ = px_per_frame_ * (kHistorySize - 1) - available_rainbow_width_;
|
x_offset_ = px_per_frame_ * (kHistorySize - 1) - available_rainbow_width_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,11 +112,11 @@ void NyanCatAnalyzer::analyze(QPainter& p, const Analyzer::Scope& s,
|
|||||||
QPointF* dest = polyline;
|
QPointF* dest = polyline;
|
||||||
float* source = history_;
|
float* source = history_;
|
||||||
|
|
||||||
const float top_of_cat = float(height()) / 2 - float(kCatHeight) / 2;
|
const float top_of_cat = static_cast<float>(height()) / 2 - static_cast<float>(kCatHeight) / 2;
|
||||||
for (int band = 0; band < kRainbowBands; ++band) {
|
for (int band = 0; band < kRainbowBands; ++band) {
|
||||||
// Calculate the Y position of this band.
|
// Calculate the Y position of this band.
|
||||||
const float y =
|
const float y =
|
||||||
float(kCatHeight) / (kRainbowBands + 1) * (band + 0.5) + top_of_cat;
|
static_cast<float>(kCatHeight) / (kRainbowBands + 1) * (band + 0.5) + top_of_cat;
|
||||||
|
|
||||||
// Add each point in the line.
|
// Add each point in the line.
|
||||||
for (int x = 0; x < kHistorySize; ++x) {
|
for (int x = 0; x < kHistorySize; ++x) {
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
/* This file is part of Clementine.
|
/* This file is part of Clementine.
|
||||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
Copyright 2011, Tyler Rhodes <tyler.s.rhodes@gmail.com>
|
||||||
|
Copyright 2011-2012, David Sansome <me@davidsansome.com>
|
||||||
|
Copyright 2011, 2014, John Maguire <john.maguire@gmail.com>
|
||||||
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
|
|
||||||
Clementine is free software: you can redistribute it and/or modify
|
Clementine 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
|
||||||
@ -15,8 +18,8 @@
|
|||||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef NYANCATANALYZER_H
|
#ifndef ANALYZERS_NYANCATANALYZER_H_
|
||||||
#define NYANCATANALYZER_H
|
#define ANALYZERS_NYANCATANALYZER_H_
|
||||||
|
|
||||||
#include "analyzerbase.h"
|
#include "analyzerbase.h"
|
||||||
|
|
||||||
@ -102,4 +105,4 @@ class NyanCatAnalyzer : public Analyzer::Base {
|
|||||||
QBrush background_brush_;
|
QBrush background_brush_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // NYANCATANALYZER_H
|
#endif // ANALYZERS_NYANCATANALYZER_H_
|
||||||
|
180
src/analyzers/rainbowdashanalyzer.cpp
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
/* This file is part of Clementine.
|
||||||
|
Copyright 2014, Alibek Omarov <a1ba.omarov@gmail.com>
|
||||||
|
Copyright 2014, Mark Furneaux <mark@romaco.ca>
|
||||||
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
|
Copyright 2014, David Sansome <me@davidsansome.com>
|
||||||
|
|
||||||
|
Clementine 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.
|
||||||
|
|
||||||
|
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "rainbowdashanalyzer.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include <QTimerEvent>
|
||||||
|
#include <QBrush>
|
||||||
|
|
||||||
|
#include "core/arraysize.h"
|
||||||
|
#include "core/logging.h"
|
||||||
|
|
||||||
|
using Analyzer::Scope;
|
||||||
|
|
||||||
|
const char* RainbowDashAnalyzer::kName = "Rainbow Dash";
|
||||||
|
const float RainbowDashAnalyzer::kPixelScale = 0.02f;
|
||||||
|
|
||||||
|
RainbowDashAnalyzer::RainbowDashAnalyzer(QWidget* parent)
|
||||||
|
: Analyzer::Base(parent, 9),
|
||||||
|
dash_(":/rainbowdash.png"),
|
||||||
|
timer_id_(startTimer(kFrameIntervalMs)),
|
||||||
|
frame_(0),
|
||||||
|
current_buffer_(0),
|
||||||
|
available_rainbow_width_(0),
|
||||||
|
px_per_frame_(0),
|
||||||
|
x_offset_(0),
|
||||||
|
background_brush_(QColor(0x0f, 0x43, 0x73)) {
|
||||||
|
memset(history_, 0, sizeof(history_));
|
||||||
|
|
||||||
|
for (int i = 0; i < kRainbowBands; ++i) {
|
||||||
|
colors_[i] = QPen(QColor::fromHsv(i * 255 / kRainbowBands, 255, 255),
|
||||||
|
kRainbowHeight / kRainbowBands, Qt::SolidLine,
|
||||||
|
Qt::FlatCap, Qt::RoundJoin);
|
||||||
|
|
||||||
|
// pow constants computed so that
|
||||||
|
// | band_scale(0) | ~= .5 and | band_scale(5) | ~= 32
|
||||||
|
band_scale_[i] =
|
||||||
|
-std::cos(M_PI * i / (kRainbowBands - 1)) * 0.5 * std::pow(2.3, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RainbowDashAnalyzer::transform(Scope& s) { m_fht->spectrum(&s.front()); }
|
||||||
|
|
||||||
|
void RainbowDashAnalyzer::timerEvent(QTimerEvent* e) {
|
||||||
|
if (e->timerId() == timer_id_) {
|
||||||
|
frame_ = (frame_ + 1) % kDashFrameCount;
|
||||||
|
} else {
|
||||||
|
Analyzer::Base::timerEvent(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RainbowDashAnalyzer::resizeEvent(QResizeEvent* e) {
|
||||||
|
// Invalidate the buffer so it's recreated from scratch in the next paint
|
||||||
|
// event.
|
||||||
|
buffer_[0] = QPixmap();
|
||||||
|
buffer_[1] = QPixmap();
|
||||||
|
|
||||||
|
available_rainbow_width_ = width() - kDashWidth + kRainbowOverlap;
|
||||||
|
px_per_frame_ = static_cast<float>(available_rainbow_width_) / (kHistorySize - 1) + 1;
|
||||||
|
x_offset_ = px_per_frame_ * (kHistorySize - 1) - available_rainbow_width_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RainbowDashAnalyzer::analyze(QPainter& p, const Analyzer::Scope& s,
|
||||||
|
bool new_frame) {
|
||||||
|
// Discard the second half of the transform
|
||||||
|
const int scope_size = s.size() / 2;
|
||||||
|
|
||||||
|
if ((new_frame && is_playing_) ||
|
||||||
|
(buffer_[0].isNull() && buffer_[1].isNull())) {
|
||||||
|
// Transform the music into rainbows!
|
||||||
|
for (int band = 0; band < kRainbowBands; ++band) {
|
||||||
|
float* band_start = history_ + band * kHistorySize;
|
||||||
|
|
||||||
|
// Move the history of each band across by 1 frame.
|
||||||
|
memmove(band_start, band_start + 1, (kHistorySize - 1) * sizeof(float));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now accumulate the scope data into each band. Should maybe use a series
|
||||||
|
// of band pass filters for this, so bands can leak into neighbouring bands,
|
||||||
|
// but for now it's a series of separate square filters.
|
||||||
|
const int samples_per_band = scope_size / kRainbowBands;
|
||||||
|
int sample = 0;
|
||||||
|
for (int band = 0; band < kRainbowBands; ++band) {
|
||||||
|
float accumulator = 0.0;
|
||||||
|
for (int i = 0; i < samples_per_band; ++i) {
|
||||||
|
accumulator += s[sample++];
|
||||||
|
}
|
||||||
|
history_[(band + 1) * kHistorySize - 1] = accumulator * band_scale_[band];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create polylines for the rainbows.
|
||||||
|
QPointF polyline[kRainbowBands * kHistorySize];
|
||||||
|
QPointF* dest = polyline;
|
||||||
|
float* source = history_;
|
||||||
|
|
||||||
|
const float top_of_Dash = static_cast<float>(height()) / 2 - static_cast<float>(kRainbowHeight) / 2;
|
||||||
|
for (int band = 0; band < kRainbowBands; ++band) {
|
||||||
|
// Calculate the Y position of this band.
|
||||||
|
const float y =
|
||||||
|
static_cast<float>(kRainbowHeight) / (kRainbowBands + 1) * (band + 0.5) +
|
||||||
|
top_of_Dash;
|
||||||
|
|
||||||
|
// Add each point in the line.
|
||||||
|
for (int x = 0; x < kHistorySize; ++x) {
|
||||||
|
*dest = QPointF(px_per_frame_ * x, y + *source * kPixelScale);
|
||||||
|
++dest;
|
||||||
|
++source;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do we have to draw the whole rainbow into the buffer?
|
||||||
|
if (buffer_[0].isNull()) {
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
buffer_[i] = QPixmap(QSize(width() + x_offset_, height()));
|
||||||
|
buffer_[i].fill(background_brush_.color());
|
||||||
|
}
|
||||||
|
current_buffer_ = 0;
|
||||||
|
|
||||||
|
QPainter buffer_painter(&buffer_[0]);
|
||||||
|
buffer_painter.setRenderHint(QPainter::Antialiasing);
|
||||||
|
for (int band = kRainbowBands - 1; band >= 0; --band) {
|
||||||
|
buffer_painter.setPen(colors_[band]);
|
||||||
|
buffer_painter.drawPolyline(&polyline[band * kHistorySize],
|
||||||
|
kHistorySize);
|
||||||
|
buffer_painter.drawPolyline(&polyline[band * kHistorySize],
|
||||||
|
kHistorySize);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const int last_buffer = current_buffer_;
|
||||||
|
current_buffer_ = (current_buffer_ + 1) % 2;
|
||||||
|
|
||||||
|
// We can just shuffle the buffer along a bit and draw the new frame's
|
||||||
|
// data.
|
||||||
|
QPainter buffer_painter(&buffer_[current_buffer_]);
|
||||||
|
buffer_painter.setRenderHint(QPainter::Antialiasing);
|
||||||
|
|
||||||
|
buffer_painter.drawPixmap(
|
||||||
|
0, 0, buffer_[last_buffer], px_per_frame_, 0,
|
||||||
|
x_offset_ + available_rainbow_width_ - px_per_frame_, 0);
|
||||||
|
buffer_painter.fillRect(
|
||||||
|
x_offset_ + available_rainbow_width_ - px_per_frame_, 0,
|
||||||
|
kDashWidth - kRainbowOverlap + px_per_frame_, height(),
|
||||||
|
background_brush_);
|
||||||
|
|
||||||
|
for (int band = kRainbowBands - 1; band >= 0; --band) {
|
||||||
|
buffer_painter.setPen(colors_[band]);
|
||||||
|
buffer_painter.drawPolyline(&polyline[(band + 1) * kHistorySize - 3],
|
||||||
|
3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the buffer on to the widget
|
||||||
|
p.drawPixmap(0, 0, buffer_[current_buffer_], x_offset_, 0, 0, 0);
|
||||||
|
|
||||||
|
if (!is_playing_) {
|
||||||
|
// Ssshhh!
|
||||||
|
p.drawPixmap(SleepingDashDestRect(), dash_, SleepingDashSourceRect());
|
||||||
|
} else {
|
||||||
|
p.drawPixmap(DashDestRect(), dash_, DashSourceRect());
|
||||||
|
}
|
||||||
|
}
|
108
src/analyzers/rainbowdashanalyzer.h
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/* This file is part of Clementine.
|
||||||
|
Copyright 2014, Alibek Omarov <a1ba.omarov@gmail.com>
|
||||||
|
Copyright 2014, Mark Furneaux <mark@romaco.ca>
|
||||||
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
|
|
||||||
|
Clementine 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.
|
||||||
|
|
||||||
|
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ANALYZERS_RAINBOWDASHANALYZER_H_
|
||||||
|
#define ANALYZERS_RAINBOWDASHANALYZER_H_
|
||||||
|
|
||||||
|
#include "analyzerbase.h"
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
class RainbowDashAnalyzer : public Analyzer::Base {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
Q_INVOKABLE RainbowDashAnalyzer(QWidget* parent);
|
||||||
|
|
||||||
|
static const char* kName;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void transform(Analyzer::Scope&);
|
||||||
|
void analyze(QPainter& p, const Analyzer::Scope&, bool new_frame);
|
||||||
|
|
||||||
|
void timerEvent(QTimerEvent* e);
|
||||||
|
void resizeEvent(QResizeEvent* e);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const int kDashHeight = 33;
|
||||||
|
static const int kDashWidth = 53;
|
||||||
|
static const int kRainbowHeight = 16;
|
||||||
|
static const int kDashFrameCount = 16;
|
||||||
|
static const int kRainbowOverlap = 15;
|
||||||
|
static const int kSleepingDashHeight = 33;
|
||||||
|
|
||||||
|
static const int kHistorySize = 128;
|
||||||
|
static const int kRainbowBands = 6;
|
||||||
|
static const float kPixelScale;
|
||||||
|
|
||||||
|
static const int kFrameIntervalMs = 150;
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline QRect DashSourceRect() const {
|
||||||
|
return QRect(0, kDashHeight * frame_, kDashWidth, kDashHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QRect SleepingDashSourceRect() const {
|
||||||
|
return QRect(0, kDashHeight * kDashFrameCount, kDashWidth,
|
||||||
|
kSleepingDashHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QRect DashDestRect() const {
|
||||||
|
return QRect(width() - kDashWidth, (height() - kDashHeight) / 2, kDashWidth,
|
||||||
|
kDashHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QRect SleepingDashDestRect() const {
|
||||||
|
return QRect(width() - kDashWidth, (height() - kSleepingDashHeight) / 2,
|
||||||
|
kDashWidth, kSleepingDashHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// "constants" that get initialised in the constructor
|
||||||
|
float band_scale_[kRainbowBands];
|
||||||
|
QPen colors_[kRainbowBands];
|
||||||
|
|
||||||
|
QPixmap dash_;
|
||||||
|
|
||||||
|
// For the animation
|
||||||
|
int timer_id_;
|
||||||
|
int frame_;
|
||||||
|
|
||||||
|
// The y positions of each point on the rainbow.
|
||||||
|
float history_[kHistorySize * kRainbowBands];
|
||||||
|
|
||||||
|
// A cache of the last frame's rainbow, so it can be used in the next frame.
|
||||||
|
QPixmap buffer_[2];
|
||||||
|
int current_buffer_;
|
||||||
|
|
||||||
|
// Geometry information that's updated on resize:
|
||||||
|
// The width of the widget minus the space for the pony
|
||||||
|
int available_rainbow_width_;
|
||||||
|
|
||||||
|
// X spacing between each point in the polyline.
|
||||||
|
int px_per_frame_;
|
||||||
|
|
||||||
|
// Amount the buffer_ is shifted to the left (off the edge of the widget) to
|
||||||
|
// make the rainbow extend from 0 to available_rainbow_width_.
|
||||||
|
int x_offset_;
|
||||||
|
|
||||||
|
QBrush background_brush_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ANALYZERS_RAINBOWDASHANALYZER_H_
|
@ -1,15 +1,26 @@
|
|||||||
//
|
/* This file is part of Clementine.
|
||||||
//
|
Copyright 2004, Melchior FRANZ <mfranz@kde.org>
|
||||||
// C++ Implementation: Sonogram
|
Copyright 2009-2010, David Sansome <davidsansome@gmail.com>
|
||||||
//
|
Copyright 2010, 2014, John Maguire <john.maguire@gmail.com>
|
||||||
// Description:
|
Copyright 2014, Mark Furneaux <mark@romaco.ca>
|
||||||
//
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
//
|
|
||||||
// Author: Melchior FRANZ <mfranz@kde.org>, (C) 2004
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
//
|
it under the terms of the GNU General Public License as published by
|
||||||
// Copyright: See COPYING file that comes with this distribution
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
//
|
(at your option) any later version.
|
||||||
//
|
|
||||||
|
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Original Author: Melchior FRANZ <mfranz@kde.org> 2004
|
||||||
|
*/
|
||||||
|
|
||||||
#include "sonogram.h"
|
#include "sonogram.h"
|
||||||
|
|
||||||
@ -53,9 +64,9 @@ void Sonogram::analyze(QPainter& p, const Scope& s, bool new_frame) {
|
|||||||
if (it >= end || *it < .005)
|
if (it >= end || *it < .005)
|
||||||
c = palette().color(QPalette::Background);
|
c = palette().color(QPalette::Background);
|
||||||
else if (*it < .05)
|
else if (*it < .05)
|
||||||
c.setHsv(95, 255, 255 - int(*it * 4000.0));
|
c.setHsv(95, 255, 255 - static_cast<int>(*it * 4000.0));
|
||||||
else if (*it < 1.0)
|
else if (*it < 1.0)
|
||||||
c.setHsv(95 - int(*it * 90.0), 255, 255);
|
c.setHsv(95 - static_cast<int>(*it * 90.0), 255, 255);
|
||||||
else
|
else
|
||||||
c = Qt::red;
|
c = Qt::red;
|
||||||
|
|
||||||
|
@ -1,18 +1,28 @@
|
|||||||
//
|
/* This file is part of Clementine.
|
||||||
//
|
Copyright 2004, Melchior FRANZ <mfranz@kde.org>
|
||||||
// C++ Interface: Sonogram
|
Copyright 2009-2010, David Sansome <davidsansome@gmail.com>
|
||||||
//
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
// Description:
|
Copyright 2014, John Maguire <john.maguire@gmail.com>
|
||||||
//
|
|
||||||
//
|
|
||||||
// Author: Melchior FRANZ <mfranz@kde.org>, (C) 2004
|
|
||||||
//
|
|
||||||
// Copyright: See COPYING file that comes with this distribution
|
|
||||||
//
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef SONOGRAM_H
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
#define SONOGRAM_H
|
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.
|
||||||
|
|
||||||
|
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Original Author: Melchior FRANZ <mfranz@kde.org> 2004
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ANALYZERS_SONOGRAM_H_
|
||||||
|
#define ANALYZERS_SONOGRAM_H_
|
||||||
|
|
||||||
#include "analyzerbase.h"
|
#include "analyzerbase.h"
|
||||||
|
|
||||||
@ -37,4 +47,4 @@ class Sonogram : public Analyzer::Base {
|
|||||||
QPixmap canvas_;
|
QPixmap canvas_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // ANALYZERS_SONOGRAM_H_
|
||||||
|
@ -1,11 +1,28 @@
|
|||||||
//
|
/* This file is part of Clementine.
|
||||||
// Amarok BarAnalyzer 3 - Jet Turbine: Symmetric version of analyzer 1
|
Copyright 2003, Stanislav Karchebny <berkus@users.sf.net>
|
||||||
//
|
Copyright 2003, Max Howell <max.howell@methylblue.com>
|
||||||
// Author: Stanislav Karchebny <berkus@users.sf.net>, (C) 2003
|
Copyright 2009-2010, David Sansome <davidsansome@gmail.com>
|
||||||
// Max Howell (I modified it to use boom analyzer code)
|
Copyright 2014, Mark Furneaux <mark@romaco.ca>
|
||||||
//
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
// Copyright: like rest of Amarok
|
Copyright 2014, John Maguire <john.maguire@gmail.com>
|
||||||
//
|
|
||||||
|
Clementine 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.
|
||||||
|
|
||||||
|
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Original Author: Stanislav Karchebny <berkus@users.sf.net> 2003
|
||||||
|
* Original Author: Max Howell <max.howell@methylblue.com> 2003
|
||||||
|
*/
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
@ -41,8 +58,9 @@ void TurbineAnalyzer::analyze(QPainter& p, const Scope& scope, bool new_frame) {
|
|||||||
if (h > peak_height[i]) {
|
if (h > peak_height[i]) {
|
||||||
peak_height[i] = h;
|
peak_height[i] = h;
|
||||||
peak_speed[i] = 0.01;
|
peak_speed[i] = 0.01;
|
||||||
} else
|
} else {
|
||||||
goto peak_handling;
|
goto peak_handling;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (bar_height[i] > 0.0) {
|
if (bar_height[i] > 0.0) {
|
||||||
bar_height[i] -= K_barHeight; // 1.4
|
bar_height[i] -= K_barHeight; // 1.4
|
||||||
@ -60,15 +78,16 @@ void TurbineAnalyzer::analyze(QPainter& p, const Scope& scope, bool new_frame) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
y = hd2 - uint(bar_height[i]);
|
y = hd2 - static_cast<uint>(bar_height[i]);
|
||||||
canvas_painter.drawPixmap(x + 1, y, barPixmap, 0, y, -1, -1);
|
canvas_painter.drawPixmap(x + 1, y, barPixmap, 0, y, -1, -1);
|
||||||
canvas_painter.drawPixmap(x + 1, hd2, barPixmap, 0, int(bar_height[i]), -1,
|
canvas_painter.drawPixmap(x + 1, hd2, barPixmap, 0,
|
||||||
-1);
|
static_cast<int>(bar_height[i]),
|
||||||
|
-1, -1);
|
||||||
|
|
||||||
canvas_painter.setPen(palette().color(QPalette::Highlight));
|
canvas_painter.setPen(palette().color(QPalette::Highlight));
|
||||||
if (bar_height[i] > 0)
|
if (bar_height[i] > 0)
|
||||||
canvas_painter.drawRect(x, y, COLUMN_WIDTH - 1,
|
canvas_painter.drawRect(x, y, COLUMN_WIDTH - 1,
|
||||||
(int)bar_height[i] * 2 - 1);
|
static_cast<int>(bar_height[i]) * 2 - 1);
|
||||||
|
|
||||||
const uint x2 = x + COLUMN_WIDTH - 1;
|
const uint x2 = x + COLUMN_WIDTH - 1;
|
||||||
canvas_painter.setPen(palette().color(QPalette::Base));
|
canvas_painter.setPen(palette().color(QPalette::Base));
|
||||||
|
@ -1,13 +1,28 @@
|
|||||||
//
|
/* This file is part of Clementine.
|
||||||
// Amarok BarAnalyzer 3 - Jet Turbine: Symmetric version of analyzer 1
|
Copyright 2003, Stanislav Karchebny <berkus@users.sf.net>
|
||||||
//
|
Copyright 2009-2010, David Sansome <davidsansome@gmail.com>
|
||||||
// Author: Stanislav Karchebny <berkus@users.sf.net>, (C) 2003
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
//
|
Copyright 2014, John Maguire <john.maguire@gmail.com>
|
||||||
// Copyright: like rest of Amarok
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef ANALYZER_TURBINE_H
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
#define ANALYZER_TURBINE_H
|
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.
|
||||||
|
|
||||||
|
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Original Author: Stanislav Karchebny <berkus@users.sf.net> 2003
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ANALYZERS_TURBINE_H_
|
||||||
|
#define ANALYZERS_TURBINE_H_
|
||||||
|
|
||||||
#include "boomanalyzer.h"
|
#include "boomanalyzer.h"
|
||||||
|
|
||||||
@ -21,4 +36,4 @@ class TurbineAnalyzer : public BoomAnalyzer {
|
|||||||
static const char* kName;
|
static const char* kName;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // ANALYZERS_TURBINE_H_
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#cmakedefine HAVE_LIBPULSE
|
#cmakedefine HAVE_LIBPULSE
|
||||||
#cmakedefine HAVE_MOODBAR
|
#cmakedefine HAVE_MOODBAR
|
||||||
#cmakedefine HAVE_QCA
|
#cmakedefine HAVE_QCA
|
||||||
|
#cmakedefine HAVE_SEAFILE
|
||||||
#cmakedefine HAVE_SKYDRIVE
|
#cmakedefine HAVE_SKYDRIVE
|
||||||
#cmakedefine HAVE_SPARKLE
|
#cmakedefine HAVE_SPARKLE
|
||||||
#cmakedefine HAVE_SPOTIFY_DOWNLOADER
|
#cmakedefine HAVE_SPOTIFY_DOWNLOADER
|
||||||
@ -44,5 +45,6 @@
|
|||||||
#cmakedefine TAGLIB_HAS_OPUS
|
#cmakedefine TAGLIB_HAS_OPUS
|
||||||
#cmakedefine USE_INSTALL_PREFIX
|
#cmakedefine USE_INSTALL_PREFIX
|
||||||
#cmakedefine USE_SYSTEM_PROJECTM
|
#cmakedefine USE_SYSTEM_PROJECTM
|
||||||
|
#cmakedefine USE_SYSTEM_SHA2
|
||||||
|
|
||||||
#endif // CONFIG_H_IN
|
#endif // CONFIG_H_IN
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
/* This file is part of Clementine.
|
/* This file is part of Clementine.
|
||||||
Copyright 2012, David Sansome <me@davidsansome.com>
|
Copyright 2012, Arnaud Bienner <arnaud.bienner@gmail.com>
|
||||||
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
|
Copyright 2014, John Maguire <john.maguire@gmail.com>
|
||||||
|
|
||||||
Clementine is free software: you can redistribute it and/or modify
|
Clementine 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
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
/* This file is part of Clementine.
|
/* This file is part of Clementine.
|
||||||
Copyright 2012, David Sansome <me@davidsansome.com>
|
Copyright 2012, Arnaud Bienner <arnaud.bienner@gmail.com>
|
||||||
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||||
|
Copyright 2014, John Maguire <john.maguire@gmail.com>
|
||||||
|
|
||||||
Clementine is free software: you can redistribute it and/or modify
|
Clementine 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
|
||||||
@ -15,15 +17,15 @@
|
|||||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef APPEARANCE_H
|
#ifndef CORE_APPEARANCE_H_
|
||||||
#define APPEARANCE_H
|
#define CORE_APPEARANCE_H_
|
||||||
|
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <QPalette>
|
#include <QPalette>
|
||||||
|
|
||||||
class Appearance : public QObject {
|
class Appearance : public QObject {
|
||||||
public:
|
public:
|
||||||
Appearance(QObject* parent = nullptr);
|
explicit Appearance(QObject* parent = nullptr);
|
||||||
// Load the user preferred theme, which could the default system theme or a
|
// Load the user preferred theme, which could the default system theme or a
|
||||||
// custom set of colors that user has chosen
|
// custom set of colors that user has chosen
|
||||||
void LoadUserTheme();
|
void LoadUserTheme();
|
||||||
@ -42,4 +44,4 @@ class Appearance : public QObject {
|
|||||||
QColor background_color_;
|
QColor background_color_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // APPEARANCE_H
|
#endif // CORE_APPEARANCE_H_
|
||||||
|