Compare commits
91 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba04930133 | ||
|
|
18f137636d | ||
|
|
eba8bbe5aa | ||
|
|
7a6e3b159c | ||
|
|
cc85da9c71 | ||
|
|
9586f6cd31 | ||
|
|
4a7ab848e7 | ||
|
|
2703e79d39 | ||
|
|
dbab804d52 | ||
|
|
c3f82416f5 | ||
|
|
145b41cb6c | ||
|
|
26d1db9e4f | ||
|
|
cc311f4f18 | ||
|
|
d85e83c89e | ||
|
|
55b9b08230 | ||
|
|
400e221a4f | ||
|
|
5b93c91bfe | ||
|
|
cbd07a9709 | ||
|
|
def4917a07 | ||
|
|
e9c0ed8b38 | ||
|
|
400a7d41f8 | ||
|
|
40a9d06e4c | ||
|
|
e820ce0cc4 | ||
|
|
ebc603143e | ||
|
|
c74290d8e1 | ||
|
|
295e932bf1 | ||
|
|
1a65deb8d5 | ||
|
|
4509c14bbc | ||
|
|
d7f10eb509 | ||
|
|
b1a8d69dba | ||
|
|
20769ace01 | ||
|
|
2633bac5d8 | ||
|
|
af1d3a2906 | ||
|
|
06fd3eee66 | ||
|
|
acb1c1e273 | ||
|
|
7bf55352b8 | ||
|
|
6a1d1de390 | ||
|
|
b798d6ee39 | ||
|
|
ba810bf4f8 | ||
|
|
24a1c2718b | ||
|
|
31a635839a | ||
|
|
d7b3f7a3d6 | ||
|
|
6512696240 | ||
|
|
f1359d18e4 | ||
|
|
85ce157bb8 | ||
|
|
6daaf47cd8 | ||
|
|
3a849de954 | ||
|
|
a06c5dc07e | ||
|
|
29124043ba | ||
|
|
e93e6bd16b | ||
|
|
f7ddd5e0d6 | ||
|
|
6a082acc53 | ||
|
|
1abcc82829 | ||
|
|
c964d38c17 | ||
|
|
12c2ccc87f | ||
|
|
a6d07fd802 | ||
|
|
215683b167 | ||
|
|
741482afd4 | ||
|
|
991527418a | ||
|
|
96317d5ac5 | ||
|
|
d24cc97f5d | ||
|
|
cac7e74d71 | ||
|
|
74583e9a7c | ||
|
|
03c3c48ecf | ||
|
|
aa2cc7bbb1 | ||
|
|
ec14a41869 | ||
|
|
9778dc47c3 | ||
|
|
71c3a1e66f | ||
|
|
bdb35ddf54 | ||
|
|
4ca140ab48 | ||
|
|
d2f821eee1 | ||
|
|
e607c6cf37 | ||
|
|
dc66db841a | ||
|
|
e80683aea2 | ||
|
|
b7d2d7d1c5 | ||
|
|
cd5d7387f3 | ||
|
|
8a39a178c6 | ||
|
|
40ebcfaf16 | ||
|
|
de68d0449f | ||
|
|
d280bf1ca6 | ||
|
|
b245e1bac6 | ||
|
|
8d7fffb6d1 | ||
|
|
f8e35ff685 | ||
|
|
3f717a51cd | ||
|
|
90df427200 | ||
|
|
322c59032e | ||
|
|
1b1919649e | ||
|
|
e7c7efe857 | ||
|
|
17b067f853 | ||
|
|
8ec3d6579c | ||
|
|
5bd6f8fc2c |
12
HACKING
12
HACKING
@@ -3,7 +3,7 @@ In general everything brings down to figure out:
|
||||
-Position
|
||||
-Possible value range
|
||||
|
||||
There seems to be two possible ways to figure that out.
|
||||
There seems to be three possible ways to figure that out.
|
||||
1) Use USB sniffer together with X-Edit
|
||||
Once you set up X-Edit and usb sniffer, set some option.
|
||||
USB sniffer should report something like this being sent to device:
|
||||
@@ -66,3 +66,13 @@ There seems to be two possible ways to figure that out.
|
||||
save new patch
|
||||
check patch file and note the change
|
||||
while you don't have all possible values
|
||||
3) Use gdigi
|
||||
After starting gdigi turn the knobs on your device.
|
||||
Check out console output, you should notice something like this:
|
||||
** Message: Received parameter change ID: 210 Position: 4 Value: 0
|
||||
ID is ID, Position is Position and Value is one of possible values.
|
||||
To get all possible values keep turning knobs and watch the output.
|
||||
If you change effect type usually there's more messages - where,
|
||||
usually the first one is type change, and rest are default values.
|
||||
This way you *CANNOT* gather all information (there're X-Edit only
|
||||
controlled values, check device manual for more information).
|
||||
|
||||
49
Makefile
49
Makefile
@@ -1,28 +1,43 @@
|
||||
CC = gcc
|
||||
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 gio-2.0 gtk+-2.0 alsa` -lexpat
|
||||
EXTRA_CFLAGS ?=
|
||||
EXTRA_LDFLAGS ?=
|
||||
CFLAGS := $(shell pkg-config --cflags glib-2.0 gio-2.0 gtk+-2.0) -Wall -g -ansi -std=c99 $(EXTRA_CFLAGS)
|
||||
LDFLAGS := $(shell pkg-config --libs glib-2.0 gio-2.0 gtk+-2.0 gthread-2.0 alsa) -lexpat $(EXTRA_LDFLAGS)
|
||||
OBJECTS = gdigi.o gui.o effects.o preset.o gtkknob.o
|
||||
DEPFILES = $(foreach m,$(OBJECTS:.o=),.$(m).m)
|
||||
|
||||
.SUFFIXES : .o .c
|
||||
.c.o :
|
||||
.PHONY : clean distclean all
|
||||
%.o : %.c
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
.%.m : %.c
|
||||
$(CC) $(CFLAGS) -M -MF $@ -MG $<
|
||||
|
||||
all: gdigi
|
||||
|
||||
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: $(OBJECTS)
|
||||
$(CC) $(LDFLAGS) -o $@ $+
|
||||
|
||||
gdigi.o: gdigi.c
|
||||
|
||||
tests.o: tests.c
|
||||
|
||||
gui.o: gui.c
|
||||
|
||||
effects.o: effects.c
|
||||
|
||||
preset.o: preset.c
|
||||
knob.h: knob.png
|
||||
gdk-pixbuf-csource --name=knob_pixbuf knob.png > $@
|
||||
|
||||
clean:
|
||||
rm *.o
|
||||
rm -f *.o
|
||||
rm -f knob.h
|
||||
|
||||
distclean : clean
|
||||
rm -f .*.m
|
||||
rm -f gdigi
|
||||
|
||||
NODEP_TARGETS := clean distclean
|
||||
depinc := 1
|
||||
ifneq (,$(filter $(NODEP_TARGETS),$(MAKECMDGOALS)))
|
||||
depinc := 0
|
||||
endif
|
||||
ifneq (,$(fitler-out $(NODEP_TARGETS),$(MAKECMDGOALS)))
|
||||
depinc := 1
|
||||
endif
|
||||
|
||||
ifeq ($(depinc),1)
|
||||
-include $(DEPFILES)
|
||||
endif
|
||||
|
||||
12
TODO
12
TODO
@@ -1,8 +1,6 @@
|
||||
-make complete gui
|
||||
-cabinet models
|
||||
-tone library
|
||||
-effects library
|
||||
-effects level
|
||||
-make complete gui (expression pedal settings, usb settings, effect level, preset level)
|
||||
-handling presets (saving, exporting to xml patches)
|
||||
-buildsystem
|
||||
-expression pedal settings
|
||||
-buildsystem (install knob.png to share dir, don't use inline knob pixbuf)
|
||||
-various fixes to MIDI IN messages handling
|
||||
-guess device port when user doesn't explicitly provide it (don't use hardcoded "hw:1,0,0")
|
||||
-optimizations
|
||||
|
||||
78
effects.h
78
effects.h
@@ -17,36 +17,76 @@
|
||||
#ifndef GDIGI_EFFECTS_H
|
||||
#define GDIGI_EFFECTS_H
|
||||
|
||||
#include <glib/gtypes.h>
|
||||
#include <glib.h>
|
||||
|
||||
typedef struct {
|
||||
char *label; /* Parameter name */
|
||||
gdouble min; /* Parameter minumum value */
|
||||
gdouble max; /* Parameter maximum value */
|
||||
guint option; /* ID (to set parameter) */
|
||||
guint position; /* position */
|
||||
gdouble min; /**< Minumum value */
|
||||
gdouble max; /**< Maximum value */
|
||||
GStrv labels; /**< value labels */
|
||||
} EffectValues;
|
||||
|
||||
typedef struct {
|
||||
gchar *label; /**< Parameter name */
|
||||
guint id; /**< ID (to set parameter) */
|
||||
guint position; /**< position */
|
||||
EffectValues *values; /**< valid parameter values */
|
||||
} EffectSettings;
|
||||
|
||||
typedef struct {
|
||||
guint id; /* value (type) */
|
||||
gchar *label; /* Effect name */
|
||||
guint option; /* ID (to set effect type) */
|
||||
guint position; /* position */
|
||||
EffectSettings *settings; /* possible parameters */
|
||||
gint settings_amt; /* possible parameters length */
|
||||
guint type; /**< value (type) */
|
||||
gchar *label; /**< Effect name */
|
||||
EffectSettings *settings; /**< possible parameters */
|
||||
gint settings_amt; /**< possible parameters length */
|
||||
} EffectGroup;
|
||||
|
||||
typedef struct {
|
||||
char *label; /* Base effect name */
|
||||
guint option; /* ID (to set effect on/off) */
|
||||
guint position; /* position */
|
||||
EffectGroup *group; /* possible effect types */
|
||||
gint group_amt; /* possible effect types length */
|
||||
gchar *label; /**< Group label */
|
||||
guint id; /**< ID to set effect on/off, or if it isn't on/off group then -1 */
|
||||
guint type; /**< ID to set effect type */
|
||||
guint position; /**< position */
|
||||
EffectGroup *group; /**< possible effect types */
|
||||
gint group_amt; /**< possible effect types length */
|
||||
} Effect;
|
||||
|
||||
typedef struct {
|
||||
Effect *effect; /* list of supported effects */
|
||||
gint amt; /* list of supported effects length */
|
||||
gchar *label; /**< base effect name */
|
||||
Effect *effect; /**< list of supported effects */
|
||||
gint amt; /**< list of supported effects length */
|
||||
} EffectList;
|
||||
|
||||
typedef struct {
|
||||
guint type; /**< ID to set effect type */
|
||||
guint position;
|
||||
EffectGroup *group;
|
||||
gint group_amt;
|
||||
} ModifierGroup;
|
||||
|
||||
typedef struct {
|
||||
gchar *name;
|
||||
EffectList *effects;
|
||||
gint n_effects;
|
||||
gint n_rows;
|
||||
} EffectPage;
|
||||
|
||||
typedef struct {
|
||||
gchar *name;
|
||||
PresetBank bank;
|
||||
} Banks;
|
||||
|
||||
typedef struct {
|
||||
gchar *name;
|
||||
unsigned char family_id;
|
||||
unsigned char product_id;
|
||||
EffectPage *pages;
|
||||
gint n_pages;
|
||||
Banks *banks;
|
||||
gint n_banks;
|
||||
} Device;
|
||||
|
||||
ModifierGroup *modifier_linkable_list();
|
||||
void modifier_group_free(ModifierGroup *modifier_group);
|
||||
gboolean get_device_info(unsigned char device_id, unsigned char family_id,
|
||||
unsigned char product_id,
|
||||
Device **device);
|
||||
|
||||
#endif /* GDIGI_EFFECTS_H */
|
||||
|
||||
841
gdigi.c
841
gdigi.c
@@ -28,30 +28,21 @@ 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";
|
||||
static char *device_port = "hw:1,0,0";
|
||||
|
||||
/*
|
||||
calculate checksum
|
||||
array - the command to set over usb
|
||||
length - length of array
|
||||
check - position of checksum byte in array
|
||||
*/
|
||||
char calculate_checksum(gchar *array, int length, int check)
|
||||
{
|
||||
int x;
|
||||
char checksum;
|
||||
static GQueue *message_queue = NULL;
|
||||
static GMutex *message_queue_mutex = NULL;
|
||||
static GCond *message_queue_cond = NULL;
|
||||
|
||||
checksum = 0x07;
|
||||
|
||||
for (x = 0; x<length; x++) {
|
||||
if (x == check) continue;
|
||||
checksum ^= array[x];
|
||||
}
|
||||
|
||||
return checksum;
|
||||
}
|
||||
|
||||
static char calc_checksum(gchar *array, gint length)
|
||||
/**
|
||||
* \param array data to calculate checksum
|
||||
* \param length data length
|
||||
*
|
||||
* Calculates message checksum.
|
||||
*
|
||||
* \return calculated checksum.
|
||||
**/
|
||||
static char calculate_checksum(gchar *array, gint length)
|
||||
{
|
||||
int x;
|
||||
int checksum = 0;
|
||||
@@ -63,17 +54,18 @@ static char calc_checksum(gchar *array, gint length)
|
||||
return checksum;
|
||||
}
|
||||
|
||||
/*
|
||||
opens MIDI device
|
||||
Returns TRUE on error
|
||||
*/
|
||||
/**
|
||||
* Opens MIDI device. This function modifies global input and output variables.
|
||||
*
|
||||
* \return FALSE on success, TRUE on error.
|
||||
**/
|
||||
gboolean open_device()
|
||||
{
|
||||
int err;
|
||||
|
||||
err = snd_rawmidi_open(&input, &output, device, SND_RAWMIDI_NONBLOCK);
|
||||
err = snd_rawmidi_open(&input, &output, device_port, SND_RAWMIDI_SYNC);
|
||||
if (err) {
|
||||
fprintf(stderr, "snd_rawmidi_open %s failed: %d\n", device, err);
|
||||
fprintf(stderr, "snd_rawmidi_open %s failed: %d\n", device_port, err);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -88,91 +80,25 @@ gboolean open_device()
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param data data to be sent
|
||||
* \param length data length
|
||||
*
|
||||
* Sends data to device. This function uses global output variable.
|
||||
**/
|
||||
void send_data(char *data, int length)
|
||||
{
|
||||
if (output == NULL)
|
||||
open_device();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* \param data data to be packed
|
||||
* \param len data length
|
||||
*
|
||||
* Packs data using method used on all newer DigiTech products.
|
||||
*
|
||||
* \return GString containing packed data
|
||||
**/
|
||||
GString *pack_data(gchar *data, gint len)
|
||||
{
|
||||
GString *packed;
|
||||
@@ -203,10 +129,233 @@ GString *pack_data(gchar *data, gint len)
|
||||
return packed;
|
||||
}
|
||||
|
||||
/*
|
||||
data - unpacked data to send
|
||||
len - data length
|
||||
*/
|
||||
static void message_free_func(GString *msg, gpointer user_data)
|
||||
{
|
||||
g_string_free(msg, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* \param msg message to unpack
|
||||
*
|
||||
* Unpacks message data. This function modifies given GString.
|
||||
**/
|
||||
static void unpack_message(GString *msg)
|
||||
{
|
||||
int offset;
|
||||
int x;
|
||||
int i;
|
||||
unsigned char status;
|
||||
unsigned char *str;
|
||||
gboolean stop = FALSE;
|
||||
|
||||
g_return_if_fail(msg != NULL);
|
||||
g_return_if_fail(msg->len > 9);
|
||||
|
||||
offset = 1;
|
||||
x = 0;
|
||||
i = 8;
|
||||
|
||||
str = (unsigned char*)msg->str;
|
||||
do {
|
||||
offset += 8;
|
||||
status = str[offset-1];
|
||||
for (x=0; x<7; x++) {
|
||||
if (offset+x >= msg->len) {
|
||||
stop = TRUE;
|
||||
break;
|
||||
}
|
||||
if (str[offset+x] == 0xF7) {
|
||||
str[i] = 0xF7;
|
||||
stop = TRUE;
|
||||
}
|
||||
|
||||
str[i] = (((status << (x+1)) & 0x80) | str[x+offset]);
|
||||
i++;
|
||||
}
|
||||
} while (!stop && (offset+x < msg->len));
|
||||
|
||||
g_string_truncate(msg, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* \param msg SysEx message
|
||||
*
|
||||
* Checks message ID.
|
||||
*
|
||||
* \return MessageID, or -1 on error.
|
||||
**/
|
||||
MessageID get_message_id(GString *msg)
|
||||
{
|
||||
/** \todo check if msg is valid SysEx message */
|
||||
g_return_val_if_fail(msg != NULL, -1);
|
||||
g_return_val_if_fail(msg->str != NULL, -1);
|
||||
|
||||
if (msg->len > 7) {
|
||||
return (unsigned char)msg->str[7];
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void push_message(GString *msg)
|
||||
{
|
||||
if (((unsigned char)msg->str[0] == 0xF0) && ((unsigned char)msg->str[msg->len-1] == 0xF7))
|
||||
g_message("Pushing correct message!");
|
||||
else
|
||||
g_warning("Pushing incorrect message!");
|
||||
|
||||
int x;
|
||||
for (x = 0; x<msg->len; x++)
|
||||
printf("%02x ", (unsigned char)msg->str[x]);
|
||||
printf("\n");
|
||||
|
||||
switch (get_message_id(msg)) {
|
||||
case ACK:
|
||||
g_message("Received ACK");
|
||||
g_string_free(msg, TRUE);
|
||||
return;
|
||||
|
||||
case NACK:
|
||||
g_message("Received NACK");
|
||||
g_string_free(msg, TRUE);
|
||||
return;
|
||||
|
||||
case RECEIVE_PARAMETER_VALUE:
|
||||
unpack_message(msg);
|
||||
SettingParam *param = setting_param_new_from_data(&msg->str[8], NULL);
|
||||
g_message("Received parameter change ID: %d Position: %d Value: %d", param->id, param->position, param->value);
|
||||
|
||||
GDK_THREADS_ENTER();
|
||||
apply_setting_param_to_gui(param);
|
||||
GDK_THREADS_LEAVE();
|
||||
|
||||
setting_param_free(param);
|
||||
g_string_free(msg, TRUE);
|
||||
return;
|
||||
|
||||
case RECEIVE_DEVICE_NOTIFICATION:
|
||||
unpack_message(msg);
|
||||
unsigned char *str = (unsigned char*)msg->str;
|
||||
switch (str[8]) {
|
||||
case NOTIFY_PRESET_MOVED:
|
||||
if (str[11] == PRESETS_EDIT_BUFFER && str[12] == 0) {
|
||||
g_message("Loaded preset %d from bank %d", str[10], str[9]);
|
||||
|
||||
GDK_THREADS_ENTER();
|
||||
g_timeout_add(0, apply_current_preset_to_gui, NULL);
|
||||
GDK_THREADS_LEAVE();
|
||||
} else
|
||||
g_message("%d %d moved to %d %d", str[9], str[10], str[11], str[12]);
|
||||
default:
|
||||
g_message("Received unhandled device notification");
|
||||
}
|
||||
g_string_free(msg, TRUE);
|
||||
return;
|
||||
default:
|
||||
g_mutex_lock(message_queue_mutex);
|
||||
g_queue_push_tail(message_queue, msg);
|
||||
g_cond_signal(message_queue_cond);
|
||||
g_mutex_unlock(message_queue_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
gpointer read_data_thread(gboolean *stop)
|
||||
{
|
||||
/* This is mostly taken straight from alsa-utils-1.0.19 amidi/amidi.c
|
||||
by Clemens Ladisch <clemens@ladisch.de> */
|
||||
int err;
|
||||
int npfds;
|
||||
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 {
|
||||
unsigned char buf[256];
|
||||
int i, length;
|
||||
unsigned short revents;
|
||||
|
||||
/* SysEx messages can't contain bytes with 8th bit set.
|
||||
memset our buffer to 0xFF, so if for some reason we'll get out of reply bounds, we'll catch it */
|
||||
memset(buf, sizeof(buf), 0xFF);
|
||||
|
||||
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 ((unsigned char)buf[i] != 0xFE) /* ignore active sensing */
|
||||
buf[length++] = buf[i];
|
||||
|
||||
i = 0;
|
||||
|
||||
while (i < length) {
|
||||
int pos;
|
||||
int bytes;
|
||||
|
||||
if (string == NULL) {
|
||||
while (buf[i] != 0xF0 && i < length)
|
||||
i++;
|
||||
}
|
||||
|
||||
pos = i;
|
||||
|
||||
for (bytes = 0; (bytes<length-i) && (buf[i+bytes] != 0xF7); bytes++);
|
||||
|
||||
if (buf[i+bytes] == 0xF7) bytes++;
|
||||
|
||||
i += bytes;
|
||||
|
||||
if (string == NULL)
|
||||
string = g_string_new_len((gchar*)&buf[pos], bytes);
|
||||
else
|
||||
g_string_append_len(string, (gchar*)&buf[pos], bytes);
|
||||
|
||||
if ((unsigned char)string->str[string->len-1] == 0xF7) {
|
||||
/* push message on stack */
|
||||
push_message(string);
|
||||
string = NULL;
|
||||
}
|
||||
}
|
||||
} while (*stop == FALSE);
|
||||
|
||||
if (string) {
|
||||
g_string_free(string, TRUE);
|
||||
string = NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param procedure procedure ID
|
||||
* \param data unpacked message data
|
||||
* \param len data length
|
||||
*
|
||||
* Creates SysEx message then sends it. This function uses folowing global variables: device_id, family_id and product_id.
|
||||
**/
|
||||
void send_message(gint procedure, gchar *data, gint len)
|
||||
{
|
||||
GString *msg = g_string_new_len("\xF0" /* SysEx status byte */
|
||||
@@ -225,21 +374,55 @@ void send_message(gint procedure, gchar *data, gint len)
|
||||
}
|
||||
|
||||
g_string_append_printf(msg, "%c\xF7",
|
||||
calc_checksum(&msg->str[1], msg->len - 1));
|
||||
calculate_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)
|
||||
/**
|
||||
* \param id MessageID of requested message
|
||||
*
|
||||
* Reads data from message queue until message with matching id is found.
|
||||
*
|
||||
* \return GString containing unpacked message.
|
||||
**/
|
||||
GString *get_message_by_id(MessageID id)
|
||||
{
|
||||
if (msg->len > 7) {
|
||||
return (unsigned char)msg->str[7];
|
||||
}
|
||||
return -1;
|
||||
GString *data = NULL;
|
||||
guint x, len;
|
||||
gboolean found = FALSE;
|
||||
|
||||
g_mutex_lock(message_queue_mutex);
|
||||
do {
|
||||
len = g_queue_get_length(message_queue);
|
||||
for (x = 0; x<len; x++) {
|
||||
data = g_queue_peek_nth(message_queue, x);
|
||||
if (get_message_id(data) == id) {
|
||||
found = TRUE;
|
||||
g_queue_pop_nth(message_queue, x);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == FALSE)
|
||||
g_cond_wait(message_queue_cond, message_queue_mutex);
|
||||
|
||||
} while (found == FALSE);
|
||||
g_mutex_unlock(message_queue_mutex);
|
||||
|
||||
unpack_message(data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param msg message to append value
|
||||
* \param value value to append
|
||||
*
|
||||
* Packs value using scheme used on all newer DigiTech products.
|
||||
**/
|
||||
void append_value(GString *msg, guint value)
|
||||
{
|
||||
/* check how many bytes long the value is */
|
||||
@@ -267,11 +450,103 @@ void append_value(GString *msg, guint value)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
id - ID as found in preset file
|
||||
position - Position as found in preset file
|
||||
value - Value as found in preset file
|
||||
*/
|
||||
/**
|
||||
* \param str pointer to value to unpack
|
||||
* \param len return location for how many bytes value is encoded on (length is added to current value)
|
||||
*
|
||||
* Unpacks value using scheme used on all newer DigiTech products.
|
||||
*
|
||||
* \return unpacked value
|
||||
**/
|
||||
guint unpack_value(gchar *str, int *len)
|
||||
{
|
||||
guint value;
|
||||
gint tmp;
|
||||
|
||||
value = (unsigned char)str[0];
|
||||
if (len != NULL)
|
||||
*len += 1;
|
||||
|
||||
if (value > 0x80) {
|
||||
tmp = value & 0x7F;
|
||||
value = 0;
|
||||
gint i;
|
||||
for (i = 0; i<tmp; i++) {
|
||||
value |= ((unsigned char)str[1+i] << (8*(tmp-i-1)));
|
||||
}
|
||||
|
||||
if (len != NULL)
|
||||
*len += tmp;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates memory for SettingParam.
|
||||
*
|
||||
* \return SettingParam which must be freed using setting_param_free.
|
||||
**/
|
||||
SettingParam *setting_param_new()
|
||||
{
|
||||
SettingParam *param = g_slice_new(SettingParam);
|
||||
param->id = -1;
|
||||
param->position = -1;
|
||||
param->value = -1;
|
||||
|
||||
return param;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param str pointer to setting param in message
|
||||
* \param len return location for how many bytes value is encoded on (length is added to current value)
|
||||
*
|
||||
* Creates SettingParam basing on data.
|
||||
* This function expects str to point on:
|
||||
* -Parameter ID - 2 bytes
|
||||
* -Parameter position - 1 byte
|
||||
* -Parameter value - var
|
||||
*
|
||||
* \return newly created SettingParam which must be freed using setting_param_free.
|
||||
**/
|
||||
SettingParam *setting_param_new_from_data(gchar *str, gint *len)
|
||||
{
|
||||
gint id;
|
||||
gint position;
|
||||
guint value;
|
||||
|
||||
id = ((unsigned char)str[0] << 8) | (unsigned char)str[1];
|
||||
position = (unsigned char)str[2];
|
||||
if (len != NULL)
|
||||
*len += 3;
|
||||
|
||||
value = unpack_value(&str[3], len);
|
||||
|
||||
SettingParam *param = g_slice_new(SettingParam);
|
||||
param->id = id;
|
||||
param->position = position;
|
||||
param->value = value;
|
||||
|
||||
return param;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param param SettingParam to be freed
|
||||
*
|
||||
* Frees all memory used by SettingParam.
|
||||
**/
|
||||
void setting_param_free(SettingParam *param)
|
||||
{
|
||||
g_slice_free(SettingParam, param);
|
||||
}
|
||||
|
||||
/**
|
||||
* \param id Parameter ID
|
||||
* \param position Parameter position
|
||||
* \param value Parameter value
|
||||
*
|
||||
* Forms SysEx message to set parameter then sends it to device.
|
||||
**/
|
||||
void set_option(guint id, guint position, guint value)
|
||||
{
|
||||
GString *msg = g_string_sized_new(9);
|
||||
@@ -283,7 +558,12 @@ void set_option(guint id, guint position, guint value)
|
||||
g_string_free(msg, TRUE);
|
||||
}
|
||||
|
||||
/* x = 0 to 60 */
|
||||
/**
|
||||
* \param bank preset bank
|
||||
* \param x preset index
|
||||
*
|
||||
* Switches to selected preset.
|
||||
**/
|
||||
void switch_preset(guint bank, guint x)
|
||||
{
|
||||
GString *msg = g_string_sized_new(6);
|
||||
@@ -296,12 +576,12 @@ void switch_preset(guint bank, guint x)
|
||||
g_string_free(msg, TRUE);
|
||||
}
|
||||
|
||||
/* level = 0 to 99 */
|
||||
void set_preset_level(int level)
|
||||
{
|
||||
set_option(PRESET_LEVEL, PRESET_POSITION, level);
|
||||
}
|
||||
|
||||
/**
|
||||
* \param x preset index
|
||||
* \param name preset name
|
||||
*
|
||||
* Stores current edit buffer in user presets bank.
|
||||
**/
|
||||
void store_preset_name(int x, const gchar *name)
|
||||
{
|
||||
GString *msg = g_string_sized_new(6);
|
||||
@@ -314,7 +594,12 @@ void store_preset_name(int x, const gchar *name)
|
||||
g_string_free(msg, TRUE);
|
||||
}
|
||||
|
||||
/* x = 0 to 59 (preset number) */
|
||||
/**
|
||||
* \param x preset index
|
||||
* \param name preset name
|
||||
*
|
||||
* Sets preset name.
|
||||
**/
|
||||
void set_preset_name(int x, gchar *name)
|
||||
{
|
||||
GString *msg = g_string_sized_new(12);
|
||||
@@ -326,12 +611,13 @@ void set_preset_name(int x, gchar *name)
|
||||
g_string_free(msg, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
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
|
||||
*/
|
||||
/**
|
||||
* \param bank preset bank
|
||||
*
|
||||
* Queries preset names.
|
||||
*
|
||||
* \return GStrv which must be freed with g_strfreev, or NULL on error.
|
||||
**/
|
||||
GStrv query_preset_names(gchar bank)
|
||||
{
|
||||
GString *data = NULL;
|
||||
@@ -340,138 +626,180 @@ GStrv query_preset_names(gchar bank)
|
||||
int n_total; /* total number of presets */
|
||||
gchar **str_array = NULL;
|
||||
|
||||
/* clear MIDI IN buffer */
|
||||
clear_midi_in_buffer();
|
||||
|
||||
/* 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);
|
||||
data = get_message_by_id(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[9];
|
||||
str_array = g_new(gchar*, n_total + 1);
|
||||
str_array[n_total] = NULL;
|
||||
}
|
||||
|
||||
if (data->len >= 10) {
|
||||
n_total = data->str[10];
|
||||
str_array = g_new(gchar*, n_total + 1);
|
||||
str_array[n_total] = NULL;
|
||||
}
|
||||
for (x=10; ((x<data->len) && (n<n_total)); x++) {
|
||||
if ((unsigned char)data->str[x] == 0xF7) /* every message ends with 0xF7 */
|
||||
break;
|
||||
|
||||
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!");
|
||||
}
|
||||
}
|
||||
}
|
||||
str_array[n] = g_strdup(&data->str[x]);
|
||||
x += strlen(str_array[n]);
|
||||
n++;
|
||||
}
|
||||
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()
|
||||
/**
|
||||
* Queries current edit buffer.
|
||||
*
|
||||
* \return GList with preset SysEx messages, which must be freed using preset_list_free.
|
||||
**/
|
||||
GList *get_current_preset()
|
||||
{
|
||||
GString *data = NULL;
|
||||
GList *list = NULL;
|
||||
guint x, len;
|
||||
gboolean found = FALSE;
|
||||
gboolean done = FALSE;
|
||||
|
||||
/* clear MIDI IN buffer */
|
||||
clear_midi_in_buffer();
|
||||
send_message(REQUEST_PRESET, "\x04\x00", 2);
|
||||
|
||||
send_message(REQUEST_PRESET, "\x04\x00", 3);
|
||||
g_mutex_lock(message_queue_mutex);
|
||||
do {
|
||||
len = g_queue_get_length(message_queue);
|
||||
|
||||
/* read reply */
|
||||
data = read_data();
|
||||
g_string_free(data, TRUE);
|
||||
for (x = 0; x<len && (found == FALSE); x++) {
|
||||
data = g_queue_peek_nth(message_queue, x);
|
||||
if (get_message_id(data) == RECEIVE_PRESET_START) {
|
||||
found = TRUE;
|
||||
g_queue_pop_nth(message_queue, x);
|
||||
unpack_message(data);
|
||||
list = g_list_append(list, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
data = read_data();
|
||||
if (found == TRUE) {
|
||||
int i;
|
||||
int amt;
|
||||
|
||||
unpack_message(data);
|
||||
for (i = 10; (i < data->len) && data->str[i]; i++);
|
||||
|
||||
return data;
|
||||
amt = (unsigned char)data->str[i+2];
|
||||
|
||||
while (amt) {
|
||||
data = g_queue_pop_nth(message_queue, x);
|
||||
if (data == NULL) {
|
||||
g_cond_wait(message_queue_cond, message_queue_mutex);
|
||||
} else {
|
||||
unpack_message(data);
|
||||
list = g_list_append(list, data);
|
||||
amt--;
|
||||
}
|
||||
}
|
||||
|
||||
done = TRUE;
|
||||
} else {
|
||||
/* Receive Preset Start not found in message queue */
|
||||
g_cond_wait(message_queue_cond, message_queue_mutex);
|
||||
}
|
||||
} while (done == FALSE);
|
||||
g_mutex_unlock(message_queue_mutex);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void preset_list_free(GList *list)
|
||||
{
|
||||
g_return_if_fail(list != NULL);
|
||||
|
||||
g_list_foreach(list, (GFunc) message_free_func, NULL);
|
||||
g_list_free(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* \param device_id Variable to hold device ID
|
||||
* \param family_id Variable to hold family ID
|
||||
* \param product_id Variable to hold product ID
|
||||
*
|
||||
* Requests device information.
|
||||
*
|
||||
* \return TRUE on success, FALSE on error.
|
||||
**/
|
||||
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);
|
||||
send_message(REQUEST_WHO_AM_I, "\x7F\x7F\x7F", 3);
|
||||
|
||||
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;
|
||||
}
|
||||
GString *data = get_message_by_id(RECEIVE_WHO_AM_I);
|
||||
if ((data != NULL) && (data->len > 11)) {
|
||||
*device_id = data->str[8];
|
||||
*family_id = data->str[9];
|
||||
*product_id = data->str[10];
|
||||
g_string_free(data, TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void request_device_configuration()
|
||||
{
|
||||
gint os_major, os_minor;
|
||||
gint cpu_major, cpu_minor;
|
||||
gint protocol_version;
|
||||
gint current_bank, current_preset;
|
||||
gint media_card;
|
||||
|
||||
send_message(REQUEST_DEVICE_CONFIGURATION, NULL, 0);
|
||||
|
||||
GString *data = get_message_by_id(RECEIVE_DEVICE_CONFIGURATION);
|
||||
|
||||
if (data->len > 14) {
|
||||
os_major = data->str[8];
|
||||
os_minor = (((data->str[9] & 0xF0) >> 4) * 10) |
|
||||
(data->str[9] & 0x0F);
|
||||
g_message("OS version: %d.%d", os_major, os_minor);
|
||||
|
||||
cpu_major = data->str[10];
|
||||
cpu_minor = data->str[11];
|
||||
g_message("CPU version: %d.%d", cpu_major, cpu_minor);
|
||||
|
||||
protocol_version = data->str[12];
|
||||
g_message("Protocol version: %d", protocol_version);
|
||||
|
||||
current_bank = data->str[13];
|
||||
current_preset = data->str[14];
|
||||
g_message("Active bank: %d", current_bank);
|
||||
g_message("Active preset: %d", current_preset);
|
||||
|
||||
if (os_major >= 1) {
|
||||
media_card = data->str[15];
|
||||
g_message("Media card present: %d", media_card);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
static GOptionEntry options[] = {
|
||||
{"device", 'd', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_STRING, &device, "MIDI device port to use", NULL},
|
||||
{"device", 'd', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_STRING, &device_port, "MIDI device port to use", NULL},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
GError *error = NULL;
|
||||
GOptionContext *context;
|
||||
static gboolean stop_read_thread = FALSE;
|
||||
GThread *read_thread = NULL;
|
||||
|
||||
g_thread_init(NULL);
|
||||
gdk_threads_init();
|
||||
|
||||
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));
|
||||
@@ -488,18 +816,63 @@ int main(int argc, char *argv[]) {
|
||||
if (open_device() == TRUE) {
|
||||
show_error_message(NULL, "Failed to open MIDI device");
|
||||
} else {
|
||||
message_queue = g_queue_new();
|
||||
message_queue_mutex = g_mutex_new();
|
||||
message_queue_cond = g_cond_new();
|
||||
read_thread = g_thread_create((GThreadFunc)read_data_thread,
|
||||
&stop_read_thread,
|
||||
TRUE, NULL);
|
||||
|
||||
if (request_who_am_i(&device_id, &family_id, &product_id) == FALSE) {
|
||||
show_error_message(NULL, "No suitable reply from device - is it connected?");
|
||||
show_error_message(NULL, "No suitable reply from device");
|
||||
} else {
|
||||
create_window();
|
||||
gtk_main();
|
||||
Device *device = NULL;
|
||||
|
||||
if (get_device_info(device_id, family_id, product_id, &device) == FALSE) {
|
||||
if (unsupported_device_dialog(&device) == FALSE) {
|
||||
g_message("Shutting down");
|
||||
}
|
||||
}
|
||||
|
||||
if (device != NULL) {
|
||||
/* enable GUI mode */
|
||||
set_option(GUI_MODE_ON_OFF, USB_POSITION, 1);
|
||||
|
||||
gui_create(device);
|
||||
gtk_main();
|
||||
gui_free();
|
||||
|
||||
/* disable GUI mode */
|
||||
set_option(GUI_MODE_ON_OFF, USB_POSITION, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (output != NULL)
|
||||
if (read_thread != NULL) {
|
||||
stop_read_thread = TRUE;
|
||||
g_thread_join(read_thread);
|
||||
}
|
||||
|
||||
if (message_queue_mutex != NULL) {
|
||||
g_mutex_free(message_queue_mutex);
|
||||
}
|
||||
|
||||
if (message_queue != NULL) {
|
||||
g_message("%d unread messages in queue",
|
||||
g_queue_get_length(message_queue));
|
||||
g_queue_foreach(message_queue, (GFunc) message_free_func, NULL);
|
||||
g_queue_free(message_queue);
|
||||
}
|
||||
|
||||
if (output != NULL) {
|
||||
snd_rawmidi_drain(output);
|
||||
snd_rawmidi_close(output);
|
||||
if (input != NULL)
|
||||
}
|
||||
|
||||
if (input != NULL) {
|
||||
snd_rawmidi_drain(input);
|
||||
snd_rawmidi_close(input);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
621
gdigi.h
621
gdigi.h
@@ -20,7 +20,20 @@
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
#define GNX_CHANNEL_POSITION 7
|
||||
#define GNX_CHANNEL_AMP 260
|
||||
#define GNX_WARP 261
|
||||
#define GNX_AMP_WARP 262
|
||||
#define GNX_CABINET_WARP 263
|
||||
#define GNX_CHANNEL_FS_MODE 264
|
||||
|
||||
enum {
|
||||
GNX3K_WAH_TYPE_CRY = 129,
|
||||
GNX3K_WAH_TYPE_BOUTIQUE = 130,
|
||||
GNX3K_WAH_TYPE_FULLRANGE = 131,
|
||||
|
||||
WAH_TYPE_CRY = 132,
|
||||
WAH_TYPE_FULLRANGE = 133,
|
||||
WAH_TYPE_CLYDE = 134
|
||||
@@ -39,17 +52,45 @@ enum {
|
||||
|
||||
enum {
|
||||
COMP_TYPE_DIGI = 195,
|
||||
COMP_TYPE_CS = 196
|
||||
COMP_TYPE_CS = 196,
|
||||
COMP_TYPE_DYNA = 197
|
||||
};
|
||||
|
||||
#define GNX3K_WHAM_TYPE 768
|
||||
#define GNX3K_WHAM_ENABLE 769
|
||||
#define GNX3K_WHAM_POSITION 5
|
||||
#define GNX3K_DETUNE_AMOUNT 1670
|
||||
#define GNX3K_PITCH_AMOUNT 1732
|
||||
#define GNX3K_PITCH_LEVEL 1731
|
||||
#define GNX3K_TALK_LEVEL 2818
|
||||
|
||||
enum {
|
||||
GNX3K_WHAM_TYPE_WHAMMY = 1344,
|
||||
GNX3K_WHAM_TYPE_IPS = 1345,
|
||||
GNX3K_WHAM_TYPE_DETUNE = 1346,
|
||||
GNX3K_WHAM_TYPE_PITCH = 1347,
|
||||
GNX3K_WHAM_TYPE_TALK1 = 1348,
|
||||
GNX3K_WHAM_TYPE_TALK2 = 1349,
|
||||
GNX3K_WHAM_TYPE_TALK3 = 1350,
|
||||
GNX3K_WHAM_TYPE_TALK4 = 1351,
|
||||
GNX3K_WHAM_TYPE_TALK5 = 1352
|
||||
};
|
||||
|
||||
#define COMP_TYPE 207
|
||||
#define COMP_ON_OFF 193
|
||||
#define COMP_POSITION 4
|
||||
|
||||
#define GNX3K_COMP_ATTACK 194
|
||||
#define GNX3K_COMP_RATIO 195
|
||||
#define GNX3K_COMP_THRESHOLD 200
|
||||
#define GNX3K_COMP_GAIN 201
|
||||
|
||||
#define COMP_SUSTAIN 208
|
||||
#define COMP_TONE 209
|
||||
#define COMP_ATTACK 211
|
||||
#define COMP_LEVEL 210
|
||||
#define COMP_SENSITIVITY 213
|
||||
#define COMP_OUTPUT 212
|
||||
|
||||
enum {
|
||||
PICKUP_TYPE_HB_SC = 66,
|
||||
@@ -63,8 +104,10 @@ enum {
|
||||
enum {
|
||||
DIST_TYPE_SCREAMER = 1280,
|
||||
DIST_TYPE_808 = 1292,
|
||||
DIST_TYPE_SPARKDRIVE = 1286,
|
||||
DIST_TYPE_GUYOD = 1285,
|
||||
DIST_TYPE_DOD250 = 1283,
|
||||
DIST_TYPE_REDLINE = 1297,
|
||||
DIST_TYPE_RODENT = 1281,
|
||||
DIST_TYPE_MX = 1291,
|
||||
DIST_TYPE_DS = 1282,
|
||||
@@ -72,6 +115,9 @@ enum {
|
||||
DIST_TYPE_ZONE = 1289,
|
||||
DIST_TYPE_DEATH = 1294,
|
||||
DIST_TYPE_GONK = 1293,
|
||||
DIST_TYPE_8TAVIA = 1290,
|
||||
DIST_TYPE_FUZZLATOR = 1295,
|
||||
DIST_TYPE_CLASSIC_FUZZ = 1296,
|
||||
DIST_TYPE_FUZZY = 1288,
|
||||
DIST_TYPE_MP = 1284
|
||||
};
|
||||
@@ -83,41 +129,74 @@ enum {
|
||||
#define DIST_SCREAMER_DRIVE 2434
|
||||
#define DIST_SCREAMER_TONE 2435
|
||||
#define DIST_SCREAMER_LVL 2436
|
||||
|
||||
#define DIST_808_OVERDRIVE 2473
|
||||
#define DIST_808_TONE 2474
|
||||
#define DIST_808_LVL 2475
|
||||
|
||||
#define DIST_SPARKDRIVE_GAIN 2450
|
||||
#define DIST_SPARKDRIVE_TONE 2451
|
||||
#define DIST_SPARKDRIVE_CLEAN 2452
|
||||
#define DIST_SPARKDRIVE_VOLUME 2453
|
||||
|
||||
#define DIST_GUYOD_DRIVE 2448
|
||||
#define DIST_GUYOD_LVL 2449
|
||||
|
||||
#define DIST_DOD250_GAIN 2443
|
||||
#define DIST_DOD250_LVL 2444
|
||||
|
||||
#define DIST_REDLINE_GAIN 2488
|
||||
#define DIST_REDLINE_LOW 2489
|
||||
#define DIST_REDLINE_HIGH 2490
|
||||
#define DIST_REDLINE_LEVEL 2491
|
||||
|
||||
#define DIST_RODENT_DIST 2437
|
||||
#define DIST_RODENT_FILTER 2438
|
||||
#define DIST_RODENT_LVL 2439
|
||||
|
||||
#define DIST_MX_DIST 2468
|
||||
#define DIST_MX_OUTPUT 2469
|
||||
#define DIST_DS_GAIN 2440
|
||||
#define DIST_DS_TONE 2441
|
||||
#define DIST_DS_LVL 2442
|
||||
|
||||
#define DIST_GRUNGE_GRUNGE 2454
|
||||
#define DIST_GRUNGE_FACE 2456
|
||||
#define DIST_GRUNGE_LOUD 2457
|
||||
#define DIST_GRUNGE_BUTT 2455
|
||||
|
||||
#define DIST_ZONE_GAIN 2460
|
||||
#define DIST_ZONE_LOW 2463
|
||||
#define DIST_ZONE_MID_LVL 2462
|
||||
#define DIST_ZONE_MID_FREQ 2461
|
||||
#define DIST_ZONE_HIGH 2464
|
||||
#define DIST_ZONE_LEVEL 2465
|
||||
|
||||
#define DIST_DEATH_LOW 2477
|
||||
#define DIST_DEATH_MID 2476
|
||||
#define DIST_DEATH_HIGH 2479
|
||||
#define DIST_DEATH_LVL 2478
|
||||
|
||||
#define DIST_GONK_GONK 2480
|
||||
#define DIST_GONK_SMEAR 2471
|
||||
#define DIST_GONK_SUCK 2470
|
||||
#define DIST_GONK_HEAVE 2472
|
||||
|
||||
#define DIST_8TAVIA_DRIVE 2466
|
||||
#define DIST_8TAVIA_VOLUME 2467
|
||||
|
||||
#define DIST_FUZZLATOR_FUZZ 2481
|
||||
#define DIST_FUZZLATOR_TONE 2482
|
||||
#define DIST_FUZZLATOR_LOOSETIGHT 2483
|
||||
#define DIST_FUZZLATOR_VOLUME 2484
|
||||
|
||||
#define DIST_CLASSIC_FUZZ_FUZZ 2485
|
||||
#define DIST_CLASSIC_FUZZ_TONE 2486
|
||||
#define DIST_CLASSIC_FUZZ_VOLUME 2487
|
||||
|
||||
#define DIST_FUZZY_FUZZ 2458
|
||||
#define DIST_FUZZY_VOLUME 2459
|
||||
|
||||
#define DIST_MP_SUSTAIN 2445
|
||||
#define DIST_MP_TONE 2446
|
||||
#define DIST_MP_VOLUME 2447
|
||||
@@ -129,25 +208,66 @@ enum {
|
||||
AMP_TYPE_TWEED_CHAMP = 307,
|
||||
AMP_TYPE_TWEED_DELUXE = 308,
|
||||
AMP_TYPE_TWEED_BASSMAN = 309,
|
||||
AMP_TYPE_BROWN_BASSMAN = 310,
|
||||
AMP_TYPE_BLACKFACE_TWIN = 311,
|
||||
AMP_TYPE_BLACKFACE_DELUXE = 312,
|
||||
AMP_TYPE_PLEXI_JTM_45 = 313,
|
||||
AMP_TYPE_SUPER_LEAD_PLEXI = 314,
|
||||
AMP_TYPE_PLEXI_JUMP_PANEL = 315,
|
||||
AMP_TYPE_MASTER_VOLUME = 316,
|
||||
AMP_TYPE_JCM800 = 317,
|
||||
AMP_TYPE_JCM900 = 318,
|
||||
AMP_TYPE_JCM2000 = 319,
|
||||
AMP_TYPE_AC15 = 322,
|
||||
AMP_TYPE_AC30TB = 323,
|
||||
AMP_TYPE_HIWATT_100 = 324,
|
||||
AMP_TYPE_BOOGIE_MARK_II = 320,
|
||||
AMP_TYPE_BOOGIE_MARK_IV = 371,
|
||||
AMP_TYPE_DUAL_RECTIFIER = 321,
|
||||
AMP_TYPE_TRIPLE_RECTIFIER = 370,
|
||||
AMP_TYPE_LEGACY_VL100 = 327,
|
||||
AMP_TYPE_MATCHLESS_HC30 = 326,
|
||||
AMP_TYPE_SOLDANO_100 = 325,
|
||||
AMP_TYPE_SUPERGROUP = 381,
|
||||
AMP_TYPE_GA40 = 380,
|
||||
AMP_TYPE_OR120 = 372,
|
||||
AMP_TYPE_PV5150II = 373,
|
||||
AMP_TYPE_RG100 = 374,
|
||||
AMP_TYPE_JC120_JAZZ = 375,
|
||||
AMP_TYPE_SOLAR100 = 376,
|
||||
AMP_TYPE_SOLO = 331,
|
||||
AMP_TYPE_METAL = 332,
|
||||
AMP_TYPE_BRIGHT = 333,
|
||||
AMP_TYPE_CHUNK = 334,
|
||||
AMP_TYPE_CLEAN = 335,
|
||||
AMP_TYPE_HIGH_GAIN = 337,
|
||||
AMP_TYPE_BLUES = 338,
|
||||
AMP_TYPE_FUZZ = 339,
|
||||
AMP_TYPE_SPANK = 330,
|
||||
AMP_TYPE_GSP2101_CLEAN_TUBE = 328,
|
||||
AMP_TYPE_GSP2101_SAT_TUBE = 329,
|
||||
AMP_TYPE_CRUNCH = 336,
|
||||
AMP_TYPE_MONSTER = 377,
|
||||
AMP_TYPE_TWEEDFACE = 378,
|
||||
AMP_TYPE_BLACKBASS = 379,
|
||||
AMP_TYPE_STONER_ROCK = 368,
|
||||
AMP_TYPE_DARK_METAL = 369,
|
||||
AMP_TYPE_TRANSISTOR = 382,
|
||||
AMP_TYPE_BROWN_SOUND = 383,
|
||||
AMP_TYPE_MOSH = 384,
|
||||
AMP_TYPE_ACOUSTIC = 341,
|
||||
AMP_TYPE_DIRECT = 306
|
||||
AMP_TYPE_JUMBO_ACOUSTIC = 340,
|
||||
AMP_TYPE_DIRECT = 306,
|
||||
AMP_TYPE_SVT_ROCK_BASS = 342,
|
||||
AMP_TYPE_SVT_CLASSIC_BASS = 343,
|
||||
AMP_TYPE_PEG_B15_BASS = 344,
|
||||
AMP_TYPE_BASIC_BASS = 345,
|
||||
AMP_TYPE_SHOWMAN_BASS = 346,
|
||||
AMP_TYPE_ASH_MODERN_BASS = 347,
|
||||
AMP_TYPE_BRIT_BASS = 348,
|
||||
AMP_TYPE_SOLAR_BASS = 349,
|
||||
AMP_TYPE_BOOGIE_BASS = 350,
|
||||
AMP_TYPE_HART_BASS = 351,
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -160,9 +280,90 @@ enum {
|
||||
#define AMP_TYPE 2496
|
||||
#define AMP_ON_OFF 265
|
||||
#define AMP_POSITION 8
|
||||
#define CH2_AMP_POSITION 10
|
||||
|
||||
#define AMP_GAIN 2497
|
||||
#define AMP_LEVEL 2498
|
||||
#define AMP_BASS_FREQ 2499
|
||||
#define AMP_BASS_LEVEL 2500
|
||||
#define AMP_MID_FREQ 2501
|
||||
#define AMP_MID_LEVEL 2502
|
||||
#define AMP_TREBLE_FREQ 2503
|
||||
#define AMP_TREBLE_LEVEL 2504
|
||||
#define AMP_EQ_ON_OFF 2505
|
||||
#define AMP_PRESENCE 2506
|
||||
#define AMP_BASS 2507
|
||||
#define AMP_MID 2508
|
||||
#define AMP_TREBLE 2509
|
||||
|
||||
#define AMP_CAB_TYPE 2560
|
||||
#define AMP_CAB_TUNING 2561
|
||||
#define AMP_CAB_POSITION 9
|
||||
#define CH2_AMP_CAB_POSITION 11
|
||||
|
||||
enum {
|
||||
AMP_CAB_DIRECT = 570,
|
||||
AMP_CAB_CHAMP = 571,
|
||||
AMP_CAB_DELUXE = 572,
|
||||
AMP_CAB_DELUXE_REVERB = 573,
|
||||
AMP_CAB_BRITISH1_12 = 623,
|
||||
AMP_CAB_GA1_12 = 624,
|
||||
AMP_CAB_BLONDE2_12 = 577,
|
||||
AMP_CAB_TWIN = 576,
|
||||
AMP_CAB_BRITISH2_12 = 613,
|
||||
AMP_CAB_JAZZ2_12 = 626,
|
||||
AMP_CAB_BASSMAN = 579,
|
||||
AMP_CAB_BRITISH4_12 = 614,
|
||||
AMP_CAB_BRITISH_GREEN = 616,
|
||||
AMP_CAB_FANE4_12 = 584,
|
||||
AMP_CAB_BOUTIQUE4_12 = 583,
|
||||
AMP_CAB_VINTAGE = 622,
|
||||
AMP_CAB_RECTO4_12 = 625,
|
||||
AMP_CAB_DIGI_SOLO = 609,
|
||||
AMP_CAB_DIGI_BRIGHT = 611,
|
||||
AMP_CAB_DIGI_METAL = 618,
|
||||
AMP_CAB_DIGI_ROCK = 619,
|
||||
AMP_CAB_DIGI_ALT = 620,
|
||||
AMP_CAB_DIGI_VNTG = 621,
|
||||
AMP_CAB_DIGI_CHUNK = 612,
|
||||
AMP_CAB_DIGI_SPANK2_12 = 608,
|
||||
AMP_CAB_DIGI_SPKR_COMP = 585
|
||||
};
|
||||
|
||||
enum {
|
||||
GNX_AMP_CAB_DIRECT = 570,
|
||||
GNX_AMP_CAB_TWEED1_8 = 571,
|
||||
GNX_AMP_CAB_TWEED1_12 = 572,
|
||||
GNX_AMP_CAB_BLACKFACE1_12 = 573,
|
||||
GNX_AMP_CAB_BRITISH1_12 = 574,
|
||||
GNX_AMP_CAB_BLACKFACE2_12 = 576,
|
||||
GNX_AMP_CAB_BLONDE2_12 = 577,
|
||||
GNX_AMP_CAB_BRITISH2_12 = 578,
|
||||
GNX_AMP_CAB_TWEED4_10 = 579,
|
||||
GNX_AMP_CAB_BRITISH_70_4_12 = 580,
|
||||
GNX_AMP_CAB_BRITISH_GREEN4_12 = 581,
|
||||
GNX_AMP_CAB_STRAIGHT_V30_4_12 = 582,
|
||||
GNX_AMP_CAB_SLANT_V30_4_12 = 583,
|
||||
GNX_AMP_CAB_FANE4_12 = 584,
|
||||
GNX_AMP_CAB_2101_SPKR_COMP = 585,
|
||||
GNX_AMP_CAB_JUMBO_ACOUSTIC = 606,
|
||||
GNX_AMP_CAB_DREAD_ACOUSTIC = 607,
|
||||
GNX_AMP_CAB_DIGI_SPANK = 608,
|
||||
GNX_AMP_CAB_DIGI_SOLO = 609,
|
||||
GNX_AMP_CAB_DIGI_METAL = 610,
|
||||
GNX_AMP_CAB_DIGI_BRIGHT = 611,
|
||||
GNX_AMP_CAB_DIGI_CHUNK = 612,
|
||||
GNX_AMP_CAB_HART_BASS1_15 = 586,
|
||||
GNX_AMP_CAB_BASIC_BASS1_15 = 587,
|
||||
GNX_AMP_CAB_PORTA_BASS1_15 = 588,
|
||||
GNX_AMP_CAB_REFLEX1_18 = 589,
|
||||
GNX_AMP_CAB_SOLAR_BASS2_15 = 590,
|
||||
GNX_AMP_CAB_DE_BASS4_10 = 591,
|
||||
GNX_AMP_CAB_ASH_BASS4_10 = 592,
|
||||
GNX_AMP_CAB_GOLIATH_BASS4_10 = 593,
|
||||
GNX_AMP_CAB_HART_BASS4_10 = 594,
|
||||
GNX_AMP_CAB_SVT_BASS8_10 = 595,
|
||||
};
|
||||
|
||||
#define EQ_TYPE 3202
|
||||
#define EQ_ON_OFF 3212
|
||||
@@ -173,6 +374,15 @@ enum {
|
||||
#define EQ_MID_HZ 3206
|
||||
#define EQ_TREBLE 3205
|
||||
#define EQ_TREBLE_HZ 3211
|
||||
#define EQ_LOW_LEVEL 3203
|
||||
#define EQ_MID_LEVEL 3204
|
||||
#define EQ_HIGH_LEVEL 3205
|
||||
#define EQ_LOW_FREQ 3213
|
||||
#define EQ_MID_FREQ 3214
|
||||
#define EQ_HIGH_FREQ 3215
|
||||
#define EQ_LOW_BANDWIDTH 3216
|
||||
#define EQ_MID_BANDWIDTH 3217
|
||||
#define EQ_HIGH_BANDWIDTH 3218
|
||||
|
||||
enum {
|
||||
NOISEGATE_GATE = 768,
|
||||
@@ -183,6 +393,8 @@ enum {
|
||||
#define NOISEGATE_ON_OFF 705
|
||||
#define NOISEGATE_POSITION 12
|
||||
|
||||
#define GNX3K_GATE_ATTACK 706
|
||||
|
||||
/* available only in Gate mode */
|
||||
#define NOISEGATE_GATE_TRESHOLD 710
|
||||
/* available only in Swell mode */
|
||||
@@ -192,75 +404,140 @@ enum {
|
||||
#define NOISEGATE_RELEASE 713
|
||||
#define NOISEGATE_ATTN 714
|
||||
|
||||
enum {
|
||||
GNX3K_MOD_TYPE_CHORUS = 857,
|
||||
GNX3K_MOD_TYPE_FLANGER = 858,
|
||||
GNX3K_MOD_TYPE_TRIGFLANGER = 859,
|
||||
GNX3K_MOD_TYPE_PHASER = 860,
|
||||
GNX3K_MOD_TYPE_TRIGPHASER = 861,
|
||||
GNX3K_MOD_TYPE_TREMOLO = 862,
|
||||
GNX3K_MOD_TYPE_PANNER = 863,
|
||||
GNX3K_MOD_TYPE_VIBRATO = 864,
|
||||
GNX3K_MOD_TYPE_ROTARY = 865,
|
||||
GNX3K_MOD_TYPE_AUTOYA = 866,
|
||||
GNX3K_MOD_TYPE_YAYA = 867,
|
||||
GNX3K_MOD_TYPE_SYNTHTALK = 868,
|
||||
GNX3K_MOD_TYPE_ENVELOPE = 869,
|
||||
GNX3K_MOD_TYPE_DETUNE = 870,
|
||||
GNX3K_MOD_TYPE_PITCH = 871,
|
||||
GNX3K_MOD_TYPE_UNOVIBE = 880,
|
||||
};
|
||||
|
||||
enum {
|
||||
CHORUS_TYPE_CE = 0x37B,
|
||||
CHORUS_TYPE_TC = 0x37C,
|
||||
CHORUS_TYPE_DUAL = 0x379,
|
||||
CHORUS_TYPE_GLISTEN = 0x392,
|
||||
CHORUS_TYPE_MULTI = 0x37a,
|
||||
CHORUS_TYPE_FLANGER = 0x37d,
|
||||
CHORUS_TYPE_TRIGGERED_FLANGER = 0x37e,
|
||||
CHORUS_TYPE_MXR_FLANGER = 0x37f,
|
||||
CHORUS_TYPE_EH_FLANGER = 0x380,
|
||||
CHORUS_TYPE_AD_FLANGER = 0x393,
|
||||
CHORUS_TYPE_PHASER = 0x381,
|
||||
CHORUS_TYPE_TRIGGERED_PHASER = 0x382,
|
||||
CHORUS_TYPE_MX_PHASER = 0x383,
|
||||
CHORUS_TYPE_EH_PHASER = 0x384,
|
||||
CHORUS_TYPE_VIBRATO = 0x360,
|
||||
CHORUS_TYPE_ROTARY = 0x361,
|
||||
CHORUS_TYPE_VIBROPAN = 0x38f,
|
||||
CHORUS_TYPE_UNOVIBE = 0x390,
|
||||
CHORUS_TYPE_TREMOLO = 0x35e,
|
||||
CHORUS_TYPE_SCATTER_TREM = 0x394,
|
||||
CHORUS_TYPE_OPTO_TREMOLO = 0x388,
|
||||
CHORUS_TYPE_BIAS_TREMOLO = 0x389,
|
||||
CHORUS_TYPE_PANNER = 0x35f,
|
||||
CHORUS_TYPE_ENVELOPE = 0x38a,
|
||||
CHORUS_TYPE_FX25 = 0x38e,
|
||||
CHORUS_TYPE_AUTOYA = 0x38b,
|
||||
CHORUS_TYPE_YAYA = 0x38c,
|
||||
CHORUS_TYPE_SYNTH_TALK = 0x391,
|
||||
CHORUS_TYPE_STEP_FILTER = 0x38d,
|
||||
CHORUS_TYPE_SAMPLE_HOLD = 0x395,
|
||||
CHORUS_TYPE_WHAMMY = 0x540,
|
||||
CHORUS_TYPE_PITCH_SHIFT = 0x543,
|
||||
CHORUS_TYPE_DETUNE = 0x542,
|
||||
CHORUS_TYPE_IPS = 0x541
|
||||
CHORUS_TYPE_IPS = 0x541,
|
||||
CHORUS_TYPE_OCTAVER = 0x385,
|
||||
};
|
||||
|
||||
#define CHORUSFX_TYPE 768
|
||||
#define CHORUSFX_ON_OFF 769
|
||||
#define CHORUSFX_POSITION 14
|
||||
|
||||
#define CE_CHORUS_SPEED 837
|
||||
#define CE_CHORUS_DEPTH 838
|
||||
#define CHORUS_SPEED 837
|
||||
#define CHORUS_DEPTH 838
|
||||
#define CHORUS_PREDELAY 839
|
||||
|
||||
#define DUAL_CHORUS_SPEED 837
|
||||
#define DUAL_CHORUS_DEPTH 838
|
||||
#define DUAL_CHORUS_LEVEL 836
|
||||
#define DUAL_CHORUS_WAVE 840
|
||||
#define CHORUS_WIDTH 848
|
||||
#define CHORUS_INTENSITY 849
|
||||
|
||||
#define MULTI_CHORUS_SPEED 837
|
||||
#define MULTI_CHORUS_DEPTH 838
|
||||
#define MULTI_CHORUS_WAVE 840
|
||||
#define MULTI_CHORUS_LEVEL 836
|
||||
#define CHORUS_LEVEL 836
|
||||
#define CHORUS_WAVE 840
|
||||
#define CHORUS_BALANCE 841
|
||||
|
||||
#define FLANGER_SPEED 902
|
||||
#define FLANGER_DEPTH 903
|
||||
#define FLANGER_REGEN 904
|
||||
#define FLANGER_LEVEL 901
|
||||
#define FLANGER_WAVE 905
|
||||
#define FLANGER_BALANCE 906
|
||||
|
||||
#define TRIG_FLANGER_SPEED 1030
|
||||
#define TRIG_FLANGER_SENS 1031
|
||||
#define TRIG_FLANGER_LFO_START 1028
|
||||
#define TRIG_FLANGER_MIX 1029
|
||||
#define TRIG_FLANGER_LEVEL 1032
|
||||
|
||||
#define MXR_FLANGER_SPEED 902
|
||||
#define MXR_FLANGER_WIDTH 914
|
||||
#define MXR_FLANGER_REGEN 904
|
||||
#define MXR_FLANGER_MANUAL 917
|
||||
|
||||
#define EH_FLANGER_RATE 918
|
||||
#define EH_FLANGER_RANGE 919
|
||||
#define EH_FLANGER_COLOR 916
|
||||
|
||||
#define AD_FLANGER_ENHANCE 920
|
||||
#define AD_FLANGER_HARMONICS 921
|
||||
|
||||
#define PHASER_SPEED 962
|
||||
#define PHASER_DEPTH 963
|
||||
#define PHASER_REGEN 966
|
||||
#define PHASER_LEVEL 965
|
||||
#define PHASER_WAVE 967
|
||||
#define PHASER_BALANCE 968
|
||||
|
||||
#define TRIG_PHASER_SPEED 1094
|
||||
#define TRIG_PHASER_SENS 1095
|
||||
#define TRIG_PHASER_LFO_START 1092
|
||||
#define TRIG_PHASER_MIX 1093
|
||||
#define TRIG_PHASER_LEVEL 1096
|
||||
|
||||
#define MX_PHASER_INTENSITY 976
|
||||
|
||||
#define EH_PHASER_RATE 979
|
||||
#define EH_PHASER_COLOR 977
|
||||
|
||||
#define VIBRATO_SPEED 1284
|
||||
#define VIBRATO_DEPTH 1285
|
||||
#define VIBRATO_WAVEFORM 1286
|
||||
|
||||
#define ROTARY_SPEED 1346
|
||||
#define ROTARY_INTENSITY 1348
|
||||
#define ROTARY_MIX 1349
|
||||
#define ROTARY_DOPPLER 1350
|
||||
#define ROTARY_CROSSOVER 1351
|
||||
#define ROTARY_BALANCE 1352
|
||||
|
||||
#define VIBROPAN_SPEED 1314
|
||||
#define VIBROPAN_DEPTH 1315
|
||||
#define VIBROPAN_VIBRA 1316
|
||||
#define VIBROPAN_WAVE 1317
|
||||
|
||||
#define UNOVIBE_PEDAL_SPEED 2884
|
||||
#define UNOVIBE_INTENSITY 2883
|
||||
#define UNOVIBE_CHORUS_VIBRATO 2882
|
||||
#define UNOVIBE_VOLUME 2885
|
||||
|
||||
#define TREMOLO_SPEED 1156
|
||||
#define TREMOLO_DEPTH 1155
|
||||
#define TREMOLO_WAVE 1157
|
||||
@@ -269,103 +546,83 @@ enum {
|
||||
#define PANNER_DEPTH 1219
|
||||
#define PANNER_WAVE 1221
|
||||
|
||||
#define ENVELOPE_MIX 1604
|
||||
#define ENVELOPE_SENSITIVITY 1606
|
||||
#define ENVELOPE_RANGE 1605
|
||||
#define ENVELOPE_BALANCE 1607
|
||||
#define ENVELOPE_BLEND 1608
|
||||
|
||||
#define GNX3K_AUTOYA_RANGE 1476
|
||||
#define AUTOYA_MIX 1477
|
||||
#define AUTOYA_SPEED 1478
|
||||
#define AUTOYA_DEPTH 1479
|
||||
#define AUTOYA_BALANCE 1481
|
||||
#define AUTOYA_INTENSITY 1482
|
||||
#define AUTOYA_RANGE 1483
|
||||
|
||||
#define YAYA_PEDAL 1410
|
||||
#define GNX3K_YAYA_RANGE 1412
|
||||
#define YAYA_MIX 1413
|
||||
#define YAYA_DEPTH 1414
|
||||
#define YAYA_BALANCE 1416
|
||||
#define YAYA_INTENSITY 1417
|
||||
#define YAYA_RANGE 1418
|
||||
|
||||
#define SYNTH_TALK_ATTACK 1542
|
||||
#define GNX3K_SYNTH_TALK_RELEASE 1543
|
||||
#define SYNTH_TALK_RELEASE 1547
|
||||
#define SYNTH_TALK_SENS 1544
|
||||
#define SYNTH_TALK_VOX 1540
|
||||
#define SYNTH_TALK_BALANCE 1545
|
||||
|
||||
#define STEP_FILTER_SPEED 3010
|
||||
#define STEP_FILTER_INTENSITY 3011
|
||||
|
||||
#define SAMPLE_HOLD_SPEED 3012
|
||||
#define SAMPLE_HOLD_INTENSITY 3013
|
||||
|
||||
#define WHAMMY_AMOUNT 1797
|
||||
#define WHAMMY_PEDAL 1795
|
||||
#define WHAMMY_MIX 1796
|
||||
|
||||
#define PITCH_AMOUNT 1730
|
||||
#define PITCH_BALANCE 1733
|
||||
#define PITCH_MIX 1745
|
||||
|
||||
#define DETUNE_AMOUNT 1668
|
||||
#define DETUNE_LEVEL 1667
|
||||
#define DETUNE_AMOUNT 1668
|
||||
#define DETUNE_BALANCE 1669
|
||||
|
||||
#define IPS_SHIFT_AMOUNT 2754
|
||||
#define IPS_KEY 2756
|
||||
#define IPS_SCALE 2755
|
||||
#define IPS_LEVEL 2757
|
||||
|
||||
/* DUAL_CHORUS_WAVE, MULTI_CHORUS_WAVE, FLANGER_WAVE, PHASER_WAVE,
|
||||
VIBROPAN_WAVE, TREMOLO_WAVE, PANNER_WAVE valid values */
|
||||
#define WAVE_TRI 0x00
|
||||
#define WAVE_SINE 0x01
|
||||
#define WAVE_SQUARE 0x02
|
||||
|
||||
/* WHAMMY_AMOUNT valid values */
|
||||
#define WHAMMY_OCT_UP 0x00
|
||||
#define WHAMMY_2OCT_UP 0x01
|
||||
#define WHAMMY_2ND_DN 0x02
|
||||
#define WHAMMY_RV_2ND 0x03
|
||||
#define WHAMMY_4TH_DN 0x04
|
||||
#define WHAMMY_OCT_DN 0x05
|
||||
#define WHAMMY_2OCT_DN 0x06
|
||||
#define WHAMMY_DIV_BMB 0x07
|
||||
#define WHAMMY_M3_MA 0x08
|
||||
#define WHAMMY_2ND_MA3 0x09
|
||||
#define WHAMMY_3RD_4TH 0x0A
|
||||
#define WHAMMY_4TH_5TH 0x0B
|
||||
#define WHAMMY_5TH_OCT 0x0C
|
||||
#define WHAMMY_HOCT_UP 0x0D
|
||||
#define WHAMMY_HOCT_DN 0x0E
|
||||
#define WHAMMY_OCT_UD 0x0F
|
||||
|
||||
/* IPS_SHIFT_AMOUNT valid values */
|
||||
#define IPS_OCT_D 0x00
|
||||
#define IPS_7TH_DN 0x01
|
||||
#define IPS_6TH_DN 0x02
|
||||
#define IPS_5TH_DN 0x03
|
||||
#define IPS_4TH_DN 0x04
|
||||
#define IPS_3RD_DN 0x05
|
||||
#define IPS_2ND_DN 0x06
|
||||
#define IPS_2ND_UP 0x07
|
||||
#define IPS_3RD_UP 0x08
|
||||
#define IPS_4TH_UP 0x09
|
||||
#define IPS_5TH_UP 0x0A
|
||||
#define IPS_6TH_UP 0x0B
|
||||
#define IPS_7TH_UP 0x0C
|
||||
#define IPS_OCT_U 0x0D
|
||||
|
||||
/* IPS_KEY valid values */
|
||||
#define IPS_E 0x00
|
||||
#define IPS_F 0x01
|
||||
#define IPS_GB 0x02
|
||||
#define IPS_G 0x03
|
||||
#define IPS_AB 0x04
|
||||
#define IPS_A 0x05
|
||||
#define IPS_BB 0x06
|
||||
#define IPS_B 0x07
|
||||
#define IPS_C 0x08
|
||||
#define IPS_DD 0x09
|
||||
#define IPS_D 0x0A
|
||||
#define IPS_EB 0x0B
|
||||
|
||||
/* IPS_SCALE valid values */
|
||||
#define IPS_MAJOR 0x00
|
||||
#define IPS_MINOR 0x01
|
||||
#define IPS_DORIA 0x02
|
||||
#define IPS_MIXLYD 0x03
|
||||
#define IPS_LYDIAN 0x04
|
||||
#define IPS_HMINO 0x05
|
||||
#define OCTAVER_OCTAVE1 1746
|
||||
#define OCTAVER_OCTAVE2 1747
|
||||
#define OCTAVER_DRY_LEVEL 1748
|
||||
|
||||
enum {
|
||||
DELAY_TYPE_ANALOG = 1046,
|
||||
DELAY_TYPE_DIGITAL = 1045,
|
||||
DELAY_TYPE_MODULATED = 1047,
|
||||
DELAY_TYPE_PONG = 1048,
|
||||
DELAY_TYPE_TAPE = 1049
|
||||
DELAY_TYPE_TAPE = 1049,
|
||||
|
||||
DELAY_RP500_TYPE_DIGITAL = 1052,
|
||||
DELAY_RP500_TYPE_ANALOG = 1053,
|
||||
DELAY_RP500_TYPE_DM = 1058,
|
||||
DELAY_RP500_TYPE_ECHOPLEX = 1057,
|
||||
DELAY_RP500_TYPE_MODULATED = 1054,
|
||||
DELAY_RP500_TYPE_PONG = 1055,
|
||||
DELAY_RP500_TYPE_REVERSE = 1064,
|
||||
DELAY_RP500_TYPE_TAPE = 1056,
|
||||
|
||||
DELAY_GNX3K_TYPE_MONO = 1027,
|
||||
DELAY_GNX3K_TYPE_PINGPONG = 1028,
|
||||
DELAY_GNX3K_TYPE_ANALOG = 1029,
|
||||
DELAY_GNX3K_TYPE_ANAPONG = 1030,
|
||||
DELAY_GNX3K_TYPE_SPREAD = 1031,
|
||||
};
|
||||
|
||||
#define DELAY_TYPE 1856
|
||||
@@ -374,29 +631,44 @@ enum {
|
||||
|
||||
#define DELAY_TIME 1888
|
||||
|
||||
#define ANALOG_LEVEL 1860
|
||||
#define ANALOG_REPEATS 1863
|
||||
#define DELAY_TAPE_WOW 1891
|
||||
#define DELAY_TAPE_FLUTTER 1892
|
||||
|
||||
#define DIGITAL_LEVEL 1860
|
||||
#define DIGITAL_REPEATS 1863
|
||||
#define DIGITAL_DUCKER_THRESH 1889
|
||||
#define DIGITAL_DUCKER_LEVEL 1890
|
||||
#define DELAY_LEVEL 1860
|
||||
#define DELAY_REPEATS 1863
|
||||
#define DELAY_TAP_TIME 1868
|
||||
#define DELAY_DUCK_THRESH 1889
|
||||
#define DELAY_DUCK_LEVEL 1890
|
||||
#define DELAY_REPEAT_RATE 1898
|
||||
#define DELAY_ECHO 1895
|
||||
#define DELAY_INTENSITY 1896
|
||||
#define DELAY_TIME_0_760 1899
|
||||
#define DELAY_VOLUME 1893
|
||||
#define DELAY_REPEATS_0_99 1874
|
||||
#define DELAY_DEPTH 1873
|
||||
#define DELAY_TAP_TIME_0_4990 1900
|
||||
#define DELAY_MIX 1902
|
||||
#define DELAY_TIME_0_4650 1901
|
||||
|
||||
#define MODULATED_LEVEL 1860
|
||||
#define MODULATED_REPEATS 1863
|
||||
#define MODULATED_DEPTH 1873
|
||||
|
||||
#define PONG_LEVEL 1860
|
||||
#define PONG_REPEATS 1863
|
||||
#define PONG_DUCKER_THRESH 1889
|
||||
#define PONG_DUCKER_LEVEL 1890
|
||||
|
||||
#define TAPE_LEVEL 1860
|
||||
#define TAPE_REPEATS 1863
|
||||
#define TAPE_WOW 1891
|
||||
#define TAPE_FLUTTER 1892
|
||||
#define GNX3K_DELAY_TIME 1862
|
||||
#define GNX3K_DELAY_FEEDBACK 1863
|
||||
#define GNX3K_DELAY_DUCK_THRESH 1864
|
||||
#define GNX3K_DELAY_DUCK_ATTEN 1865
|
||||
#define GNX3K_DELAY_BALANCE 1866
|
||||
#define GNX3K_DELAY_SPREAD 1867
|
||||
|
||||
enum {
|
||||
GNX3K_REVERB_TYPE_STUDIO = 1107,
|
||||
GNX3K_REVERB_TYPE_ROOM = 1108,
|
||||
GNX3K_REVERB_TYPE_CLUB = 1109,
|
||||
GNX3K_REVERB_TYPE_PLATE = 1110,
|
||||
GNX3K_REVERB_TYPE_HALL = 1111,
|
||||
GNX3K_REVERB_TYPE_AMPHITHEATER = 1112,
|
||||
GNX3K_REVERB_TYPE_CHURCH = 1113,
|
||||
GNX3K_REVERB_TYPE_GARAGE = 1114,
|
||||
GNX3K_REVERB_TYPE_ARENA = 1115,
|
||||
GNX3K_REVERB_TYPE_SPRING = 1116,
|
||||
|
||||
REVERB_TYPE_TWIN = 1146,
|
||||
REVERB_TYPE_LEX_AMBIENCE = 1150,
|
||||
REVERB_TYPE_LEX_STUDIO = 1149,
|
||||
@@ -409,32 +681,12 @@ enum {
|
||||
#define REVERB_ON_OFF 1921
|
||||
#define REVERB_POSITION 16
|
||||
|
||||
#define TWIN_REVERB 1925
|
||||
|
||||
#define LEX_AMBIENCE_PREDELAY 1922
|
||||
#define LEX_AMBIENCE_DECAY 1927
|
||||
#define LEX_AMBIENCE_LIVELINESS 1933
|
||||
#define LEX_AMBIENCE_LEVEL 1925
|
||||
|
||||
#define LEX_STUDIO_PREDELAY 1922
|
||||
#define LEX_STUDIO_DECAY 1927
|
||||
#define LEX_STUDIO_LIVELINESS 1933
|
||||
#define LEX_STUDIO_LEVEL 1925
|
||||
|
||||
#define LEX_ROOM_PREDELAY 1922
|
||||
#define LEX_ROOM_DECAY 1927
|
||||
#define LEX_ROOM_LIVELINESS 1933
|
||||
#define LEX_ROOM_LEVEL 1925
|
||||
|
||||
#define LEX_HALL_PREDELAY 1922
|
||||
#define LEX_HALL_DECAY 1927
|
||||
#define LEX_HALL_LIVELINESS 1933
|
||||
#define LEX_HALL_LEVEL 1925
|
||||
|
||||
#define EMT240_PLATE_PREDELAY 1922
|
||||
#define EMT240_PLATE_DECAY 1927
|
||||
#define EMT240_PLATE_LIVELINESS 1933
|
||||
#define EMT240_PLATE_LEVEL 1925
|
||||
#define REVERB_PREDELAY 1922
|
||||
#define REVERB_DAMPING 1924
|
||||
#define REVERB_DECAY 1927
|
||||
#define REVERB_BALANCE 1928
|
||||
#define REVERB_LIVELINESS 1933
|
||||
#define REVERB_LEVEL 1925
|
||||
|
||||
#define EXP_TYPE 8194
|
||||
#define EXP_POSITION 19
|
||||
@@ -442,11 +694,93 @@ enum {
|
||||
#define EXP_MIN 8195
|
||||
#define EXP_MAX 8196
|
||||
|
||||
#define LIBRARY_TONE 8704
|
||||
#define LIBRARY_EFFECTS 8705
|
||||
#define EFFECTS_LEVEL 8706
|
||||
|
||||
#define LIBRARY_POSITION 25
|
||||
|
||||
enum {
|
||||
TONE_LIB_OVERDRIVE = 1793,
|
||||
TONE_LIB_ROCK1 = 1794,
|
||||
TONE_LIB_ROCK2 = 1795,
|
||||
TONE_LIB_BLUES1 = 1796,
|
||||
TONE_LIB_BLUES2 = 1797,
|
||||
TONE_LIB_METAL1 = 1798,
|
||||
TONE_LIB_METAL2 = 1799,
|
||||
TONE_LIB_COUNTRY1 = 1800,
|
||||
TONE_LIB_COUNTRY2 = 1801,
|
||||
TONE_LIB_WARM_DRIVE = 1802,
|
||||
TONE_LIB_CRUNCH = 1803,
|
||||
TONE_LIB_TEXAS_TONE = 1804,
|
||||
TONE_LIB_ROCKABILLY = 1805,
|
||||
TONE_LIB_SOLO1 = 1806,
|
||||
TONE_LIB_SOLO2 = 1807,
|
||||
TONE_LIB_ROCKWAH = 1808,
|
||||
TONE_LIB_CHUNKY = 1809,
|
||||
TONE_LIB_SMOOTH = 1810,
|
||||
TONE_LIB_HEAVY = 1811,
|
||||
TONE_LIB_CLEAN1 = 1812,
|
||||
TONE_LIB_CLEAN2 = 1813,
|
||||
TONE_LIB_BRITISH1 = 1814,
|
||||
TONE_LIB_BRITISH2 = 1815,
|
||||
TONE_LIB_AMERICAN1 = 1816,
|
||||
TONE_LIB_AMERICAN2 = 1817,
|
||||
TONE_LIB_TUBE_DRIVE = 1818,
|
||||
TONE_LIB_DISTORTION = 1819,
|
||||
TONE_LIB_SCOOPED = 1820,
|
||||
TONE_LIB_PUNCHY = 1821,
|
||||
TONE_LIB_BRIGHT_CLEAN = 1822,
|
||||
|
||||
/* setting LIBRARY_TONE to this option seems to crash device */
|
||||
TONE_LIB_CUSTOM = 1792
|
||||
};
|
||||
|
||||
enum {
|
||||
EFFECTS_LIB_CHORUS = 1857,
|
||||
EFFECTS_LIB_PHASER = 1858,
|
||||
EFFECTS_LIB_FLANGER = 1859,
|
||||
EFFECTS_LIB_PITCH = 1860,
|
||||
EFFECTS_LIB_TREMOLO = 1861,
|
||||
EFFECTS_LIB_ROTARY = 1862,
|
||||
EFFECTS_LIB_ENVELOPE = 1863,
|
||||
EFFECTS_LIB_DIGITAL = 1864,
|
||||
EFFECTS_LIB_ANALOG = 1865,
|
||||
EFFECTS_LIB_PONG = 1866,
|
||||
EFFECTS_LIB_MOD = 1867,
|
||||
EFFECTS_LIB_TAPE = 1868,
|
||||
EFFECTS_LIB_HALL = 1869,
|
||||
EFFECTS_LIB_PLATE = 1870,
|
||||
EFFECTS_LIB_SPRING = 1871,
|
||||
EFFECTS_LIB_CHORUS_DIGITAL = 1872,
|
||||
EFFECTS_LIB_CHORUS_DELAY_REVERB = 1873,
|
||||
EFFECTS_LIB_FLANGER_ANALOG = 1874,
|
||||
EFFECTS_LIB_PHASER_TAPE = 1875,
|
||||
EFFECTS_LIB_PHASER_MOD = 1876,
|
||||
EFFECTS_LIB_PHASER_ROOM = 1877,
|
||||
EFFECTS_LIB_DIGITAL_HALL = 1878,
|
||||
EFFECTS_LIB_ANALOG_SPRING = 1879,
|
||||
EFFECTS_LIB_CHORUS_HALL = 1880,
|
||||
EFFECTS_LIB_PONG_HALL = 1881,
|
||||
EFFECTS_LIB_TAPE_SPRING = 1882,
|
||||
EFFECTS_LIB_TREMOLO_TAPE = 1883,
|
||||
EFFECTS_LIB_PITCH_DIGITAL = 1884,
|
||||
EFFECTS_LIB_MOD_PLATE = 1885,
|
||||
EFFECTS_LIB_ROTARY_TAPE = 1886,
|
||||
|
||||
/* setting EFFECTS_LIBRARY to this option seems to crash device */
|
||||
EFFECTS_LIB_CUSTOM = 1856
|
||||
};
|
||||
|
||||
#define USB_POSITION 0
|
||||
#define USB_AUDIO_PLAYBACK_MIX 12297
|
||||
#define USB_AUDIO_LEVEL 12307
|
||||
|
||||
enum {
|
||||
#define GUI_MODE_ON_OFF 12298
|
||||
|
||||
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
|
||||
|
||||
typedef enum {
|
||||
PRESETS_SYSTEM = 0,
|
||||
PRESETS_USER = 1,
|
||||
PRESETS_ARTIST = 2,
|
||||
@@ -458,9 +792,26 @@ enum {
|
||||
|
||||
/* Version 2 and later */
|
||||
PRESETS_EXTERNAL = 6
|
||||
};
|
||||
} PresetBank;
|
||||
|
||||
enum {
|
||||
typedef enum {
|
||||
/* Version 0 only */
|
||||
NOTIFY_PRESET_LOADED = 0,
|
||||
NOTIFY_PRESET_STORED = 1,
|
||||
|
||||
NOTIFY_MODIFIER_GROUP_CHANGED = 2,
|
||||
|
||||
/* Version 1 */
|
||||
NOTIFY_PRESET_MOVED = 3,
|
||||
NOTIFY_OBJECT_MOVED = 4,
|
||||
NOTIFY_OBJECT_RENAMED = 5,
|
||||
NOTIFY_MEDIA_CARD_PRESENT_CHANGED = 6,
|
||||
NOTIFY_ALL_GLOBALS_CHANGED = 7,
|
||||
NOTIFY_PRESET_INDEX_TABLE_CHANGED = 8,
|
||||
NOTIFY_PRESET_RENAMED = 9
|
||||
} NotifyCode;
|
||||
|
||||
typedef enum {
|
||||
REQUEST_WHO_AM_I = 0x01,
|
||||
RECEIVE_WHO_AM_I = 0x02,
|
||||
|
||||
@@ -491,7 +842,7 @@ enum {
|
||||
MOVE_PRESET = 0x39,
|
||||
|
||||
REQUEST_MODIFIER_LINKABLE_LIST = 0x3A,
|
||||
RECEIVE_MOFIFIER_LINKABLE_LIST = 0x3B,
|
||||
RECEIVE_MODIFIER_LINKABLE_LIST = 0x3B,
|
||||
|
||||
REQUEST_PARAMETER_VALUE = 0x40,
|
||||
RECEIVE_PARAMETER_VALUE = 0x41,
|
||||
@@ -512,15 +863,27 @@ enum {
|
||||
|
||||
ACK = 0x7E,
|
||||
NACK = 0x7F
|
||||
};
|
||||
} MessageID;
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
int position;
|
||||
int value;
|
||||
} SettingParam;
|
||||
|
||||
void send_message(gint procedure, gchar *data, gint len);
|
||||
MessageID get_message_id(GString *msg);
|
||||
void append_value(GString *msg, guint value);
|
||||
GString *get_message_by_id(MessageID id);
|
||||
SettingParam *setting_param_new();
|
||||
SettingParam *setting_param_new_from_data(gchar *str, gint *len);
|
||||
void setting_param_free(SettingParam *param);
|
||||
void set_option(guint id, guint position, guint value);
|
||||
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();
|
||||
GList *get_current_preset();
|
||||
void preset_list_free(GList *list);
|
||||
|
||||
#endif /* GDIGI_H */
|
||||
|
||||
919
gtkknob.c
Normal file
919
gtkknob.c
Normal file
@@ -0,0 +1,919 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Most of this code comes from gAlan 0.2.0, copyright (C) 1999
|
||||
* Tony Garnock-Jones, with modifications from Sean Bolton,
|
||||
* copyright (C) 2004, William Weston copyright (C) 2007,
|
||||
* Pete Shorthose copyright (C) 2007, and Tomasz Moń,
|
||||
* copyright (C) 2009
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <math.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
#include "gtkknob.h"
|
||||
|
||||
|
||||
#ifndef M_PI
|
||||
# define M_PI 3.14159265358979323846 /* pi */
|
||||
#endif
|
||||
#ifndef M_1_PI
|
||||
# define M_1_PI 0.31830988618379067154 /* 1/pi */
|
||||
#endif
|
||||
|
||||
|
||||
#define SCROLL_DELAY_LENGTH 250
|
||||
#define KNOB_SIZE 32 /* this should really be read from the knob image */
|
||||
|
||||
#define STATE_IDLE 0
|
||||
#define STATE_PRESSED 1
|
||||
#define STATE_DRAGGING 2
|
||||
|
||||
static void gtk_knob_class_init(GtkKnobClass *klass);
|
||||
static void gtk_knob_init(GtkKnob *knob);
|
||||
static void gtk_knob_destroy(GtkObject *object);
|
||||
static void gtk_knob_realize(GtkWidget *widget);
|
||||
static void gtk_knob_size_request(GtkWidget *widget, GtkRequisition *requisition);
|
||||
static void gtk_knob_size_allocate(GtkWidget *widget, GtkAllocation *allocation);
|
||||
static gint gtk_knob_expose(GtkWidget *widget, GdkEventExpose *event);
|
||||
static gint gtk_knob_scroll(GtkWidget *widget, GdkEventScroll *event);
|
||||
static gint gtk_knob_button_press(GtkWidget *widget, GdkEventButton *event);
|
||||
static gint gtk_knob_button_release(GtkWidget *widget, GdkEventButton *event);
|
||||
static gint gtk_knob_key_press(GtkWidget *widget, GdkEventKey *event);
|
||||
static gint gtk_knob_motion_notify(GtkWidget *widget, GdkEventMotion *event);
|
||||
static gint gtk_knob_timer(GtkKnob *knob);
|
||||
|
||||
static void gtk_knob_update_mouse_update(GtkKnob *knob);
|
||||
static void gtk_knob_update_mouse(GtkKnob *knob, gint x, gint y, gboolean step);
|
||||
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);
|
||||
|
||||
/* Local data */
|
||||
|
||||
static GtkWidgetClass *parent_class = NULL;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* gtk_knob_get_type()
|
||||
*
|
||||
*****************************************************************************/
|
||||
GType
|
||||
gtk_knob_get_type(void) {
|
||||
static GType knob_type = 0;
|
||||
|
||||
if (!knob_type) {
|
||||
static const GTypeInfo knob_info = {
|
||||
sizeof (GtkKnobClass),
|
||||
NULL,
|
||||
NULL,
|
||||
(GClassInitFunc) gtk_knob_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof (GtkKnob),
|
||||
0,
|
||||
(GInstanceInitFunc) gtk_knob_init,
|
||||
};
|
||||
knob_type = g_type_register_static (GTK_TYPE_WIDGET, "GtkKnob", &knob_info, 0);
|
||||
}
|
||||
|
||||
return knob_type;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* gtk_knob_class_init()
|
||||
*
|
||||
*****************************************************************************/
|
||||
static void
|
||||
gtk_knob_class_init (GtkKnobClass *klass) {
|
||||
GtkObjectClass *object_class;
|
||||
GtkWidgetClass *widget_class;
|
||||
|
||||
object_class = (GtkObjectClass*) klass;
|
||||
widget_class = (GtkWidgetClass*) klass;
|
||||
|
||||
parent_class = g_type_class_peek_parent(klass);
|
||||
|
||||
object_class->destroy = gtk_knob_destroy;
|
||||
|
||||
widget_class->realize = gtk_knob_realize;
|
||||
widget_class->expose_event = gtk_knob_expose;
|
||||
widget_class->size_request = gtk_knob_size_request;
|
||||
widget_class->size_allocate = gtk_knob_size_allocate;
|
||||
widget_class->scroll_event = gtk_knob_scroll;
|
||||
widget_class->button_press_event = gtk_knob_button_press;
|
||||
widget_class->button_release_event = gtk_knob_button_release;
|
||||
widget_class->key_press_event = gtk_knob_key_press;
|
||||
widget_class->motion_notify_event = gtk_knob_motion_notify;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* gtk_knob_init()
|
||||
*
|
||||
*****************************************************************************/
|
||||
static void
|
||||
gtk_knob_init (GtkKnob *knob) {
|
||||
knob->policy = GTK_UPDATE_CONTINUOUS;
|
||||
knob->state = STATE_IDLE;
|
||||
knob->saved_x = 0;
|
||||
knob->saved_y = 0;
|
||||
knob->timer = 0;
|
||||
knob->anim = NULL;
|
||||
knob->mask = NULL;
|
||||
knob->mask_gc = NULL;
|
||||
knob->red_gc = NULL;
|
||||
knob->old_value = 0.0;
|
||||
knob->old_lower = 0.0;
|
||||
knob->old_upper = 0.0;
|
||||
knob->adjustment = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* gtk_knob_new()
|
||||
*
|
||||
*****************************************************************************/
|
||||
GtkWidget *
|
||||
gtk_knob_new(GtkAdjustment *adjustment, GtkKnobAnim *anim) {
|
||||
GtkKnob *knob;
|
||||
|
||||
g_return_val_if_fail (anim != NULL, NULL);
|
||||
g_return_val_if_fail (GDK_IS_PIXBUF (anim->pixbuf), NULL);
|
||||
|
||||
knob = g_object_new (gtk_knob_get_type (), NULL);
|
||||
|
||||
gtk_knob_set_animation (knob, anim);
|
||||
|
||||
if (!adjustment) {
|
||||
adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
gtk_knob_set_adjustment (knob, adjustment);
|
||||
|
||||
return GTK_WIDGET (knob);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* gtk_knob_destroy()
|
||||
*
|
||||
*****************************************************************************/
|
||||
static void
|
||||
gtk_knob_destroy(GtkObject *object) {
|
||||
GtkKnob *knob;
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (GTK_IS_KNOB (object));
|
||||
|
||||
knob = GTK_KNOB (object);
|
||||
|
||||
gtk_knob_set_adjustment (knob, NULL);
|
||||
/* FIXME: needs ref counting for automatic GtkKnobAnim cleanup
|
||||
if (knob->anim) {
|
||||
gtk_knob_anim_unref (knob->anim);
|
||||
knob->anim = NULL;
|
||||
}
|
||||
*/
|
||||
|
||||
if (knob->mask) {
|
||||
g_object_unref (knob->mask);
|
||||
knob->mask = NULL;
|
||||
}
|
||||
|
||||
if (knob->mask_gc) {
|
||||
g_object_unref (knob->mask_gc);
|
||||
knob->mask_gc = NULL;
|
||||
}
|
||||
if (knob->red_gc) {
|
||||
g_object_unref (knob->red_gc);
|
||||
knob->red_gc = NULL;
|
||||
}
|
||||
|
||||
if (GTK_OBJECT_CLASS (parent_class)->destroy) {
|
||||
(*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* gtk_knob_get_adjustment()
|
||||
*
|
||||
*****************************************************************************/
|
||||
GtkAdjustment*
|
||||
gtk_knob_get_adjustment(GtkKnob *knob) {
|
||||
|
||||
g_return_val_if_fail (knob != NULL, NULL);
|
||||
g_return_val_if_fail (GTK_IS_KNOB (knob), NULL);
|
||||
|
||||
return knob->adjustment;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* gtk_knob_set_update_policy()
|
||||
*
|
||||
*****************************************************************************/
|
||||
void
|
||||
gtk_knob_set_update_policy(GtkKnob *knob, GtkUpdateType policy) {
|
||||
|
||||
g_return_if_fail (knob != NULL);
|
||||
g_return_if_fail (GTK_IS_KNOB (knob));
|
||||
|
||||
knob->policy = policy;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* gtk_knob_set_adjustment()
|
||||
*
|
||||
*****************************************************************************/
|
||||
void
|
||||
gtk_knob_set_adjustment(GtkKnob *knob, GtkAdjustment *adjustment) {
|
||||
|
||||
g_return_if_fail (knob != NULL);
|
||||
g_return_if_fail (GTK_IS_KNOB (knob));
|
||||
|
||||
if (knob->adjustment) {
|
||||
g_signal_handlers_disconnect_matched(knob->adjustment,
|
||||
G_SIGNAL_MATCH_DATA,
|
||||
0, 0, NULL, NULL,
|
||||
knob);
|
||||
g_object_unref (knob->adjustment);
|
||||
}
|
||||
|
||||
knob->adjustment = adjustment;
|
||||
if (adjustment) {
|
||||
g_object_ref_sink (adjustment);
|
||||
|
||||
g_signal_connect (adjustment, "changed",
|
||||
G_CALLBACK(gtk_knob_adjustment_changed),
|
||||
knob);
|
||||
g_signal_connect (adjustment, "value_changed",
|
||||
G_CALLBACK(gtk_knob_adjustment_value_changed),
|
||||
knob);
|
||||
|
||||
knob->old_value = adjustment->value;
|
||||
knob->old_lower = adjustment->lower;
|
||||
knob->old_upper = adjustment->upper;
|
||||
|
||||
gtk_knob_update (knob);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* gtk_knob_realize()
|
||||
*
|
||||
*****************************************************************************/
|
||||
static void
|
||||
gtk_knob_realize(GtkWidget *widget) {
|
||||
GtkKnob *knob;
|
||||
GdkWindowAttr attributes;
|
||||
gint attributes_mask;
|
||||
GdkColor color = { 0, 0xffff, 0, 0 };
|
||||
|
||||
g_return_if_fail (widget != NULL);
|
||||
g_return_if_fail (GTK_IS_KNOB (widget));
|
||||
|
||||
GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
|
||||
GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
|
||||
knob = GTK_KNOB (widget);
|
||||
|
||||
attributes.x = widget->allocation.x;
|
||||
attributes.y = widget->allocation.y;
|
||||
attributes.width = widget->allocation.width;
|
||||
attributes.height = widget->allocation.height;
|
||||
attributes.wclass = GDK_INPUT_OUTPUT;
|
||||
attributes.window_type = GDK_WINDOW_CHILD;
|
||||
attributes.event_mask =
|
||||
gtk_widget_get_events (widget) |
|
||||
GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
|
||||
GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
|
||||
GDK_POINTER_MOTION_HINT_MASK;
|
||||
attributes.visual = gtk_widget_get_visual (widget);
|
||||
attributes.colormap = gtk_widget_get_colormap (widget);
|
||||
|
||||
attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
|
||||
|
||||
widget->window = gdk_window_new (widget->parent->window,
|
||||
&attributes, attributes_mask);
|
||||
|
||||
widget->style = gtk_style_attach (widget->style, widget->window);
|
||||
|
||||
gdk_window_set_user_data (widget->window, widget);
|
||||
|
||||
gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
|
||||
|
||||
knob->mask_gc = gdk_gc_new (widget->window);
|
||||
gdk_gc_copy (knob->mask_gc, widget->style->bg_gc[GTK_STATE_NORMAL]);
|
||||
gdk_gc_set_clip_mask (knob->mask_gc, knob->mask);
|
||||
|
||||
knob->red_gc = gdk_gc_new (widget->window);
|
||||
gdk_gc_copy (knob->red_gc, widget->style->bg_gc[GTK_STATE_NORMAL]);
|
||||
gdk_colormap_alloc_color (attributes.colormap, &color, FALSE, TRUE);
|
||||
gdk_gc_set_foreground (knob->red_gc, &color);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* gtk_knob_size_request()
|
||||
*
|
||||
*****************************************************************************/
|
||||
static void
|
||||
gtk_knob_size_request (GtkWidget *widget, GtkRequisition *requisition) {
|
||||
|
||||
g_return_if_fail (widget != NULL);
|
||||
g_return_if_fail (GTK_IS_KNOB (widget));
|
||||
|
||||
requisition->width = GTK_KNOB (widget)->width;
|
||||
requisition->height = GTK_KNOB (widget)->height;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* gtk_knob_size_allocate()
|
||||
*
|
||||
*****************************************************************************/
|
||||
static void
|
||||
gtk_knob_size_allocate (GtkWidget *widget, GtkAllocation *allocation) {
|
||||
GtkKnob *knob;
|
||||
|
||||
g_return_if_fail (widget != NULL);
|
||||
g_return_if_fail (GTK_IS_KNOB (widget));
|
||||
g_return_if_fail (allocation != NULL);
|
||||
|
||||
widget->allocation = *allocation;
|
||||
knob = GTK_KNOB (widget);
|
||||
|
||||
if (GTK_WIDGET_REALIZED (widget)) {
|
||||
gdk_window_move_resize (widget->window,
|
||||
allocation->x, allocation->y,
|
||||
allocation->width, allocation->height);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* gtk_knob_expose()
|
||||
*
|
||||
*****************************************************************************/
|
||||
static gint
|
||||
gtk_knob_expose(GtkWidget *widget, GdkEventExpose *event) {
|
||||
GtkKnob *knob;
|
||||
gfloat dx, dy;
|
||||
gint frames;
|
||||
|
||||
g_return_val_if_fail (widget != NULL, FALSE);
|
||||
g_return_val_if_fail (GTK_IS_KNOB (widget), FALSE);
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
g_return_val_if_fail (GTK_IS_ADJUSTMENT (GTK_KNOB (widget)->adjustment), FALSE);
|
||||
|
||||
if (event->count > 0)
|
||||
return FALSE;
|
||||
|
||||
knob = GTK_KNOB (widget);
|
||||
|
||||
frames = ((knob->anim->width / knob->anim->frame_width) - 1);
|
||||
dx = knob->adjustment->value - knob->adjustment->lower; /* value, from 0 */
|
||||
dy = knob->adjustment->upper - knob->adjustment->lower; /* range */
|
||||
|
||||
dx = (int)(frames * dx / dy) * knob->width; /* check this for height != width */
|
||||
|
||||
gdk_draw_pixbuf (widget->window, knob->mask_gc, knob->anim->pixbuf,
|
||||
dx, 0, 0, 0, knob->width, knob->height,
|
||||
GDK_RGB_DITHER_NONE, 0, 0);
|
||||
|
||||
if (GTK_WIDGET_HAS_FOCUS(widget)) {
|
||||
gtk_paint_focus (widget->style, widget->window, widget->state,
|
||||
NULL, widget, NULL, 0, 0,
|
||||
widget->allocation.width, widget->allocation.height);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* gtk_knob_scroll()
|
||||
*
|
||||
*****************************************************************************/
|
||||
static gint
|
||||
gtk_knob_scroll(GtkWidget *widget, GdkEventScroll *event) {
|
||||
GtkKnob *knob;
|
||||
|
||||
g_return_val_if_fail (widget != NULL, FALSE);
|
||||
g_return_val_if_fail (GTK_IS_KNOB (widget), FALSE);
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
g_return_val_if_fail (GTK_IS_ADJUSTMENT (GTK_KNOB (widget)->adjustment), FALSE);
|
||||
|
||||
knob = GTK_KNOB (widget);
|
||||
|
||||
switch (event->direction) {
|
||||
case GDK_SCROLL_UP:
|
||||
knob->adjustment->value += knob->adjustment->step_increment;
|
||||
g_signal_emit_by_name (knob->adjustment, "value_changed");
|
||||
break;
|
||||
case GDK_SCROLL_DOWN:
|
||||
knob->adjustment->value -= knob->adjustment->step_increment;
|
||||
g_signal_emit_by_name (knob->adjustment, "value_changed");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* gtk_knob_button_press()
|
||||
*
|
||||
*****************************************************************************/
|
||||
static gint
|
||||
gtk_knob_button_press(GtkWidget *widget, GdkEventButton *event) {
|
||||
GtkKnob *knob;
|
||||
|
||||
g_return_val_if_fail (widget != NULL, FALSE);
|
||||
g_return_val_if_fail (GTK_IS_KNOB (widget), FALSE);
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
g_return_val_if_fail (GTK_IS_ADJUSTMENT (GTK_KNOB (widget)->adjustment), FALSE);
|
||||
|
||||
knob = GTK_KNOB (widget);
|
||||
|
||||
switch (knob->state) {
|
||||
case STATE_IDLE:
|
||||
switch (event->button) {
|
||||
case 1:
|
||||
case 3:
|
||||
if (!GTK_WIDGET_HAS_FOCUS(widget))
|
||||
gtk_widget_grab_focus(widget);
|
||||
knob->state = STATE_PRESSED;
|
||||
knob->saved_x = event->x;
|
||||
knob->saved_y = event->y;
|
||||
break;
|
||||
case 2:
|
||||
knob->adjustment->value = floor ((knob->adjustment->lower +
|
||||
knob->adjustment->upper + 1.0)
|
||||
* 0.5);
|
||||
g_signal_emit_by_name (knob->adjustment, "value_changed");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* gtk_knob_button_release()
|
||||
*
|
||||
*****************************************************************************/
|
||||
static gint
|
||||
gtk_knob_button_release(GtkWidget *widget, GdkEventButton *event) {
|
||||
GtkKnob *knob;
|
||||
|
||||
g_return_val_if_fail (widget != NULL, FALSE);
|
||||
g_return_val_if_fail (GTK_IS_KNOB (widget), FALSE);
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
g_return_val_if_fail (GTK_IS_ADJUSTMENT (GTK_KNOB (widget)->adjustment), FALSE);
|
||||
|
||||
knob = GTK_KNOB (widget);
|
||||
|
||||
switch (knob->state) {
|
||||
|
||||
case STATE_PRESSED:
|
||||
knob->state = STATE_IDLE;
|
||||
break;
|
||||
|
||||
case STATE_DRAGGING:
|
||||
knob->state = STATE_IDLE;
|
||||
|
||||
switch (event->button) {
|
||||
case 1:
|
||||
case 3:
|
||||
if (knob->policy != GTK_UPDATE_CONTINUOUS
|
||||
&& knob->old_value != knob->adjustment->value)
|
||||
{
|
||||
g_signal_emit_by_name (knob->adjustment, "value_changed");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gint gtk_knob_key_press(GtkWidget *widget, GdkEventKey *event)
|
||||
{
|
||||
GtkKnob *knob;
|
||||
|
||||
g_return_val_if_fail (widget != NULL, FALSE);
|
||||
g_return_val_if_fail (GTK_IS_KNOB (widget), FALSE);
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
g_return_val_if_fail (GTK_IS_ADJUSTMENT (GTK_KNOB (widget)->adjustment), FALSE);
|
||||
|
||||
knob = GTK_KNOB (widget);
|
||||
|
||||
switch (event->keyval) {
|
||||
|
||||
case GDK_Up:
|
||||
if (GTK_WIDGET_HAS_FOCUS (widget))
|
||||
{
|
||||
gtk_adjustment_set_value (knob->adjustment,
|
||||
knob->old_value + knob->adjustment->step_increment);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
case GDK_Down:
|
||||
if (GTK_WIDGET_HAS_FOCUS (widget))
|
||||
{
|
||||
gtk_adjustment_set_value (knob->adjustment,
|
||||
knob->old_value - knob->adjustment->step_increment);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* gtk_knob_motion_notify()
|
||||
*
|
||||
*****************************************************************************/
|
||||
static gint
|
||||
gtk_knob_motion_notify(GtkWidget *widget, GdkEventMotion *event) {
|
||||
GtkKnob *knob;
|
||||
GdkModifierType mods;
|
||||
gint x, y;
|
||||
|
||||
g_return_val_if_fail (widget != NULL, FALSE);
|
||||
g_return_val_if_fail (GTK_IS_KNOB (widget), FALSE);
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
|
||||
knob = GTK_KNOB (widget);
|
||||
|
||||
x = event->x;
|
||||
y = event->y;
|
||||
|
||||
if (event->is_hint || (event->window != widget->window)) {
|
||||
gdk_window_get_pointer (widget->window, &x, &y, &mods);
|
||||
}
|
||||
|
||||
switch (knob->state) {
|
||||
|
||||
case STATE_PRESSED:
|
||||
knob->state = STATE_DRAGGING;
|
||||
/* fall through */
|
||||
|
||||
case STATE_DRAGGING:
|
||||
if (mods & GDK_BUTTON1_MASK) {
|
||||
gtk_knob_update_mouse (knob, x, y, TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
else if (mods & GDK_BUTTON3_MASK) {
|
||||
gtk_knob_update_mouse (knob, x, y, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* gtk_knob_timer()
|
||||
*
|
||||
*****************************************************************************/
|
||||
static gint
|
||||
gtk_knob_timer(GtkKnob *knob) {
|
||||
|
||||
g_return_val_if_fail (knob != NULL, FALSE);
|
||||
g_return_val_if_fail (GTK_IS_KNOB (knob), FALSE);
|
||||
g_return_val_if_fail (GTK_IS_ADJUSTMENT (knob->adjustment), FALSE);
|
||||
|
||||
if (knob->policy == GTK_UPDATE_DELAYED) {
|
||||
g_signal_emit_by_name (knob->adjustment, "value_changed");
|
||||
}
|
||||
|
||||
/* don't keep running this timer */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* gtk_knob_update_mouse_update()
|
||||
*
|
||||
*****************************************************************************/
|
||||
static void
|
||||
gtk_knob_update_mouse_update(GtkKnob *knob) {
|
||||
g_return_if_fail(GTK_IS_ADJUSTMENT (knob->adjustment));
|
||||
|
||||
if (knob->policy == GTK_UPDATE_CONTINUOUS) {
|
||||
g_signal_emit_by_name (knob->adjustment, "value_changed");
|
||||
}
|
||||
else {
|
||||
gtk_widget_queue_draw (GTK_WIDGET (knob));
|
||||
|
||||
if (knob->policy == GTK_UPDATE_DELAYED) {
|
||||
if (knob->timer) {
|
||||
g_source_remove (knob->timer);
|
||||
}
|
||||
knob->timer = g_timeout_add (SCROLL_DELAY_LENGTH,
|
||||
(GSourceFunc) gtk_knob_timer,
|
||||
(gpointer) knob);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* gtk_knob_update_mouse()
|
||||
*
|
||||
*****************************************************************************/
|
||||
static void
|
||||
gtk_knob_update_mouse(GtkKnob *knob, gint x, gint y, gboolean step) {
|
||||
gfloat old_value, new_value, dv, dh;
|
||||
gfloat angle;
|
||||
|
||||
g_return_if_fail (knob != NULL);
|
||||
g_return_if_fail (GTK_IS_KNOB (knob));
|
||||
g_return_if_fail (GTK_IS_ADJUSTMENT (knob->adjustment));
|
||||
|
||||
old_value = knob->adjustment->value;
|
||||
|
||||
angle = atan2f (-y + (knob->height >> 1), x - (knob->width >> 1));
|
||||
|
||||
/* inverted cartesian graphics coordinate system */
|
||||
dv = knob->saved_y - y;
|
||||
dh = x - knob->saved_x;
|
||||
knob->saved_x = x;
|
||||
knob->saved_y = y;
|
||||
|
||||
if ((x >= 0) && (x <= knob->width)) {
|
||||
dh = 0; /* dead zone */
|
||||
} else {
|
||||
angle = cosf (angle);
|
||||
dh *= angle * angle;
|
||||
}
|
||||
|
||||
new_value = knob->adjustment->value +
|
||||
dv * (step ? knob->adjustment->step_increment : knob->adjustment->page_increment) +
|
||||
dh * (knob->adjustment->upper -
|
||||
knob->adjustment->lower) * 0.005; /* 0.005 == (1 / 200) */
|
||||
|
||||
new_value = MAX (MIN (new_value, knob->adjustment->upper),
|
||||
knob->adjustment->lower);
|
||||
|
||||
knob->adjustment->value = new_value;
|
||||
|
||||
if (knob->adjustment->value != old_value) {
|
||||
gtk_knob_update_mouse_update (knob);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* gtk_knob_update()
|
||||
*
|
||||
*****************************************************************************/
|
||||
static void
|
||||
gtk_knob_update(GtkKnob *knob) {
|
||||
gfloat new_value;
|
||||
|
||||
g_return_if_fail (knob != NULL);
|
||||
g_return_if_fail (GTK_IS_KNOB (knob));
|
||||
g_return_if_fail (GTK_IS_ADJUSTMENT (knob->adjustment));
|
||||
|
||||
if (knob->adjustment->step_increment == 1) {
|
||||
new_value = floor (knob->adjustment->value + 0.5);
|
||||
}
|
||||
else {
|
||||
new_value = knob->adjustment->value;
|
||||
}
|
||||
|
||||
if (new_value < knob->adjustment->lower) {
|
||||
new_value = knob->adjustment->lower;
|
||||
}
|
||||
|
||||
if (new_value > knob->adjustment->upper) {
|
||||
new_value = knob->adjustment->upper;
|
||||
}
|
||||
|
||||
if (new_value != knob->adjustment->value) {
|
||||
knob->adjustment->value = new_value;
|
||||
g_signal_emit_by_name (knob->adjustment, "value_changed");
|
||||
}
|
||||
|
||||
gtk_widget_queue_draw (GTK_WIDGET (knob));
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* gtk_knob_adjustment_changed()
|
||||
*
|
||||
*****************************************************************************/
|
||||
static void
|
||||
gtk_knob_adjustment_changed(GtkAdjustment *adjustment, gpointer data) {
|
||||
GtkKnob *knob;
|
||||
|
||||
g_return_if_fail (adjustment != NULL);
|
||||
g_return_if_fail (data != NULL);
|
||||
|
||||
knob = GTK_KNOB (data);
|
||||
|
||||
if ((knob->old_value != adjustment->value) ||
|
||||
(knob->old_lower != adjustment->lower) ||
|
||||
(knob->old_upper != adjustment->upper))
|
||||
{
|
||||
gtk_knob_update (knob);
|
||||
|
||||
knob->old_value = adjustment->value;
|
||||
knob->old_lower = adjustment->lower;
|
||||
knob->old_upper = adjustment->upper;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* gtk_knob_adjustment_value_changed()
|
||||
*
|
||||
*****************************************************************************/
|
||||
static void
|
||||
gtk_knob_adjustment_value_changed (GtkAdjustment *adjustment, gpointer data) {
|
||||
GtkKnob *knob;
|
||||
|
||||
g_return_if_fail (adjustment != NULL);
|
||||
g_return_if_fail (data != NULL);
|
||||
|
||||
knob = GTK_KNOB (data);
|
||||
|
||||
if (knob->old_value != adjustment->value) {
|
||||
gtk_knob_update (knob);
|
||||
knob->old_value = adjustment->value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* gtk_knob_set_animation()
|
||||
*
|
||||
*****************************************************************************/
|
||||
void
|
||||
gtk_knob_set_animation (GtkKnob *knob, GtkKnobAnim *anim) {
|
||||
g_return_if_fail (knob != NULL);
|
||||
g_return_if_fail (anim != NULL);
|
||||
g_return_if_fail (GTK_IS_KNOB (knob));
|
||||
g_return_if_fail (GDK_IS_PIXBUF (anim->pixbuf));
|
||||
|
||||
knob->anim = (GtkKnobAnim *)anim;
|
||||
knob->width = anim->frame_width;
|
||||
knob->height = anim->height;
|
||||
|
||||
if (GTK_WIDGET_REALIZED (knob)) {
|
||||
gtk_widget_queue_resize (GTK_WIDGET (knob));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* gtk_knob_animation_new_from_file()
|
||||
*
|
||||
*****************************************************************************/
|
||||
GtkKnobAnim *
|
||||
gtk_knob_animation_new_from_file(gchar *filename) {
|
||||
GtkKnobAnim *anim;
|
||||
|
||||
anim = gtk_knob_animation_new_from_file_full (filename, -1, -1, KNOB_SIZE);
|
||||
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;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* gtk_knob_new_from_file_full()
|
||||
*
|
||||
* frame_width: overrides the frame width (to make rectangular frames)
|
||||
* but doesn't affect the image size width and height cause optional
|
||||
* scaling if not set to -1 when they are derived from the native
|
||||
* image size.
|
||||
*
|
||||
* FIXME: account for any problems where (width % frame_width != 0)
|
||||
*
|
||||
*****************************************************************************/
|
||||
GtkKnobAnim *
|
||||
gtk_knob_animation_new_from_file_full(gchar *filename, gint frame_width,
|
||||
gint width, gint height) {
|
||||
GtkKnobAnim *anim = g_new0 (GtkKnobAnim, 1);
|
||||
|
||||
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))) {
|
||||
g_error_free(gerror);
|
||||
gerror = NULL;
|
||||
return NULL;
|
||||
}
|
||||
#else /* GTK_MINOR_VERSION >= 10 */
|
||||
if (!(anim->pixbuf = gdk_pixbuf_new_from_file_at_size (filename, width,
|
||||
height, &gerror))) {
|
||||
g_error_free(gerror);
|
||||
gerror = NULL;
|
||||
return NULL;
|
||||
}
|
||||
#endif /* GTK_MINOR_VERSION < 10 */
|
||||
else {
|
||||
anim->height = gdk_pixbuf_get_height (anim->pixbuf);
|
||||
anim->width = gdk_pixbuf_get_width (anim->pixbuf);
|
||||
anim->frame_width = (frame_width != -1) ? frame_width : anim->height;
|
||||
}
|
||||
|
||||
return anim;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* gtk_knob_animation_free()
|
||||
*
|
||||
*****************************************************************************/
|
||||
void
|
||||
gtk_knob_animation_free(GtkKnobAnim *anim) {
|
||||
g_return_if_fail (anim != NULL);
|
||||
|
||||
if (anim->pixbuf)
|
||||
g_object_unref (anim->pixbuf);
|
||||
|
||||
g_free (anim);
|
||||
}
|
||||
102
gtkknob.h
Normal file
102
gtkknob.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Most of this code comes from gAlan 0.2.0, copyright (C) 1999
|
||||
* Tony Garnock-Jones, with modifications by Sean Bolton,
|
||||
* copyright (C) 2004, and minor modifications by William Weston,
|
||||
* copyright (C) 2007, Tomasz Moń, copyright (C) 2009
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*****************************************************************************/
|
||||
#ifndef __GTK_KNOB_H__
|
||||
#define __GTK_KNOB_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GTK_KNOB(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, gtk_knob_get_type(), GtkKnob)
|
||||
#define GTK_KNOB_CLASS(klass) G_TYPE_CHECK_CLASS_CAST(klass, gtk_knob_get_type(), GtkKnobClass)
|
||||
#define GTK_IS_KNOB(obj) G_TYPE_CHECK_INSTANCE_TYPE(obj, gtk_knob_get_type())
|
||||
|
||||
typedef struct _GtkKnob GtkKnob;
|
||||
typedef struct _GtkKnobClass GtkKnobClass;
|
||||
typedef struct _GtkKnobAnim GtkKnobAnim;
|
||||
|
||||
/* better to make this an object and let widgets ref/deref it perhaps */
|
||||
struct _GtkKnobAnim {
|
||||
GdkPixbuf *pixbuf;
|
||||
gint width; /* derived from image width */
|
||||
gint height; /* derived from image height. */
|
||||
gint frame_width; /* derived from pixbuf (width / height) or provided override for rectangular frames */
|
||||
};
|
||||
|
||||
struct _GtkKnob {
|
||||
GtkWidget widget;
|
||||
|
||||
/* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
|
||||
guint policy : 2;
|
||||
|
||||
/* State of widget (to do with user interaction) */
|
||||
guint8 state;
|
||||
gint saved_x, saved_y;
|
||||
|
||||
/* ID of update timer, or 0 if none */
|
||||
guint32 timer;
|
||||
|
||||
/* knob animation */
|
||||
GtkKnobAnim *anim;
|
||||
gint width, height;
|
||||
|
||||
GdkBitmap *mask;
|
||||
GdkGC *mask_gc;
|
||||
GdkGC *red_gc;
|
||||
|
||||
/* Old values from adjustment stored so we know when something changes */
|
||||
gfloat old_value;
|
||||
gfloat old_lower;
|
||||
gfloat old_upper;
|
||||
|
||||
/* The adjustment object that stores the data for this knob */
|
||||
GtkAdjustment *adjustment;
|
||||
};
|
||||
|
||||
struct _GtkKnobClass {
|
||||
GtkWidgetClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
extern GtkWidget *gtk_knob_new(GtkAdjustment *adjustment, GtkKnobAnim *anim);
|
||||
extern GType gtk_knob_get_type(void);
|
||||
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,
|
||||
gint height);
|
||||
|
||||
GtkKnobAnim *gtk_knob_animation_new_from_file(gchar *filename);
|
||||
void gtk_knob_set_animation (GtkKnob *knob, GtkKnobAnim *anim);
|
||||
void gtk_knob_animation_free(GtkKnobAnim *anim);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
671
gui.c
671
gui.c
@@ -19,17 +19,35 @@
|
||||
#include "gui.h"
|
||||
#include "effects.h"
|
||||
#include "preset.h"
|
||||
#include "gtkknob.h"
|
||||
#include "knob.h"
|
||||
|
||||
extern EffectList effects[];
|
||||
extern int n_effects;
|
||||
typedef struct {
|
||||
GtkObject *widget;
|
||||
|
||||
static gboolean allow_send = FALSE;
|
||||
/* 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 */
|
||||
} WidgetTreeElem;
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
static GtkKnobAnim *knob_anim = NULL; /* animation used by knobs */
|
||||
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
|
||||
static GTree *widget_tree = NULL; /**< this tree contains lists containing WidgetTreeElem data elements */
|
||||
static gboolean allow_send = FALSE; /**< if FALSE GUI parameter changes won't be sent to device */
|
||||
|
||||
/**
|
||||
* \param parent transient parent, or NULL for none
|
||||
* \param message error description
|
||||
*
|
||||
* Shows error message dialog.
|
||||
**/
|
||||
void show_error_message(GtkWidget *parent, gchar *message)
|
||||
{
|
||||
g_return_if_fail(message != NULL);
|
||||
|
||||
GtkWidget *msg = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL,
|
||||
GtkWidget *msg = gtk_message_dialog_new(GTK_WINDOW(parent),
|
||||
GTK_DIALOG_MODAL,
|
||||
GTK_MESSAGE_ERROR,
|
||||
GTK_BUTTONS_OK,
|
||||
message);
|
||||
@@ -38,137 +56,280 @@ void show_error_message(GtkWidget *parent, gchar *message)
|
||||
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)
|
||||
/**
|
||||
* \param adj the object which emitted the signal
|
||||
* \param setting setting controlled by adj
|
||||
*
|
||||
* Sets effect value.
|
||||
**/
|
||||
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->id, setting->position, (gint)val);
|
||||
}
|
||||
|
||||
if (setting->values != NULL && setting->values->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->values->min) && (x <= setting->values->max)) {
|
||||
label = g_object_get_data(G_OBJECT(adj), "label");
|
||||
gtk_label_set_text(GTK_LABEL(label), setting->values->labels[x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \param button the object which emitted the signal
|
||||
* \param effect effect controlled by button
|
||||
*
|
||||
* Turns effect on/off basing on state of button.
|
||||
**/
|
||||
void toggled_cb(GtkToggleButton *button, Effect *effect)
|
||||
{
|
||||
g_return_if_fail(effect != NULL);
|
||||
|
||||
if (allow_send) {
|
||||
guint val = gtk_toggle_button_get_active(button);
|
||||
set_option(effect->option, effect->position, val);
|
||||
set_option(effect->id, effect->position, val);
|
||||
}
|
||||
}
|
||||
|
||||
static void widget_list_add(GList **list, GtkWidget *widget, gint id, gint position, gint value, gint x)
|
||||
/**
|
||||
* \param widget GtkObject to add to widget tree
|
||||
* \param id object controlled ID
|
||||
* \param position object controlled position
|
||||
* \param value effect value type (if widget is GtkComboBox, otherwise -1)
|
||||
* \param x combo box item number (if widget is GtkComboBox, otherwise -1)
|
||||
*
|
||||
* Adds widget to widget tree.
|
||||
**/
|
||||
static WidgetTreeElem *widget_tree_add(GtkObject *widget, gint id, gint position, gint value, gint x)
|
||||
{
|
||||
WidgetListElem *el;
|
||||
GList *list;
|
||||
WidgetTreeElem *el;
|
||||
gpointer key;
|
||||
|
||||
el = g_malloc(sizeof(WidgetListElem));
|
||||
el = g_slice_new(WidgetTreeElem);
|
||||
el->widget = widget;
|
||||
el->id = id;
|
||||
el->position = position;
|
||||
el->value = value;
|
||||
el->x = x;
|
||||
|
||||
*list = g_list_prepend(*list, el);
|
||||
key = GINT_TO_POINTER((position << 16) | id);
|
||||
|
||||
list = g_tree_lookup(widget_tree, key);
|
||||
|
||||
if (list == NULL) {
|
||||
list = g_list_append(list, el);
|
||||
g_tree_insert(widget_tree, key, list);
|
||||
} else {
|
||||
list = g_list_append(list, el);
|
||||
|
||||
/* replace the list pointer */
|
||||
g_tree_steal(widget_tree, key);
|
||||
g_tree_insert(widget_tree, key, list);
|
||||
}
|
||||
|
||||
return el;
|
||||
}
|
||||
|
||||
static void apply_widget_setting(WidgetListElem *el, SettingParam *param)
|
||||
/**
|
||||
* \param el widget tree element
|
||||
* \param param parameter to set
|
||||
*
|
||||
* Sets widget tree element value to param value.
|
||||
**/
|
||||
static void apply_widget_setting(WidgetTreeElem *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);
|
||||
}
|
||||
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_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);
|
||||
}
|
||||
}
|
||||
|
||||
static void apply_preset_to_gui(GList *list, Preset *preset)
|
||||
/**
|
||||
* \param param SettingParam to apply to GUI
|
||||
*
|
||||
* Applies SettingParam to GUI
|
||||
**/
|
||||
void apply_setting_param_to_gui(SettingParam *param)
|
||||
{
|
||||
gpointer key;
|
||||
g_return_if_fail(param != NULL);
|
||||
|
||||
allow_send = FALSE;
|
||||
key = GINT_TO_POINTER((param->position << 16) | param->id);
|
||||
GList *list = g_tree_lookup(widget_tree, key);
|
||||
g_list_foreach(list, (GFunc)apply_widget_setting, param);
|
||||
allow_send = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param preset preset to sync
|
||||
*
|
||||
* Synces GUI with preset.
|
||||
**/
|
||||
static void apply_preset_to_gui(Preset *preset)
|
||||
{
|
||||
g_return_if_fail(preset != NULL);
|
||||
g_return_if_fail(widget_tree != NULL);
|
||||
|
||||
allow_send = FALSE;
|
||||
|
||||
GList *iter = preset->params;
|
||||
while (iter) {
|
||||
gpointer key;
|
||||
|
||||
SettingParam *param = iter->data;
|
||||
iter = iter->next;
|
||||
|
||||
if (param != NULL)
|
||||
if (param != NULL) {
|
||||
key = GINT_TO_POINTER((param->position << 16) | param->id);
|
||||
GList *list = g_tree_lookup(widget_tree, key);
|
||||
g_list_foreach(list, (GFunc)apply_widget_setting, param);
|
||||
}
|
||||
}
|
||||
|
||||
allow_send = TRUE;
|
||||
}
|
||||
|
||||
static void apply_current_preset(GList *list)
|
||||
/**
|
||||
* Synces GUI with device current edit buffer.
|
||||
**/
|
||||
static void apply_current_preset()
|
||||
{
|
||||
GString *msg = get_current_preset();
|
||||
Preset *preset = create_preset_from_data(msg);
|
||||
g_string_free(msg, TRUE);
|
||||
apply_preset_to_gui(list, preset);
|
||||
GList *list = get_current_preset();
|
||||
Preset *preset = create_preset_from_data(list);
|
||||
preset_list_free(list);
|
||||
apply_preset_to_gui(preset);
|
||||
preset_free(preset);
|
||||
}
|
||||
|
||||
GtkWidget *create_table(GList **list, EffectSettings *settings, gint amt)
|
||||
gboolean apply_current_preset_to_gui(gpointer data)
|
||||
{
|
||||
GtkWidget *table, *label, *widget;
|
||||
apply_current_preset();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param settings effect parameters
|
||||
* \param amt amount of effect parameters
|
||||
* \param widget_table hash table matching settings pointer with created table (may be NULL)
|
||||
*
|
||||
* Creates knobs that allow user to set effect parameters.
|
||||
*
|
||||
* \return GtkTable containing necessary widgets to set effect parameters.
|
||||
**/
|
||||
GtkWidget *create_table(EffectSettings *settings, gint amt, GHashTable *widget_table)
|
||||
{
|
||||
GtkWidget *table, *label, *widget, *knob;
|
||||
GtkObject *adj;
|
||||
int x;
|
||||
|
||||
table = gtk_table_new(2, amt, FALSE);
|
||||
if (widget_table != NULL) {
|
||||
table = g_hash_table_lookup(widget_table, settings);
|
||||
if (table != NULL)
|
||||
return table;
|
||||
}
|
||||
|
||||
table = gtk_table_new(3, amt, FALSE);
|
||||
|
||||
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, 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);
|
||||
adj = gtk_adjustment_new(0.0, settings[x].values->min, settings[x].values->max,
|
||||
1.0, /* step increment */
|
||||
MAX((settings[x].values->max / 100), 5.0), /* page increment */
|
||||
0.0);
|
||||
knob = gtk_knob_new(GTK_ADJUSTMENT(adj), knob_anim);
|
||||
|
||||
if (settings[x].values->labels == NULL) {
|
||||
widget = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1.0, 0);
|
||||
gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(widget), TRUE);
|
||||
gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(widget), GTK_UPDATE_IF_VALID);
|
||||
} else {
|
||||
widget = gtk_label_new(settings[x].values->labels[0]);
|
||||
g_object_set_data(G_OBJECT(adj), "label", widget);
|
||||
}
|
||||
|
||||
widget_tree_add(adj, settings[x].id, 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);
|
||||
gtk_table_attach(GTK_TABLE(table), knob, 1, 2, x, x+1, GTK_SHRINK, GTK_SHRINK, 2, 2);
|
||||
gtk_table_attach(GTK_TABLE(table), widget, 2, 3, x, x+1, GTK_SHRINK, GTK_SHRINK, 2, 2);
|
||||
|
||||
g_signal_connect(G_OBJECT(adj), "value-changed", G_CALLBACK(value_changed_option_cb), &settings[x]);
|
||||
|
||||
if (widget_table != NULL) {
|
||||
g_hash_table_insert(widget_table, settings, table);
|
||||
}
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
GtkWidget *create_on_off_button(GList **list, Effect *effect)
|
||||
/**
|
||||
* \param effect Effect that can be turned on/off
|
||||
*
|
||||
* Creates toggle button that allow user to turn effect on/off.
|
||||
*
|
||||
* \return GtkToggleButton
|
||||
**/
|
||||
GtkWidget *create_on_off_button(Effect *effect)
|
||||
{
|
||||
GtkWidget *button = gtk_toggle_button_new_with_label(effect->label);
|
||||
GtkWidget *button;
|
||||
if (effect->label == NULL)
|
||||
button = gtk_check_button_new();
|
||||
else
|
||||
button = gtk_check_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);
|
||||
widget_tree_add(GTK_OBJECT(button), effect->id, effect->position, -1, -1);
|
||||
return button;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
gint id; /* effect group ID (value) */
|
||||
gint option; /* option ID */
|
||||
gint position; /* position */
|
||||
GtkWidget *child; /* child widget */
|
||||
gint type; /**< effect group type (value) */
|
||||
gint id; /**< option ID */
|
||||
gint position; /**< position */
|
||||
GtkWidget *child; /**< child widget */
|
||||
} EffectSettingsGroup;
|
||||
|
||||
/**
|
||||
* \param group group to be freed
|
||||
*
|
||||
* Frees all memory used by group
|
||||
**/
|
||||
void effect_settings_group_free(EffectSettingsGroup *group)
|
||||
{
|
||||
/* destroy widget without parent */
|
||||
if (gtk_widget_get_parent(group->child) == NULL)
|
||||
gtk_widget_destroy(group->child);
|
||||
if (group->child != NULL) {
|
||||
/* destroy widget without parent */
|
||||
if (gtk_widget_get_parent(group->child) == NULL)
|
||||
gtk_widget_destroy(group->child);
|
||||
|
||||
g_object_unref(group->child);
|
||||
g_free(group);
|
||||
g_object_unref(group->child);
|
||||
}
|
||||
|
||||
g_slice_free(EffectSettingsGroup, group);
|
||||
}
|
||||
|
||||
/**
|
||||
* \param widget the object which emitted the signal
|
||||
* \param data user data (unused, can be anything)
|
||||
*
|
||||
* Switches effect type and shows widgets allowing to set selected effect type parameters.
|
||||
**/
|
||||
void combo_box_changed_cb(GtkComboBox *widget, gpointer data)
|
||||
{
|
||||
GtkWidget *child;
|
||||
@@ -186,23 +347,41 @@ void combo_box_changed_cb(GtkComboBox *widget, gpointer data)
|
||||
g_free(name);
|
||||
|
||||
if (settings != NULL && allow_send)
|
||||
set_option(settings->option, settings->position, settings->id);
|
||||
set_option(settings->id, settings->position, settings->type);
|
||||
|
||||
child = g_object_get_data(G_OBJECT(widget), "active_child");
|
||||
if (child == settings->child) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (child != NULL) {
|
||||
gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(gtk_widget_get_parent(vbox))), child);
|
||||
}
|
||||
gtk_container_add(GTK_CONTAINER(gtk_widget_get_parent(gtk_widget_get_parent(vbox))), settings->child);
|
||||
gtk_widget_show_all(gtk_widget_get_parent(gtk_widget_get_parent(vbox)));
|
||||
|
||||
if (settings->child != NULL) {
|
||||
gtk_container_add(GTK_CONTAINER(gtk_widget_get_parent(gtk_widget_get_parent(vbox))), settings->child);
|
||||
gtk_widget_show_all(gtk_widget_get_parent(gtk_widget_get_parent(vbox)));
|
||||
}
|
||||
g_object_set_data(G_OBJECT(widget), "active_child", settings->child);
|
||||
}
|
||||
}
|
||||
|
||||
GtkWidget *create_widget_container(GList **list, EffectGroup *group, gint amt)
|
||||
/**
|
||||
* \param group Effect type groups
|
||||
* \param amt amount of effect groups
|
||||
* \param id ID to set effect type
|
||||
* \param position position
|
||||
*
|
||||
* Creates widget allowing user to choose effect type.
|
||||
*
|
||||
* \return widget that allow user to set effect type.
|
||||
**/
|
||||
GtkWidget *create_widget_container(EffectGroup *group, gint amt, gint id, gint position)
|
||||
{
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *widget;
|
||||
GtkWidget *combo_box = NULL;
|
||||
GHashTable *widget_table;
|
||||
EffectSettingsGroup *settings = NULL;
|
||||
gchar *name = NULL;
|
||||
gint x;
|
||||
@@ -210,6 +389,8 @@ GtkWidget *create_widget_container(GList **list, EffectGroup *group, gint amt)
|
||||
|
||||
vbox = gtk_vbox_new(FALSE, 0);
|
||||
|
||||
widget_table = g_hash_table_new(g_direct_hash, g_direct_equal);
|
||||
|
||||
for (x = 0; x<amt; x++) {
|
||||
if (group[x].label) {
|
||||
if (combo_box == NULL) {
|
||||
@@ -221,51 +402,85 @@ GtkWidget *create_widget_container(GList **list, EffectGroup *group, gint amt)
|
||||
gtk_combo_box_append_text(GTK_COMBO_BOX(combo_box), group[x].label);
|
||||
cmbox_no++;
|
||||
|
||||
widget = create_table(list, group[x].settings, group[x].settings_amt);
|
||||
g_object_ref_sink(widget);
|
||||
if ((group[x].settings != NULL) && (group[x].settings_amt > 0)) {
|
||||
widget = create_table(group[x].settings, group[x].settings_amt, widget_table);
|
||||
g_object_ref_sink(widget);
|
||||
} else
|
||||
widget = NULL;
|
||||
|
||||
settings = g_malloc(sizeof(EffectSettingsGroup));
|
||||
settings->id = group[x].id;
|
||||
settings->option = group[x].option;
|
||||
settings->position = group[x].position;
|
||||
settings = g_slice_new(EffectSettingsGroup);
|
||||
settings->id = id;
|
||||
settings->type = group[x].type;
|
||||
settings->position = position;
|
||||
settings->child = widget;
|
||||
widget_list_add(list, combo_box, group[x].option, group[x].position, group[x].id, x);
|
||||
|
||||
widget_tree_add(GTK_OBJECT(combo_box), id, position, group[x].type, 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(list, group[x].settings, group[x].settings_amt);
|
||||
gtk_container_add(GTK_CONTAINER(vbox), widget);
|
||||
if ((group[x].settings != NULL) && (group[x].settings_amt > 0)) {
|
||||
widget = create_table(group[x].settings, group[x].settings_amt, widget_table);
|
||||
gtk_container_add(GTK_CONTAINER(vbox), widget);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return vbox;
|
||||
};
|
||||
g_hash_table_destroy(widget_table);
|
||||
|
||||
GtkWidget *create_vbox(GList **list, Effect *widgets, gint amt)
|
||||
return vbox;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param widgets Effect descriptions
|
||||
* \param amt amount of effect descriptions
|
||||
* \param label frame label (can be NULL)
|
||||
*
|
||||
* Creates frame (with optional label) containing widgets allowing user to set effect options.
|
||||
*
|
||||
* \return widget that allow user to set effect options.
|
||||
**/
|
||||
GtkWidget *create_vbox(Effect *widgets, gint amt, gchar *label)
|
||||
{
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *widget;
|
||||
GtkWidget *table;
|
||||
GtkWidget *container;
|
||||
GtkWidget *frame;
|
||||
int x;
|
||||
int y;
|
||||
|
||||
frame = gtk_frame_new(label);
|
||||
|
||||
vbox = gtk_vbox_new(FALSE, 0);
|
||||
hbox = gtk_hbox_new(FALSE, 0);
|
||||
|
||||
gtk_box_set_homogeneous(GTK_BOX(hbox), TRUE);
|
||||
table = gtk_table_new(2, amt, FALSE);
|
||||
gtk_table_set_col_spacings(GTK_TABLE(table), 2);
|
||||
|
||||
for (x = 0; x<amt; x++) {
|
||||
widget = create_on_off_button(list, &widgets[x]);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), widget, TRUE, TRUE, 2);
|
||||
if ((widgets[x].id != -1) && (widgets[x].position != -1)) {
|
||||
widget = create_on_off_button(&widgets[x]);
|
||||
gtk_table_attach_defaults(GTK_TABLE(table), widget, 0, 1, x, x+1);
|
||||
|
||||
table = create_widget_container(list, widgets[x].group, widgets[x].group_amt);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), table, TRUE, TRUE, 2);
|
||||
if (widgets[x].label)
|
||||
y = 1;
|
||||
else
|
||||
y = 0;
|
||||
|
||||
} else if (widgets[x].label) {
|
||||
widget = gtk_label_new(widgets[x].label);
|
||||
gtk_table_attach_defaults(GTK_TABLE(table), widget, 0, 1, x, x+1);
|
||||
y = 0;
|
||||
}
|
||||
|
||||
container = create_widget_container(widgets[x].group, widgets[x].group_amt, widgets[x].type, widgets[x].position);
|
||||
gtk_table_attach_defaults(GTK_TABLE(table), container, 1-y, 2-y, x+y, x+y+1);
|
||||
}
|
||||
gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 2);
|
||||
|
||||
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
|
||||
return vbox;
|
||||
gtk_container_add(GTK_CONTAINER(frame), vbox);
|
||||
return frame;
|
||||
}
|
||||
|
||||
enum {
|
||||
@@ -275,6 +490,14 @@ enum {
|
||||
NUM_COLUMNS
|
||||
};
|
||||
|
||||
/**
|
||||
* \param treeview the object which emitted the signal
|
||||
* \param path the GtkTreePath for the activated row
|
||||
* \param column the GtkTreeViewColumn in which the activation occurred
|
||||
* \param model model holding preset names
|
||||
*
|
||||
* Sets active device preset to preset selected by user.
|
||||
**/
|
||||
void row_activate_cb(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, GtkTreeModel *model) {
|
||||
GtkTreeIter iter;
|
||||
gint id;
|
||||
@@ -284,13 +507,18 @@ void row_activate_cb(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn
|
||||
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);
|
||||
apply_current_preset();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \param model model to fill
|
||||
* \param bank preset bank
|
||||
* \param name preset bank description visible to user
|
||||
*
|
||||
* Appends to model preset names found in device preset bank.
|
||||
**/
|
||||
static void fill_store_with_presets(GtkTreeStore *model, guint bank, gchar *name)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
@@ -298,6 +526,8 @@ static void fill_store_with_presets(GtkTreeStore *model, guint bank, gchar *name
|
||||
int x;
|
||||
|
||||
GStrv presets = query_preset_names(bank);
|
||||
g_return_if_fail(presets != NULL);
|
||||
|
||||
gtk_tree_store_append(model, &iter, NULL);
|
||||
gtk_tree_store_set(model, &iter,
|
||||
PRESET_NAME_COLUMN, name,
|
||||
@@ -306,29 +536,53 @@ static void fill_store_with_presets(GtkTreeStore *model, guint bank, gchar *name
|
||||
-1);
|
||||
|
||||
for (x=0; x<g_strv_length(presets); x++) {
|
||||
gchar *tmp = g_strdup_printf("%d - %s", x+1, presets[x]);
|
||||
|
||||
gtk_tree_store_append(model, &child_iter, &iter);
|
||||
gtk_tree_store_set(model, &child_iter,
|
||||
PRESET_NAME_COLUMN, presets[x],
|
||||
PRESET_NAME_COLUMN, tmp,
|
||||
PRESET_NUMBER_COLUMN, x,
|
||||
PRESET_BANK_COLUMN, bank,
|
||||
-1);
|
||||
|
||||
g_free(tmp);
|
||||
}
|
||||
g_strfreev(presets);
|
||||
}
|
||||
|
||||
/**
|
||||
* \param model model to fill
|
||||
*
|
||||
* Fills model with preset names found on device.
|
||||
**/
|
||||
static void fill_store(GtkTreeStore *model)
|
||||
{
|
||||
fill_store_with_presets(model, PRESETS_USER, "User Presets");
|
||||
fill_store_with_presets(model, PRESETS_SYSTEM, "System Presets");
|
||||
Device *device = g_object_get_data(G_OBJECT(model), "device");
|
||||
|
||||
g_return_if_fail(device != NULL);
|
||||
|
||||
gint i;
|
||||
for (i=0; i<device->n_banks; i++)
|
||||
fill_store_with_presets(model,
|
||||
device->banks[i].bank,
|
||||
device->banks[i].name);
|
||||
}
|
||||
|
||||
GtkWidget *create_preset_tree(GList **list)
|
||||
/**
|
||||
* \param device device information
|
||||
*
|
||||
* Creates treeview showing list of presets available on device.
|
||||
*
|
||||
* \return treeview containing all preset names found on device.
|
||||
**/
|
||||
GtkWidget *create_preset_tree(Device *device)
|
||||
{
|
||||
GtkWidget *treeview;
|
||||
GtkTreeStore *store;
|
||||
GtkCellRenderer *renderer;
|
||||
|
||||
store = gtk_tree_store_new(NUM_COLUMNS, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT);
|
||||
g_object_set_data(G_OBJECT(store), "device", device);
|
||||
fill_store(store);
|
||||
|
||||
treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
|
||||
@@ -344,14 +598,18 @@ GtkWidget *create_preset_tree(GList **list)
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param window application toplevel window
|
||||
* \param default_name default preset name
|
||||
*
|
||||
* Shows window allowing user to store current edit buffer.
|
||||
**/
|
||||
static void show_store_preset_window(GtkWidget *window, gchar *default_name)
|
||||
{
|
||||
GtkWidget *dialog, *cmbox, *entry, *table, *label;
|
||||
GtkWidget *dialog, *cmbox, *entry, *table, *label, *vbox;
|
||||
GStrv names;
|
||||
int x;
|
||||
|
||||
@@ -362,8 +620,10 @@ static void show_store_preset_window(GtkWidget *window, gchar *default_name)
|
||||
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
|
||||
NULL);
|
||||
|
||||
vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
|
||||
|
||||
table = gtk_table_new(2, 2, FALSE);
|
||||
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), table);
|
||||
gtk_container_add(GTK_CONTAINER(vbox), table);
|
||||
|
||||
cmbox = gtk_combo_box_new_text();
|
||||
names = query_preset_names(PRESETS_USER);
|
||||
@@ -386,7 +646,7 @@ static void show_store_preset_window(GtkWidget *window, gchar *default_name)
|
||||
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);
|
||||
gtk_widget_show_all(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) {
|
||||
@@ -397,12 +657,22 @@ static void show_store_preset_window(GtkWidget *window, gchar *default_name)
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
/**
|
||||
* \param action the object which emitted the signal
|
||||
*
|
||||
* Shows store preset window.
|
||||
**/
|
||||
static void action_store_cb(GtkAction *action)
|
||||
{
|
||||
GtkWidget *window = g_object_get_data(G_OBJECT(action), "window");
|
||||
show_store_preset_window(window, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* \param action the object which emitted the signal
|
||||
*
|
||||
* Shows about dialog.
|
||||
**/
|
||||
static void action_show_about_dialog_cb(GtkAction *action)
|
||||
{
|
||||
static const gchar * const authors[] = {
|
||||
@@ -421,6 +691,8 @@ static void action_show_about_dialog_cb(GtkAction *action)
|
||||
NULL);
|
||||
}
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
typedef struct {
|
||||
gchar *name;
|
||||
gchar *suffix;
|
||||
@@ -428,9 +700,19 @@ typedef struct {
|
||||
|
||||
static SupportedFileTypes file_types[] = {
|
||||
{"RP250Preset", "*.rp250p"},
|
||||
{"RP500Preset", "*.rp500p"},
|
||||
};
|
||||
|
||||
static guint n_file_types = G_N_ELEMENTS(file_types);
|
||||
|
||||
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
|
||||
|
||||
/**
|
||||
* \param action the object which emitted the signal
|
||||
*
|
||||
* Shows file chooser dialog.
|
||||
* If user opens valid preset file, the preset gets applied to edit buffer and store preset window is shown.
|
||||
**/
|
||||
static void action_open_preset_cb(GtkAction *action)
|
||||
{
|
||||
static GtkWidget *dialog = NULL;
|
||||
@@ -439,7 +721,6 @@ static void action_open_preset_cb(GtkAction *action)
|
||||
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,
|
||||
@@ -465,11 +746,15 @@ static void action_open_preset_cb(GtkAction *action)
|
||||
|
||||
gboolean loaded = FALSE;
|
||||
while (!loaded && gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
||||
GError *error = NULL;
|
||||
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);
|
||||
Preset *preset = create_preset_from_xml_file(filename, &error);
|
||||
if (error) {
|
||||
show_error_message(window, error->message);
|
||||
g_error_free(error);
|
||||
error = NULL;
|
||||
} else if (preset != NULL) {
|
||||
apply_preset_to_gui(preset);
|
||||
|
||||
gtk_widget_hide(dialog);
|
||||
|
||||
@@ -518,27 +803,35 @@ static void action_open_preset_cb(GtkAction *action)
|
||||
dialog = NULL;
|
||||
}
|
||||
|
||||
static void widget_list_free(GList *list)
|
||||
/**
|
||||
* \param list widget tree list to be freed
|
||||
*
|
||||
* Frees all memory used by widget tree list.
|
||||
*/
|
||||
static void widget_tree_elem_free(GList *list)
|
||||
{
|
||||
GList *iter;
|
||||
for (iter = list; iter; iter = iter->next) {
|
||||
g_free(iter->data);
|
||||
g_slice_free(WidgetTreeElem, iter->data);
|
||||
}
|
||||
g_list_free(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* \param action the object which emitted the signal
|
||||
*
|
||||
* Destroys action object "window" data, then stops gtk main loop.
|
||||
**/
|
||||
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();
|
||||
}
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
static GtkActionEntry entries[] = {
|
||||
{"File", NULL, "_File"},
|
||||
{"Preset", NULL, "_Preset"},
|
||||
@@ -567,16 +860,32 @@ static const gchar *menu_info =
|
||||
" </menubar>"
|
||||
"</ui>";
|
||||
|
||||
static void add_action_data(GtkUIManager *ui, const gchar *path, GtkWidget *window, GList **list)
|
||||
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
|
||||
|
||||
/**
|
||||
* \param ui GtkUIManager to lookup actions
|
||||
* \param path path to action
|
||||
* \param window toplevel window
|
||||
*
|
||||
* Sets action object "window" data to toplevel window.
|
||||
**/
|
||||
static void add_action_data(GtkUIManager *ui, const gchar *path, GtkWidget *window)
|
||||
{
|
||||
GtkAction *action;
|
||||
|
||||
action = gtk_ui_manager_get_action(ui, path);
|
||||
g_return_if_fail(action != NULL);
|
||||
|
||||
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)
|
||||
/**
|
||||
* \param window toplevel window
|
||||
* \param vbox vbox to hold menubar
|
||||
*
|
||||
* Creates menubar (adds accel group to toplevel window as well) and packs it into vbox.
|
||||
**/
|
||||
static void add_menubar(GtkWidget *window, GtkWidget *vbox)
|
||||
{
|
||||
GtkUIManager *ui;
|
||||
GtkActionGroup *actions;
|
||||
@@ -599,23 +908,42 @@ static void add_menubar(GList **list, GtkWidget *window, GtkWidget *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);
|
||||
add_action_data(ui, "/MenuBar/File/Quit", window);
|
||||
add_action_data(ui, "/MenuBar/File/Open", window);
|
||||
add_action_data(ui, "/MenuBar/Preset/Store", window);
|
||||
add_action_data(ui, "/MenuBar/Help/About", window);
|
||||
|
||||
g_object_unref(ui);
|
||||
}
|
||||
|
||||
void create_window()
|
||||
static gint widget_tree_key_compare_func(gconstpointer a, gconstpointer b, gpointer data)
|
||||
{
|
||||
gint position_a = GPOINTER_TO_INT(a) & 0xFF0000;
|
||||
gint position_b = GPOINTER_TO_INT(b) & 0xFF0000;
|
||||
|
||||
if (position_a > position_b) {
|
||||
return 1;
|
||||
} else if (position_a == position_b) {
|
||||
gint val_a = GPOINTER_TO_INT(a) & 0xFFFF;
|
||||
gint val_b = GPOINTER_TO_INT(b) & 0xFFFF;
|
||||
return val_a - val_b;
|
||||
} else
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates main window.
|
||||
**/
|
||||
void gui_create(Device *device)
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *widget;
|
||||
GtkWidget *notebook;
|
||||
GtkWidget *sw; /* scrolled window to carry preset treeview */
|
||||
static GList *list = NULL; /* widget list (every data element is WidgetListElem) */
|
||||
gint x;
|
||||
gint i;
|
||||
|
||||
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_title(GTK_WINDOW(window), "gdigi");
|
||||
@@ -623,7 +951,7 @@ void create_window()
|
||||
vbox = gtk_vbox_new(FALSE, 0);
|
||||
gtk_container_add(GTK_CONTAINER(window), vbox);
|
||||
|
||||
add_menubar(&list, window, vbox);
|
||||
add_menubar(window, vbox);
|
||||
|
||||
hbox = gtk_hbox_new(FALSE, 0);
|
||||
gtk_container_add(GTK_CONTAINER(vbox), hbox);
|
||||
@@ -632,23 +960,106 @@ void create_window()
|
||||
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);
|
||||
widget = create_preset_tree(device);
|
||||
gtk_container_add(GTK_CONTAINER(sw), widget);
|
||||
|
||||
vbox = gtk_vbox_new(FALSE, 0);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 2);
|
||||
notebook = gtk_notebook_new();
|
||||
gtk_box_pack_start(GTK_BOX(hbox), notebook, TRUE, TRUE, 2);
|
||||
|
||||
for (x = 0; x<n_effects; x++) {
|
||||
if ((x % 3) == 0) {
|
||||
hbox = gtk_hbox_new(TRUE, 0);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 2);
|
||||
knob_anim = gtk_knob_animation_new_from_inline(knob_pixbuf);
|
||||
|
||||
widget_tree = g_tree_new_full(widget_tree_key_compare_func,
|
||||
NULL, /* key compare data */
|
||||
NULL, /* key destroy func */
|
||||
(GDestroyNotify) widget_tree_elem_free);
|
||||
|
||||
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), device->n_pages > 1 ? TRUE : FALSE);
|
||||
|
||||
for (i = 0; i<device->n_pages; i++) {
|
||||
GtkWidget *label = NULL;
|
||||
vbox = gtk_vbox_new(FALSE, 0);
|
||||
label = gtk_label_new(device->pages[i].name);
|
||||
|
||||
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label);
|
||||
|
||||
for (x = 0; x<device->pages[i].n_effects; x++) {
|
||||
if ((x % ((device->pages[i].n_effects+1)/device->pages[i].n_rows)) == 0) {
|
||||
hbox = gtk_hbox_new(FALSE, 0);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 2);
|
||||
}
|
||||
widget = create_vbox(device->pages[i].effects[x].effect, device->pages[i].effects[x].amt, device->pages[i].effects[x].label);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), widget, TRUE, TRUE, 2);
|
||||
}
|
||||
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);
|
||||
apply_current_preset();
|
||||
gtk_widget_show_all(window);
|
||||
|
||||
g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(gtk_main_quit), NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees memory allocated by gui_create which is not explicitly freed when main window is destroyed.
|
||||
**/
|
||||
void gui_free()
|
||||
{
|
||||
g_tree_destroy(widget_tree);
|
||||
widget_tree = NULL;
|
||||
|
||||
gtk_knob_animation_free(knob_anim);
|
||||
knob_anim = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param device Variable to hold device information
|
||||
*
|
||||
* Displays dialogbox stating that device is unsupported.
|
||||
*
|
||||
* \return TRUE if user selects "compability mode", otherwise FALSE.
|
||||
**/
|
||||
gboolean unsupported_device_dialog(Device **device)
|
||||
{
|
||||
extern Device* supported_devices[];
|
||||
extern int n_supported_devices;
|
||||
|
||||
GtkWidget *dialog;
|
||||
GtkWidget *label;
|
||||
GtkWidget *combo_box;
|
||||
GtkWidget *vbox;
|
||||
int x;
|
||||
|
||||
dialog = gtk_dialog_new_with_buttons("Unsupported device",
|
||||
NULL, GTK_DIALOG_MODAL,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
|
||||
NULL);
|
||||
|
||||
vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
|
||||
|
||||
label = gtk_label_new("Your device appears to be unsupported by gdigi.\n"
|
||||
"As some of the settings may be common between different devices,\n"
|
||||
"you can now select compability mode with one of the supported devices.\n"
|
||||
"Please take a look at gdigi's HACKING file.");
|
||||
gtk_container_add(GTK_CONTAINER(vbox), label);
|
||||
|
||||
combo_box = gtk_combo_box_new_text();
|
||||
for (x=0; x<n_supported_devices; x++) {
|
||||
gtk_combo_box_append_text(GTK_COMBO_BOX(combo_box), supported_devices[x]->name);
|
||||
}
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(vbox), combo_box);
|
||||
|
||||
gtk_widget_show_all(vbox);
|
||||
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
||||
gint number = gtk_combo_box_get_active(GTK_COMBO_BOX(combo_box));
|
||||
if (number != -1 && number <n_supported_devices) {
|
||||
g_message("Starting %s compability mode", supported_devices[number]->name);
|
||||
*device = supported_devices[number];
|
||||
gtk_widget_destroy(dialog);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_widget_destroy(dialog);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
9
gui.h
9
gui.h
@@ -17,7 +17,14 @@
|
||||
#ifndef GDIGI_GUI_H
|
||||
#define GDIGI_GUI_H
|
||||
|
||||
#include <glib.h>
|
||||
#include "effects.h"
|
||||
|
||||
void show_error_message(GtkWidget *parent, gchar *message);
|
||||
void create_window();
|
||||
void apply_setting_param_to_gui(SettingParam *param);
|
||||
gboolean apply_current_preset_to_gui(gpointer data);
|
||||
void gui_create(Device *device);
|
||||
void gui_free();
|
||||
gboolean unsupported_device_dialog(Device **device);
|
||||
|
||||
#endif /* GDIGI_GUI_H */
|
||||
|
||||
152
preset.c
152
preset.c
@@ -18,6 +18,9 @@
|
||||
#include <expat.h>
|
||||
#include <string.h>
|
||||
#include "preset.h"
|
||||
#include "gdigi.h"
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
enum {
|
||||
PARSER_TYPE_NOT_SET = -1,
|
||||
@@ -51,10 +54,7 @@ static void XMLCALL start(void *data, const char *el, const char **attr) {
|
||||
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;
|
||||
SettingParam *param = setting_param_new();
|
||||
ad->preset->params = g_list_prepend(ad->preset->params, param);
|
||||
} else if (g_strcmp0(el, "ID") == 0) {
|
||||
ad->id = PARSER_TYPE_PARAM_ID;
|
||||
@@ -112,27 +112,34 @@ static void XMLCALL text_cb(void *data, const char* text, int len)
|
||||
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)
|
||||
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
|
||||
|
||||
/**
|
||||
* \param filename valid path to file
|
||||
* \param error return location for an error
|
||||
*
|
||||
* Tries to open file pointed by path, then parses it.
|
||||
*
|
||||
* \return Preset which must be freed using preset_free, or NULL on error.
|
||||
**/
|
||||
Preset *create_preset_from_xml_file(gchar *filename, GError **error)
|
||||
{
|
||||
GFile *file;
|
||||
GError *error = NULL;
|
||||
GError *err = 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);
|
||||
if (g_file_get_contents(filename, &contents, NULL, &err) == FALSE) {
|
||||
g_message("Failed to get %s contents: %s", filename, err->message);
|
||||
*error = g_error_copy(err);
|
||||
g_error_free(err);
|
||||
g_object_unref(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AppData *ad = (AppData *) g_malloc(sizeof(AppData));
|
||||
AppData *ad = g_slice_new(AppData);
|
||||
ad->depth = 0;
|
||||
ad->preset = g_malloc(sizeof(Preset));
|
||||
ad->preset = g_slice_new(Preset);
|
||||
ad->preset->name = NULL;
|
||||
ad->preset->params = NULL;
|
||||
ad->id = PARSER_TYPE_NOT_SET;
|
||||
@@ -144,11 +151,11 @@ Preset *create_preset_from_xml_file(gchar *filename)
|
||||
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)));
|
||||
g_set_error(error, 0, 0, "Parse error at line %d:\n%s",
|
||||
(int)XML_GetCurrentLineNumber(p),
|
||||
XML_ErrorString(XML_GetErrorCode(p)));
|
||||
preset_free(ad->preset);
|
||||
g_free(ad);
|
||||
g_slice_free(AppData, ad);
|
||||
g_free(contents);
|
||||
g_object_unref(file);
|
||||
return NULL;
|
||||
@@ -158,72 +165,97 @@ Preset *create_preset_from_xml_file(gchar *filename)
|
||||
preset->params = g_list_reverse(preset->params);
|
||||
|
||||
XML_ParserFree(p);
|
||||
g_free(ad);
|
||||
g_slice_free(AppData, ad);
|
||||
|
||||
g_free(contents);
|
||||
g_object_unref(file);
|
||||
return preset;
|
||||
}
|
||||
|
||||
Preset *create_preset_from_data(GString *data)
|
||||
/**
|
||||
* \param list list containing unpacked preset SysEx messages.
|
||||
*
|
||||
* Parses message
|
||||
*
|
||||
* \return Preset which must be freed using preset_free, or NULL on error.
|
||||
**/
|
||||
Preset *create_preset_from_data(GList *list)
|
||||
{
|
||||
gint total;
|
||||
gint n;
|
||||
gint id;
|
||||
gint position;
|
||||
guint value;
|
||||
gint x;
|
||||
gint tmp;
|
||||
GString *data;
|
||||
GList *iter;
|
||||
gint total, n, x;
|
||||
gint bank, number, modified;
|
||||
gchar *name;
|
||||
|
||||
x = 0x09;
|
||||
n = 0;
|
||||
total = (unsigned char)data->str[x];
|
||||
x++;
|
||||
g_return_val_if_fail(list != NULL, NULL);
|
||||
|
||||
Preset *preset = g_malloc(sizeof(Preset));
|
||||
preset->name = NULL; /* TODO */
|
||||
Preset *preset = g_slice_new(Preset);
|
||||
preset->name = NULL;
|
||||
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;
|
||||
iter = list;
|
||||
for (iter = list; iter; iter = g_list_next(iter)) {
|
||||
data = (GString*) iter->data;
|
||||
switch (get_message_id(data)) {
|
||||
case RECEIVE_PRESET_START:
|
||||
bank = (unsigned char)data->str[8];
|
||||
number = (unsigned char)data->str[9];
|
||||
name = g_strdup(&data->str[10]);
|
||||
modified = (unsigned char)data->str[11+strlen(name)];
|
||||
|
||||
if ((bank == PRESETS_EDIT_BUFFER) && (number == 0)) {
|
||||
g_message("Received current edit buffer");
|
||||
} else {
|
||||
g_message("Received preset %d from bank %d", number, bank);
|
||||
}
|
||||
|
||||
g_message("Modified flag: %d Name: %s", modified, name);
|
||||
preset->name = name;
|
||||
break;
|
||||
case RECEIVE_PRESET_PARAMETERS:
|
||||
x = 0x09;
|
||||
n = 0;
|
||||
total = (unsigned char)data->str[x];
|
||||
x++;
|
||||
|
||||
do {
|
||||
SettingParam *param = setting_param_new_from_data(&data->str[x], &x);
|
||||
n++;
|
||||
preset->params = g_list_prepend(preset->params, param);
|
||||
g_message("%d ID %d Position %d Value %d", n, param->id, param->position, param->value);
|
||||
} while ((x < data->len) && n<total);
|
||||
g_message("TOTAL %d", total);
|
||||
preset->params = g_list_reverse(preset->params);
|
||||
break;
|
||||
case RECEIVE_PRESET_END:
|
||||
break;
|
||||
default:
|
||||
g_message("Unhandled message in preset messages list");
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param preset preset to be freed
|
||||
*
|
||||
* Frees all memory used by 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);
|
||||
GList *iter;
|
||||
for (iter = preset->params; iter; iter = iter->next) {
|
||||
setting_param_free((SettingParam*)iter->data);
|
||||
}
|
||||
g_list_free(preset->params);
|
||||
}
|
||||
|
||||
if (preset->name != NULL)
|
||||
g_free(preset->name);
|
||||
|
||||
g_free(preset);
|
||||
g_slice_free(Preset, preset);
|
||||
}
|
||||
|
||||
10
preset.h
10
preset.h
@@ -19,19 +19,13 @@
|
||||
|
||||
#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);
|
||||
Preset *create_preset_from_xml_file(gchar *filename, GError **error);
|
||||
Preset *create_preset_from_data(GList *list);
|
||||
void preset_free(Preset *preset);
|
||||
|
||||
#endif /* GDIGI_PRESET_H */
|
||||
|
||||
647
tests.c
647
tests.c
@@ -1,647 +0,0 @@
|
||||
/*
|
||||
* 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 "gdigi.h"
|
||||
|
||||
void test_wah()
|
||||
{
|
||||
int x;
|
||||
|
||||
set_option(WAH_TYPE, WAH_POSITION, WAH_TYPE_CRY);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(WAH_MIN, WAH_POSITION_MIN_MAX, x);
|
||||
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(WAH_MAX, WAH_POSITION_MIN_MAX, x);
|
||||
|
||||
for (x=0; x<=12; x++)
|
||||
set_option(WAH_LEVEL, WAH_POSITION, x);
|
||||
|
||||
set_option(WAH_TYPE, WAH_POSITION, WAH_TYPE_FULLRANGE);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(WAH_MIN, WAH_POSITION_MIN_MAX, x);
|
||||
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(WAH_MAX, WAH_POSITION_MIN_MAX, x);
|
||||
|
||||
for (x=0; x<=12; x++)
|
||||
set_option(WAH_LEVEL, WAH_POSITION, x);
|
||||
|
||||
set_option(WAH_TYPE, WAH_POSITION, WAH_TYPE_CLYDE);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(WAH_MIN, WAH_POSITION_MIN_MAX, x);
|
||||
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(WAH_MAX, WAH_POSITION_MIN_MAX, x);
|
||||
|
||||
for (x=0; x<=12; x++)
|
||||
set_option(WAH_LEVEL, WAH_POSITION, x);
|
||||
|
||||
set_option(WAH_ON_OFF, WAH_POSITION, 1);
|
||||
set_option(WAH_ON_OFF, WAH_POSITION, 0);
|
||||
}
|
||||
|
||||
void test_compressor()
|
||||
{
|
||||
int x;
|
||||
|
||||
set_option(COMP_TYPE, COMP_POSITION, COMP_TYPE_DIGI);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(COMP_SUSTAIN, COMP_POSITION, x);
|
||||
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(COMP_TONE, COMP_POSITION, x);
|
||||
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(COMP_ATTACK, COMP_POSITION, x);
|
||||
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(COMP_LEVEL, COMP_POSITION, x);
|
||||
|
||||
set_option(COMP_TYPE, COMP_POSITION, COMP_TYPE_CS);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(COMP_SUSTAIN, COMP_POSITION, x);
|
||||
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(COMP_ATTACK, COMP_POSITION, x);
|
||||
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(COMP_LEVEL, COMP_POSITION, x);
|
||||
|
||||
set_option(COMP_ON_OFF, COMP_POSITION, 1);
|
||||
set_option(COMP_ON_OFF, COMP_POSITION, 0);
|
||||
}
|
||||
|
||||
void test_dist()
|
||||
{
|
||||
int x;
|
||||
|
||||
set_option(DIST_TYPE, DIST_POSITION, DIST_TYPE_SCREAMER);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_SCREAMER_DRIVE, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_SCREAMER_TONE, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_SCREAMER_LVL, DIST_POSITION, x);
|
||||
|
||||
set_option(DIST_TYPE, DIST_POSITION, DIST_TYPE_808);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_808_OVERDRIVE, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_808_TONE, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_808_LVL, DIST_POSITION, x);
|
||||
|
||||
set_option(DIST_TYPE, DIST_POSITION, DIST_TYPE_GUYOD);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_GUYOD_DRIVE, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_GUYOD_LVL, DIST_POSITION, x);
|
||||
|
||||
set_option(DIST_TYPE, DIST_POSITION, DIST_TYPE_DOD250);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_DOD250_GAIN, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_DOD250_LVL, DIST_POSITION, x);
|
||||
|
||||
set_option(DIST_TYPE, DIST_POSITION, DIST_TYPE_RODENT);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_RODENT_DIST, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_RODENT_FILTER, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_RODENT_LVL, DIST_POSITION, x);
|
||||
|
||||
set_option(DIST_TYPE, DIST_POSITION, DIST_TYPE_MX);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_MX_DIST, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_MX_OUTPUT, DIST_POSITION, x);
|
||||
|
||||
set_option(DIST_TYPE, DIST_POSITION, DIST_TYPE_DS);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_DS_GAIN, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_DS_TONE, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_DS_LVL, DIST_POSITION, x);
|
||||
|
||||
set_option(DIST_TYPE, DIST_POSITION, DIST_TYPE_GRUNGE);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_GRUNGE_GRUNGE, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_GRUNGE_FACE, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_GRUNGE_LOUD, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_GRUNGE_BUTT, DIST_POSITION, x);
|
||||
|
||||
set_option(DIST_TYPE, DIST_POSITION, DIST_TYPE_ZONE);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_ZONE_GAIN, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_ZONE_LOW, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_ZONE_MID_LVL, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_ZONE_MID_FREQ, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_ZONE_HIGH, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_ZONE_LEVEL, DIST_POSITION, x);
|
||||
|
||||
set_option(DIST_TYPE, DIST_POSITION, DIST_TYPE_DEATH);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_DEATH_LOW, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_DEATH_MID, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_DEATH_HIGH, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_DEATH_LVL, DIST_POSITION, x);
|
||||
|
||||
set_option(DIST_TYPE, DIST_POSITION, DIST_TYPE_GONK);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_GONK_GONK, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_GONK_SMEAR, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_GONK_SUCK, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_GONK_HEAVE, DIST_POSITION, x);
|
||||
|
||||
set_option(DIST_TYPE, DIST_POSITION, DIST_TYPE_FUZZY);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_FUZZY_FUZZ, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_FUZZY_VOLUME, DIST_POSITION, x);
|
||||
|
||||
set_option(DIST_TYPE, DIST_POSITION, DIST_TYPE_MP);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_MP_SUSTAIN, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_MP_TONE, DIST_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIST_MP_VOLUME, DIST_POSITION, x);
|
||||
|
||||
set_option(DIST_ON_OFF, DIST_POSITION, 1);
|
||||
set_option(DIST_ON_OFF, DIST_POSITION, 0);
|
||||
}
|
||||
|
||||
void test_presets()
|
||||
{
|
||||
int x;
|
||||
|
||||
for (x=0; x<=60; x++)
|
||||
switch_preset(PRESETS_USER, x);
|
||||
|
||||
for (x=0; x<=60; x++)
|
||||
switch_preset(PRESETS_SYSTEM, x);
|
||||
|
||||
for (x=0; x<=99; x++)
|
||||
set_preset_level(x);
|
||||
}
|
||||
|
||||
void test_pickups()
|
||||
{
|
||||
set_option(PICKUP_TYPE, PICKUP_POSITION, PICKUP_TYPE_HB_SC);
|
||||
set_option(PICKUP_TYPE, PICKUP_POSITION, PICKUP_TYPE_SC_HB);
|
||||
|
||||
set_option(PICKUP_ON_OFF, PICKUP_POSITION, 1);
|
||||
set_option(PICKUP_ON_OFF, PICKUP_POSITION, 0);
|
||||
}
|
||||
|
||||
void test_eq()
|
||||
{
|
||||
int x;
|
||||
|
||||
set_option(EQ_TYPE, EQ_POSITION, EQ_TYPE_BRIGHT);
|
||||
set_option(EQ_TYPE, EQ_POSITION, EQ_TYPE_MIDBOOST);
|
||||
set_option(EQ_TYPE, EQ_POSITION, EQ_TYPE_SCOOP);
|
||||
set_option(EQ_TYPE, EQ_POSITION, EQ_TYPE_WARM);
|
||||
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(AMP_GAIN, AMP_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(AMP_LEVEL, AMP_POSITION, x);
|
||||
|
||||
for (x=0; x<=0x18; x++)
|
||||
set_option(EQ_BASS, EQ_POSITION, x);
|
||||
for (x=0; x<=0x18; x++)
|
||||
set_option(EQ_MID, EQ_POSITION, x);
|
||||
for (x=0; x<=4700; x++)
|
||||
set_option(EQ_MID_HZ, EQ_POSITION, x);
|
||||
for (x=0; x<=0x18; x++)
|
||||
set_option(EQ_TREBLE, EQ_POSITION, x);
|
||||
for (x=0; x<=7500; x++)
|
||||
set_option(EQ_TREBLE_HZ, EQ_POSITION, x);
|
||||
|
||||
set_option(EQ_ON_OFF, EQ_POSITION, 1);
|
||||
set_option(EQ_ON_OFF, EQ_POSITION, 0);
|
||||
}
|
||||
|
||||
void test_noisegate()
|
||||
{
|
||||
int x;
|
||||
|
||||
set_option(NOISEGATE_TYPE, NOISEGATE_POSITION, NOISEGATE_GATE);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(NOISEGATE_GATE_TRESHOLD, NOISEGATE_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(NOISEGATE_ATTACK, NOISEGATE_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(NOISEGATE_RELEASE, NOISEGATE_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(NOISEGATE_ATTN, NOISEGATE_POSITION, x);
|
||||
|
||||
set_option(NOISEGATE_TYPE, NOISEGATE_POSITION, NOISEGATE_SWELL);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(NOISEGATE_SWELL_SENS, NOISEGATE_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(NOISEGATE_ATTACK, NOISEGATE_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(NOISEGATE_RELEASE, NOISEGATE_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(NOISEGATE_ATTN, NOISEGATE_POSITION, x);
|
||||
|
||||
set_option(NOISEGATE_ON_OFF, NOISEGATE_POSITION, 1);
|
||||
set_option(NOISEGATE_ON_OFF, NOISEGATE_POSITION, 0);
|
||||
}
|
||||
|
||||
void test_chorusfx()
|
||||
{
|
||||
int x;
|
||||
|
||||
set_option(CHORUSFX_TYPE, CHORUSFX_POSITION, CHORUS_TYPE_CE);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(CE_CHORUS_SPEED, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(CE_CHORUS_DEPTH, CHORUSFX_POSITION, x);
|
||||
|
||||
set_option(CHORUSFX_TYPE, CHORUSFX_POSITION, CHORUS_TYPE_DUAL);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DUAL_CHORUS_SPEED, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DUAL_CHORUS_DEPTH, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DUAL_CHORUS_LEVEL, CHORUSFX_POSITION, x);
|
||||
set_option(DUAL_CHORUS_WAVE, CHORUSFX_POSITION, WAVE_TRI);
|
||||
set_option(DUAL_CHORUS_WAVE, CHORUSFX_POSITION, WAVE_SINE);
|
||||
set_option(DUAL_CHORUS_WAVE, CHORUSFX_POSITION, WAVE_SQUARE);
|
||||
|
||||
set_option(CHORUSFX_TYPE, CHORUSFX_POSITION, CHORUS_TYPE_MULTI);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(MULTI_CHORUS_SPEED, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(MULTI_CHORUS_DEPTH, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(MULTI_CHORUS_LEVEL, CHORUSFX_POSITION, x);
|
||||
set_option(MULTI_CHORUS_WAVE, CHORUSFX_POSITION, WAVE_TRI);
|
||||
set_option(MULTI_CHORUS_WAVE, CHORUSFX_POSITION, WAVE_SINE);
|
||||
set_option(MULTI_CHORUS_WAVE, CHORUSFX_POSITION, WAVE_SQUARE);
|
||||
|
||||
set_option(CHORUSFX_TYPE, CHORUSFX_POSITION, CHORUS_TYPE_FLANGER);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(FLANGER_SPEED, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(FLANGER_DEPTH, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(FLANGER_REGEN, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(FLANGER_LEVEL, CHORUSFX_POSITION, x);
|
||||
set_option(FLANGER_WAVE, CHORUSFX_POSITION, WAVE_TRI);
|
||||
set_option(FLANGER_WAVE, CHORUSFX_POSITION, WAVE_SINE);
|
||||
set_option(FLANGER_WAVE, CHORUSFX_POSITION, WAVE_SQUARE);
|
||||
|
||||
set_option(CHORUSFX_TYPE, CHORUSFX_POSITION, CHORUS_TYPE_MXR_FLANGER);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(MXR_FLANGER_SPEED, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(MXR_FLANGER_WIDTH, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(MXR_FLANGER_REGEN, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(MXR_FLANGER_MANUAL, CHORUSFX_POSITION, x);
|
||||
|
||||
set_option(CHORUSFX_TYPE, CHORUSFX_POSITION, CHORUS_TYPE_PHASER);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(PHASER_SPEED, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(PHASER_DEPTH, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(PHASER_REGEN, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(PHASER_LEVEL, CHORUSFX_POSITION, x);
|
||||
set_option(PHASER_WAVE, CHORUSFX_POSITION, WAVE_TRI);
|
||||
set_option(PHASER_WAVE, CHORUSFX_POSITION, WAVE_SINE);
|
||||
set_option(PHASER_WAVE, CHORUSFX_POSITION, WAVE_SQUARE);
|
||||
|
||||
set_option(CHORUSFX_TYPE, CHORUSFX_POSITION, CHORUS_TYPE_VIBRATO);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(VIBRATO_SPEED, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(VIBRATO_DEPTH, CHORUSFX_POSITION, x);
|
||||
|
||||
set_option(CHORUSFX_TYPE, CHORUSFX_POSITION, CHORUS_TYPE_ROTARY);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(ROTARY_SPEED, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(ROTARY_INTENSITY, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(ROTARY_DOPPLER, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(ROTARY_CROSSOVER, CHORUSFX_POSITION, x);
|
||||
|
||||
set_option(CHORUSFX_TYPE, CHORUSFX_POSITION, CHORUS_TYPE_VIBROPAN);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(VIBROPAN_SPEED, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(VIBROPAN_DEPTH, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(VIBROPAN_VIBRA, CHORUSFX_POSITION, x);
|
||||
set_option(VIBROPAN_WAVE, CHORUSFX_POSITION, WAVE_TRI);
|
||||
set_option(VIBROPAN_WAVE, CHORUSFX_POSITION, WAVE_SINE);
|
||||
set_option(VIBROPAN_WAVE, CHORUSFX_POSITION, WAVE_SQUARE);
|
||||
|
||||
set_option(CHORUSFX_TYPE, CHORUSFX_POSITION, CHORUS_TYPE_TREMOLO);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(TREMOLO_SPEED, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(TREMOLO_DEPTH, CHORUSFX_POSITION, x);
|
||||
set_option(TREMOLO_WAVE, CHORUSFX_POSITION, WAVE_TRI);
|
||||
set_option(TREMOLO_WAVE, CHORUSFX_POSITION, WAVE_SINE);
|
||||
set_option(TREMOLO_WAVE, CHORUSFX_POSITION, WAVE_SQUARE);
|
||||
|
||||
set_option(CHORUSFX_TYPE, CHORUSFX_POSITION, CHORUS_TYPE_PANNER);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(PANNER_SPEED, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(PANNER_DEPTH, CHORUSFX_POSITION, x);
|
||||
set_option(PANNER_WAVE, CHORUSFX_POSITION, WAVE_TRI);
|
||||
set_option(PANNER_WAVE, CHORUSFX_POSITION, WAVE_SINE);
|
||||
set_option(PANNER_WAVE, CHORUSFX_POSITION, WAVE_SQUARE);
|
||||
|
||||
set_option(CHORUSFX_TYPE, CHORUSFX_POSITION, CHORUS_TYPE_ENVELOPE);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(ENVELOPE_SENSITIVITY, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(ENVELOPE_RANGE, CHORUSFX_POSITION, x);
|
||||
|
||||
set_option(CHORUSFX_TYPE, CHORUSFX_POSITION, CHORUS_TYPE_AUTOYA);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(AUTOYA_SPEED, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(AUTOYA_INTENSITY, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=0x31; x++)
|
||||
set_option(AUTOYA_RANGE, CHORUSFX_POSITION, x);
|
||||
|
||||
set_option(CHORUSFX_TYPE, CHORUSFX_POSITION, CHORUS_TYPE_YAYA);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(YAYA_PEDAL, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(YAYA_INTENSITY, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=0x31; x++)
|
||||
set_option(YAYA_RANGE, CHORUSFX_POSITION, x);
|
||||
|
||||
set_option(CHORUSFX_TYPE, CHORUSFX_POSITION, CHORUS_TYPE_STEP_FILTER);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(STEP_FILTER_SPEED, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(STEP_FILTER_INTENSITY, CHORUSFX_POSITION, x);
|
||||
|
||||
set_option(CHORUSFX_TYPE, CHORUSFX_POSITION, CHORUS_TYPE_WHAMMY);
|
||||
set_option(WHAMMY_AMOUNT, CHORUSFX_POSITION, WHAMMY_OCT_UP);
|
||||
set_option(WHAMMY_AMOUNT, CHORUSFX_POSITION, WHAMMY_2OCT_UP);
|
||||
set_option(WHAMMY_AMOUNT, CHORUSFX_POSITION, WHAMMY_2ND_DN);
|
||||
set_option(WHAMMY_AMOUNT, CHORUSFX_POSITION, WHAMMY_RV_2ND);
|
||||
set_option(WHAMMY_AMOUNT, CHORUSFX_POSITION, WHAMMY_4TH_DN);
|
||||
set_option(WHAMMY_AMOUNT, CHORUSFX_POSITION, WHAMMY_OCT_DN);
|
||||
set_option(WHAMMY_AMOUNT, CHORUSFX_POSITION, WHAMMY_2OCT_DN);
|
||||
set_option(WHAMMY_AMOUNT, CHORUSFX_POSITION, WHAMMY_DIV_BMB);
|
||||
set_option(WHAMMY_AMOUNT, CHORUSFX_POSITION, WHAMMY_M3_MA);
|
||||
set_option(WHAMMY_AMOUNT, CHORUSFX_POSITION, WHAMMY_2ND_MA3);
|
||||
set_option(WHAMMY_AMOUNT, CHORUSFX_POSITION, WHAMMY_3RD_4TH);
|
||||
set_option(WHAMMY_AMOUNT, CHORUSFX_POSITION, WHAMMY_4TH_5TH);
|
||||
set_option(WHAMMY_AMOUNT, CHORUSFX_POSITION, WHAMMY_5TH_OCT);
|
||||
set_option(WHAMMY_AMOUNT, CHORUSFX_POSITION, WHAMMY_HOCT_UP);
|
||||
set_option(WHAMMY_AMOUNT, CHORUSFX_POSITION, WHAMMY_HOCT_DN);
|
||||
set_option(WHAMMY_AMOUNT, CHORUSFX_POSITION, WHAMMY_OCT_UD);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(WHAMMY_PEDAL, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(WHAMMY_MIX, CHORUSFX_POSITION, x);
|
||||
|
||||
set_option(CHORUSFX_TYPE, CHORUSFX_POSITION, CHORUS_TYPE_PITCH_SHIFT);
|
||||
for (x=0; x<=0x30; x++)
|
||||
set_option(PITCH_AMOUNT, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(PITCH_MIX, CHORUSFX_POSITION, x);
|
||||
|
||||
set_option(CHORUSFX_TYPE, CHORUSFX_POSITION, CHORUS_TYPE_DETUNE);
|
||||
for (x=0; x<=0x30; x++)
|
||||
set_option(DETUNE_AMOUNT, CHORUSFX_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DETUNE_LEVEL, CHORUSFX_POSITION, x);
|
||||
|
||||
set_option(CHORUSFX_TYPE, CHORUSFX_POSITION, CHORUS_TYPE_IPS);
|
||||
set_option(IPS_SHIFT_AMOUNT, CHORUSFX_POSITION, IPS_OCT_D);
|
||||
set_option(IPS_SHIFT_AMOUNT, CHORUSFX_POSITION, IPS_7TH_DN);
|
||||
set_option(IPS_SHIFT_AMOUNT, CHORUSFX_POSITION, IPS_6TH_DN);
|
||||
set_option(IPS_SHIFT_AMOUNT, CHORUSFX_POSITION, IPS_5TH_DN);
|
||||
set_option(IPS_SHIFT_AMOUNT, CHORUSFX_POSITION, IPS_4TH_DN);
|
||||
set_option(IPS_SHIFT_AMOUNT, CHORUSFX_POSITION, IPS_3RD_DN);
|
||||
set_option(IPS_SHIFT_AMOUNT, CHORUSFX_POSITION, IPS_2ND_DN);
|
||||
set_option(IPS_SHIFT_AMOUNT, CHORUSFX_POSITION, IPS_2ND_UP);
|
||||
set_option(IPS_SHIFT_AMOUNT, CHORUSFX_POSITION, IPS_3RD_UP);
|
||||
set_option(IPS_SHIFT_AMOUNT, CHORUSFX_POSITION, IPS_4TH_UP);
|
||||
set_option(IPS_SHIFT_AMOUNT, CHORUSFX_POSITION, IPS_5TH_UP);
|
||||
set_option(IPS_SHIFT_AMOUNT, CHORUSFX_POSITION, IPS_6TH_UP);
|
||||
set_option(IPS_SHIFT_AMOUNT, CHORUSFX_POSITION, IPS_7TH_UP);
|
||||
set_option(IPS_SHIFT_AMOUNT, CHORUSFX_POSITION, IPS_OCT_U);
|
||||
set_option(IPS_KEY, CHORUSFX_POSITION, IPS_E);
|
||||
set_option(IPS_KEY, CHORUSFX_POSITION, IPS_F);
|
||||
set_option(IPS_KEY, CHORUSFX_POSITION, IPS_GB);
|
||||
set_option(IPS_KEY, CHORUSFX_POSITION, IPS_G);
|
||||
set_option(IPS_KEY, CHORUSFX_POSITION, IPS_AB);
|
||||
set_option(IPS_KEY, CHORUSFX_POSITION, IPS_A);
|
||||
set_option(IPS_KEY, CHORUSFX_POSITION, IPS_BB);
|
||||
set_option(IPS_KEY, CHORUSFX_POSITION, IPS_B);
|
||||
set_option(IPS_KEY, CHORUSFX_POSITION, IPS_C);
|
||||
set_option(IPS_KEY, CHORUSFX_POSITION, IPS_DD);
|
||||
set_option(IPS_KEY, CHORUSFX_POSITION, IPS_D);
|
||||
set_option(IPS_KEY, CHORUSFX_POSITION, IPS_EB);
|
||||
set_option(IPS_SCALE, CHORUSFX_POSITION, IPS_MAJOR);
|
||||
set_option(IPS_SCALE, CHORUSFX_POSITION, IPS_MINOR);
|
||||
set_option(IPS_SCALE, CHORUSFX_POSITION, IPS_DORIA);
|
||||
set_option(IPS_SCALE, CHORUSFX_POSITION, IPS_MIXLYD);
|
||||
set_option(IPS_SCALE, CHORUSFX_POSITION, IPS_LYDIAN);
|
||||
set_option(IPS_SCALE, CHORUSFX_POSITION, IPS_HMINO);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(IPS_LEVEL, CHORUSFX_POSITION, x);
|
||||
|
||||
set_option(CHORUSFX_ON_OFF, CHORUSFX_POSITION, 1);
|
||||
set_option(CHORUSFX_ON_OFF, CHORUSFX_POSITION, 0);
|
||||
}
|
||||
|
||||
void test_delay()
|
||||
{
|
||||
int x;
|
||||
|
||||
set_option(DELAY_TYPE, DELAY_POSITION, DELAY_TYPE_ANALOG);
|
||||
for (x=0; x<=139; x++)
|
||||
set_option(DELAY_TIME, DELAY_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(ANALOG_LEVEL, DELAY_POSITION, x);
|
||||
for (x=0; x<=100; x++)
|
||||
set_option(ANALOG_REPEATS, DELAY_POSITION, x);
|
||||
|
||||
set_option(DELAY_TYPE, DELAY_POSITION, DELAY_TYPE_DIGITAL);
|
||||
for (x=0; x<=139; x++)
|
||||
set_option(DELAY_TIME, DELAY_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIGITAL_LEVEL, DELAY_POSITION, x);
|
||||
for (x=0; x<=100; x++)
|
||||
set_option(DIGITAL_REPEATS, DELAY_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIGITAL_DUCKER_THRESH, DELAY_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(DIGITAL_DUCKER_LEVEL, DELAY_POSITION, x);
|
||||
|
||||
set_option(DELAY_TYPE, DELAY_POSITION, DELAY_TYPE_MODULATED);
|
||||
for (x=0; x<=139; x++)
|
||||
set_option(DELAY_TIME, DELAY_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(MODULATED_LEVEL, DELAY_POSITION, x);
|
||||
for (x=0; x<=100; x++)
|
||||
set_option(MODULATED_REPEATS, DELAY_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(MODULATED_DEPTH, DELAY_POSITION, x);
|
||||
|
||||
set_option(DELAY_TYPE, DELAY_POSITION, DELAY_TYPE_PONG);
|
||||
for (x=0; x<=139; x++)
|
||||
set_option(DELAY_TIME, DELAY_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(PONG_LEVEL, DELAY_POSITION, x);
|
||||
for (x=0; x<=100; x++)
|
||||
set_option(PONG_REPEATS, DELAY_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(PONG_DUCKER_THRESH, DELAY_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(PONG_DUCKER_LEVEL, DELAY_POSITION, x);
|
||||
|
||||
set_option(DELAY_TYPE, DELAY_POSITION, DELAY_TYPE_TAPE);
|
||||
for (x=0; x<=139; x++)
|
||||
set_option(DELAY_TIME, DELAY_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(TAPE_LEVEL, DELAY_POSITION, x);
|
||||
for (x=0; x<=100; x++)
|
||||
set_option(TAPE_REPEATS, DELAY_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(TAPE_WOW, DELAY_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(TAPE_FLUTTER, DELAY_POSITION, x);
|
||||
|
||||
set_option(DELAY_ON_OFF, DELAY_POSITION, 1);
|
||||
set_option(DELAY_ON_OFF, DELAY_POSITION, 0);
|
||||
}
|
||||
|
||||
void test_reverb()
|
||||
{
|
||||
int x;
|
||||
|
||||
set_option(REVERB_TYPE, REVERB_POSITION, REVERB_TYPE_TWIN);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(TWIN_REVERB, REVERB_POSITION, x);
|
||||
|
||||
set_option(REVERB_TYPE, REVERB_POSITION, REVERB_TYPE_LEX_AMBIENCE);
|
||||
for (x=0; x<=15; x++)
|
||||
set_option(LEX_AMBIENCE_PREDELAY, REVERB_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(LEX_AMBIENCE_DECAY, REVERB_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(LEX_AMBIENCE_LIVELINESS, REVERB_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(LEX_AMBIENCE_LEVEL, REVERB_POSITION, x);
|
||||
|
||||
set_option(REVERB_TYPE, REVERB_POSITION, REVERB_TYPE_LEX_STUDIO);
|
||||
for (x=0; x<=15; x++)
|
||||
set_option(LEX_STUDIO_PREDELAY, REVERB_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(LEX_STUDIO_DECAY, REVERB_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(LEX_STUDIO_LIVELINESS, REVERB_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(LEX_STUDIO_LEVEL, REVERB_POSITION, x);
|
||||
|
||||
set_option(REVERB_TYPE, REVERB_POSITION, REVERB_TYPE_LEX_ROOM);
|
||||
for (x=0; x<=15; x++)
|
||||
set_option(LEX_ROOM_PREDELAY, REVERB_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(LEX_ROOM_DECAY, REVERB_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(LEX_ROOM_LIVELINESS, REVERB_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(LEX_ROOM_LEVEL, REVERB_POSITION, x);
|
||||
|
||||
set_option(REVERB_TYPE, REVERB_POSITION, REVERB_TYPE_LEX_HALL);
|
||||
for (x=0; x<=15; x++)
|
||||
set_option(LEX_HALL_PREDELAY, REVERB_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(LEX_HALL_DECAY, REVERB_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(LEX_HALL_LIVELINESS, REVERB_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(LEX_HALL_LEVEL, REVERB_POSITION, x);
|
||||
|
||||
set_option(REVERB_TYPE, REVERB_POSITION, REVERB_TYPE_EMT240_PLATE);
|
||||
for (x=0; x<=15; x++)
|
||||
set_option(EMT240_PLATE_PREDELAY, REVERB_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(EMT240_PLATE_DECAY, REVERB_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(EMT240_PLATE_LIVELINESS, REVERB_POSITION, x);
|
||||
for (x=0; x<=99; x++)
|
||||
set_option(EMT240_PLATE_LEVEL, REVERB_POSITION, x);
|
||||
|
||||
set_option(REVERB_ON_OFF, REVERB_POSITION, 1);
|
||||
set_option(REVERB_ON_OFF, REVERB_POSITION, 0);
|
||||
}
|
||||
|
||||
void test_usb()
|
||||
{
|
||||
int x;
|
||||
|
||||
for (x=0; x<=100; x++)
|
||||
set_option(USB_AUDIO_PLAYBACK_MIX, USB_POSITION, x);
|
||||
|
||||
for (x=0; x<=36; x++)
|
||||
set_option(USB_AUDIO_LEVEL, USB_POSITION, x);
|
||||
}
|
||||
|
||||
void test_all()
|
||||
{
|
||||
test_wah();
|
||||
test_compressor();
|
||||
test_dist();
|
||||
test_presets();
|
||||
test_pickups();
|
||||
test_eq();
|
||||
test_noisegate();
|
||||
test_chorusfx();
|
||||
test_delay();
|
||||
test_reverb();
|
||||
test_usb();
|
||||
}
|
||||
35
tests.h
35
tests.h
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* 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_TESTS_H
|
||||
#define GDIGI_TESTS_H
|
||||
|
||||
#include "gdigi.h"
|
||||
|
||||
void test_wah();
|
||||
void test_compressor();
|
||||
void test_dist();
|
||||
void test_presets();
|
||||
void test_pickups();
|
||||
void test_eq();
|
||||
void test_noisegate();
|
||||
void test_chorusfx();
|
||||
void test_delay();
|
||||
void test_reverb();
|
||||
void test_usb();
|
||||
void test_all();
|
||||
|
||||
#endif /* GDIGI_TESTS_H */
|
||||
Reference in New Issue
Block a user