72 Commits

Author SHA1 Message Date
Tomasz Moń
cada964d61 Merge pull request #10 from acspike/master
additional modifiers for rp1000
2014-02-06 09:11:14 +01:00
Frederic DE WEVER
4bb78a5fe7 Fix Mid frequency Equalizer name ID error. 2014-01-05 09:20:00 +01:00
Aaron C. Spike
a2a4842fd9 additional modifiers for rp1000 2014-01-01 13:22:15 -06:00
Tim LaBerge
079547c20f Fix up some whitespace. 2013-12-26 10:29:03 -08:00
Tim LaBerge
e3447292c4 Restore modifier for delay tap time 4990. 2013-12-26 10:26:31 -08:00
Tim LaBerge
9f4bd66217 Remove duplicate RP1000 code.
Support for RP1000 has been merged upstream, so the rp1000 changes
in this branch are unneeded.
2013-12-26 10:20:53 -08:00
Tim LaBerge
85be87a636 Merge mainline RP1000 changes. 2013-12-26 10:16:05 -08:00
Tim LaBerge
d61e6c3046 Merge branch 'master' into rp1000 2013-12-26 09:49:19 -08:00
Tim LaBerge
196a7c2aa5 Fine tune debugging.
1) If get_modifier() fails, set the label to "Unknown pos/id". Thus, label
   will always be non-null and debugging should be easier. The minor downside
   is that the label string is leaked when we update the modifier group.

2) Restore the assert in update_modifier_vbox() and the now unnecessary
   test of group[x].label.
2013-12-25 14:10:57 -08:00
Tim LaBerge
f1aa3665ed Support for RP1000
1) Add missing support for DELAY_TAP_TIME, DELAY_MULTIPLIER, and
   AMP_LOOP_ON_OFF.

2) Add a warning when get_modifier() fails.

3) In update_modifier_linkable_list(), set label to "Unknown" when
   the lookup of a modfier fails.

4) In format ipv(), the warning message that's emitted if get_xml_settings()
   fails reversed position and id.

5) In update_modifier_vbox(), remove the assert that the group label is not
   null. Set the combo box text to "Unknown".
2013-12-25 13:52:15 -08:00
Aaron C. Spike
478f580e76 add values needed for rp1000 2013-12-22 18:04:02 -06:00
Tim LaBerge
dfec60e7b4 Add support for RP500 amp bypass. 2013-08-21 22:51:19 -07:00
Tim LaBerge
e7de6b2bb5 RP500 specific xml settings. 2013-08-20 21:53:56 -07:00
Tim LaBerge
17ff7063ec Need RP500 changes in modifiers array. 2013-08-18 09:14:19 -07:00
Tim LaBerge
f1bca1eabb Fix expression pedel for rp500 2013-08-17 10:19:19 -07:00
Ahmed Toulan
ba71876ebf Fix installed files permissions. 2013-01-30 00:32:14 +02:00
Ahmed Toulan
8591b0feb7 Change category GNOME to GTK 2013-01-30 00:31:58 +02:00
Tomasz Moń
f94ed1c93b Tag version 0.4.0. 2013-01-14 17:13:46 +01:00
Tomasz Moń
7023e1fa92 Add expression pedal setting for RP250, RP255, RP500 and RP1000. 2012-12-22 15:35:45 +01:00
Tim LaBerge
a51103964b Fix comments from code review.
1) #include gui.h in effects.c.

2) Copy/paste error in xml_settings for UNOVIBE_CHORUS_VIBRATO.

3) Use a gboolean instead of a guint.

4) Remove a warning that fires under normal circumstances on devices
   without LFO's.
2012-12-21 06:55:49 -08:00
Tim LaBerge
f6a2ba7420 Free allocated exp settings.
Code to properly free exp settings when we rebuild the modifer list.

1) Fix up mislabeled modifier settings for Presence.

2) Add missing xml settings (avoids crashes with -D a).

3) When we free the modifier group, free the data associated with the
   dynamically allocated settings for the EXP_POSITION combo box.
2012-12-20 20:52:22 -08:00
Tim LaBerge
bad10ed0f2 Add proper min/max settings to pedal assign effect.
1) Delete definition of pedal1_assign_settings since it should be calculated
   at runtime from the modifier list.

2) Delete the pedal1_assign_settings EffectSetting from
rp355_pedal1_assign_group.

3) Add "None" entries to the tone_lib_group[] and effect_lib_group[]. Otherwise,
   once a library tone or effect is selected, it can't be deselected.

4) Fix up some tracing of effect values that was displaying incorrect values.

5) Change 'update_modifier_combo_box()' to 'update_modifier_vbox()' and for
   the expression pedal let it handle instantiating per combo box entry
   settings.

6) Don't forget to free the links we remove from the list when we're cleaning
   the combo box. If there are per-combo box entry settings, free them using
   the usual destructor.

7) Poll the device for the appropriate settings for EXP_MIN/MAX after we
   we update the modifier list.
2012-12-18 21:49:57 -08:00
Tim LaBerge
cee33835a7 Enforce hysteresis on modifier list requests.
With the tone and effect libraries implemented on rp355, it appears that
the device will send multiple NOTIFY_MODIFIER_GROUP_CHANGED messages
in response to selecting a new tone or effect library.

If we receive a NOTIFY_MODIFIER_GROUP_CHANGED, but haven't yet processed
the RECEIVE_MODIFIER_LINKABLE_LIST from the previous notification,
we will drop the most recent.

This greatly reduces the device churn and time it takes to apply a new library
setting.
2012-12-17 21:40:04 -08:00
Tim LaBerge
0cd6727d45 Fix review comments for pull request.
1) Don't expose gui mode to the causual user. Hide under the DEVELOPMENT_MODE
   #define.

2) Add accessors for the ModifierLinkableList's interesting fields.

3) Free the ModifierLinkableList from modifier_linkable_list(). This allows
   us to make the free function static.

4) Rename modifier_linkable_list() to update_modifier_linkable_list().

5) In effects.h, reflect the renaming of update_modifier_linkable_list() and
   correct it's signature.

6) Whitespace fixups in gdigi.c.

7) In the handler for RECEIVE_GLOBAL_PARAMETERS, apply the parameter to the gui.

8) Fixup some merge damage ;-(

9) UnCamelCaseIze some variables.

10) When we create the gui, issue a single call to REQUEST_GLOBAL_PARAMETERS to
    retrieve the globals from the device, instead of polling each parameter
    individually.
2012-12-17 21:21:17 -08:00
Tim LaBerge
22aeaf8ffa Enable tone/effects library for rp355.
Implement the recent addition of the tone/effects library for the rp355.

Get rid of USB_POSITION.

Add tone lib A for rp355.

Minor comment changes.

Remove a couple of commented out lines.
2012-12-17 06:58:44 -08:00
Tim LaBerge
a389c785f7 Merge branch 'global'
Conflicts:
	.gitignore
	effects.c
	gdigi.c
	gdigi.h
	gdigi_xml.h
	gui.c
	gui.h
	preset.c
	preset_xml.c

effects.c: More effect_values_0_to_* arrays for various effects.
           VALUE_TYPE_POSID for linkable effects.
           Add the rest of the global settings (need to change USB_POSITION
           to GLOBAL_POSITION throughout).
           A few label typos.
           New settings, groups, and effects for linkables.
           Make the display three rows instead of two.
           Add missing modifiers.
           Add missing xml settings.
           Code for handling/updating the global modifier linkable list.

effects.h Add VALUE_TYPE_POSID.

gdigi.c   Tweaks for value formatting.
          Use NOTIFY_MODIFIER_GROUP_CHANGED to drive the update of the combo
          boxes for linkable effects.
          Use RECEIVE_MODIFIER_LINKABLE_LIST to handle the update of the
          combo boxes for linkable effects.

gdigi.h   Minor changes.

gui.c     Deprecate gtk_vbox_new().
          Use simpler API gtk_combo_box_text_append_text().
          Minor reformatting/whitespace changes.
          Code to update combo boxes for linkable effects.
          Code to retrieve global parameters from device at startup.

preset_xml.c
          Some tweaks to map_xml_value() so that it's passed resolved
          EffectValues for settings of type EXTRA.
2012-12-16 21:30:41 -08:00
Tim LaBerge
44dbbe7b72 Add remaining rp355 effects to modifiers array.
1) A few rp355 effects were missing from the modifiers array.
2) The EH_PHASER effects were missing from the xml_settings array.
3) Added a disambiguating string to the "Unable to map" warning in
   gdigi.c.
2012-12-16 11:12:10 -08:00
Tim LaBerge
3a3017b46f Add support for linkable parameters.
These changes allow gdigi to link parameters to the expression pedal,
LFO1, and LFO2. The changes have been implemented only for RP355, but
should be easily extendible to other devices.

The design is as follows:

The effect group entries for the linkable effects have only a placeholder
entry "None" at startup.

During startup, we send an unsolicited REQUEST_MODIFIER_LINKABLE_LIST. When we
receive RECEIVE_MODIFIER_LINKABLE_LIST in response, we use it to construct the
ModifierLinkableList and update the combo boxes for the Pedal Assign and LFO
effects.

Whenever the selected chorus/fx effect changes, the list of linkable parameters
also changes, so the device will send us a NOTIFY_MODIFIER_GROUP_CHANGED. Again,
we send a REQUEST_MODIFIER_LINKABLE_LIST and use the response to rebuild
ModifierLinkableList. Then we tear down and rebuild the state associated with
the affected combo boxes.

The changes made are as follows:

1) Add settings for pedal1_assign. This is the min/max value returned
   by the pedal.

2) Add separate EffectGroup for both pedal assignment and the LFO's
   for the non-combo box settings.

3) Fix up a few more missing effects in the xml and modifier lists.
   There is additional work to do here, but that will be in future
   commits.

4) Fixed a missing break in the RECEIVE_DEVICE_NOTIFICATION case
   in push_message().

5) When we receive a NOTIFY_MODIFIER_GROUP_CHANGED message, free the exisiting
   modifier group and send a REQUEST_MODIFIER_LINKABLE_LIST so we can
   rebuild it.

6) When we receive a RECEIVE_MODIFIER_LINKABLE_LIST, protect the calls to
   create_modifier_group() with GDK_THREADS_ENTER() so we don't crash
   because of interactions with the event/gui threads.

7) Added a BUG assert to an error leg in get_message_list().

