Mercurial > hg > xmms-sid
diff src/xs_stil.c @ 62:0d1df20745dd
Started to rewrite STIL-support
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Sun, 22 Jun 2003 11:38:00 +0000 |
parents | 1788f4ce6a44 |
children | 086681f70910 |
line wrap: on
line diff
--- a/src/xs_stil.c Sun Jun 22 11:37:05 2003 +0000 +++ b/src/xs_stil.c Sun Jun 22 11:38:00 2003 +0000 @@ -24,560 +24,3 @@ #include "xmms-sid.h" #include <glib.h> #include <stdio.h> -#include <sys/stat.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> - - -/* Variables and constants */ -#define XMMS_SID_MAX_BUFSIZE 2048 -struct T_sid_stil_info xs_stil_info; - -/* - * Utility routines - */ -int xs_strcalloc(gchar **result, gchar *str) -{ - if ((result == NULL) || (str == NULL)) return -1; - - if (*result != NULL) g_free(*result); - - *result = (gchar *) g_malloc(strlen(str)+1); - - if (*result == NULL) return -2; - - strcpy(*result, str); - - return 0; -} - - -int xs_strcat(gchar **result, gchar *str) -{ - if ((result == NULL) || (str == NULL)) return -1; - - *result = (gchar *) g_realloc(*result, strlen(*result) + strlen(str) + 1); - - if (*result == NULL) return -2; - - strcat(*result, str); - - return 0; -} - - -/* - * Make lowercase, strip evt. extension - */ -static gchar * uncase_strip_fn(gchar *str) -{ - gchar *res; - gint i, l; - - l = str ? strlen(str) : 0; - - res = strrchr(str, '/'); - - if (res) res = strrchr(res, '.'); - - if (res) l = (res - str); - - res = g_new(gchar, l + 1); - - for (i = 0; i < l; i++) { - res[i] = tolower(str[i]); - } - - res[i] = '\0'; - - return res; -} - - -static gchar * xs_get_hvscname(gchar *fname) -{ - gchar *p, *q, *r; - - p = xs_cfg.stilpath; - - q = r = fname; - - while (*p == *q) { - if (*q == '/') r = q + 1; - p++; q++; - } - - return r; -} - - -/* - * Get line (string) from given file to given buffer. - * Takes care of winDOS CR/LF and *NIX LF formats. - */ -void stil_get_line(gchar *buf, gint bufsize, FILE *f) -{ - gint i; - - /* Get the string */ - fgets(buf, bufsize-1, f); - - /* The file may be in DOS CR-LF format, - so check for the line endings and - remove the \n and \r accordingly - */ - i = strlen(buf); - if (i > 0) { - if (buf[i-2] == '\r') - buf[i-2] = '\0'; - else - buf[i-1] = '\0'; - } -} - - -/* - xs_token_skipsp(buf, j); - token2 = xs_token_getcopy(buf, j, ')'); -*/ -gint stil_token_skipsp(gchar *buf, gint i) -{ - gint len = strlen(buf); - - while ((i < len) && ((buf[i] == 32) || (buf[i] == '\t'))) i++; - - return i; -} - - -gchar * stil_token_get(gchar *buf, gint i, gchar c) -{ - gint j, len = strlen(buf); - gchar *res; - - /* Find out the end place */ - j = i; - while ((buf[j] != c) && (j < len)) j++; - - /* Malloc some memory */ - len = (j - i); - res = (gchar *) g_malloc(len+1); - if (res == NULL) return NULL; - - /* Return the token */ - strncpy(res, &buf[i], len); - res[len] = '\0'; - - return res; -} - - -/* - * Clear the informations - */ -void xs_stil_clearone(T_sid_stil_subtune *tune) -{ - xs_strcalloc(&tune->title, "\0"); - xs_strcalloc(&tune->name, "\0"); - xs_strcalloc(&tune->artist, "\0"); - xs_strcalloc(&tune->comment, "\0"); -} - -void xs_stil_clear(void) -{ - int i; - - for (i = 0; i < XMMS_SID_STIL_MAXENTRY; i++) - xs_stil_clearone(&xs_stil_info.subtune[i]); -} - - -/* - * Simple string-list handling functions - */ -typedef struct { - gint nitems; - gchar * * items; -} T_stringlist; - - -int sl_insert(T_stringlist *list, gchar *str) -{ - gchar *res; - - /* Check the list pointer */ - if (list == NULL) return -1; - if (str == NULL) return -2; - - /* Increase the space in pointer list */ - list->nitems++; - - list->items = (gchar * *) g_realloc(list->items, (sizeof(gchar **) * list->nitems)); - if (list->items == NULL) return -3; - - /* Allocate space for the string */ - res = (gchar *) g_malloc(strlen(str) + 1); - if (res == NULL) return -4; - - /* Put the data in */ - strcpy(res, str); - list->items[(list->nitems - 1)] = res; - - /* Return number of items */ - return (list->nitems); -} - - -gchar * sl_getitem(T_stringlist *list, gint n) -{ - /* Check the list pointer */ - if (list == NULL) return NULL; - if (list->items == NULL) return NULL; - - /* Check the argument */ - if ((n >= 0) && (n < list->nitems)) return (list->items[n]); - - return NULL; -} - - -int sl_clear(T_stringlist *list) -{ - /* Check the list pointer */ - if (list == NULL) return -1; - - /* Clear the variables */ - list->nitems = 0; - list->items = NULL; - - return 0; -} - - -int sl_free(T_stringlist *list) -{ - gint i; - - /* Check the list pointer */ - if (list == NULL) return -1; - - /* Check the items */ - if (list->items != NULL) - { - /* Free all strings in list, if any */ - for (i = 0; i < list->nitems; i++) - { - if (list->items[i] != NULL) - free(list->items[i]); - } - - /* Free the list itself */ - free(list->items); - } - - /* Clear the data */ - list->nitems = 0; - list->items = NULL; - - return 0; -} - - -/* - * "Submit" all gathered "lists" to given tunedef - */ -void xs_stil_submit(T_sid_stil_subtune *tune, T_stringlist *iartist, - T_stringlist *icomment, T_stringlist *iname, T_stringlist *ititle) -{ - gchar *tmpstr; - gint i, ok; - - /* Clear the data */ - xs_stil_clearone(tune); - - /* "Submit" lists to tunedata */ - if ((iartist->nitems > 1) || - (icomment->nitems > 1) || - (iname->nitems > 1) || - (ititle->nitems > 1)) - { - /* Multiple items per category */ - i = 0; - ok = 1; - while (ok) { - /* Clear the flag */ - ok = 0; - - /* Get items from lists */ - tmpstr = sl_getitem(iartist, i); - if (tmpstr != NULL) { - xs_strcat(&tune->comment, "\nArtist: "); - xs_strcat(&tune->comment, tmpstr); - ok = 1; - } - - tmpstr = sl_getitem(icomment, i); - if (tmpstr != NULL) { - xs_strcat(&tune->comment, "\nComment: "); - xs_strcat(&tune->comment, tmpstr); - ok = 1; - } - - tmpstr = sl_getitem(iname, i); - if (tmpstr != NULL) { - xs_strcat(&tune->comment, "\nName: "); - xs_strcat(&tune->comment, tmpstr); - ok = 1; - } - - tmpstr = sl_getitem(ititle, i); - if (tmpstr != NULL) { - xs_strcat(&tune->comment, "\nTitle: "); - xs_strcat(&tune->comment, tmpstr); - ok = 1; - } - - /* Next one */ - i++; - } - } else - { - /* Only one item or none */ - tmpstr = sl_getitem(iartist, 0); - if (tmpstr != NULL) xs_strcalloc(&tune->artist, tmpstr); - - tmpstr = sl_getitem(icomment, 0); - if (tmpstr != NULL) xs_strcalloc(&tune->comment, tmpstr); - - tmpstr = sl_getitem(iname, 0); - if (tmpstr != NULL) xs_strcalloc(&tune->name, tmpstr); - - tmpstr = sl_getitem(ititle, 0); - if (tmpstr != NULL) xs_strcalloc(&tune->title, tmpstr); - } - - /* Free the lists */ - sl_free(iartist); - sl_free(icomment); - sl_free(iname); - sl_free(ititle); -} - - -/* - * Parse all STIL data for one song (subsongs, etc) - */ -int xs_stil_parse_entry(FILE *stilf, gchar *buf, gint bufsize) -{ - T_stringlist iartist, icomment, iname, ititle; - gchar *token1, *token2, *tmpbuf; - gint ntune, found, found2; - gint i, j; - - XSDEBUG("token '%s':\n", buf); - - /* Clear and initialize variables */ - ntune = 0; - - sl_clear(&iartist); - sl_clear(&icomment); - sl_clear(&iname); - sl_clear(&ititle); - - tmpbuf = NULL; - - /* Ok, it was found! Now get and parse the data */ - found = ntune = 0; - - while ((!feof(stilf)) && (found == 0)) { - /* Get line from file */ - stil_get_line(buf, bufsize, stilf); - -nreadln: - - /* Check for empty (end of STIL record) */ - if (buf[0] == '\0') found = 1; else - - { - /* Skip whitespaces and get first token */ - j = 0; - token1 = (gchar *) (buf); - - /* Check for data types and act accordingly */ - if (token1[0] == '(') { - j = stil_token_skipsp(buf, j+1); - if (buf[j] == '#') { - token2 = stil_token_get(buf, j+1, ')'); - i = atoi(token2); - - if ((i >= 1) || (i < XMMS_SID_STIL_MAXENTRY)) { - - xs_stil_submit(&xs_stil_info.subtune[ntune], - &iartist, - &icomment, - &iname, - &ititle); - - ntune = i; - - XSDEBUG("tune_num: '%d'\n", ntune); - } - - g_free(token2); - } - } else - - if (!strncmp(token1, "COMMENT:", 8)) { - j = stil_token_skipsp(buf, j + 8); - token1 = (gchar *) (buf + j); - - if (xs_strcalloc(&tmpbuf, token1)) return -4; - - found2 = 0; - while ((!feof(stilf)) && (found2 == 0)) { - - /* Read next entry line */ - j = 0; - stil_get_line(buf, bufsize, stilf); - - /* Check if the comment continues? */ - if (strncmp(" ", buf, 9) != 0) { - found2 = 1; - } else { - - /* Get the comment line and parse it */ - j = stil_token_skipsp(buf, j + 9); - token1 = (gchar *) (buf + j); - - /* Cat to the end */ - if (xs_strcat(&tmpbuf, " ") < 0) return -4; - if (xs_strcat(&tmpbuf, token1) < 0) return -4; - - } /* if..else */ - } /* while */ - - - /* Insert the result */ - XSDEBUG("comment: '%s'\n", tmpbuf); - sl_insert(&icomment, tmpbuf); - - if (tmpbuf != NULL) free(tmpbuf); - tmpbuf = NULL; - - goto nreadln; /* EVIL GOTO! */ - } else - - if (!strncmp(token1, " TITLE:", 8)) { - j = stil_token_skipsp(buf, j + 8); - token1 = (gchar *) (buf + j); - - XSDEBUG("title : '%s'\n", token1); - sl_insert(&ititle, token1); - } else - - if (!strncmp(token1, " ARTIST:", 8)) { - j = stil_token_skipsp(buf, j + 8); - token1 = (gchar *) (buf + j); - - XSDEBUG("artist : '%s'\n", token1); - sl_insert(&iartist, token1); - } else - - if (!strncmp(token1, " NAME:", 8)) { - j = stil_token_skipsp(buf, j + 8); - token1 = (gchar *) (buf + j); - - XSDEBUG("name : '%s'\n", token1); - sl_insert(&iname, token1); - } - } - - } /* while */ - - - /* Submit the last entry */ - xs_stil_submit(&xs_stil_info.subtune[ntune], - &iartist, - &icomment, - &iname, - &ititle); - - - XSDEBUG("end of tunedef.\n"); - return 0; -} - - -/* - * Main routine for searching the STIL-database file - */ -int xs_stil_get(gchar *sidfn) -{ - FILE *stilf; - gchar *e, *a, *buf; - guint bufsize; - gint found, i, result; - struct stat stilst; - - - /* Clear the STIL info */ - xs_stil_clear(); - - /* Check the given STIL database filename */ - if ((!xs_cfg.stilpath || !xs_cfg.stilpath[0])) return -1; - - /* Check if the STIL database file exists */ - if (stat(xs_cfg.stilpath, &stilst) < 0) return -1; - - /* Try to allocate the temporary buffer */ - bufsize = (XMMS_SID_MAX_BUFSIZE + 1); - buf = (gchar *) g_malloc(bufsize); - if (buf == NULL) return -2; - - - /* Try to open the STIL database file */ - stilf = fopen(xs_cfg.stilpath, "r"); - if (!stilf) return -3; - - /* -- */ - e = uncase_strip_fn(xs_get_hvscname(sidfn)); - XSDEBUG("sfn = '%s'\n", e); - - result = found = 0; - - while ((!feof(stilf)) && (found == 0)) { - - stil_get_line(buf, bufsize, stilf); - - /* Ignore everything else until a filename is found */ - if (buf[0] == '/') { - - /* Check against our sidname */ - a = uncase_strip_fn((gchar *) (buf+1)); - i = strcmp(a, e); - g_free(a); - - /* Parse entry if found */ - if (!i) { - result = xs_stil_parse_entry(stilf, buf, bufsize); - found = 1; - } - - } /* if (buf[0]... */ - - } /* while */ - - /* Shutdown & close */ - g_free(e); - g_free(buf); - - if (!fclose(stilf)) return -3; - - /* Successful return ?? */ - if ((found) && (result >= 0)) - return 0; - else - return 1; -}