push file opening upwards, instead of duplicating it in each loader

This commit is contained in:
Glenn Maynard
2007-02-21 10:10:18 +00:00
parent f081f56388
commit acc0b14ee1
8 changed files with 61 additions and 85 deletions
+8 -1
View File
@@ -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;
+6 -1
View File
@@ -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 );
+9 -18
View File
@@ -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);
+1 -3
View File
@@ -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;
+4 -23
View File
@@ -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;
+1 -2
View File
@@ -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 );
+31 -34
View File
@@ -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;
}
+1 -3
View File
@@ -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;