8) Fix memory leak in get_digitech_devices() found by valgrind.

9) Add a function to tear down the state associated with the entries of a
   pedal assign or LFO combo box.

10) Add a function to build up the entries of a pedal assign or LFO combo
    box from the modifier linkable list received from the device.

11) Use gtk_combo_box_text_append_text() throughout.

12) A few whitespace/readability changes and more comments.
2012-12-16 09:29:16 -08:00
Tim LaBerge
8b998c636f Replace deprecated API's gtk_vbox/hbox_new().
The API's gtk_vbox_new() and gtk_hbox_new() are deprecated and result
in compilation warnings. Replace these API's with calls to
gtk_box_new() with GTK_ORIENTATION_VERTICAL and GTK_ORIENTATION_HORIZONTAL,
respectively.
2012-12-03 19:25:53 -08:00
Tim LaBerge
f389caffbc Fix RHold display for delay repeats.
This involved passing the EffectValue resulting from the resolution of
an VALUE_TYPE_EXTRA to map_xml_value() and some more careful range
checking.

Also, the delay repeats effect needed an xml_label for the special
'repeat forever' value 100, which maps to the string RHold.
2012-12-03 19:25:24 -08:00
Tim LaBerge
b5aa30d599 Fix up LFO speed EffectValues. 2012-12-03 12:19:35 -08:00
Tomasz Moń
29d33ce93a Add Mauro Carvalho Chehab to the authors list. 2012-12-03 10:48:12 +01:00
Tomasz Moń
27ffb9c65a Fix FSF address at gtkknob.c/gtkknob.h. 2012-12-03 10:46:14 +01:00
Tim LaBerge
4f40132742 Implement the LFO1 and LFO2 effects.
For now, this is just for rp355, though the code should work for other
devices with minimal modification.

1) The EffectValues for values_*_assign need to be VALUE_TYPE_POSID.

2) Disabmiguate "Delay Tape" for a couple of EffectSettings. This fixed
   some bugs in the creation of the global modifier group.

3) Remove #if 0's around the definition of the lfo2_settings.

4) Define proper lfo1 and lfo2 groups arrays.

5) Define the lfo2_effect[] array.

6) Add the lfo1 and lfo2 effects to the rp355_effects array.

7) Disambiguate "EQ B" from "Eq" for some effedts in the modifiers array.

8) In push_message(), after we receive the RECEIVE_MODIFIER_LINKABLE_LIST
   message, kick off the creation of the EXP, LFO1, and LFO2 effects.

9) Generalize the function used for the pedal1_assign effect and make it work
   for lfo1 and lfo2 as well. Convert printf's to debug_msg().

10) Since we're destroying the association of the grid with the placeholder
    combo box entry, steal the data so the child widget isn't destroyed.

11) Silence warning on exit about 0 unread messages in queue.
2012-12-02 21:59:26 -08:00
Mauro Carvalho Chehab
1a5fab5f5a Add Tone Lib/Effects support on RP255
RP255 (firmware version 1.1) has the Tone Library at position 25, instead of 26.
Add this library position alternative as "LIB_POSITION_B", renaming the existing
one to LIB_POSITION_A, and add the corresponding bits at effects.c.

Also, adds a menu there, to let it to be controlled via the library.
2012-12-02 15:00:52 +01:00
Tim LaBerge
cf239da94c Implement parameter linking to expression pedal. 2012-12-01 15:30:56 -08:00
Tomasz Moń
890d40f6c6 Fix problems found by Coverity scan.
CID #743175 Unchecked return value
CID #743176 Logically dead code
CID #743177 Dereference after null check
CID #743178 Dereference before null check
CID #743179 Uninitialized scalar variable
CID #743180 Uninitialized scalar variable
2012-11-12 21:38:15 +01:00
Tomasz Moń
c927b075a7 Fix trailing whitespaces. 2012-11-12 21:11:38 +01:00
Tomasz Moń
7691323989 Fix mouse scroll on GtkKnob widget. 2012-11-12 21:04:06 +01:00
Tomasz Moń
d90d7e4b70 Add missing libm linker flag 2012-07-05 23:25:44 +02:00
Tomasz Moń
79d80fee46 Merge pull request #3 from thelinuxer/master
Fix spelling mistakes
2012-05-22 08:03:05 -07:00
Ahmed Toulan
034f353aa9 Fix spelling mistakes 2012-05-22 16:30:25 +02:00
Tomasz Moń
db04032b46 Merge pull request #2 from andrewshadoura/patch-1
Update my last name
2012-05-06 08:14:26 -07:00
Andrew Shadura
d7043d471d Fix my last name 2012-05-06 16:27:00 +03:00
Andrew Shadura
c614783e87 Fix my last name 2012-05-06 16:25:21 +03:00
Tomasz Moń
06cee3eef1 Use gdigi icon. 2012-05-02 17:18:50 +02:00
Islam Alwazery
8a98e2703f Add gdigi icon. 2012-05-02 17:17:21 +02:00
Tomasz Moń
b1a8fb4a3b Merge pull request #1 from tlaberge/master
Refine debug/logging infrastructure
2012-04-09 09:21:57 -07:00
Tim LaBerge
2b1c74ac30 Cleanups on the Logging branch.
1) Add a more reasonable max value for the the pedal/vswitch assign values.
2) Minor format change in format_ipv().
3) Formatting cleanup in push_message(). Also change debug messages to
   emphasize message direction.
4) Cleanup startup messages and add one that emits device name.
5) Cleanup the option message so that it's complete and readable.
2012-04-08 09:41:04 -07:00
Tim LaBerge
baa5fdff85 Fix display of signed/unsigned debug msg.
Also twiddle the .gitignore file.
2012-04-07 20:05:04 -07:00
Tim LaBerge
d139a3d89a Add a .gitignore file. 2012-04-07 20:04:02 -07:00
Tim LaBerge
4291fa71b2 Fixup label range values.
A number of EffectValues of type label had invalid ranges. Make
them less invalid.

Also add SYNTH_TALK id's to xml settings.

Make format_ipv warn instead of crashing if an xml setting is not
found.
2012-04-07 19:46:36 -07:00
Tim LaBerge
ea80320531 Human readable debug
Leverage the code that writes a preset to XML so that messages
can be displayed in a human readable format.

E.g.,

(6, 2432, 1280)  Distortion: Dist Type: Screamer

The 3-tuple is position, id, value, which is followed by the
colon separated decode of the position, id, and the mapped value.
2012-04-07 19:45:50 -07:00
Tim LaBerge
88819a795b Fixup label range values.
A number of EffectValues of type label had invalid ranges. Make
them less invalid.

Also add SYNTH_TALK id's to xml settings.

Make format_ipv warn instead of crashing if an xml setting is not
found.
2012-04-06 10:06:12 -07:00
Tim LaBerge
3002d2256e Human readable debug
Leverage the code that writes a preset to XML so that messages
can be displayed in a human readable format.

E.g.,

(6, 2432, 1280)  Distortion: Dist Type: Screamer

The 3-tuple is position, id, value, which is followed by the
colon separated decode of the position, id, and the mapped value.
2012-04-06 08:57:08 -07:00
Tim LaBerge
1205a1639d Add 'Label' to modifier group log message. 2012-03-31 18:48:49 -07:00
Tim LaBerge
122bbcd823 More logging changes. 2012-03-31 18:48:22 -07:00
Tim LaBerge
5c42cad5e7 Add labels to debug messages.
Add a global settings settings to the xml settings array.

Start adding label strings to the debug messages. This
needs cleaning up, but it should help.
2012-03-31 18:25:19 -07:00
Tim LaBerge
7781063407 Presence effect in wrong place for some devices. 2012-03-31 18:25:10 -07:00
Tim LaBerge
e56884ecd9 Add missing effects to modifier array.
Change AMP_POSITION to AMP_A_POSITION.

Add AMP_B_POSITION to the modifier array.

Add AMP_PRESENCE to the modifier array and move it to follow Treble
in the Equalizer effect.

Add EQ_B_POSITION settings to the modifier array.

Change the formatting of the debug messages to print more
readable columns.

Conflicts:

	gdigi.c
2012-03-31 18:24:29 -07:00
Tim LaBerge
dd1f4408c9 Better message tracking. 2012-03-31 18:18:00 -07:00
Tim LaBerge
f3dbaf43ec Merge remote-tracking branch 'upstream/master' 2012-03-31 17:54:53 -07:00
Tim LaBerge
87ae4cd280 Add 'Label' to modifier group log message. 2012-03-31 17:45:12 -07:00
Tim LaBerge
a073f5cde2 Refine logging infrastructure.
1) Make logging conditional on debug flags.

2) Add command line option for setting these flags.

3) Emit warnings with g_warning() instead of g_message().

4) Added note about how FX_LIB_LEVEL_MAX[1-3] is used.
2012-02-27 20:26:42 -08:00
Tim LaBerge
9fcf6939d0 Add labels to debug messages.
Add a global settings settings to the xml settings array.

Start adding label strings to the debug messages. This
needs cleaning up, but it should help.
2012-02-26 21:52:27 -08:00
Tim LaBerge
71e087cfd0 Presence effect in wrong place for some devices. 2012-02-26 21:27:54 -08:00
Tim LaBerge
6a16e66cbd Add missing effects to modifier array.
Change AMP_POSITION to AMP_A_POSITION.

Add AMP_B_POSITION to the modifier array.

Add AMP_PRESENCE to the modifier array and move it to follow Treble
in the Equalizer effect.

Add EQ_B_POSITION settings to the modifier array.

Change the formatting of the debug messages to print more
readable columns.
2012-02-26 21:21:27 -08:00
Tim LaBerge
4351613e72 Add a .gitignore file. 2012-02-26 20:45:26 -08:00
Tim LaBerge
2253833105 Add retrieval of global settings. Start LFO. 2012-02-26 08:37:51 -08:00
Tim LaBerge
87e6dcbb9c Better message tracking and retrieve usb settings. 2012-02-26 08:29:43 -08:00
Tim LaBerge
d92489348d Add the USB (global) effects. 2012-02-25 18:10:58 -08:00
Tim LaBerge
2b27302166 1) Require libxml-2 and build new file preset_xml.c
2) In effects.c, some EffectsValues are changed to better reflect the
   strings used in the XML.

3) New EffectSettings are added for use when writing out effects to XML.

