21 Commits
0.1.2 ... 0.1.4

Author SHA1 Message Date
Tomasz Moń
c61c2372ae cleaning 2009-03-03 23:06:03 +01:00
Tomasz Moń
49b7f42012 compile with -ansi 2009-03-03 22:39:55 +01:00
Tomasz Moń
157fba0380 make set_option wrapper to send_message 2009-03-03 22:31:25 +01:00
Tomasz Moń
904a30bb38 propertly apply xml patch 2009-03-03 21:57:47 +01:00
Tomasz Moń
8e445bb408 update gui on preset switch 2009-03-03 13:42:15 +01:00
Tomasz Moń
eb48d0b9d2 add get_message_id stub 2009-03-03 11:46:28 +01:00
Tomasz Moń
baa3829263 start gui with proper values 2009-03-03 11:39:25 +01:00
Tomasz Moń
79554a99ce Added tag 0.1.3 for changeset 5cc97dba5d41 2009-03-01 20:24:06 +01:00
Tomasz Moń
4740bef10f update TODO 2009-03-01 20:23:01 +01:00
Tomasz Moń
968d2947a7 set gui widgets to proper values after loading xml file 2009-03-01 19:00:35 +01:00
Tomasz Moń
e2cb03ab32 add store preset window 2009-03-01 13:31:15 +01:00
Tomasz Moń
ce5fe3fe0c add menubar 2009-03-01 11:57:27 +01:00
Tomasz Moń
966fc748af add store_preset_name 2009-03-01 10:05:24 +01:00
Tomasz Moń
709406f3ef add preset.c and preset.h 2009-03-01 09:52:31 +01:00
Tomasz Moń
ce522227c7 add amp types 2009-02-28 00:17:54 +01:00
Tomasz Moń
7d13b2a7ea add preset treeview 2009-02-27 23:28:34 +01:00
Tomasz Moń
d4c86b3a60 use GOptionContext instead of getopt 2009-02-27 12:57:52 +01:00
Tomasz Moń
ca23f2c94c rename query_user_presets to query_preset_names, make it return GStrv 2009-02-26 22:57:08 +01:00
Tomasz Moń
bfc285ad0f add some defines 2009-02-26 20:32:35 +01:00
Tomasz Moń
4e5f2438d3 add query user presets 2009-02-26 18:21:01 +01:00
Tomasz Moń
10aac46dde Added tag 0.1.2 for changeset 7a31bc520752 2009-02-25 22:25:57 +01:00
13 changed files with 1333 additions and 492 deletions

View File

@@ -1,7 +1,7 @@
CC = gcc
CFLAGS = `pkg-config --cflags glib-2.0 gtk+-2.0` -Wall -g
CFLAGS = `pkg-config --cflags glib-2.0 gio-2.0 gtk+-2.0` -Wall -g -ansi
OFLAG = -o
LIBS = `pkg-config --libs glib-2.0 gtk+-2.0 alsa`
LIBS = `pkg-config --libs glib-2.0 gio-2.0 gtk+-2.0 alsa` -lexpat
.SUFFIXES : .o .c
.c.o :
@@ -9,8 +9,8 @@ LIBS = `pkg-config --libs glib-2.0 gtk+-2.0 alsa`
all: gdigi
gdigi: gdigi.o tests.o gui.o effects.o
$(CC) $(LIBS) $(OFLAG) gdigi gdigi.o tests.o gui.o effects.o
gdigi: gdigi.o tests.o gui.o effects.o preset.o
$(CC) $(LIBS) $(OFLAG) gdigi gdigi.o tests.o gui.o effects.o preset.o
gdigi.o: gdigi.c
@@ -20,6 +20,8 @@ gui.o: gui.c
effects.o: effects.c
preset.o: preset.c
clean:
rm *.o

2
README
View File

@@ -1,4 +1,4 @@
Requirments: alsa, gtk+, glib
Requirments: alsa, gtk+, glib, expat
Getting started guide:
-to compile: make

8
TODO
View File

@@ -1,10 +1,8 @@
-figure out all magic commands
-make complete gui
-amp/cabinet models
-cabinet models
-tone library
-effects library
-effects level
-handling presets (loading, saving, exporting/importing to/from xml patches)
-handling presets (saving, exporting to xml patches)
-buildsystem
-figure out how to get current device settings, start gui with proper values
-fix expression pedal settings (possible types depend on active preset)
-expression pedal settings

115
effects.c
View File

