# HG changeset patch # User Matti Hamalainen # Date 1455232672 -7200 # Node ID d9cb7c635e7b9f0e7777d0ab6efec848319bdde7 # Parent c5ff71d64e53bf3dd9b6d303381b6cc0baa3dbde Implement initial SLDB support. diff -r c5ff71d64e53 -r d9cb7c635e7b sidinfo.c --- a/sidinfo.c Fri Feb 12 01:13:48 2016 +0200 +++ b/sidinfo.c Fri Feb 12 01:17:52 2016 +0200 @@ -5,10 +5,12 @@ */ #include "th_args.h" #include "th_string.h" +#include "th_file.h" #include "sidlib.h" // Some constants +#define SET_SLDB_FILENAME "Songlengths.txt" // Flags for various information fields @@ -32,6 +34,7 @@ SIF_PLAYSID_TUNE = 0x00002000, SIF_VIDEO_CLOCK = 0x00004000, SIF_SID_MODEL = 0x00008000, + SIF_SONGLENGTHS = 0x00010000, SIF_DATA_SIZE = 0x00100000, SIF_HASH = 0x00200000, @@ -86,6 +89,8 @@ { SIF_SID_COPYRIGHT , "Copyright" , NULL }, { SIF_HASH , "Hash" , NULL }, + { SIF_SONGLENGTHS , "Songlengths", "Song lengths" }, + { SIF_ALL , "All" , NULL }, }; @@ -93,6 +98,8 @@ // Option variables +char *setHVSCPath = NULL, + *setSLDBPath = NULL; BOOL optParsable = FALSE, optNoNamePrefix = FALSE, optHexadecimal = FALSE, @@ -103,6 +110,8 @@ PSFStack optFormat; +SIDLibSLDB *sidSLDB = NULL; + // Define option arguments static const th_optarg_t optList[] = @@ -115,6 +124,8 @@ { 3, 'f', "fields", "Show only specified field(s)", OPT_ARGREQ }, { 4, 'x', "hex", "Use hexadecimal values", OPT_NONE }, { 7, 'F', "format", "Use given format string (see below)", OPT_ARGREQ }, + { 8, 'H', "hvsc", "Specify path to HVSC documents directory", OPT_ARGREQ }, + { 9, 'S', "sldb", "Specify Songlengths.txt file (use -H if possible)", OPT_ARGREQ }, }; static const int optListN = sizeof(optList) / sizeof(optList[0]); @@ -148,6 +159,9 @@ "Format strings for '-F' option are composed of @fields@ that\n" "are expanded to their value. Also, escape sequences \\r, \\n and \\t\n" "can be used: -F \"hash=@hash@\\ncopy=@copyright@\\n\"\n" + "\n" + "When specifying HVSC path, it is preferable to use -H/--hvsc option,\n" + "as STIL.txt and Songlengths.txt will be automatically used from there.\n" , th_prog_name); } @@ -380,6 +394,14 @@ return FALSE; break; + case 8: + setHVSCPath = th_strdup(optArg); + break; + + case 9: + setSLDBPath = th_strdup(optArg); + break; + default: THERR("Unknown option '%s'.\n", currArg); return FALSE; @@ -410,8 +432,9 @@ } -static void siPrintFieldPrefix(FILE *outFile, const char *name) +static void siPrintFieldPrefix(FILE *outFile, const PSFOption *opt) { + const char *name = (optParsable || opt->lname == NULL) ? opt->name : opt->lname; if (!optNoNamePrefix && !optFormat.nitems) fprintf(outFile, optParsable ? "%s=" : "%-20s : ", name); } @@ -432,7 +455,7 @@ va_list ap; const char *fmt = optHexadecimal ? (xaltfmt != NULL ? xaltfmt : xfmt) : xfmt; - siPrintFieldPrefix(outFile, (optParsable || opt->lname == NULL) ? opt->name : opt->lname); + siPrintFieldPrefix(outFile, opt); va_start(ap, xaltfmt); vfprintf(outFile, fmt, ap); @@ -443,6 +466,7 @@ } } + #define PR(xfmt, xaltfmt, ...) siPrintPSIDInfoLine(outFile, shown, xindex, xfmt, xaltfmt, __VA_ARGS__ ) @@ -483,12 +507,34 @@ const PSFOption *opt = &optPSFlags[xindex]; if (optFormat.nitems || (optFields & opt->flag)) { - siPrintFieldPrefix(outFile, "Hash"); + siPrintFieldPrefix(outFile, opt); th_md5_print(outFile, psid->hash); siPrintFieldSeparator(outFile); } } break; + + case 18: + { + const PSFOption *opt = &optPSFlags[xindex]; + if (optFormat.nitems || (optFields & opt->flag)) + { + siPrintFieldPrefix(outFile, opt); + if (psid->lengths != NULL) + { + int i; + for (i = 0; i < psid->lengths->nlengths; i++) + { + int len = psid->lengths->lengths[i]; + fprintf(outFile, "%d:%d%s", len / 60, len % 60, + (i < psid->lengths->nlengths - 1) ? " " : ""); + } + } + siPrintFieldSeparator(outFile); + } + } + break; + } } @@ -517,6 +563,10 @@ goto error; } + // Get songlength information, if any + if (sidSLDB != NULL) + psid.lengths = si_sldb_get_by_hash(sidSLDB, psid.hash); + // Output if (optFormat.nitems) { @@ -575,10 +625,42 @@ optNoNamePrefix = TRUE; } + if (setHVSCPath != NULL) + { + if (setSLDBPath == NULL) + setSLDBPath = th_strdup_printf("%s%c%s", setHVSCPath, TH_DIR_SEPARATOR, SET_SLDB_FILENAME); + } + + if (setSLDBPath != NULL) + { + // Initialize SLDB + int ret; + th_ioctx *ctx = th_io_new(&th_stdio_io_ops); + if (ctx == NULL || th_io_open(ctx, setSLDBPath, "r") != THERR_OK) + { + THERR("Ululu!\n"); + goto out; + } + + if ((sidSLDB = si_sldb_new()) == NULL || + si_sldb_read(ctx, sidSLDB) != THERR_OK) + { + THERR("Error parsing SLDB.\n"); + goto out; + } + + if ((ret = si_sldb_build_index(sidSLDB)) != THERR_OK) + { + THERR("Error building SLDB index: %s.\n", + th_error_str(ret)); + goto out; + } + } + // Process files if (!th_args_process(argc, argv, optList, optListN, argHandleOpt, argHandleFile, OPTH_ONLY_OTHER)) - return -2; + goto out; if (optNFiles == 0) { @@ -586,5 +668,11 @@ THERR("No filename(s) specified.\n"); } +out: + + th_free(setHVSCPath); + th_free(setSLDBPath); + th_free(setSTILPath); + si_sldb_free(sidSLDB); return 0; }