diff --git a/stepmania/src/RageSoundReader_FileReader.cpp b/stepmania/src/RageSoundReader_FileReader.cpp index 72811542cc..f288825de2 100644 --- a/stepmania/src/RageSoundReader_FileReader.cpp +++ b/stepmania/src/RageSoundReader_FileReader.cpp @@ -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; diff --git a/stepmania/src/RageSoundReader_FileReader.h b/stepmania/src/RageSoundReader_FileReader.h index d770f385ec..c0222ef585 100644 --- a/stepmania/src/RageSoundReader_FileReader.h +++ b/stepmania/src/RageSoundReader_FileReader.h @@ -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 m_pFile; private: static RageSoundReader_FileReader *TryOpenFile( RString filename, RString &error, RString format, bool &bKeepTrying ); diff --git a/stepmania/src/RageSoundReader_MP3.cpp b/stepmania/src/RageSoundReader_MP3.cpp index de6ff0c9a0..71933dafad 100644 --- a/stepmania/src/RageSoundReader_MP3.cpp +++ b/stepmania/src/RageSoundReader_MP3.cpp @@ -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); diff --git a/stepmania/src/RageSoundReader_MP3.h b/stepmania/src/RageSoundReader_MP3.h index 42b737a1e8..cc8862808a 100644 --- a/stepmania/src/RageSoundReader_MP3.h +++ b/stepmania/src/RageSoundReader_MP3.h @@ -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; diff --git a/stepmania/src/RageSoundReader_Vorbisfile.cpp b/stepmania/src/RageSoundReader_Vorbisfile.cpp index 8ab2c754bd..b1e0fd7e6c 100644 --- a/stepmania/src/RageSoundReader_Vorbisfile.cpp +++ b/stepmania/src/RageSoundReader_Vorbisfile.cpp @@ -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; diff --git a/stepmania/src/RageSoundReader_Vorbisfile.h b/stepmania/src/RageSoundReader_Vorbisfile.h index 53c689efe9..b117cb9638 100644 --- a/stepmania/src/RageSoundReader_Vorbisfile.h +++ b/stepmania/src/RageSoundReader_Vorbisfile.h @@ -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 ); diff --git a/stepmania/src/RageSoundReader_WAV.cpp b/stepmania/src/RageSoundReader_WAV.cpp index 0c1159714f..108b52be84 100644 --- a/stepmania/src/RageSoundReader_WAV.cpp +++ b/stepmania/src/RageSoundReader_WAV.cpp @@ -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; } diff --git a/stepmania/src/RageSoundReader_WAV.h b/stepmania/src/RageSoundReader_WAV.h index 73ad441260..20dcdeeaa2 100644 --- a/stepmania/src/RageSoundReader_WAV.h +++ b/stepmania/src/RageSoundReader_WAV.h @@ -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;