From 2cc80e12676c666ce0cb8ad27a919d5ad52110cc Mon Sep 17 00:00:00 2001 From: Frank Zago Date: Sun, 7 Aug 2011 19:14:46 +0000 Subject: [PATCH] Modified CMediaHandler to handle more than one file. --- client/CMusicHandler.cpp | 11 ++++---- client/CMusicHandler.h | 5 ++-- client/CSndHandler.cpp | 59 ++++++++++++++++++++++++++-------------- client/CSndHandler.h | 9 +++--- client/CVideoHandler.cpp | 16 ++++------- client/CVideoHandler.h | 10 +++---- 6 files changed, 63 insertions(+), 47 deletions(-) diff --git a/client/CMusicHandler.cpp b/client/CMusicHandler.cpp index 6e9dbaa60..1902dff97 100644 --- a/client/CMusicHandler.cpp +++ b/client/CMusicHandler.cpp @@ -62,7 +62,7 @@ void CAudioBase::setVolume(unsigned int percent) volume = percent; } -CSoundHandler::CSoundHandler(): sndh(NULL) +CSoundHandler::CSoundHandler() { // Map sound names #define VCMI_SOUND_NAME(x) ( soundBase::x, @@ -86,16 +86,17 @@ void CSoundHandler::init() { CAudioBase::init(); - if (initialized) + if (initialized) { // Load sounds - sndh = new CSndHandler(std::string(DATA_DIR "/Data/Heroes3.snd")); + sndh.add_file(std::string(DATA_DIR "/Data/Heroes3.snd")); + sndh.add_file(std::string(DATA_DIR "/Data/H3ab_ahd.snd")); + } } void CSoundHandler::release() { if (initialized) { Mix_HaltChannel(-1); - delete sndh; std::map::iterator it; for (it=soundChunks.begin(); it != soundChunks.end(); it++) { @@ -118,7 +119,7 @@ Mix_Chunk *CSoundHandler::GetSoundChunk(soundBase::soundID soundID) // Load and insert int size; - const char *data = sndh->extract(it->second, size); + const char *data = sndh.extract(it->second, size); if (!data) return NULL; diff --git a/client/CMusicHandler.h b/client/CMusicHandler.h index f7cc78e86..ead2f92db 100644 --- a/client/CMusicHandler.h +++ b/client/CMusicHandler.h @@ -6,7 +6,7 @@ #include "CSoundBase.h" #include "CMusicBase.h" #include "../lib/CCreatureHandler.h" - +#include "CSndHandler.h" /* * CMusicHandler.h, part of VCMI engine @@ -18,7 +18,6 @@ * */ -class CSndHandler; class CSpell; struct _Mix_Music; typedef struct _Mix_Music Mix_Music; @@ -67,7 +66,7 @@ public: class CSoundHandler: public CAudioBase { private: - CSndHandler *sndh; + CSndHandler sndh; soundBase::soundID getSoundID(std::string &fileName); std::map soundChunks; diff --git a/client/CSndHandler.cpp b/client/CSndHandler.cpp index c73b01d38..ff0e22839 100644 --- a/client/CSndHandler.cpp +++ b/client/CSndHandler.cpp @@ -14,16 +14,27 @@ * */ +/* Media file are kept in container files. We map these files in + * memory, parse them and create an index of them to easily retrieve + * the data+size of the objects. */ + CMediaHandler::~CMediaHandler() { + std::vector::iterator it; + entries.clear(); fimap.clear(); - mfile->close(); - delete mfile; + + for (it=mfiles.begin() ; it < mfiles.end(); it++ ) { + (*it)->close(); + delete *it; + } } -CMediaHandler::CMediaHandler(std::string fname) +boost::iostreams::mapped_file_source *CMediaHandler::add_file(std::string fname) { + boost::iostreams::mapped_file_source *mfile; + try //c-tor of mapped_file_source throws exception on failure { mfile = new boost::iostreams::mapped_file_source(fname); @@ -32,15 +43,19 @@ CMediaHandler::CMediaHandler(std::string fname) { tlog1 << "Cannot open " << fname << std::endl; throw std::string("Cannot open ")+fname; + return NULL; + } else { + mfiles.push_back(mfile); + return mfile; } } void CMediaHandler::extract(int index, std::string dstfile) //saves selected file { std::ofstream out(dstfile.c_str(),std::ios_base::binary); - const char *data = mfile->data(); - - out.write(&data[entries[index].offset], entries[index].size); + Entry &entry = entries[index]; + + out.write(entry.data, entry.size); out.close(); } @@ -98,10 +113,10 @@ MemberFile CMediaHandler::getFile(std::string name) const char * CMediaHandler::extract (int index, int & size) { - size = entries[index].size; - const char *data = mfile->data(); + Entry &entry = entries[index]; - return &data[entries[index].offset]; + size = entry.size; + return entry.data; } const char * CMediaHandler::extract (std::string srcName, int &size) @@ -119,35 +134,38 @@ const char * CMediaHandler::extract (std::string srcName, int &size) return NULL; } -CSndHandler::CSndHandler(std::string fname) : CMediaHandler(fname) +void CSndHandler::add_file(std::string fname) { - const unsigned char *data = (const unsigned char *)mfile->data(); + boost::iostreams::mapped_file_source *mfile = CMediaHandler::add_file(fname); + if (!mfile) + /* File doesn't exist. Silently skip it.*/ + return; + + const char *data = mfile->data(); unsigned int numFiles = SDL_SwapLE32(*(Uint32 *)&data[0]); struct soundEntry *se = (struct soundEntry *)&data[4]; for (unsigned int i=0; ifilename; - // entry.name += '.'; - // p = se->filename; - // while(*p) p++; - // p++; - // entry.name += p; - entry.offset = SDL_SwapLE32(se->offset); entry.size = SDL_SwapLE32(se->size); + entry.data = mfile->data() + entry.offset; entries.push_back(entry); fimap[entry.name] = i; } } -CVidHandler::CVidHandler(std::string fname) : CMediaHandler(fname) +void CVidHandler::add_file(std::string fname) { + boost::iostreams::mapped_file_source *mfile = CMediaHandler::add_file(fname); + if (!mfile) + /* File doesn't exist. Silently skip it.*/ + return; + if(mfile->size() < 48) { tlog1 << fname << " doesn't contain needed data!\n"; @@ -173,6 +191,7 @@ CVidHandler::CVidHandler(std::string fname) : CMediaHandler(fname) entry.size = SDL_SwapLE32(ve_next->offset) - entry.offset; } + entry.data = mfile->data() + entry.offset; entries.push_back(entry); fimap[entry.name] = i; diff --git a/client/CSndHandler.h b/client/CSndHandler.h index 00a6a6825..365fa0ea0 100644 --- a/client/CSndHandler.h +++ b/client/CSndHandler.h @@ -54,15 +54,16 @@ protected: std::string name; unsigned int size; unsigned int offset; + const char *data; }; - boost::iostreams::mapped_file_source *mfile; + std::vector mfiles; + boost::iostreams::mapped_file_source *add_file(std::string fname); public: std::vector entries; std::map fimap; // map of file and index ~CMediaHandler(); //d-tor - CMediaHandler(std::string fname); //c-tor void extract(std::string srcfile, std::string dstfile, bool caseSens=true); //saves selected file const char * extract (std::string srcfile, int & size); //return selecte file data, NULL if file doesn't exist void extract(int index, std::string dstfile); //saves selected file @@ -73,13 +74,13 @@ public: class CSndHandler: public CMediaHandler { public: - CSndHandler(std::string fname); + void add_file(std::string fname); }; class CVidHandler: public CMediaHandler { public: - CVidHandler(std::string fname); + void add_file(std::string fname); }; diff --git a/client/CVideoHandler.cpp b/client/CVideoHandler.cpp index cf7fa6caf..7e6f69086 100644 --- a/client/CVideoHandler.cpp +++ b/client/CVideoHandler.cpp @@ -401,15 +401,14 @@ void CSmackPlayer::redraw( int x, int y, SDL_Surface *dst, bool update ) CVideoPlayer::CVideoPlayer() { - vidh = new CVidHandler(std::string(DATA_DIR "/Data/VIDEO.VID")); - vidh_ab = new CVidHandler(std::string(DATA_DIR "/Data/H3ab_ahd.vid")); + vidh.add_file(std::string(DATA_DIR "/Data/VIDEO.VID")); + vidh.add_file(std::string(DATA_DIR "/Data/H3ab_ahd.vid")); + current = NULL; } CVideoPlayer::~CVideoPlayer() { - delete vidh; - delete vidh_ab; } bool CVideoPlayer::open(std::string name) @@ -663,8 +662,8 @@ CVideoPlayer::CVideoPlayer() av_register_protocol(&lod_protocol); #endif - vidh = new CVidHandler(std::string(DATA_DIR "/Data/VIDEO.VID")); - vidh_ab = new CVidHandler(std::string(DATA_DIR "/Data/H3ab_ahd.vid")); + vidh.add_file(std::string(DATA_DIR "/Data/VIDEO.VID")); + vidh.add_file(std::string(DATA_DIR "/Data/H3ab_ahd.vid")); } // loop = to loop through the video @@ -679,10 +678,7 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay) refreshCount = -1; doLoop = loop; - data = vidh->extract(fname, length); - if (!data) { - data = vidh_ab->extract(fname, length); - } + data = vidh.extract(fname, length); if (data) { // Create our URL name with the 'lod' protocol as a prefix and a diff --git a/client/CVideoHandler.h b/client/CVideoHandler.h index 600ec9dd7..6d0e39025 100644 --- a/client/CVideoHandler.h +++ b/client/CVideoHandler.h @@ -9,6 +9,8 @@ struct SDL_Surface; #define WIN32_LEAN_AND_MEAN //excludes rarely used stuff from windows headers - delete this line if something is missing #include +#include "CSndHandler.h" + #pragma pack(push,1) struct BINK_STRUCT { @@ -161,8 +163,7 @@ class CVidHandler; class CVideoPlayer : public IVideoPlayer { private: - CVidHandler * vidh; //.vid file handling - CVidHandler *vidh_ab; // armageddon's blade video file handling + CVidHandler vidh; //.vid file handling CSmackPlayer smkPlayer; //for .SMK CBIKHandler bikPlayer; //for .BIK @@ -199,6 +200,7 @@ public: #else +#include "CSndHandler.h" #include typedef struct AVFormatContext AVFormatContext; @@ -206,7 +208,6 @@ typedef struct AVCodecContext AVCodecContext; typedef struct AVCodec AVCodec; typedef struct AVFrame AVFrame; struct SwsContext; -class CVidHandler; class CVideoPlayer //: public IVideoPlayer { @@ -224,8 +225,7 @@ private: SDL_Rect destRect; // valid when dest is used SDL_Rect pos; // destination on screen - CVidHandler *vidh; - CVidHandler *vidh_ab; + CVidHandler vidh; int refreshWait; // Wait several refresh before updating the image int refreshCount;