diff --git a/Makefile b/Makefile index 4e0dc08..c36c6e0 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ LIBS = `pkg-config --libs glib-2.0 gio-2.0 gtk+-2.0 alsa` -lexpat all: gdigi -gdigi: gdigi.o tests.o gui.o effects.o preset.o gtkknob.o +gdigi: knob.h gdigi.o tests.o gui.o effects.o preset.o gtkknob.o $(CC) $(LIBS) $(OFLAG) gdigi gdigi.o tests.o gui.o effects.o preset.o gtkknob.o gdigi.o: gdigi.c @@ -24,6 +24,11 @@ preset.o: preset.c gtkknob.o: gtkknob.c +gtkknob.o: gtkknob.c + +knob.h: + gdk-pixbuf-csource --name=knob_pixbuf knob.png > $@ + clean: rm *.o diff --git a/TODO b/TODO index 9a64b1f..d61fd94 100644 --- a/TODO +++ b/TODO @@ -4,9 +4,8 @@ -effects library -effects level -handling presets (saving, exporting to xml patches) --buildsystem +-buildsystem (install knob.png to share dir, don't use inline knob pixbuf) -expression pedal settings -finish modifier_linkable_list() (gdigi.c) -make modifiers[] complete (gdigi.c) -add it to gui - diff --git a/effects.c b/effects.c index a617097..e9ff691 100644 --- a/effects.c +++ b/effects.c @@ -17,6 +17,77 @@ #include "gdigi.h" #include "effects.h" +static gchar *wave_labels[] = { + "Tri", + "Sine", + "Square", + NULL, +}; + +static gchar *whammy_labels[] = { + "OctUp", + "2OctUp", + "2ndDn", + "Rv2nd", + "4thDn", + "OctDn", + "2OctDn", + "DivBmb", + "M3>Ma3", + "2ndMa3", + "3rd4th", + "4th5th", + "5thOct", + "HOctUp", + "HOctDn", + "OctU>D", + NULL, +}; + +static gchar *ips_shift_labels[] = { + "Oct Dn", + "7th Dn", + "6th Dn", + "5th Dn", + "4th Dn", + "3rd Dn", + "2nd Dn", + "2nd Up", + "3rd Up", + "4th Up", + "5th Up", + "6th Up", + "7th Up", + "Oct Up", + NULL, +}; + +static gchar *ips_key_labels[] = { + "E", + "F", + "Gb", + "G", + "Ab", + "A", + "Bb", + "B", + "C", + "Db", + "D", + "Eb", + NULL, +}; + +static gchar *ips_scale_labels[] = { + "Major", + "Minor", + "Dorian", + "Mixolydian", + "Lydian", + "HMinor", + NULL, +}; + static EffectSettings wah_settings[] = { {"Wah min", 0.0, 99.0, WAH_MIN, WAH_POSITION_MIN_MAX}, {"Wah max", 0.0, 99.0, WAH_MAX, WAH_POSITION_MIN_MAX}, @@ -159,14 +230,14 @@ static EffectSettings chorusfx_dual_settings[] = { {"Dual chorus speed", 0.0, 99.0, DUAL_CHORUS_SPEED, CHORUSFX_POSITION}, {"Dual chorus depth", 0.0, 99.0, DUAL_CHORUS_DEPTH, CHORUSFX_POSITION}, {"Dual chorus level", 0.0, 99.0, DUAL_CHORUS_LEVEL, CHORUSFX_POSITION}, - /* TODO: DUAL_CHORUS_WAVE with valid options WAVE_TRI, WAVE_SINE, WAVE_SQUARE */ + {"Dual chorus wave", 0.0, 2.0, DUAL_CHORUS_WAVE, CHORUSFX_POSITION, wave_labels}, }; static EffectSettings chorusfx_multi_settings[] = { {"Multi chorus speed", 0.0, 99.0, MULTI_CHORUS_SPEED, CHORUSFX_POSITION}, {"Multi chorus depth", 0.0, 99.0, MULTI_CHORUS_DEPTH, CHORUSFX_POSITION}, {"Multi chorus level", 0.0, 99.0, MULTI_CHORUS_LEVEL, CHORUSFX_POSITION}, - /* TODO: MULTI_CHORUS_WAVE with valid options WAVE_TRI, WAVE_SINE, WAVE_SQUARE */ + {"Multi chorus wave", 0.0, 2.0, MULTI_CHORUS_WAVE, CHORUSFX_POSITION, wave_labels}, }; static EffectSettings chorusfx_flanger_settings[] = { @@ -174,7 +245,7 @@ static EffectSettings chorusfx_flanger_settings[] = { {"Flanger depth", 0.0, 99.0, FLANGER_DEPTH, CHORUSFX_POSITION}, {"Flanger regen", 0.0, 99.0, FLANGER_REGEN, CHORUSFX_POSITION}, {"Flanger level", 0.0, 99.0, FLANGER_LEVEL, CHORUSFX_POSITION}, - /* TODO: FLANGER_WAVE with valid options WAVE_TRI, WAVE_SINE, WAVE_SQUARE */ + {"Flanger wave", 0.0, 2.0, FLANGER_WAVE, CHORUSFX_POSITION, wave_labels}, }; static EffectSettings chorusfx_mxr_flanger_settings[] = { @@ -189,7 +260,7 @@ static EffectSettings chorusfx_phaser_settings[] = { {"Phaser depth", 0.0, 99.0, PHASER_DEPTH, CHORUSFX_POSITION}, {"Phaser regen", 0.0, 99.0, PHASER_REGEN, CHORUSFX_POSITION}, {"Phaser level", 0.0, 99.0, PHASER_LEVEL, CHORUSFX_POSITION}, - /* TODO: PHASER_WAVE with valid options WAVE_TRI, WAVE_SINE, WAVE_SQUARE */ + {"Phaser wave", 0.0, 2.0, PHASER_WAVE, CHORUSFX_POSITION, wave_labels}, }; static EffectSettings chorusfx_vibrato_settings[] = { @@ -208,19 +279,19 @@ static EffectSettings chorusfx_vibropan_settings[] = { {"Vibropan speed", 0.0, 99.0, VIBROPAN_SPEED, CHORUSFX_POSITION}, {"Vibropan depth", 0.0, 99.0, VIBROPAN_DEPTH, CHORUSFX_POSITION}, {"Vibropan vibra", 0.0, 99.0, VIBROPAN_VIBRA, CHORUSFX_POSITION}, - /* TODO: VIBROPAN_WAVE with valid options WAVE_TRI, WAVE_SINE, WAVE_SQUARE */ + {"Vibropan wave", 0.0, 2.0, VIBROPAN_WAVE, CHORUSFX_POSITION, wave_labels}, }; static EffectSettings chorusfx_tremolo_settings[] = { {"Tremolo speed", 0.0, 99.0, TREMOLO_SPEED, CHORUSFX_POSITION}, {"Tremolo depth", 0.0, 99.0, TREMOLO_DEPTH, CHORUSFX_POSITION}, - /* TODO: TREMOLO_WAVE with valid options WAVE_TRI, WAVE_SINE, WAVE_SQUARE */ + {"Tremolo wave", 0.0, 2.0, TREMOLO_WAVE, CHORUSFX_POSITION, wave_labels}, }; static EffectSettings chorusfx_panner_settings[] = { {"Panner speed", 0.0, 99.0, PANNER_SPEED, CHORUSFX_POSITION}, {"Panner depth", 0.0, 99.0, PANNER_DEPTH, CHORUSFX_POSITION}, - /* TODO: PANNER_WAVE with valid options WAVE_TRI, WAVE_SINE, WAVE_SQUARE */ + {"Panner wave", 0.0, 2.0, PANNER_WAVE, CHORUSFX_POSITION, wave_labels}, }; static EffectSettings chorusfx_envelope_settings[] = { @@ -248,13 +319,7 @@ static EffectSettings chorusfx_step_filter_settings[] = { static EffectSettings chorusfx_whammy_settings[] = { {"Whammy pedal", 0.0, 99.0, WHAMMY_PEDAL, CHORUSFX_POSITION}, {"Whammy mix", 0.0, 99.0, WHAMMY_MIX, CHORUSFX_POSITION}, - /* - TODO: WHAMMY_AMOUNT with valid options: - WHAMMY_OCT_UP, WHAMMY_2OCT_UP, WHAMMY_2ND_DN, WHAMMY_RV_2ND, - WHAMMY_4TH_DN, WHAMMY_OCT_DN, WHAMMY_2OCT_DN, WHAMMY_DIV_BMB, - WHAMMY_M3_MA, WHAMMY_2ND_MA3, WHAMMY_3RD_4TH, WHAMMY_4TH_5TH, - WHAMMY_5TH_OCT, WHAMMY_HOCT_UP, WHAMMY_HOCT_DN, WHAMMY_OCT_UD - */ + {"Whammy amount", 0.0, 15.0, WHAMMY_AMOUNT, CHORUSFX_POSITION, whammy_labels}, }; static EffectSettings chorusfx_pitch_shift_settings[] = { @@ -269,20 +334,9 @@ static EffectSettings chorusfx_detune_settings[] = { }; static EffectSettings chorusfx_ips_settings[] = { - /* - TODO: IPS_SHIFT_AMOUNT with valid options: - IPS_7TH_DN, IPS_6TH_DN, IPS_5TH_DN, IPS_4TH_DN, IPS_3RD_DN, - IPS_2ND_DN, IPS_2ND_UP, IPS_3RD_UP, IPS_4TH_UP, IPS_5TH_UP, - IPS_6TH_UP, IPS_7TH_UP, IPS_OCT_U - - TODO: IPS_KEY with valid options: - IPS_E, IPS_F, IPS_GB, IPS_G, IPS_AB, IPS_A, IPS_BB, IPS_B, - IPS_C, IPS_DD, IPS_D, IPS_EB - - TODO: IPS_SCALE with valid options: - IPS_MAJOR, IPS_MINOR, IPS_DORIA, IPS_MIXLYD, IPS_LYDIAN, IPS_HMINO - */ - + {"IPS shift", 0.0, 13.0, IPS_SHIFT_AMOUNT, CHORUSFX_POSITION, ips_shift_labels}, + {"IPS key", 0.0, 11.0, IPS_KEY, CHORUSFX_POSITION, ips_key_labels}, + {"IPS scale", 0.0, 5.0, IPS_SCALE, CHORUSFX_POSITION, ips_scale_labels}, {"IPS level", 0.0, 99.0, IPS_LEVEL, CHORUSFX_POSITION}, }; diff --git a/effects.h b/effects.h index 0c3be8a..e0135c1 100644 --- a/effects.h +++ b/effects.h @@ -25,6 +25,8 @@ typedef struct { gdouble max; /* Parameter maximum value */ guint option; /* ID (to set parameter) */ guint position; /* position */ + + GStrv labels; /* value labels */ } EffectSettings; typedef struct { diff --git a/gdigi.c b/gdigi.c index ca266be..0a1bfe9 100644 --- a/gdigi.c +++ b/gdigi.c @@ -132,6 +132,7 @@ static void unpack_message(GString *msg) int x; int i; unsigned char status; + unsigned char *str; gboolean stop = FALSE; g_return_if_fail(msg != NULL); @@ -141,20 +142,21 @@ static void unpack_message(GString *msg) x = 0; i = 8; + str = (unsigned char*)msg->str; do { offset += 8; - status = (unsigned char)msg->str[offset-1]; + status = str[offset-1]; for (x=0; x<7; x++) { if (offset+x >= msg->len) { stop = TRUE; break; } - if ((unsigned char)msg->str[offset+x] == 0xF7) { - msg->str[i] = 0xF7; + if (str[offset+x] == 0xF7) { + str[i] = 0xF7; stop = TRUE; } - msg->str[i] = (((status << (x+1)) & 0x80) | (unsigned char)msg->str[x+offset]); + str[i] = (((status << (x+1)) & 0x80) | str[x+offset]); i++; } } while (!stop && (offset+x < msg->len)); diff --git a/gtkknob.c b/gtkknob.c index 6dba276..67bc0f6 100644 --- a/gtkknob.c +++ b/gtkknob.c @@ -62,8 +62,6 @@ static void gtk_knob_update(GtkKnob *knob); static void gtk_knob_adjustment_changed(GtkAdjustment *adjustment, gpointer data); static void gtk_knob_adjustment_value_changed(GtkAdjustment *adjustment, gpointer data); -GError *gerror; - /* Local data */ static GtkWidgetClass *parent_class = NULL; @@ -792,6 +790,29 @@ gtk_knob_animation_new_from_file(gchar *filename) { return anim; } +/***************************************************************************** + * + * gtk_knob_animation_new_from_inline() + * + *****************************************************************************/ +GtkKnobAnim * +gtk_knob_animation_new_from_inline(const guint8 *pixbuf) { + GtkKnobAnim *anim = g_new0 (GtkKnobAnim, 1); + + g_return_val_if_fail((pixbuf != NULL), NULL); + + anim->pixbuf = gdk_pixbuf_new_from_inline(-1, pixbuf, FALSE, NULL); + if (anim->pixbuf == NULL) { + g_free(anim); + return NULL; + } + + anim->height = gdk_pixbuf_get_height (anim->pixbuf); + anim->width = gdk_pixbuf_get_width (anim->pixbuf); + anim->frame_width = anim->height; + + return anim; +} /***************************************************************************** * @@ -812,6 +833,8 @@ gtk_knob_animation_new_from_file_full(gchar *filename, gint frame_width, g_return_val_if_fail ((filename != NULL), NULL); + GError *gerror = NULL; + #if GTK_MINOR_VERSION < 10 if (!(anim->pixbuf = gdk_pixbuf_new_from_file (filename, &gerror))) { return NULL; diff --git a/gtkknob.h b/gtkknob.h index 04d7f97..9a7fb93 100644 --- a/gtkknob.h +++ b/gtkknob.h @@ -1,8 +1,4 @@ /***************************************************************************** - * - * gtkknob.h - * - * PHASEX: [P]hase [H]armonic [A]dvanced [S]ynthesis [EX]periment * * Most of this code comes from gAlan 0.2.0, copyright (C) 1999 * Tony Garnock-Jones, with modifications by Sean Bolton, @@ -90,7 +86,8 @@ typedef struct _GtkKnobAnim GtkKnobAnim; extern GtkAdjustment *gtk_knob_get_adjustment(GtkKnob *knob); extern void gtk_knob_set_update_policy(GtkKnob *knob, GtkUpdateType policy); extern void gtk_knob_set_adjustment(GtkKnob *knob, GtkAdjustment *adjustment); - + + GtkKnobAnim *gtk_knob_animation_new_from_inline(const guint8 *pixbuf); GtkKnobAnim *gtk_knob_animation_new_from_file_full(gchar *filename, gint frame_width, gint width, diff --git a/gui.c b/gui.c index d5f1ffe..5a92e9b 100644 --- a/gui.c +++ b/gui.c @@ -19,10 +19,13 @@ #include "gui.h" #include "effects.h" #include "preset.h" +#include "gtkknob.h" +#include "knob.h" extern EffectList effects[]; extern int n_effects; +static GtkKnobAnim *knob_anim = NULL; static gboolean allow_send = FALSE; void show_error_message(GtkWidget *parent, gchar *message) @@ -39,7 +42,7 @@ void show_error_message(GtkWidget *parent, gchar *message) } typedef struct { - GtkWidget *widget; + GtkObject *widget; gint id; gint position; @@ -48,13 +51,28 @@ typedef struct { gint x; /* combo box item number */ } WidgetListElem; -void value_changed_option_cb(GtkSpinButton *spinbutton, EffectSettings *setting) +void value_changed_option_cb(GtkAdjustment *adj, EffectSettings *setting) { g_return_if_fail(setting != NULL); if (allow_send) { - gint val = gtk_spin_button_get_value_as_int(spinbutton); - set_option(setting->option, setting->position, val); + gdouble val; + g_object_get(G_OBJECT(adj), "value", &val, NULL); + set_option(setting->option, setting->position, (gint)val); + } + + if (setting->labels != NULL) { + GtkWidget *label; + gint x; + gdouble val = -1.0; + g_object_get(G_OBJECT(adj), "value", &val, NULL); + + x = (gint)val; + + if ((x >= setting->min) && (x <= setting->max)) { + label = g_object_get_data(G_OBJECT(adj), "label"); + gtk_label_set_text(GTK_LABEL(label), setting->labels[x]); + } } } @@ -68,7 +86,7 @@ void toggled_cb(GtkToggleButton *button, Effect *effect) } } -static void widget_list_add(GList **list, GtkWidget *widget, gint id, gint position, gint value, gint x) +static void widget_list_add(GList **list, GtkObject *widget, gint id, gint position, gint value, gint x) { WidgetListElem *el; @@ -88,8 +106,8 @@ static void apply_widget_setting(WidgetListElem *el, SettingParam *param) if (el->value == -1) { if (GTK_IS_TOGGLE_BUTTON(el->widget)) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(el->widget), (param->value == 0) ? FALSE : TRUE); - else if (GTK_IS_SPIN_BUTTON(el->widget)) - gtk_spin_button_set_value(GTK_SPIN_BUTTON(el->widget), param->value); + else if (GTK_IS_ADJUSTMENT(el->widget)) + gtk_adjustment_set_value(GTK_ADJUSTMENT(el->widget), (gdouble)param->value); } else { /* combo box */ if (el->value == param->value) gtk_combo_box_set_active(GTK_COMBO_BOX(el->widget), el->x); @@ -124,20 +142,35 @@ static void apply_current_preset(GList *list) GtkWidget *create_table(GList **list, EffectSettings *settings, gint amt) { - GtkWidget *table, *label, *widget; + GtkWidget *table, *label, *widget, *knob; GtkObject *adj; int x; - table = gtk_table_new(2, amt, FALSE); + table = gtk_table_new(3, amt, FALSE); for (x = 0; xlabel); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE); g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(toggled_cb), effect); - widget_list_add(list, button, effect->option, effect->position, -1, -1); + widget_list_add(list, GTK_OBJECT(button), effect->option, effect->position, -1, -1); return button; } @@ -229,7 +262,7 @@ GtkWidget *create_widget_container(GList **list, EffectGroup *group, gint amt) settings->option = group[x].option; settings->position = group[x].position; settings->child = widget; - widget_list_add(list, combo_box, group[x].option, group[x].position, group[x].id, x); + widget_list_add(list, GTK_OBJECT(combo_box), group[x].option, group[x].position, group[x].id, x); name = g_strdup_printf("SettingsGroup%d", cmbox_no); g_object_set_data_full(G_OBJECT(combo_box), name, settings, ((GDestroyNotify)effect_settings_group_free)); @@ -640,6 +673,8 @@ void create_window() vbox = gtk_vbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 2); + knob_anim = gtk_knob_animation_new_from_inline(knob_pixbuf); + for (x = 0; x