mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-04-13 12:31:52 +02:00
* Now supports FLAC playback.
This commit is contained in:
parent
484cab1553
commit
ebca511e43
@ -38,6 +38,7 @@ SET( tomahawkSources ${tomahawkSources}
|
||||
|
||||
audio/madtranscode.cpp
|
||||
audio/vorbistranscode.cpp
|
||||
audio/flactranscode.cpp
|
||||
audio/audioengine.cpp
|
||||
|
||||
utils/tomahawkutils.cpp
|
||||
@ -167,6 +168,7 @@ SET( tomahawkHeaders ${tomahawkHeaders}
|
||||
audio/transcodeinterface.h
|
||||
audio/madtranscode.h
|
||||
audio/vorbistranscode.h
|
||||
audio/flactranscode.h
|
||||
audio/audioengine.h
|
||||
|
||||
database/fuzzyindex.h
|
||||
|
@ -17,4 +17,5 @@ SET( OS_SPECIFIC_LINK_LIBRARIES
|
||||
mad
|
||||
vorbisfile
|
||||
ogg
|
||||
FLAC++
|
||||
)
|
||||
|
@ -10,6 +10,9 @@
|
||||
#ifndef NO_OGG
|
||||
#include "vorbistranscode.h"
|
||||
#endif
|
||||
#ifndef NO_FLAC
|
||||
#include "flactranscode.h"
|
||||
#endif
|
||||
|
||||
|
||||
AudioEngine::AudioEngine()
|
||||
@ -187,6 +190,12 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
|
||||
{
|
||||
m_transcode = QSharedPointer<TranscodeInterface>(new VorbisTranscode());
|
||||
}
|
||||
#endif
|
||||
#ifndef NO_FLAC
|
||||
else if ( m_currentTrack->mimetype() == "audio/flac" )
|
||||
{
|
||||
m_transcode = QSharedPointer<TranscodeInterface>(new FLACTranscode());
|
||||
}
|
||||
#endif
|
||||
else
|
||||
qDebug() << "Could NOT find suitable transcoder! Stopping audio.";
|
||||
|
150
src/audio/flactranscode.cpp
Normal file
150
src/audio/flactranscode.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
#include "flactranscode.h"
|
||||
|
||||
|
||||
FLACTranscode::FLACTranscode()
|
||||
: m_FLACInit( false )
|
||||
, m_FLACRunning( false )
|
||||
, m_finished( false )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
FLACTranscode::~FLACTranscode()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FLACTranscode::onSeek( int seconds )
|
||||
{
|
||||
QMutexLocker locker( &m_mutex );
|
||||
|
||||
m_buffer.clear();
|
||||
m_outBuffer.clear();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FLACTranscode::clearBuffers()
|
||||
{
|
||||
QMutexLocker locker( &m_mutex );
|
||||
|
||||
m_FLACInit = false;
|
||||
m_FLACRunning = false;
|
||||
m_finished = false;
|
||||
|
||||
m_buffer.clear();
|
||||
m_outBuffer.clear();
|
||||
|
||||
flush();
|
||||
reset();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FLACTranscode::processData( const QByteArray& data, bool finish )
|
||||
{
|
||||
m_mutex.lock();
|
||||
m_buffer.append( data );
|
||||
m_mutex.unlock();
|
||||
|
||||
if ( !m_FLACInit && m_buffer.size() > FLAC_BUFFER )
|
||||
{
|
||||
m_FLACInit = true;
|
||||
set_metadata_respond_all();
|
||||
process_single();
|
||||
}
|
||||
|
||||
while ( m_buffer.size() > FLAC_BUFFER / 2 )
|
||||
{
|
||||
process_single();
|
||||
}
|
||||
|
||||
m_finished = finish;
|
||||
}
|
||||
|
||||
|
||||
::FLAC__StreamDecoderReadStatus
|
||||
FLACTranscode::read_callback( FLAC__byte buffer[], size_t *bytes )
|
||||
{
|
||||
QMutexLocker locker( &m_mutex );
|
||||
|
||||
if ( *bytes > (unsigned int)m_buffer.size() )
|
||||
*bytes = m_buffer.size();
|
||||
|
||||
memcpy( buffer, (char*)m_buffer.data(), *bytes );
|
||||
m_buffer.remove( 0, *bytes );
|
||||
|
||||
if ( !*bytes )
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
|
||||
else
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
|
||||
::FLAC__StreamDecoderWriteStatus
|
||||
FLACTranscode::write_callback( const ::FLAC__Frame *frame, const FLAC__int32 *const buffer[] )
|
||||
{
|
||||
union PCMDATA
|
||||
{
|
||||
FLAC__int32 i;
|
||||
unsigned char b[2];
|
||||
} pcmDataLeft, pcmDataRight;
|
||||
|
||||
for ( unsigned int sample = 0; sample < frame->header.blocksize; sample++ )
|
||||
{
|
||||
pcmDataLeft.i = buffer[0][sample];
|
||||
pcmDataRight.i = buffer[1][sample];
|
||||
|
||||
m_outBuffer.append( pcmDataLeft.b[0] );
|
||||
m_outBuffer.append( pcmDataLeft.b[1] );
|
||||
m_outBuffer.append( pcmDataRight.b[0] );
|
||||
m_outBuffer.append( pcmDataRight.b[1] );
|
||||
}
|
||||
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FLACTranscode::metadata_callback( const ::FLAC__StreamMetadata *metadata )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
switch ( metadata->type )
|
||||
{
|
||||
case FLAC__METADATA_TYPE_STREAMINFO:
|
||||
{
|
||||
FLAC::Metadata::StreamInfo stream_info( (::FLAC__StreamMetadata *)metadata, true );
|
||||
|
||||
// Try to determine samplerate
|
||||
qDebug() << "FLACTranscode( BitsPerSample:" << stream_info.get_bits_per_sample() << "Samplerate:" << stream_info.get_sample_rate() << "Channels:" << stream_info.get_channels() << ")";
|
||||
emit streamInitialized( stream_info.get_sample_rate(), stream_info.get_channels() );
|
||||
|
||||
m_FLACRunning = true;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
qDebug() << "Not handling type:" << metadata->type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FLACTranscode::error_callback( ::FLAC__StreamDecoderErrorStatus status )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << status;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
FLACTranscode::eof_callback()
|
||||
{
|
||||
return ( m_buffer.isEmpty() && m_finished );
|
||||
}
|
71
src/audio/flactranscode.h
Normal file
71
src/audio/flactranscode.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*! \class FLACTranscode
|
||||
\brief Transcoding plugin for FLAC streams.
|
||||
*/
|
||||
|
||||
#ifndef FLAC_TRANSCODE_H
|
||||
#define FLAC_TRANSCODE_H
|
||||
|
||||
#include "transcodeinterface.h"
|
||||
|
||||
#include <FLAC/format.h>
|
||||
#include <FLAC++/decoder.h>
|
||||
#include <FLAC++/metadata.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QMutex>
|
||||
#include <QDebug>
|
||||
|
||||
#define FLAC_BUFFER 32768
|
||||
#define FLAC_BUFFER_PREFERRED 32768
|
||||
|
||||
class FLACTranscode : public TranscodeInterface , protected FLAC::Decoder::Stream
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FLACTranscode();
|
||||
~FLACTranscode();
|
||||
|
||||
const QStringList supportedTypes() const { QStringList l; l << "audio/flac" << "flac"; return l; }
|
||||
|
||||
int needData() { return FLAC_BUFFER - m_buffer.count(); }
|
||||
bool haveData() { return !m_outBuffer.isEmpty(); }
|
||||
|
||||
unsigned int preferredDataSize() { return FLAC_BUFFER_PREFERRED; }
|
||||
|
||||
QByteArray data() { QByteArray b = m_outBuffer; m_outBuffer.clear(); return b; }
|
||||
|
||||
QMutex* mutex() { return &m_mutex; }
|
||||
QByteArray* buffer() { return &m_buffer; }
|
||||
|
||||
signals:
|
||||
void streamInitialized( long sampleRate, int channels );
|
||||
|
||||
public slots:
|
||||
void onSeek( int seconds );
|
||||
void clearBuffers();
|
||||
void processData( const QByteArray& data, bool finish );
|
||||
|
||||
protected:
|
||||
virtual ::FLAC__StreamDecoderReadStatus read_callback( FLAC__byte buffer[], size_t *bytes );
|
||||
virtual ::FLAC__StreamDecoderWriteStatus write_callback( const ::FLAC__Frame *frame, const FLAC__int32 *const buffer[] );
|
||||
virtual bool eof_callback();
|
||||
void metadata_callback( const ::FLAC__StreamMetadata *metadata );
|
||||
void error_callback( ::FLAC__StreamDecoderErrorStatus status );
|
||||
|
||||
/* ::FLAC__StreamDecoderSeekStatus seek_callback( FLAC__uint64 absolute_byte_offset );
|
||||
::FLAC__StreamDecoderTellStatus tell_callback( FLAC__uint64 *absolute_byte_offset );
|
||||
::FLAC__StreamDecoderLengthStatus length_callback( FLAC__uint64 *stream_length );*/
|
||||
|
||||
private:
|
||||
QByteArray m_outBuffer;
|
||||
|
||||
QMutex m_mutex;
|
||||
QByteArray m_buffer;
|
||||
|
||||
bool m_FLACInit;
|
||||
bool m_FLACRunning;
|
||||
bool m_finished;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,24 +1,3 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005 - 2007 by *
|
||||
* Christian Muehlhaeuser, Last.fm Ltd <chris@last.fm> *
|
||||
* Erik Jaelevik, Last.fm Ltd <erik@last.fm> *
|
||||
* *
|
||||
* 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, Inc., *
|
||||
* 51 Franklin Steet, Fifth Floor, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "madtranscode.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
@ -1,23 +1,3 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005 - 2007 by *
|
||||
* Christian Muehlhaeuser, Last.fm Ltd <chris@last.fm> *
|
||||
* *
|
||||
* 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, Inc., *
|
||||
* 51 Franklin Steet, Fifth Floor, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
/*! \class MadTranscode
|
||||
\brief Transcoding plugin for MP3 streams, using libmad.
|
||||
*/
|
||||
|
@ -1,23 +1,3 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005 - 2006 by *
|
||||
* Christian Muehlhaeuser, Last.fm Ltd <chris@last.fm> *
|
||||
* *
|
||||
* 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, Inc., *
|
||||
* 51 Franklin Steet, Fifth Floor, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "vorbistranscode.h"
|
||||
|
||||
|
||||
|
@ -1,23 +1,3 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005 - 2006 by *
|
||||
* Christian Muehlhaeuser, Last.fm Ltd <chris@last.fm> *
|
||||
* *
|
||||
* 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, Inc., *
|
||||
* 51 Franklin Steet, Fifth Floor, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
/*! \class VorbisTranscode
|
||||
\brief Transcoding plugin for OGG/Vorbis streams.
|
||||
*/
|
||||
|
@ -17,15 +17,17 @@ MusicScanner::MusicScanner( const QString& dir, quint32 bs )
|
||||
|
||||
m_ext2mime.insert( "mp3", "audio/mpeg" );
|
||||
|
||||
#ifndef NO_OGG
|
||||
m_ext2mime.insert( "ogg", "application/ogg" );
|
||||
#endif
|
||||
|
||||
#ifndef NO_FLAC
|
||||
m_ext2mime.insert( "flac", "audio/flac" );
|
||||
#endif
|
||||
|
||||
// m_ext2mime.insert( "aac", "audio/mp4" );
|
||||
// m_ext2mime.insert( "m4a", "audio/mp4" );
|
||||
// m_ext2mime.insert( "mp4", "audio/mp4" );
|
||||
// m_ext2mime.insert( "flac", "audio/flac" );
|
||||
|
||||
#ifndef NO_OGG
|
||||
// not compiled on windows yet
|
||||
m_ext2mime.insert( "ogg", "application/ogg" );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user