4) Added an XmlLabel structure for mapping a value to a string. Generally,
   these are the union of the set of all values over the set of supported
   devices.

5) There's a large array of XmlSettings used to derive the translation of
   a preset to XML.

6) Add an enum for product_id and use it to set a filter for file suffix.

7) Minor cleanup in push_message() that suppresses spurious error messages.

8) Fixed a bad memset in read_data_thread().

9) In gdigi.h, a few changes in names to be consistent with XML.

   There are some new definitions of LFO and VSWITCH parameters that
   need to be computed.

10) In gui.c, fixed up a compiler warning.

    Added a map from device id to file type and code to set a default filter
    in the read dialog.

    Wired up the 'save to XML' callback and reorganized the menue entries to
    better distinguish between 'save to file' and 'store to device'.

   In preset.c, sort the params so that what we write as XML more closely
   matches what is generated on the windows side.
2012-02-25 17:52:52 -08:00
18 changed files with 6907 additions and 5616 deletions

9
.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
*.[om]
*.rp355p
cscope.*
tags
gdigi
*.orig
*.swp
images/gdigi_icon.h
core

View File

@@ -2,10 +2,11 @@ Tomasz Moń <desowin@gmail.com>
Stephen Rigler <riglersc@gmail.com>
Jaco Kroon <jaco@kroon.co.za>
Rafael Moreno <laocanfei@yahoo.com>
Andrew O. Shadoura <bugzilla@tut.by>
Andrew Shadura <bugzilla@tut.by>
Andreas Karajannis <aakara13@googlemail.com>
Miklos Aubert <miklos.aubert@gmail.com>
Jonathan A. Tice <jonandtice@gmail.com>
John Hammen <jhammen@gmail.com>
Ahmed Toulan <thelinuxer@gmail.com>
Tim LaBerge <tlaberge@visi.com>
Mauro Carvalho Chehab <maurochehab@gmail.com>

View File

@@ -3,7 +3,7 @@ EXTRA_CFLAGS ?=
EXTRA_LDFLAGS ?=
CFLAGS := $(shell pkg-config --cflags glib-2.0 gio-2.0 gtk+-3.0 libxml-2.0) -Wall -g -ansi -std=c99 $(EXTRA_CFLAGS)
LDFLAGS = $(EXTRA_LDFLAGS) -Wl,--as-needed
LDADD := $(shell pkg-config --libs glib-2.0 gio-2.0 gtk+-3.0 gthread-2.0 alsa libxml-2.0) -lexpat
LDADD := $(shell pkg-config --libs glib-2.0 gio-2.0 gtk+-3.0 gthread-2.0 alsa libxml-2.0) -lexpat -lm
OBJECTS = gdigi.o gui.o effects.o preset.o gtkknob.o preset_xml.o
DEPFILES = $(foreach m,$(OBJECTS:.o=),.$(m).m)
@@ -19,16 +19,21 @@ all: gdigi
gdigi: $(OBJECTS)
$(CC) $(LDFLAGS) -o $@ $+ $(LDADD)
images/gdigi_icon.h: images/icon.png
gdk-pixbuf-csource --raw --name=gdigi_icon $< > $@
clean:
rm -f *.o
distclean : clean
rm -f .*.m
rm -f images/gdigi_icon.h
rm -f gdigi
install: gdigi
install gdigi $(DESTDIR)/usr/bin
install gdigi.desktop $(DESTDIR)/usr/share/applications/
install -m 0644 gdigi.desktop $(DESTDIR)/usr/share/applications/
install -m 0644 images/gdigi.png $(DESTDIR)/usr/share/icons/
NODEP_TARGETS := clean distclean
depinc := 1

825
effects.c

File diff suppressed because it is too large Load Diff

View File

