push file opening upwards, instead of duplicating it in each loader
This commit is contained in:
@@ -37,7 +37,14 @@ RageSoundReader_FileReader *RageSoundReader_FileReader::TryOpenFile( RString fil
|
||||
if( !Sample )
|
||||
return NULL;
|
||||
|
||||
OpenResult ret = Sample->Open(filename);
|
||||
RageFile file;
|
||||
if( !file.Open(filename) )
|
||||
{
|
||||
error = ssprintf( "Couldn't open file: %s", file.GetError().c_str() );
|
||||
bKeepTrying = false;
|
||||
}
|
||||
|
||||
OpenResult ret = Sample->Open( file.Copy() );
|
||||
if( ret == OPEN_OK )
|
||||
return Sample;
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#define RAGE_SOUND_READER_FILE_READER_H
|
||||
|
||||
#include "RageSoundReader.h"
|
||||
#include "RageUtil_AutoPtr.h"
|
||||
class RageFileBasic;
|
||||
|
||||
#define SoundReader_FileReader RageSoundReader_FileReader
|
||||
class RageSoundReader_FileReader: public RageSoundReader
|
||||
@@ -23,7 +25,9 @@ public:
|
||||
OPEN_UNKNOWN_FILE_FORMAT=1,
|
||||
OPEN_FATAL_ERROR=2,
|
||||
};
|
||||
virtual OpenResult Open(RString filename) = 0;
|
||||
|
||||
/* Takes ownership of pFile (even on failure). */
|
||||
virtual OpenResult Open( RageFileBasic *pFile ) = 0;
|
||||
virtual float GetStreamToSourceRatio() const { return 1.0f; }
|
||||
virtual RString GetError() const { return m_sError; }
|
||||
|
||||
@@ -31,6 +35,7 @@ public:
|
||||
|
||||
protected:
|
||||
void SetError( RString sError ) const { m_sError = sError; }
|
||||
HiddenPtr<RageFileBasic> m_pFile;
|
||||
|
||||
private:
|
||||
static RageSoundReader_FileReader *TryOpenFile( RString filename, RString &error, RString format, bool &bKeepTrying );
|
||||
|
||||
@@ -348,16 +348,16 @@ int RageSoundReader_MP3::fill_buffer()
|
||||
mad->inbuf_filepos += mad->Stream.next_frame - mad->inbuf;
|
||||
}
|
||||
|
||||
const bool bWasAtEOF = file.AtEOF();
|
||||
const bool bWasAtEOF = m_pFile->AtEOF();
|
||||
|
||||
int rc = file.Read( mad->inbuf + inbytes, sizeof(mad->inbuf)-inbytes-MAD_BUFFER_GUARD );
|
||||
int rc = m_pFile->Read( mad->inbuf + inbytes, sizeof(mad->inbuf)-inbytes-MAD_BUFFER_GUARD );
|
||||
if( rc < 0 )
|
||||
{
|
||||
SetError( file.GetError() );
|
||||
SetError( m_pFile->GetError() );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( file.AtEOF() && !bWasAtEOF )
|
||||
if ( m_pFile->AtEOF() && !bWasAtEOF )
|
||||
{
|
||||
/* We just reached EOF. Append MAD_BUFFER_GUARD bytes of NULs to the
|
||||
* buffer, to ensure that the last frame is flushed. */
|
||||
@@ -545,7 +545,7 @@ void RageSoundReader_MP3::synth_output()
|
||||
* to use this. */
|
||||
int RageSoundReader_MP3::seek_stream_to_byte( int byte )
|
||||
{
|
||||
if( file.Seek(byte) == -1 )
|
||||
if( m_pFile->Seek(byte) == -1 )
|
||||
{
|
||||
SetError( strerror(errno) );
|
||||
return 0;
|
||||
@@ -644,16 +644,11 @@ RageSoundReader_MP3::~RageSoundReader_MP3()
|
||||
delete mad;
|
||||
}
|
||||
|
||||
RageSoundReader_FileReader::OpenResult RageSoundReader_MP3::Open( RString filename_ )
|
||||
RageSoundReader_FileReader::OpenResult RageSoundReader_MP3::Open( RageFileBasic *pFile )
|
||||
{
|
||||
filename = filename_;
|
||||
if( !file.Open( filename ) )
|
||||
{
|
||||
SetError( ssprintf("Couldn't open file: %s", file.GetError().c_str()) );
|
||||
return OPEN_FATAL_ERROR;
|
||||
}
|
||||
m_pFile = pFile;
|
||||
|
||||
mad->filesize = file.GetFileSize();
|
||||
mad->filesize = m_pFile->GetFileSize();
|
||||
ASSERT( mad->filesize != -1 );
|
||||
|
||||
/* Make sure we can decode at least one frame. This will also fill in header info. */
|
||||
@@ -698,10 +693,6 @@ RageSoundReader_MP3 *RageSoundReader_MP3::Copy() const
|
||||
{
|
||||
RageSoundReader_MP3 *ret = new RageSoundReader_MP3;
|
||||
|
||||
ret->filename = filename;
|
||||
bool b = ret->file.Open( filename );
|
||||
ASSERT( b );
|
||||
|
||||
ret->m_bAccurateSync = m_bAccurateSync;
|
||||
ret->mad->filesize = mad->filesize;
|
||||
ret->mad->bitrate = mad->bitrate;
|
||||
@@ -771,7 +762,7 @@ int RageSoundReader_MP3::Read( float *buf, int iFrames )
|
||||
|
||||
bool RageSoundReader_MP3::MADLIB_rewind()
|
||||
{
|
||||
this->file.Seek(0);
|
||||
m_pFile->Seek(0);
|
||||
|
||||
mad_frame_mute(&mad->Frame);
|
||||
mad_synth_mute(&mad->Synth);
|
||||
|
||||
@@ -11,7 +11,7 @@ struct madlib_t;
|
||||
class RageSoundReader_MP3: public RageSoundReader_FileReader
|
||||
{
|
||||
public:
|
||||
OpenResult Open(RString filename);
|
||||
OpenResult Open( RageFileBasic *pFile );
|
||||
void Close();
|
||||
int GetLength() const { return GetLengthConst(false); }
|
||||
int GetLength_Fast() const { return GetLengthConst(true); }
|
||||
@@ -32,8 +32,6 @@ private:
|
||||
int Channels;
|
||||
bool m_bAccurateSync;
|
||||
|
||||
RString filename;
|
||||
RageFile file;
|
||||
madlib_t *mad;
|
||||
|
||||
|
||||
|
||||
@@ -33,8 +33,6 @@ static int OggRageFile_seek_func( void *datasource, ogg_int64_t offset, int when
|
||||
|
||||
static int OggRageFile_close_func( void *datasource )
|
||||
{
|
||||
RageFileBasic *f = (RageFileBasic *) datasource;
|
||||
delete f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -72,24 +70,9 @@ static RString ov_ssprintf( int err, const char *fmt, ...)
|
||||
return s + ssprintf( " (%s)", errstr.c_str() );
|
||||
}
|
||||
|
||||
RageSoundReader_FileReader::OpenResult RageSoundReader_Vorbisfile::Open(RString filename_)
|
||||
{
|
||||
filename=filename_;
|
||||
|
||||
RageFile *f = new RageFile;
|
||||
|
||||
if( !f->Open( filename ) )
|
||||
{
|
||||
SetError( ssprintf("ogg: opening \"%s\" failed: %s", filename.c_str(), f->GetError().c_str()) );
|
||||
delete f;
|
||||
return OPEN_FATAL_ERROR;
|
||||
}
|
||||
|
||||
return Open( f );
|
||||
}
|
||||
|
||||
RageSoundReader_FileReader::OpenResult RageSoundReader_Vorbisfile::Open( RageFileBasic *f )
|
||||
RageSoundReader_FileReader::OpenResult RageSoundReader_Vorbisfile::Open( RageFileBasic *pFile )
|
||||
{
|
||||
m_pFile = pFile;
|
||||
vf = new OggVorbis_File;
|
||||
memset( vf, 0, sizeof(*vf) );
|
||||
|
||||
@@ -99,11 +82,10 @@ RageSoundReader_FileReader::OpenResult RageSoundReader_Vorbisfile::Open( RageFil
|
||||
callbacks.close_func = OggRageFile_close_func;
|
||||
callbacks.tell_func = OggRageFile_tell_func;
|
||||
|
||||
int ret = ov_open_callbacks( f, vf, NULL, 0, callbacks );
|
||||
int ret = ov_open_callbacks( pFile, vf, NULL, 0, callbacks );
|
||||
if( ret < 0 )
|
||||
{
|
||||
SetError( ov_ssprintf(ret, "ov_open failed") );
|
||||
delete f;
|
||||
delete vf;
|
||||
vf = NULL;
|
||||
switch( ret )
|
||||
@@ -309,8 +291,7 @@ RageSoundReader_Vorbisfile::~RageSoundReader_Vorbisfile()
|
||||
|
||||
RageSoundReader_Vorbisfile *RageSoundReader_Vorbisfile::Copy() const
|
||||
{
|
||||
const RageFileBasic *pFrom = (RageFileBasic *) vf->datasource;
|
||||
RageFileBasic *pFile = pFrom->Copy();
|
||||
RageFileBasic *pFile = m_pFile->Copy();
|
||||
pFile->Seek(0);
|
||||
RageSoundReader_Vorbisfile *ret = new RageSoundReader_Vorbisfile;
|
||||
|
||||
|
||||
@@ -11,8 +11,7 @@ class RageFileBasic;
|
||||
class RageSoundReader_Vorbisfile: public RageSoundReader_FileReader
|
||||
{
|
||||
public:
|
||||
OpenResult Open(RString filename);
|
||||
OpenResult Open( RageFileBasic *f );
|
||||
OpenResult Open( RageFileBasic *pFile );
|
||||
|
||||
int GetLength() const;
|
||||
int SetPosition( int iFrame );
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "RageSoundReader_WAV.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageFile.h"
|
||||
#include "RageFileBasic.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -84,7 +84,7 @@ namespace
|
||||
|
||||
struct WavReader
|
||||
{
|
||||
WavReader( RageFile &f, const RageSoundReader_WAV::WavData &data ):
|
||||
WavReader( RageFileBasic &f, const RageSoundReader_WAV::WavData &data ):
|
||||
m_File(f), m_WavData(data) { }
|
||||
virtual ~WavReader() { }
|
||||
virtual int Read( float *pBuf, int iFrames ) = 0;
|
||||
@@ -95,14 +95,14 @@ struct WavReader
|
||||
RString GetError() const { return m_sError; }
|
||||
|
||||
protected:
|
||||
RageFile &m_File;
|
||||
RageFileBasic &m_File;
|
||||
const RageSoundReader_WAV::WavData &m_WavData;
|
||||
RString m_sError;
|
||||
};
|
||||
|
||||
struct WavReaderPCM: public WavReader
|
||||
{
|
||||
WavReaderPCM( RageFile &f, const RageSoundReader_WAV::WavData &data ):
|
||||
WavReaderPCM( RageFileBasic &f, const RageSoundReader_WAV::WavData &data ):
|
||||
WavReader(f, data) { }
|
||||
|
||||
bool Init()
|
||||
@@ -197,7 +197,7 @@ public:
|
||||
float *m_pBuffer;
|
||||
int m_iBufferAvail, m_iBufferUsed;
|
||||
|
||||
WavReaderADPCM( RageFile &f, const RageSoundReader_WAV::WavData &data ):
|
||||
WavReaderADPCM( RageFileBasic &f, const RageSoundReader_WAV::WavData &data ):
|
||||
WavReader(f, data)
|
||||
{
|
||||
m_pBuffer = NULL;
|
||||
@@ -274,7 +274,7 @@ public:
|
||||
{
|
||||
if( iPredictor[i] >= (int) m_iaCoef1.size() )
|
||||
{
|
||||
LOG->Trace( "%s: predictor out of range", m_File.GetPath().c_str() );
|
||||
LOG->Trace( "%s: predictor out of range", m_File.GetDisplayPath().c_str() );
|
||||
|
||||
/* XXX: silence this block? */
|
||||
iPredictor[i] = 0;
|
||||
@@ -450,7 +450,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
RString ReadString( RageFile &f, int iSize, RString &sError )
|
||||
RString ReadString( RageFileBasic &f, int iSize, RString &sError )
|
||||
{
|
||||
if( sError.size() != 0 )
|
||||
return RString();
|
||||
@@ -469,24 +469,21 @@ RString ReadString( RageFile &f, int iSize, RString &sError )
|
||||
return OPEN_FATAL_ERROR; \
|
||||
}
|
||||
|
||||
RageSoundReader_FileReader::OpenResult RageSoundReader_WAV::Open( RString filename_ )
|
||||
RageSoundReader_FileReader::OpenResult RageSoundReader_WAV::Open( RageFileBasic *pFile )
|
||||
{
|
||||
m_sFilename = filename_;
|
||||
m_pFile = pFile;
|
||||
|
||||
RString sError;
|
||||
|
||||
if( !m_File.Open( m_sFilename ) )
|
||||
FATAL_ERROR( ssprintf("wav: opening \"%s\" failed: %s", m_sFilename.c_str(), m_File.GetError().c_str()) );
|
||||
|
||||
/* RIFF header: */
|
||||
if( ReadString( m_File, 4, sError ) != "RIFF" )
|
||||
if( ReadString( *m_pFile, 4, sError ) != "RIFF" )
|
||||
{
|
||||
SetError( "Not a WAV file" );
|
||||
return OPEN_UNKNOWN_FILE_FORMAT;
|
||||
}
|
||||
|
||||
FileReading::read_32_le( m_File, sError ); /* file size */
|
||||
if( ReadString( m_File, 4, sError ) != "WAVE" )
|
||||
FileReading::read_32_le( *m_pFile, sError ); /* file size */
|
||||
if( ReadString( *m_pFile, 4, sError ) != "WAVE" )
|
||||
{
|
||||
SetError( "Not a WAV file" );
|
||||
return OPEN_UNKNOWN_FILE_FORMAT;
|
||||
@@ -495,8 +492,8 @@ RageSoundReader_FileReader::OpenResult RageSoundReader_WAV::Open( RString filena
|
||||
bool bGotFormatChunk = false, bGotDataChunk = false;
|
||||
while( !bGotFormatChunk || !bGotDataChunk )
|
||||
{
|
||||
RString ChunkID = ReadString( m_File, 4, sError );
|
||||
int32_t iChunkSize = FileReading::read_32_le( m_File, sError );
|
||||
RString ChunkID = ReadString( *m_pFile, 4, sError );
|
||||
int32_t iChunkSize = FileReading::read_32_le( *m_pFile, sError );
|
||||
|
||||
if( sError.size() != 0 )
|
||||
{
|
||||
@@ -504,22 +501,22 @@ RageSoundReader_FileReader::OpenResult RageSoundReader_WAV::Open( RString filena
|
||||
return OPEN_FATAL_ERROR;
|
||||
}
|
||||
|
||||
int iNextChunk = m_File.Tell() + iChunkSize;
|
||||
int iNextChunk = m_pFile->Tell() + iChunkSize;
|
||||
/* Chunks are always word-aligned: */
|
||||
iNextChunk = (iNextChunk+1)&~1;
|
||||
|
||||
if( ChunkID == "fmt " )
|
||||
{
|
||||
if( bGotFormatChunk )
|
||||
LOG->Warn( "File %s has more than one fmt chunk", m_File.GetPath().c_str() );
|
||||
LOG->Warn( "File %s has more than one fmt chunk", m_pFile->GetDisplayPath().c_str() );
|
||||
|
||||
m_WavData.m_iFormatTag = FileReading::read_16_le( m_File, sError );
|
||||
m_WavData.m_iChannels = FileReading::read_16_le( m_File, sError );
|
||||
m_WavData.m_iSampleRate = FileReading::read_32_le( m_File, sError );
|
||||
FileReading::read_32_le( m_File, sError ); /* BytesPerSec */
|
||||
m_WavData.m_iBlockAlign = FileReading::read_16_le( m_File, sError );
|
||||
m_WavData.m_iBitsPerSample = FileReading::read_16_le( m_File, sError );
|
||||
m_WavData.m_iExtraFmtBytes = FileReading::read_16_le( m_File, sError );
|
||||
m_WavData.m_iFormatTag = FileReading::read_16_le( *m_pFile, sError );
|
||||
m_WavData.m_iChannels = FileReading::read_16_le( *m_pFile, sError );
|
||||
m_WavData.m_iSampleRate = FileReading::read_32_le( *m_pFile, sError );
|
||||
FileReading::read_32_le( *m_pFile, sError ); /* BytesPerSec */
|
||||
m_WavData.m_iBlockAlign = FileReading::read_16_le( *m_pFile, sError );
|
||||
m_WavData.m_iBitsPerSample = FileReading::read_16_le( *m_pFile, sError );
|
||||
m_WavData.m_iExtraFmtBytes = FileReading::read_16_le( *m_pFile, sError );
|
||||
|
||||
if( m_WavData.m_iChannels < 1 || m_WavData.m_iChannels > 2 )
|
||||
FATAL_ERROR( ssprintf( "Unsupported channel count: %i", m_WavData.m_iChannels) );
|
||||
@@ -527,21 +524,21 @@ RageSoundReader_FileReader::OpenResult RageSoundReader_WAV::Open( RString filena
|
||||
if( m_WavData.m_iSampleRate < 4000 || m_WavData.m_iSampleRate > 100000 ) /* unlikely */
|
||||
FATAL_ERROR( ssprintf( "Invalid sample rate: %i", m_WavData.m_iSampleRate) );
|
||||
|
||||
m_WavData.m_iExtraFmtPos = m_File.Tell();
|
||||
m_WavData.m_iExtraFmtPos = m_pFile->Tell();
|
||||
|
||||
bGotFormatChunk = true;
|
||||
}
|
||||
|
||||
if( ChunkID == "data" )
|
||||
{
|
||||
m_WavData.m_iDataChunkPos = m_File.Tell();
|
||||
m_WavData.m_iDataChunkPos = m_pFile->Tell();
|
||||
m_WavData.m_iDataChunkSize = iChunkSize;
|
||||
|
||||
int iFileSize = m_File.GetFileSize();
|
||||
int iFileSize = m_pFile->GetFileSize();
|
||||
int iMaxSize = iFileSize-m_WavData.m_iDataChunkPos;
|
||||
if( iMaxSize < m_WavData.m_iDataChunkSize )
|
||||
{
|
||||
LOG->Warn( "File %s truncated (%i < data chunk size %i)", m_File.GetPath().c_str(),
|
||||
LOG->Warn( "File %s truncated (%i < data chunk size %i)", m_pFile->GetDisplayPath().c_str(),
|
||||
iMaxSize, m_WavData.m_iDataChunkSize );
|
||||
|
||||
m_WavData.m_iDataChunkSize = iMaxSize;
|
||||
@@ -549,7 +546,7 @@ RageSoundReader_FileReader::OpenResult RageSoundReader_WAV::Open( RString filena
|
||||
|
||||
bGotDataChunk = true;
|
||||
}
|
||||
m_File.Seek( iNextChunk );
|
||||
m_pFile->Seek( iNextChunk );
|
||||
}
|
||||
|
||||
if( sError.size() != 0 )
|
||||
@@ -562,10 +559,10 @@ RageSoundReader_FileReader::OpenResult RageSoundReader_WAV::Open( RString filena
|
||||
{
|
||||
case 1: // PCM
|
||||
case 3: // FLOAT
|
||||
m_pImpl = new WavReaderPCM( m_File, m_WavData );
|
||||
m_pImpl = new WavReaderPCM( *m_pFile, m_WavData );
|
||||
break;
|
||||
case 2: // ADPCM
|
||||
m_pImpl = new WavReaderADPCM( m_File, m_WavData );
|
||||
m_pImpl = new WavReaderADPCM( *m_pFile, m_WavData );
|
||||
break;
|
||||
case 85: // MP3
|
||||
/* Return unknown, so other decoders will be tried. MAD can read MP3s embedded in WAVs. */
|
||||
@@ -620,7 +617,7 @@ RageSoundReader_WAV::~RageSoundReader_WAV()
|
||||
RageSoundReader_WAV *RageSoundReader_WAV::Copy() const
|
||||
{
|
||||
RageSoundReader_WAV *ret = new RageSoundReader_WAV;
|
||||
ret->Open( m_sFilename );
|
||||
ret->Open( m_pFile->Copy() );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ struct WavReader;
|
||||
class RageSoundReader_WAV: public RageSoundReader_FileReader
|
||||
{
|
||||
public:
|
||||
OpenResult Open( RString m_sFilename );
|
||||
OpenResult Open( RageFileBasic *pFile );
|
||||
void Close();
|
||||
int GetLength() const;
|
||||
int SetPosition( int iFrame );
|
||||
@@ -30,8 +30,6 @@ public:
|
||||
};
|
||||
|
||||
private:
|
||||
RageFile m_File;
|
||||
RString m_sFilename;
|
||||
WavData m_WavData;
|
||||
|
||||
WavReader *m_pImpl;
|
||||
|
||||
Reference in New Issue
Block a user