summaryrefslogtreecommitdiff
path: root/plugins/uade2/uade-2.13/src/frontends/common/songinfo.c
diff options
context:
space:
mode:
authorGravatar waker <wakeroid@gmail.com>2011-03-23 21:26:26 +0100
committerGravatar waker <wakeroid@gmail.com>2011-03-23 21:26:26 +0100
commitfd302d7abc36942e7ff14b22fae1e72b4495bef1 (patch)
tree2a36f8361c907a5bea91a9d905957a709f31ea64 /plugins/uade2/uade-2.13/src/frontends/common/songinfo.c
parent11e63b53b8c91da89592c373bb32fc2b656c6024 (diff)
renamed soundtouch and uade2 plugin folders and output .so
Diffstat (limited to 'plugins/uade2/uade-2.13/src/frontends/common/songinfo.c')
-rw-r--r--plugins/uade2/uade-2.13/src/frontends/common/songinfo.c721
1 files changed, 721 insertions, 0 deletions
diff --git a/plugins/uade2/uade-2.13/src/frontends/common/songinfo.c b/plugins/uade2/uade-2.13/src/frontends/common/songinfo.c
new file mode 100644
index 00000000..5997b183
--- /dev/null
+++ b/plugins/uade2/uade-2.13/src/frontends/common/songinfo.c
@@ -0,0 +1,721 @@
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdint.h>
+#include <ctype.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "songinfo.h"
+#include "uadeutils.h"
+#include "ossupport.h"
+#include "amifilemagic.h"
+#include "support.h"
+
+
+static void asciiline(char *dst, unsigned char *buf)
+{
+ int i, c;
+ for (i = 0; i < 16; i++) {
+ c = buf[i];
+ if (isgraph(c) || c == ' ') {
+ dst[i] = c;
+ } else {
+ dst[i] = '.';
+ }
+ }
+ dst[i] = 0;
+}
+
+static int hexdump(char *info, size_t maxlen, char *filename, size_t toread)
+{
+ FILE *f;
+ size_t rb, ret;
+ uint8_t *buf;
+
+ assert(maxlen >= 8192);
+
+ f = fopen(filename, "rb");
+ if (f == NULL)
+ return 0;
+
+ buf = malloc(toread);
+ if (buf == NULL)
+ return 0;
+
+ rb = 0;
+ while (rb < toread) {
+ ret = fread(&buf[rb], 1, toread - rb, f);
+ if (ret == 0)
+ break;
+ rb += ret;
+ }
+
+ if (rb > 0) {
+ size_t roff = 0;
+ size_t woff = 0;
+
+ while (roff < rb) {
+ int iret;
+
+ if (woff >= maxlen)
+ break;
+
+ if (woff + 32 >= maxlen) {
+ strcpy(&info[woff], "\nbuffer overflow...\n");
+ woff += strlen(&info[woff]);
+ break;
+ }
+
+ iret = snprintf(&info[woff], maxlen - woff, "%.3zx: ",
+ roff);
+ assert(iret > 0);
+ woff += iret;
+
+ if (woff >= maxlen)
+ break;
+
+ if (roff + 16 > rb) {
+ iret = snprintf(&info[woff], maxlen - woff,
+ "Aligned line ");
+ assert(iret > 0);
+ woff += iret;
+
+ } else {
+ char dbuf[17];
+ asciiline(dbuf, &buf[roff]);
+ iret = snprintf(&info[woff], maxlen - woff,
+ "%.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x |%s|",
+ buf[roff + 0], buf[roff + 1],
+ buf[roff + 2], buf[roff + 3],
+ buf[roff + 4], buf[roff + 5],
+ buf[roff + 6], buf[roff + 7],
+ buf[roff + 8], buf[roff + 9],
+ buf[roff + 10], buf[roff + 11],
+ buf[roff + 12], buf[roff + 13],
+ buf[roff + 14], buf[roff + 15],
+ dbuf);
+ assert(iret > 0);
+ woff += iret;
+ }
+
+ if (woff >= maxlen)
+ break;
+
+ iret = snprintf(&info[woff], maxlen - woff, "\n");
+ woff += iret;
+
+ roff += 16;
+ }
+
+ if (woff >= maxlen)
+ woff = maxlen - 1;
+ info[woff] = 0;
+ }
+
+ fclose(f);
+ free(buf);
+ return rb == 0;
+}
+
+static size_t find_tag(uint8_t * buf, size_t startoffset, size_t buflen,
+ uint8_t * tag, size_t taglen)
+{
+ uint8_t *treasure;
+
+ if (startoffset >= buflen)
+ return -1;
+
+ treasure = memmem(buf + startoffset, buflen - startoffset, tag, taglen);
+ if (treasure == NULL)
+ return -1;
+
+ return (size_t) (treasure - buf);
+}
+
+static int string_checker(unsigned char *str, size_t off, size_t maxoff)
+{
+ assert(maxoff > 0);
+ while (off < maxoff) {
+ if (*str == 0)
+ return 1;
+ off++;
+ str++;
+ }
+ return 0;
+}
+
+/* Wanted Team's loadseg modules */
+static void process_WTWT_mod(char *credits, size_t credits_len,
+ unsigned char *buf, size_t len, char *lo,
+ char *hi, int rel)
+{
+ int offset, txt_offset, chunk;
+ char tmpstr[256];
+
+ /* check for Magic ID */
+ offset = find_tag((uint8_t *) buf, 0, len, (uint8_t *) lo, 4);
+ if (offset == -1)
+ return;
+
+ offset =
+ find_tag((uint8_t *) buf, offset + 4, offset + 8, (uint8_t *) hi,
+ 4);
+ if (offset == -1)
+ return;
+
+ chunk = offset - 8; /* here's where our first chunk should be */
+ offset = offset + rel; /* offset to our info pointers */
+
+ if (chunk < len && offset < len) {
+ txt_offset = read_be_u32(buf + offset) + chunk;
+ if (txt_offset < len && txt_offset != chunk) {
+ if (!string_checker(buf, txt_offset, len))
+ return;
+ snprintf(tmpstr, sizeof tmpstr, "\nMODULENAME:\n %s\n",
+ buf + txt_offset);
+ strlcat(credits, tmpstr, credits_len);
+
+ }
+ txt_offset = read_be_u32(buf + offset + 4) + chunk;
+ if (txt_offset < len && txt_offset != chunk) {
+ if (!string_checker(buf, txt_offset, len))
+ return;
+ snprintf(tmpstr, sizeof tmpstr, "\nAUTHORNAME:\n %s\n",
+ buf + txt_offset);
+ strlcat(credits, tmpstr, credits_len);
+ }
+
+ txt_offset = read_be_u32(buf + offset + 8) + chunk;
+ if (txt_offset < len && txt_offset != chunk) {
+ if (!string_checker(buf, txt_offset, len))
+ return;
+ snprintf(tmpstr, sizeof tmpstr, "\nSPECIALINFO:\n %s",
+ buf + txt_offset);
+ strlcat(credits, tmpstr, credits_len);
+ }
+ }
+}
+
+/* Get the info out of the AHX module data*/
+static void process_ahx_mod(char *credits, size_t credits_len,
+ unsigned char *buf, size_t len)
+{
+ int i;
+ size_t offset;
+ char tmpstr[256];
+
+ if (len < 13)
+ return;
+
+ offset = read_be_u16(buf + 4);
+
+ if (offset >= len)
+ return;
+
+ if (!string_checker(buf, offset, len))
+ return;
+
+ snprintf(tmpstr, sizeof tmpstr, "\nSong title: %s\n", buf + offset);
+ strlcat(credits, tmpstr, credits_len);
+
+ for (i = 0; i < buf[12]; i++) {
+ if (!string_checker(buf, offset, len))
+ break;
+ offset = offset + 1 + strlen((char *)buf + offset);
+ if (offset < len) {
+ snprintf(tmpstr, 256, "\n %s", buf + offset);
+ strlcat(credits, tmpstr, credits_len);
+ }
+ }
+}
+
+/* Get the info out of the protracker module data*/
+static void process_ptk_mod(char *credits, size_t credits_len, int inst,
+ uint8_t * buf, size_t len)
+{
+ int i;
+ char tmpstr[256];
+
+ if (!string_checker(buf, 0, len))
+ return;
+
+ snprintf(tmpstr, 35, "\nSong title: %s", buf);
+ strlcat(credits, tmpstr, credits_len);
+
+ if (inst == 31) {
+ if (len >= 0x43c) {
+ snprintf(tmpstr, sizeof tmpstr,
+ "\nmax positions: %d\n", buf[0x3b6]);
+ strlcat(credits, tmpstr, credits_len);
+ }
+ } else {
+ if (len >= 0x1da) {
+ snprintf(tmpstr, sizeof tmpstr,
+ "\nmax positions: %d\n", buf[0x1d6]);
+ strlcat(credits, tmpstr, credits_len);
+ }
+ }
+
+ snprintf(tmpstr, sizeof tmpstr, "\nINST - NAME SIZE VOL FINE LSTART LSIZE\n");
+ strlcat(credits, tmpstr, credits_len);
+ if (len >= (0x14 + inst * 0x1e)) {
+ for (i = 0; i < inst; i++) {
+ if (!string_checker(buf, 0x14 + i * 0x1e, len))
+ break;
+ snprintf(tmpstr, sizeof tmpstr, "[%2d] - ", i + 1);
+ strlcat(credits, tmpstr, credits_len);
+ snprintf(tmpstr, 23, "%-23s", buf + 0x14 + (i * 0x1e));
+ strlcat(credits, tmpstr, credits_len);
+ snprintf(tmpstr, sizeof tmpstr,
+ " %6d %2d %2d %6d %6d\n",
+ read_be_u16(buf + 42 + i * 0x1e) * 2,
+ buf[45 + i * 0x1e], buf[44 + i * 0x1e],
+ read_be_u16(buf + 46 + i * 0x1e) * 2,
+ read_be_u16(buf + 48 + i * 0x1e) * 2);
+ strlcat(credits, tmpstr, credits_len);
+ }
+ }
+}
+
+/* Get the info out of the digibooster module data*/
+static void process_digi_mod(char *credits, size_t credits_len,
+ uint8_t * buf, size_t len)
+{
+ int i;
+ char tmpstr[256];
+
+ if (len < (642 + 0x30 * 0x1e))
+ return;
+
+ if (!string_checker(buf, 610, len))
+ return;
+
+ snprintf(tmpstr, 0x2f, "\nSong title: %s \n", buf + 610);
+ strlcat(credits, tmpstr, credits_len);
+
+ snprintf(tmpstr, sizeof tmpstr, "max positions: %d\n", buf[47]);
+ strlcat(credits, tmpstr, credits_len);
+
+ snprintf(tmpstr, sizeof tmpstr, "\nINST - NAME SIZE VOL FINE LSTART LSIZE\n");
+ strlcat(credits, tmpstr, credits_len);
+ if (len >= (642 + 0x1f * 0x1e)) {
+ for (i = 0; i < 0x1f; i++) {
+ if (!string_checker(buf, 642 + i * 0x1e, len))
+ break;
+ snprintf(tmpstr, sizeof tmpstr, "[%2d] - ", i + 1);
+ strlcat(credits, tmpstr, credits_len);
+ snprintf(tmpstr, 30, "%-30s", buf + 642 + (i * 0x1e));
+ strlcat(credits, tmpstr, credits_len);
+ snprintf(tmpstr, sizeof tmpstr,
+ " %11d %2d %3d %11d %11d\n",
+ read_be_u32(buf + 176 + i * 4), buf[548 + i],
+ buf[579 + i], read_be_u32(buf + 300 + i * 4),
+ read_be_u32(buf + 424 + i * 4));
+ strlcat(credits, tmpstr, credits_len);
+ }
+ }
+}
+
+/* Get the info out of custom song. FIX ME, clean this function. */
+static void process_custom(char *credits, size_t credits_len,
+ unsigned char *buf, size_t len)
+{
+ char tmpstr[1024];
+ unsigned char *hunk;
+ unsigned char *tag_table;
+ int hunk_size;
+ int table_size;
+
+ int i;
+ int offset;
+ unsigned int x, y;
+ unsigned char startpattern[4] = { 0x70, 0xff, 0x4e, 0x75 };
+
+ if (len < 4)
+ return;
+
+ if (read_be_u32(buf) != 0x000003f3)
+ return;
+
+ i = find_tag(buf, 0, len, startpattern, sizeof startpattern);
+ if (i == -1 || (i + 12) >= len)
+ return;
+
+ if (strncmp((char *)buf + i + 4, "DELIRIUM", 8) != 0 &&
+ strncmp((char *)buf + i + 4, "EPPLAYER", 8) != 0) {
+ return;
+ }
+
+ /* Hunk found */
+ hunk = buf + i;
+ hunk_size = len - i;
+
+ if (16 + i + 5 >= hunk_size)
+ return;
+
+ /* Check if $VER is available */
+ if (!memcmp(&hunk[16], "$VER:", 5)) {
+ offset = 16 + 5;
+ while (offset < hunk_size) {
+ if (memcmp(&hunk[offset], " ", 1))
+ break;
+ offset++;
+ }
+ if (offset >= hunk_size)
+ return;
+
+ if ((offset + strlen((char *)hunk + offset) + 1) >
+ ((size_t) hunk_size))
+ return;
+
+ snprintf(tmpstr, sizeof tmpstr, "\nVERSION:\n%s\n\n",
+ hunk + offset);
+ strlcat(credits, tmpstr, credits_len);
+ }
+
+ offset = read_be_u32(hunk + 12);
+ if (offset < 0) {
+ return;
+ }
+
+ tag_table = hunk + offset;
+
+ if (tag_table >= &buf[len])
+ return;
+
+ table_size = ((int)(&buf[len] - tag_table)) / 8;
+
+ if (table_size <= 0)
+ return;
+
+ /* check all tags in this loop */
+ for (i = 0; i < table_size; i += 2) {
+ x = read_be_u32(tag_table + 4 * i);
+ y = read_be_u32(tag_table + 4 * (i + 1));
+
+ if (!x)
+ break;
+
+ switch (x) {
+ case 0x8000445a:
+ if (y >= ((unsigned int)hunk_size))
+ return;
+ if ((y + strlen((char *)hunk + y) + 1) >
+ ((size_t) hunk_size))
+ return;
+ snprintf(tmpstr, sizeof tmpstr, "\nCREDITS:\n%s\n\n",
+ hunk + y);
+ strlcat(credits, tmpstr, credits_len);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/*
+ * Get the info out of the Deltamusic 2 module data
+ */
+static void process_dm2_mod(char *credits, size_t credits_len,
+ unsigned char *buf, size_t len)
+{
+ char tmpstr[256];
+ if (!string_checker(buf, 0x148, len))
+ return;
+ snprintf(tmpstr, sizeof tmpstr, "\nRemarks:\n%s", buf + 0x148);
+ strlcat(credits, tmpstr, credits_len);
+}
+
+static int process_module(char *credits, size_t credits_len, char *filename)
+{
+ FILE *modfile;
+ struct stat st;
+ size_t modfilelen;
+ unsigned char *buf;
+ char pre[11];
+ char tmpstr[256];
+ size_t rb;
+
+ if (!(modfile = fopen(filename, "rb")))
+ return 0;
+
+ if (fstat(fileno(modfile), &st))
+ return 0;
+
+ modfilelen = st.st_size;
+
+ if ((buf = malloc(modfilelen)) == NULL) {
+ fprintf(stderr, "uade: can't allocate mem in process_module()");
+ fclose(modfile);
+ return 0;
+ }
+
+ rb = 0;
+ while (rb < modfilelen) {
+ size_t ret = fread(&buf[rb], 1, modfilelen - rb, modfile);
+ if (ret == 0)
+ break;
+ rb += ret;
+ }
+
+ fclose(modfile);
+
+ if (rb < modfilelen) {
+ fprintf(stderr, "uade: song info could not read %s fully\n",
+ filename);
+ free(buf);
+ return 0;
+ }
+
+ snprintf(tmpstr, sizeof tmpstr, "UADE2 MODINFO:\n\nFile name: %s\nFile length: %zd bytes\n", filename, modfilelen);
+ strlcpy(credits, tmpstr, credits_len);
+
+ /* Get filetype in pre */
+ uade_filemagic(buf, modfilelen, pre, modfilelen, filename, 0);
+
+ snprintf(tmpstr, sizeof tmpstr, "File prefix: %s.*\n", pre);
+ strlcat(credits, tmpstr, credits_len);
+
+ if (strcasecmp(pre, "CUST") == 0) {
+ /* CUST */
+ process_custom(credits, credits_len, buf, modfilelen);
+
+ } else if (strcasecmp(pre, "DM2") == 0) {
+ /* DM2 */
+ process_dm2_mod(credits, credits_len, buf, modfilelen);
+
+ } else if (strcasecmp(pre, "DIGI") == 0) {
+ /* DIGIBooster */
+ process_digi_mod(credits, credits_len, buf, modfilelen);
+
+ } else if ((strcasecmp(pre, "AHX") == 0) ||
+ (strcasecmp(pre, "THX") == 0)) {
+ /* AHX */
+ process_ahx_mod(credits, credits_len, buf, modfilelen);
+
+ } else if ((strcasecmp(pre, "MOD15") == 0) ||
+ (strcasecmp(pre, "MOD15_UST") == 0) ||
+ (strcasecmp(pre, "MOD15_MST") == 0) ||
+ (strcasecmp(pre, "MOD15_ST-IV") == 0)) {
+ /*MOD15 */
+ process_ptk_mod(credits, credits_len, 15, buf, modfilelen);
+
+ } else if ((strcasecmp(pre, "MOD") == 0) ||
+ (strcasecmp(pre, "MOD_DOC") == 0) ||
+ (strcasecmp(pre, "MOD_NTK") == 0) ||
+ (strcasecmp(pre, "MOD_NTK1") == 0) ||
+ (strcasecmp(pre, "MOD_NTK2") == 0) ||
+ (strcasecmp(pre, "MOD_FLT4") == 0) ||
+ (strcasecmp(pre, "MOD_FLT8") == 0) ||
+ (strcasecmp(pre, "MOD_ADSC4") == 0) ||
+ (strcasecmp(pre, "MOD_ADSC8") == 0) ||
+ (strcasecmp(pre, "MOD_COMP") == 0) ||
+ (strcasecmp(pre, "MOD_NTKAMP") == 0) ||
+ (strcasecmp(pre, "PPK") == 0) ||
+ (strcasecmp(pre, "MOD_PC") == 0) ||
+ (strcasecmp(pre, "ICE") == 0) ||
+ (strcasecmp(pre, "ADSC") == 0)) {
+ /*MOD*/
+ process_ptk_mod(credits, credits_len, 31, buf, modfilelen);
+ } else if (strcasecmp(pre, "DL") == 0) {
+ process_WTWT_mod(credits, credits_len, buf, modfilelen, "UNCL",
+ "EART", 0x28);
+ } else if (strcasecmp(pre, "BSS") == 0) {
+ process_WTWT_mod(credits, credits_len, buf, modfilelen, "BEAT",
+ "HOVE", 0x1c);
+ } else if (strcasecmp(pre, "GRAY") == 0) {
+ process_WTWT_mod(credits, credits_len, buf, modfilelen, "FRED",
+ "GRAY", 0x10);
+ } else if (strcasecmp(pre, "JMF") == 0) {
+ process_WTWT_mod(credits, credits_len, buf, modfilelen, "J.FL",
+ "OGEL", 0x14);
+ } else if (strcasecmp(pre, "SPL") == 0) {
+ process_WTWT_mod(credits, credits_len, buf, modfilelen, "!SOP",
+ "ROL!", 0x10);
+ } else if (strcasecmp(pre, "HD") == 0) {
+ process_WTWT_mod(credits, credits_len, buf, modfilelen, "H.DA",
+ "VIES", 24);
+ } else if (strcasecmp(pre, "RIFF") == 0) {
+ process_WTWT_mod(credits, credits_len, buf, modfilelen, "RIFF",
+ "RAFF", 0x14);
+ } else if (strcasecmp(pre, "FP") == 0) {
+ process_WTWT_mod(credits, credits_len, buf, modfilelen, "F.PL",
+ "AYER", 0x8);
+ } else if (strcasecmp(pre, "CORE") == 0) {
+ process_WTWT_mod(credits, credits_len, buf, modfilelen, "S.PH",
+ "IPPS", 0x20);
+ } else if (strcasecmp(pre, "BDS") == 0) {
+ process_WTWT_mod(credits, credits_len, buf, modfilelen, "DAGL",
+ "ISH!", 0x14);
+ }
+
+ free(buf);
+
+ return 0;
+}
+
+int uade_generate_song_title(char *title, size_t dstlen,
+ struct uade_state *state)
+{
+ size_t srcoffs;
+ size_t dstoffs;
+ size_t srclen;
+ char *format;
+ char *bname;
+ char p[64];
+ char *default_format = "%F %X [%P]";
+ struct uade_song *us = state->song;
+ struct uade_config *uc = &state->config;
+
+ /* %A min subsong
+ %B cur subsong
+ %C max subsong
+ %F file base name (us->module_filename)
+ %P player name
+ %T title
+ %X print subsong info if more than one subsong exist
+ */
+
+ format = uc->song_title;
+
+ if (format == NULL)
+ format = default_format;
+
+ if (strcmp("default", format) == 0)
+ format = default_format;
+
+ if ((srclen = strlen(format)) == 0) {
+ fprintf(stderr, "Warning: empty song_title format string.\n");
+ return 1;
+ }
+
+ if (dstlen == 0)
+ return 1;
+
+ if (strlen(us->module_filename) == 0)
+ return 1;
+
+ bname = xbasename(us->module_filename);
+
+ p[0] = 0;
+ if (us->formatname[0] == 0) {
+ if (us->playername[0] == 0) {
+ strlcpy(p, "Custom", sizeof p);
+ } else {
+ strlcpy(p, us->playername, sizeof p);
+ }
+ } else {
+ if (strncmp(us->formatname, "type: ", 6) == 0) {
+ strlcpy(p, us->formatname + 6, sizeof p);
+ } else {
+ strlcpy(p, us->formatname, sizeof p);
+ }
+ }
+
+ srcoffs = dstoffs = 0;
+
+ title[0] = 0;
+
+ while (dstoffs < dstlen) {
+ char c;
+ if (srcoffs >= srclen)
+ break;
+
+ if ((c = format[srcoffs]) == 0)
+ break;
+
+ if (c != '%') {
+ title[dstoffs++] = format[srcoffs++];
+ } else {
+ size_t inc;
+ char *dat = NULL;
+ char tmp[32];
+
+ if ((srcoffs + 1) >= srclen) {
+ fprintf(stderr, "Error: no identifier given in song title format: %s\n", format);
+ title[dstoffs] = 0;
+ return 1;
+ }
+
+ c = format[srcoffs + 1];
+
+ switch (c) {
+ case 'A':
+ snprintf(tmp, sizeof tmp, "%d",
+ us->min_subsong);
+ dat = tmp;
+ break;
+ case 'B':
+ snprintf(tmp, sizeof tmp, "%d",
+ us->cur_subsong);
+ dat = tmp;
+ break;
+ case 'C':
+ snprintf(tmp, sizeof tmp, "%d",
+ us->max_subsong);
+ dat = tmp;
+ break;
+ case 'F':
+ dat = bname;
+ break;
+ case 'P':
+ dat = p;
+ break;
+ case 'T':
+ dat = us->modulename;
+ if (strcmp("<no songtitle>", dat) == 0)
+ dat[0] = 0;
+ if (dat[0] == 0)
+ dat = bname;
+ break;
+ case 'X':
+ if (us->min_subsong == us->max_subsong) {
+ tmp[0] = 0;
+ } else {
+ snprintf(tmp, sizeof tmp, "(%d/%d)",
+ us->cur_subsong,
+ us->max_subsong);
+ }
+ dat = tmp;
+ break;
+ default:
+ fprintf(stderr,
+ "Unknown identifier %%%c in song_title format: %s\n",
+ c, format);
+ title[dstoffs] = 0;
+ return 1;
+ }
+ inc = strlcpy(&title[dstoffs], dat, dstlen - dstoffs);
+ srcoffs += 2;
+ dstoffs += inc;
+ }
+ }
+
+ if (dstoffs < dstlen)
+ title[dstoffs] = 0;
+ else
+ title[dstlen - 1] = 0;
+
+ return 0;
+}
+
+/* Returns zero on success, non-zero otherwise. */
+int uade_song_info(char *info, size_t maxlen, char *filename,
+ enum song_info_type type)
+{
+ switch (type) {
+ case UADE_MODULE_INFO:
+ return process_module(info, maxlen, filename);
+ case UADE_HEX_DUMP_INFO:
+ return hexdump(info, maxlen, filename, 2048);
+ default:
+ fprintf(stderr, "Illegal info requested.\n");
+ exit(-1);
+ }
+ return 0;
+}