Prechádzať zdrojové kódy

Modified CMediaHandler to handle more than one file.

Frank Zago 14 rokov pred
rodič
commit
2cc80e1267

+ 6 - 5
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<soundBase::soundID, Mix_Chunk *>::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;
 

+ 2 - 3
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<soundBase::soundID, Mix_Chunk *> soundChunks;

+ 39 - 20
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<boost::iostreams::mapped_file_source *>::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; i<numFiles; i++, se++)
 	{
 		Entry entry;
-		//		char *p;
 
-		// Reassemble the filename, drop extension
 		entry.name = se->filename;
-		//		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;

+ 5 - 4
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<boost::iostreams::mapped_file_source *> mfiles;
+	boost::iostreams::mapped_file_source *add_file(std::string fname);
 
 public:
 	std::vector<Entry> entries;
 	std::map<std::string, int> 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);
 };
 
 

+ 6 - 10
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

+ 5 - 5
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 <windows.h>
 
+#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 <SDL_video.h>
 
 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;