@@ -116,16 +116,23 @@ static EffectSettings dist_mp_settings[] = {
{"MP volume", 0.0, 99.0, DIST_MP_VOLUME, DIST_POSITION},
};
static EffectSettings amp_settings[] = {
{"AMP gain", 0.0, 99.0, AMP_GAIN, AMP_POSITION},
{"AMP level", 0.0, 99.0, AMP_LEVEL, AMP_POSITION},
};
static EffectSettings amp_settings2[] = {
{"AMP level", 0.0, 99.0, AMP_LEVEL, AMP_POSITION},
};
static EffectSettings eq_settings[] = {
{"EQ gain", 0.0, 99.0, AMP_GAIN, AMP_POSITION},
{"EQ level", 0.0, 99.0, AMP_LEVEL, AMP_POSITION},
// TODO: make those display propertly (display range -12 to 12)
/* TODO: make those display propertly (display range -12 to 12) */
{"EQ bass", 0.0, 24.0, EQ_BASS, EQ_POSITION},
{"EQ mid", 0.0, 24.0, EQ_MID, EQ_POSITION},
{"EQ treble", 0.0, 24.0, EQ_TREBLE, EQ_POSITION},
// TODO: make this display propertly (display range 300 to 5000)
/* TODO: make this display propertly (display range 300 to 5000) */
{"EQ mid Hz", 0.0, 4700.0, EQ_MID_HZ, EQ_POSITION},
// TODO: make this display propertly (display range 500 to 8000)
/* TODO: make this display propertly (display range 500 to 8000) */
{"EQ treb Hz", 0.0, 7500.0, EQ_TREBLE_HZ, EQ_POSITION},
};
@@ -152,14 +159,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
/* TODO: DUAL_CHORUS_WAVE with valid options WAVE_TRI, WAVE_SINE, WAVE_SQUARE */
};
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
/* TODO: MULTI_CHORUS_WAVE with valid options WAVE_TRI, WAVE_SINE, WAVE_SQUARE */
};
static EffectSettings chorusfx_flanger_settings[] = {
@@ -167,7 +174,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
/* TODO: FLANGER_WAVE with valid options WAVE_TRI, WAVE_SINE, WAVE_SQUARE */
};
static EffectSettings chorusfx_mxr_flanger_settings[] = {
@@ -182,7 +189,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
/* TODO: PHASER_WAVE with valid options WAVE_TRI, WAVE_SINE, WAVE_SQUARE */
};
static EffectSettings chorusfx_vibrato_settings[] = {
@@ -201,19 +208,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
/* TODO: VIBROPAN_WAVE with valid options WAVE_TRI, WAVE_SINE, WAVE_SQUARE */
};
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
/* TODO: TREMOLO_WAVE with valid options WAVE_TRI, WAVE_SINE, WAVE_SQUARE */
};
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
/* TODO: PANNER_WAVE with valid options WAVE_TRI, WAVE_SINE, WAVE_SQUARE */
};
static EffectSettings chorusfx_envelope_settings[] = {
@@ -241,15 +248,17 @@ 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
/*
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
*/
};
static EffectSettings chorusfx_pitch_shift_settings[] = {
// TODO: make this display propertly (display range -24 to 24)
/* TODO: make this display propertly (display range -24 to 24) */
{"Pitch amount", 0.0, 48.0, PITCH_AMOUNT, CHORUSFX_POSITION},
{"Pitch mix", 0.0, 99.0, PITCH_MIX, CHORUSFX_POSITION},
};
@@ -260,63 +269,65 @@ 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_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_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
TODO: IPS_SCALE with valid options:
IPS_MAJOR, IPS_MINOR, IPS_DORIA, IPS_MIXLYD, IPS_LYDIAN, IPS_HMINO
*/
{"IPS level", 0.0, 99.0, IPS_LEVEL, CHORUSFX_POSITION},
};
static EffectSettings delay_analog_settings[] = {
// TODO: make this display propertly (10 msec to 5 sec)
/* TODO: make this display propertly (10 msec to 5 sec) */
{"Delay time", 0.0, 139.0, DELAY_TIME, DELAY_POSITION},
{"Delay analog level", 0.0, 99.0, ANALOG_LEVEL, DELAY_POSITION},
// TODO: make last value display propertly
/* TODO: make last value display propertly */
{"Delay analog repeats", 0.0, 100.0, ANALOG_REPEATS, DELAY_POSITION},
};
static EffectSettings delay_digital_settings[] = {
// TODO: make this display propertly (10 msec to 5 sec)
/* TODO: make this display propertly (10 msec to 5 sec) */
{"Delay time", 0.0, 139.0, DELAY_TIME, DELAY_POSITION},
{"Delay digital level", 0.0, 99.0, DIGITAL_LEVEL, DELAY_POSITION},
// TODO: make last value display propertly
/* TODO: make last value display propertly */
{"Delay digital repeats", 0.0, 100.0, DIGITAL_REPEATS, DELAY_POSITION},
{"Delay digital ducker thresh", 0.0, 99.0, DIGITAL_DUCKER_THRESH, DELAY_POSITION},
{"Delay digital ducker level", 0.0, 99.0, DIGITAL_DUCKER_LEVEL, DELAY_POSITION},
};
static EffectSettings delay_modulated_settings[] = {
// TODO: make this display propertly (10 msec to 5 sec)
/* TODO: make this display propertly (10 msec to 5 sec) */
{"Delay time", 0.0, 139.0, DELAY_TIME, DELAY_POSITION},
{"Delay modulated level", 0.0, 99.0, MODULATED_LEVEL, DELAY_POSITION},
// TODO: make last value display propertly
/* TODO: make last value display propertly */
{"Delay modulated repeats", 0.0, 100.0, MODULATED_REPEATS, DELAY_POSITION},
{"Delay modulated depth", 0.0, 99.0, MODULATED_DEPTH, DELAY_POSITION},
};
static EffectSettings delay_pong_settings[] = {
// TODO: make this display propertly (10 msec to 5 sec)
/* TODO: make this display propertly (10 msec to 5 sec) */
{"Delay time", 0.0, 139.0, DELAY_TIME, DELAY_POSITION},
{"Delay pong level", 0.0, 99.0, PONG_LEVEL, DELAY_POSITION},
// TODO: make last value display propertly
/* TODO: make last value display propertly */
{"Delay pong repeats", 0.0, 100.0, PONG_REPEATS, DELAY_POSITION},
{"Delay pong ducker thresh", 0.0, 99.0, PONG_DUCKER_THRESH, DELAY_POSITION},
{"Delay pong ducker level", 0.0, 99.0, PONG_DUCKER_LEVEL, DELAY_POSITION},
};
static EffectSettings delay_tape_settings[] = {
// TODO: make this display propertly (10 msec to 5 sec)
/* TODO: make this display propertly (10 msec to 5 sec) */
{"Delay time", 0.0, 139.0, DELAY_TIME, DELAY_POSITION},
{"Delay tape level", 0.0, 99.0, TAPE_LEVEL, DELAY_POSITION},
// TODO: make last value display propertly
/* TODO: make last value display propertly */
{"Delay tape repeats", 0.0, 100.0, TAPE_REPEATS, DELAY_POSITION},
{"Delay tape wow", 0.0, 99.0, TAPE_WOW, DELAY_POSITION},
{"Delay tape flutter", 0.0, 99.0, TAPE_FLUTTER, DELAY_POSITION},
@@ -432,6 +443,31 @@ static EffectGroup reverb_group[] = {
{REVERB_TYPE_EMT240_PLATE, "EMT240 Plate", REVERB_TYPE, REVERB_POSITION, reverb_emt240_plate_settings, G_N_ELEMENTS(reverb_emt240_plate_settings)},
};
static EffectGroup amp_group[] = {
{AMP_TYPE_TWEED_CHAMP, "Tweed Champ", AMP_TYPE, AMP_POSITION, amp_settings, G_N_ELEMENTS(amp_settings)},
{AMP_TYPE_TWEED_DELUXE, "Tweed Deluxe", AMP_TYPE, AMP_POSITION, amp_settings, G_N_ELEMENTS(amp_settings)},
{AMP_TYPE_TWEED_BASSMAN, "Tweed Bassman", AMP_TYPE, AMP_POSITION, amp_settings, G_N_ELEMENTS(amp_settings)},
{AMP_TYPE_BLACKFACE_TWIN, "Blackface Twin", AMP_TYPE, AMP_POSITION, amp_settings, G_N_ELEMENTS(amp_settings)},
{AMP_TYPE_BLACKFACE_DELUXE, "Blackface Deluxe", AMP_TYPE, AMP_POSITION, amp_settings, G_N_ELEMENTS(amp_settings)},
{AMP_TYPE_SUPER_LEAD_PLEXI, "Super Lead Plexi", AMP_TYPE, AMP_POSITION, amp_settings, G_N_ELEMENTS(amp_settings)},
{AMP_TYPE_MASTER_VOLUME, "Master Volume", AMP_TYPE, AMP_POSITION, amp_settings, G_N_ELEMENTS(amp_settings)},
{AMP_TYPE_JCM800, "JCM800", AMP_TYPE, AMP_POSITION, amp_settings, G_N_ELEMENTS(amp_settings)},
{AMP_TYPE_JCM900, "JCM900", AMP_TYPE, AMP_POSITION, amp_settings, G_N_ELEMENTS(amp_settings)},
{AMP_TYPE_AC15, "AC15", AMP_TYPE, AMP_POSITION, amp_settings, G_N_ELEMENTS(amp_settings)},
{AMP_TYPE_AC30TB, "AC30TB", AMP_TYPE, AMP_POSITION, amp_settings, G_N_ELEMENTS(amp_settings)},
{AMP_TYPE_HIWATT_100, "Hiwatt 100", AMP_TYPE, AMP_POSITION, amp_settings, G_N_ELEMENTS(amp_settings)},
{AMP_TYPE_BOOGIE_MARK_II, "Boogie Mark II", AMP_TYPE, AMP_POSITION, amp_settings, G_N_ELEMENTS(amp_settings)},
{AMP_TYPE_DUAL_RECTIFIER, "Dual Rectifier", AMP_TYPE, AMP_POSITION, amp_settings, G_N_ELEMENTS(amp_settings)},
{AMP_TYPE_MATCHLESS_HC30, "Matchless HC30", AMP_TYPE, AMP_POSITION, amp_settings, G_N_ELEMENTS(amp_settings)},
{AMP_TYPE_SOLO, "Solo", AMP_TYPE, AMP_POSITION, amp_settings, G_N_ELEMENTS(amp_settings)},
{AMP_TYPE_METAL, "Metal", AMP_TYPE, AMP_POSITION, amp_settings, G_N_ELEMENTS(amp_settings)},
{AMP_TYPE_BRIGHT, "Bright", AMP_TYPE, AMP_POSITION, amp_settings, G_N_ELEMENTS(amp_settings)},
{AMP_TYPE_CLEAN, "Clean", AMP_TYPE, AMP_POSITION, amp_settings, G_N_ELEMENTS(amp_settings)},
{AMP_TYPE_HIGH_GAIN, "High Gain", AMP_TYPE, AMP_POSITION, amp_settings, G_N_ELEMENTS(amp_settings)},
{AMP_TYPE_ACOUSTIC, "Acoustic", AMP_TYPE, AMP_POSITION, amp_settings2, G_N_ELEMENTS(amp_settings2)},
{AMP_TYPE_DIRECT, "Direct", AMP_TYPE, AMP_POSITION, amp_settings2, G_N_ELEMENTS(amp_settings2)},
};
static EffectGroup eq_group[] = {
{EQ_TYPE_BRIGHT, "Bright", EQ_TYPE, EQ_POSITION, eq_settings, G_N_ELEMENTS(eq_settings)},
{EQ_TYPE_MIDBOOST, "Mid Boost", EQ_TYPE, EQ_POSITION, eq_settings, G_N_ELEMENTS(eq_settings)},
@@ -467,12 +503,17 @@ static Effect reverb_effect[] = {
{"Reverb", REVERB_ON_OFF, REVERB_POSITION, reverb_group, G_N_ELEMENTS(reverb_group)},
};
static Effect amp_effect[] = {
{"Amp", AMP_ON_OFF, AMP_POSITION, amp_group, G_N_ELEMENTS(amp_group)},
};
static Effect eq_effect[] = {
{"EQ", EQ_ON_OFF, EQ_POSITION, eq_group, G_N_ELEMENTS(eq_group)},
};
EffectList effects[] = {
{wah_effect, G_N_ELEMENTS(wah_effect)},
{amp_effect, G_N_ELEMENTS(amp_effect)},
{eq_effect, G_N_ELEMENTS(eq_effect)},
{comp_effect, G_N_ELEMENTS(comp_effect)},
{dist_effect, G_N_ELEMENTS(dist_effect)},

View File

@@ -14,6 +14,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses>.
*/
#ifndef GDIGI_EFFECTS_H
#define GDIGI_EFFECTS_H
#include <glib/gtypes.h>
typedef struct {
@@ -45,3 +48,5 @@ typedef struct {
Effect *effect; /* list of supported effects */
gint amt; /* list of supported effects length */
} EffectList;
#endif /* GDIGI_EFFECTS_H */

531
gdigi.c
View File

@@ -18,11 +18,16 @@
#include <gtk/gtk.h>
#include <getopt.h>
#include <alsa/asoundlib.h>
#include <string.h>
#include <alloca.h>
#include "gdigi.h"
#include "gui.h"
static snd_rawmidi_t *output;
static unsigned char device_id = 0x7F;
static unsigned char family_id = 0x7F;
static unsigned char product_id = 0x7F;
static snd_rawmidi_t *output = NULL;
static snd_rawmidi_t *input = NULL;
static char *device = "hw:1,0,0";
/*
@@ -46,6 +51,18 @@ char calculate_checksum(gchar *array, int length, int check)
return checksum;
}
static char calc_checksum(gchar *array, gint length)
{
int x;
int checksum = 0;
for (x = 0; x<length; x++) {
checksum ^= array[x];
}
return checksum;
}
/*
opens MIDI device
Returns TRUE on error
@@ -54,7 +71,7 @@ gboolean open_device()
{
int err;
err = snd_rawmidi_open(NULL, &output, device, SND_RAWMIDI_NONBLOCK);
err = snd_rawmidi_open(&input, &output, device, SND_RAWMIDI_NONBLOCK);
if (err) {
fprintf(stderr, "snd_rawmidi_open %s failed: %d\n", device, err);
return TRUE;
@@ -65,6 +82,9 @@ gboolean open_device()
fprintf(stderr, "snd_rawmidi_nonblock failed: %d\n", err);
return TRUE;
}
snd_rawmidi_read(input, NULL, 0); /* trigger reading */
return FALSE;
}
@@ -76,6 +96,177 @@ void send_data(char *data, int length)
snd_rawmidi_write(output, data, length);
}
/*
reads data from MIDI IN
returns GString containing data
if no data was read it returns NULL
*/
GString* read_data()
{
/* This is mostly taken straight from alsa-utils-1.0.19 amidi/amidi.c
by Clemens Ladisch <clemens@ladisch.de> */
int err;
int npfds;
gboolean stop = FALSE;
struct pollfd *pfds;
GString *string = NULL;
npfds = snd_rawmidi_poll_descriptors_count(input);
pfds = alloca(npfds * sizeof(struct pollfd));
snd_rawmidi_poll_descriptors(input, pfds, npfds);
do {
char buf[20];
int i, length;
unsigned short revents;
err = poll(pfds, npfds, 200);
if (err < 0 && errno == EINTR)
break;
if (err < 0) {
g_error("poll failed: %s", strerror(errno));
break;
}
if ((err = snd_rawmidi_poll_descriptors_revents(input, pfds, npfds, &revents)) < 0) {
g_error("cannot get poll events: %s", snd_strerror(errno));
break;
}
if (revents & (POLLERR | POLLHUP))
break;
if (!(revents & POLLIN))
continue;
err = snd_rawmidi_read(input, buf, sizeof(buf));
if (err == -EAGAIN)
continue;
if (err < 0) {
g_error("cannot read: %s", snd_strerror(err));
break;
}
length = 0;
for (i = 0; i < err; ++i)
if (buf[i] != 0xFE) /* ignore active sensing */
buf[length++] = buf[i];
if ((unsigned char)buf[length-1] == 0xF7)
stop = TRUE;
if (length != 0) {
if (string == NULL) {
string = g_string_new_len(buf, length);
} else {
string = g_string_append_len(string, buf, length);
}
}
} while ((err != 0) && (stop == FALSE));
return string;
}
static void clear_midi_in_buffer()
{
GString *str;
do {
str = read_data();
} while (str != NULL);
}
GString *pack_data(gchar *data, gint len)
{
GString *packed;
gint i;
gint new_len;
unsigned char status;
gint offset;
gint status_byte;
new_len = len + (len/7);
packed = g_string_sized_new(new_len);
status = 0;
offset = -1;
status_byte = 0;
for (i=0; i<len; i++) {
if ((i % 7) == 0) {
packed->str[status_byte] = status;
status = 0;
status_byte = packed->len;
g_string_append_c(packed, '\0');
}
g_string_append_c(packed, (data[i] & 0x7F));
status |= (data[i] & 0x80) >> ((i%7) + 1);
}
packed->str[status_byte] = status;
return packed;
}
/*
data - unpacked data to send
len - data length
*/
void send_message(gint procedure, gchar *data, gint len)
{
GString *msg = g_string_new_len("\xF0" /* SysEx status byte */
"\x00\x00\x10", /* Manufacturer ID */
4);
g_string_append_printf(msg,
"%c%c%c" /* device, family, product ID */
"%c", /* procedure */
device_id, family_id, product_id,
procedure);
if (len > 0) {
GString *tmp = pack_data(data, len);
g_string_append_len(msg, tmp->str, tmp->len);
g_string_free(tmp, TRUE);
}
g_string_append_printf(msg, "%c\xF7",
calc_checksum(&msg->str[1], msg->len - 1));
send_data(msg->str, msg->len);
g_string_free(msg, TRUE);
}
static gint get_message_id(GString *msg)
{
if (msg->len > 7) {
return (unsigned char)msg->str[7];
}
return -1;
}
void append_value(GString *msg, guint value)
{
/* check how many bytes long the value is */
guint temp = value;
gint n = 0;
do {
n++;
temp = temp >> 8;
} while (temp);
if (n == 1) {
if (value & 0x80)
n = 2;
else
g_string_append_printf(msg, "%c", value);
}
if (n > 1) {
gint x;
g_string_append_printf(msg, "%c", (n | 0x80));
for (x=0; x<n; x++) {
g_string_append_printf(msg, "%c",
((value >> (8*(n-x-1))) & 0xFF));
}
}
}
/*
id - ID as found in preset file
position - Position as found in preset file
@@ -83,93 +274,26 @@ void send_data(char *data, int length)
*/
void set_option(guint id, guint position, guint value)
{
static char option[] = {0xF0, 0x00, 0x00, 0x10, 0x00, 0x5E, 0x02, 0x41,
0x00, 0x00, 0x00, /* ID */
0x00, /* position */
0x00, /* value length (not necesarry) */
0x00, 0x00, 0x00, /* value (can be either 1, 2 or 3 bytes) */
0x00, /* checksum */ 0xF7};
option[8] = ((id & 0x80) >> 2);
option[9] = ((id & 0xFF00) >> 8);
option[10] = ((id & 0x007F));
option[11] = position;
if (value < 0x80) {
// [12] = value, [13] - checksum, [14] = 0xF7
option[12] = value;
option[14] = 0xF7;
option[13] = calculate_checksum(option, 15, 13);
send_data(option, 15);
} else if (value <= 0xFF) {
option[8] |= 0x08; // there'll be length before value
if (((value & 0x80) >> 7) == 1)
option[8] |= 0x04;
option[12] = 0x01;
// [13] = value, [14] - checksum, [15] = 0xF7
option[13] = (value & 0x007F);
option[15] = 0xF7;
option[14] = calculate_checksum(option, 16, 14);
send_data(option, 16);
} else if (value <= 0xFFFF) {
option[8] |= 0x08; // there'll be length before value
if (((value & 0x80) >> 7) == 1)
option[8] |= 0x02;
option[12] = 0x02;
option[13] = ((value & 0xFF00) >> 8);
option[14] = ((value & 0x007F));
option[16] = 0xF7;
option[15] = calculate_checksum(option, 17, 15);
send_data(option, 17);
} else if (value <= 0xFFFFFF) {
option[8] |= 0x08; // there'll be length before value
if (((value & 0x80) >> 7) == 1)
option[8] |= 0x01;
option[12] = 0x03;
option[13] = ((value & 0xFF0000) >> 16);
option[14] = ((value & 0x00FF00) >> 8);
option[15] = ((value & 0x00007F));
option[17] = 0xF7;
option[16] = calculate_checksum(option, 18, 16);
send_data(option, 18);
}
GString *msg = g_string_sized_new(9);
g_string_append_printf(msg, "%c%c%c",
((id & 0xFF00) >> 8), (id & 0xFF),
position);
append_value(msg, value);
send_message(RECEIVE_PARAMETER_VALUE, msg->str, msg->len);
g_string_free(msg, TRUE);
}
/* x = 0 to 60 */
void switch_user_preset(int x)
void switch_preset(guint bank, guint x)
{
static char switch_preset[] = {0x00, 0xF0, 0x00, 0x00, 0x10, 0x00, 0x5E, 0x02, 0x39, 0x00, 0x01 /* bank = user */, 0x00 /* no */, 0x04, 0x00, 0x00, 0x01, 0x00 /* confirm */, 0xF7};
switch_preset[11] = x;
switch_preset[16] = calculate_checksum(switch_preset, sizeof(switch_preset), 16);
send_data(switch_preset, sizeof(switch_preset));
}
/* x = 0 to 60 */
void switch_system_preset(int x)
{
static char switch_preset[] = {0x00, 0xF0, 0x00, 0x00, 0x10, 0x00, 0x5E, 0x02, 0x39, 0x00, 0x00 /* bank = system */, 0x00 /* no */, 0x04, 0x00, 0x00, 0x01, 0x00 /* confirm */, 0xF7};
switch_preset[11] = x;
switch_preset[16] = calculate_checksum(switch_preset, sizeof(switch_preset), 16);
send_data(switch_preset, sizeof(switch_preset));
GString *msg = g_string_sized_new(6);
g_string_append_printf(msg, "%c%c%c%c%c%c",
bank, x, /* source */
PRESETS_EDIT_BUFFER, 0, /* destination */
0, /* keep existing name */
1); /* load */
send_message(MOVE_PRESET, msg->str, msg->len);
g_string_free(msg, TRUE);
}
/* level = 0 to 99 */
@@ -178,73 +302,204 @@ void set_preset_level(int level)
set_option(PRESET_LEVEL, PRESET_POSITION, level);
}
void store_preset_name(int x, const gchar *name)
{
GString *msg = g_string_sized_new(6);
g_string_append_printf(msg, "%c%c%c%c%s%c%c",
PRESETS_EDIT_BUFFER, 0, /* source */
PRESETS_USER, x, /* destination */
name, 0, /* name */
1); /* load */
send_message(MOVE_PRESET, msg->str, msg->len);
g_string_free(msg, TRUE);
}
/* x = 0 to 59 (preset number) */
void set_preset_name(int x, gchar *name)
{
static char set_name[] = {0x00, 0xF0, 0x00, 0x00, 0x10, 0x00, 0x5E, 0x02, 0x29, 0x00, 0x01, 0x00 /* preset no */, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
set_name[11] = x;
int a;
int b;
b = 0;
for (a=0; (name != NULL && a<strlen(name)) && a<10 ; a++) {
if (a == 5) {
set_name[12+a] = 0x00;
b++;
}
set_name[12+a+b] = name[a];
}
if (a == 5)
a = 4;
else
set_name[12+a+b] = 0x00;
set_name[12+a+2+b] = 0xF7;
set_name[12+a+1+b] = calculate_checksum(set_name, 12+a+3+b, 12+a+1+b);
send_data(set_name, 13+a+3+b);
GString *msg = g_string_sized_new(12);
g_string_append_printf(msg, "%c%c%s%c",
PRESETS_USER, /* preset bank */
x, /* preset index */
name, 0); /* name */
send_message(RECEIVE_PRESET_NAME, msg->str, msg->len);
g_string_free(msg, TRUE);
}
int main(int argc, char *argv[]) {
gtk_init(&argc, &argv);
/*
Queries user preset names
Valid bank values are PRESETS_SYSTEM and PRESETS_USER
Returns GStrv which must be freed with g_strfreev
Returns NULL on error
*/
GStrv query_preset_names(gchar bank)
{
GString *data = NULL;
int x; /* used to iterate over whole reply */
int n = 0; /* current preset number */
int n_total; /* total number of presets */
gchar **str_array = NULL;
int c;
while (1) {
static struct option long_options[] = {
{"device", required_argument, 0, 'd'},
{0, 0, 0, 0}
};
int option_index = 0;
c = getopt_long(argc, argv, "d:", long_options, &option_index);
if (c == -1)
break;
/* clear MIDI IN buffer */
clear_midi_in_buffer();
switch(c) {
case 'd':
device = optarg;
break;
default:
abort();
/* query user preset names */
send_message(REQUEST_PRESET_NAMES, &bank, 1);
/* read reply */
do {
if (data)
g_string_free(data, TRUE);
data = read_data();
} while (get_message_id(data) != RECEIVE_PRESET_NAMES);
if (data != NULL) {
char preset_reply_magic[] = {0xF0, 0x00, 0x00, 0x10, 0x00, 0x5E, 0x02, 0x22, 0x00, 0x01};
if (strncmp(data->str, preset_reply_magic, sizeof(preset_reply_magic)) == 0) {
char buf[10]; /* temporary, used to read single preset name */
int b = 0; /* used to iterate over buf */
if (data->len >= 10) {
n_total = data->str[10];
str_array = g_new(gchar*, n_total + 1);
str_array[n_total] = NULL;
}
for (x=11; ((x<data->len) && (n<n_total)); x++) {
if ((x % 8) == 0) /* every 8th byte is 0x00 */
continue;
if (data->str[x] == 0xF7) /* every message ends with 0xF7 */
break;
if (data->str[x] == 0) { /* presets are splitted with 0x00 */
gchar *name;
name = g_new(gchar, b+1);
strncpy(name, buf, b);
name[b] = 0;
if (n < n_total)
str_array[n] = name;
b = 0;
n++;
} else {
if (b < 10) {
buf[b] = data->str[x];
b++;
} else {
g_message("Preset name seems to be longer than 10 chars!");
}
}
}
}
g_string_free(data, TRUE);
}
return str_array;
}
static void unpack_message(GString *msg)
{
int offset;
int x;
int i;
unsigned char status;
gboolean finish = FALSE;
offset = 9;
x = 0;
i = 8;
do {
status = (unsigned char)msg->str[offset-1];
for (x=0; x<7; x++) {
if ((unsigned char)msg->str[offset+x] == 0xF7) {
msg->str[i] = 0xF7;
finish = TRUE;
}
msg->str[i] = (((status << (x+1)) & 0x80) | (unsigned char)msg->str[x+offset]);
i++;
}
offset += 8;
} while (finish == FALSE && offset < msg->len);
}
GString *get_current_preset()
{
GString *data = NULL;
/* clear MIDI IN buffer */
clear_midi_in_buffer();
send_message(REQUEST_PRESET, "\x04\x00", 3);
/* read reply */
data = read_data();
g_string_free(data, TRUE);
data = read_data();
unpack_message(data);
return data;
}
static gboolean request_who_am_i(unsigned char *device_id, unsigned char *family_id,
unsigned char *product_id)
{
send_message(REQUEST_WHO_AM_I, NULL, 0);
GString *data = read_data();
if (data != NULL) {
if ((data->len == 15) && (data->str[7] == RECEIVE_WHO_AM_I)) {
*device_id = data->str[9];
*family_id = data->str[10];
*product_id = data->str[11];
g_string_free(data, TRUE);
return TRUE;
}
g_string_free(data, TRUE);
}
return FALSE;
}
static GOptionEntry options[] = {
{"device", 'd', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_STRING, &device, "MIDI device port to use", NULL},
{NULL}
};
int main(int argc, char *argv[]) {
GError *error = NULL;
GOptionContext *context;
context = g_option_context_new(NULL);
g_option_context_add_main_entries(context, options, NULL);
g_option_context_add_group(context, gtk_get_option_group(TRUE));
if (!g_option_context_parse(context, &argc, &argv, &error)) {
g_message("option parsing failed: %s\n", error->message);
g_error_free(error);
g_option_context_free(context);
exit(EXIT_FAILURE);
}
if (open_device() == TRUE) {
GtkWidget *msg = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
"Failed to open MIDI device");
g_option_context_free(context);
gtk_dialog_run(GTK_DIALOG(msg));
gtk_widget_destroy(msg);
if (open_device() == TRUE) {
show_error_message(NULL, "Failed to open MIDI device");
} else {
create_window();
gtk_main();
if (request_who_am_i(&device_id, &family_id, &product_id) == FALSE) {
show_error_message(NULL, "No suitable reply from device - is it connected?");
} else {
create_window();
gtk_main();
}
}
if (output != NULL)
snd_rawmidi_close(output);
if (input != NULL)
snd_rawmidi_close(input);
return 0;
return EXIT_SUCCESS;
}

152
gdigi.h
View File

@@ -14,7 +14,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses>.
*/
#ifndef GDIGI_H
#define GDIGI_H
#include <glib.h>
#include <glib-object.h>
enum {
WAH_TYPE_CRY = 132,
@@ -121,6 +125,31 @@ enum {
#define PRESET_POSITION 18
#define PRESET_LEVEL 2626
enum {
AMP_TYPE_TWEED_CHAMP = 307,
AMP_TYPE_TWEED_DELUXE = 308,
AMP_TYPE_TWEED_BASSMAN = 309,
AMP_TYPE_BLACKFACE_TWIN = 311,
AMP_TYPE_BLACKFACE_DELUXE = 312,
AMP_TYPE_SUPER_LEAD_PLEXI = 314,
AMP_TYPE_MASTER_VOLUME = 316,
AMP_TYPE_JCM800 = 317,
AMP_TYPE_JCM900 = 318,
AMP_TYPE_AC15 = 322,
AMP_TYPE_AC30TB = 323,
AMP_TYPE_HIWATT_100 = 324,
AMP_TYPE_BOOGIE_MARK_II = 320,
AMP_TYPE_DUAL_RECTIFIER = 321,
AMP_TYPE_MATCHLESS_HC30 = 326,
AMP_TYPE_SOLO = 331,
AMP_TYPE_METAL = 332,
AMP_TYPE_BRIGHT = 333,
AMP_TYPE_CLEAN = 335,
AMP_TYPE_HIGH_GAIN = 337,
AMP_TYPE_ACOUSTIC = 341,
AMP_TYPE_DIRECT = 306
};
enum {
EQ_TYPE_BRIGHT = 1474,
EQ_TYPE_MIDBOOST = 1472,
@@ -128,6 +157,8 @@ enum {
EQ_TYPE_WARM = 1475
};
#define AMP_TYPE 2496
#define AMP_ON_OFF 265
#define AMP_POSITION 8
#define AMP_GAIN 2497
@@ -405,49 +436,6 @@ enum {
#define EMT240_PLATE_LIVELINESS 1933
#define EMT240_PLATE_LEVEL 1925
enum {
EXP_TYPE_NONE = 0,
EXP_TYPE_PICKUP_ENABLE = 131137,
EXP_TYPE_PIKCUP_TYPE = 131136,
EXP_TYPE_COMP_ENABLE = 262337,
EXP_TYPE_COMP_SUST = 262352,
EXP_TYPE_COMP_TONE = 262353,
EXP_TYPE_COMP_LEVEL = 262354,
EXP_TYPE_COMP_ATTACK = 262355,
EXP_TYPE_DIST_ENABLE = 395649,
EXP_TYPE_DIST_DISTORTION = 395653,
EXP_TYPE_DIST_FILTER = 395654,
EXP_TYPE_DIST_VOLUME = 395655,
EXP_TYPE_AMP_ENABLE = 524553,
EXP_TYPE_AMP_GAIN = 526785,
EXP_TYPE_AMP_LEVEL = 526786,
EXP_TYPE_EQ_ENABLE = 1576076,
EXP_TYPE_EQ_BASS = 1576067,
EXP_TYPE_EQ_MID = 1576068,
EXP_TYPE_EQ_TREB = 1576069,
EXP_TYPE_GATE_ENABLE = 787137,
EXP_TYPE_GATE_THRESHOLD = 787142,
EXP_TYPE_GATE_ATTACK = 787144,
EXP_TYPE_GATE_RELEASE = 787145,
EXP_TYPE_GATE_ATTN = 787146,
EXP_TYPE_CHORUSFX_ENABLE = 918273,
EXP_TYPE_PHASER_SPEED = 918466,
EXP_TYPE_PHASER_DEPTH = 918467,
EXP_TYPE_PHASER_REGEN = 918470,
EXP_TYPE_PHASER_WAVEFORM = 918471,
EXP_TYPE_PHASER_LEVEL = 918469,
EXP_TYPE_DELAY_ENABLE = 984897,
EXP_TYPE_DELAY_TIME = 984928,
EXP_TYPE_DELAY_REPEATS = 984903,
EXP_TYPE_DELAY_LEVEL = 984900,
EXP_TYPE_DELAY_DUCK_THRESH = 984929,
EXP_TYPE_DELAY_DUCK_LEVEL = 984930,
EXP_TYPE_REVERB_ENABLE = 1050497,
EXP_TYPE_REVERB_LEVEL = 1050501,
EXP_TYPE_VOLUME_PRE_FX = 854594,
EXP_TYPE_VOLUME_POST_FX = 1116738
};
#define EXP_TYPE 8194
#define EXP_POSITION 19
@@ -458,7 +446,81 @@ enum {
#define USB_AUDIO_PLAYBACK_MIX 12297
#define USB_AUDIO_LEVEL 12307
enum {
PRESETS_SYSTEM = 0,
PRESETS_USER = 1,
PRESETS_ARTIST = 2,
/* Version 1 and later */
PRESETS_MEDIA_CARD = 3,
PRESETS_EDIT_BUFFER = 4, /* Current preset edit buffer, index must be 0 */
PRESETS_FACTORY2 = 5,
/* Version 2 and later */
PRESETS_EXTERNAL = 6
};
enum {
REQUEST_WHO_AM_I = 0x01,
RECEIVE_WHO_AM_I = 0x02,
REQUEST_DEVICE_CONFIGURATION = 0x08,
RECEIVE_DEVICE_CONFIGURATION = 0x09,
REQUEST_GLOBAL_PARAMETERS = 0x10,
RECEIVE_GLOBAL_PARAMETERS = 0x11,
REQUEST_BULK_DUMP = 0x18,
RECEIVE_BULK_DUMP_START = 0x19,
RECEIVE_BULK_DUMP_END = 0x1B,
REQUEST_PRESET_NAMES = 0x21,
RECEIVE_PRESET_NAMES = 0x22,
REQUEST_PRESET_NAME = 0x28,
RECEIVE_PRESET_NAME = 0x29,
REQUEST_PRESET = 0x2A,
RECEIVE_PRESET_START = 0x2B,
RECEIVE_PRESET_END = 0x2C,
RECEIVE_PRESET_PARAMETERS = 0x2D,
LOAD_EDIT_BUFFER_PRESET = 0x38, /* version 0 only
use move preset in later versions */
MOVE_PRESET = 0x39,
REQUEST_MODIFIER_LINKABLE_LIST = 0x3A,
RECEIVE_MOFIFIER_LINKABLE_LIST = 0x3B,
REQUEST_PARAMETER_VALUE = 0x40,
RECEIVE_PARAMETER_VALUE = 0x41,
/* version 1 and later */
REQUEST_OBJECT_NAMES = 0x50,
RECEIVE_OBJECT_NAMES = 0x51,
REQUEST_OBJECT_NAME = 0x52,
RECEIVE_OBJECT_NAME = 0x53,
REQUEST_OBJECT = 0x54,
RECEIVE_OBJECT = 0x55,
MOVE_OBJECT = 0x56,
DELETE_OBJECT = 0x57,
REQUEST_TABLE = 0x5A,
RECEIVE_TABLE = 0x5B,
RECEIVE_DEVICE_NOTIFICATION = 0x70,
ACK = 0x7E,
NACK = 0x7F
};
void send_message(gint procedure, gchar *data, gint len);
void append_value(GString *msg, guint value);
void set_option(guint id, guint position, guint value);
void switch_user_preset(int x);
void switch_system_preset(int x);
void switch_preset(guint bank, guint x);
void store_preset_name(int x, const gchar *name);
void set_preset_level(int level);
GStrv query_preset_names(gchar bank);
GString *get_current_preset();
#endif /* GDIGI_H */

478
gui.c
View File

@@ -18,27 +18,111 @@
#include "gdigi.h"
#include "gui.h"
#include "effects.h"
#include "preset.h"
extern EffectList effects[];
extern int n_effects;
static gboolean allow_send = FALSE;
void show_error_message(GtkWidget *parent, gchar *message)
{
g_return_if_fail(message != NULL);
GtkWidget *msg = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
message);
gtk_dialog_run(GTK_DIALOG(msg));
gtk_widget_destroy(msg);
}
typedef struct {
GtkWidget *widget;
gint id;
gint position;
/* used for combo boxes, if widget isn't combo box, then both value and x are -1 */
gint value; /* effect type value */
gint x; /* combo box item number */
} WidgetListElem;
void value_changed_option_cb(GtkSpinButton *spinbutton, EffectSettings *setting)
{
g_return_if_fail(setting != NULL);
int val = gtk_spin_button_get_value_as_int(spinbutton);
set_option(setting->option, setting->position, val);
if (allow_send) {
gint val = gtk_spin_button_get_value_as_int(spinbutton);
set_option(setting->option, setting->position, val);
}
}
void toggled_cb(GtkToggleButton *button, Effect *effect)
{
g_return_if_fail(effect != NULL);
guint val = gtk_toggle_button_get_active(button);
set_option(effect->option, effect->position, val);
if (allow_send) {
guint val = gtk_toggle_button_get_active(button);
set_option(effect->option, effect->position, val);
}
}
GtkWidget *create_table(EffectSettings *settings, gint amt)
static void widget_list_add(GList **list, GtkWidget *widget, gint id, gint position, gint value, gint x)
{
WidgetListElem *el;
el = g_malloc(sizeof(WidgetListElem));
el->widget = widget;
el->id = id;
el->position = position;
el->value = value;
el->x = x;
*list = g_list_prepend(*list, el);
}
static void apply_widget_setting(WidgetListElem *el, SettingParam *param)
{
if ((el->id == param->id) && (el->position == param->position)) {
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 { /* combo box */
if (el->value == param->value)
gtk_combo_box_set_active(GTK_COMBO_BOX(el->widget), el->x);
}
}
}
static void apply_preset_to_gui(GList *list, Preset *preset)
{
allow_send = FALSE;
GList *iter = preset->params;
while (iter) {
SettingParam *param = iter->data;
iter = iter->next;
if (param != NULL)
g_list_foreach(list, (GFunc)apply_widget_setting, param);
}
allow_send = TRUE;
}
static void apply_current_preset(GList *list)
{
GString *msg = get_current_preset();
Preset *preset = create_preset_from_data(msg);
g_string_free(msg, TRUE);
apply_preset_to_gui(list, preset);
preset_free(preset);
}
GtkWidget *create_table(GList **list, EffectSettings *settings, gint amt)
{
GtkWidget *table, *label, *widget;
GtkObject *adj;
@@ -48,10 +132,10 @@ GtkWidget *create_table(EffectSettings *settings, gint amt)
for (x = 0; x<amt; x++) {
label = gtk_label_new(settings[x].label);
adj = gtk_adjustment_new(0.0, settings[x].min, settings[x].max, 1.0, 1.0, 1.0);
adj = gtk_adjustment_new(0.0, settings[x].min, settings[x].max, 1.0, 1.0, 0.0);
widget = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1.0, 0);
g_signal_connect(G_OBJECT(widget), "value-changed", G_CALLBACK(value_changed_option_cb), &settings[x]);
widget_list_add(list, widget, settings[x].option, settings[x].position, -1, -1);
gtk_table_attach(GTK_TABLE(table), label, 0, 1, x, x+1, GTK_SHRINK, GTK_SHRINK, 2, 2);
gtk_table_attach(GTK_TABLE(table), widget, 1, 2, x, x+1, GTK_SHRINK, GTK_SHRINK, 2, 2);
}
@@ -59,11 +143,12 @@ GtkWidget *create_table(EffectSettings *settings, gint amt)
return table;
}
GtkWidget *create_on_off_button(Effect *effect)
GtkWidget *create_on_off_button(GList **list, Effect *effect)
{
GtkWidget *button = gtk_toggle_button_new_with_label(effect->label);
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);
return button;
}
@@ -100,7 +185,7 @@ void combo_box_changed_cb(GtkComboBox *widget, gpointer data)
settings = g_object_get_data(G_OBJECT(widget), name);
g_free(name);
if (settings != NULL)
if (settings != NULL && allow_send)
set_option(settings->option, settings->position, settings->id);
child = g_object_get_data(G_OBJECT(widget), "active_child");
@@ -113,7 +198,7 @@ void combo_box_changed_cb(GtkComboBox *widget, gpointer data)
}
}
GtkWidget *create_widget_container(EffectGroup *group, gint amt)
GtkWidget *create_widget_container(GList **list, EffectGroup *group, gint amt)
{
GtkWidget *vbox;
GtkWidget *widget;
@@ -136,7 +221,7 @@ GtkWidget *create_widget_container(EffectGroup *group, gint amt)
gtk_combo_box_append_text(GTK_COMBO_BOX(combo_box), group[x].label);
cmbox_no++;
widget = create_table(group[x].settings, group[x].settings_amt);
widget = create_table(list, group[x].settings, group[x].settings_amt);
g_object_ref_sink(widget);
settings = g_malloc(sizeof(EffectSettingsGroup));
@@ -144,12 +229,13 @@ GtkWidget *create_widget_container(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);
name = g_strdup_printf("SettingsGroup%d", cmbox_no);
g_object_set_data_full(G_OBJECT(combo_box), name, settings, ((GDestroyNotify)effect_settings_group_free));
g_free(name);
} else {
widget = create_table(group[x].settings, group[x].settings_amt);
widget = create_table(list, group[x].settings, group[x].settings_amt);
gtk_container_add(GTK_CONTAINER(vbox), widget);
}
}
@@ -157,7 +243,7 @@ GtkWidget *create_widget_container(EffectGroup *group, gint amt)
return vbox;
};
GtkWidget *create_vbox(Effect *widgets, gint amt)
GtkWidget *create_vbox(GList **list, Effect *widgets, gint amt)
{
GtkWidget *vbox;
GtkWidget *hbox;
@@ -171,10 +257,10 @@ GtkWidget *create_vbox(Effect *widgets, gint amt)
gtk_box_set_homogeneous(GTK_BOX(hbox), TRUE);
for (x = 0; x<amt; x++) {
widget = create_on_off_button(&widgets[x]);
widget = create_on_off_button(list, &widgets[x]);
gtk_box_pack_start(GTK_BOX(hbox), widget, TRUE, TRUE, 2);
table = create_widget_container(widgets[x].group, widgets[x].group_amt);
table = create_widget_container(list, widgets[x].group, widgets[x].group_amt);
gtk_box_pack_start(GTK_BOX(hbox), table, TRUE, TRUE, 2);
}
@@ -182,28 +268,386 @@ GtkWidget *create_vbox(Effect *widgets, gint amt)
return vbox;
}
enum {
PRESET_NAME_COLUMN = 0,
PRESET_NUMBER_COLUMN,
PRESET_BANK_COLUMN,
NUM_COLUMNS
};
void row_activate_cb(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, GtkTreeModel *model) {
GtkTreeIter iter;
gint id;
gint bank;
gtk_tree_model_get_iter(model, &iter, path);
gtk_tree_model_get(model, &iter, PRESET_NUMBER_COLUMN, &id, PRESET_BANK_COLUMN, &bank, -1);
if ((bank != -1) && (id != -1)) {
GList **list = g_object_get_data(G_OBJECT(treeview), "widgets-list");
switch_preset(bank, id);
if (*list != NULL)
apply_current_preset(*list);
}
}
static void fill_store_with_presets(GtkTreeStore *model, guint bank, gchar *name)
{
GtkTreeIter iter;
GtkTreeIter child_iter;
int x;
GStrv presets = query_preset_names(bank);
gtk_tree_store_append(model, &iter, NULL);
gtk_tree_store_set(model, &iter,
PRESET_NAME_COLUMN, name,
PRESET_NUMBER_COLUMN, -1,
PRESET_BANK_COLUMN, -1,
-1);
for (x=0; x<g_strv_length(presets); x++) {
gtk_tree_store_append(model, &child_iter, &iter);
gtk_tree_store_set(model, &child_iter,
PRESET_NAME_COLUMN, presets[x],
PRESET_NUMBER_COLUMN, x,
PRESET_BANK_COLUMN, bank,
-1);
}
g_strfreev(presets);
}
static void fill_store(GtkTreeStore *model)
{
fill_store_with_presets(model, PRESETS_USER, "User Presets");
fill_store_with_presets(model, PRESETS_SYSTEM, "System Presets");
}
GtkWidget *create_preset_tree(GList **list)
{
GtkWidget *treeview;
GtkTreeStore *store;
GtkCellRenderer *renderer;
store = gtk_tree_store_new(NUM_COLUMNS, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT);
fill_store(store);
treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
g_object_unref(store);
renderer = gtk_cell_renderer_text_new();
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview),
-1, "Preset name",
renderer, "text",
PRESET_NAME_COLUMN, NULL);
g_object_set(G_OBJECT(treeview), "headers-visible", FALSE, NULL);
g_signal_connect(G_OBJECT(treeview), "realize", G_CALLBACK(gtk_tree_view_expand_all), NULL);
g_signal_connect(G_OBJECT(treeview), "row-activated", G_CALLBACK(row_activate_cb), GTK_TREE_MODEL(store));
g_object_set_data(G_OBJECT(treeview), "widgets-list", list);
return treeview;
}
static void show_store_preset_window(GtkWidget *window, gchar *default_name)
{
GtkWidget *dialog, *cmbox, *entry, *table, *label;
GStrv names;
int x;
dialog = gtk_dialog_new_with_buttons("Store preset",
GTK_WINDOW(window),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
NULL);
table = gtk_table_new(2, 2, FALSE);
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), table);
cmbox = gtk_combo_box_new_text();
names = query_preset_names(PRESETS_USER);
for (x=0; x<g_strv_length(names); x++) {
gchar *title = g_strdup_printf("%d - %s", x+1, names[x]);
gtk_combo_box_append_text(GTK_COMBO_BOX(cmbox), title);
g_free(title);
}
g_strfreev(names);
gtk_table_attach_defaults(GTK_TABLE(table), cmbox, 1, 2, 0, 1);
entry = gtk_entry_new();
if (default_name != NULL)
gtk_entry_set_text(GTK_ENTRY(entry), default_name);
gtk_table_attach_defaults(GTK_TABLE(table), entry, 1, 2, 1, 2);
label = gtk_label_new("Preset slot:");
gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
label = gtk_label_new("Preset name:");
gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2);
gtk_widget_show_all(GTK_DIALOG(dialog)->vbox);
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
gint number = gtk_combo_box_get_active(GTK_COMBO_BOX(cmbox));
if (number != -1) {
store_preset_name(number, gtk_entry_get_text(GTK_ENTRY(entry)));
}
}
gtk_widget_destroy(dialog);
}
static void action_store_cb(GtkAction *action)
{
GtkWidget *window = g_object_get_data(G_OBJECT(action), "window");
show_store_preset_window(window, NULL);
}
static void action_show_about_dialog_cb(GtkAction *action)
{
static const gchar * const authors[] = {
"Tomasz Moń <desowin@gmail.com>",
NULL
};
static const gchar copyright[] = "Copyright \xc2\xa9 2009 Tomasz Moń";
static const gchar website[] = "http://desowin.org/gdigi/";
GtkWidget *window = g_object_get_data(G_OBJECT(action), "window");
gtk_show_about_dialog(GTK_WINDOW(window),
"authors", authors,
"copyright", copyright,
"website", website,
NULL);
}
typedef struct {
gchar *name;
gchar *suffix;
} SupportedFileTypes;
static SupportedFileTypes file_types[] = {
{"RP250Preset", "*.rp250p"},
};
static guint n_file_types = G_N_ELEMENTS(file_types);
static void action_open_preset_cb(GtkAction *action)
{
static GtkWidget *dialog = NULL;
if (dialog != NULL)
return;
GtkWidget *window = g_object_get_data(G_OBJECT(action), "window");
GList **list = g_object_get_data(G_OBJECT(action), "widget-list");
dialog = gtk_file_chooser_dialog_new("Open Preset", GTK_WINDOW(window),
GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
NULL);
GtkFileFilter *filter;
filter = gtk_file_filter_new();
gtk_file_filter_set_name(filter, "All Supported Types");
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
int x;
for (x=0; x<n_file_types; x++) {
GtkFileFilter *current_filter = gtk_file_filter_new();
gtk_file_filter_set_name(current_filter, file_types[x].name);
gtk_file_filter_add_pattern(current_filter, file_types[x].suffix);
gtk_file_filter_add_pattern(filter, file_types[x].suffix);
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), current_filter);
}
gboolean loaded = FALSE;
while (!loaded && gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
Preset *preset = create_preset_from_xml_file(filename);
if (preset != NULL) {
if (list != NULL)
apply_preset_to_gui(*list, preset);
gtk_widget_hide(dialog);
GString *msg = g_string_sized_new(500);
GList *iter = preset->params;
gint len = g_list_length(iter);
g_string_append_printf(msg, "%c%c",
((len & 0xFF00) >> 8),
(len & 0xFF));
while (iter) {
SettingParam *param = iter->data;
iter = iter->next;
g_string_append_printf(msg, "%c%c%c",
((param->id & 0xFF00) >> 8),
(param->id & 0xFF),
param->position);
append_value(msg, param->value);
};
GString *start = g_string_new(NULL);
g_string_append_printf(start,
"%c%c%s%c%c%c",
PRESETS_EDIT_BUFFER, 0,
preset->name, 0 /* NULL terminated string */,
0 /* modified */, 2 /* messages to follow */);
send_message(RECEIVE_PRESET_START, start->str, start->len);
send_message(RECEIVE_PRESET_PARAMETERS, msg->str, msg->len);
send_message(RECEIVE_PRESET_END, NULL, 0);
show_store_preset_window(window, preset->name);
g_string_free(start, TRUE);
g_string_free(msg, TRUE);
preset_free(preset);
loaded = TRUE;
}
g_free(filename);
}
gtk_widget_destroy(dialog);
dialog = NULL;
}
static void widget_list_free(GList *list)
{
GList *iter;
for (iter = list; iter; iter = iter->next) {
g_free(iter->data);
}
g_list_free(list);
}
static void action_quit_cb(GtkAction *action)
{
GtkWidget *window = g_object_get_data(G_OBJECT(action), "window");
GList **list = g_object_get_data(G_OBJECT(action), "widget-list");
widget_list_free(*list);
*list = NULL;
gtk_widget_destroy(window);
gtk_main_quit();
}
static GtkActionEntry entries[] = {
{"File", NULL, "_File"},
{"Preset", NULL, "_Preset"},
{"Help", NULL, "_Help"},
{"Open", GTK_STOCK_OPEN, "_Open", "<control>O", "Open preset file", G_CALLBACK(action_open_preset_cb)},
{"Quit", GTK_STOCK_QUIT, "_Quit", "<control>Q", "Quit", G_CALLBACK(action_quit_cb)},
{"Store", NULL, "_Store", "<control>S", "Store", G_CALLBACK(action_store_cb)},
{"About", GTK_STOCK_ABOUT, "_About", "<control>A", "About", G_CALLBACK(action_show_about_dialog_cb)},
};
static guint n_entries = G_N_ELEMENTS(entries);
static const gchar *menu_info =
"<ui>"
" <menubar name='MenuBar'>"
" <menu action='File'>"
" <menuitem action='Open'/>"
" <separator/>"
" <menuitem action='Quit'/>"
" </menu>"
" <menu action='Preset'>"
" <menuitem action='Store'/>"
" </menu>"
" <menu action='Help'>"
" <menuitem action='About'/>"
" </menu>"
" </menubar>"
"</ui>";
static void add_action_data(GtkUIManager *ui, const gchar *path, GtkWidget *window, GList **list)
{
GtkAction *action;
action = gtk_ui_manager_get_action(ui, path);
g_object_set_data(G_OBJECT(action), "window", window);
g_object_set_data(G_OBJECT(action), "widget-list", list);
}
static void add_menubar(GList **list, GtkWidget *window, GtkWidget *vbox)
{
GtkUIManager *ui;
GtkActionGroup *actions;
GError *error = NULL;
actions = gtk_action_group_new("Actions");
gtk_action_group_add_actions(actions, entries, n_entries, NULL);
ui = gtk_ui_manager_new();
gtk_ui_manager_insert_action_group(ui, actions, 0);
g_object_unref(actions);
gtk_window_add_accel_group(GTK_WINDOW(window), gtk_ui_manager_get_accel_group(ui));
if (!gtk_ui_manager_add_ui_from_string(ui, menu_info, -1, &error)) {
g_message("building menus failed: %s", error->message);
g_error_free(error);
error = NULL;
}
gtk_box_pack_start(GTK_BOX(vbox),
gtk_ui_manager_get_widget(ui, "/MenuBar"),
FALSE, FALSE, 0);
add_action_data(ui, "/MenuBar/File/Quit", window, list);
add_action_data(ui, "/MenuBar/File/Open", window, list);
add_action_data(ui, "/MenuBar/Preset/Store", window, list);
add_action_data(ui, "/MenuBar/Help/About", window, list);
g_object_unref(ui);
}
void create_window()
{
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *hbox;
GtkWidget *widget;
GtkWidget *sw; /* scrolled window to carry preset treeview */
static GList *list = NULL; /* widget list (every data element is WidgetListElem) */
gint x;
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "gdigi");
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(window), vbox);
add_menubar(&list, window, vbox);
hbox = gtk_hbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(vbox), hbox);
sw = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
gtk_box_pack_start(GTK_BOX(hbox), sw, FALSE, FALSE, 0);
widget = create_preset_tree(&list);
gtk_container_add(GTK_CONTAINER(sw), widget);
vbox = gtk_vbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 2);
for (x = 0; x<n_effects; x++) {
if ((x % 2) == 0) {
if ((x % 3) == 0) {
hbox = gtk_hbox_new(TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 2);
}
widget = create_vbox(effects[x].effect, effects[x].amt);
widget = create_vbox(&list, effects[x].effect, effects[x].amt);
gtk_box_pack_start(GTK_BOX(hbox), widget, TRUE, TRUE, 2);
}
apply_current_preset(list);
gtk_widget_show_all(window);
g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(gtk_main_quit), NULL);

