From 90a24f67d489e8d95720d0dbb1ab52b49cd8d273 Mon Sep 17 00:00:00 2001 From: Scott Duensing Date: Sun, 1 Dec 2019 19:12:12 -0600 Subject: [PATCH] Command line option parsing complete. --- .gitignore | 2 + singe/main.c | 393 ++++++++++++++++++++++++++++++++++++++++++-- singe/preBuild.sh | 75 ++++++++- singe/singe.c | 22 +++ singe/singe.h | 17 ++ singe/singe.pro | 3 +- singe/util.c | 87 +++++++++- singe/util.h | 15 +- singe/videoPlayer.c | 4 +- singe/videoPlayer.h | 2 +- 10 files changed, 594 insertions(+), 26 deletions(-) diff --git a/.gitignore b/.gitignore index a97aa9198..ab0345b4e 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,5 @@ singe/thirdparty/SDL2_image/external/libpng-1.6.37/autom4te.cache/ singe/thirdparty/SDL2_image/external/libwebp-1.0.3/autom4te.cache/ singe/thirdparty/SDL2_image/external/tiff-4.1.0/autom4te.cache/ thirdparty-build/ +singe/extensions.h +videotest/*.singe diff --git a/singe/main.c b/singe/main.c index b4832ecbc..7233f1ecc 100644 --- a/singe/main.c +++ b/singe/main.c @@ -20,6 +20,9 @@ */ +#include +#include + #include #include #include @@ -31,31 +34,372 @@ #include "util.h" #include "videoPlayer.h" #include "singe.h" +#include "extensions.h" -// /home/scott/code/singe2/videotest/Stargate.m4v +#define VERSION_STRING "v2.00" +#define COPYRIGHT_END_YEAR "2020" + + +typedef struct RatioS { + int aspectNum; + int aspectDom; +} RatioT; + +typedef struct ResolutionS { + int width; + int height; +} ResolutionT; + +typedef struct ModeS { + RatioT ratio; + ResolutionT resolution; +} ModeT; + + +void showUsage(char *name, char *message); + + +// /home/scott/code/singe2/videotest/Stargate.singe // /home/scott/code/singe2/videotest/TestClip_720x480_29.97fps_2000_frames.avi +__attribute__((noreturn)) +void showUsage(char *name, char *message) { + utilSay(" ___ ___ _ _ ___ ___"); + utilSay("/ __|_ _| \\| |/ __| __| Somewhat Interactive Nostalgic Game Emulator %s", VERSION_STRING); + utilSay("\\__ \\| || .` | (_ | _| Copyright (c) 2006-%s Scott C. Duensing", COPYRIGHT_END_YEAR); + utilSay("|___/___|_|\\_|\\___|___| https://kangaroopunch.com"); + utilSay(""); + utilSay("Usage: %s [OPTIONS] scriptName{.singe}", utilGetLastPathComponent(name)); + utilSay(""); + utilSay(" -v, --framefile=FILENAME use an alternate video file"); + utilSay(" -d, --datadir=PATHNAME alternate location for written files"); + utilSay(" -m, --nomouse disable mouse"); + utilSay(" -n, --noserversend do not send usage statistics"); + utilSay(" -s, --nosound, --mutesound mutes all sound"); + utilSay(" -f, --fullscreen run in full screen mode"); + utilSay(" -w, --fullscreen_window run in windowed full screen mode"); + utilSay(" -l, --volume_vldp=PERCENT specify laserdisc volume in percent"); + utilSay(" -e, --volume_nonvldp=PERCENT specify sound effects volume in percent"); + // 00000000011111111112222222222333333333344444444445555555555666666666677777777778 + // 12345678901234567890123456789012345678901234567890123456789012345678901234567890 + utilSay(" -z, --scalefactor=PERCENT reduce screen size for overscan compensation"); + utilSay(" -x, --xresolution=VALUE specify horizontal resolution"); + utilSay(" -y, --yresolution=VALUE specify vertical resolution"); + utilSay(" -h, --help this display"); + utilSay(""); + if (message) { + utilSay("Error: %s", message); + utilSay(""); + exit(1); + } + exit(0); +} + + int main(int argc, char *argv[]) { - int err = 0; - int flags = 0; - int thisFrame = -1; - int lastFrame = -1; - int videoHandle = -1; - char *filename = argv[1]; - bool running = true; - SDL_Window *window = NULL; - SDL_Renderer *renderer = NULL; - SDL_Texture *texture = NULL; + int x = 0; + int err = 0; + int flags = 0; + int thisFrame = -1; + int lastFrame = -1; + int videoHandle = -1; + int optionIndex = 0; + int bestResIndex = -1; + int bestRatioIndex = -1; + char *temp = NULL; + float thisRatio = 0; + float bestRatio = 9999; + bool running = true; + SDL_Window *window = NULL; + SDL_Renderer *renderer = NULL; + SDL_Texture *texture = NULL; + SDL_DisplayMode mode; + static struct option options[] = { + { "nomouse", no_argument, NULL, 'm' }, + { "noserversend", no_argument, NULL, 'n' }, + { "nosound", no_argument, NULL, 's' }, + { "mutesound", no_argument, NULL, 's' }, + { "fullscreen", no_argument, NULL, 'f' }, + { "fullscreen_window", no_argument, NULL, 'w' }, + { "datadir", optional_argument, NULL, 'd' }, + { "framefile", optional_argument, NULL, 'v' }, + { "volume_vldp", optional_argument, NULL, 'l' }, + { "volume_nonlvdp", optional_argument, NULL, 'e' }, + { "scalefactor", optional_argument, NULL, 'z' }, + { "xresolution", optional_argument, NULL, 'x' }, + { "yresolution", optional_argument, NULL, 'y' }, + { "help", no_argument, NULL, 'h' }, + { NULL, 0, NULL, 0 } + }; + static ModeT modes[] = { + { { 4, 3 }, { 640, 480 } }, + { { 4, 3 }, { 800, 600 } }, + { { 4, 3 }, { 960, 720 } }, + { { 4, 3 }, { 1024, 768 } }, + { { 4, 3 }, { 1280, 960 } }, + { { 4, 3 }, { 1400, 1050 } }, + { { 4, 3 }, { 1440, 1080 } }, + { { 4, 3 }, { 1600, 1200 } }, + { { 4, 3 }, { 1856, 1392 } }, + { { 4, 3 }, { 1920, 1440 } }, + { { 4, 3 }, { 2048, 1536 } }, + { { 16, 9 }, { 1024, 576 } }, + { { 16, 9 }, { 1152, 648 } }, + { { 16, 9 }, { 1280, 720 } }, + { { 16, 9 }, { 1366, 768 } }, + { { 16, 9 }, { 1600, 900 } }, + { { 16, 9 }, { 1920, 1080 } }, + { { 16, 9 }, { 2560, 1440 } }, + { { 16, 9 }, { 3840, 2160 } }, + { { 16, 9 }, { 7680, 4320 } }, + { { 16, 10 }, { 1280, 800 } }, + { { 16, 10 }, { 1440, 900 } }, + { { 16, 10 }, { 1680, 1050 } }, + { { 16, 10 }, { 1920, 1200 } }, + { { 16, 10 }, { 2560, 1600 } }, + { { 0, 0 }, { 0, 0 } } + }; - // Did we get a filename to open? - if (argc != 2) utilDie("Usage: %s \n", argv[0]); + // Parse command line + while (true) { + optionIndex = 0; + opterr = 0; + x = getopt_long(argc, argv, "mnsfwhd:v:l:e:z:x:y:", options, &optionIndex); + + // Out of options? + if (x == -1) break; + + // Handle options + switch (x) { + // No Mouse + case 'm': + _confNoMouse = true; + break; + + // No Server Statss + case 'n': + _confNoStats = true; + break; + + // No Sound + case 's': + _confNoSound = true; + break; + + // Full Screen + case 'f': + _confFullScreen = true; + break; + + // Full Screen Windowed + case 'w': + _confFullScreenWindow = true; + break; + + // Video File + case 'v': + if (_confVideoFile) free(_confVideoFile); + _confVideoFile = strdup(optarg); + break; + + // Data Dir + case 'd': + if (_confDataDir) free(_confDataDir); + _confDataDir = strdup(optarg); + break; + + // Video Volume + case 'l': + _confVolumeVldp = atoi(optarg); + break; + + // Effects Volume + case 'e': + _confVolumeNonVldp = atoi(optarg); + break; + + // Zoom + case 'z': + _confScaleFactor = atoi(optarg); + break; + + // X Resolution + case 'x': + _confXResolution = atoi(optarg); + break; + + // Y Resolution + case 'y': + _confYResolution = atoi(optarg); + break; + + // Help + case 'h': + showUsage(argv[0], NULL); + break; + + case '?': + showUsage(argv[0], "Unknown option."); + break; + + default: + abort(); // Something bad happened + break; + } + } + + // Did we get a filename or path to open? + if (optind != (argc - 1)) showUsage(argv[0], "No script file specified."); + _confScriptFile = strdup(argv[optind]); + // Exists? + if (!utilFileExists(_confScriptFile)) { + // Missing. Is a path? + if (utilPathExists(_confScriptFile)) { + // See if the script exists in the path. + temp = utilCreateString("%s%c%s.singe", _confScriptFile, utilGetPathSeparator(), utilGetLastPathComponent(_confScriptFile)); + if (utilFileExists(temp)) { + // Found script named for path inside path. + free(_confScriptFile); + _confScriptFile = temp; + temp = NULL; + } else { + // Not in the path either. + free(_confScriptFile); + _confScriptFile = NULL; + } + } else { + // Not a path either. + free(_confScriptFile); + _confScriptFile = NULL; + } + } + if (!_confScriptFile) showUsage(argv[0], "Unable to locate script."); + + // Do we need to generate a video name? + if (_confVideoFile) { + if (!utilFileExists(_confVideoFile)) { + free(_confVideoFile); + _confVideoFile = NULL; + } + } else { + x = (int)(strlen(_confScriptFile) - strlen(utilGetFileExtension(_confScriptFile))) - 1; + if (x < 0) { + x = 0; + } + temp = strdup(_confScriptFile); + temp[x] = 0; + // Check all known extensions - lower case only, Windows users! + x = 0; + while (ffmpegExtensions[x]) { + _confVideoFile = utilCreateString("%s.%s", temp, ffmpegExtensions[x]); + if (utilFileExists(_confVideoFile)) { + break; + } + free(_confVideoFile); + _confVideoFile = NULL; + x++; + } + free(temp); + } + if (!_confVideoFile) showUsage(argv[0], "Unable to locate video."); + + // Do we need to generate a data directory name? + if (_confDataDir) { + if (!utilPathExists(_confDataDir)) { + free(_confDataDir); + _confDataDir = NULL; + } + } else { + // Put it in the game folder. + x = (int)(strlen(_confScriptFile) - strlen(utilGetLastPathComponent(_confScriptFile))) - 1; + if (x < 0) { + x = 0; + } + _confDataDir = strdup(_confScriptFile); + _confDataDir[x] = 0; + } + if (!_confDataDir) showUsage(argv[0], "Unable to locate data directory."); + + // Do the full screen options make sense? + if (_confFullScreen && _confFullScreenWindow) showUsage(argv[0], "Full Screen or Full Screen Windowed. Pick one."); + + // Sane volume values? + if ((_confVolumeVldp < 0) || (_confVolumeVldp > 100)) showUsage(argv[0], "Laserdisc volume must be between 0 and 100 percent."); + if ((_confVolumeNonVldp < 0) || (_confVolumeNonVldp > 100)) showUsage(argv[0], "Effects volume must be between 0 and 100 percent."); + + // Sane scale factor? + if ((_confScaleFactor < 50) || (_confScaleFactor > 100)) showUsage(argv[0], "Display scale must be between 50 and 100 percent."); // Init SDL - err = SDL_Init(SDL_INIT_EVERYTHING); - if (err != 0) utilDie("%s", SDL_GetError()); + if (SDL_Init(SDL_INIT_EVERYTHING) != 0) utilDie("%s", SDL_GetError()); + if (SDL_GetCurrentDisplayMode(0, &mode) < 0) utilDie("%s", SDL_GetError()); + + // Determine resolution if not specified + if ((_confXResolution <= 0) || (_confYResolution <= 0)) { + // Find our current aspect ratio + x = 0; + while (modes[x].ratio.aspectNum != 0) { + thisRatio = fabsf(((float)modes[x].ratio.aspectNum / (float)modes[x].ratio.aspectDom) - ((float)mode.w / (float)mode.h)); + if (thisRatio < bestRatio) { + bestRatio = thisRatio; + bestRatioIndex = x; + } + x++; + } + x = 0; + // Were both resolutions not specified? + if ((_confXResolution <= 0) && (_confYResolution <= 0)) { + // Are we full screen? + if (_confFullScreen || _confFullScreenWindow) { + // Use desktop resolution + _confXResolution = mode.w; + _confYResolution = mode.h; + } else { + // Find largest window that will fit on the screen but not fill it + while (modes[x].ratio.aspectNum != 0) { + if ((modes[x].ratio.aspectNum == modes[bestRatioIndex].ratio.aspectNum) && (modes[x].ratio.aspectDom == modes[bestRatioIndex].ratio.aspectDom)) { + if ((modes[x].resolution.width < mode.w) && (modes[x].resolution.height < mode.h)) { + bestResIndex = x; + } + } + x++; + } + _confXResolution = modes[bestResIndex].resolution.width; + _confYResolution = modes[bestResIndex].resolution.height; + } + } else { + // Find unprovided width/height using provided value + while (modes[x].ratio.aspectNum != 0) { + // Is this the aspect ratio we're using? + if ((modes[bestRatioIndex].ratio.aspectNum == modes[x].ratio.aspectNum) && (modes[bestRatioIndex].ratio.aspectDom == modes[x].ratio.aspectDom)) { + // Do we have the width or height? + if (_confXResolution > 0) { + // We have the width. Is this the matching entry? + if (modes[x].resolution.width == _confXResolution) { + bestResIndex = x; + _confYResolution = modes[x].resolution.height; + break; + } + } else { + // We have the height. Is this the matching entry? + if (modes[x].resolution.height == _confYResolution) { + bestResIndex = x; + _confXResolution = modes[x].resolution.width; + break; + } + } + } + x++; + } + } + } + // Did we end up with a valid resolution? + if (_confXResolution <= 0) showUsage(argv[0], "Unable to determine X resolution. (Is the Y value sane?)"); + if (_confYResolution <= 0) showUsage(argv[0], "Unable to determine Y resolution. (Is the X value sane?)"); + if ((_confXResolution > mode.w) || (_confYResolution > mode.h)) showUsage(argv[0], "Specified resolution is larger than the display."); // Init SDL_mixer ***FIX*** flags = /* MIX_INIT_FLAC | */ MIX_INIT_MOD | MIX_INIT_MP3 | MIX_INIT_OGG | MIX_INIT_MID | MIX_INIT_OPUS; @@ -71,9 +415,15 @@ int main(int argc, char *argv[]) { if (TTF_Init() < 0) utilDie("%s", TTF_GetError()); // Create Resizable Window - window = SDL_CreateWindow(filename, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1280, 720, SDL_WINDOW_RESIZABLE); + window = SDL_CreateWindow("SINGE", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, _confXResolution, _confYResolution, SDL_WINDOW_RESIZABLE); if (window == NULL) utilDie("%s", SDL_GetError()); + // Do we want full screen of some kind? + if (_confFullScreen || _confFullScreenWindow) { + flags = _confFullScreen ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_FULLSCREEN_DESKTOP; + SDL_SetWindowFullscreen(window, (Uint32)flags); + } + // Create an accelerated renderer. renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); if (renderer == NULL) utilDie("%s", SDL_GetError()); @@ -86,10 +436,13 @@ int main(int argc, char *argv[]) { err = Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 44100 /* freq */ * 16 /* bits */ * 2 /* channels */ * 2 /* seconds */); if (err != 0) utilDie("%s", Mix_GetError()); + // Finish our setup + SDL_DisableScreenSaver(); + if (videoInit()) utilDie("Unable to initialize video player."); - videoHandle = videoLoad(filename, renderer); - if (videoHandle < 0) utilDie("Unable to load video file: %s", filename); + videoHandle = videoLoad(_confVideoFile, _confDataDir, renderer); + if (videoHandle < 0) utilDie("Unable to load video file: %s", _confVideoFile); videoPlay(videoHandle); @@ -148,10 +501,14 @@ int main(int argc, char *argv[]) { Mix_CloseAudio(); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); + SDL_EnableScreenSaver(); TTF_Quit(); IMG_Quit(); Mix_Quit(); SDL_Quit(); + if (_confDataDir) free(_confDataDir); + if (_confVideoFile) free(_confVideoFile); + if (_confScriptFile) free(_confScriptFile); return 0; } diff --git a/singe/preBuild.sh b/singe/preBuild.sh index 37566dc32..3e58215fa 100755 --- a/singe/preBuild.sh +++ b/singe/preBuild.sh @@ -73,6 +73,76 @@ function autoBuild() { } +function createExtensionHeader() { + local FFMPEG=$1 + local a= + local c=0 + + outputLicense + printf "\n\n#ifndef FFMPEG_EXTENSIONS_H\n#define FFMPEG_EXTENSIONS_H\n\n\n" + printf "// ===== THIS FILE IS AUTOMATICALLY GENERATED - DO NOT EDIT =====\n\n\n" + printf "#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wunused-variable\"\n" + printf "static char *ffmpegExtensions[] = {\n" + printf "\t" + getExtensions "${FFMPEG}" | sort | uniq -u | while read a; do + printf "\"${a}\", " + c=$((c+1)) + if [[ ${c} -ge 10 ]]; then + printf "\n\t" + c=0 + fi + done + printf "0\n};\n#pragma GCC diagnostic pop\n\n\n#endif // FFMPEG_EXTENSIONS_H\n" +} + + +function getExtensions() { + local FFMPEG=$1 + local a= + local b= + local c= + local d= + local e= + local f= + local g= + + "${FFMPEG}" -demuxers 2> /dev/null | while read a b c; do + if [[ "${a}x" == "Dx" ]]; then + "${FFMPEG}" -h demuxer=${b} 2> /dev/null | grep "Common extensions" | while read d e f; do + g=${f/./} + echo -e "${g//,/\\n}" + done + fi + done +} + + +function outputLicense() { + cat <<-LICENSE + /* + * + * Singe 2 + * Copyright (C) 2019 Scott Duensing + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + LICENSE +} + + # === zlib === if [[ ! -e "${G_INSTALLED}/lib/libz.a" ]]; then echo ${G_L} @@ -164,7 +234,10 @@ DEPS_CFLAGS="-I${G_INSTALLED}/include -I${G_INSTALLED}/include/opus" \ autoBuild libopusfile.a SDL2_mixer/external/opusfile-0.11 --disable-http # === FFMPEG === -autoBuild libavcodec.a ffmpeg "--disable-debug --disable-muxers --disable-encoders --disable-filters --disable-hwaccels --disable-network --disable-devices --disable-programs --enable-gpl" +autoBuild libavcodec.a ffmpeg "--disable-debug --disable-muxers --disable-encoders --disable-filters --disable-hwaccels --disable-network --disable-devices --enable-gpl" +if [[ ! -e extensions.h ]]; then + createExtensionHeader "${G_DEST}/installed/bin/ffmpeg" > extensions.h +fi # === FFMS2 === FFMPEG_LIBS="-L${G_INSTALLED}/lib -l:libavformat.a -l:libavcodec.a -l:libswscale.a -l:libavutil.a -l:libswresample.a -l:libz.a -l:liblzma.a -l:libbz2.a -lpthread -lXv -lX11 -lXext -lm" \ diff --git a/singe/singe.c b/singe/singe.c index f4504b0f6..cbb361365 100644 --- a/singe/singe.c +++ b/singe/singe.c @@ -23,3 +23,25 @@ #include #include #include + +#include "thirdparty/uthash.h" + +#include "common.h" +#include "util.h" +#include "singe.h" + + +// Command line options +char *_confVideoFile = NULL; +char *_confScriptFile = NULL; +char *_confDataDir = NULL; +int _confNoMouse = false; +int _confNoStats = false; +int _confNoSound = false; +int _confFullScreen = false; +int _confFullScreenWindow = false; +int _confVolumeVldp = 100; +int _confVolumeNonVldp = 100; +int _confScaleFactor = 100; +int _confXResolution = -1; +int _confYResolution = -1; diff --git a/singe/singe.h b/singe/singe.h index 331ff9d37..bf33d2415 100644 --- a/singe/singe.h +++ b/singe/singe.h @@ -23,4 +23,21 @@ #ifndef SINGE_H #define SINGE_H + +// Command line options +extern char *_confVideoFile; +extern char *_confScriptFile; +extern char *_confDataDir; +extern int _confNoMouse; +extern int _confNoStats; +extern int _confNoSound; +extern int _confFullScreen; +extern int _confFullScreenWindow; +extern int _confVolumeVldp; +extern int _confVolumeNonVldp; +extern int _confScaleFactor; +extern int _confXResolution; +extern int _confYResolution; + + #endif // SINGE_H diff --git a/singe/singe.pro b/singe/singe.pro index c05aef9c9..ad54d28e5 100644 --- a/singe/singe.pro +++ b/singe/singe.pro @@ -101,7 +101,8 @@ HEADERS += \ common.h \ util.h \ videoPlayer.h \ - singe.h + singe.h \ + extensions.h SOURCES += \ $$MANYMOUSE_SOURCES \ diff --git a/singe/util.c b/singe/util.c index 5e69ba6ab..7cfedbb25 100644 --- a/singe/util.c +++ b/singe/util.c @@ -22,12 +22,34 @@ #include #include +#include +#include #include -#include "common.h" #include "util.h" +__attribute__((__format__(__printf__, 1, 0))) +char *utilCreateString(char *format, ...) { + va_list args; + va_list argsCopy; + int size = 0; + char *buffer = NULL; + + va_start(args, format); + va_copy(argsCopy, args); + size = vsnprintf(NULL, 0, format, argsCopy) + 1; + va_end(argsCopy); + buffer = calloc(1, (size_t)size); + if (buffer) { + vsnprintf(buffer, (size_t)size, format, args); + } + va_end(args); + + return buffer; +} + + __attribute__((__format__(__printf__, 1, 0))) __attribute__((noreturn)) void utilDie(char *fmt, ...) { @@ -41,6 +63,69 @@ void utilDie(char *fmt, ...) { } +bool utilFileExists(char *filename) { + FILE *file; + if ((file = fopen(filename, "r+"))) { + fclose(file); + return true; + } + return false; +} + + +char *utilGetFileExtension(char *filename) { + char *start = filename + strlen(filename); + int x; + + // Scan through name and find the last '.' + for (x=0; x<(int)strlen(filename); x++) { + if (filename[x] == '.') { + start = &filename[x + 1]; + } + // Reset if we find a path separator + if (filename[x] == utilGetPathSeparator()) { + start = filename + strlen(filename); + } + } + + return start; +} + + +char *utilGetLastPathComponent(char *pathname) { + char *start = pathname; + int x; + + // Scan through name and find the last path separator + for (x=0; x<(int)strlen(pathname); x++) { + if (pathname[x] == utilGetPathSeparator()) { + start = &pathname[x + 1]; + } + } + + return start; +} + + +char utilGetPathSeparator(void) { +#ifdef _WIN32 + return '\\'; +#else + return '/'; +#endif +} + + +bool utilPathExists(char *pathname) { + DIR *dir = opendir(pathname); + if (dir) { + closedir(dir); + return true; + } + return false; +} + + __attribute__((__format__(__printf__, 1, 0))) void utilSay(char *fmt, ...) { va_list args; diff --git a/singe/util.h b/singe/util.h index f9a63d549..fcdd4df5a 100644 --- a/singe/util.h +++ b/singe/util.h @@ -23,7 +23,18 @@ #ifndef UTIL_H #define UTIL_H -void utilDie(char *fmt, ...); -void utilSay(char *fmt, ...); + +#include "common.h" + + +char *utilCreateString(char *format, ...); +void utilDie(char *fmt, ...); +bool utilFileExists(char *filename); +char *utilGetFileExtension(char *filename); +char *utilGetLastPathComponent(char *pathname); +char utilGetPathSeparator(void); +bool utilPathExists(char *pathname); +void utilSay(char *fmt, ...); + #endif // UTIL_H diff --git a/singe/videoPlayer.c b/singe/videoPlayer.c index 05511d45c..b361ed501 100644 --- a/singe/videoPlayer.c +++ b/singe/videoPlayer.c @@ -154,7 +154,7 @@ int videoIsPlaying(int playerIndex) { } -int videoLoad(char *filename, SDL_Renderer *renderer) { +int videoLoad(char *filename, char *indexPath, SDL_Renderer *renderer) { char indexName[1024]; int pixelFormats[2]; int result = -1; @@ -177,7 +177,7 @@ int videoLoad(char *filename, SDL_Renderer *renderer) { v->errInfo.SubType = FFMS_ERROR_SUCCESS; // Index file - snprintf(indexName, 1024, "%s.index", filename); + snprintf(indexName, 1024, "%s%c%s.index", indexPath, utilGetPathSeparator(), utilGetLastPathComponent(filename)); index = FFMS_ReadIndex(indexName, &v->errInfo); if (index) { if (FFMS_IndexBelongsToFile(index, filename, &v->errInfo)) { diff --git a/singe/videoPlayer.h b/singe/videoPlayer.h index 38b240091..d3e0f4380 100644 --- a/singe/videoPlayer.h +++ b/singe/videoPlayer.h @@ -29,7 +29,7 @@ int videoInit(void); int videoIsPlaying(int playerIndex); -int videoLoad(char *filename, SDL_Renderer *renderer); +int videoLoad(char *filename, char *indexPath, SDL_Renderer *renderer); int videoPause(int playerIndex); int videoPlay(int playerIndex); int videoQuit(void);