From 0f6d82df7ea06a2c93d4bd07c8fd28b520c72f35 Mon Sep 17 00:00:00 2001 From: rubidium Date: Fri, 26 Feb 2010 00:00:55 +0000 Subject: [PATCH] (svn r19262) -Feature: finalise BaNaNaS support for music sets --- src/base_media_base.h | 4 +- src/fileio.cpp | 73 +++++++++++++++++++++++++++++ src/fileio_func.h | 1 + src/network/network_content.cpp | 6 +++ src/network/network_content_gui.cpp | 5 ++ 5 files changed, 88 insertions(+), 1 deletion(-) diff --git a/src/base_media_base.h b/src/base_media_base.h index 4b43c24fd8..88b78374b4 100644 --- a/src/base_media_base.h +++ b/src/base_media_base.h @@ -170,7 +170,9 @@ public: static uint FindSets() { BaseMedia fs; - return fs.Scan(GetExtension(), Tbase_set::SUBDIR); + /* GM_DIR == music set. Music sets don't support tars, + * so there is no need to search for tars in that case. */ + return fs.Scan(GetExtension(), Tbase_set::SUBDIR, Tbase_set::SUBDIR != GM_DIR); } /** diff --git a/src/fileio.cpp b/src/fileio.cpp index 253ad8ebb3..1ae3c7e5e6 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -743,6 +743,79 @@ bool TarListAddFile(const char *filename) return true; } +/** + * Extract the tar with the given filename in the directory + * where the tar resides. + * @param tar_filename the name of the tar to extract. + * @return false on failure. + */ +bool ExtractTar(const char *tar_filename) +{ + TarList::iterator it = _tar_list.find(tar_filename); + /* We don't know the file. */ + if (it == _tar_list.end()) return false; + + const char *dirname = (*it).second.dirname; + + /* The file doesn't have a sub directory! */ + if (dirname == NULL) return false; + + char filename[MAX_PATH]; + strecpy(filename, tar_filename, lastof(filename)); + char *p = strrchr(filename, PATHSEPCHAR); + /* The file's path does not have a separator? */ + if (p == NULL) return false; + + p++; + strecpy(p, dirname, lastof(filename)); + DEBUG(misc, 8, "Extracting %s to directory %s", tar_filename, filename); + FioCreateDirectory(filename); + + for (TarFileList::iterator it2 = _tar_filelist.begin(); it2 != _tar_filelist.end(); it2++) { + if (strcmp((*it2).second.tar_filename, tar_filename) != 0) continue; + + strecpy(p, (*it2).first.c_str(), lastof(filename)); + + DEBUG(misc, 9, " extracting %s", filename); + + /* First open the file in the .tar. */ + size_t to_copy = 0; + FILE *in = FioFOpenFileTar(&(*it2).second, &to_copy); + if (in == NULL) { + DEBUG(misc, 6, "Extracting %s failed; could not open %s", filename, tar_filename); + return false; + } + + /* Now open the 'output' file. */ + FILE *out = fopen(filename, "wb"); + if (out == NULL) { + DEBUG(misc, 6, "Extracting %s failed; could not open %s", filename, filename); + fclose(in); + return false; + } + + /* Now read from the tar and write it into the file. */ + char buffer[4096]; + size_t read; + for (; to_copy != 0; to_copy -= read) { + read = fread(buffer, 1, min(to_copy, lengthof(buffer)), in); + if (read <= 0 || fwrite(buffer, 1, read, out) != read) break; + } + + /* Close everything up. */ + fclose(in); + fclose(out); + + if (to_copy != 0) { + DEBUG(misc, 6, "Extracting %s failed; still %i bytes to copy", filename, (int)to_copy); + return false; + } + } + + DEBUG(misc, 9, " extraction successful"); + return true; +} + static int ScanPathForTarFiles(const char *path, size_t basepath_length) { extern bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb); diff --git a/src/fileio_func.h b/src/fileio_func.h index b2d2da8032..53b3aa233c 100644 --- a/src/fileio_func.h +++ b/src/fileio_func.h @@ -63,6 +63,7 @@ void *ReadFileToMem(const char *filename, size_t *lenp, size_t maxsize); bool FileExists(const char *filename); const char *FioTarFirstDir(const char *tarname); void FioTarAddLink(const char *src, const char *dest); +bool ExtractTar(const char *tar_filename); extern char *_personal_dir; ///< custom directory for personal settings, saves, newgrf, etc. diff --git a/src/network/network_content.cpp b/src/network/network_content.cpp index d5ed2a3747..76576f2c23 100644 --- a/src/network/network_content.cpp +++ b/src/network/network_content.cpp @@ -481,6 +481,12 @@ void ClientNetworkContentSocketHandler::AfterDownload() TarListAddFile(GetFullFilename(this->curInfo, false)); + if (this->curInfo->type == CONTENT_TYPE_BASE_MUSIC) { + /* Music can't be in a tar. So extract the tar! */ + ExtractTar(GetFullFilename(this->curInfo, false)); + unlink(GetFullFilename(this->curInfo, false)); + } + this->OnDownloadComplete(this->curInfo->id); } else { ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_EXTRACT, INVALID_STRING_ID, WL_ERROR); diff --git a/src/network/network_content_gui.cpp b/src/network/network_content_gui.cpp index a25a5ad4ab..8f377a0ba3 100644 --- a/src/network/network_content_gui.cpp +++ b/src/network/network_content_gui.cpp @@ -106,6 +106,11 @@ public: SetWindowDirty(WC_GAME_OPTIONS, 0); break; + case CONTENT_TYPE_BASE_MUSIC: + BaseMusic::FindSets(); + SetWindowDirty(WC_GAME_OPTIONS, 0); + break; + case CONTENT_TYPE_NEWGRF: ScanNewGRFFiles(); /* Yes... these are the NewGRF windows */