/**
* GJay, copyright (c) 2002 Chuck Groom
*
* The preference XML format is:
*
* Path
*
* enum
* random|selected|color
* songs|dir
* float
* ...
* ...
* ...
* ...
* ...
* ...
* ...
* float float float
*
* int
*
* 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 1, 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 "config.h"
#endif /* HAVE_CONFIG_H */
#include
#include
#include
#include
#include
#include
#include "gjay.h"
typedef enum {
PE_GJAY_PREFS,
PE_ROOTDIR,
PE_FLAGS,
PE_DAEMON_ACTION,
PE_START,
PE_SELECTION_LIMIT,
PE_RATING,
PE_HUE,
PE_BRIGHTNESS,
PE_SATURATION,
PE_BPM,
PE_FREQ,
PE_VARIANCE,
PE_PATH_WEIGHT,
PE_COLOR,
PE_TIME,
PE_MAX_WORKING_SET,
/* attributes */
PE_EXTENSION_FILTER,
PE_HIDE_TIP,
PE_WANDER,
PE_CUTOFF,
PE_VERSION,
PE_USE_RATINGS,
PE_TYPE,
/* values */
PE_RANDOM,
PE_SELECTED,
PE_SONGS,
PE_DIR,
PE_LAST
} pref_element_type;
char * pref_element_strs[PE_LAST] = {
"gjay_prefs",
"rootdir",
"flags",
"daemon_action",
"start",
"selection_limit",
"rating",
"hue",
"brightness",
"saturation",
"bpm",
"freq",
"variance",
"path_weight",
"color",
"time",
"max_working_set",
"extension_filter",
"hide_tip",
"wander",
"cutoff",
"version",
"use_ratings",
"type",
"random",
"selected",
"songs",
"dir"
};
static void data_start_element ( GMarkupParseContext *context,
const gchar *element_name,
const gchar **attribute_names,
const gchar **attribute_values,
gpointer user_data,
GError **error );
static void data_text ( GMarkupParseContext *context,
const gchar *text,
gsize text_len,
gpointer user_data,
GError **error );
static int get_element ( gchar * element_name );
GjayPrefs*
load_prefs ( void ) {
GMarkupParseContext * parse_context;
GMarkupParser parser;
gboolean result = TRUE;
GError * error;
char buffer[BUFFER_SIZE];
FILE * f;
gssize text_len;
pref_element_type element;
GjayPrefs *prefs;
/* Set default values */
prefs = g_malloc0(sizeof(GjayPrefs));
gjay->prefs = prefs;
prefs->rating = DEFAULT_RATING;
prefs->use_ratings = FALSE;
prefs->time = DEFAULT_PLAYLIST_TIME;
prefs->max_working_set = DEFAULT_MAX_WORKING_SET;
prefs->variance =
prefs->hue =
prefs->brightness =
prefs->bpm =
prefs->freq =
prefs->path_weight = DEFAULT_CRITERIA;
prefs->saturation = 1;
prefs->extension_filter = TRUE;
prefs->color.H = 0;
prefs->color.S = 0.5;
prefs->color.V = 1.0;
prefs->use_hsv = FALSE;
prefs->daemon_action = PREF_DAEMON_QUIT;
prefs->hide_tips = FALSE;
snprintf(buffer, BUFFER_SIZE, "%s/%s/%s", getenv("HOME"),
GJAY_DIR, GJAY_PREFS);
f = fopen(buffer, "r");
if (f) {
parser.start_element = data_start_element;
parser.text = data_text;
parser.end_element = NULL;
parse_context = g_markup_parse_context_new(&parser, 0, &element, NULL);
while (result && !feof(f)) {
text_len = fread(buffer, 1, BUFFER_SIZE, f);
result = g_markup_parse_context_parse ( parse_context,
buffer,
text_len,
&error);
error = NULL;
}
g_markup_parse_context_free(parse_context);
fclose(f);
}
return prefs;
}
void save_prefs ( void ) {
char buffer[BUFFER_SIZE], buffer_temp[BUFFER_SIZE];
char * utf8;
FILE * f;
GjayPrefs *prefs=gjay->prefs;
snprintf(buffer, BUFFER_SIZE, "%s/%s/%s", getenv("HOME"),
GJAY_DIR, GJAY_PREFS);
snprintf(buffer_temp, BUFFER_SIZE, "%s_temp", buffer);
f = fopen(buffer_temp, "w");
if (f) {
fprintf(f, "\n", VERSION);
if (prefs->song_root_dir) {
fprintf(f, "<%s", pref_element_strs[PE_ROOTDIR]);
if (prefs->extension_filter)
fprintf(f, " %s=\"t\"", pref_element_strs[PE_EXTENSION_FILTER]);
utf8 = strdup_to_utf8(prefs->song_root_dir);
fprintf(f, ">%s%s>\n",
utf8,
pref_element_strs[PE_ROOTDIR]);
g_free(utf8);
}
fprintf(f, "<%s", pref_element_strs[PE_FLAGS]);
if (prefs->hide_tips)
fprintf(f, " %s=\"t\"", pref_element_strs[PE_HIDE_TIP]);
if (prefs->wander)
fprintf(f, " %s=\"t\"", pref_element_strs[PE_WANDER]);
if (prefs->use_ratings)
fprintf(f, " %s=\"t\"", pref_element_strs[PE_USE_RATINGS]);
fprintf(f, ">%s>\n", pref_element_strs[PE_FLAGS]);
fprintf(f, "<%s>%d%s>\n",
pref_element_strs[PE_DAEMON_ACTION],
prefs->daemon_action,
pref_element_strs[PE_DAEMON_ACTION]);
fprintf(f, "<%s>", pref_element_strs[PE_START]);
if (prefs->start_selected)
fprintf(f, "%s", pref_element_strs[PE_SELECTED]);
else if (prefs->start_color)
fprintf(f, "%s", pref_element_strs[PE_COLOR]);
else
fprintf(f, "%s", pref_element_strs[PE_RANDOM]);
fprintf(f, "%s>\n", pref_element_strs[PE_START]);
fprintf(f, "<%s>", pref_element_strs[PE_SELECTION_LIMIT]);
if (prefs->use_selected_songs)
fprintf(f, "%s", pref_element_strs[PE_SONGS]);
else if (prefs->use_selected_dir)
fprintf(f, "%s", pref_element_strs[PE_DIR]);
fprintf(f, "%s>\n", pref_element_strs[PE_SELECTION_LIMIT]);
fprintf(f, "<%s>%d%s>\n",
pref_element_strs[PE_TIME],
prefs->time,
pref_element_strs[PE_TIME]);
fprintf(f, "<%s>%d%s>\n",
pref_element_strs[PE_MAX_WORKING_SET],
prefs->max_working_set,
pref_element_strs[PE_MAX_WORKING_SET]);
fprintf(f, "<%s %s=\"hsv\">%f %f %f%s>\n",
pref_element_strs[PE_COLOR],
pref_element_strs[PE_TYPE],
prefs->color.H,
prefs->color.S,
prefs->color.V,
pref_element_strs[PE_COLOR]);
if (prefs->rating_cutoff) {
fprintf(f, "<%s %s=\"t\">",
pref_element_strs[PE_RATING],
pref_element_strs[PE_CUTOFF]);
} else {
fprintf(f, "<%s>", pref_element_strs[PE_RATING]);
}
fprintf(f, "%f", prefs->rating);
fprintf(f, "%s>\n", pref_element_strs[PE_RATING]);
fprintf(f, "<%s>%f%s>\n",
pref_element_strs[PE_VARIANCE],
prefs->variance,
pref_element_strs[PE_VARIANCE]);
fprintf(f, "<%s>%f%s>\n",
pref_element_strs[PE_HUE],
prefs->hue,
pref_element_strs[PE_HUE]);
fprintf(f, "<%s>%f%s>\n",
pref_element_strs[PE_BRIGHTNESS],
prefs->brightness,
pref_element_strs[PE_BRIGHTNESS]);
fprintf(f, "<%s>%f%s>\n",
pref_element_strs[PE_SATURATION],
prefs->saturation,
pref_element_strs[PE_SATURATION]);
fprintf(f, "<%s>%f%s>\n",
pref_element_strs[PE_BPM],
prefs->bpm,
pref_element_strs[PE_BPM]);
fprintf(f, "<%s>%f%s>\n",
pref_element_strs[PE_FREQ],
prefs->freq,
pref_element_strs[PE_FREQ]);
fprintf(f, "<%s>%f%s>\n",
pref_element_strs[PE_PATH_WEIGHT],
prefs->path_weight,
pref_element_strs[PE_PATH_WEIGHT]);
fprintf(f, "\n");
fclose(f);
rename(buffer_temp, buffer);
} else {
fprintf(stderr, "Unable to write prefs %s\n", buffer);
}
}
/* Called for open tags */
void data_start_element (GMarkupParseContext *context,
const gchar *element_name,
const gchar **attribute_names,
const gchar **attribute_values,
gpointer user_data,
GError **error) {
gint k;
pref_element_type * element = (pref_element_type *) user_data;
pref_element_type attr;
*element = get_element((char *) element_name);
for (k = 0; attribute_names[k]; k++) {
attr = get_element((char *) attribute_names[k]);
switch(attr) {
case PE_TYPE:
if (strcasecmp(attribute_values[k], "hsv") == 0) {
gjay->prefs->use_hsv = TRUE;
}
break;
case PE_EXTENSION_FILTER:
if (*element == PE_ROOTDIR)
gjay->prefs->extension_filter = TRUE;
break;
case PE_HIDE_TIP:
if (*element == PE_FLAGS)
gjay->prefs->hide_tips = TRUE;
break;
case PE_WANDER:
if (*element == PE_FLAGS)
gjay->prefs->wander = TRUE;
break;
case PE_USE_RATINGS:
if (*element == PE_FLAGS)
gjay->prefs->use_ratings = TRUE;
break;
case PE_CUTOFF:
if (*element == PE_RATING)
gjay->prefs->rating_cutoff = TRUE;
break;
default:
break;
}
}
}
void data_text ( GMarkupParseContext *context,
const gchar *text,
gsize text_len,
gpointer user_data,
GError **error) {
gchar buffer[BUFFER_SIZE];
gchar * buffer_str;
pref_element_type * element = (pref_element_type *) user_data;
pref_element_type val;
memcpy(buffer, text, text_len);
buffer[text_len] = '\0';
switch(*element) {
case PE_ROOTDIR:
gjay->prefs->song_root_dir = strdup_to_latin1(buffer);
break;
case PE_DAEMON_ACTION:
gjay->prefs->daemon_action = atoi(buffer);
break;
case PE_START:
case PE_SELECTION_LIMIT:
val = get_element((char *) buffer);
switch(val) {
case PE_SELECTED:
gjay->prefs->start_selected = TRUE;
break;
case PE_COLOR:
gjay->prefs->start_color = TRUE;
break;
case PE_SONGS:
gjay->prefs->use_selected_songs = TRUE;
break;
case PE_DIR:
gjay->prefs->use_selected_dir = TRUE;
break;
case PE_RANDOM:
/* Don't do anything */
default:
break;
}
break;
case PE_RATING:
gjay->prefs->rating = strtof_gjay(buffer, NULL);
break;
case PE_HUE:
gjay->prefs->hue = strtof_gjay(buffer, NULL);
break;
case PE_BRIGHTNESS:
gjay->prefs->brightness = strtof_gjay(buffer, NULL);
break;
case PE_SATURATION:
gjay->prefs->saturation = strtof_gjay(buffer, NULL);
break;
case PE_BPM:
gjay->prefs->bpm = strtof_gjay(buffer, NULL);
break;
case PE_FREQ:
gjay->prefs->freq = strtof_gjay(buffer, NULL);
break;
case PE_VARIANCE:
gjay->prefs->variance = strtof_gjay(buffer, NULL);
break;
case PE_PATH_WEIGHT:
gjay->prefs->path_weight = strtof_gjay(buffer, NULL);
break;
case PE_COLOR:
if (gjay->prefs->use_hsv) {
gjay->prefs->color.H = strtof_gjay(buffer, &buffer_str);
gjay->prefs->color.S = strtof_gjay(buffer_str, &buffer_str);
gjay->prefs->color.V = strtof_gjay(buffer_str, NULL);
} else {
HB hb;
hb.H = strtof_gjay(buffer, &buffer_str);
hb.B = strtof_gjay(buffer_str, NULL);
gjay->prefs->color = hb_to_hsv(hb);
}
break;
case PE_TIME:
gjay->prefs->time = atoi(buffer);
break;
default:
break;
case PE_MAX_WORKING_SET:
gjay->prefs->max_working_set = atoi(buffer);
break;
}
*element = PE_LAST;
}
static int get_element ( gchar * element_name ) {
int k;
for (k = 0; k < PE_LAST; k++) {
if (strcasecmp(pref_element_strs[k], element_name) == 0)
return k;
}
return k;
}