6
gui.h
View File

@@ -14,4 +14,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses>.
*/
#ifndef GDIGI_GUI_H
#define GDIGI_GUI_H
void show_error_message(GtkWidget *parent, gchar *message);
void create_window();
#endif /* GDIGI_GUI_H */

229
preset.c Normal file
View File

@@ -0,0 +1,229 @@
/*
* Copyright (c) 2009 Tomasz Moń <desowin@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; under version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses>.
*/
#include <gio/gio.h>
#include <expat.h>
#include <string.h>
#include "preset.h"
enum {
PARSER_TYPE_NOT_SET = -1,
PARSER_TYPE_PRESET_NAME = 0,
PARSER_TYPE_PARAM_ID,
PARSER_TYPE_PARAM_POSITION,
PARSER_TYPE_PARAM_VALUE,
PARSER_TYPE_PARAM_NAME,
PARSER_TYPE_PARAM_TEXT
};
typedef struct {
int depth;
int id;
Preset *preset;
} AppData;
static void XMLCALL start(void *data, const char *el, const char **attr) {
AppData *ad = (AppData *) data;
ad->id = PARSER_TYPE_NOT_SET;
if (g_strcmp0(el, "Name") == 0) {
if (ad->depth == 1) {
ad->id = PARSER_TYPE_PRESET_NAME;
} else if (ad->depth == 3) {
ad->id = PARSER_TYPE_PARAM_NAME;
}
}
if (g_strcmp0(el, "Params") == 0) {
if (ad->preset->params != NULL)
g_message("Params aleady exists!");
} else if (g_strcmp0(el, "Param") == 0) {
SettingParam *param = (SettingParam *)g_malloc(sizeof(SettingParam));
param->id = -1;
param->position = -1;
param->value = -1;
ad->preset->params = g_list_prepend(ad->preset->params, param);
} else if (g_strcmp0(el, "ID") == 0) {
ad->id = PARSER_TYPE_PARAM_ID;
} else if (g_strcmp0(el, "Position") == 0) {
ad->id = PARSER_TYPE_PARAM_POSITION;
} else if (g_strcmp0(el, "Value") == 0) {
ad->id = PARSER_TYPE_PARAM_VALUE;
} else if (g_strcmp0(el, "Text") == 0) {
ad->id = PARSER_TYPE_PARAM_TEXT;
}
ad->depth++;
}
static void XMLCALL end(void *data, const char *el) {
AppData *ad = (AppData *) data;
ad->depth--;
ad->id = PARSER_TYPE_NOT_SET;
}
static void XMLCALL text_cb(void *data, const char* text, int len)
{
AppData *ad = (AppData *) data;
if ((ad == NULL) || (ad->preset == NULL))
return;
if (ad->id == PARSER_TYPE_PRESET_NAME) {
if (ad->preset->name != NULL)
g_free(ad->preset->name);
ad->preset->name = g_strndup(text, len);
}
if (ad->preset->params == NULL)
return;
SettingParam *param = (SettingParam *) ad->preset->params->data;
if (param == NULL)
return;
gchar *value = g_strndup(text, len);
switch (ad->id) {
case PARSER_TYPE_PARAM_ID:
param->id = atoi(value);
break;
case PARSER_TYPE_PARAM_POSITION:
param->position = atoi(value);
break;
case PARSER_TYPE_PARAM_VALUE:
param->value = atoi(value);
break;
}
g_free(value);
}
/*
Parses preset file
On success returns Preset which must be freed using preset_free, or NULL on error
*/
Preset *create_preset_from_xml_file(gchar *filename)
{
GFile *file;
GError *error = NULL;
gchar *contents;
file = g_file_new_for_path(filename);
if (g_file_get_contents(filename, &contents, NULL, &error) == FALSE) {
g_message("Failed to get %s contents: %s", filename, error->message);
g_error_free(error);
g_object_unref(file);
return NULL;
}
AppData *ad = (AppData *) g_malloc(sizeof(AppData));
ad->depth = 0;
ad->preset = g_malloc(sizeof(Preset));
ad->preset->name = NULL;
ad->preset->params = NULL;
ad->id = PARSER_TYPE_NOT_SET;
XML_Parser p;
p = XML_ParserCreate(NULL);
XML_SetUserData(p, (void *) ad);
XML_SetElementHandler(p, start, end);
XML_SetCharacterDataHandler(p, text_cb);
if (XML_Parse(p, contents, strlen(contents), XML_TRUE) != XML_STATUS_OK) {
g_warning("Parse error at line %d:\n%s",
(int)XML_GetCurrentLineNumber(p),
XML_ErrorString(XML_GetErrorCode(p)));
preset_free(ad->preset);
g_free(ad);
g_free(contents);
g_object_unref(file);
return NULL;
}
Preset *preset = ad->preset;
preset->params = g_list_reverse(preset->params);
XML_ParserFree(p);
g_free(ad);
g_free(contents);
g_object_unref(file);
return preset;
}
Preset *create_preset_from_data(GString *data)
{
gint total;
gint n;
gint id;
gint position;
guint value;
gint x;
gint tmp;
x = 0x09;
n = 0;
total = (unsigned char)data->str[x];
x++;
Preset *preset = g_malloc(sizeof(Preset));
preset->name = NULL; /* TODO */
preset->params = NULL;
do {
id = ((unsigned char)data->str[x] << 8) | (unsigned char)data->str[x+1];
position = (unsigned char)data->str[x+2];
x+=3;
value = data->str[x];
x++;
if (value > 0x80) {
tmp = value & 0x7F;
value = 0;
gint i;
for (i=0; i<tmp; i++) {
value |= ((unsigned char)data->str[x+i] << (8*(tmp-i-1)));
}
x+=tmp;
}
n++;
SettingParam *param = (SettingParam *)g_malloc(sizeof(SettingParam));
param->id = id;
param->position = position;
param->value = value;
preset->params = g_list_prepend(preset->params, param);
g_message("%d ID %d Position %d Value %d", n, id, position, value);
} while ((x < data->len) && n<total);
g_message("TOTAL %d", total);
preset->params = g_list_reverse(preset->params);
return preset;
}
void preset_free(Preset *preset)
{
g_return_if_fail(preset != NULL);
if (preset->params != NULL) {
g_list_foreach(preset->params, (GFunc)g_free, NULL);
g_list_free(preset->params);
}
if (preset->name != NULL)
g_free(preset->name);
g_free(preset);
}