@@ -27,7 +27,8 @@ typedef enum {
VALUE_TYPE_LABEL = 1 << 3, /**< use value labels (overrides any other option) */
VALUE_TYPE_EXTRA = 1 << 4, /**< use extra values */
VALUE_TYPE_DECIMAL= 1 << 5, /**< display decimal places */
VALUE_TYPE_NONE = 1 << 6, /**< no value displayed */
VALUE_TYPE_POSID = 1 << 6, /**< Packed Position/ID: (pos << 16) | id */
VALUE_TYPE_NONE = 1 << 7, /**< no value displayed */
} ValueType;
typedef struct _EffectValues {
@@ -105,7 +106,7 @@ enum product_id {
RP255 = 8,
RP355 = 9,
};
typedef struct {
gchar *name;
unsigned char family_id;
@@ -116,12 +117,16 @@ typedef struct {
gint n_banks;
} Device;
ModifierGroup *modifier_linkable_list();
void modifier_group_free(ModifierGroup *modifier_group);
gchar *get_position(guint position);
void update_modifier_linkable_list(GString* msg);
extern ModifierGroup *ModifierLinkableList;
EffectGroup *get_modifier_group(void);
guint get_modifier_amt(void);
void get_values_info(EffectValues *values,
gdouble *min, gdouble *max, gboolean *custom);
gboolean get_device_info(unsigned char device_id, unsigned char family_id,
unsigned char product_id,
Device **device);
#endif /* GDIGI_EFFECTS_H */

415
gdigi.c
View File

@@ -21,6 +21,7 @@
#include <alsa/asoundlib.h>
#include <alloca.h>
#include "gdigi.h"
#include "gdigi_xml.h"
#include "gui.h"
static unsigned char device_id = 0x7F;
@@ -35,6 +36,173 @@ static GQueue *message_queue = NULL;
static GMutex *message_queue_mutex = NULL;
static GCond *message_queue_cond = NULL;
static guint DebugFlags;
gboolean
debug_flag_is_set (debug_flags_t flags)
{
if (DebugFlags & flags) {
return TRUE;
}
return FALSE;
}
gboolean set_debug_flags (const gchar *option_name, const gchar *value,
gpointer data, GError **error)
{
if (strchr(value, 'd')) {
DebugFlags |= DEBUG_MSG2DEV;
}
if (strchr(value, 'h')) {
DebugFlags |= DEBUG_MSG2HOST;
}
if (strchr(value, 'm')) {
DebugFlags |= DEBUG_MSG2DEV|DEBUG_MSG2HOST|DEBUG_GROUP;
}
if (strchr(value, 's')) {
DebugFlags |= DEBUG_STARTUP;
}
if (strchr(value, 'H')) {
DebugFlags |= DEBUG_HEX;
}
if (strchr(value, 'g')) {
DebugFlags |= DEBUG_GROUP;
}
if (strchr(value, 'x')) {
DebugFlags |= DEBUG_XML;
}
if (strchr(value, 'v')) {
DebugFlags |= DEBUG_VERBOSE;
}
if (strchr(value, 'a')) {
DebugFlags = -1;
}
return TRUE;
}
void
debug_msg (debug_flags_t flags, char *fmt, ...)
{
char buf[1024];
if (flags & DebugFlags) {
va_list ap;
va_start(ap, fmt);
vsnprintf(buf, 1024, fmt, ap);
va_end(ap);
fprintf(stderr, "%s\n", buf);
}
}
/*
* Format a value according to the xml setting.
* Returns an allocated buffer that must be freed by the caller.
*/
GString *
format_value (XmlSettings *xml, guint value)
{
GString *buf = g_string_sized_new(1);
EffectValues *values = NULL;
ValueType vtype;
gchar *suffix = "";
gdouble step = 1.0;
gint offset = 0;
gboolean decimal = FALSE;
values = xml->values;
vtype = values->type;
while ((vtype & VALUE_TYPE_EXTRA) && value_is_extra(values, value)) {
values = values->extra;
vtype = values->type;
}
vtype &= ~VALUE_TYPE_EXTRA;
if (vtype & VALUE_TYPE_OFFSET) {
offset = values->offset;
vtype &= ~VALUE_TYPE_OFFSET;
}
if (vtype & VALUE_TYPE_STEP) {
step = values->step;
vtype &= ~VALUE_TYPE_STEP;
}
if (vtype & VALUE_TYPE_SUFFIX) {
suffix = values->suffix;
vtype &= ~VALUE_TYPE_SUFFIX;
}
if (vtype & VALUE_TYPE_DECIMAL) {
decimal = TRUE;
vtype &= ~VALUE_TYPE_DECIMAL;
}
switch (vtype) {
case VALUE_TYPE_LABEL:
{
char *textp = map_xml_value(xml, values, value);
if (!textp) {
g_warning("%s: Unable to map %s value %d for id %d position %d",
__FUNCTION__, xml->label, value, xml->id, xml->position);
textp = "";
}
g_string_printf(buf, "%s", textp);
break;
}
case VALUE_TYPE_PLAIN:
{
if (decimal) {
double dvalue = ((gint)value + offset) * step;
g_string_printf(buf, "%0.2f%s", dvalue, suffix);
} else {
gint ivalue = ((gint)value + offset) * step;
g_string_printf(buf, "%d%s", ivalue, suffix);
}
break;
}
case VALUE_TYPE_NONE:
g_string_printf(buf, "%s", "");
break;
case VALUE_TYPE_POSID:
g_string_printf(buf, "%d", value);
break;
default:
g_warning("Unhandled value type %d", vtype);
break;
}
return buf;
}
GString *
format_ipv (guint id, guint pos, guint val)
{
GString *buf = g_string_sized_new(1);
GString *vec_buf = g_string_sized_new(1);
XmlSettings *xml = get_xml_settings(id, pos);
GString *val_buf;
if (!xml) {
g_warning("Failed to find xml settings for position %d id %d.",
pos, id);
g_string_printf(buf, "%s", "error");
return buf;
}
val_buf = format_value(xml, val);
g_string_printf(vec_buf, "(%d, %d, %d)", pos, id, val);
g_string_printf(buf, "%-16s %s: %s: %s",
vec_buf->str,
get_position(pos), xml->label, val_buf->str);
g_string_free(vec_buf, TRUE);
g_string_free(val_buf, TRUE);
return buf;
}
/**
* Registers an error quark for gdigi if necessary.
*
@@ -218,33 +386,57 @@ MessageID get_message_id(GString *msg)
return -1;
}
#define HEX_WIDTH 26
static gboolean modifier_linkable_list_request_pending = FALSE;
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
MessageID msgid = get_message_id(msg);
if (((unsigned char)msg->str[0] == 0xF0) &&
((unsigned char)msg->str[msg->len-1] == 0xF7)) {
debug_msg(DEBUG_VERBOSE, "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");
if (debug_flag_is_set(DEBUG_HEX)) {
for (x = 0; x<msg->len; x++) {
if (x && (x % HEX_WIDTH) == 0) {
printf("\n");
}
printf("%02x ", (unsigned char)msg->str[x]);
}
if (x % HEX_WIDTH) {
printf("\n");
}
}
debug_msg(DEBUG_VERBOSE, "Received %s", get_message_name(msgid));
switch (get_message_id(msg)) {
SettingParam *param;
switch (msgid) {
case ACK:
g_message("Received ACK");
g_string_free(msg, TRUE);
return;
case NACK:
g_message("Received NACK");
g_warning("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);
param = setting_param_new_from_data(&msg->str[8], NULL);
if (debug_flag_is_set(DEBUG_MSG2HOST)) {
GString *ipv = format_ipv(param->id,
param->position,
param->value);
debug_msg(DEBUG_MSG2HOST, "RECEIVE_PARAMETER_VALUE\n%s",
ipv->str);
g_string_free(ipv, TRUE);
}
GDK_THREADS_ENTER();
apply_setting_param_to_gui(param);
@@ -253,32 +445,127 @@ void push_message(GString *msg)
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]);
case NOTIFY_PRESET_MOVED:
if (str[11] == PRESETS_EDIT_BUFFER && str[12] == 0) {
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]);
GDK_THREADS_ENTER();
g_timeout_add(0, apply_current_preset_to_gui, NULL);
GDK_THREADS_LEAVE();
debug_msg(DEBUG_MSG2HOST,
"RECEIVE_DEVICE_NOTIFICATION: Loaded preset "
"%d from bank %d",
str[10], str[9]);
} else {
debug_msg(DEBUG_MSG2HOST,
"RECEIVE_DEVICE_NOTIFICATION: %d %d moved to "
"%d %d",
str[9], str[10],
str[11], str[12]);
}
break;
case NOTIFY_MODIFIER_GROUP_CHANGED:
{
int i;
if (debug_flag_is_set(DEBUG_HEX)) {
printf("\n");
for (i = 0; i < msg->len; i++) {
printf(" %02x", (unsigned char) str[i]);
}
break;
default:
g_message("Received unhandled device notification 0x%x", str[11]);
printf("\n");
}
debug_msg(DEBUG_MSG2HOST,
"NOTIFY_MODIFIER_GROUP_CHANGED: Modifier group "
"id %d changed",
(str[9] << 8) | (str[10]));
if (!modifier_linkable_list_request_pending) {
send_message(REQUEST_MODIFIER_LINKABLE_LIST, "\x00\x01", 2);
modifier_linkable_list_request_pending = TRUE;
}
break;
}
default:
g_warning("Received unhandled device notification 0x%x",
str[11]);
}
g_string_free(msg, TRUE);
return;
case RECEIVE_GLOBAL_PARAMETERS:
unpack_message(msg);
gint tot, n, x;
tot = (unsigned char)msg->str[9];
if (debug_flag_is_set(DEBUG_HEX)) {
for (n = 0; n < msg->len; n++) {
printf("%02x ",(unsigned char) msg->str[n]);
}
printf("\n");
}
n = 0;
x = 10;
do {
param = setting_param_new_from_data(&msg->str[x], &x);
debug_msg(DEBUG_MSG2HOST,
"RECEIVE_GLOBAL_PARAMETERS ID: %5d "
"Position: %2.1d Value: %6.1d: %s",
param->id,
param->position, param->value, "XXX");
GDK_THREADS_ENTER();
apply_setting_param_to_gui(param);
GDK_THREADS_LEAVE();
setting_param_free(param);
} while ( (x < msg->len) && n < tot);
g_string_free(msg, TRUE);
return;
case RECEIVE_MODIFIER_LINKABLE_LIST:
modifier_linkable_list_request_pending = FALSE;
unpack_message(msg);
tot = (unsigned char)msg->str[9];
if (debug_flag_is_set(DEBUG_HEX)) {
for (n = 0; n < msg->len; n++) {
printf("%02x ",(unsigned char) msg->str[n]);
}
printf("\n");
}
update_modifier_linkable_list(msg);
g_string_free(msg, TRUE);
GDK_THREADS_ENTER();
create_modifier_group(EXP_POSITION, EXP_ASSIGN1);
create_modifier_group(LFO1_POSITION, LFO_TYPE);
create_modifier_group(LFO2_POSITION, LFO_TYPE);
GDK_THREADS_LEAVE();
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);
break;
}
}
@@ -301,7 +588,8 @@ gpointer read_data_thread(gboolean *stop)
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 our buffer to 0xFF, so if for some reason we'll
get out of reply bounds, we'll catch it */
memset(buf, '\0', sizeof(buf));
err = poll(pfds, npfds, 200);
@@ -400,6 +688,9 @@ void send_message(gint procedure, gchar *data, gint len)
g_string_append_printf(msg, "%c\xF7",
calculate_checksum(&msg->str[1], msg->len - 1));
debug_msg(DEBUG_VERBOSE, "Sending %s len %d",
get_message_name(procedure), len);
send_data(msg->str, msg->len);
g_string_free(msg, TRUE);
@@ -620,12 +911,30 @@ SectionID get_genetx_section_id(gint version, gint type)
}
}
g_message("This version of gdigi don't know what to do with this "
g_warning("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
* \param value Parameter value
*
* Forms SysEx message to request parameter then sends it to device.
**/
void get_option(guint id, guint position)
{
GString *msg = g_string_sized_new(9);
debug_msg(DEBUG_MSG2DEV, "REQUEST_PARAMETER_VALUE: id %d position %d",
id, position);
g_string_append_printf(msg, "%c%c%c",
((id & 0xFF00) >> 8), (id & 0xFF),
position);
send_message(REQUEST_PARAMETER_VALUE, msg->str, msg->len);
g_string_free(msg, TRUE);
}
/**
* \param id Parameter ID
* \param position Parameter position
@@ -640,6 +949,11 @@ void set_option(guint id, guint position, guint value)
((id & 0xFF00) >> 8), (id & 0xFF),
position);
append_value(msg, value);
if (debug_flag_is_set(DEBUG_MSG2DEV)) {
GString *ipv = format_ipv(id, position, value);
debug_msg(DEBUG_MSG2DEV, "RECEIVE_PARAMETER_VALUE\n%s", ipv->str);
g_string_free(ipv, TRUE);
}
send_message(RECEIVE_PARAMETER_VALUE, msg->str, msg->len);
g_string_free(msg, TRUE);
}
@@ -846,11 +1160,12 @@ GList *get_message_list(MessageID id)
g_error("get_message_list() doesn't support followning id: %d", id);
g_string_free(data, TRUE);
g_list_free(list);
g_assert(!"BUG");
return NULL;
}
while (amt) {
g_message("%d messages left", amt);
debug_msg(DEBUG_VERBOSE, "%d messages left", amt);
data = g_queue_pop_nth(message_queue, x);
if (data == NULL) {
g_cond_wait(message_queue_cond, message_queue_mutex);
@@ -1058,9 +1373,11 @@ static gboolean request_who_am_i(unsigned char *device_id, unsigned char *family
*device_id = data->str[8];
*family_id = data->str[9];
*product_id = data->str[10];
g_message("I am device id %d family %d product id %d.",
*device_id, *family_id, *product_id);
g_string_free(data, TRUE);
debug_msg(DEBUG_STARTUP, "Found device id %d family %d product id %d.",
*device_id,
*family_id,
*product_id);
return TRUE;
}
return FALSE;
@@ -1107,6 +1424,25 @@ static void request_device_configuration()
static GOptionEntry options[] = {
{"device", 'd', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_STRING, &device_port, "MIDI device port to use", NULL},
{"debug-flags <flags>", 'D', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_CALLBACK, set_debug_flags,
"<flags> any of a, d, g, h, m, s, x, v:\n"
" "
"a: Everything.\n"
" "
"d: Messages to the device.\n"
" "
"g: Group messages.\n"
" "
"h: Dump message contents in hex.\n"
" "
"m: All messages.\n"
" "
"s: Startup.\n"
" "
"x: Debug xml parsing/writing.\n"
" "
"v: Additional verbosity.\n" ,
NULL},
{NULL}
};
@@ -1132,6 +1468,7 @@ static gint get_digitech_devices(GList **devices)
number++;
*devices = g_list_append(*devices, GINT_TO_POINTER(card_num));
}
free(name);
}
return number;
@@ -1151,7 +1488,7 @@ int main(int argc, char *argv[]) {
g_option_context_add_group(context, gtk_get_option_group(TRUE));
if (!g_option_context_parse(context, &argc, &argv, &error)) {
g_message("option parsing failed: %s\n", error->message);
g_warning("option parsing failed: %s\n", error->message);
g_error_free(error);
g_option_context_free(context);
exit(EXIT_FAILURE);
@@ -1159,12 +1496,12 @@ int main(int argc, char *argv[]) {
if (device_port == NULL) {
/* port not given explicitly in commandline - search for devices */
GList *devices = NULL;
GList *device = NULL;
int num_devices = 0;
int chosen_device = 0;
GList *devices = NULL;
GList *device = NULL;
int num_devices = 0;
int chosen_device = 0;
if ((num_devices = get_digitech_devices(&devices)) <= 0) {
g_message("Couldn't find any DigiTech devices!");
g_warning("Couldn't find DigiTech devices!");
exit(EXIT_FAILURE);
}
if (num_devices > 1) {
@@ -1178,9 +1515,9 @@ int main(int argc, char *argv[]) {
device_port = g_strdup_printf("hw:%d,0,0",
GPOINTER_TO_INT(device->data));
g_list_free(devices);
g_message("Found device %s", device_port);
debug_msg(DEBUG_STARTUP, "Found device %s.", device_port);
} else {
g_message("Using device %s", device_port);
debug_msg(DEBUG_STARTUP, "Using device %s.", device_port);
}
g_option_context_free(context);
@@ -1208,14 +1545,14 @@ int main(int argc, char *argv[]) {
if (device != NULL) {
/* enable GUI mode */
set_option(GUI_MODE_ON_OFF, USB_POSITION, 1);
set_option(GUI_MODE_ON_OFF, GLOBAL_POSITION, 1);
gui_create(device);
gtk_main();
gui_free();
/* disable GUI mode */
set_option(GUI_MODE_ON_OFF, USB_POSITION, 0);
set_option(GUI_MODE_ON_OFF, GLOBAL_POSITION, 0);
}
}
}
@@ -1229,8 +1566,8 @@ int main(int argc, char *argv[]) {
g_mutex_free(message_queue_mutex);
}
if (message_queue != NULL) {
g_message("%d unread messages in queue",
if (message_queue != NULL && g_queue_get_length(message_queue)) {
g_warning("%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);

View File

@@ -3,5 +3,7 @@ Version=1.0
Type=Application
Name=gdigi
Exec=gdigi
Categories=GNOME;Audio;AudioVideo;
Categories=GTK;Audio;AudioVideo;
Icon=gdigi
X-Desktop-File-Install-Version=0.20

53
gdigi.h
View File

@@ -22,6 +22,19 @@
#ifndef DOXYGEN_SHOULD_SKIP_THIS
typedef enum {
DEBUG_MSG2DEV = (1 << 0), // Device bound messages.
DEBUG_MSG2HOST = (1 << 1), // Host bound messages.
DEBUG_STARTUP = (1 << 2),
DEBUG_GROUP = (1 << 3), // Modifier group
DEBUG_HEX = (1 << 4), // Dump message contents in hex.
DEBUG_XML = (1 << 5),
DEBUG_VERBOSE = (1 << 6),
} debug_flags_t;
void debug_msg (debug_flags_t, char *fmt, ...);
gboolean debug_flag_is_set (debug_flags_t flag);
#define GNX_CHANNEL_POSITION 7
#define GNX_CHANNEL_AMP 260
#define GNX_WARP 261
@@ -238,6 +251,9 @@ enum {
#define PRESET_POSITION 18
#define PRESET_LEVEL 2626
#define STOMP_LOOP_ON_OFF 3329
#define STOMP_LOOP_POSITION 34
enum {
AMP_TYPE_TWEED_CHAMP = 307,
AMP_TYPE_TWEED_DELUXE = 308,
@@ -315,7 +331,7 @@ enum {
#define AMP_TYPE 2496
#define AMP_ON_OFF 265
#define AMP_POSITION 8
#define AMP_A_POSITION 8
#define AMP_B_POSITION 10
#define AMP_LOOP_ON_OFF 3649
@@ -427,9 +443,8 @@ enum {
#define EQ_TREB_FREQ 3211
#define EQ_ENABLE 3212
#define EQ_LOW_FREQ 3213
#define EQ_MID_FREQ_XXX 3214
#define EQ_MID_FREQ_RP500 3214
#define EQ_HIGH_FREQ 3215
#define EQ_TREBLE_FREQ 3215
@@ -518,7 +533,6 @@ enum {
};
#define MOD_TYPE 768
#define MOD_POSITION 768
#define MOD_PRE_POST 1798
#define CHORUSFX_TYPE 768
@@ -731,7 +745,7 @@ enum {
IPS_SCALE_LYDIAN = 4,
IPS_SCALE_HMINOR = 5,
};
#define OCTAVER_OCTAVE1 1746
#define OCTAVER_OCTAVE2 1747
#define OCTAVER_DRY_LEVEL 1748
@@ -842,7 +856,7 @@ enum {
#define EXP_POSITION 19
#define EXP_VOLUME_PRE_FX 854594
#define EXP_VOLUME_POST_FX 1116738
#define EXP_VOLUME_POST_FX 1116738
#define EXP_MIN 8195
#define EXP_MAX 8196
@@ -855,7 +869,7 @@ enum {
#define LFO_WAVEFORM_TRI 0
#define LFO_WAVEFORM_SINE 1
#define LFO_WAVEFORM_SQUARE 2
#define LFO_WAVEFORM_SQUARE 2
#define LFO1_POSITION 22
#define LFO2_POSITION 23
@@ -864,7 +878,7 @@ enum {
#define LFO_ASSIGN_NONE 0
#define LFO_ASSIGN_PICKUP_ON 131137
#define LFO_ASSIGN_COMP_ON 262337
#define LFO_ASSIGN_SUSTAN 262352
#define LFO_ASSIGN_SUSTAN 262352
#define VSWITCH_ASSIGN 8384
#define VSWITCH_MIN 8385
@@ -877,16 +891,24 @@ enum {
#define VSWITCH_PEDAL_ASSIGN_WAH 196740
#define VSWITCH_ASSIGN_WAH_ENABLE 196737
#define FOOTSWITCH_6_POSITION 28
#define FOOTSWITCH_7_POSITION 29
#define FOOTSWITCH_8_POSITION 30
#define FOOTSWITCH_9_POSITION 31
#define FOOTSWITCH_10_POSITION 32
#define LIBRARY_TONE 8704
#define LIBRARY_EFFECTS 8705
#define EFFECTS_LEVEL 8706
#define LIBRARY_POSITION 25
#define LIB_POSITION 26
#define LIB_POSITION_A 26
#define LIB_POSITION_B 25
#define TONE_LIB_TYPE 8704
#define FX_LIB_TYPE 8705
#define FX_LIB_LEVEL 8706
#define FX_LIB_LEVEL 8706 // This influences pitch shift mix, delay level,
// and reverb level, in proportion, as
// specified by FX_LIB_LEVEL_MAX1,2,3.
#define FX_LIB_LEVEL_MAX1 8708
#define FX_LIB_LEVEL_MAX2 8710
#define FX_LIB_LEVEL_MAX3 8712
@@ -963,12 +985,17 @@ enum {
EFFECTS_LIB_CUSTOM = 1856
};
#define USB_POSITION 0
#define GLOBAL_POSITION 0
#define TUNING_REFERENCE 12288
#define USB_AUDIO_PLAYBACK_MIX 12297
#define USB_AUDIO_LEVEL 12307
#define GUI_MODE_ON_OFF 12298
#define EXP_PEDAL_LEVEL 12300
#define STOMP_MODE 12370
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
typedef enum {
@@ -1114,6 +1141,7 @@ 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 get_option(guint id, guint position);
void send_object(SectionID section, guint bank, guint index,
gchar *name, GString *data);
void send_preset_parameters(GList *params);
@@ -1123,5 +1151,6 @@ void set_preset_level(int level);
GStrv query_preset_names(gchar bank);
void message_list_free(GList *list);
GList *get_current_preset();
GString *format_ipv(guint id, guint pos, guint val);
#endif /* GDIGI_H */

View File

@@ -33,7 +33,8 @@ typedef struct {
guint xml_labels_amt;
} XmlSettings;
// XmlSettings *get_xml_settings(guint id, guint position);
// gchar *get_xml_label(guint id, guint position, gint type);
XmlSettings *get_xml_settings(guint id, guint position);
gboolean value_is_extra(EffectValues *val, int value);
gchar * map_xml_value(XmlSettings *xml, EffectValues *values, gint value);
#endif /* GDIGI_XML_H */

View File

@@ -18,7 +18,8 @@
*
* 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.
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA.
*****************************************************************************/
#include <math.h>
@@ -153,6 +154,7 @@ gtk_knob_init (GtkKnob *knob) {
gtk_widget_set_has_window(GTK_WIDGET(knob), FALSE);
gtk_widget_set_hexpand(GTK_WIDGET(knob), FALSE);
gtk_widget_set_vexpand(GTK_WIDGET(knob), FALSE);
gtk_widget_add_events(GTK_WIDGET(knob), GDK_SCROLL_MASK);
}
@@ -367,7 +369,7 @@ gtk_knob_get_preferred_width(GtkWidget *widget,
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_KNOB (widget));
*minimum_width = *natural_width = GTK_KNOB(widget)->width;
*minimum_width = *natural_width = GTK_KNOB(widget)->width;
}
static void
@@ -378,7 +380,7 @@ gtk_knob_get_preferred_height(GtkWidget *widget,
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_KNOB (widget));
*minimum_height = *natural_height = GTK_KNOB(widget)->height;
*minimum_height = *natural_height = GTK_KNOB(widget)->height;
}
@@ -624,7 +626,7 @@ static gint gtk_knob_key_press(GtkWidget *widget, GdkEventKey *event)
static gint
gtk_knob_motion_notify(GtkWidget *widget, GdkEventMotion *event) {
GtkKnob *knob;
GdkModifierType mods;
GdkWindow *window;
gint x, y;
g_return_val_if_fail (widget != NULL, FALSE);
@@ -636,10 +638,6 @@ gtk_knob_motion_notify(GtkWidget *widget, GdkEventMotion *event) {
x = event->x;
y = event->y;
if (event->is_hint || (event->window != gtk_widget_get_window(widget))) {
gdk_window_get_pointer(gtk_widget_get_window(widget), &x, &y, &mods);
}
switch (knob->state) {
case STATE_PRESSED:
@@ -647,14 +645,22 @@ gtk_knob_motion_notify(GtkWidget *widget, GdkEventMotion *event) {
/* 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;
}
window = gtk_widget_get_window(widget);
if (event->is_hint || (event->window != window)) {
GdkModifierType mods;
GdkDeviceManager *device_manager = gdk_display_get_device_manager(gdk_window_get_display(window));
GdkDevice *pointer = gdk_device_manager_get_client_pointer(device_manager);
gdk_window_get_device_position(window, pointer, &x, &y, &mods);
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;
}

View File

@@ -17,7 +17,8 @@
*
* 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.
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA.
*****************************************************************************/
#ifndef __GTK_KNOB_H__
#define __GTK_KNOB_H__
@@ -50,7 +51,7 @@ typedef enum
gint height; /* derived from image height. */
gint frame_width; /* derived from pixbuf (width / height) or provided override for rectangular frames */
};
struct _GtkKnob {
GtkWidget widget;
@@ -68,7 +69,7 @@ typedef enum
/* knob animation */
GtkKnobAnim *anim;
gint width, height;
/* Old values from adjustment stored so we know when something changes */
gdouble old_value;
gdouble old_lower;

413
gui.c
View File

@@ -23,6 +23,73 @@
#include "effects.h"
#include "preset.h"
#include "gtkknob.h"
#include "images/gdigi_icon.h"
#include "gdigi_xml.h"
static gchar* MessageID_names[] = {
[REQUEST_WHO_AM_I] = "REQUEST_WHO_AM_I",
[RECEIVE_WHO_AM_I] = "RECEIVE_WHO_AM_I",
[REQUEST_DEVICE_CONFIGURATION] = "REQUEST_DEVICE_CONFIGURATION",
[RECEIVE_DEVICE_CONFIGURATION] = "RECEIVE_DEVICE_CONFIGURATION",
[REQUEST_GLOBAL_PARAMETERS] = "REQUEST_GLOBAL_PARAMETERS",
[RECEIVE_GLOBAL_PARAMETERS] = "RECEIVE_GLOBAL_PARAMETERS",
[REQUEST_BULK_DUMP] = "REQUEST_BULK_DUMP",
[RECEIVE_BULK_DUMP_START] = "RECEIVE_BULK_DUMP_START",
[RECEIVE_BULK_DUMP_END] = "RECEIVE_BULK_DUMP_END",
[REQUEST_PRESET_NAMES] = "REQUEST_PRESET_NAMES",
[RECEIVE_PRESET_NAMES] = "RECEIVE_PRESET_NAMES",
[REQUEST_PRESET_NAME] = "REQUEST_PRESET_NAME",
[RECEIVE_PRESET_NAME] = "RECEIVE_PRESET_NAME",
[REQUEST_PRESET] = "REQUEST_PRESET",
[RECEIVE_PRESET_START] = "RECEIVE_PRESET_START",
[RECEIVE_PRESET_END] = "RECEIVE_PRESET_END",
[RECEIVE_PRESET_PARAMETERS] = "RECEIVE_PRESET_PARAMETERS",
[LOAD_EDIT_BUFFER_PRESET] = "LOAD_EDIT_BUFFER_PRESET",
[MOVE_PRESET] = "MOVE_PRESET",
[REQUEST_MODIFIER_LINKABLE_LIST] = "REQUEST_MODIFIER_LINKABLE_LIST",
[RECEIVE_MODIFIER_LINKABLE_LIST] = "RECEIVE_MODIFIER_LINKABLE_LIST",
[REQUEST_PARAMETER_VALUE] = "REQUEST_PARAMETER_VALUE",
[RECEIVE_PARAMETER_VALUE] = "RECEIVE_PARAMETER_VALUE",
/* version 1 and later */
[REQUEST_OBJECT_NAMES] = "REQUEST_OBJECT_NAMES",
[RECEIVE_OBJECT_NAMES] = "RECEIVE_OBJECT_NAMES",
[REQUEST_OBJECT_NAME] = "REQUEST_OBJECT_NAME",
[RECEIVE_OBJECT_NAME] = "RECEIVE_OBJECT_NAME",
[REQUEST_OBJECT] = "REQUEST_OBJECT",
[RECEIVE_OBJECT] = "RECEIVE_OBJECT",
[MOVE_OBJECT] = "MOVE_OBJECT",
[DELETE_OBJECT] = "DELETE_OBJECT",
[REQUEST_TABLE] = "REQUEST_TABLE",
[RECEIVE_TABLE] = "RECEIVE_TABLE",
[RECEIVE_DEVICE_NOTIFICATION] = "RECEIVE_DEVICE_NOTIFICATION",
[ACK] = "ACK",
[NACK] = "NACK",
};
const gchar*
get_message_name(MessageID msgid)
{
if (MessageID_names[msgid]) {
return MessageID_names[msgid];
}
return "Unknown";
}
typedef struct {
GObject *widget;
@@ -54,7 +121,7 @@ void show_error_message(GtkWidget *parent, gchar *message)
GTK_BUTTONS_OK,
"%s", message);
gtk_dialog_run(GTK_DIALOG(msg));
(void)gtk_dialog_run(GTK_DIALOG(msg));
gtk_widget_destroy(msg);
}
@@ -184,7 +251,7 @@ static gboolean custom_value_output_cb(GtkSpinButton *spin, EffectValues *values
if (values->type & VALUE_TYPE_EXTRA) {
values = values->extra;
} else {
g_message("custom_value_output_cb called with out of bounds value");
g_warning("custom_value_output_cb called with out of bounds value");
return FALSE;
}
}
@@ -306,8 +373,9 @@ static void apply_widget_setting(WidgetTreeElem *el, SettingParam *param)
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)
if (el->value == param->value) {
gtk_combo_box_set_active(GTK_COMBO_BOX(el->widget), el->x);
}
}
}
@@ -375,6 +443,56 @@ gboolean apply_current_preset_to_gui(gpointer data)
return FALSE;
}
/**
* Free the data associated with the dynamically allocated settings
* for the EXP_POSITION.
*/
void modifier_settings_exp_free(EffectSettings *settings)
{
guint i;
guint id = settings->id;
guint pos = settings->position;
gpointer key;
GList *link, *next, *orig_list;
WidgetTreeElem *el;
GObject *widget;
for (i = 0; i < 2; i++) {
id = settings[i].id;
pos = settings[i].position;
key = GINT_TO_POINTER(pos <<16| id);
orig_list = g_tree_lookup(widget_tree, key);
if (!orig_list) {
continue;
}
link = g_list_first(orig_list);
while (link != NULL) {
next = link->next;
el = link->data;
if (el) {
widget = el->widget;
if (g_object_get_data(G_OBJECT(widget), "exp")) {
g_slice_free(WidgetTreeElem, el);
link->data = NULL;
}
}
link = next;
}
/* Remove all the list elements from which we freed data. */
orig_list = g_list_remove_all(orig_list, NULL);
/* The list should be empty at this point. */
g_assert(!orig_list);
/* Removed them all, so remove the key from the tree.*/
g_tree_steal(widget_tree, key);
}
}
/**
* \param settings effect parameters
* \param amt amount of effect parameters
@@ -424,6 +542,12 @@ GtkWidget *create_grid(EffectSettings *settings, gint amt, GHashTable *widget_ta
widget_tree_add(G_OBJECT(adj), settings[x].id,
settings[x].position, -1, -1);
if (settings[x].position == EXP_POSITION) {
/* Tag the adj so we can free it when we free the modifier group. */
g_object_set_data(G_OBJECT(adj), "exp", GINT_TO_POINTER(1));
}
gtk_grid_attach(GTK_GRID(grid), label, 0, x, 1, 1);
gtk_grid_attach(GTK_GRID(grid), knob, 1, x, 1, 1);
gtk_grid_attach(GTK_GRID(grid), widget, 2, x, 1, 1);
@@ -474,8 +598,9 @@ void effect_settings_group_free(EffectSettingsGroup *group)
{
if (group->child != NULL) {
/* destroy widget without parent */
if (gtk_widget_get_parent(group->child) == NULL)
if (gtk_widget_get_parent(group->child) == NULL) {
gtk_widget_destroy(group->child);
}
g_object_unref(group->child);
}
@@ -496,32 +621,40 @@ void combo_box_changed_cb(GtkComboBox *widget, gpointer data)
EffectSettingsGroup *settings = NULL;
gchar *name = NULL;
gint x;
g_object_get(G_OBJECT(widget), "active", &x, NULL);
vbox = g_object_get_data(G_OBJECT(widget), "vbox");
if (x != -1) {
GtkWidget *new_child = NULL;
name = g_strdup_printf("SettingsGroup%d", x);
settings = g_object_get_data(G_OBJECT(widget), name);
g_free(name);
if (settings != NULL && allow_send)
set_option(settings->id, settings->position, settings->type);
child = g_object_get_data(G_OBJECT(widget), "active_child");
if (child == settings->child) {
return;
if (settings != NULL)
{
if (allow_send)
set_option(settings->id, settings->position, settings->type);
if (child == settings->child) {
return;
}
}
if (child != NULL) {
gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(gtk_widget_get_parent(vbox))), child);
}
if (settings->child != NULL) {
if (settings != NULL && 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)));
new_child = settings->child;
}
g_object_set_data(G_OBJECT(widget), "active_child", settings->child);
g_object_set_data(G_OBJECT(widget), "active_child", new_child);
}
}
@@ -546,7 +679,7 @@ GtkWidget *create_widget_container(EffectGroup *group, gint amt, gint id, gint p
gint x;
gint cmbox_no = -1;
vbox = gtk_vbox_new(FALSE, 0);
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
widget_table = g_hash_table_new(g_direct_hash, g_direct_equal);
@@ -558,15 +691,22 @@ GtkWidget *create_widget_container(EffectGroup *group, gint amt, gint id, gint p
g_signal_connect(G_OBJECT(combo_box), "changed", G_CALLBACK(combo_box_changed_cb), group);
g_object_set_data(G_OBJECT(combo_box), "vbox", vbox);
}
gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo_box),
NULL, group[x].label);
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo_box), group[x].label);
cmbox_no++;
if ((group[x].settings != NULL) && (group[x].settings_amt > 0)) {
widget = create_grid(group[x].settings, group[x].settings_amt, widget_table);
/*
* Create a grid for each combo box entry to contain per
* combo box entry settings.
*/
widget = create_grid(group[x].settings,
group[x].settings_amt,
widget_table);
g_object_ref_sink(widget);
} else
} else {
widget = NULL;
}
settings = g_slice_new(EffectSettingsGroup);
settings->id = id;
@@ -577,11 +717,15 @@ GtkWidget *create_widget_container(EffectGroup *group, gint amt, gint id, gint p
widget_tree_add(G_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_object_set_data_full(G_OBJECT(combo_box),
name, settings,
((GDestroyNotify)effect_settings_group_free));
g_free(name);
} else {
if ((group[x].settings != NULL) && (group[x].settings_amt > 0)) {
widget = create_grid(group[x].settings, group[x].settings_amt, widget_table);
widget = create_grid(group[x].settings,
group[x].settings_amt,
widget_table);
gtk_box_pack_end(GTK_BOX(vbox), widget, FALSE, TRUE, 0);
}
}
@@ -592,6 +736,157 @@ GtkWidget *create_widget_container(EffectGroup *group, gint amt, gint id, gint p
return vbox;
}
/**
* Populate the vbox for an effect dependent on the modifier list.
*
* \param vbox The vbox for the effect.
* \param combo_box The combo box to repopulate.
* \param id The id of the effect.
* \param position The position of the effect.
*/
static void update_modifier_vbox(GtkWidget *vbox, GObject *combo_box, gint id, gint position)
{
gint x;
EffectSettingsGroup *settings = NULL;
EffectGroup *group = get_modifier_group();
guint amt = get_modifier_amt();
GtkWidget *child = NULL;
GHashTable *widget_table;
widget_table = g_hash_table_new(g_direct_hash, g_direct_equal);
for (x = 0; x<amt; x++) {
gchar *name;
g_assert(group[x].label);
settings = g_slice_new(EffectSettingsGroup);
settings->id = id;
settings->type = group[x].type;
settings->position = position;
if (position == EXP_POSITION) {
child = g_object_steal_data(G_OBJECT(combo_box), "active_child");
child = create_grid(group[x].settings, group[x].settings_amt,
widget_table);
g_object_ref_sink(child);
settings->child = child;
} else {
/* LFO has one settings group.*/
settings->child = NULL;
}
name = g_strdup_printf("SettingsGroup%d", x);
g_object_set_data(G_OBJECT(combo_box), name, settings);
g_free(name);
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo_box), group[x].label);
widget_tree_add(combo_box, id, position, group[x].type, x);
}
g_hash_table_destroy(widget_table);
return;
}
static void clean_modifier_combo_box(GObject *combo_box, GList *list)
{
EffectSettingsGroup *settings = NULL;
WidgetTreeElem *el;
gchar *name;
GList *link, *next, *stale_link;
link = g_list_first(list);
while (link != NULL) {
next = link->next;
el = link->data;
stale_link = NULL;
/* We need to clean the data associated with a combo box.
* This may include the per-entry settings widgets.
*/
if (el->value != -1) {
/* This is a combo box entry. Remove the associated data. */
stale_link = link;
link = g_list_remove_link(list, link);
name = g_strdup_printf("SettingsGroup%d", el->x);
settings = g_object_steal_data(G_OBJECT(combo_box), name);
if (settings && settings->child) {
gtk_widget_destroy(settings->child);
}
g_slice_free(EffectSettingsGroup, settings);
g_free(name);
g_slice_free(WidgetTreeElem, el);
}
if (stale_link) {
g_list_free_1(stale_link);
}
link = next;
}
gtk_combo_box_text_remove_all(GTK_COMBO_BOX_TEXT(combo_box));
}
/**
* Given a linkable effect, update the combo box for the linkable parameters.
*
* @param[in] pos Position
* @param[in] id Id
*/
void
create_modifier_group (guint pos, guint id)
{
GtkWidget *vbox;
gpointer key;
WidgetTreeElem *el;
GList *list;
GObject *modifier_combo_box;
debug_msg(DEBUG_GROUP, "Building modifier group for position %d id %d \"%s\"",
pos, id, get_xml_settings(id, pos)->label);
key = GINT_TO_POINTER((pos << 16) | id);
list = g_tree_lookup(widget_tree, key);
/*
* The list will be destroyed and recreated, but we don't want to
* handle the teardown ourselves. So steal it from the tree.
*/
g_tree_steal(widget_tree, key);
if (!list) {
return;
}
el = g_list_nth_data(list, 0);
if (!el) {
g_warning("No effect settings group for position %d id %d!\n",
pos, id);
return;
}
modifier_combo_box = el->widget;
g_assert(modifier_combo_box != NULL);
vbox = g_object_get_data(modifier_combo_box, "vbox");
g_assert(vbox != NULL);
clean_modifier_combo_box(modifier_combo_box, list);
update_modifier_vbox(vbox, modifier_combo_box, id, pos);
get_option(id, pos);
if (pos == EXP_POSITION) {
get_option(EXP_MIN, EXP_POSITION);
get_option(EXP_MAX, EXP_POSITION);
}
}
/**
* \param widgets Effect descriptions
* \param amt amount of effect descriptions
@@ -613,13 +908,14 @@ GtkWidget *create_vbox(Effect *widgets, gint amt, gchar *label)
frame = gtk_frame_new(label);
vbox = gtk_vbox_new(FALSE, 0);
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
grid = gtk_grid_new();
gtk_grid_set_column_spacing(GTK_GRID(grid), 2);
for (x = 0; x<amt; x++) {
if ((widgets[x].id != -1) && (widgets[x].position != -1)) {
widget = create_on_off_button(&widgets[x]);
gtk_grid_attach(GTK_GRID(grid), widget, 0, x, 1, 1);
@@ -629,21 +925,29 @@ GtkWidget *create_vbox(Effect *widgets, gint amt, gchar *label)
y = 0;
} else if (widgets[x].label) {
widget = gtk_label_new(widgets[x].label);
gtk_grid_attach(GTK_GRID(grid), widget, 0, x, 1, 1);
y = 0;
} else {
/* Default to 1 */
if (x == 0)
y = 1;
}
container = create_widget_container(widgets[x].group, widgets[x].group_amt, widgets[x].type, widgets[x].position);
container = create_widget_container(widgets[x].group,
widgets[x].group_amt,
widgets[x].type,
widgets[x].position);
gtk_grid_attach(GTK_GRID(grid), container, 1-y, x+y, 1, 1);
}
gtk_box_pack_start(GTK_BOX(vbox), grid, FALSE, FALSE, 2);
gtk_container_add(GTK_CONTAINER(frame), vbox);
return frame;
}
@@ -844,23 +1148,31 @@ static void action_show_about_dialog_cb(GtkAction *action)
"Stephen Rigler <riglersc@gmail.com>",
"Jaco Kroon <jaco@kroon.co.za>",
"Rafael Moreno <laocanfei@yahoo.com>",
"Andrew O. Shadoura <bugzilla@tut.by>",
"Andrew Shadura <bugzilla@tut.by>",
"Andreas Karajannis <aakara13@googlemail.com>",
"Miklos Aubert <miklos.aubert@gmail.com>",
"Jonathan A. Tice <jonandtice@gmail.com>",
"John Hammen <jhammen@gmail.com>",
"Ahmed Toulan <thelinuxer@gmail.com>",
"Tim LaBerge <tlaberge@visi.com>",
"Mauro Carvalho Chehab <maurochehab@gmail.com>",
NULL
};
static const gchar copyright[] = "Copyright \xc2\xa9 2009 Tomasz Moń";
static const gchar * const artists[] = {
"Islam Alwazery <wazery@ubuntu.com>",
NULL
};
static const gchar copyright[] = "Copyright \xc2\xa9 2009-2013 Tomasz Moń";
static const gchar website[] = "http://desowin.org/gdigi/";
static const gchar version[] = "0.3.0";
static const gchar version[] = "0.4.0";
GtkWidget *window = g_object_get_data(G_OBJECT(action), "window");
gtk_show_about_dialog(GTK_WINDOW(window),
"authors", authors,
"artists", artists,
"copyright", copyright,
"website", website,
"license-type", GTK_LICENSE_GPL_3_0,
@@ -891,7 +1203,7 @@ SupportedFileTypes file_types[] = {
static guint n_file_types = G_N_ELEMENTS(file_types);
gchar *
gchar *
get_preset_filename (int prod_id)
{
return file_types[prod_id].name;
@@ -928,7 +1240,7 @@ static void action_open_preset_cb(GtkAction *action)
for (x=0; x<n_file_types; x++) {
GtkFileFilter *current_filter = gtk_file_filter_new();
if (file_types[x].name == NULL) {
g_message("Skipping NULL array entry");
g_warning("Skipping NULL array entry");
continue;
}
@@ -938,7 +1250,6 @@ static void action_open_preset_cb(GtkAction *action)
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), current_filter);
if (x == product_id) {
gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), current_filter);
}
@@ -1008,10 +1319,9 @@ static void action_open_preset_cb(GtkAction *action)
section = get_genetx_section_id(genetx->version,
genetx->type);
bank = 0x04;
index = genetx->channel;
if (i == 0) {
index = genetx->channel;
} else {
if (i != 0) {
if (genetx->channel == GENETX_CHANNEL1) {
index = GENETX_CHANNEL1_CUSTOM;
} else if (genetx->channel == GENETX_CHANNEL2) {
@@ -1061,15 +1371,10 @@ static void action_save_preset_cb(GtkAction *action)
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
NULL);
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
GError *error = NULL;
gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
if (error) {
show_error_message(window, error->message);
g_error_free(error);
error = NULL;
if (filename == NULL) {
show_error_message(window, "No file name");
} else {
gchar real_filename[256];
GList *list = get_current_preset();
@@ -1082,8 +1387,8 @@ static void action_save_preset_cb(GtkAction *action)
write_preset_to_xml(preset, real_filename);
preset_free(preset);
g_free(filename);
}
g_free(filename);
}
gtk_widget_destroy(dialog);
@@ -1190,7 +1495,7 @@ static void add_menubar(GtkWidget *window, GtkWidget *vbox)
gtk_window_add_accel_group(GTK_WINDOW(window), gtk_ui_manager_get_accel_group(ui));
if (!gtk_ui_manager_add_ui_from_string(ui, menu_info, -1, &error)) {
g_message("building menus failed: %s", error->message);
g_warning("building menus failed: %s", error->message);
g_error_free(error);
error = NULL;
}
@@ -1233,18 +1538,23 @@ void gui_create(Device *device)
GtkWidget *widget;
GtkWidget *notebook;
GtkWidget *sw; /* scrolled window to carry preset treeview */
GdkPixbuf *icon;
gint x;
gint i;
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "gdigi");
vbox = gtk_vbox_new(FALSE, 0);
icon = gdk_pixbuf_new_from_inline(-1, gdigi_icon, FALSE, NULL);
gtk_window_set_icon(GTK_WINDOW(window), icon);
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_container_add(GTK_CONTAINER(window), vbox);
add_menubar(window, vbox);
hbox = gtk_hbox_new(FALSE, 0);
hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_container_add(GTK_CONTAINER(vbox), hbox);
sw = gtk_scrolled_window_new(NULL, NULL);
@@ -1268,14 +1578,14 @@ void gui_create(Device *device)
for (i = 0; i<device->n_pages; i++) {
GtkWidget *label = NULL;
vbox = gtk_vbox_new(FALSE, 0);
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 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);
hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 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);
@@ -1287,6 +1597,10 @@ void gui_create(Device *device)
gtk_widget_show_all(window);
g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(gtk_main_quit), NULL);
/* Get the initial values for the linkable parameters and the globals. */
send_message(REQUEST_MODIFIER_LINKABLE_LIST, "\x00\x01", 2);
send_message(REQUEST_GLOBAL_PARAMETERS, "\x00\x01", 2);
}
/**
@@ -1306,7 +1620,7 @@ void gui_free()
*
* Displays dialogbox stating that device is unsupported.
*
* \return TRUE if user selects "compability mode", otherwise FALSE.
* \return TRUE if user selects "compatibility mode", otherwise FALSE.
**/
gboolean unsupported_device_dialog(Device **device)
{
@@ -1329,7 +1643,7 @@ gboolean unsupported_device_dialog(Device **device)
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"
"you can now select compatibility mode with one of the supported devices.\n"
"Please take a look at gdigi's HACKING file.");
gtk_container_add(GTK_CONTAINER(vbox), label);
@@ -1345,7 +1659,8 @@ gboolean unsupported_device_dialog(Device **device)
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);
g_message("Starting %s compatibility mode",
supported_devices[number]->name);
*device = supported_devices[number];
gtk_widget_destroy(dialog);
return TRUE;
@@ -1365,7 +1680,6 @@ gboolean unsupported_device_dialog(Device **device)
**/
gint select_device_dialog (GList *devices)
{
GtkWidget *dialog;
GtkWidget *label;
GtkWidget *combo_box;
@@ -1385,13 +1699,14 @@ gint select_device_dialog (GList *devices)
combo_box = gtk_combo_box_text_new();
device = g_list_first(devices);
do {
while (device != NULL) {
char *name;
snd_card_get_longname(GPOINTER_TO_INT(device->data), &name);
gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo_box), NULL, name);
} while ((device = g_list_next(device)));
device = g_list_next(device);
};
gtk_container_add(GTK_CONTAINER(vbox), combo_box);

