Remove lame usage, its not actually required for audio cd playback!

This commit is contained in:
craig.p.drummond
2013-07-12 19:29:34 +00:00
parent 9df7ad18c4
commit 83faed9837
8 changed files with 85 additions and 117 deletions

View File

@@ -36,7 +36,6 @@ option(ENABLE_OVERLAYSCROLLBARS "Enable support for overlay style scrollbars whe
option(ENABLE_CDPARANOIA "Enable CDParanoia libraries(required for AudioCD support)" ON)
option(ENABLE_CDDB "Enable CDDB libraries(either this or MusicBrianz required for AudioCD support)" ON)
option(ENABLE_MUSICBRAINZ "Enable MusicBrianz libraries(either this or CDDB required for AudioCD support)" ON)
option(ENABLE_LAME "Enable LAME libraries(required for AudioCD playback support)" ON)
option(ENABLE_PROXY_CONFIG "Enable proxy config in settings dialog" OFF)
if (ENABLE_QT5)
@@ -148,9 +147,6 @@ if (ENABLE_TAGLIB)
if (ENABLE_MUSICBRAINZ)
find_package(MusicBrainz5)
endif (ENABLE_MUSICBRAINZ)
if (ENABLE_LAME)
find_package(Lame)
endif (ENABLE_LAME)
endif (CDPARANOIA_FOUND)
endif (TAGLIB_FOUND AND ENABLE_CDPARANOIA)
endif (ENABLE_TAGLIB)
@@ -495,13 +491,9 @@ else (WIN32)
target_link_libraries(cantata ${MUSICBRAINZ5_LIBRARIES})
include_directories(${MUSICBRAINZ5_INCLUDE_DIR})
endif (MUSICBRAINZ5_FOUND)
if (LAME_FOUND)
target_link_libraries(cantata ${LAME_LIBS})
include_directories(${LAME_INCLUDE_DIR})
if (ENABLE_KDE_SUPPORT)
install(FILES cantata-play-audiocd.desktop DESTINATION ${DATA_INSTALL_DIR}/solid/actions)
endif (ENABLE_KDE_SUPPORT)
endif (LAME_FOUND)
if (ENABLE_KDE_SUPPORT)
install(FILES cantata-play-audiocd.desktop DESTINATION ${DATA_INSTALL_DIR}/solid/actions)
endif (ENABLE_KDE_SUPPORT)
endif (CDDB_FOUND OR MUSICBRAINZ5_FOUND)
endif (WIN32)
@@ -584,9 +576,6 @@ if (TAGLIB_FOUND)
endif (MTP_FOUND)
if (CDDB_FOUND OR MUSICBRAINZ5_FOUND)
message(" - AudioCD")
if (LAME_FOUND)
message(" - AudioCD playback via MP3")
endif (LAME_FOUND)
endif (CDDB_FOUND OR MUSICBRAINZ5_FOUND)
if (ENABLE_REMOTE_DEVICES)
message(" - Remote device sync (EXPERIMENTAL)")
@@ -602,7 +591,7 @@ if (TAGLIB_FOUND)
endif (ENABLE_PROXY_CONFIG)
endif (ENABLE_REMOTE_DEVICES OR ENABLE_HTTP_STREAM_PLAYBACK OR AUDIOCD_SUPPORT OR MTP_FOUND OR ENABLE_PROXY_CONFIG OR ENABLE_REPLAYGAIN_SUPPORT)
if (NOT TAGLIB_FOUND OR NOT MTP_FOUND OR NOT AUDIOCD_SUPPORT OR NOT ENABLE_REPLAYGAIN_SUPPORT OR NOT ENABLE_HTTP_STREAM_PLAYBACK OR NOT ENABLE_REMOTE_DEVICES OR (NOT ENABLE_PROXY_CONFIG AND NOT ENABLE_KDE_SUPPORT) OR (AUDIOCD_SUPPORT AND NOT LAME_FOUND))
if (NOT TAGLIB_FOUND OR NOT MTP_FOUND OR NOT AUDIOCD_SUPPORT OR NOT ENABLE_REPLAYGAIN_SUPPORT OR NOT ENABLE_HTTP_STREAM_PLAYBACK OR NOT ENABLE_REMOTE_DEVICES OR (NOT ENABLE_PROXY_CONFIG AND NOT ENABLE_KDE_SUPPORT))
message(" Disabled features:")
if (NOT ENABLE_HTTP_STREAM_PLAYBACK)
message(" - MPD HTTP stream playback (Phonon required for Qt4, QtMultiMedia for Qt5)")
@@ -613,9 +602,6 @@ if (TAGLIB_FOUND)
if (NOT AUDIOCD_SUPPORT AND NOT WIN32)
message(" - AudioCD (libcdparanoia and libcddb/libmusicbrainz5 required)")
endif (NOT AUDIOCD_SUPPORT AND NOT WIN32)
if (AUDIOCD_SUPPORT AND NOT LAME_FOUND)
message(" - AudioCD playback via MP3 (liblame required)")
endif (AUDIOCD_SUPPORT AND NOT LAME_FOUND)
if (NOT ENABLE_REMOTE_DEVICES)
message(" - Remote device sync (EXPERIMENTAL)")
endif (NOT ENABLE_REMOTE_DEVICES)
@@ -625,7 +611,7 @@ if (TAGLIB_FOUND)
if (NOT ENABLE_PROXY_CONFIG AND NOT ENABLE_KDE_SUPPORT)
message(" - Proxy configuration")
endif (NOT ENABLE_PROXY_CONFIG AND NOT ENABLE_KDE_SUPPORT)
endif (NOT TAGLIB_FOUND OR NOT MTP_FOUND OR NOT AUDIOCD_SUPPORT OR NOT ENABLE_REPLAYGAIN_SUPPORT OR NOT ENABLE_HTTP_STREAM_PLAYBACK OR NOT ENABLE_REMOTE_DEVICES OR (NOT ENABLE_PROXY_CONFIG AND NOT ENABLE_KDE_SUPPORT) OR (AUDIOCD_SUPPORT AND NOT LAME_FOUND))
endif (NOT TAGLIB_FOUND OR NOT MTP_FOUND OR NOT AUDIOCD_SUPPORT OR NOT ENABLE_REPLAYGAIN_SUPPORT OR NOT ENABLE_HTTP_STREAM_PLAYBACK OR NOT ENABLE_REMOTE_DEVICES OR (NOT ENABLE_PROXY_CONFIG AND NOT ENABLE_KDE_SUPPORT))
else (TAGLIB_FOUND)

View File

@@ -113,6 +113,7 @@
71. Allow seeking in cantata HTTP streams.
72. Default to enabling use of media keys under GNOME/Unity.
73. Add SoundCloud to online services.
74. Drop usage of lame when playing back AudioCDs, its not required.
1.0.3
-----

21
README
View File

@@ -19,17 +19,16 @@ Cantata requires the following Qt libraries:
Cantata may also use the following optional libraries:
1. KDElibs4
2. TagLib - Tag edit dialog, replaygain, track organizer, and UMS device
support.
3. LibMTP - MTP devices.
4. FFMPEG (libavcodec) - ReplayGain detection code.
5. SpeexDSP - ReplayGain detection code.
6. MPG123 - ReplayGain detection code.
7. CDParanoia - Read/rip Audio CDs.
8. CDDB - either this or MusicBrainz5 required for Audio CDs
9. MusicBrainz5 - either this or CDDB required for Audio CDs
10. Lame - Encode Audio CD streams when sent via HTTP server.
1. KDElibs4
2. TagLib - Tag edit dialog, replaygain, track organizer, and UMS device
support.
3. LibMTP - MTP devices.
4. FFMPEG (libavcodec) - ReplayGain detection code.
5. SpeexDSP - ReplayGain detection code.
6. MPG123 - ReplayGain detection code.
7. CDParanoia - Read/rip Audio CDs.
8. CDDB - either this or MusicBrainz5 required for Audio CDs
9. MusicBrainz5 - either this or CDDB required for Audio CDs
Translations

View File

@@ -1,14 +0,0 @@
# - Try to find LAME
# Once done this will define
#
# LAME_FOUND - system has UDev
# LAME_INCLUDE_DIR - the libudev include directory
# LAME_LIBS - The libudev libraries
find_path(LAME_INCLUDE_DIR lame/lame.h)
find_library(LAME_LIBS mp3lame)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LAME DEFAULT_MSG LAME_INCLUDE_DIR LAME_LIBS)
mark_as_advanced(LAME_INCLUDE_DIR LAME_LIBS)