37
preset.h Normal file
View File

@@ -0,0 +1,37 @@
/*
* Copyright (c) 2009 Tomasz Moń <desowin@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; under version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses>.
*/
#ifndef GDIGI_PRESET_H
#define GDIGI_PRESET_H
#include <glib.h>
typedef struct {
int id;
int position;
int value;
} SettingParam;
typedef struct {
gchar *name;
GList *params;
} Preset;
Preset *create_preset_from_xml_file(gchar *filename);
Preset *create_preset_from_data(GString *data);
void preset_free(Preset *preset);
#endif /* GDIGI_PRESET_H */

246
tests.c
View File

@@ -206,10 +206,10 @@ void test_presets()
int x;
for (x=0; x<=60; x++)
switch_user_preset(x);
switch_preset(PRESETS_USER, x);
for (x=0; x<=60; x++)
switch_system_preset(x);
switch_preset(PRESETS_SYSTEM, x);
for (x=0; x<=99; x++)
set_preset_level(x);
@@ -620,247 +620,6 @@ void test_reverb()
set_option(REVERB_ON_OFF, REVERB_POSITION, 0);
}
void test_exp()
{
int x;
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_NONE);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_PICKUP_ENABLE);
for (x=0; x<=1; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=1; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_PIKCUP_TYPE);
for (x=0; x<=1; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=1; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_COMP_ENABLE);
for (x=0; x<=1; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=1; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_COMP_SUST);
for (x=0; x<=99; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=99; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_COMP_TONE);
for (x=0; x<=99; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=99; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_COMP_LEVEL);
for (x=0; x<=99; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=99; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_COMP_ATTACK);
for (x=0; x<=99; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=99; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_DIST_ENABLE);
for (x=0; x<=1; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=1; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_DIST_DISTORTION);
for (x=0; x<=99; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=99; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_DIST_FILTER);
for (x=0; x<=99; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=99; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_DIST_VOLUME);
for (x=0; x<=99; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=99; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_AMP_ENABLE);
for (x=0; x<=1; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=1; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_AMP_GAIN);
for (x=0; x<=99; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=99; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_AMP_LEVEL);
for (x=0; x<=99; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=99; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_EQ_ENABLE);
for (x=0; x<=1; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=1; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_EQ_BASS);
for (x=0; x<=24; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=24; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_EQ_MID);
for (x=0; x<=24; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=24; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_EQ_TREB);
for (x=0; x<=24; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=24; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_GATE_ENABLE);
for (x=0; x<=1; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=1; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_GATE_THRESHOLD);
for (x=0; x<=99; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=99; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_GATE_ATTACK);
for (x=0; x<=99; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=99; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_GATE_RELEASE);
for (x=0; x<=99; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=99; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_GATE_ATTN);
for (x=0; x<=99; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=99; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_CHORUSFX_ENABLE);
for (x=0; x<=1; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=1; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_PHASER_SPEED);
for (x=0; x<=99; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=99; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_PHASER_DEPTH);
for (x=0; x<=99; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=99; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_PHASER_REGEN);
for (x=0; x<=99; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=99; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_PHASER_WAVEFORM);
for (x=0; x<=2; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=2; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_PHASER_LEVEL);
for (x=0; x<=99; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=99; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_DELAY_ENABLE);
for (x=0; x<=1; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=1; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_DELAY_TIME);
for (x=0; x<=139; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=139; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_DELAY_REPEATS);
for (x=0; x<=100; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=100; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_DELAY_LEVEL);
for (x=0; x<=99; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=99; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_DELAY_DUCK_THRESH);
for (x=0; x<=99; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=99; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_DELAY_DUCK_LEVEL);
for (x=0; x<=99; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=99; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_REVERB_ENABLE);
for (x=0; x<=1; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=1; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_REVERB_LEVEL);
for (x=0; x<=99; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=99; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_VOLUME_PRE_FX);
for (x=0; x<=99; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=99; x++)
set_option(EXP_MAX, EXP_POSITION, x);
set_option(EXP_TYPE, EXP_POSITION, EXP_TYPE_VOLUME_POST_FX);
for (x=0; x<=99; x++)
set_option(EXP_MIN, EXP_POSITION, x);
for (x=0; x<=99; x++)
set_option(EXP_MAX, EXP_POSITION, x);
}
void test_usb()
{
int x;
@@ -884,6 +643,5 @@ void test_all()
test_chorusfx();
test_delay();
test_reverb();
test_exp();
test_usb();
}

View File

@@ -14,6 +14,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses>.
*/
#ifndef GDIGI_TESTS_H
#define GDIGI_TESTS_H
#include "gdigi.h"
void test_wah();
@@ -26,6 +29,7 @@ void test_noisegate();
void test_chorusfx();
void test_delay();
void test_reverb();
void test_exp();
void test_usb();
void test_all();
#endif /* GDIGI_TESTS_H */