/* paste.c */ /* Blursk - visualization plugin for XMMS * Copyright (C) 1999 Steve Kirkendall * * Portions of this file are derived from the XMMS "Blur Scope" plugin. * XMMS is Copyright (C) 1998-1999 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies * * 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. */ #include #include #include #include #include #include #include #include "xmms/configfile.h" #include "blursk.h" /* Convert the leading words in a value into a single letter and '.' */ static char *abbreviate(char *value) { char full[40]; /* full value */ static char abbr[40]; /* abbreviated value */ char *word; /* Strip off a trailing "stencil" or "flash" word */ strcpy(full, value); word = strrchr(full, ' '); if (word && (!strcmp(word, " stencil") || !strcmp(word, " flash"))) *word = '\0'; /* generate the abbreviated version of the string */ word = strrchr(full, ' '); if (word) sprintf(abbr, "%.1s.%s", full, word + 1); else strcpy(abbr, full); return abbr; } /* Convert a value to its shortest possible form */ static void genfield( char **buf, /* where to stuff the short value */ char *current, /* current value */ char *(*namefunc)(int), /* called to generate names of items */ ...) /* NULL-terminated list of hardcoded items */ { char str[40]; /* abbreviated value */ char *value; int i,len, found; va_list ap; /* generate the abbreviated version of the string */ strcpy(str, abbreviate(current)); /* compare to other values, to see how short we can make this */ va_start(ap, namefunc); i = 0; value = namefunc ? (*namefunc)(i) : NULL; if (!value) { namefunc = NULL; value = va_arg(ap, char *); } /* For each arg... */ for (found = FALSE, len = 1; value; ) { /* abbreviate this possible value */ value = abbreviate(value); /* if this is the initial value, remember that. */ if (!strcmp(value, str)) found = TRUE; else /* make sure "len" is big enough to distinguish this * item from any preceding item. */ while (!found && !strncmp(value, str, len)) len++; /* get the next value, from either the function or args */ i++; value = namefunc ? (*namefunc)(i) : NULL; if (!value) { namefunc = NULL; value = va_arg(ap, char *); } } va_end(ap); /* Add the shortest abbreviation of this item to the buffer */ strncpy(*buf, str, len); (*buf) += len; **buf = '\0'; } /* return a string which describes the current configuration */ char *paste_genstring(void) { static char buf[100]; char *str; /* start with the color, as a decimal number */ #if 0 str = preset_gettitle(); if (str) sprintf(buf, "[%s]%ld", str, config.color); else #endif sprintf(buf, "%ld", config.color); str = buf + strlen(buf); /* Add the color options */ genfield(&str, config.color_style, color_name, NULL); genfield(&str, config.fade_speed, NULL, "No fade", "Slow fade", "Medium fade", "Fast fade", NULL); genfield(&str, config.signal_color, NULL, "Normal signal", "White signal", "Cycling signal", NULL); *str++ = config.contour_lines ? 'Y' : 'N'; *str++ = config.hue_on_beats ? 'Y' : 'N'; genfield(&str, config.background, color_background_name, NULL); *str++ = '/'; /* Add the blur options */ genfield(&str, config.blur_style, blur_name, NULL); genfield(&str, config.transition_speed, NULL, "Slow switch", "Medium switch", "Fast switch", NULL); genfield(&str, config.blur_when, blur_when_name, NULL); genfield(&str, config.blur_stencil, bitmap_stencil_name, NULL); *str++ = config.slow_motion ? 'Y': 'N'; *str++ = '/'; /* Add the effects options */ genfield(&str, config.signal_style, blursk_name, NULL); genfield(&str, config.plot_style, render_plotname, NULL); *str++ = config.thick_on_beats ? 'Y' : 'N'; genfield(&str, config.flash_style, bitmap_flash_name, NULL); genfield(&str, config.overall_effect, NULL, "Normal effect", "Bump effect", "Anti-fade effect", "Ripple effect", NULL); genfield(&str, config.floaters, blursk_floater_name, NULL); *str = '\0'; return buf; } /* Convert a single field. The behavior of this function has been tweaked to * make it easy to convert a long series of fields... * o It moves "field" past the end of the converted field. * o If the field can't be converted, "field" is set to NULL * o If "field" was already NULL when the function is called, it does nothing. * o If "field" points to a slash, then the default is returned. * o Allocated strings are stored at "out", and then "out" moved past it. * o The return value points to the start of the value. * The idea is that "field" pointing at the start of a field, and "out" pointing * at the start of a buffer. Then you call parsefield() repeatedly without * bothering to check for errors. At the end of a series, if "field" is NULL * then there was an error. */ static char *parsefield( char **field, /* pointer into string of fields */ char *dflt, /* default return value */ char *(*namefunc)(int), /* called to generate names of items */ ...) /* NULL-terminated list of hardcoded items */ { char *value, *abbr; int i,len; char *found; va_list ap; /* if "field" is NULL or points to a slash, do nothing */ if (!*field || !**field || **field == '/') { return dflt; } /* count the length of this abbreviated field */ len = 1; if ((*field)[1] == '.') len = 2; while (islower((*field)[len])) len++; /* compare to each possible value, to find the unabbreviated form */ va_start(ap, namefunc); i = 0; value = namefunc ? (*namefunc)(i) : NULL; if (!value) { namefunc = NULL; value = va_arg(ap, char *); } for (found = NULL; value; ) { /* abbreviate this possible value */ abbr = abbreviate(value); /* if this is the value value, remember that. */ if (!found && !strncmp(abbr, *field, len)) found = value; /* get the next value, from either the function or args */ i++; value = namefunc ? (*namefunc)(i) : NULL; if (!value) { namefunc = NULL; value = va_arg(ap, char *); } } va_end(ap); /* did we find it? */ if (found) { /* Yes - move past the field, and then return long version */ *field += len; return found; } else { /* No - skip to next slash or end of string & return default */ while (**field && **field != '/') (*field)++; return dflt; } } /* This is like parsefield(), but for booleans */ int parsebool( char **field, /* pointer to current field within pasted string */ int dflt) /* default value */ { if (!*field || !**field || **field == '/') return dflt; if (**field == 'Y') { (*field)++; return TRUE; } if (**field == 'N') { (*field)++; return FALSE; } /* Not recognized -- skip to next slash or end of string */ while (**field && **field != '/') (*field)++; return dflt; } /* parse a configuration string & set the current configuration accordingly */ BlurskConfig *paste_parsestring(char *str) { char *title; char *afternumber; long newcolor; static BlurskConfig c; /* skip leading whitespace */ while (isspace(*str)) str++; /* skip title, if any */ if (*str == '[') { title = ++str; while (*str && *str != ']') str++; if (*str) *str++ = '\0'; } else title = ""; /* use defaults for most things */ config_default(&c); /* parse the color */ newcolor = strtol(str, &afternumber, 10); if (afternumber == str) return &c; c.color = newcolor; str = afternumber; /* parse the color options */ c.color_style = parsefield(&str, c.color_style, color_name,NULL); c.fade_speed = parsefield(&str, c.fade_speed, NULL, "No fade", "Slow fade", "Medium fade", "Fast fade", NULL); c.signal_color = parsefield(&str, c.signal_color, NULL, "Normal signal", "White signal", "Cycling signal", NULL); c.contour_lines = parsebool(&str, c.contour_lines); c.hue_on_beats = parsebool(&str, c.hue_on_beats); c.background = parsefield(&str, c.background, color_background_name, NULL); if (!str) return &c; while (*str && *str != '/') str++; if (*str == '/') str++; /* parse the blur options */ c.blur_style = parsefield(&str, c.blur_style, blur_name, NULL); c.transition_speed = parsefield(&str, c.transition_speed, NULL, "Slow switch", "Medium switch", "Fast switch", NULL); c.blur_when = parsefield(&str, c.blur_when, blur_when_name, NULL); c.blur_stencil = parsefield(&str, c.blur_stencil, bitmap_stencil_name, NULL); c.slow_motion = parsebool(&str, c.slow_motion); if (!str) return &c; while (*str && *str != '/') str++; if (*str == '/') str++; /* parse the effects options */ c.signal_style = parsefield(&str, c.signal_style, blursk_name, NULL); c.plot_style = parsefield(&str, c.plot_style, render_plotname, NULL); c.thick_on_beats = parsebool(&str, c.thick_on_beats); c.flash_style = parsefield(&str, c.flash_style, bitmap_flash_name, NULL); c.overall_effect = parsefield(&str, c.overall_effect, NULL, "Normal effect", "Bump effect", "Anti-fade effect", "Ripple effect", NULL); c.flash_style = parsefield(&str, c.floaters, blursk_floater_name, NULL); return &c; } /* Set the configuration from some other program's cut buffer. */ void paste(char *str) { BlurskConfig *c; /* parse the string */ c = paste_parsestring(str); /* use this configuration */ config_load_preset(c); }