/* scivi - visualization plugin for XMMS * Copyright (C) 2003 Vitaly V. Bursov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #ifdef HAVE_CTYPE_H #include #endif #ifdef HAVE_DIRENT_H #include #endif #include #include "common.h" #include "presets.h" #ifndef HAVE_ISSPACE static int isspace(char c) { return (c == ' ') || (c == '\f') || (c == '\n') || (c == '\r') || (c == '\t') || (c == '\v'); } #endif static char *_get_first_non_space(char *p) { while (isspace(*p)) p++; return p; } static char *_get_first_non_space_non_eq(char *p) { while (isspace(*p) || (*p == '=')) p++; return p; } static char *_right_trim(char *p) { int l = strlen(p)-1; while ((l>=0) && isspace(p[l])){ p[l] = '\0'; l--; } return p; } static int _is_commt_start(char c) { return (c == '#') || (c == '\0'); } enum { SECTION_UNK = 0, SECTION_GENERAL, SECTION_INIT, SECTION_PFRAME, SECTION_PPIXEL, SECTION_POSTFRAME }; /* BUG: line numbers line| preset [ per-frame ] 1 2 3 [ per-pixel ] 1 2 [ per-frame ] 4 5 # comment 6 */ static PresetInfo *preset_load_from_file_to(char *fn, PresetInfo *pi) { FILE *f; int linebuffersize; char *linebuffer; char *l, *ll; char *ptr; int glr; int curr_section; int llen; int line; int init_bs; int pframe_bs; int ppixel_bs; int postframe_bs; f = fopen(fn, "r"); if (f == NULL){ eprintf("can not open preset file %s: %s\n", fn, strerror(errno)); return NULL; } linebuffersize = 1024; linebuffer = (char*)malloc(sizeof(char)*linebuffersize); if (linebuffer == NULL){ eprintf("could not allocate %d bytes\n", sizeof(char)*linebuffersize); fclose(f); return NULL; } memset(pi, 0, sizeof(PresetInfo)); pi->init = NULL; pi->pframe = NULL; pi->ppixel = NULL; pi->postframe = NULL; pi->init_clen = 0; pi->pframe_clen = 0; pi->ppixel_clen = 0; pi->postframe_clen = 0; pi->init_lineoffs = 0; pi->pframe_lineoffs = 0; pi->ppixel_lineoffs = 0; pi->postframe_lineoffs = 0; init_bs = 0; pframe_bs = 0; ppixel_bs = 0; postframe_bs = 0; curr_section = SECTION_UNK; line = 1; while (1) { if (fgets(linebuffer, linebuffersize, f) == NULL) break; glr = strlen(linebuffer); line++; l = _get_first_non_space(linebuffer); if (_is_commt_start(*l) && (curr_section == SECTION_GENERAL)) continue; if ((*l) == '['){ ll = _get_first_non_space(l+1); if (!strncasecmp(ll, "general",7)){ curr_section = SECTION_GENERAL; } else if (!strncasecmp(ll, "initialization",14)){ curr_section = SECTION_INIT; if (pi->init_lineoffs == 0) pi->init_lineoffs = line; else scivi_complier_warning("Section [%s] is already present!\n", "initialization"); } else if (!strncasecmp(ll, "per-frame",9)){ curr_section = SECTION_PFRAME; if (pi->pframe_lineoffs == 0) pi->pframe_lineoffs = line; else scivi_complier_warning("Section [%s] is already present!\n", "per-frame"); } else if (!strncasecmp(ll, "per-pixel",9)){ curr_section = SECTION_PPIXEL; if (pi->ppixel_lineoffs == 0) pi->ppixel_lineoffs = line; else scivi_complier_warning("Section [%s] is already present!\n", "per-pixel"); } else if (!strncasecmp(ll, "post-frame",10)){ curr_section = SECTION_POSTFRAME; if (pi->postframe_lineoffs == 0) pi->postframe_lineoffs = line; else scivi_complier_warning("Section [%s] is already present!\n", "post-frame"); } else { eprintf("unknown section in file %s\n", fn); curr_section = SECTION_UNK; } continue; } llen = glr - (l-linebuffer); switch (curr_section) { case SECTION_GENERAL: #define COPY_LL_TO(a) { \ int t = strlen(ll)+1; \ (a) = malloc(t); \ if ((a) == NULL){ \ eprintf("cannot alloc %d bytes\n", t); \ } \ memcpy((a), ll, t); \ } if (!strncasecmp(l, "name",4)){ ll = _get_first_non_space_non_eq(l+4); _right_trim(ll); COPY_LL_TO(pi->name); } else if (!strncasecmp(l, "author",6)){ ll = _get_first_non_space_non_eq(l+6); _right_trim(ll); COPY_LL_TO(pi->author); } else if (!strncasecmp(l, "uuid",4)){ ll = _get_first_non_space_non_eq(l+4); _right_trim(ll); COPY_LL_TO(pi->uuid); } else if (!strncasecmp(l, "rating",6)){ ll = _get_first_non_space_non_eq(l+6); pi->rating = strtol(ll, NULL, 0); } break; #undef COPY_LL_TO #define CODE_SECTION(__name__) {\ if (__name__## _bs < (pi->__name__## _clen + llen + 1)){ \ __name__## _bs += 1024; \ ptr = realloc(pi->__name__ , __name__## _bs); \ if (ptr == 0){ \ eprintf("could not realloc block to %d bytes\n", __name__## _bs); \ break; \ } \ pi->__name__ = ptr; \ } \ memcpy(pi->__name__ + pi->__name__## _clen, l, llen); \ pi->__name__## _clen += llen; \ break; \ } case SECTION_INIT: CODE_SECTION(init) case SECTION_PFRAME: CODE_SECTION(pframe) case SECTION_PPIXEL: CODE_SECTION(ppixel) case SECTION_POSTFRAME: CODE_SECTION(postframe) } #undef CODE_SECTION } free(linebuffer); #define REALLOC(a) { \ void *p; \ int i, nonempty; \ if (pi->a){ \ nonempty = 0; \ for (i=0;ia##_clen;i++) \ if (!isspace(pi->a[i])){ \ nonempty = 1; \ break; \ } \ if (nonempty){ \ p = realloc(pi->a, pi->a##_clen + 1); \ if (p != NULL){ \ pi->a = p; \ } \ pi->a[pi->a##_clen] = '\0'; \ } else { \ free(pi->a); \ pi->a = NULL; \ pi->a##_clen = 0; \ } \ } \ } REALLOC(init); REALLOC(pframe); REALLOC(ppixel); REALLOC(postframe); #if 0 printf("####### LOADED PRESET\n"); printf("name: '%s'\n",pi->name); printf("author: '%s'\n",pi->author); printf("rating: %d\n",pi->rating); printf("INIT:\n"); printf("%s\n", pi->init ? pi->init : "NULL"); printf("PFRM:\n"); printf("%s\n", pi->pframe ? pi->pframe : "NULL"); printf("PPIX:\n"); printf("%s\n", pi->ppixel ? pi->ppixel : "NULL"); printf("POSTFRAME:\n"); printf("%s\n", pi->postframe ? pi->postframe : "NULL"); #endif fclose(f); return pi; } PresetInfo *scivi_preset_load_from_file(char *fn) { PresetInfo *pi; pi = (PresetInfo *) malloc (sizeof(PresetInfo)); if (pi == NULL){ eprintf("could not allocate %d bytes\n", sizeof(PresetInfo)); return NULL; } if (!preset_load_from_file_to(fn, pi)){ free(pi); return NULL; } return pi; } static int preset_load_from_dir_to(char *dir, PresetInfo **pis, int *arrsize, int *arrcnt) { #ifdef HAVE_OPENDIR DIR *d; char fullfn[512]; struct dirent *dr; void *di; int l; PresetInfo *pi; int loadcnt = 0; d = opendir(dir); if (d == NULL){ eprintf("cant open dir %s: %s\n",dir, strerror(errno)); return 0; } if (*arrsize <= 0){ *arrsize = 512; l = sizeof(PresetInfo)*(*arrsize); (*pis) = (PresetInfo *)malloc(l); if (!(*pis)){ eprintf("could not allocate %d bytes\n", l); closedir(d); (*pis) = NULL; return -1; } memset((*pis), 0, l); *arrcnt = 0; } l = ((char*)&(dr->d_name) - (char*)dr) + NAME_MAX + 1; if (sizeof(struct dirent) > l) l = sizeof(struct dirent); di = malloc(l); if (di == NULL){ eprintf("could not allocate %d bytes\n", l); closedir(d); return -1; } while ((!readdir_r(d, (struct dirent*)di, &dr)) && dr){ l = strlen(dr->d_name); if ((l < 5) || (dr->d_name[0] == '.')) continue; if (strncasecmp(dr->d_name+l-4, ".scv", 4)) continue; snprintf(fullfn, 512, "%s/%s", dir, dr->d_name); dprintf("Loading Preset: %s\n",fullfn); if (preset_load_from_file_to(fullfn, &((*pis)[*arrcnt]))){ (*arrcnt)++; loadcnt++; if ((*arrcnt) == (*arrsize)){ void *p; int t; (*arrsize) += 1024; t = sizeof(PresetInfo)*(*arrsize); p = realloc((*pis), t); if (p == NULL){ eprintf("Failed to reallocate %d bytes\n", t); closedir(d); free(di); return -1; } (*pis) = p; } } } closedir(d); free(di); return loadcnt; #else /* FIXME */ eprintf("loading directory of presets is not supported\n"); *pis = NULL; return -1; #endif } int scivi_preset_load_from_dir(char *dir, PresetInfo **pis) { int c = 0, p; return preset_load_from_dir_to(dir, pis, &c, &p); } int scivi_preset_load_from_dirs(char **dirs, PresetInfo **pis) { int i; int c = 0; int p = 0; for (i=0;dirs[i];i++){ if (preset_load_from_dir_to(dirs[i], pis, &c, &p) < 0) break; } return p; } void scivi_presets_free(PresetInfo *pis, int cnt) { int i; if (!pis){ return; } for (i=0;i