3
gui.h
View File

@@ -29,5 +29,8 @@ void gui_create(Device *device);
void gui_free();
gboolean unsupported_device_dialog(Device **device);
gint select_device_dialog (GList *devices);
const gchar* get_message_name(MessageID msgid);
void create_modifier_group (guint pos, guint id);
void modifier_settings_exp_free(EffectSettings *settings);
#endif /* GDIGI_GUI_H */

BIN
images/gdigi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
images/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

10644
knob.h

File diff suppressed because it is too large Load Diff

View File

@@ -69,7 +69,7 @@ static void XMLCALL start(void *data, const char *el, const char **attr) {
if (g_strcmp0(el, "Params") == 0) {
ad->section = SECTION_PARAMS;
if (ad->preset->params != NULL)
g_message("Params aleady exists!");
g_warning("Params aleady exists!");
} else if (g_strcmp0(el, "Param") == 0) {
SettingParam *param = setting_param_new();
ad->preset->params = g_list_prepend(ad->preset->params, param);
@@ -84,7 +84,7 @@ static void XMLCALL start(void *data, const char *el, const char **attr) {
} else if (g_strcmp0(el, "Genetx") == 0) {
ad->section = SECTION_GENETX;
if (ad->preset->genetxs != NULL)
g_message("Genetx already exists!");
g_warning("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);
@@ -160,7 +160,7 @@ static void XMLCALL text_cb(void *data, const char* text, int len)
} else if (g_strcmp0(value, "Version2") == 0) {
genetx->version = GENETX_VERSION_2;
} else {
g_message("Unknown GeNetX version: %s", value);
g_warning("Unknown GeNetX version: %s", value);
}
break;
case PARSER_TYPE_GENETX_TYPE:
@@ -169,7 +169,7 @@ static void XMLCALL text_cb(void *data, const char* text, int len)
} else if (g_strcmp0(value, "Cabinet") == 0) {
genetx->type = GENETX_TYPE_CABINET;
} else {
g_message("Unknown GeNetX type: %s", value);
g_warning("Unknown GeNetX type: %s", value);
}
break;
case PARSER_TYPE_GENETX_CHANNEL:
@@ -178,7 +178,7 @@ static void XMLCALL text_cb(void *data, const char* text, int len)
} else if (g_strcmp0(value, "Channel2") == 0) {
genetx->channel = GENETX_CHANNEL2;
} else {
g_message("Unknown GeNetX channel: %s", value);
g_warning("Unknown GeNetX channel: %s", value);
}
break;
case PARSER_TYPE_GENETX_NAME:
@@ -219,7 +219,7 @@ Preset *create_preset_from_xml_file(gchar *filename, GError **error)
gchar *contents;
if (g_file_get_contents(filename, &contents, NULL, &err) == FALSE) {
g_message("Failed to get %s contents: %s", filename, err->message);
g_warning("Failed to get %s contents: %s", filename, err->message);
*error = g_error_copy(err);
g_error_free(err);
return NULL;
@@ -308,12 +308,16 @@ Preset *create_preset_from_data(GList *list)
modified = (unsigned char)data->str[11+strlen(name)];
if ((bank == PRESETS_EDIT_BUFFER) && (number == 0)) {
g_message("Received current edit buffer");
debug_msg(DEBUG_MSG2HOST,
"RECEIVE_PRESET_START: current edit buffer");
} else {
g_message("Received preset %d from bank %d", number, bank);
debug_msg(DEBUG_MSG2HOST,
"RECEIVE_PRESET_START: preset %d from bank %d",
number, bank);
}
g_message("Modified flag: %d Name: %s", modified, name);
debug_msg(DEBUG_MSG2HOST, "Name: %s, %sodified",
name, modified ? "M" : "Not m");
preset->name = name;
break;
case RECEIVE_PRESET_PARAMETERS:
@@ -326,15 +330,20 @@ Preset *create_preset_from_data(GList *list)
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);
if (debug_flag_is_set(DEBUG_MSG2HOST)) {
GString *ipv = format_ipv(param->id, param->position, param->value);
debug_msg(DEBUG_MSG2HOST, "%3d %s", n, ipv->str);
g_string_free(ipv, TRUE);
}
} while ((x < data->len) && n<total);
g_message("TOTAL %d", total);
debug_msg(DEBUG_MSG2HOST, "TOTAL %d", total);
preset->params = g_list_sort(preset->params, params_cmp);
break;
case RECEIVE_PRESET_END:
break;
default:
g_message("Unhandled message in preset messages list");
g_warning("Unhandled message 0x%x in preset messages list",
get_message_id(data));
}
}

