add support for GNX4 and GNX3k patches

This commit is contained in:
Tomasz Moń
2010-06-17 19:20:58 +02:00
parent e12de97fab
commit 0886ba00c1
5 changed files with 356 additions and 45 deletions

124
gdigi.c
View File

@@ -564,6 +564,68 @@ void setting_param_free(SettingParam *param)
g_slice_free(SettingParam, param);
}
/**
* Allocates memory for SettingGenetx.
*
* \return SettingGenetx which must be freed using setting_genetx_free.
**/
SettingGenetx *setting_genetx_new()
{
SettingGenetx *genetx = g_slice_new(SettingGenetx);
/* Older patches don't specify GeNetX version */
genetx->version = GENETX_VERSION_1;
genetx->type = GENETX_TYPE_NOT_SET;
genetx->channel = -1;
genetx->name = NULL;
genetx->data = NULL;
return genetx;
}
/**
* \param genetx SettingGenetx to be freed
*
* Frees all memory used by SettingGenetx.
**/
void setting_genetx_free(SettingGenetx *genetx)
{
g_free(genetx->name);
if (genetx->data != NULL) {
g_string_free(genetx->data, TRUE);
}
g_slice_free(SettingGenetx, genetx);
}
/**
* \param version GeNetX version
* \param type GeNetX type
*
* Retrieves SectionID for specified GeNetX version and type.
*
* \return SectionID specified by version and type, or -1 on error.
**/
SectionID get_genetx_section_id(gint version, gint type)
{
if (version == GENETX_VERSION_1) {
if (type == GENETX_TYPE_AMP) {
return SECTION_GENETX_AMP;
} else if (type == GENETX_TYPE_CABINET) {
return SECTION_GENETX_CABINET;
}
} else if (version == GENETX_VERSION_2) {
if (type == GENETX_TYPE_AMP) {
return SECTION_GENETX2_AMP;
} else if (type == GENETX_TYPE_CABINET) {
return SECTION_GENETX2_CABINET;
}
}
g_message("This version of gdigi don't know what to do with this "
"GeNetX version (%d) and type (%d)", version, type);
return -1;
}
/**
* \param id Parameter ID
* \param position Parameter position
@@ -582,6 +644,68 @@ void set_option(guint id, guint position, guint value)
g_string_free(msg, TRUE);
}
/**
* \param section data section ID
* \param bank section-specific bank number
* \param index index of the desired object within the bank
* \param name object name
* \param data GString containing object data
*
* Forms RECEIVE_OBJECT SysEx message then sends it to device.
**/
void send_object(SectionID section, guint bank, guint index,
gchar *name, GString *data)
{
GString *msg = g_string_new(NULL);
gint len = data->len;
g_string_append_printf(msg,
"%c%c%c%c%s%c%c%c",
section, bank,
((index & 0xFF00) >> 8), (index & 0xFF),
name, 0 /* NULL terminated string */,
((len & 0xFF00) >> 8), (len & 0xFF));
g_string_append_len(msg, data->str, data->len);
send_message(RECEIVE_OBJECT, msg->str, msg->len);
g_string_free(msg, TRUE);
}
/**
* \param params GList containing SettingParam
*
* Forms RECEIVE_PRESET_PARAMETERS SysEx message then sends it to device.
**/
void send_preset_parameters(GList *params)
{
GString *msg = g_string_sized_new(500);
GList *iter = params;
gint len = g_list_length(iter);
g_string_append_printf(msg, "%c%c",
((len & 0xFF00) >> 8),
(len & 0xFF));
while (iter) {
SettingParam *param = (SettingParam *) iter->data;
iter = iter->next;
g_string_append_printf(msg, "%c%c%c",
((param->id & 0xFF00) >> 8),
(param->id & 0xFF),
param->position);
append_value(msg, param->value);
};
send_message(RECEIVE_PRESET_PARAMETERS, msg->str, msg->len);
g_string_free(msg, TRUE);
}
/**
* \param bank preset bank
* \param x preset index

47
gdigi.h
View File

@@ -936,20 +936,67 @@ typedef enum {
NACK = 0x7F
} MessageID;
typedef enum {
SECTION_GENETX_AMP = 0,
SECTION_GENETX_CABINET = 1,
SECTION_DRUM_PATTERN = 2,
SECTION_DRUM_KIT = 3,
SECTION_DRUM_SAMPLES = 4,
SECTION_SONG = 5,
SECTION_FOOTSWITCH = 6,
SECTION_GENETX2_AMP = 7,
SECTION_GENETX2_CABINET = 8,
SECTION_DEVICE_GUID = 9,
SECTION_DEVICE_NAME = 10,
} SectionID;
typedef struct {
int id;
int position;
int value;
} SettingParam;
enum {
GENETX_VERSION_1,
GENETX_VERSION_2
};
enum {
GENETX_TYPE_NOT_SET = -1,
GENETX_TYPE_AMP,
GENETX_TYPE_CABINET
};
enum {
GENETX_CHANNEL1 = 0,
GENETX_CHANNEL2 = 1,
GENETX_CHANNEL1_CUSTOM = 2,
GENETX_CHANNEL2_CUSTOM = 3,
GENETX_CHANNEL_CURRENT = 4
} ChannelBankIndex;
typedef struct {
int version;
int type;
int channel;
gchar *name;
GString *data;
} SettingGenetx;
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);
SettingGenetx *setting_genetx_new();
void setting_genetx_free(SettingGenetx *genetx);
void setting_param_free(SettingParam *param);
SectionID get_genetx_section_id(gint version, gint type);
void set_option(guint id, guint position, guint value);
void send_object(SectionID section, guint bank, guint index,
gchar *name, GString *data);
void send_preset_parameters(GList *params);
void switch_preset(guint bank, guint x);
void store_preset_name(int x, const gchar *name);
void set_preset_level(int level);

84
gui.c
View File

@@ -862,6 +862,8 @@ static SupportedFileTypes file_types[] = {
{"RP355Preset", "*.rp355p"},
{"RP500Preset", "*.rp500p"},
{"RP1000Preset", "*.rp1000p"},
{"GNX4 Preset", "*.g4p"},
{"GNX3kPreset", "*.g3kp"},
};
static guint n_file_types = G_N_ELEMENTS(file_types);
@@ -919,41 +921,77 @@ static void action_open_preset_cb(GtkAction *action)
gtk_widget_hide(dialog);
GString *msg = g_string_sized_new(500);
GList *iter = preset->params;
gint len = g_list_length(iter);
g_string_append_printf(msg, "%c%c",
((len & 0xFF00) >> 8),
(len & 0xFF));
while (iter) {
SettingParam *param = iter->data;
iter = iter->next;
g_string_append_printf(msg, "%c%c%c",
((param->id & 0xFF00) >> 8),
(param->id & 0xFF),
param->position);
append_value(msg, param->value);
};
GString *start = g_string_new(NULL);
g_string_append_printf(start,
"%c%c%s%c%c%c",
PRESETS_EDIT_BUFFER, 0,
preset->name, 0 /* NULL terminated string */,
0 /* modified */, 2 /* messages to follow */);
0 /* modified */,
/* messages to follow */
preset->genetxs ? 10 : 2);
send_message(RECEIVE_PRESET_START, start->str, start->len);
send_message(RECEIVE_PRESET_PARAMETERS, msg->str, msg->len);
send_preset_parameters(preset->params);
if (preset->genetxs != NULL) {
gint i;
/* GNX4 sends messages in following order:
* Section Bank Index
* 0x00 0x04 0x0000
* 0x00 0x04 0x0001
* 0x01 0x04 0x0000
* 0x01 0x04 0x0001
* 0x00 0x04 0x0002
* 0x00 0x04 0x0003
* 0x01 0x04 0x0002
* 0x01 0x04 0x0003
*/
/* GNX3000 sends messages in following order:
* Section Bank Index
* 0x07 0x04 0x0000
* 0x07 0x04 0x0001
* 0x08 0x04 0x0000
* 0x08 0x04 0x0001
* 0x07 0x04 0x0002
* 0x07 0x04 0x0003
* 0x08 0x04 0x0002
* 0x08 0x04 0x0003
*/
for (i = 0; i < 2; i++) {
GList *iter = preset->genetxs;
while (iter) {
SectionID section;
guint bank, index;
SettingGenetx *genetx = (SettingGenetx *) iter->data;
iter = iter->next;
section = get_genetx_section_id(genetx->version,
genetx->type);
bank = 0x04;
if (i == 0) {
index = genetx->channel;
} else {
if (genetx->channel == GENETX_CHANNEL1) {
index = GENETX_CHANNEL1_CUSTOM;
} else if (genetx->channel == GENETX_CHANNEL2) {
index = GENETX_CHANNEL2_CUSTOM;
}
}
send_object(section, bank, index,
genetx->name, genetx->data);
}
}
}
send_message(RECEIVE_PRESET_END, NULL, 0);
show_store_preset_window(window, preset->name);
g_string_free(start, TRUE);
g_string_free(msg, TRUE);
preset_free(preset);
loaded = TRUE;
}

