comparison sidinfo.c @ 89:d9cb7c635e7b

Implement initial SLDB support.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 12 Feb 2016 01:17:52 +0200
parents 1e89b757f8a1
children 2ab9ab4b59eb
comparison
equal deleted inserted replaced
88:c5ff71d64e53 89:d9cb7c635e7b
3 * Written by Matti 'ccr' Hämäläinen <ccr@tnsp.org> 3 * Written by Matti 'ccr' Hämäläinen <ccr@tnsp.org>
4 * (C) Copyright 2014-2016 Tecnic Software productions (TNSP) 4 * (C) Copyright 2014-2016 Tecnic Software productions (TNSP)
5 */ 5 */
6 #include "th_args.h" 6 #include "th_args.h"
7 #include "th_string.h" 7 #include "th_string.h"
8 #include "th_file.h"
8 #include "sidlib.h" 9 #include "sidlib.h"
9 10
10 11
11 // Some constants 12 // Some constants
13 #define SET_SLDB_FILENAME "Songlengths.txt"
12 14
13 15
14 // Flags for various information fields 16 // Flags for various information fields
15 enum 17 enum
16 { 18 {
30 SIF_SID_COPYRIGHT = 0x00000800, 32 SIF_SID_COPYRIGHT = 0x00000800,
31 SIF_PLAYER_TYPE = 0x00001000, 33 SIF_PLAYER_TYPE = 0x00001000,
32 SIF_PLAYSID_TUNE = 0x00002000, 34 SIF_PLAYSID_TUNE = 0x00002000,
33 SIF_VIDEO_CLOCK = 0x00004000, 35 SIF_VIDEO_CLOCK = 0x00004000,
34 SIF_SID_MODEL = 0x00008000, 36 SIF_SID_MODEL = 0x00008000,
37 SIF_SONGLENGTHS = 0x00010000,
35 38
36 SIF_DATA_SIZE = 0x00100000, 39 SIF_DATA_SIZE = 0x00100000,
37 SIF_HASH = 0x00200000, 40 SIF_HASH = 0x00200000,
38 SIF_FILENAME = 0x01000000, 41 SIF_FILENAME = 0x01000000,
39 42
84 { SIF_SID_NAME , "Name" , NULL }, 87 { SIF_SID_NAME , "Name" , NULL },
85 { SIF_SID_AUTHOR , "Author" , NULL }, 88 { SIF_SID_AUTHOR , "Author" , NULL },
86 { SIF_SID_COPYRIGHT , "Copyright" , NULL }, 89 { SIF_SID_COPYRIGHT , "Copyright" , NULL },
87 { SIF_HASH , "Hash" , NULL }, 90 { SIF_HASH , "Hash" , NULL },
88 91
92 { SIF_SONGLENGTHS , "Songlengths", "Song lengths" },
93
89 { SIF_ALL , "All" , NULL }, 94 { SIF_ALL , "All" , NULL },
90 }; 95 };
91 96
92 static const int noptPSFlags = sizeof(optPSFlags) / sizeof(optPSFlags[0]); 97 static const int noptPSFlags = sizeof(optPSFlags) / sizeof(optPSFlags[0]);
93 98
94 99
95 // Option variables 100 // Option variables
101 char *setHVSCPath = NULL,
102 *setSLDBPath = NULL;
96 BOOL optParsable = FALSE, 103 BOOL optParsable = FALSE,
97 optNoNamePrefix = FALSE, 104 optNoNamePrefix = FALSE,
98 optHexadecimal = FALSE, 105 optHexadecimal = FALSE,
99 optOneLine = FALSE; 106 optOneLine = FALSE;
100 char *optFieldSep = NULL; 107 char *optFieldSep = NULL;
101 uint32_t optFields = SIF_ALL; 108 uint32_t optFields = SIF_ALL;
102 int optNFiles = 0; 109 int optNFiles = 0;
103 110
104 PSFStack optFormat; 111 PSFStack optFormat;
112
113 SIDLibSLDB *sidSLDB = NULL;
105 114
106 115
107 // Define option arguments 116 // Define option arguments
108 static const th_optarg_t optList[] = 117 static const th_optarg_t optList[] =
109 { 118 {
113 { 5, 'n', "noprefix", "Output without field name prefix", OPT_NONE }, 122 { 5, 'n', "noprefix", "Output without field name prefix", OPT_NONE },
114 { 6, 'l', "line", "Output in one line format, -l <field separator>", OPT_ARGREQ }, 123 { 6, 'l', "line", "Output in one line format, -l <field separator>", OPT_ARGREQ },
115 { 3, 'f', "fields", "Show only specified field(s)", OPT_ARGREQ }, 124 { 3, 'f', "fields", "Show only specified field(s)", OPT_ARGREQ },
116 { 4, 'x', "hex", "Use hexadecimal values", OPT_NONE }, 125 { 4, 'x', "hex", "Use hexadecimal values", OPT_NONE },
117 { 7, 'F', "format", "Use given format string (see below)", OPT_ARGREQ }, 126 { 7, 'F', "format", "Use given format string (see below)", OPT_ARGREQ },
127 { 8, 'H', "hvsc", "Specify path to HVSC documents directory", OPT_ARGREQ },
128 { 9, 'S', "sldb", "Specify Songlengths.txt file (use -H if possible)", OPT_ARGREQ },
118 }; 129 };
119 130
120 static const int optListN = sizeof(optList) / sizeof(optList[0]); 131 static const int optListN = sizeof(optList) / sizeof(optList[0]);
121 132
122 133
146 "Example: %s -x -p -f hash,copyright somesidfile.sid\n" 157 "Example: %s -x -p -f hash,copyright somesidfile.sid\n"
147 "\n" 158 "\n"
148 "Format strings for '-F' option are composed of @fields@ that\n" 159 "Format strings for '-F' option are composed of @fields@ that\n"
149 "are expanded to their value. Also, escape sequences \\r, \\n and \\t\n" 160 "are expanded to their value. Also, escape sequences \\r, \\n and \\t\n"
150 "can be used: -F \"hash=@hash@\\ncopy=@copyright@\\n\"\n" 161 "can be used: -F \"hash=@hash@\\ncopy=@copyright@\\n\"\n"
162 "\n"
163 "When specifying HVSC path, it is preferable to use -H/--hvsc option,\n"
164 "as STIL.txt and Songlengths.txt will be automatically used from there.\n"
151 , th_prog_name); 165 , th_prog_name);
152 } 166 }
153 167
154 168
155 int argMatchPSField(const char *field) 169 int argMatchPSField(const char *field)
378 case 7: 392 case 7:
379 if (!argParsePSFormatStr(&optFormat, optArg)) 393 if (!argParsePSFormatStr(&optFormat, optArg))
380 return FALSE; 394 return FALSE;
381 break; 395 break;
382 396
397 case 8:
398 setHVSCPath = th_strdup(optArg);
399 break;
400
401 case 9:
402 setSLDBPath = th_strdup(optArg);
403 break;
404
383 default: 405 default:
384 THERR("Unknown option '%s'.\n", currArg); 406 THERR("Unknown option '%s'.\n", currArg);
385 return FALSE; 407 return FALSE;
386 } 408 }
387 409
408 str++; 430 str++;
409 } 431 }
410 } 432 }
411 433
412 434
413 static void siPrintFieldPrefix(FILE *outFile, const char *name) 435 static void siPrintFieldPrefix(FILE *outFile, const PSFOption *opt)
414 { 436 {
437 const char *name = (optParsable || opt->lname == NULL) ? opt->name : opt->lname;
415 if (!optNoNamePrefix && !optFormat.nitems) 438 if (!optNoNamePrefix && !optFormat.nitems)
416 fprintf(outFile, optParsable ? "%s=" : "%-20s : ", name); 439 fprintf(outFile, optParsable ? "%s=" : "%-20s : ", name);
417 } 440 }
418 441
419 442
430 if (optFormat.nitems || (optFields & opt->flag)) 453 if (optFormat.nitems || (optFields & opt->flag))
431 { 454 {
432 va_list ap; 455 va_list ap;
433 const char *fmt = optHexadecimal ? (xaltfmt != NULL ? xaltfmt : xfmt) : xfmt; 456 const char *fmt = optHexadecimal ? (xaltfmt != NULL ? xaltfmt : xfmt) : xfmt;
434 457
435 siPrintFieldPrefix(outFile, (optParsable || opt->lname == NULL) ? opt->name : opt->lname); 458 siPrintFieldPrefix(outFile, opt);
436 459
437 va_start(ap, xaltfmt); 460 va_start(ap, xaltfmt);
438 vfprintf(outFile, fmt, ap); 461 vfprintf(outFile, fmt, ap);
439 va_end(ap); 462 va_end(ap);
440 463
441 siPrintFieldSeparator(outFile); 464 siPrintFieldSeparator(outFile);
442 *shown = TRUE; 465 *shown = TRUE;
443 } 466 }
444 } 467 }
468
445 469
446 #define PR(xfmt, xaltfmt, ...) siPrintPSIDInfoLine(outFile, shown, xindex, xfmt, xaltfmt, __VA_ARGS__ ) 470 #define PR(xfmt, xaltfmt, ...) siPrintPSIDInfoLine(outFile, shown, xindex, xfmt, xaltfmt, __VA_ARGS__ )
447 471
448 472
449 static void siPrintPSIDInformationField(FILE *outFile, const char *filename, const PSIDHeader *psid, BOOL *shown, const int xindex) 473 static void siPrintPSIDInformationField(FILE *outFile, const char *filename, const PSIDHeader *psid, BOOL *shown, const int xindex)
481 case 17: 505 case 17:
482 { 506 {
483 const PSFOption *opt = &optPSFlags[xindex]; 507 const PSFOption *opt = &optPSFlags[xindex];
484 if (optFormat.nitems || (optFields & opt->flag)) 508 if (optFormat.nitems || (optFields & opt->flag))
485 { 509 {
486 siPrintFieldPrefix(outFile, "Hash"); 510 siPrintFieldPrefix(outFile, opt);
487 th_md5_print(outFile, psid->hash); 511 th_md5_print(outFile, psid->hash);
488 siPrintFieldSeparator(outFile); 512 siPrintFieldSeparator(outFile);
489 } 513 }
490 } 514 }
491 break; 515 break;
516
517 case 18:
518 {
519 const PSFOption *opt = &optPSFlags[xindex];
520 if (optFormat.nitems || (optFields & opt->flag))
521 {
522 siPrintFieldPrefix(outFile, opt);
523 if (psid->lengths != NULL)
524 {
525 int i;
526 for (i = 0; i < psid->lengths->nlengths; i++)
527 {
528 int len = psid->lengths->lengths[i];
529 fprintf(outFile, "%d:%d%s", len / 60, len % 60,
530 (i < psid->lengths->nlengths - 1) ? " " : "");
531 }
532 }
533 siPrintFieldSeparator(outFile);
534 }
535 }
536 break;
537
492 } 538 }
493 } 539 }
494 540
495 541
496 BOOL argHandleFile(char *filename) 542 BOOL argHandleFile(char *filename)
515 { 561 {
516 THERR("Error reading %s\n", filename); 562 THERR("Error reading %s\n", filename);
517 goto error; 563 goto error;
518 } 564 }
519 565
566 // Get songlength information, if any
567 if (sidSLDB != NULL)
568 psid.lengths = si_sldb_get_by_hash(sidSLDB, psid.hash);
569
520 // Output 570 // Output
521 if (optFormat.nitems) 571 if (optFormat.nitems)
522 { 572 {
523 for (index = 0; index < optFormat.nitems; index++) 573 for (index = 0; index < optFormat.nitems; index++)
524 { 574 {
573 { 623 {
574 optParsable = FALSE; 624 optParsable = FALSE;
575 optNoNamePrefix = TRUE; 625 optNoNamePrefix = TRUE;
576 } 626 }
577 627
628 if (setHVSCPath != NULL)
629 {
630 if (setSLDBPath == NULL)
631 setSLDBPath = th_strdup_printf("%s%c%s", setHVSCPath, TH_DIR_SEPARATOR, SET_SLDB_FILENAME);
632 }
633
634 if (setSLDBPath != NULL)
635 {
636 // Initialize SLDB
637 int ret;
638 th_ioctx *ctx = th_io_new(&th_stdio_io_ops);
639 if (ctx == NULL || th_io_open(ctx, setSLDBPath, "r") != THERR_OK)
640 {
641 THERR("Ululu!\n");
642 goto out;
643 }
644
645 if ((sidSLDB = si_sldb_new()) == NULL ||
646 si_sldb_read(ctx, sidSLDB) != THERR_OK)
647 {
648 THERR("Error parsing SLDB.\n");
649 goto out;
650 }
651
652 if ((ret = si_sldb_build_index(sidSLDB)) != THERR_OK)
653 {
654 THERR("Error building SLDB index: %s.\n",
655 th_error_str(ret));
656 goto out;
657 }
658 }
659
578 // Process files 660 // Process files
579 if (!th_args_process(argc, argv, optList, optListN, 661 if (!th_args_process(argc, argv, optList, optListN,
580 argHandleOpt, argHandleFile, OPTH_ONLY_OTHER)) 662 argHandleOpt, argHandleFile, OPTH_ONLY_OTHER))
581 return -2; 663 goto out;
582 664
583 if (optNFiles == 0) 665 if (optNFiles == 0)
584 { 666 {
585 argShowHelp(); 667 argShowHelp();
586 THERR("No filename(s) specified.\n"); 668 THERR("No filename(s) specified.\n");
587 } 669 }
588 670
671 out:
672
673 th_free(setHVSCPath);
674 th_free(setSLDBPath);
675 th_free(setSTILPath);
676 si_sldb_free(sidSLDB);
589 return 0; 677 return 0;
590 } 678 }