View File

@@ -25,7 +25,6 @@
#cmakedefine ENABLE_HTTP_STREAM_PLAYBACK 1
#cmakedefine FFMPEG_FOUND 1
#cmakedefine MPG123_FOUND 1
#cmakedefine LAME_FOUND 1
#cmakedefine CDDB_FOUND 1
#cmakedefine MUSICBRAINZ5_FOUND 1
#cmakedefine USE_SPEEX_RESAMPLER 1

View File

@@ -32,22 +32,37 @@
#include <QProcess>
#include <QFile>
void ExtractJob::writeWavHeader(QIODevice &dev)
const int ExtractJob::constWavHeaderSize=44; // ffmpeg uses 46 byte header?
static void insertSize(unsigned char *data, qint32 size)
{
static const unsigned char riffHeader[] = {
data[0]=(size&0x000000ff);
data[1]=(size&0x0000ff00)>>8;
data[2]=(size&0x00ff0000)>>16;
data[3]=(size&0xff000000)>>24;
}
void ExtractJob::writeWavHeader(QIODevice &dev, qint32 size)
{
unsigned char riffHeader[] = {
0x52, 0x49, 0x46, 0x46, // 0 "RIFF"
0x00, 0x00, 0x00, 0x00, // 4 wavSize
0x57, 0x41, 0x56, 0x45, // 8 "WAVE"
0x66, 0x6d, 0x74, 0x20, // 12 "fmt "
0x10, 0x00, 0x00, 0x00, // 16
0x01, 0x00, 0x02, 0x00, // 20
0x44, 0xac, 0x00, 0x00, // 24
0x10, 0xb1, 0x02, 0x00, // 28
0x04, 0x00, 0x10, 0x00, // 32
0x64, 0x61, 0x74, 0x61, // 36 "data"
0x10, 0x00, 0x00, 0x00, // 16 Size of WAVE section chunk (ffmpeg has 12 here???)
0x01, 0x00, 0x02, 0x00, // 20 WAVE type format / Number of channels
0x44, 0xac, 0x00, 0x00, // 24 Samples per second
0x10, 0xb1, 0x02, 0x00, // 28 Bytes per second
0x04, 0x00, 0x10, 0x00, // 32 Block alignment / Bits per sample
0x64, 0x61, 0x74, 0x61, // 36 "data" (ffmpeg preceeds this with two 0 bytes)
0x00, 0x00, 0x00, 0x00 // 40 byteCount
};
if (0!=size) {
insertSize(&riffHeader[4], (size+constWavHeaderSize)-8);
insertSize(&riffHeader[40], size);
}
dev.write((char*)riffHeader, 44);
}

View File

@@ -32,7 +32,8 @@ class ExtractJob : public FileJob
{
Q_OBJECT
public:
static void writeWavHeader(QIODevice &dev);
static const int constWavHeaderSize;
static void writeWavHeader(QIODevice &dev, qint32 size=0);
explicit ExtractJob(const Encoders::Encoder &enc, int val, const QString &src, const QString &dest, const Song &s, const QString &cover);
virtual ~ExtractJob();

View File

@@ -28,9 +28,6 @@
#if defined CDDB_FOUND || defined MUSICBRAINZ5_FOUND
#include "cdparanoia.h"
#include "extractjob.h"
#ifdef LAME_FOUND
#include "lame/lame.h"
#endif
#endif
#include <QTcpSocket>
#include <QNetworkInterface>
@@ -128,18 +125,20 @@ static QString detectMimeType(const QString &file)
return QString();
}
static void writeMimeType(const QString &mimeType, QTcpSocket *socket, qint64 size=0)
static void writeMimeType(const QString &mimeType, QTcpSocket *socket, qint32 size, bool allowSeek)
{
if (!mimeType.isEmpty()) {
QTextStream os(socket);
os.setAutoDetectUnicode(true);
if (size>0) {
if (allowSeek) {
os << "HTTP/1.0 200 OK"
<< "\r\nAccept-Ranges: bytes"
<< "\r\nContent-Length: " << QString::number(size)
<< "\r\nContent-Type: " << mimeType << "\r\n\r\n";
} else {
os << "HTTP/1.0 200 OK\r\nContent-Type: " << mimeType << "\r\n\r\n";
os << "HTTP/1.0 200 OK"
<< "\r\nContent-Length: " << QString::number(size)
<< "\r\nContent-Type: " << mimeType << "\r\n\r\n";
}
}
}
@@ -198,7 +197,7 @@ static bool isFromMpd(const QStringList &params)
return false;
}
static void getRange(const QStringList &params, qint64 &from, qint64 &to)
static void getRange(const QStringList &params, qint32 &from, qint32 &to)
{
foreach (const QString &str, params) {
if (str.startsWith("Range:")) {
@@ -206,10 +205,10 @@ static void getRange(const QStringList &params, qint64 &from, qint64 &to)
if (start>0) {
QStringList range=str.mid(start+6).split("-", QString::SkipEmptyParts);
if (1==range.length()) {
from=range.at(0).toLongLong();
from=range.at(0).toLong();
} else if (2==range.length()) {
from=range.at(0).toLongLong();
to=range.at(1).toLongLong();
from=range.at(0).toLong();
to=range.at(1).toLong();
}
}
break;
@@ -327,6 +326,9 @@ void HttpSocket::readClient()
QUrlQuery q(url);
#endif
bool ok=false;
qint32 readBytesFrom=0;
qint32 readBytesTo=0;
getRange(params, readBytesFrom, readBytesTo);
if (q.hasQueryItem("cantata")) {
Song song=HttpServer::self()->decodeUrl(url);
@@ -340,32 +342,21 @@ void HttpSocket::readClient()
if (cdparanoia) {
int firstSector = cdparanoia.firstSectorOfTrack(song.id);
int lastSector = cdparanoia.lastSectorOfTrack(song.id);
qint32 totalSize = ((lastSector-firstSector)+1)*CD_FRAMESIZE_RAW;
int count = 0;
//int bytesToDiscard = 0; // Number of bytes to discard in first read sector due to range request in HTTP header
//if (readBytesFrom>0) {
// int sectorsToSeek=readBytesFrom/CD_FRAMESIZE_RAW;
// firstSector+=sectorsToSeek;
// bytesToDiscard=readBytesFrom-(sectorsToSeek*CD_FRAMESIZE_RAW);
//}
cdparanoia.seek(firstSector, SEEK_SET);
ok=true;
#ifdef LAME_FOUND
static const int constMp3BufferSize=CD_FRAMESIZE_RAW*2*sizeof(short int);
static const int constPcmSize=CD_FRAMESIZE_RAW/(2*sizeof(short int));
unsigned char mp3Buffer[constMp3BufferSize];
lame_global_flags *lame = lame_init();
lame_set_num_channels(lame, 2);
lame_set_in_samplerate(lame, 44100);
lame_set_brate(lame, 128);
lame_set_quality(lame, 5);
lame_set_VBR(lame, vbr_off);
if (-1!=lame_init_params(lame)) {
writeMimeType(QLatin1String("audio/mpeg"), socket);
} else {
lame_close(lame);
lame=0;
}
if (!lame) {
#endif
writeMimeType(QLatin1String("audio/x-wav"), socket);
ExtractJob::writeWavHeader(*socket);
#ifdef LAME_FOUND
}
#endif
writeMimeType(QLatin1String("audio/x-wav"), socket, totalSize+ExtractJob::constWavHeaderSize, false);
//if (0==readBytesFrom) { // Only write header if we are no seeking...
ExtractJob::writeWavHeader(*socket, totalSize);
//}
bool stop=false;
while (!terminated && (firstSector+count) <= lastSector && !stop) {
qint16 *buf = cdparanoia.read();
@@ -373,18 +364,17 @@ void HttpSocket::readClient()
break;
}
char *buffer=(char *)buf;
qint64 writePos=0;
qint64 toWrite=CD_FRAMESIZE_RAW;
qint32 writePos=0;
qint32 toWrite=CD_FRAMESIZE_RAW;
#ifdef LAME_FOUND
if (lame) {
toWrite=lame_encode_buffer_interleaved(lame, (short *)buffer, constPcmSize, mp3Buffer, constMp3BufferSize);
buffer=(char *)mp3Buffer;
}
#endif
//if (0==count && bytesToDiscard) {
// writePos=bytesToDiscard;
// toWrite-=bytesToDiscard;
// bytesToDiscard=0;
//}
do {
qint64 bytesWritten=socket->write(&buffer[writePos], toWrite - writePos);
qint32 bytesWritten=socket->write(&buffer[writePos], toWrite - writePos);
if (terminated || -1==bytesWritten) {
stop=true;
break;
@@ -394,41 +384,32 @@ void HttpSocket::readClient()
} while (!terminated && writePos<toWrite);
count++;
}
#ifdef LAME_FOUND
if (lame) {
lame_close(lame);
lame=0;
}
#endif
}
}
#endif
} else {
QFile f(url.path());
if (f.open(QIODevice::ReadOnly)) {
qint64 from=0;
qint64 to=0;
qint64 totalBytes = f.size();
if (f.open(QIODevice::ReadOnly)) {
qint32 totalBytes = f.size();
getRange(params, from, to);
writeMimeType(detectMimeType(url.path()), socket, totalBytes);
writeMimeType(detectMimeType(url.path()), socket, totalBytes, true);
ok=true;
static const int constChunkSize=32768;
char buffer[constChunkSize];
qint64 readPos = 0;
qint64 bytesRead = 0;
qint32 readPos = 0;
qint32 bytesRead = 0;
bool stop=false;
if (0!=from) {
if (!f.seek(from)) {
if (0!=readBytesFrom) {
if (!f.seek(readBytesFrom)) {
ok=false;
}
bytesRead+=from;
bytesRead+=readBytesFrom;
}
if (0!=to && to>from && to!=totalBytes) {
totalBytes-=(totalBytes-to);
if (0!=readBytesTo && readBytesTo>readBytesFrom && readBytesTo!=totalBytes) {
totalBytes-=(totalBytes-readBytesTo);
}
if (ok) {
@@ -439,9 +420,9 @@ void HttpSocket::readClient()
break;
}
qint64 writePos=0;
qint32 writePos=0;
do {
qint64 bytesWritten = socket->write(&buffer[writePos], bytesRead - writePos);
qint32 bytesWritten = socket->write(&buffer[writePos], bytesRead - writePos);
if (terminated || -1==bytesWritten) {
stop=true;
break;