105
preset.c
View File

@@ -29,12 +29,24 @@ enum {
PARSER_TYPE_PARAM_POSITION,
PARSER_TYPE_PARAM_VALUE,
PARSER_TYPE_PARAM_NAME,
PARSER_TYPE_PARAM_TEXT
PARSER_TYPE_PARAM_TEXT,
PARSER_TYPE_GENETX_VERSION,
PARSER_TYPE_GENETX_TYPE,
PARSER_TYPE_GENETX_CHANNEL,
PARSER_TYPE_GENETX_NAME,
PARSER_TYPE_GENETX_DATA
};
enum {
SECTION_NOT_SET = -1,
SECTION_PARAMS,
SECTION_GENETX
};
typedef struct {
int depth;
int id;
int section;
Preset *preset;
} AppData;
@@ -46,11 +58,16 @@ static void XMLCALL start(void *data, const char *el, const char **attr) {
if (ad->depth == 1) {
ad->id = PARSER_TYPE_PRESET_NAME;
} else if (ad->depth == 3) {
if (ad->section == SECTION_PARAMS) {
ad->id = PARSER_TYPE_PARAM_NAME;
} else if (ad->section == SECTION_GENETX) {
ad->id = PARSER_TYPE_GENETX_NAME;
}
}
}
if (g_strcmp0(el, "Params") == 0) {
ad->section = SECTION_PARAMS;
if (ad->preset->params != NULL)
g_message("Params aleady exists!");
} else if (g_strcmp0(el, "Param") == 0) {
@@ -64,6 +81,21 @@ static void XMLCALL start(void *data, const char *el, const char **attr) {
ad->id = PARSER_TYPE_PARAM_VALUE;
} else if (g_strcmp0(el, "Text") == 0) {
ad->id = PARSER_TYPE_PARAM_TEXT;
} else if (g_strcmp0(el, "Genetx") == 0) {
ad->section = SECTION_GENETX;
if (ad->preset->genetxs != NULL)
g_message("Genetx already exists!");
} else if (g_strcmp0(el, "GenetxModel") == 0) {
SettingGenetx *genetx = setting_genetx_new();
ad->preset->genetxs = g_list_prepend(ad->preset->genetxs, genetx);
} else if (g_strcmp0(el, "Version") == 0) {
ad->id = PARSER_TYPE_GENETX_VERSION;
} else if (g_strcmp0(el, "Type") == 0) {
ad->id = PARSER_TYPE_GENETX_TYPE;
} else if (g_strcmp0(el, "Channel") == 0) {
ad->id = PARSER_TYPE_GENETX_CHANNEL;
} else if (g_strcmp0(el, "Data") == 0) {
ad->id = PARSER_TYPE_GENETX_DATA;
}
ad->depth++;
@@ -88,6 +120,7 @@ static void XMLCALL text_cb(void *data, const char* text, int len)
ad->preset->name = g_strndup(text, len);
}
if (ad->section == SECTION_PARAMS) {
if (ad->preset->params == NULL)
return;
@@ -110,6 +143,64 @@ static void XMLCALL text_cb(void *data, const char* text, int len)
}
g_free(value);
} else if (ad->section == SECTION_GENETX) {
if (ad->preset->genetxs == NULL)
return;
SettingGenetx *genetx = (SettingGenetx *) ad->preset->genetxs->data;
if (genetx == NULL)
return;
gchar *value = g_strndup(text, len);
switch (ad->id) {
case PARSER_TYPE_GENETX_VERSION:
if (g_strcmp0(value, "Version1") == 0) {
genetx->version = GENETX_VERSION_1;
} else if (g_strcmp0(value, "Version2") == 0) {
genetx->version = GENETX_VERSION_2;
} else {
g_message("Unknown GeNetX version: %s", value);
}
break;
case PARSER_TYPE_GENETX_TYPE:
if (g_strcmp0(value, "Amp") == 0) {
genetx->type = GENETX_TYPE_AMP;
} else if (g_strcmp0(value, "Cabinet") == 0) {
genetx->type = GENETX_TYPE_CABINET;
} else {
g_message("Unknown GeNetX type: %s", value);
}
break;
case PARSER_TYPE_GENETX_CHANNEL:
if (g_strcmp0(value, "Channel1") == 0) {
genetx->channel = GENETX_CHANNEL1;
} else if (g_strcmp0(value, "Channel2") == 0) {
genetx->channel = GENETX_CHANNEL2;
} else {
g_message("Unknown GeNetX channel: %s", value);
}
break;
case PARSER_TYPE_GENETX_NAME:
/* reassign pointer */
genetx->name = value;
value = NULL;
break;
case PARSER_TYPE_GENETX_DATA:
{
guchar *data = NULL;
gsize length = 0;
data = g_base64_decode(value, &length);
genetx->data = g_string_new_len((gchar *) data, length);
g_free(data);
break;
}
}
g_free(value);
}
}
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
@@ -139,6 +230,7 @@ Preset *create_preset_from_xml_file(gchar *filename, GError **error)
ad->preset = g_slice_new(Preset);
ad->preset->name = NULL;
ad->preset->params = NULL;
ad->preset->genetxs = NULL;
ad->id = PARSER_TYPE_NOT_SET;
XML_Parser p;
@@ -159,6 +251,7 @@ Preset *create_preset_from_xml_file(gchar *filename, GError **error)
Preset *preset = ad->preset;
preset->params = g_list_reverse(preset->params);
preset->genetxs = g_list_reverse(preset->genetxs);
XML_ParserFree(p);
g_slice_free(AppData, ad);
@@ -187,6 +280,7 @@ Preset *create_preset_from_data(GList *list)
Preset *preset = g_slice_new(Preset);
preset->name = NULL;
preset->params = NULL;
preset->genetxs = NULL;
iter = list;
for (iter = list; iter; iter = g_list_next(iter)) {
@@ -249,7 +343,14 @@ void preset_free(Preset *preset)
g_list_free(preset->params);
}
if (preset->name != NULL)
if (preset->genetxs != NULL) {
GList *iter;
for (iter = preset->genetxs; iter; iter = iter->next) {
setting_genetx_free((SettingGenetx*)iter->data);
}
g_list_free(preset->genetxs);
}
g_free(preset->name);
g_slice_free(Preset, preset);

View File

@@ -22,6 +22,7 @@
typedef struct {
gchar *name;
GList *params;
GList *genetxs;
} Preset;
Preset *create_preset_from_xml_file(gchar *filename, GError **error);