diff --git a/WaveSabreStandAlonePlayer/main.cpp b/WaveSabreStandAlonePlayer/main.cpp index e5676a22..76014ec5 100644 --- a/WaveSabreStandAlonePlayer/main.cpp +++ b/WaveSabreStandAlonePlayer/main.cpp @@ -2,6 +2,8 @@ #include using namespace WaveSabrePlayerLib; +#include +#include #include WaveSabreCore::Device *SongFactory(SongRenderer::DeviceId id) @@ -34,20 +36,135 @@ void progressCallback(double progress, void *data) printf("]"); } -int main(int argc, char **argv) +struct player_args +{ + const char* infile; + const char* outfile; + int nthreads; + bool prerender; + bool wavwriter; +}; + +static void print_usage(const char* prgm) +{ + printf("%s: WaveSabre standalone song player/renderer\n" + "Usage:\n" + "\t%s [-p|--prerender] [-w|--wav [out.wav]] [-t|--threads n] \n" + "\n" + "Arguments:\n" + "\tprerender prerender the song instead of rendering while playing.\n" + "\twav instead of playing back the song, write a WAV file. By default,\n" + "\t the output file is called `out.wav', but another may be supplied\n" + "\t immediately after this argument.\n" + "\tthreads the amount of threads to use in parallel for rendering. By\n" + "\t default, this number is 3.\n" + "\tinput.bin the input song file, exported by the WaveSabre exporter.\n" + , prgm, prgm); +} +static void parse_args(struct player_args* args, int argc, char** argv) { - bool writeWav = argc >= 3 && !strcmp(argv[2], "-w"); - bool preRender = argc == 3 && !strcmp(argv[2], "-p"); + if (argc < 2) + { + print_usage(argv[0]); + exit(1); + } + + args->infile = NULL; + args->outfile = NULL; + args->nthreads = 3; + args->prerender = false; + args->wavwriter = false; + + for (int i = 1; i < argc; ++i) + { + if (argv[i][0] == '-') + { + const char* as = argv[i] + 1; // skip arg prefix char ('-') + + if (!strcmp(as, "h") || !strcmp(as, "-help")) + { + print_usage(argv[0]); + exit(0); + } + // TODO: option for printing version info + if (!strcmp(as, "p") || !strcmp(as, "-prerender")) + { + args->prerender = true; + continue; + } + if (!strcmp(as, "w") || !strcmp(as, "-wav")) + { + args->wavwriter = true; + + if (i+1 < argc && argv[i+1][0] != '-') + { + // last argument, and no input file set yet, so we really + // need to prioritise the input file here + if (argc-1 == i+1 && args->infile == NULL) + { + args->outfile = "out.wav"; + } + else + { + args->outfile = argv[i+1]; + ++i; + } + } + else + { + args->outfile = "out.wav"; + } + continue; + } + if (!strcmp(as, "t") || !strcmp(as, "-threads")) + { + if (i+1 == argc) + { + printf("Expecting thread amount\n"); + exit(2); + } + + ++i; + int res = sscanf(argv[i], "%d", &args->nthreads); + if (res != 1 || args->nthreads < 0) + { + printf("Can't parse thread amount '%s'\n", argv[i]); + exit(2); + } + + continue; + } + + printf("Unrecognised option '%s', ignoring...\n", argv[i]); + } + else + { + if (args->infile != NULL) + { + printf("Unexpected argument '%s'\n", argv[i]); + exit(2); + } - const int numRenderThreads = 3; + args->infile = argv[i]; + } + } +} + +int main(int argc, char **argv) +{ + struct player_args args; + parse_args(&args, argc, argv); FILE * pFile; long lSize; unsigned char * buffer; size_t result; - pFile = fopen(argv[1], "rb"); - if (pFile == NULL) { printf("File error\n"); exit(1); } + pFile = fopen(args.infile, "rb"); + if (pFile == NULL) { + printf("Can't open input file '%s'\n", args.infile); + exit(1); + } // obtain file size: fseek(pFile, 0, SEEK_END); @@ -59,7 +176,10 @@ int main(int argc, char **argv) // copy the file into the buffer: result = fread(buffer, 1, lSize, pFile); - if (result != lSize) { printf("Reading error\n"); exit(3); } + if (result != lSize) { + printf("Can't read from input file '%s'\n", args.infile); + exit(3); + } // terminate fclose(pFile); @@ -68,34 +188,41 @@ int main(int argc, char **argv) song.blob = buffer; song.factory = SongFactory; - if (writeWav) + if (args.wavwriter) { - WavWriter wavWriter(&song, numRenderThreads); + FILE* outf = fopen(args.outfile, "wb"); + if (!outf) + { + printf("Can't open output file '%s'\n", args.outfile); + exit(4); + } + fclose(outf); // close again because WavWriter wants a file path + + WavWriter wavWriter(&song, args.nthreads); printf("WAV writer activated.\n"); - auto fileName = argc >= 4 ? argv[3] : "out.wav"; printf("Rendering...\n"); - wavWriter.Write(fileName, progressCallback, nullptr); + wavWriter.Write(args.outfile, progressCallback, nullptr); - printf("\n\nWAV file written to \"%s\". Enjoy.\n", fileName); + printf("\n\nWAV file written to \"%s\". Enjoy.\n", args.outfile); } else { IPlayer *player; - if (preRender) + if (args.prerender) { printf("Prerender activated.\n"); printf("Rendering...\n"); - player = new PreRenderPlayer(&song, numRenderThreads, progressCallback, nullptr); + player = new PreRenderPlayer(&song, args.nthreads, progressCallback, nullptr); printf("\n\n"); } else { - player = new RealtimePlayer(&song, numRenderThreads); + player = new RealtimePlayer(&song, args.nthreads); } printf("Realtime player activated. Press ESC to quit.\n"); @@ -108,7 +235,6 @@ int main(int argc, char **argv) int seconds = (int)songPos % 60; int hundredths = (int)(songPos * 100.0) % 100; printf("\r %.1i:%.2i.%.2i", minutes, seconds, hundredths); - Sleep(10); } printf("\n"); @@ -118,4 +244,4 @@ int main(int argc, char **argv) free(buffer); return 0; -} \ No newline at end of file +}