View File

@@ -30,6 +30,7 @@
extern XmlSettings xml_settings[];
extern guint n_xml_settings;
extern EffectValues values_on_off;
/**
* \param id modifier ID
* \param position modifier position
@@ -52,16 +53,18 @@ XmlSettings *get_xml_settings (guint id, guint position)
}
gchar *
map_xml_value(XmlSettings *xml, gint value)
map_xml_value (XmlSettings *xml, EffectValues *values, gint value)
{
switch (xml->values->type) {
switch (values->type) {
case VALUE_TYPE_LABEL:
if ((xml->values == &values_on_off) && (value > 1)) {
g_message("Skipping modifier->label %s\n", xml->label);
if ((values == &values_on_off) && (value > 1)) {
g_warning("Skipping modifier->label %s\n", xml->label);
return NULL;
}
if (value > xml->values->max || value < xml->values->min) {
g_message("%s value %d out of range %0.1f %0.1f", xml->label, value, xml->values->min, xml->values->max);
if (value > values->max || value < values->min) {
g_warning("%s value %d out of range %0.1f %0.1f",
xml->label, value, xml->values->min, xml->values->max);
}
{
XmlLabel *labels = xml->xml_labels;
@@ -83,10 +86,9 @@ map_xml_value(XmlSettings *xml, gint value)
return NULL;
}
gboolean value_is_extra (EffectValues *val, SettingParam *param)
gboolean value_is_extra (EffectValues *val, int value)
{
if ((param->value < val->min) || (param->value > val->max)) {
if ((value < val->min) || (value > val->max)) {
return TRUE;
}
return FALSE;
@@ -111,7 +113,7 @@ write_preset_to_xml(Preset *preset, gchar *filename)
return;
}
/*
/*
* Start the document with the xml default for the version,
* encoding and the default for the standalone declaration.
*/
@@ -130,7 +132,7 @@ write_preset_to_xml(Preset *preset, gchar *filename)
rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "SchemaVersion",
BAD_CAST "1.2");
rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "xmlns",
BAD_CAST "http://www.digitech.com/xml/preset");
@@ -142,9 +144,9 @@ write_preset_to_xml(Preset *preset, gchar *filename)
while (iter_params) {
XmlSettings *xml;
SettingParam *param = (SettingParam *) iter_params->data;
if (param->id == last_id && param->position == last_position) {
g_message("Skipping duplicate parameter id %d position %d",
g_warning("Skipping duplicate parameter id %d position %d",
last_id, last_position);
iter_params = iter_params->next;
continue;
@@ -177,7 +179,7 @@ write_preset_to_xml(Preset *preset, gchar *filename)
BAD_CAST xml->label);
values = xml->values;
type = values->type;
while ((type & VALUE_TYPE_EXTRA) && value_is_extra(values, param)) {
while ((type & VALUE_TYPE_EXTRA) && value_is_extra(values, param->value)) {
values = values->extra;
type = values->type;
}
@@ -206,10 +208,11 @@ write_preset_to_xml(Preset *preset, gchar *filename)
switch (type) {
case VALUE_TYPE_LABEL:
{
char *textp = map_xml_value(xml, param->value);
char *textp = map_xml_value(xml, values, param->value);
if (!textp) {
g_message("Unable to map %s value %d for id %d position %d",
xml->label, param->value, param->id, param->position);
g_warning("Unable to map %s value %d for id %d position %d",
xml->label, param->value, param->id,
param->position);
textp = "";
}
rc = xmlTextWriterWriteElement(writer, BAD_CAST "Text",
@@ -223,7 +226,7 @@ write_preset_to_xml(Preset *preset, gchar *filename)
double value = (param->value + offset) * step;
rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "Text",
"%0.2f%s", value, suffix);
} else {
} else {
gint value = (param->value + offset) * step;
rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "Text",
"%d%s", value, suffix);
@@ -237,20 +240,16 @@ write_preset_to_xml(Preset *preset, gchar *filename)
break;
default:
g_message("Unhandled value type %d", type);
g_warning("Unhandled value type %d", type);
break;
}
}
rc = xmlTextWriterEndElement(writer);
iter_params = iter_params->next;
}
/* Here we could close the elements ORDER and EXAMPLE using the
* function xmlTextWriterEndElement, but since we do not want to
* write any other elements, we simply call xmlTextWriterEndDocument,
* which will do all the work. */
rc = xmlTextWriterEndDocument(writer);
if (rc < 0) {
printf("testXmlwriterFilename: Error at xmlTextWriterEndDocument\n");