#include "snd.h"
#include "sndlib-strings.h"
static GtkWidget *preferences_dialog = NULL, *load_path_text_widget = NULL;
static bool prefs_unsaved = false;
static char *prefs_saved_filename = NULL;
static char *include_load_path = NULL;
#define POWER_WAIT_TIME ((guint32)100)
#define POWER_INITIAL_WAIT_TIME ((guint32)500)
#define ERROR_WAIT_TIME ((guint32)5000)
#if (!HAVE_GTK_WIDGET_GET_VISIBLE)
#define Widget_Is_Sensitive(Wid) GTK_WIDGET_SENSITIVE(Wid)
#else
#define Widget_Is_Sensitive(Wid) gtk_widget_is_sensitive(Wid)
#endif
#define STARTUP_WIDTH 750
#define STARTUP_HEIGHT 800
typedef struct prefs_info {
GtkWidget *label, *text, *arrow_up, *arrow_down, *arrow_right, *error, *toggle, *scale, *toggle2, *toggle3;
GtkWidget *color, *rscl, *gscl, *bscl, *rtxt, *gtxt, *btxt, *list_menu, *radio_button;
GtkAdjustment *adj, *radj, *gadj, *badj;
GtkWidget **radio_buttons;
bool got_error;
timeout_result_t help_id, power_id, erase_id;
const char *var_name, *saved_label;
const char **values;
int num_values, num_buttons;
mus_float_t scale_max;
GtkSizeGroup *color_texts, *color_scales;
void (*toggle_func)(struct prefs_info *prf);
void (*toggle2_func)(struct prefs_info *prf);
void (*toggle3_func)(struct prefs_info *prf);
void (*scale_func)(struct prefs_info *prf);
void (*arrow_up_func)(struct prefs_info *prf);
void (*arrow_down_func)(struct prefs_info *prf);
void (*text_func)(struct prefs_info *prf);
void (*color_func)(struct prefs_info *prf, double r, double g, double b);
void (*reflect_func)(struct prefs_info *prf);
void (*save_func)(struct prefs_info *prf, FILE *fd);
const char *(*help_func)(struct prefs_info *prf);
void (*clear_func)(struct prefs_info *prf);
void (*revert_func)(struct prefs_info *prf);
} prefs_info;
static void prefs_set_dialog_title(const char *filename);
static void reflect_key(prefs_info *prf, const char *key_name);
static void save_key(prefs_info *prf, FILE *fd, char *(*binder)(char *key, bool c, bool m, bool x));
static void key_bind(prefs_info *prf, char *(*binder)(char *key, bool c, bool m, bool x));
static void clear_prefs_dialog_error(void);
static void scale_set_color(prefs_info *prf, color_t pixel);
static char *get_text(GtkWidget *w);
static void set_text(GtkWidget *w, const char *value);
static void post_prefs_error(const char *msg, prefs_info *data);
#ifdef __GNUC__
static void va_post_prefs_error(const char *msg, prefs_info *data, ...) __attribute__ ((format (printf, 1, 0)));
#else
static void va_post_prefs_error(const char *msg, prefs_info *data, ...);
#endif
/* used in snd-prefs.c */
#define GET_TOGGLE(Toggle) gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Toggle))
#define SET_TOGGLE(Toggle, Value) set_toggle_button(Toggle, Value, false, (void *)prf)
#define GET_TEXT(Text) get_text(Text)
#define SET_TEXT(Text, Val) set_text(Text, Val)
#define free_TEXT(Val)
#define TIMEOUT(Func) g_timeout_add_full(0, ERROR_WAIT_TIME, Func, (gpointer)prf, NULL)
#define SET_SCALE(Value) ADJUSTMENT_SET_VALUE(prf->adj, Value)
#define GET_SCALE() (ADJUSTMENT_VALUE(prf->adj) * prf->scale_max)
#define SET_SENSITIVE(Wid, Val) gtk_widget_set_sensitive(Wid, Val)
#define black_text(Prf)
#define red_text(Prf)
/* gdk_gc_set_foreground(Prf->label->style->black_gc, ss->red) no effect? */
static GtkWidget *make_basic_row(GtkWidget *box)
{
#if GTK_CHECK_VERSION(3, 92, 1)
GtkWidget *row;
row = gtk_hbox_new(false, 0);
sg_box_pack_start(GTK_BOX(box), row, false, false, 0);
gtk_widget_set_hexpand(GTK_WIDGET(row), true);
gtk_widget_show(row);
#else
#if GTK_CHECK_VERSION(3, 0, 0)
GtkWidget *row, *r;
r = gtk_event_box_new(); /* not button! */
gtk_widget_set_hexpand(GTK_WIDGET(r), true);
sg_box_pack_start(GTK_BOX(box), r, false, false, 0);
add_highlight_button_style(r);
gtk_widget_show(r);
row = gtk_hbox_new(false, 0);
gtk_container_add(GTK_CONTAINER(r), row);
gtk_widget_set_hexpand(GTK_WIDGET(row), true);
gtk_widget_show(row);
#else
GtkWidget *row;
row = gtk_hbox_new(false, 0);
sg_box_pack_start(GTK_BOX(box), row, false, false, 0);
gtk_widget_show(row);
#endif
#endif
return(row);
}
static void set_radio_button(prefs_info *prf, int which)
{
if ((which >= 0) && (which < prf->num_buttons))
set_toggle_button(prf->radio_buttons[which], true, false, (void *)prf);
}
#define which_radio_button(Prf) get_user_int_data(G_OBJECT(Prf->radio_button))
#include "snd-prefs.c"
static void sg_entry_set_text(GtkEntry* entry, const char *text)
{
if (text)
gtk_entry_set_text(entry, (gchar *)text);
else gtk_entry_set_text(entry, " ");
}
static void set_text(GtkWidget *w, const char *value)
{
if (GTK_IS_ENTRY(w))
sg_entry_set_text(GTK_ENTRY(w), value);
else
{
if (GTK_IS_ENTRY(BIN_CHILD(w)))
sg_entry_set_text(GTK_ENTRY(BIN_CHILD(w)), value);
}
}
static char *get_text(GtkWidget *w)
{
if (GTK_IS_ENTRY(w))
return((char *)gtk_entry_get_text(GTK_ENTRY(w)));
if (GTK_IS_ENTRY(BIN_CHILD(w)))
return((char *)gtk_entry_get_text(GTK_ENTRY(BIN_CHILD(w))));
return(NULL);
}
/* ---------------- help strings ---------------- */
static bool prefs_dialog_error_is_posted = false;
static void post_prefs_dialog_error(const char *message, void *data)
{
gtk_window_set_title(GTK_WINDOW(preferences_dialog), (char *)message);
prefs_dialog_error_is_posted = (bool)message;
}
static void clear_prefs_dialog_error(void)
{
if (prefs_dialog_error_is_posted)
{
prefs_dialog_error_is_posted = false;
post_prefs_dialog_error(NULL, NULL);
}
}
static void prefs_change_callback(GtkWidget *w, gpointer context)
{
prefs_unsaved = true;
prefs_set_dialog_title(NULL);
clear_prefs_dialog_error();
}
static GtkSizeGroup *label_group;
static GtkSizeGroup *widgets_group;
static color_info *rscl_color, *gscl_color, *bscl_color;
#define PACK_1 true
#define PACK_2 false
/* ---------------- row (main) label widget ---------------- */
static GtkWidget *make_row_label(prefs_info *prf, const char *label, GtkWidget *box)
{
GtkWidget *w;
w = gtk_label_new(label);
#if (!GTK_CHECK_VERSION(3, 0, 0))
gtk_misc_set_alignment(GTK_MISC(w), 1.0, 0.0);
#else
#if GTK_CHECK_VERSION(3, 14, 0)
gtk_widget_set_halign(GTK_WIDGET(w), GTK_ALIGN_END);
#else
gtk_misc_set_alignment(GTK_MISC(w), 1.0, 0.5);
#endif
#endif
gtk_size_group_add_widget(label_group, w);
sg_box_pack_start(GTK_BOX(box), w, PACK_1, PACK_2, 0);
gtk_widget_show(w);
prf->saved_label = label;
return(w);
}
/* ---------------- row inner label widget ---------------- */
static void make_row_inner_label(prefs_info *prf, const char *label, GtkWidget *box)
{
GtkWidget *w;
w = gtk_label_new(label);
sg_box_pack_start(GTK_BOX(box), w, false, false, 4);
gtk_widget_show(w);
}
/* ---------------- row middle separator widget ---------------- */
static void make_row_middle_separator(GtkWidget *box)
{
GtkWidget *w;
w = gtk_vseparator_new();
sg_box_pack_start(GTK_BOX(box), w, false, false, 10);
gtk_widget_show(w);
}
/* ---------------- row inner separator widget ---------------- */
static void make_row_inner_separator(int width, GtkWidget *box)
{
GtkWidget *w;
w = gtk_hseparator_new();
sg_box_pack_start(GTK_BOX(box), w, false, false, width);
gtk_widget_show(w);
}
/* ---------------- row toggle widget ---------------- */
static GtkWidget *make_row_toggle_with_label(prefs_info *prf, bool current_value, GtkWidget *box, const char *label)
{
GtkWidget *w;
if (label)
w = gtk_check_button_new_with_label(label);
else w = gtk_check_button_new();
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), current_value);
sg_box_pack_start(GTK_BOX(box), w, false, false, 0); /* was 10 */
gtk_widget_show(w);
SG_SIGNAL_CONNECT(w, "toggled", prefs_change_callback, NULL);
return(w);
}
static GtkWidget *make_row_toggle(prefs_info *prf, bool current_value, GtkWidget *box)
{
return(make_row_toggle_with_label(prf, current_value, box, NULL));
}
/* ---------------- error widget ---------------- */
static GtkWidget *make_row_error(prefs_info *prf, GtkWidget *box)
{
GtkWidget *w;
w = gtk_label_new("");
sg_box_pack_end(GTK_BOX(box), w, true, false, 0);
gtk_widget_show(w);
return(w);
}
/* ---------------- row arrows ---------------- */
static gboolean remove_arrow_func(GtkWidget *w, GdkEventButton *ev, gpointer context)
{
prefs_info *prf = (prefs_info *)context;
if (prf->power_id != 0)
{
g_source_remove(prf->power_id);
prf->power_id = 0;
}
return(false);
}
static gint arrow_func_up(gpointer context)
{
prefs_info *prf = (prefs_info *)context;
if (Widget_Is_Sensitive(prf->arrow_up))
{
if (prf->arrow_up_func)
{
(*(prf->arrow_up_func))(prf);
prf->power_id = g_timeout_add_full(0,
POWER_WAIT_TIME,
arrow_func_up,
(gpointer)prf, NULL);
}
else prf->power_id = 0;
}
return(0);
}
static gint arrow_func_down(gpointer context)
{
prefs_info *prf = (prefs_info *)context;
if (Widget_Is_Sensitive(prf->arrow_down))
{
if (prf->arrow_down_func)
{
(*(prf->arrow_down_func))(prf);
prf->power_id = g_timeout_add_full(0,
POWER_WAIT_TIME,
arrow_func_down,
(gpointer)prf, NULL);
}
else prf->power_id = 0;
}
return(0);
}
static gboolean call_arrow_down_press(GtkWidget *w, GdkEventButton *ev, gpointer context)
{
prefs_info *prf = (prefs_info *)context;
if ((prf) && (prf->arrow_down_func))
{
(*(prf->arrow_down_func))(prf);
if (Widget_Is_Sensitive(w))
prf->power_id = g_timeout_add_full(0,
POWER_INITIAL_WAIT_TIME,
arrow_func_down,
(gpointer)prf, NULL);
else prf->power_id = 0;
}
return(false);
}
static gboolean call_arrow_up_press(GtkWidget *w, GdkEventButton *ev, gpointer context)
{
prefs_info *prf = (prefs_info *)context;
if ((prf) && (prf->arrow_up_func))
{
(*(prf->arrow_up_func))(prf);
if (Widget_Is_Sensitive(w))
prf->power_id = g_timeout_add_full(0,
POWER_INITIAL_WAIT_TIME,
arrow_func_up,
(gpointer)prf, NULL);
else prf->power_id = 0;
}
return(false);
}
static GtkWidget *make_row_arrows(prefs_info *prf, GtkWidget *box)
{
#if (!GTK_CHECK_VERSION(3, 92, 1))
GtkWidget *ev_up, *ev_down;
#endif
GtkWidget *up, *down;
#if GTK_CHECK_VERSION(3, 14, 0)
GtkIconTheme *icon_theme;
icon_theme = gtk_icon_theme_get_default();
#endif
#if (!GTK_CHECK_VERSION(3, 92, 1))
ev_down = gtk_event_box_new();
sg_box_pack_start(GTK_BOX(box), ev_down, false, false, 0);
gtk_widget_show(ev_down);
#endif
#if GTK_CHECK_VERSION(3, 14, 0)
down = gtk_image_new_from_pixbuf(gtk_icon_theme_load_icon(icon_theme, "pan-down-symbolic", 16, (GtkIconLookupFlags)0, NULL));
#else
down = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_ETCHED_OUT);
#endif
#if (!GTK_CHECK_VERSION(3, 92, 1))
gtk_container_add(GTK_CONTAINER(ev_down), down);
#else
sg_box_pack_start(GTK_BOX(box), down, false, false, 0);
#endif
gtk_widget_show(down);
#if (!GTK_CHECK_VERSION(3, 92, 1))
ev_up = gtk_event_box_new();
sg_box_pack_start(GTK_BOX(box), ev_up, false, false, 0);
gtk_widget_show(ev_up);
#endif
#if GTK_CHECK_VERSION(3, 14, 0)
up = gtk_image_new_from_pixbuf(gtk_icon_theme_load_icon(icon_theme, "pan-up-symbolic", 16, (GtkIconLookupFlags)0, NULL));
#else
up = gtk_arrow_new(GTK_ARROW_UP, GTK_SHADOW_ETCHED_OUT);
#endif
#if (!GTK_CHECK_VERSION(3, 92, 1))
gtk_container_add(GTK_CONTAINER(ev_up), up);
#else
sg_box_pack_start(GTK_BOX(box), up, false, false, 0);
#endif
gtk_widget_show(up);
prf->arrow_up = up;
prf->arrow_down = down;
#if (!GTK_CHECK_VERSION(3, 92, 1))
SG_SIGNAL_CONNECT(ev_down, "button_press_event", call_arrow_down_press, (gpointer)prf);
SG_SIGNAL_CONNECT(ev_down, "button_release_event", remove_arrow_func, (gpointer)prf);
SG_SIGNAL_CONNECT(ev_up, "button_press_event", call_arrow_up_press, (gpointer)prf);
SG_SIGNAL_CONNECT(ev_up, "button_release_event", remove_arrow_func, (gpointer)prf);
SG_SIGNAL_CONNECT(ev_down, "button_press_event", prefs_change_callback, NULL);
SG_SIGNAL_CONNECT(ev_up, "button_press_event", prefs_change_callback, NULL);
#else
SG_SIGNAL_CONNECT(down, "button_press_event", call_arrow_down_press, (gpointer)prf);
SG_SIGNAL_CONNECT(down, "button_release_event", remove_arrow_func, (gpointer)prf);
SG_SIGNAL_CONNECT(up, "button_press_event", call_arrow_up_press, (gpointer)prf);
SG_SIGNAL_CONNECT(up, "button_release_event", remove_arrow_func, (gpointer)prf);
SG_SIGNAL_CONNECT(down, "button_press_event", prefs_change_callback, NULL);
SG_SIGNAL_CONNECT(up, "button_press_event", prefs_change_callback, NULL);
#endif
return(up);
}
/* ---------------- bool row ---------------- */
static void call_toggle_func(GtkWidget *w, gpointer context)
{
prefs_info *prf = (prefs_info *)context;
if ((prf) && (prf->toggle_func))
(*(prf->toggle_func))(prf);
}
static prefs_info *prefs_row_with_toggle(const char *label, const char *varname, bool current_value,
GtkWidget *box,
void (*toggle_func)(prefs_info *prf))
{
prefs_info *prf;
GtkWidget *hb, *row;
prf = (prefs_info *)calloc(1, sizeof(prefs_info));
prf->var_name = varname;
prf->toggle_func = toggle_func;
row = make_basic_row(box);
prf->label = make_row_label(prf, label, row);
hb = gtk_hbox_new(false, 0);
gtk_size_group_add_widget(widgets_group, hb);
sg_box_pack_start(GTK_BOX(row), hb, false, false, 0);
gtk_widget_show(hb);
make_row_middle_separator(hb);
prf->toggle = make_row_toggle(prf, current_value, hb);
SG_SIGNAL_CONNECT(prf->toggle, "toggled", call_toggle_func, (gpointer)prf);
return(prf);
}
/* ---------------- two toggles ---------------- */
static void call_toggle2_func(GtkWidget *w, gpointer context)
{
prefs_info *prf = (prefs_info *)context;
if ((prf) && (prf->toggle2_func))
(*(prf->toggle2_func))(prf);
}
static prefs_info *prefs_row_with_two_toggles(const char *label, const char *varname,
const char *label1, bool value1,
const char *label2, bool value2,
GtkWidget *box,
void (*toggle_func)(prefs_info *prf),
void (*toggle2_func)(prefs_info *prf))
{
prefs_info *prf;
GtkWidget *row, *hb;
prf = (prefs_info *)calloc(1, sizeof(prefs_info));
prf->var_name = varname;
prf->toggle_func = toggle_func;
prf->toggle2_func = toggle2_func;
row = make_basic_row(box);
prf->label = make_row_label(prf, label, row);
hb = gtk_hbox_new(false, 0);
gtk_size_group_add_widget(widgets_group, hb);
sg_box_pack_start(GTK_BOX(row), hb, false, false, 0);
gtk_widget_show(hb);
make_row_middle_separator(hb);
prf->toggle = make_row_toggle_with_label(prf, value1, hb, label1);
make_row_inner_separator(20, hb);
prf->toggle2 = make_row_toggle_with_label(prf, value2, hb, label2);
SG_SIGNAL_CONNECT(prf->toggle, "toggled", call_toggle_func, (gpointer)prf);
SG_SIGNAL_CONNECT(prf->toggle2, "toggled", call_toggle2_func, (gpointer)prf);
return(prf);
}
/* ---------------- toggle with text ---------------- */
/* see commentary in snd-xprefs.c */
typedef struct {
bool text_focussed, text_changed;
prefs_info *prf;
} text_info;
static void text_change_callback(GtkWidget *w, gpointer context)
{
text_info *data = (text_info *)context;
if (data->text_focussed) /* try to omit non-user actions that change the value */
data->text_changed = true;
}
static void text_activate_callback(GtkWidget *w, gpointer context)
{
text_info *data = (text_info *)context;
data->text_changed = false;
}
static void text_grab_focus_callback(GtkWidget *w, GdkEventCrossing *ev, gpointer context)
{
text_info *data = (text_info *)context;
if (with_pointer_focus(ss))
goto_window(w);
data->text_focussed = true;
}
static void text_lose_focus_callback(GtkWidget *w, GdkEventCrossing *ev, gpointer context)
{
text_info *data = (text_info *)context;
if ((data->text_focussed) &&
(data->text_changed) &&
(data->prf) &&
(data->prf->text_func))
{
(*(data->prf->text_func))(data->prf);
data->text_changed = false;
}
}
static void call_text_func(GtkWidget *w, gpointer context)
{
prefs_info *prf = (prefs_info *)context;
if ((prf) && (prf->text_func))
(*(prf->text_func))(prf);
}
static GtkWidget *make_row_text(prefs_info *prf, const char *text_value, int cols, GtkWidget *box)
{
int len;
GtkWidget *w;
GtkSettings *settings;
text_info *info;
len = mus_strlen(text_value);
w = gtk_entry_new();
gtk_entry_set_has_frame(GTK_ENTRY(w), true);
if (text_value) sg_entry_set_text(GTK_ENTRY(w), text_value);
gtk_entry_set_has_frame(GTK_ENTRY(w), false);
#if (!GTK_CHECK_VERSION(3, 96, 0))
if (cols > 0)
gtk_entry_set_width_chars(GTK_ENTRY(w), cols);
else
{
if (len > 24) /* sigh... */
gtk_entry_set_width_chars(GTK_ENTRY(w), len);
}
#endif
gtk_editable_set_editable(GTK_EDITABLE(w), true);
settings = gtk_widget_get_settings(w);
g_object_set(settings, "gtk-entry-select-on-focus", false, NULL);
sg_box_pack_start(GTK_BOX(box), w, false, false, 0);
gtk_widget_show(w);
info = (text_info *)calloc(1, sizeof(text_info));
info->prf = prf;
SG_SIGNAL_CONNECT(w, "enter_notify_event", text_grab_focus_callback, (gpointer)info);
SG_SIGNAL_CONNECT(w, "leave_notify_event", text_lose_focus_callback, (gpointer)info);
SG_SIGNAL_CONNECT(w, "changed", text_change_callback, (gpointer)info);
SG_SIGNAL_CONNECT(w, "activate", text_activate_callback, (gpointer)info);
return(w);
}
static prefs_info *prefs_row_with_toggle_with_text(const char *label, const char *varname, bool current_value,
const char *text_label, const char *text_value, int cols,
GtkWidget *box,
void (*toggle_func)(prefs_info *prf),
void (*text_func)(prefs_info *prf))
{
prefs_info *prf;
GtkWidget *hb, *row;
prf = (prefs_info *)calloc(1, sizeof(prefs_info));
prf->var_name = varname;
prf->toggle_func = toggle_func;
prf->text_func = text_func;
row = make_basic_row(box);
prf->label = make_row_label(prf, label, row);
hb = gtk_hbox_new(false, 0);
gtk_size_group_add_widget(widgets_group, hb);
sg_box_pack_start(GTK_BOX(row), hb, false, false, 0);
gtk_widget_show(hb);
make_row_middle_separator(hb);
prf->toggle = make_row_toggle(prf, current_value, hb);
make_row_inner_separator(16, hb);
make_row_inner_label(prf, text_label, hb);
prf->text= make_row_text(prf, text_value, cols, hb);
SG_SIGNAL_CONNECT(prf->toggle, "toggled", call_toggle_func, (gpointer)prf);
SG_SIGNAL_CONNECT(prf->text, "activate", call_text_func, (gpointer)prf);
return(prf);
}
static prefs_info *prefs_row_with_toggle_with_two_texts(const char *label, const char *varname, bool current_value,
const char *label1, const char *text1,
const char *label2, const char *text2, int cols,
GtkWidget *box,
void (*toggle_func)(prefs_info *prf),
void (*text_func)(prefs_info *prf))
{
prefs_info *prf;
GtkWidget *hb, *row;
prf = (prefs_info *)calloc(1, sizeof(prefs_info));
prf->var_name = varname;
prf->toggle_func = toggle_func;
prf->text_func = text_func;
row = make_basic_row(box);
prf->label = make_row_label(prf, label, row);
hb = gtk_hbox_new(false, 0);
gtk_size_group_add_widget(widgets_group, hb);
sg_box_pack_start(GTK_BOX(row), hb, false, false, 0);
gtk_widget_show(hb);
make_row_middle_separator(hb);
prf->toggle = make_row_toggle(prf, current_value, hb);
make_row_inner_separator(16, hb);
make_row_inner_label(prf, label1, hb);
prf->text= make_row_text(prf, text1, cols, hb);
make_row_inner_label(prf, label2, hb);
prf->rtxt= make_row_text(prf, text2, cols, hb);
SG_SIGNAL_CONNECT(prf->toggle, "toggled", call_toggle_func, (gpointer)prf);
SG_SIGNAL_CONNECT(prf->text, "activate", call_text_func, (gpointer)prf);
SG_SIGNAL_CONNECT(prf->rtxt, "activate", call_text_func, (gpointer)prf);
return(prf);
}
/* ---------------- text with toggle ---------------- */
static prefs_info *prefs_row_with_text_with_toggle(const char *label, const char *varname, bool current_value,
const char *toggle_label, const char *text_value, int cols,
GtkWidget *box,
void (*toggle_func)(prefs_info *prf),
void (*text_func)(prefs_info *prf))
{
prefs_info *prf;
GtkWidget *hb, *row;
prf = (prefs_info *)calloc(1, sizeof(prefs_info));
prf->var_name = varname;
prf->toggle_func = toggle_func;
prf->text_func = text_func;
row = make_basic_row(box);
prf->label = make_row_label(prf, label, row);
hb = gtk_hbox_new(false, 0);
gtk_size_group_add_widget(widgets_group, hb);
sg_box_pack_start(GTK_BOX(row), hb, false, false, 0);
gtk_widget_show(hb);
make_row_middle_separator(hb);
prf->text = make_row_text(prf, text_value, cols, hb);
make_row_inner_separator(8, hb);
make_row_inner_label(prf, toggle_label, hb);
prf->toggle = make_row_toggle(prf, current_value, hb);
SG_SIGNAL_CONNECT(prf->toggle, "toggled", call_toggle_func, (gpointer)prf);
SG_SIGNAL_CONNECT(prf->text, "activate", call_text_func, (gpointer)prf);
return(prf);
}
/* ---------------- text with three toggle ---------------- */
static prefs_info *prefs_row_with_text_and_three_toggles(const char *label, const char *varname,
const char *text_label, int cols,
const char *toggle1_label, const char *toggle2_label, const char *toggle3_label,
const char *text_value,
bool toggle1_value, bool toggle2_value, bool toggle3_value,
GtkWidget *box,
void (*text_func)(prefs_info *prf))
{
prefs_info *prf;
GtkWidget *hb, *row;
prf = (prefs_info *)calloc(1, sizeof(prefs_info));
prf->var_name = varname;
prf->text_func = text_func;
row = make_basic_row(box);
prf->label = make_row_label(prf, label, row);
hb = gtk_hbox_new(false, 0);
gtk_size_group_add_widget(widgets_group, hb);
sg_box_pack_start(GTK_BOX(row), hb, false, false, 0);
gtk_widget_show(hb);
make_row_middle_separator(hb);
make_row_inner_label(prf, text_label, hb);
prf->text = make_row_text(prf, text_value, cols, hb);
make_row_inner_separator(12, hb);
make_row_inner_label(prf, toggle1_label, hb);
prf->toggle = make_row_toggle(prf, toggle1_value, hb);
make_row_inner_separator(4, hb);
make_row_inner_label(prf, toggle2_label, hb);
prf->toggle2 = make_row_toggle(prf, toggle2_value, hb);
make_row_inner_separator(4, hb);
make_row_inner_label(prf, toggle3_label, hb);
prf->toggle3 = make_row_toggle(prf, toggle3_value, hb);
SG_SIGNAL_CONNECT(prf->text, "activate", call_text_func, (gpointer)prf);
return(prf);
}
/* ---------------- radio row ---------------- */
static void call_radio_func(GtkWidget *w, gpointer context)
{
prefs_info *prf = (prefs_info *)context;
if ((prf) && (prf->toggle_func))
{
prf->radio_button = w;
(*(prf->toggle_func))(prf);
}
}
static GtkWidget *make_row_radio_box(prefs_info *prf,
const char **labels, int num_labels, int current_value,
GtkWidget *box)
{
GtkWidget *w, *current_button;
int i;
w = gtk_hbox_new(false, 0);
sg_box_pack_start(GTK_BOX(box), w, false, false, 0);
gtk_widget_show(w);
prf->radio_buttons = (GtkWidget **)calloc(num_labels, sizeof(GtkWidget *));
prf->num_buttons = num_labels;
for (i = 0; i < num_labels; i++)
{
if (i == 0)
current_button = gtk_radio_button_new_with_label(NULL, labels[i]);
else current_button = gtk_radio_button_new_with_label(gtk_radio_button_get_group(GTK_RADIO_BUTTON(prf->radio_buttons[0])), labels[i]);
prf->radio_buttons[i] = current_button;
sg_box_pack_start(GTK_BOX(w), current_button, false, false, 0);
set_user_int_data(G_OBJECT(current_button), i);
gtk_widget_show(current_button);
SG_SIGNAL_CONNECT(current_button, "clicked", call_radio_func, (gpointer)prf);
SG_SIGNAL_CONNECT(current_button, "clicked", prefs_change_callback, NULL);
}
if (current_value != -1)
set_toggle_button(prf->radio_buttons[current_value], true, false, (void *)prf);
return(w);
}
static prefs_info *prefs_row_with_radio_box(const char *label, const char *varname,
const char **labels, int num_labels, int current_value,
GtkWidget *box,
void (*toggle_func)(prefs_info *prf))
{
prefs_info *prf;
GtkWidget *hb, *row;
prf = (prefs_info *)calloc(1, sizeof(prefs_info));
prf->var_name = varname;
prf->toggle_func = toggle_func;
row = make_basic_row(box);
prf->label = make_row_label(prf, label, row);
hb = gtk_hbox_new(false, 0);
gtk_size_group_add_widget(widgets_group, hb);
sg_box_pack_start(GTK_BOX(row), hb, false, false, 0);
gtk_widget_show(hb);
make_row_middle_separator(hb);
prf->toggle = make_row_radio_box(prf, labels, num_labels, current_value, hb);
return(prf);
}
static prefs_info *prefs_row_with_radio_box_and_number(const char *label, const char *varname,
const char **labels, int num_labels, int current_value,
const char *text_value, int text_cols,
GtkWidget *box,
void (*toggle_func)(prefs_info *prf),
void (*arrow_up_func)(prefs_info *prf), void (*arrow_down_func)(prefs_info *prf),
void (*text_func)(prefs_info *prf))
{
prefs_info *prf;
GtkWidget *row, *hb;
prf = (prefs_info *)calloc(1, sizeof(prefs_info));
prf->var_name = varname;
prf->toggle_func = toggle_func;
prf->text_func = text_func;
prf->arrow_up_func = arrow_up_func;
prf->arrow_down_func = arrow_down_func;
row = make_basic_row(box);
prf->label = make_row_label(prf, label, row);
hb = gtk_hbox_new(false, 0);
gtk_size_group_add_widget(widgets_group, hb);
sg_box_pack_start(GTK_BOX(row), hb, false, false, 0);
gtk_widget_show(hb);
make_row_middle_separator(hb);
prf->toggle = make_row_radio_box(prf, labels, num_labels, current_value, hb);
prf->text = make_row_text(prf, text_value, text_cols, hb);
prf->arrow_up = make_row_arrows(prf, hb);
SG_SIGNAL_CONNECT(prf->text, "activate", call_text_func, (gpointer)prf);
return(prf);
}
/* ---------------- scale row ---------------- */
static void call_scale_func(GtkAdjustment *w, gpointer context)
{
prefs_info *prf = (prefs_info *)context;
if ((prf) && (prf->scale_func))
(*(prf->scale_func))(prf);
}
static void call_scale_text_func(GtkWidget *w, gpointer context)
{
prefs_info *prf = (prefs_info *)context;
if ((prf) && (prf->text_func))
(*(prf->text_func))(prf);
}
static void prefs_scale_callback(GtkWidget *w, gpointer context)
{
prefs_info *prf = (prefs_info *)context;
float_to_textfield(prf->text, ADJUSTMENT_VALUE(prf->adj) * prf->scale_max);
}
static prefs_info *prefs_row_with_scale(const char *label, const char *varname,
mus_float_t max_val, mus_float_t current_value,
GtkWidget *box,
void (*scale_func)(prefs_info *prf),
void (*text_func)(prefs_info *prf))
{
prefs_info *prf;
GtkWidget *hb, *row;
char *str;
prf = (prefs_info *)calloc(1, sizeof(prefs_info));
prf->var_name = varname;
prf->scale_max = max_val;
row = make_basic_row(box);
prf->label = make_row_label(prf, label, row);
hb = gtk_hbox_new(false, 0);
gtk_size_group_add_widget(widgets_group, hb);
sg_box_pack_start(GTK_BOX(row), hb, false, false, 0);
gtk_widget_show(hb);
make_row_middle_separator(hb);
str = (char *)calloc(12, sizeof(char));
snprintf(str, 12, "%.3f", current_value);
prf->text = make_row_text(prf, str, 6, hb);
free(str);
prf->adj = (GtkAdjustment *)gtk_adjustment_new(current_value /max_val, 0.0, 1.01, 0.001, 0.01, .01);
prf->scale = gtk_hscale_new(GTK_ADJUSTMENT(prf->adj));
sg_box_pack_start(GTK_BOX(hb), prf->scale, true, true, 4);
gtk_widget_show(prf->scale);
gtk_range_set_update_policy(GTK_RANGE(GTK_SCALE(prf->scale)), GTK_UPDATE_CONTINUOUS);
gtk_scale_set_draw_value(GTK_SCALE(prf->scale), false);
prf->scale_func = scale_func;
prf->text_func = text_func;
SG_SIGNAL_CONNECT(prf->scale, "value_changed", call_scale_func, (gpointer)prf);
SG_SIGNAL_CONNECT(prf->scale, "value_changed", prefs_change_callback, NULL);
SG_SIGNAL_CONNECT(prf->scale, "value_changed", prefs_scale_callback, (gpointer)prf);
SG_SIGNAL_CONNECT(prf->text, "activate", call_scale_text_func, (gpointer)prf);
return(prf);
}
/* ---------------- text row ---------------- */
static prefs_info *prefs_row_with_text(const char *label, const char *varname, const char *value,
GtkWidget *box,
void (*text_func)(prefs_info *prf))
{
prefs_info *prf;
GtkWidget *hb, *row;
prf = (prefs_info *)calloc(1, sizeof(prefs_info));
prf->var_name = varname;
row = make_basic_row(box);
prf->label = make_row_label(prf, label, row);
hb = gtk_hbox_new(false, 0);
gtk_size_group_add_widget(widgets_group, hb);
sg_box_pack_start(GTK_BOX(row), hb, false, false, 0);
gtk_widget_show(hb);
make_row_middle_separator(hb);
prf->text = make_row_text(prf, value, 0, hb);
prf->text_func = text_func;
SG_SIGNAL_CONNECT(prf->text, "activate", call_text_func, (gpointer)prf);
return(prf);
}
/* ---------------- two texts in a row ---------------- */
static prefs_info *prefs_row_with_two_texts(const char *label, const char *varname,
const char *label1, const char *text1, const char *label2, const char *text2, int cols,
GtkWidget *box,
void (*text_func)(prefs_info *prf))
{
prefs_info *prf;
GtkWidget *hb, *row;
prf = (prefs_info *)calloc(1, sizeof(prefs_info));
prf->var_name = varname;
row = make_basic_row(box);
prf->label = make_row_label(prf, label, row);
hb = gtk_hbox_new(false, 0);
gtk_size_group_add_widget(widgets_group, hb);
sg_box_pack_start(GTK_BOX(row), hb, false, false, 0);
gtk_widget_show(hb);
make_row_middle_separator(hb);
make_row_inner_label(prf, label1, hb);
prf->text = make_row_text(prf, text1, cols, hb);
make_row_inner_label(prf, label2, hb);
prf->rtxt = make_row_text(prf, text2, cols, hb);
prf->text_func = text_func;
SG_SIGNAL_CONNECT(prf->text, "activate", call_text_func, (gpointer)prf);
SG_SIGNAL_CONNECT(prf->rtxt, "activate", call_text_func, (gpointer)prf);
return(prf);
}
/* ---------------- number row ---------------- */
static prefs_info *prefs_row_with_number(const char *label, const char *varname, const char *value, int cols,
GtkWidget *box,
void (*arrow_up_func)(prefs_info *prf), void (*arrow_down_func)(prefs_info *prf),
void (*text_func)(prefs_info *prf))
{
prefs_info *prf;
GtkWidget *hb, *row;
prf = (prefs_info *)calloc(1, sizeof(prefs_info));
prf->var_name = varname;
row = make_basic_row(box);
prf->label = make_row_label(prf, label, row);
hb = gtk_hbox_new(false, 0);
gtk_size_group_add_widget(widgets_group, hb);
sg_box_pack_start(GTK_BOX(row), hb, false, false, 0);
gtk_widget_show(hb);
make_row_middle_separator(hb);
prf->text = make_row_text(prf, value, cols, hb);
prf->arrow_up = make_row_arrows(prf, hb);
prf->error = make_row_error(prf, hb);
prf->text_func = text_func;
prf->arrow_up_func = arrow_up_func;
prf->arrow_down_func = arrow_down_func;
SG_SIGNAL_CONNECT(prf->text, "activate", call_text_func, (gpointer)prf);
return(prf);
}
/* ---------------- list row ---------------- */
static prefs_info *prefs_row_with_list(const char *label, const char *varname, const char *value,
const char **values, int num_values,
GtkWidget *box,
void (*text_func)(prefs_info *prf),
char *(*completion_func)(widget_t w, const char *text, void *context), void *completion_context)
{
int i;
prefs_info *prf;
GtkWidget *hb, *row;
prf = (prefs_info *)calloc(1, sizeof(prefs_info));
prf->var_name = varname;
row = make_basic_row(box);
prf->label = make_row_label(prf, label, row);
hb = gtk_hbox_new(false, 0);
gtk_size_group_add_widget(widgets_group, hb);
sg_box_pack_start(GTK_BOX(row), hb, false, false, 0);
gtk_widget_show(hb);
make_row_middle_separator(hb);
#if GTK_CHECK_VERSION(3, 0, 0)
prf->text = gtk_combo_box_text_new_with_entry();
for (i = 0; i < num_values; i++)
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(prf->text), (values[i]) ? values[i] : " ");
#else
prf->text = gtk_combo_box_entry_new_text();
for (i = 0; i < num_values; i++)
gtk_combo_box_append_text(GTK_COMBO_BOX(prf->text), (values[i]) ? values[i] : " ");
#endif
sg_entry_set_text(GTK_ENTRY(BIN_CHILD(prf->text)), value);
sg_box_pack_start(GTK_BOX(hb), prf->text, false, false, 4);
gtk_widget_show(prf->text);
prf->error = make_row_error(prf, hb);
prf->text_func = text_func;
SG_SIGNAL_CONNECT(prf->text, "changed", call_text_func, (gpointer)prf);
SG_SIGNAL_CONNECT(prf->text, "changed", prefs_change_callback, NULL);
return(prf);
}
/* ---------------- color selector row(s) ---------------- */
static void pixel_to_rgb(color_t pix, double *r, double *g, double *b)
{
(*r) = rgb_to_float(pix->red);
(*g) = rgb_to_float(pix->green);
(*b) = rgb_to_float(pix->blue);
}
#if GTK_CHECK_VERSION(3, 92, 0)
static void display_color(GtkWidget *w, color_t pixel) {}
#else
#if GTK_CHECK_VERSION(3, 0, 0)
static void display_color(GtkWidget *w, color_t pixel)
{
cairo_t *cr;
#if GTK_CHECK_VERSION(3, 22, 0)
GdkWindow *window;
GdkDrawingContext *context;
window = WIDGET_TO_WINDOW(w);
context = gdk_window_begin_draw_frame(window, gdk_window_get_visible_region(window));
cr = gdk_drawing_context_get_cairo_context(context);
#else
cr = gdk_cairo_create(WIDGET_TO_WINDOW(w));
#endif
cairo_set_source_rgba(cr, pixel->red, pixel->green, pixel->blue, pixel->alpha);
cairo_rectangle(cr, 0, 0, widget_width(w), widget_height(w));
cairo_fill(cr);
#if GTK_CHECK_VERSION(3, 22, 0)
gdk_window_end_draw_frame(window, context);
#else
cairo_destroy(cr);
#endif
}
#endif
#endif
static void scale_set_color(prefs_info *prf, color_t pixel)
{
double r = 0.0, g = 0.0, b = 0.0;
pixel_to_rgb(pixel, &r, &g, &b);
float_to_textfield(prf->rtxt, r);
ADJUSTMENT_SET_VALUE(prf->radj, r);
float_to_textfield(prf->gtxt, g);
ADJUSTMENT_SET_VALUE(prf->gadj, g);
float_to_textfield(prf->btxt, b);
ADJUSTMENT_SET_VALUE(prf->badj, b);
#if GTK_CHECK_VERSION(3, 0, 0)
display_color(prf->color, pixel);
#else
widget_modify_bg(prf->color, GTK_STATE_NORMAL, pixel);
#endif
}
static void reflect_color(prefs_info *prf)
{
mus_float_t r, g, b;
color_info *current_color;
r = ADJUSTMENT_VALUE(prf->radj);
g = ADJUSTMENT_VALUE(prf->gadj);
b = ADJUSTMENT_VALUE(prf->badj);
current_color = rgb_to_color(r, g, b);
#if GTK_CHECK_VERSION(3, 0, 0)
display_color(prf->color, current_color);
#else
widget_modify_bg(prf->color, GTK_STATE_NORMAL, current_color);
#endif
float_to_textfield(prf->rtxt, r);
float_to_textfield(prf->gtxt, g);
float_to_textfield(prf->btxt, b);
}
static void prefs_color_callback(GtkWidget *w, gpointer context)
{
reflect_color((prefs_info *)context);
}
static gint unpost_color_error(gpointer data)
{
prefs_info *prf = (prefs_info *)data;
prf->got_error = false;
gtk_label_set_text(GTK_LABEL(prf->label), prf->saved_label);
reflect_color(prf);
return(0);
}
static void errors_to_color_text(const char *msg, void *data)
{
prefs_info *prf = (prefs_info *)data;
prf->got_error = true;
gtk_label_set_text(GTK_LABEL(prf->label), msg);
TIMEOUT(unpost_color_error);
}
static void prefs_r_callback(GtkWidget *w, gpointer context)
{
prefs_info *prf = (prefs_info *)context;
char *str;
double r;
str = (char *)gtk_entry_get_text(GTK_ENTRY(w));
redirect_errors_to(errors_to_color_text, context);
r = (double)string_to_mus_float_t(str, 0.0, "red amount");
redirect_errors_to(NULL, NULL);
if (!(prf->got_error))
{
ADJUSTMENT_SET_VALUE(prf->radj, (double)mus_fclamp(0.0, r, 1.0));
reflect_color(prf);
}
}
static void prefs_g_callback(GtkWidget *w, gpointer context)
{
prefs_info *prf = (prefs_info *)context;
char *str;
double r;
str = (char *)gtk_entry_get_text(GTK_ENTRY(w));
redirect_errors_to(errors_to_color_text, context);
r = (double)string_to_mus_float_t(str, 0.0, "green amount");
redirect_errors_to(NULL, NULL);
if (!(prf->got_error))
{
ADJUSTMENT_SET_VALUE(prf->gadj, (double)mus_fclamp(0.0, r, 1.0));
reflect_color(prf);
}
}
static void prefs_b_callback(GtkWidget *w, gpointer context)
{
prefs_info *prf = (prefs_info *)context;
char *str;
double r;
str = (char *)gtk_entry_get_text(GTK_ENTRY(w));
redirect_errors_to(errors_to_color_text, context);
r = (double)string_to_mus_float_t(str, 0.0, "blue amount");
redirect_errors_to(NULL, NULL);
if (!(prf->got_error))
{
ADJUSTMENT_SET_VALUE(prf->badj, (double)mus_fclamp(0.0, r, 1.0));
reflect_color(prf);
}
}
static void prefs_call_color_func_callback(GtkWidget *w, gpointer context)
{
prefs_info *prf = (prefs_info *)context;
if ((prf) && (prf->color_func))
{
double r, g, b;
r = ADJUSTMENT_VALUE(prf->radj);
g = ADJUSTMENT_VALUE(prf->gadj);
b = ADJUSTMENT_VALUE(prf->badj);
(*(prf->color_func))(prf, r, g, b);
}
}
#if GTK_CHECK_VERSION(3, 92, 0)
static void drawer_expose(GtkDrawingArea *w, cairo_t *cr, int width, int height, gpointer data)
{
prefs_info *prf = (prefs_info *)data;
mus_float_t r, g, b;
r = ADJUSTMENT_VALUE(prf->radj);
g = ADJUSTMENT_VALUE(prf->gadj);
b = ADJUSTMENT_VALUE(prf->badj);
cairo_set_source_rgb(cr, r, g, b);
cairo_paint(cr);
}
#else
#if GTK_CHECK_VERSION(3, 0, 0)
static gboolean drawer_expose(GtkWidget *w, GdkEventExpose *ev, gpointer data)
{
prefs_info *prf = (prefs_info *)data;
mus_float_t r, g, b;
color_info *current_color;
r = ADJUSTMENT_VALUE(prf->radj);
g = ADJUSTMENT_VALUE(prf->gadj);
b = ADJUSTMENT_VALUE(prf->badj);
current_color = rgb_to_color(r, g, b);
display_color(prf->color, current_color);
return(false);
}
#endif
#endif
static prefs_info *prefs_color_selector_row(const char *label, const char *varname,
color_t current_pixel,
GtkWidget *box,
void (*color_func)(prefs_info *prf, double r, double g, double b))
{
prefs_info *prf;
GtkWidget *hb, *row, *row2, *sep3;
double r = 0.0, g = 0.0, b = 0.0;
prf = (prefs_info *)calloc(1, sizeof(prefs_info));
prf->var_name = varname;
pixel_to_rgb(current_pixel, &r, &g, &b);
/* first row */
row = make_basic_row(box);
prf->label = make_row_label(prf, label, row);
hb = gtk_hbox_new(false, 0);
gtk_size_group_add_widget(widgets_group, hb);
sg_box_pack_start(GTK_BOX(row), hb, false, false, 0);
gtk_widget_show(hb);
make_row_middle_separator(hb);
{
GtkWidget *frame;
frame = gtk_frame_new(NULL);
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
prf->color_texts = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
sg_box_pack_start(GTK_BOX(hb), frame, false, false, 4);
gtk_size_group_add_widget(prf->color_texts, frame);
prf->color = gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER(frame), prf->color);
#if GTK_CHECK_VERSION(3, 92, 0)
gtk_drawing_area_set_content_width(GTK_DRAWING_AREA(prf->color), widget_width(prf->color));
gtk_drawing_area_set_content_height(GTK_DRAWING_AREA(prf->color), widget_height(prf->color));
gtk_drawing_area_set_draw_func(GTK_DRAWING_AREA(prf->color), drawer_expose, prf, NULL);
#else
#if GTK_CHECK_VERSION(3, 0, 0)
SG_SIGNAL_CONNECT(prf->color, DRAW_SIGNAL, drawer_expose, prf);
gtk_widget_set_hexpand(GTK_WIDGET(prf->color), true);
gtk_widget_set_vexpand(GTK_WIDGET(prf->color), true);
#else
widget_modify_bg(prf->color, GTK_STATE_NORMAL, current_pixel);
#endif
#endif
gtk_widget_show(prf->color);
gtk_widget_show(frame);
}
make_row_inner_separator(8, hb);
prf->rtxt = make_row_text(prf, NULL, 6, hb);
gtk_size_group_add_widget(prf->color_texts, prf->rtxt);
float_to_textfield(prf->rtxt, r);
prf->gtxt = make_row_text(prf, NULL, 6, hb);
gtk_size_group_add_widget(prf->color_texts, prf->gtxt);
float_to_textfield(prf->gtxt, g);
prf->btxt = make_row_text(prf, NULL, 6, hb);
gtk_size_group_add_widget(prf->color_texts, prf->btxt);
float_to_textfield(prf->btxt, b);
/* second row */
row2 = gtk_hbox_new(false, 0);
sg_box_pack_start(GTK_BOX(box), row2, false, false, 0);
gtk_widget_show(row2);
make_row_inner_separator(20, row2);
prf->radj = (GtkAdjustment *)gtk_adjustment_new(r, 0.0, 1.01, 0.001, 0.01, .01);
prf->rscl = gtk_hscale_new(GTK_ADJUSTMENT(prf->radj));
gtk_widget_set_name(prf->rscl, "prefs_color_scale");
sg_box_pack_start(GTK_BOX(row2), prf->rscl, true, true, 4);
#if (!GTK_CHECK_VERSION(3, 0, 0))
widget_modify_bg(prf->rscl, GTK_STATE_NORMAL, rscl_color); /* this is the slider except when clicked */
widget_modify_bg(prf->rscl, GTK_STATE_PRELIGHT, rscl_color); /* this is the slider when clicked */
#else
add_red_scale_style(prf->rscl);
#endif
gtk_widget_show(prf->rscl);
gtk_range_set_update_policy(GTK_RANGE(GTK_SCALE(prf->rscl)), GTK_UPDATE_CONTINUOUS);
gtk_scale_set_draw_value(GTK_SCALE(prf->rscl), false);
prf->gadj = (GtkAdjustment *)gtk_adjustment_new(g, 0.0, 1.01, 0.001, 0.01, .01);
prf->gscl = gtk_hscale_new(GTK_ADJUSTMENT(prf->gadj));
gtk_widget_set_name(prf->gscl, "prefs_color_scale");
sg_box_pack_start(GTK_BOX(row2), prf->gscl, true, true, 4);
#if (!GTK_CHECK_VERSION(3, 0, 0))
widget_modify_bg(prf->gscl, GTK_STATE_NORMAL, gscl_color);
widget_modify_bg(prf->gscl, GTK_STATE_PRELIGHT, gscl_color);
#else
add_green_scale_style(prf->gscl);
#endif
gtk_widget_show(prf->gscl);
gtk_range_set_update_policy(GTK_RANGE(GTK_SCALE(prf->gscl)), GTK_UPDATE_CONTINUOUS);
gtk_scale_set_draw_value(GTK_SCALE(prf->gscl), false);
prf->badj = (GtkAdjustment *)gtk_adjustment_new(b, 0.0, 1.01, 0.001, 0.01, .01);
prf->bscl = gtk_hscale_new(GTK_ADJUSTMENT(prf->badj));
gtk_widget_set_name(prf->bscl, "prefs_color_scale");
sg_box_pack_start(GTK_BOX(row2), prf->bscl, true, true, 4);
#if (!GTK_CHECK_VERSION(3, 0, 0))
widget_modify_bg(prf->bscl, GTK_STATE_NORMAL, bscl_color);
widget_modify_bg(prf->bscl, GTK_STATE_PRELIGHT, bscl_color);
#else
add_blue_scale_style(prf->bscl);
#endif
gtk_widget_show(prf->bscl);
gtk_range_set_update_policy(GTK_RANGE(GTK_SCALE(prf->bscl)), GTK_UPDATE_CONTINUOUS);
gtk_scale_set_draw_value(GTK_SCALE(prf->bscl), false);
sep3 = gtk_hseparator_new();
sg_box_pack_end(GTK_BOX(row2), sep3, false, false, 20);
gtk_widget_show(sep3);
SG_SIGNAL_CONNECT(prf->rtxt, "activate", prefs_r_callback, (gpointer)prf);
SG_SIGNAL_CONNECT(prf->gtxt, "activate", prefs_g_callback, (gpointer)prf);
SG_SIGNAL_CONNECT(prf->btxt, "activate", prefs_b_callback, (gpointer)prf);
SG_SIGNAL_CONNECT(prf->radj, "value_changed", prefs_call_color_func_callback, (gpointer)prf);
SG_SIGNAL_CONNECT(prf->gadj, "value_changed", prefs_call_color_func_callback, (gpointer)prf);
SG_SIGNAL_CONNECT(prf->badj, "value_changed", prefs_call_color_func_callback, (gpointer)prf);
SG_SIGNAL_CONNECT(prf->radj, "value_changed", prefs_change_callback, NULL);
SG_SIGNAL_CONNECT(prf->gadj, "value_changed", prefs_change_callback, NULL);
SG_SIGNAL_CONNECT(prf->badj, "value_changed", prefs_change_callback, NULL);
SG_SIGNAL_CONNECT(prf->radj, "value_changed", prefs_color_callback, (gpointer)prf);
SG_SIGNAL_CONNECT(prf->gadj, "value_changed", prefs_color_callback, (gpointer)prf);
SG_SIGNAL_CONNECT(prf->badj, "value_changed", prefs_color_callback, (gpointer)prf);
prf->color_func = color_func;
return(prf);
}
/* ---------------- topic separator ---------------- */
static void make_inter_topic_separator(GtkWidget *topics)
{
GtkWidget *w;
w = gtk_hseparator_new();
sg_box_pack_start(GTK_BOX(topics), w, false, false, 0);
gtk_widget_show(w);
/* height = INTER_TOPIC_SPACE no line */
}
/* ---------------- variable separator ---------------- */
static void make_inter_variable_separator(GtkWidget *topics)
{
GtkWidget *w;
w = gtk_hseparator_new();
sg_box_pack_start(GTK_BOX(topics), w, false, false, 0);
gtk_widget_show(w);
/* height = INTER_VARIABLE_SPACE no line */
}
/* ---------------- top-level contents label ---------------- */
static void make_top_level_label(const char *label, GtkWidget *parent)
{
GtkWidget *w1, *w2, *w3;
char *str;
w1 = gtk_vseparator_new();
sg_box_pack_start(GTK_BOX(parent), w1, false, false, 6);
gtk_widget_show(w1);
str = mus_format("%s", label);
#if (!GTK_CHECK_VERSION(3, 0, 0))
w2 = gtk_label_new(label);
gtk_label_set_markup(GTK_LABEL(w2), str);
gtk_label_set_use_markup(GTK_LABEL(w2), true);
gtk_misc_set_alignment(GTK_MISC(w2), 0.01, 0.5);
#else
w2 = gtk_button_new_with_label(label);
add_highlight_button_style(w2);
gtk_label_set_markup(GTK_LABEL(BIN_CHILD(w2)), str);
gtk_label_set_use_markup(GTK_LABEL(BIN_CHILD(w2)), true);
#if GTK_CHECK_VERSION(3, 14, 0)
gtk_widget_set_halign(GTK_WIDGET(w2), GTK_ALIGN_START);
#else
gtk_misc_set_alignment(GTK_MISC(BIN_CHILD(w2)), 0.01, 0.5);
#endif
#endif
free(str);
sg_box_pack_start(GTK_BOX(parent), w2, false, false, 0);
gtk_widget_show(w2);
w3 = gtk_vseparator_new();
sg_box_pack_start(GTK_BOX(parent), w3, false, false, 6);
gtk_widget_show(w3);
make_inter_variable_separator(parent);
}
static GtkWidget *make_top_level_box(GtkWidget *topics)
{
GtkWidget *w, *frame;
frame = gtk_frame_new(NULL);
sg_box_pack_start(GTK_BOX(topics), frame, true, true, 0);
gtk_widget_show(frame);
w = gtk_vbox_new(false, 2);
gtk_container_add(GTK_CONTAINER(frame), w);
gtk_widget_show(w);
return(w);
}
static void make_inner_label(const char *label, GtkWidget *parent)
{
GtkWidget *w, *w1, *w2;
char *str;
w1 = gtk_vseparator_new();
sg_box_pack_start(GTK_BOX(parent), w1, false, false, 4);
gtk_widget_show(w1);
str = mus_format("%s", label);
#if (!GTK_CHECK_VERSION(3, 0, 0))
w = gtk_label_new(label);
gtk_label_set_markup(GTK_LABEL(w), str);
gtk_label_set_use_markup(GTK_LABEL(w), true);
gtk_misc_set_alignment(GTK_MISC(w), 0.0, 0.5);
#else
w = gtk_button_new_with_label(label);
add_highlight_button_style(w);
gtk_label_set_markup(GTK_LABEL(BIN_CHILD(w)), str);
gtk_label_set_use_markup(GTK_LABEL(BIN_CHILD(w)), true);
#if GTK_CHECK_VERSION(3, 14, 0)
gtk_widget_set_halign(GTK_WIDGET(w), GTK_ALIGN_START);
#else
gtk_misc_set_alignment(GTK_MISC(BIN_CHILD(w)), 0.0, 0.5);
#endif
#endif
free(str);
sg_box_pack_start(GTK_BOX(parent), w, false, false, 0);
gtk_widget_show(w);
w2 = gtk_vseparator_new();
sg_box_pack_start(GTK_BOX(parent), w2, false, false, 4);
gtk_widget_show(w2);
make_inter_variable_separator(parent);
}
/* ---------------- base buttons ---------------- */
static gint preferences_delete_callback(GtkWidget *w, GdkEvent *event, gpointer context)
{
clear_prefs_dialog_error();
gtk_widget_hide(preferences_dialog);
return(true);
}
static void preferences_dismiss_callback(GtkWidget *w, gpointer context)
{
clear_prefs_dialog_error();
gtk_widget_hide(preferences_dialog);
}
static void preferences_help_callback(GtkWidget *w, gpointer context)
{
snd_help("preferences",
"This dialog sets various global variables. 'Save' then writes the new values \
to ~/.snd_prefs_ruby|forth|s7 so that they take effect the next time you start Snd. 'Revert' resets each variable either to \
its value when the Preferences dialog was started, or to the last saved value. 'Clear' resets each variable to its default value (its \
value when Snd starts, before loading initialization files). 'Help' starts this dialog, and as long as it's active, it will post helpful \
information if the mouse lingers over some variable -- sort of a tooltip that stays out of your way. \
You can also request help on a given topic by clicking the variable name on the far right.",
WITH_WORD_WRAP);
}
static void prefs_set_dialog_title(const char *filename)
{
char *str;
if (filename)
{
if (prefs_saved_filename) free(prefs_saved_filename);
prefs_saved_filename = mus_strdup(filename);
}
if (prefs_saved_filename)
str = mus_format("Preferences%s (saved in %s)\n",
(prefs_unsaved) ? "*" : "",
prefs_saved_filename);
else str = mus_format("Preferences%s",
(prefs_unsaved) ? "*" : "");
gtk_window_set_title(GTK_WINDOW(preferences_dialog), str);
free(str);
}
static void preferences_revert_callback(GtkWidget *w, gpointer context)
{
preferences_revert_or_clear(true);
}
static void preferences_clear_callback(GtkWidget *w, gpointer context)
{
preferences_revert_or_clear(false);
}
#if HAVE_EXTENSION_LANGUAGE
static void preferences_save_callback(GtkWidget *w, gpointer context)
{
clear_prefs_dialog_error();
redirect_snd_error_to(post_prefs_dialog_error, NULL);
redirect_snd_warning_to(post_prefs_dialog_error, NULL);
save_prefs();
redirect_snd_error_to(NULL, NULL);
redirect_snd_warning_to(NULL, NULL);
}
#endif
/* ---------------- errors ---------------- */
static void clear_prefs_error(GtkWidget *w, gpointer context)
{
prefs_info *prf = (prefs_info *)context;
g_signal_handler_disconnect(prf->text, prf->erase_id);
prf->erase_id = 0;
set_label(prf->error, "");
}
static void post_prefs_error(const char *msg, prefs_info *prf)
{
prf->got_error = true;
set_label(prf->error, msg);
if (prf->erase_id != 0)
g_signal_handler_disconnect(prf->text, prf->erase_id);
prf->erase_id = SG_SIGNAL_CONNECT(prf->text, "changed", clear_prefs_error, (gpointer)prf);
}
static void va_post_prefs_error(const char *msg, prefs_info *data, ...)
{
char *buf;
va_list ap;
va_start(ap, data);
buf = vstr(msg, ap);
va_end(ap);
post_prefs_error(buf, data);
free(buf);
}
/* ---------------- preferences dialog ---------------- */
widget_t make_preferences_dialog(void)
{
GtkWidget *save_button, *revert_button, *clear_button, *help_button, *dismiss_button, *topics, *scroller;
prefs_info *prf;
char *str;
if (preferences_dialog)
{
gtk_widget_show(preferences_dialog);
return(preferences_dialog);
}
preferences_dialog = snd_gtk_dialog_new();
#if GTK_CHECK_VERSION(3, 14, 0)
gtk_window_set_transient_for(GTK_WINDOW(preferences_dialog), GTK_WINDOW(main_shell(ss)));
#endif
gtk_window_set_title(GTK_WINDOW(preferences_dialog), "Preferences");
sg_make_resizable(preferences_dialog);
/* sg_container_set_border_width (GTK_CONTAINER(preferences_dialog), 10); */
gtk_widget_realize(preferences_dialog);
#if (!GTK_CHECK_VERSION(3, 22, 0))
if ((STARTUP_WIDTH < gdk_screen_width()) &&
(STARTUP_HEIGHT < gdk_screen_height()))
#endif
gtk_window_resize(GTK_WINDOW(preferences_dialog), STARTUP_WIDTH, STARTUP_HEIGHT);
help_button = gtk_dialog_add_button(GTK_DIALOG(preferences_dialog), "Help", GTK_RESPONSE_NONE);
revert_button = gtk_dialog_add_button(GTK_DIALOG(preferences_dialog), "Revert", GTK_RESPONSE_NONE);
clear_button = gtk_dialog_add_button(GTK_DIALOG(preferences_dialog), "Clear", GTK_RESPONSE_NONE);
dismiss_button = gtk_dialog_add_button(GTK_DIALOG(preferences_dialog), "Go away", GTK_RESPONSE_NONE);
#if HAVE_EXTENSION_LANGUAGE
save_button = gtk_dialog_add_button(GTK_DIALOG(preferences_dialog), "Save", GTK_RESPONSE_NONE);
gtk_widget_set_name(save_button, "dialog_button");
#endif
gtk_widget_set_name(help_button, "dialog_button");
gtk_widget_set_name(revert_button, "dialog_button");
gtk_widget_set_name(clear_button, "dialog_button");
gtk_widget_set_name(dismiss_button, "dialog_button");
#if GTK_CHECK_VERSION(3, 0, 0)
add_highlight_button_style(dismiss_button);
add_highlight_button_style(revert_button);
add_highlight_button_style(clear_button);
#if HAVE_EXTENSION_LANGUAGE
add_highlight_button_style(save_button);
#endif
add_highlight_button_style(help_button);
#endif
SG_SIGNAL_CONNECT(preferences_dialog, "delete_event", preferences_delete_callback, NULL);
SG_SIGNAL_CONNECT(dismiss_button, "clicked", preferences_dismiss_callback, NULL);
SG_SIGNAL_CONNECT(revert_button, "clicked", preferences_revert_callback, NULL);
SG_SIGNAL_CONNECT(clear_button, "clicked", preferences_clear_callback, NULL);
#if HAVE_EXTENSION_LANGUAGE
SG_SIGNAL_CONNECT(save_button, "clicked", preferences_save_callback, NULL);
#endif
SG_SIGNAL_CONNECT(help_button, "clicked", preferences_help_callback, NULL);
gtk_widget_show(dismiss_button);
#if HAVE_EXTENSION_LANGUAGE
gtk_widget_show(save_button);
#endif
gtk_widget_show(revert_button);
gtk_widget_show(clear_button);
gtk_widget_show(help_button);
topics = gtk_vbox_new(false, 0);
scroller = gtk_scrolled_window_new(NULL, NULL);
sg_box_pack_start(GTK_BOX(DIALOG_CONTENT_AREA(preferences_dialog)), scroller, true, true, 0);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroller), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
#if HAVE_GTK_HEADER_BAR_NEW
gtk_container_add(GTK_CONTAINER(scroller), topics);
#else
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroller), topics);
#endif
gtk_widget_show(topics);
gtk_widget_show(scroller);
label_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
widgets_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
#if 0
/* these are really garish */
rscl_color = rgb_to_color(1.0, 0.0, 0.0);
gscl_color = rgb_to_color(0.0, 1.0, 0.0);
bscl_color = rgb_to_color(0.0, 0.0, 1.0);
#else
rscl_color = rgb_to_color(1.0, 0.4, 0.4);
gscl_color = rgb_to_color(0.56, 1.0, 0.56);
bscl_color = rgb_to_color(0.68, 0.84, 1.0);
#endif
/* ---------------- overall behavior ---------------- */
{
GtkWidget *dpy_box;
char *str1, *str2;
/* ---------------- overall behavior ----------------*/
dpy_box = make_top_level_box(topics);
make_top_level_label("overall behavior choices", dpy_box);
str1 = mus_format("%d", ss->init_window_width);
str2 = mus_format("%d", ss->init_window_height);
rts_init_window_width = ss->init_window_width;
rts_init_window_height = ss->init_window_height;
prf = prefs_row_with_two_texts("start up size", S_window_width,
"width:", str1, "height:", str2, 6,
dpy_box,
startup_size_text);
remember_pref(prf, reflect_init_window_size, save_init_window_size, help_init_window_size, clear_init_window_size, revert_init_window_size);
free(str2);
free(str1);
make_inter_variable_separator(dpy_box);
prf = prefs_row_with_toggle("ask before overwriting anything", S_ask_before_overwrite,
rts_ask_before_overwrite = ask_before_overwrite(ss),
dpy_box,
overwrite_toggle);
remember_pref(prf, reflect_ask_before_overwrite, save_ask_before_overwrite, help_ask_before_overwrite, NULL, revert_ask_before_overwrite);
make_inter_variable_separator(dpy_box);
prf = prefs_row_with_toggle("ask about unsaved edits before exiting", S_ask_about_unsaved_edits,
rts_unsaved_edits = ask_about_unsaved_edits(ss),
dpy_box,
unsaved_edits_toggle);
remember_pref(prf, reflect_unsaved_edits, save_unsaved_edits, help_unsaved_edits, clear_unsaved_edits, revert_unsaved_edits);
make_inter_variable_separator(dpy_box);
prf = prefs_row_with_toggle("include thumbnail graph in upper right corner", S_with_inset_graph,
rts_with_inset_graph = with_inset_graph(ss),
dpy_box,
with_inset_graph_toggle);
remember_pref(prf, reflect_with_inset_graph, save_with_inset_graph, help_inset_graph,
clear_with_inset_graph, revert_with_inset_graph);
make_inter_variable_separator(dpy_box);
prf = prefs_row_with_toggle("resize main window as sounds open and close", S_auto_resize,
rts_auto_resize = auto_resize(ss),
dpy_box,
resize_toggle);
remember_pref(prf, reflect_auto_resize, save_auto_resize, help_auto_resize, NULL, revert_auto_resize);
make_inter_variable_separator(dpy_box);
prf = prefs_row_with_toggle("pointer focus", S_with_pointer_focus,
rts_with_pointer_focus = with_pointer_focus(ss),
dpy_box,
with_pointer_focus_toggle);
remember_pref(prf, reflect_with_pointer_focus, save_with_pointer_focus, help_pointer_focus,
clear_with_pointer_focus, revert_with_pointer_focus);
make_inter_variable_separator(dpy_box);
rts_sync_style = sync_style(ss);
prf = prefs_row_with_two_toggles("operate on all channels together", S_sync,
"within each sound", rts_sync_style == SYNC_BY_SOUND,
"across all sounds", rts_sync_style == SYNC_ALL,
dpy_box,
sync1_choice, sync2_choice);
remember_pref(prf, reflect_sync_style, save_sync_style, help_sync_style, clear_sync_style, revert_sync_style);
make_inter_variable_separator(dpy_box);
rts_remember_sound_state = remember_sound_state(ss);
prf = prefs_row_with_toggle("restore a sound's state if reopened later", S_remember_sound_state,
rts_remember_sound_state,
dpy_box,
toggle_remember_sound_state);
remember_pref(prf, reflect_remember_sound_state, save_remember_sound_state, help_remember_sound_state,
clear_remember_sound_state, revert_remember_sound_state);
make_inter_variable_separator(dpy_box);
prf = prefs_row_with_toggle("show the control panel upon opening a sound", S_show_controls,
rts_show_controls = in_show_controls(ss),
dpy_box,
controls_toggle);
remember_pref(prf, reflect_show_controls, save_show_controls, help_show_controls, NULL, revert_show_controls);
make_inter_variable_separator(dpy_box);
include_peak_env_directory = mus_strdup(peak_env_dir(ss));
rts_peak_env_directory = mus_strdup(include_peak_env_directory);
include_peak_envs = find_peak_envs();
rts_peak_envs = include_peak_envs;
prf = prefs_row_with_toggle_with_text("save peak envs to speed up initial display", S_peak_env_dir,
include_peak_envs,
"directory:", include_peak_env_directory, 25,
dpy_box,
peak_envs_toggle, peak_envs_text);
remember_pref(prf, reflect_peak_envs, save_peak_envs, help_peak_envs, clear_peak_envs, revert_peak_envs);
make_inter_variable_separator(dpy_box);
str = mus_format("%d", rts_max_regions = max_regions(ss));
prf = prefs_row_with_toggle_with_text("selection creates an associated region", S_selection_creates_region,
rts_selection_creates_region = selection_creates_region(ss),
"max regions:", str, 5,
dpy_box,
selection_creates_region_toggle, max_regions_text);
remember_pref(prf, reflect_selection_creates_region, save_selection_creates_region, help_selection_creates_region, NULL, revert_selection_creates_region);
free(str);
make_inter_variable_separator(dpy_box);
rts_with_toolbar = with_toolbar(ss);
prf = prefs_row_with_toggle("include a toolbar", S_with_toolbar,
rts_with_toolbar,
dpy_box,
toggle_with_toolbar);
remember_pref(prf, reflect_with_toolbar, save_with_toolbar, help_with_toolbar, clear_with_toolbar, revert_with_toolbar);
make_inter_variable_separator(dpy_box);
rts_with_tooltips = with_tooltips(ss);
prf = prefs_row_with_toggle("enable tooltips", S_with_tooltips,
rts_with_tooltips,
dpy_box,
toggle_with_tooltips);
remember_pref(prf, reflect_with_tooltips, save_with_tooltips, help_with_tooltips, clear_with_tooltips, revert_with_tooltips);
make_inter_variable_separator(dpy_box);
rts_with_menu_icons = with_menu_icons(ss);
prf = prefs_row_with_toggle("enable menu icons (gtk only)", S_with_menu_icons,
rts_with_menu_icons,
dpy_box,
toggle_with_menu_icons);
remember_pref(prf, reflect_with_menu_icons, save_with_menu_icons, help_with_menu_icons, clear_with_menu_icons, revert_with_menu_icons);
/* ---------------- file options ---------------- */
make_inter_variable_separator(dpy_box);
make_inner_label(" file options", dpy_box);
rts_load_path = find_sources();
prf = prefs_row_with_text("directory containing Snd's " Xen_language " files", "load path",
rts_load_path,
dpy_box,
load_path_text);
remember_pref(prf, reflect_load_path, NULL, help_load_path, clear_load_path, revert_load_path);
load_path_text_widget = prf->text;
make_inter_variable_separator(dpy_box);
prf = prefs_row_with_toggle("display only sound files in various file lists", S_just_sounds,
rts_just_sounds = just_sounds(ss),
dpy_box,
just_sounds_toggle);
remember_pref(prf, prefs_reflect_just_sounds, save_just_sounds, help_just_sounds, NULL, revert_just_sounds);
make_inter_variable_separator(dpy_box);
rts_temp_dir = mus_strdup(temp_dir(ss));
prf = prefs_row_with_text("directory for temporary files", S_temp_dir,
temp_dir(ss),
dpy_box,
temp_dir_text);
remember_pref(prf, reflect_temp_dir, save_temp_dir, help_temp_dir, NULL, revert_temp_dir);
make_inter_variable_separator(dpy_box);
rts_save_dir = mus_strdup(save_dir(ss));
prf = prefs_row_with_text("directory for save-state files", S_save_dir,
save_dir(ss),
dpy_box,
save_dir_text);
remember_pref(prf, reflect_save_dir, save_save_dir, help_save_dir, NULL, revert_save_dir);
make_inter_variable_separator(dpy_box);
rts_save_state_file = mus_strdup(save_state_file(ss));
prf = prefs_row_with_text("default save-state filename", S_save_state_file,
save_state_file(ss),
dpy_box,
save_state_file_text);
remember_pref(prf, reflect_save_state_file, save_save_state_file, help_save_state_file, NULL, revert_save_state_file);
#if HAVE_LADSPA
make_inter_variable_separator(dpy_box);
rts_ladspa_dir = mus_strdup(ladspa_dir(ss));
prf = prefs_row_with_text("directory for ladspa plugins", S_ladspa_dir,
ladspa_dir(ss),
dpy_box,
ladspa_dir_text);
remember_pref(prf, reflect_ladspa_dir, save_ladspa_dir, help_ladspa_dir, NULL, revert_ladspa_dir);
#endif
make_inter_variable_separator(dpy_box);
rts_html_program = mus_strdup(html_program(ss));
prf = prefs_row_with_text("external program to read HTML files via snd-help", S_html_program,
html_program(ss),
dpy_box,
html_program_text);
remember_pref(prf, reflect_html_program, save_html_program, help_html_program, NULL, revert_html_program);
make_inter_variable_separator(dpy_box);
rts_default_output_chans = default_output_chans(ss);
prf = prefs_row_with_radio_box("default new sound attributes: chans", S_default_output_chans,
output_chan_choices, NUM_OUTPUT_CHAN_CHOICES, -1,
dpy_box,
default_output_chans_choice);
remember_pref(prf, reflect_default_output_chans, save_default_output_chans, help_default_output_chans, NULL, revert_default_output_chans);
reflect_default_output_chans(prf);
rts_default_output_srate = default_output_srate(ss);
prf = prefs_row_with_radio_box("srate", S_default_output_srate,
output_srate_choices, NUM_OUTPUT_SRATE_CHOICES, -1,
dpy_box,
default_output_srate_choice);
remember_pref(prf, reflect_default_output_srate, save_default_output_srate, help_default_output_srate, NULL, revert_default_output_srate);
reflect_default_output_srate(prf);
rts_default_output_header_type = default_output_header_type(ss);
prf = prefs_row_with_radio_box("header type", S_default_output_header_type,
output_header_type_choices, NUM_OUTPUT_HEADER_TYPE_CHOICES, -1,
dpy_box,
default_output_header_type_choice);
output_header_type_prf = prf;
remember_pref(prf, reflect_default_output_header_type, save_default_output_header_type, help_default_output_header_type, NULL, revert_default_output_header_type);
rts_default_output_sample_type = default_output_sample_type(ss);
prf = prefs_row_with_radio_box("sample type", S_default_output_sample_type,
output_sample_type_choices, NUM_OUTPUT_SAMPLE_TYPE_CHOICES, -1,
dpy_box,
default_output_sample_type_choice);
output_sample_type_prf = prf;
remember_pref(prf, reflect_default_output_sample_type, save_default_output_sample_type, help_default_output_sample_type, NULL, revert_default_output_sample_type);
reflect_default_output_header_type(output_header_type_prf);
reflect_default_output_sample_type(output_sample_type_prf);
make_inter_variable_separator(dpy_box);
{
int i, srate = 0, chans = 0;
mus_sample_t samp_type = MUS_UNKNOWN_SAMPLE;
mus_header_raw_defaults(&srate, &chans, &samp_type);
str = mus_format("%d", chans);
str1 = mus_format("%d", srate);
rts_raw_chans = chans;
rts_raw_srate = srate;
rts_raw_sample_type = samp_type;
raw_sample_type_choices = (char **)calloc(MUS_NUM_SAMPLES - 1, sizeof(char *));
for (i = 1; i < MUS_NUM_SAMPLES; i++)
raw_sample_type_choices[i - 1] = raw_sample_type_to_string((mus_sample_t)i); /* skip MUS_UNKNOWN_SAMPLE = 0 */
prf = prefs_row_with_text("default raw sound attributes: chans", S_mus_header_raw_defaults, str,
dpy_box,
raw_chans_choice);
remember_pref(prf, reflect_raw_chans, save_raw_chans, help_raw_chans, NULL, revert_raw_chans);
prf = prefs_row_with_text("srate", S_mus_header_raw_defaults, str1,
dpy_box,
raw_srate_choice);
remember_pref(prf, reflect_raw_srate, save_raw_srate, help_raw_srate, NULL, revert_raw_srate);
free(str);
free(str1);
prf = prefs_row_with_list("sample type", S_mus_header_raw_defaults, raw_sample_type_choices[samp_type - 1],
(const char **)raw_sample_type_choices, MUS_NUM_SAMPLES - 1,
dpy_box,
raw_sample_type_from_text,
NULL, NULL);
remember_pref(prf, reflect_raw_sample_type, save_raw_sample_type, help_raw_sample_type, NULL, revert_raw_sample_type);
}
make_inter_variable_separator(dpy_box);
/* ---------------- additional keys ---------------- */
{
key_info *ki;
make_inner_label(" additional keys", dpy_box);
ki = find_prefs_key("play-from-cursor");
prf = prefs_row_with_text_and_three_toggles("play all chans from cursor", S_play,
"key:", 8, "ctrl:", "meta:", "C-x:",
ki->key, ki->c, ki->m, ki->x,
dpy_box,
bind_play_from_cursor);
remember_pref(prf, reflect_play_from_cursor, save_pfc, help_play_from_cursor, clear_play_from_cursor, NULL);
free(ki);
make_inter_variable_separator(dpy_box);
ki = find_prefs_key("show-all");
prf = prefs_row_with_text_and_three_toggles("show entire sound", S_x_bounds,
"key:", 8, "ctrl:", "meta:", "C-x:",
ki->key, ki->c, ki->m, ki->x,
dpy_box,
bind_show_all);
remember_pref(prf, reflect_show_all, save_show_all, help_show_all, clear_show_all, NULL);
free(ki);
make_inter_variable_separator(dpy_box);
ki = find_prefs_key("select-all");
prf = prefs_row_with_text_and_three_toggles("select entire sound", S_select_all,
"key:", 8, "ctrl:", "meta:", "C-x:",
ki->key, ki->c, ki->m, ki->x,
dpy_box,
bind_select_all);
remember_pref(prf, reflect_select_all, save_select_all, help_select_all, clear_select_all, NULL);
free(ki);
make_inter_variable_separator(dpy_box);
ki = find_prefs_key("show-selection");
prf = prefs_row_with_text_and_three_toggles("show current selection", "show-selection",
"key:", 8, "ctrl:", "meta:", "C-x:",
ki->key, ki->c, ki->m, ki->x,
dpy_box,
bind_show_selection);
remember_pref(prf, reflect_show_selection, save_show_selection, help_show_selection, clear_show_selection, NULL);
free(ki);
make_inter_variable_separator(dpy_box);
ki = find_prefs_key("revert-sound");
prf = prefs_row_with_text_and_three_toggles("undo all edits (revert)", S_revert_sound,
"key:", 8, "ctrl:", "meta:", "C-x:",
ki->key, ki->c, ki->m, ki->x,
dpy_box,
bind_revert);
remember_pref(prf, reflect_revert, save_revert, help_revert, clear_revert_sound, NULL);
free(ki);
make_inter_variable_separator(dpy_box);
ki = find_prefs_key("exit");
prf = prefs_row_with_text_and_three_toggles("exit from Snd", S_exit,
"key:", 8, "ctrl:", "meta:", "C-x:",
ki->key, ki->c, ki->m, ki->x,
dpy_box,
bind_exit);
remember_pref(prf, reflect_exit, save_exit, help_exit, clear_exit, NULL);
free(ki);
make_inter_variable_separator(dpy_box);
ki = find_prefs_key("goto-maxamp");
prf = prefs_row_with_text_and_three_toggles("move cursor to channel's maximum sample", S_maxamp_position,
"key:", 8, "ctrl:", "meta:", "C-x:",
ki->key, ki->c, ki->m, ki->x,
dpy_box,
bind_goto_maxamp);
remember_pref(prf, reflect_goto_maxamp, save_goto_maxamp, help_goto_maxamp, clear_goto_maxamp, NULL);
free(ki);
}
/* ---------------- cursor options ---------------- */
make_inter_variable_separator(dpy_box);
make_inner_label(" cursor options", dpy_box);
prf = prefs_row_with_toggle("report cursor location as it moves", S_with_verbose_cursor,
rts_with_verbose_cursor = with_verbose_cursor(ss),
dpy_box,
with_verbose_cursor_toggle);
remember_pref(prf, reflect_with_verbose_cursor, save_with_verbose_cursor, help_with_verbose_cursor, NULL, revert_with_verbose_cursor);
make_inter_variable_separator(dpy_box);
{
char *str1;
str = mus_format("%.2f", rts_cursor_update_interval = cursor_update_interval(ss));
str1 = mus_format("%d", rts_cursor_location_offset = cursor_location_offset(ss));
prf = prefs_row_with_toggle_with_two_texts("track current location while playing", S_with_tracking_cursor,
(rts_with_tracking_cursor = with_tracking_cursor(ss)),
"update:", str,
"offset:", str1, 8,
dpy_box,
with_tracking_cursor_toggle,
cursor_location_text);
remember_pref(prf, reflect_with_tracking_cursor, save_with_tracking_cursor, help_with_tracking_cursor, NULL, revert_with_tracking_cursor);
free(str);
free(str1);
}
make_inter_variable_separator(dpy_box);
str = mus_format("%d", rts_cursor_size = cursor_size(ss));
prf = prefs_row_with_number("size", S_cursor_size,
str, 4,
dpy_box,
cursor_size_up, cursor_size_down, cursor_size_from_text);
remember_pref(prf, reflect_cursor_size, save_cursor_size, help_cursor_size, NULL, revert_cursor_size);
free(str);
if (cursor_size(ss) <= 0) gtk_widget_set_sensitive(prf->arrow_down, false);
make_inter_variable_separator(dpy_box);
prf = prefs_row_with_radio_box("shape", S_cursor_style,
cursor_styles, NUM_CURSOR_STYLES,
rts_cursor_style = cursor_style(ss),
dpy_box,
cursor_style_choice);
remember_pref(prf, reflect_cursor_style, save_cursor_style, help_cursor_style, NULL, revert_cursor_style);
make_inter_variable_separator(dpy_box);
prf = prefs_row_with_radio_box("tracking cursor shape", S_tracking_cursor_style,
cursor_styles, NUM_CURSOR_STYLES,
rts_tracking_cursor_style = tracking_cursor_style(ss),
dpy_box,
tracking_cursor_style_choice);
remember_pref(prf, reflect_tracking_cursor_style, save_tracking_cursor_style, help_tracking_cursor_style, NULL, revert_tracking_cursor_style);
make_inter_variable_separator(dpy_box);
saved_cursor_color = ss->cursor_color;
prf = prefs_color_selector_row("color", S_cursor_color, ss->cursor_color,
dpy_box,
cursor_color_func);
remember_pref(prf, NULL, save_cursor_color, help_cursor_color, clear_cursor_color, revert_cursor_color);
/* ---------------- (overall) colors ---------------- */
make_inter_variable_separator(dpy_box);
make_inner_label(" colors", dpy_box);
saved_basic_color = ss->basic_color;
prf = prefs_color_selector_row("main background color", S_basic_color, ss->basic_color,
dpy_box,
basic_color_func);
remember_pref(prf, NULL, save_basic_color, help_basic_color, clear_basic_color, revert_basic_color);
make_inter_variable_separator(dpy_box);
saved_highlight_color = ss->highlight_color;
prf = prefs_color_selector_row("main highlight color", S_highlight_color, ss->highlight_color,
dpy_box,
highlight_color_func);
remember_pref(prf, NULL, save_highlight_color, help_highlight_color, clear_highlight_color, revert_highlight_color);
make_inter_variable_separator(dpy_box);
saved_position_color = ss->position_color;
prf = prefs_color_selector_row("second highlight color", S_position_color, ss->position_color,
dpy_box,
position_color_func);
remember_pref(prf, NULL, save_position_color, help_position_color, clear_position_color, revert_position_color);
make_inter_variable_separator(dpy_box);
saved_zoom_color = ss->zoom_color;
prf = prefs_color_selector_row("third highlight color", S_zoom_color, ss->zoom_color,
dpy_box,
zoom_color_func);
remember_pref(prf, NULL, save_zoom_color, help_zoom_color, clear_zoom_color, revert_zoom_color);
}
make_inter_topic_separator(topics);
/* -------- graphs -------- */
{
GtkWidget *grf_box;
/* ---------------- graph options ---------------- */
grf_box = make_top_level_box(topics);
make_top_level_label("graph options", grf_box);
prf = prefs_row_with_radio_box("how to connect the dots", S_graph_style,
graph_styles, NUM_GRAPH_STYLES,
rts_graph_style = graph_style(ss),
grf_box,
graph_style_choice);
remember_pref(prf, reflect_graph_style, save_graph_style, help_graph_style, NULL, revert_graph_style);
make_inter_variable_separator(grf_box);
str = mus_format("%d", rts_dot_size = dot_size(ss));
prf = prefs_row_with_number("dot size", S_dot_size,
str, 4,
grf_box,
dot_size_up, dot_size_down, dot_size_from_text);
remember_pref(prf, reflect_dot_size, save_dot_size, help_dot_size, NULL, revert_dot_size);
free(str);
if (dot_size(ss) <= 0) gtk_widget_set_sensitive(prf->arrow_down, false);
make_inter_variable_separator(grf_box);
rts_initial_beg = initial_beg(ss);
rts_initial_dur = initial_dur(ss);
str = mus_format("%.2f : %.2f", rts_initial_beg, rts_initial_dur);
prf = prefs_row_with_text_with_toggle("initial graph x bounds", S_initial_graph_hook,
(rts_full_duration = show_full_duration(ss)),
"show full duration", str, 16,
grf_box,
initial_bounds_toggle,
initial_bounds_text);
free(str);
remember_pref(prf, reflect_initial_bounds, save_initial_bounds, help_initial_bounds, clear_initial_bounds, revert_initial_bounds);
make_inter_variable_separator(grf_box);
prf = prefs_row_with_radio_box("how to layout multichannel graphs", S_channel_style,
channel_styles, NUM_CHANNEL_STYLES,
rts_channel_style = channel_style(ss),
grf_box,
channel_style_choice);
remember_pref(prf, reflect_channel_style, save_channel_style, help_channel_style, NULL, revert_channel_style);
make_inter_variable_separator(grf_box);
prf = prefs_row_with_toggle("layout wave and fft graphs horizontally", S_graphs_horizontal,
rts_graphs_horizontal = graphs_horizontal(ss),
grf_box,
graphs_horizontal_toggle);
remember_pref(prf, reflect_graphs_horizontal, save_graphs_horizontal, help_graphs_horizontal, NULL, revert_graphs_horizontal);
make_inter_variable_separator(grf_box);
prf = prefs_row_with_toggle("include y=0 line in sound graphs", S_show_y_zero,
rts_show_y_zero = show_y_zero(ss),
grf_box,
y_zero_toggle);
remember_pref(prf, reflect_show_y_zero, save_show_y_zero, help_show_y_zero, NULL, revert_show_y_zero);
make_inter_variable_separator(grf_box);
rts_show_grid = show_grid(ss);
prf = prefs_row_with_toggle("include a grid in sound graphs", S_show_grid,
rts_show_grid == WITH_GRID,
grf_box,
grid_toggle);
remember_pref(prf, reflect_show_grid, save_show_grid, help_show_grid, NULL, revert_show_grid);
make_inter_variable_separator(grf_box);
prf = prefs_row_with_scale("grid density", S_grid_density,
2.0, rts_grid_density = grid_density(ss),
grf_box,
grid_density_scale_callback, grid_density_text_callback);
remember_pref(prf, reflect_grid_density, save_grid_density, help_grid_density, NULL, revert_grid_density);
make_inter_variable_separator(grf_box);
rts_show_axes = show_axes(ss);
prf = prefs_row_with_list("what axes to display", S_show_axes, show_axes_choices[(int)rts_show_axes],
show_axes_choices, NUM_SHOW_AXES,
grf_box,
show_axes_from_text,
NULL, NULL);
remember_pref(prf, reflect_show_axes, save_show_axes, help_show_axes, clear_show_axes, revert_show_axes);
make_inter_variable_separator(grf_box);
rts_x_axis_style = x_axis_style(ss);
prf = prefs_row_with_list("time division", S_x_axis_style, x_axis_styles[(int)rts_x_axis_style],
x_axis_styles, NUM_X_AXIS_STYLES,
grf_box,
x_axis_style_from_text,
NULL, NULL);
remember_pref(prf, reflect_x_axis_style, save_x_axis_style, help_x_axis_style, clear_x_axis_style, revert_x_axis_style);
make_inter_variable_separator(grf_box);
prf = prefs_row_with_toggle("include smpte info", "show-smpte-label",
rts_with_smpte_label = with_smpte_label(ss),
grf_box,
smpte_toggle);
remember_pref(prf, reflect_smpte, save_smpte, help_smpte, clear_smpte, revert_smpte);
/* ---------------- (graph) colors ---------------- */
make_inter_variable_separator(grf_box);
make_inner_label(" colors", grf_box);
saved_data_color = ss->data_color;
prf = prefs_color_selector_row("unselected data (waveform) color", S_data_color, ss->data_color,
grf_box,
data_color_func);
remember_pref(prf, NULL, save_data_color, help_data_color, clear_data_color, revert_data_color);
make_inter_variable_separator(grf_box);
saved_graph_color = ss->graph_color;
prf = prefs_color_selector_row("unselected graph (background) color", S_graph_color, ss->graph_color,
grf_box,
graph_color_func);
remember_pref(prf, NULL, save_graph_color, help_graph_color, clear_graph_color, revert_graph_color);
make_inter_variable_separator(grf_box);
saved_selected_data_color = ss->selected_data_color;
prf = prefs_color_selector_row("selected channel data (waveform) color", S_selected_data_color, ss->selected_data_color,
grf_box,
selected_data_color_func);
remember_pref(prf, NULL, save_selected_data_color, help_selected_data_color, clear_selected_data_color, revert_selected_data_color);
make_inter_variable_separator(grf_box);
saved_selected_graph_color = ss->selected_graph_color;
prf = prefs_color_selector_row("selected channel graph (background) color", S_selected_graph_color, ss->selected_graph_color,
grf_box,
selected_graph_color_func);
remember_pref(prf, NULL, save_selected_graph_color, help_selected_graph_color, clear_selected_graph_color, revert_selected_graph_color);
make_inter_variable_separator(grf_box);
saved_selection_color = ss->selection_color;
prf = prefs_color_selector_row("selection color", S_selection_color, ss->selection_color,
grf_box,
selection_color_func);
remember_pref(prf, NULL, save_selection_color, help_selection_color, clear_selection_color, revert_selection_color);
/* ---------------- (graph) fonts ---------------- */
make_inter_variable_separator(grf_box);
make_inner_label(" fonts", grf_box);
rts_axis_label_font = mus_strdup(axis_label_font(ss));
prf = prefs_row_with_text("axis label font", S_axis_label_font,
axis_label_font(ss),
grf_box,
axis_label_font_text);
remember_pref(prf, reflect_axis_label_font, save_axis_label_font, help_axis_label_font, clear_axis_label_font, revert_axis_label_font);
make_inter_variable_separator(grf_box);
rts_axis_numbers_font = mus_strdup(axis_numbers_font(ss));
prf = prefs_row_with_text("axis number font", S_axis_numbers_font,
axis_numbers_font(ss),
grf_box,
axis_numbers_font_text);
remember_pref(prf, reflect_axis_numbers_font, save_axis_numbers_font, help_axis_numbers_font, clear_axis_numbers_font, revert_axis_numbers_font);
make_inter_variable_separator(grf_box);
rts_peaks_font = mus_strdup(peaks_font(ss));
prf = prefs_row_with_text("fft peaks font", S_peaks_font,
peaks_font(ss),
grf_box,
peaks_font_text);
remember_pref(prf, reflect_peaks_font, save_peaks_font, help_peaks_font, clear_peaks_font, revert_peaks_font);
make_inter_variable_separator(grf_box);
rts_bold_peaks_font = mus_strdup(bold_peaks_font(ss));
prf = prefs_row_with_text("fft peaks bold font (for main peaks)", S_bold_peaks_font,
bold_peaks_font(ss),
grf_box,
bold_peaks_font_text);
remember_pref(prf, reflect_bold_peaks_font, save_bold_peaks_font, help_bold_peaks_font, clear_bold_peaks_font, revert_bold_peaks_font);
make_inter_variable_separator(grf_box);
rts_tiny_font = mus_strdup(tiny_font(ss));
prf = prefs_row_with_text("tiny font (for various annotations)", S_peaks_font,
tiny_font(ss),
grf_box,
tiny_font_text);
remember_pref(prf, reflect_tiny_font, save_tiny_font, help_tiny_font, clear_tiny_font, revert_tiny_font);
}
make_inter_topic_separator(topics);
/* -------- transform -------- */
{
GtkWidget *fft_box;
/* ---------------- transform options ---------------- */
fft_box = make_top_level_box(topics);
make_top_level_label("transform options", fft_box);
rts_fft_size = transform_size(ss);
str = mus_format("%" print_mus_long, rts_fft_size);
prf = prefs_row_with_number("size", S_transform_size,
str, 12,
fft_box,
fft_size_up, fft_size_down, fft_size_from_text);
remember_pref(prf, reflect_fft_size, save_fft_size, help_fft_size, NULL, revert_fft_size);
free(str);
if (transform_size(ss) <= 2) gtk_widget_set_sensitive(prf->arrow_down, false);
make_inter_variable_separator(fft_box);
prf = prefs_row_with_radio_box("transform graph choice", S_transform_graph_type,
transform_graph_types, NUM_TRANSFORM_GRAPH_TYPES,
rts_transform_graph_type = transform_graph_type(ss),
fft_box,
transform_graph_type_choice);
remember_pref(prf, reflect_transform_graph_type, save_transform_graph_type, help_transform_graph_type, NULL, revert_transform_graph_type);
make_inter_variable_separator(fft_box);
rts_transform_type = transform_type(ss);
prf = prefs_row_with_list("transform", S_transform_type, transform_types[rts_transform_type],
transform_types, NUM_BUILTIN_TRANSFORM_TYPES,
fft_box,
transform_type_from_text,
transform_type_completer, NULL);
remember_pref(prf, reflect_transform_type, save_transform_type, help_transform_type, clear_transform_type, revert_transform_type);
make_inter_variable_separator(fft_box);
rts_fft_window = fft_window(ss);
prf = prefs_row_with_list("data window", S_fft_window, mus_fft_window_name(rts_fft_window),
mus_fft_window_names(), MUS_NUM_FFT_WINDOWS,
fft_box,
fft_window_from_text,
fft_window_completer, NULL);
remember_pref(prf, reflect_fft_window, save_fft_window, help_fft_window, clear_fft_window, revert_fft_window);
make_inter_variable_separator(fft_box);
prf = prefs_row_with_scale("data window family parameter", S_fft_window_beta,
1.0, rts_fft_window_beta = fft_window_beta(ss),
fft_box,
fft_window_beta_scale_callback, fft_window_beta_text_callback);
remember_pref(prf, reflect_fft_window_beta, save_fft_window_beta, help_fft_window_beta, NULL, revert_fft_window_beta);
make_inter_variable_separator(fft_box);
str = mus_format("%d", rts_max_transform_peaks = max_transform_peaks(ss));
prf = prefs_row_with_toggle_with_text("show fft peak data", S_show_transform_peaks,
rts_show_transform_peaks = show_transform_peaks(ss),
"max peaks:", str, 5,
fft_box,
transform_peaks_toggle, max_peaks_text);
remember_pref(prf, reflect_transform_peaks, save_transform_peaks, help_transform_peaks, NULL, revert_transform_peaks);
free(str);
make_inter_variable_separator(fft_box);
{
const char **cmaps;
int i, len;
len = num_colormaps();
cmaps = (const char **)calloc(len, sizeof(const char *));
for (i = 0; i < len; i++)
cmaps[i] = (const char *)colormap_name(i);
rts_colormap = color_map(ss);
prf = prefs_row_with_list("sonogram colormap", S_colormap, cmaps[rts_colormap],
cmaps, len,
fft_box,
colormap_from_text,
colormap_completer, NULL);
remember_pref(prf, reflect_colormap, save_colormap, help_colormap, clear_colormap, revert_colormap);
free(cmaps);
}
make_inter_variable_separator(fft_box);
prf = prefs_row_with_toggle("y axis as log magnitude (dB)", S_fft_log_magnitude,
rts_fft_log_magnitude = fft_log_magnitude(ss),
fft_box,
log_magnitude_toggle);
remember_pref(prf, reflect_fft_log_magnitude, save_fft_log_magnitude, help_fft_log_magnitude, NULL, revert_fft_log_magnitude);
make_inter_variable_separator(fft_box);
str = mus_format("%.1f", rts_min_dB = min_dB(ss));
prf = prefs_row_with_text("minimum y-axis dB value", S_min_dB, str,
fft_box,
min_dB_text);
remember_pref(prf, reflect_min_dB, save_min_dB, help_min_dB, NULL, revert_min_dB);
free(str);
make_inter_variable_separator(fft_box);
prf = prefs_row_with_toggle("x axis as log freq", S_fft_log_frequency,
rts_fft_log_frequency = fft_log_frequency(ss),
fft_box,
log_frequency_toggle);
remember_pref(prf, reflect_fft_log_frequency, save_fft_log_frequency, help_fft_log_frequency, NULL, revert_fft_log_frequency);
make_inter_variable_separator(fft_box);
prf = prefs_row_with_radio_box("normalization", S_transform_normalization,
transform_normalizations, NUM_TRANSFORM_NORMALIZATIONS,
rts_transform_normalization = transform_normalization(ss),
fft_box,
transform_normalization_choice);
remember_pref(prf, reflect_transform_normalization, save_transform_normalization, help_transform_normalization, NULL, revert_transform_normalization);
}
make_inter_topic_separator(topics);
/* -------- marks, mixes, and regions -------- */
{
GtkWidget *mmr_box;
char *str1, *str2;
/* ---------------- marks and mixes ---------------- */
mmr_box = make_top_level_box(topics);
make_top_level_label("marks and mixes", mmr_box);
saved_mark_color = ss->mark_color;
prf = prefs_color_selector_row("mark and mix tag color", S_mark_color, ss->mark_color,
mmr_box,
mark_color_func);
remember_pref(prf, NULL, save_mark_color, help_mark_color, clear_mark_color, revert_mark_color);
make_inter_variable_separator(mmr_box);
str1 = mus_format("%d", rts_mark_tag_width = mark_tag_width(ss));
str2 = mus_format("%d", rts_mark_tag_height = mark_tag_height(ss));
prf = prefs_row_with_two_texts("mark tag size", S_mark_tag_width,
"width:", str1, "height:", str2, 4,
mmr_box,
mark_tag_size_text);
remember_pref(prf, reflect_mark_tag_size, save_mark_tag_size, help_mark_tag_size, NULL, revert_mark_tag_size);
free(str2);
free(str1);
make_inter_variable_separator(mmr_box);
str1 = mus_format("%d", rts_mix_tag_width = mix_tag_width(ss));
str2 = mus_format("%d", rts_mix_tag_height = mix_tag_height(ss));
prf = prefs_row_with_two_texts("mix tag size", S_mix_tag_width,
"width:", str1, "height:", str2, 4,
mmr_box,
mix_tag_size_text);
remember_pref(prf, reflect_mix_tag_size, save_mix_tag_size, help_mix_tag_size, NULL, revert_mix_tag_size);
free(str2);
free(str1);
make_inter_variable_separator(mmr_box);
saved_mix_color = ss->mix_color;
prf = prefs_color_selector_row("mix waveform color", S_mix_color, ss->mix_color,
mmr_box,
mix_color_func);
remember_pref(prf, NULL, save_mix_color, help_mix_color, clear_mix_color, revert_mix_color);
make_inter_variable_separator(mmr_box);
str = mus_format("%d", rts_mix_waveform_height = mix_waveform_height(ss));
prf = prefs_row_with_toggle_with_text("show mix waveforms (attached to the mix tag)", S_show_mix_waveforms,
rts_show_mix_waveforms = show_mix_waveforms(ss),
"max waveform height:", str, 5,
mmr_box,
show_mix_waveforms_toggle, mix_waveform_height_text);
remember_pref(prf, reflect_mix_waveforms, save_mix_waveforms, help_mix_waveforms, NULL, revert_mix_waveforms);
free(str);
}
make_inter_topic_separator(topics);
/* -------- clm -------- */
{
GtkWidget *clm_box;
/* ---------------- clm options ---------------- */
clm_box = make_top_level_box(topics);
make_top_level_label("clm", clm_box);
str = mus_format("%d", rts_speed_control_tones = speed_control_tones(ss));
rts_speed_control_style = speed_control_style(ss);
prf = prefs_row_with_radio_box_and_number("speed control choice", S_speed_control_style,
speed_control_styles, NUM_SPEED_CONTROL_STYLES, (int)speed_control_style(ss),
str, 6,
clm_box,
speed_control_choice, speed_control_up, speed_control_down, speed_control_text);
remember_pref(prf, reflect_speed_control, save_speed_control, help_speed_control, NULL, revert_speed_control);
free(str);
make_inter_variable_separator(clm_box);
str = mus_format("%d", rts_sinc_width = sinc_width(ss));
prf = prefs_row_with_text("sinc interpolation width in srate converter", S_sinc_width, str,
clm_box,
sinc_width_text);
remember_pref(prf, reflect_sinc_width, save_sinc_width, help_sinc_width, NULL, revert_sinc_width);
free(str);
}
make_inter_topic_separator(topics);
/* -------- programming -------- */
{
GtkWidget *prg_box;
/* ---------------- listener options ---------------- */
prg_box = make_top_level_box(topics);
make_top_level_label("listener options", prg_box);
prf = prefs_row_with_toggle("show listener at start up", S_show_listener,
rts_show_listener = listener_is_visible(),
prg_box,
show_listener_toggle);
remember_pref(prf, reflect_show_listener, save_show_listener, help_show_listener, clear_show_listener, revert_show_listener);
make_inter_variable_separator(prg_box);
rts_listener_prompt = mus_strdup(listener_prompt(ss));
prf = prefs_row_with_text("prompt", S_listener_prompt,
listener_prompt(ss),
prg_box,
listener_prompt_text);
remember_pref(prf, reflect_listener_prompt, save_listener_prompt, help_listener_prompt, NULL, revert_listener_prompt);
make_inter_variable_separator(prg_box);
str = mus_format("%d", rts_print_length = print_length(ss));
prf = prefs_row_with_text("number of vector elements to display", S_print_length, str,
prg_box,
print_length_text);
remember_pref(prf, reflect_print_length, save_print_length, help_print_length, NULL, revert_print_length);
free(str);
make_inter_variable_separator(prg_box);
rts_listener_font = mus_strdup(listener_font(ss));
prf = prefs_row_with_text("font", S_listener_font,
listener_font(ss),
prg_box,
listener_font_text);
remember_pref(prf, reflect_listener_font, save_listener_font, help_listener_font, clear_listener_font, revert_listener_font);
make_inter_variable_separator(prg_box);
saved_listener_color = ss->listener_color;
prf = prefs_color_selector_row("background color", S_listener_color, ss->listener_color,
prg_box,
listener_color_func);
remember_pref(prf, NULL, save_listener_color, help_listener_color, clear_listener_color, revert_listener_color);
make_inter_variable_separator(prg_box);
saved_listener_text_color = ss->listener_text_color;
prf = prefs_color_selector_row("text color", S_listener_text_color, ss->listener_text_color,
prg_box,
listener_text_color_func);
remember_pref(prf, NULL, save_listener_text_color, help_listener_text_color, clear_listener_text_color, revert_listener_text_color);
}
/* -------- audio -------- */
{
GtkWidget *aud_box;
/* ---------------- audio options ---------------- */
aud_box = make_top_level_box(topics);
make_top_level_label("audio options", aud_box);
str = mus_format("%d", rts_dac_size = dac_size(ss));
prf = prefs_row_with_text("dac buffer size", S_dac_size,
str,
aud_box,
dac_size_text);
remember_pref(prf, reflect_dac_size, save_dac_size, help_dac_size, NULL, revert_dac_size);
free(str);
make_inter_variable_separator(aud_box);
prf = prefs_row_with_toggle("fold in otherwise unplayable channels", S_dac_combines_channels,
rts_dac_combines_channels = dac_combines_channels(ss),
aud_box,
dac_combines_channels_toggle);
remember_pref(prf, reflect_dac_combines_channels, save_dac_combines_channels, help_dac_combines_channels, NULL, revert_dac_combines_channels);
}
set_dialog_widget(PREFERENCES_DIALOG, preferences_dialog);
gtk_widget_show(preferences_dialog);
prefs_unsaved = false;
prefs_set_dialog_title(NULL);
return(preferences_dialog);
}