diff --git a/NEWS b/NEWS
index a39eb7a..10eac0f 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,6 @@
+User-visible changes between 2.8.0 and 2.8.1 include:
+ - Add bank MSB/LSB support
+
User-visible changes between 2.7.2 and 2.8.0 include:
- Drop CMake and now use autotools
diff --git a/src/jack-keyboard.c b/src/jack-keyboard.c
index f973222..a0876d1 100644
--- a/src/jack-keyboard.c
+++ b/src/jack-keyboard.c
@@ -97,6 +97,7 @@ int velocity_high = VELOCITY_HIGH;
int velocity_normal = VELOCITY_NORMAL;
int velocity_low = VELOCITY_LOW;
int *current_velocity = &velocity_normal;
+short alt_l = False;
int octave = 4;
double rate_limit = 0.0;
jack_client_t *jack_client = NULL;
@@ -115,8 +116,8 @@ lash_client_t *lash_client;
#define MIDI_ALL_SOUND_OFF 120
#define MIDI_ALL_MIDI_CONTROLLERS_OFF 121
#define MIDI_ALL_NOTES_OFF 123
-#define MIDI_BANK_SELECT_MSB 0
-#define MIDI_BANK_SELECT_LSB 32
+#define MIDI_BANK_MSB_SELECT 0
+#define MIDI_BANK_LSB_SELECT 32
#define MIDI_MOD_CC 1
#define BANK_MIN 0
@@ -176,7 +177,7 @@ const char *rc_style = "style \"default\"\n"
"widget_class\"*GtkButton*\" style : highest \"button\"\n"
"widget_class\"*GtkToggle*\" style : highest \"button\"\n";
-GtkWidget *window, *sustain_button, *channel_spin, *bank_spin, *program_spin, *connected_to_combo,
+GtkWidget *window, *sustain_button, *channel_spin, *bank_msb_spin, *bank_lsb_spin, *program_spin, *connected_to_combo,
*velocity_scale, *grab_keyboard_checkbutton, *octave_spin, *mod_scale, *pitch_scale, *panic_button;
PianoKeyboard *keyboard;
GtkListStore *connected_to_store;
@@ -205,7 +206,8 @@ jack_ringbuffer_t *ringbuffer;
int program = 0;
/* Number of currently selected bank. */
-int bank = 0;
+int bank_msb = 0;
+int bank_lsb = 0;
/* Number of currently selected channel (0..15). */
int channel = 0;
@@ -598,8 +600,8 @@ draw_window_title(void)
if (enable_window_title && jack_client != NULL) {
connected_ports = jack_port_get_connections(output_port);
- off += snprintf(title, sizeof(title) - off, "%s: channel %d, bank %d, program %d",
- jack_get_client_name(jack_client), channel + 1, bank, program);
+ off += snprintf(title, sizeof(title) - off, "%s: channel %d, bank %d/%d, program %d",
+ jack_get_client_name(jack_client), channel + 1, bank_msb, bank_lsb, program);
if (!program_change_was_sent)
off += snprintf(title + off, sizeof(title) - off, " (bank/program change not sent)");
@@ -653,8 +655,10 @@ send_program_change(void)
if (jack_port_connected(output_port) == 0)
return;
- queue_new_message(MIDI_CONTROLLER, MIDI_BANK_SELECT_LSB, bank % 128);
- queue_new_message(MIDI_CONTROLLER, MIDI_BANK_SELECT_MSB, bank / 128);
+// queue_new_message(MIDI_CONTROLLER, MIDI_BANK_SELECT_MSB, bank % 128);
+// queue_new_message(MIDI_CONTROLLER, MIDI_BANK_SELECT_LSB, bank / 128);
+ queue_new_message(MIDI_CONTROLLER, MIDI_BANK_MSB_SELECT, bank_msb);
+ queue_new_message(MIDI_CONTROLLER, MIDI_BANK_LSB_SELECT, bank_lsb);
queue_new_message(MIDI_PROGRAM_CHANGE, program, -1);
program_change_was_sent = 1;
@@ -887,11 +891,18 @@ load_config_from_lash(void)
gtk_spin_button_set_value(GTK_SPIN_BUTTON(channel_spin), value);
}
- } else if (!strcmp(key, "bank")) {
+ } else if (!strcmp(key, "bank_msb")) {
if (value < BANK_MIN || value > BANK_MAX) {
- g_warning("Bad value '%d' for 'bank' property received from LASH.", value);
+ g_warning("Bad value '%d' for 'bank_msb' property received from LASH.", value);
} else {
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(bank_spin), value);
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(bank_msb_spin), value);
+ }
+
+ } else if (!strcmp(key, "bank_lsb")) {
+ if (value < BANK_MIN || value > BANK_MAX) {
+ g_warning("Bad value '%d' for 'bank_lsb' property received from LASH.", value);
+ } else {
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(bank_lsb_spin), value);
}
} else if (!strcmp(key, "program")) {
@@ -961,7 +972,8 @@ void
save_config_into_lash(void)
{
save_config_int("channel", channel + 1);
- save_config_int("bank", bank);
+ save_config_int("bank_msb", bank_msb);
+ save_config_int("bank_lsb", bank_lsb);
save_config_int("program", program);
save_config_int("keyboard_grabbed", keyboard_grabbed);
save_config_int("octave", octave);
@@ -1043,9 +1055,18 @@ channel_event_handler(GtkSpinButton *spinbutton, gpointer notused)
}
void
-bank_event_handler(GtkSpinButton *spinbutton, gpointer notused)
+bank_msb_event_handler(GtkSpinButton *spinbutton, gpointer notused)
{
- bank = gtk_spin_button_get_value(spinbutton);
+ bank_msb = gtk_spin_button_get_value(spinbutton);
+
+ send_program_change();
+ draw_window_title();
+}
+
+void
+bank_lsb_event_handler(GtkSpinButton *spinbutton, gpointer notused)
+{
+ bank_lsb = gtk_spin_button_get_value(spinbutton);
send_program_change();
draw_window_title();
@@ -1401,6 +1422,7 @@ keyboard_event_handler(GtkWidget *widget, GdkEventKey *event, gpointer notused)
{
int tmp;
gboolean retval = FALSE;
+ GtkWidget *tmp_widget;
/* Pass signal to piano_keyboard widget. Is there a better way to do this? */
if (event->type == GDK_KEY_PRESS)
@@ -1464,17 +1486,23 @@ keyboard_event_handler(GtkWidget *widget, GdkEventKey *event, gpointer notused)
}
/*
- * PgUp key increases bank number, PgDown decreases it.
+ * PgUp key increases bank MSB number, PgDown decreases it.
+ * PgUp + Alt left key increases bank LSB number, PgDown + Alt left decreases it.
*/
if (event->keyval == GDK_Page_Up) {
if (event->type == GDK_KEY_PRESS) {
+ if( alt_l == False)
+ tmp_widget = GTK_SPIN_BUTTON(bank_msb_spin);
+ else
+ tmp_widget = GTK_SPIN_BUTTON(bank_lsb_spin);
+
tmp = get_entered_number();
if (tmp < 0)
- tmp = gtk_spin_button_get_value(GTK_SPIN_BUTTON(bank_spin)) + 1;
+ tmp = gtk_spin_button_get_value(tmp_widget) + 1;
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(bank_spin), clip(tmp, BANK_MIN, BANK_MAX));
+ gtk_spin_button_set_value(tmp_widget, clip(tmp, BANK_MIN, BANK_MAX));
}
return (TRUE);
@@ -1483,12 +1511,17 @@ keyboard_event_handler(GtkWidget *widget, GdkEventKey *event, gpointer notused)
if (event->keyval == GDK_Page_Down) {
if (event->type == GDK_KEY_PRESS) {
+ if( alt_l == False)
+ tmp_widget = GTK_SPIN_BUTTON(bank_msb_spin);
+ else
+ tmp_widget = GTK_SPIN_BUTTON(bank_lsb_spin);
+
tmp = get_entered_number();
if (tmp < 0)
- tmp = gtk_spin_button_get_value(GTK_SPIN_BUTTON(bank_spin)) - 1;
+ tmp = gtk_spin_button_get_value(tmp_widget) - 1;
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(bank_spin), clip(tmp, BANK_MIN, BANK_MAX));
+ gtk_spin_button_set_value(tmp_widget, clip(tmp, BANK_MIN, BANK_MAX));
}
return (TRUE);
@@ -1592,6 +1625,18 @@ keyboard_event_handler(GtkWidget *widget, GdkEventKey *event, gpointer notused)
return (TRUE);
}
+ /*
+ * Alt Left is used as modifier key
+ */
+ if (event->keyval == GDK_Alt_L ) {
+ if (event->type == GDK_KEY_PRESS)
+ alt_l = True;
+ else
+ alt_l = False;
+
+ return (TRUE);
+ }
+
return (FALSE);
}
@@ -1678,20 +1723,28 @@ init_gtk_2(void)
gtk_table_attach(numtable, octave_spin, 1, 2, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
g_signal_connect(G_OBJECT(octave_spin), "value-changed", G_CALLBACK(octave_event_handler), NULL);
- /* Bank label and spin. */
- label = gtk_label_new("Bank");
+ /* Bank MSB label and spin. */
+ label = gtk_label_new("Bank MSB");
gtk_table_attach(numtable, label, 2, 3, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
- bank_spin = gtk_spin_button_new_with_range(0, BANK_MAX, 1);
- GTK_WIDGET_UNSET_FLAGS(bank_spin, GTK_CAN_FOCUS);
- gtk_table_attach(numtable, bank_spin, 2, 3, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
- g_signal_connect(G_OBJECT(bank_spin), "value-changed", G_CALLBACK(bank_event_handler), NULL);
+ bank_msb_spin = gtk_spin_button_new_with_range(0, BANK_MAX, 1);
+ GTK_WIDGET_UNSET_FLAGS(bank_msb_spin, GTK_CAN_FOCUS);
+ gtk_table_attach(numtable, bank_msb_spin, 2, 3, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
+ g_signal_connect(G_OBJECT(bank_msb_spin), "value-changed", G_CALLBACK(bank_msb_event_handler), NULL);
+
+ /* Bank LSB label and spin. */
+ label = gtk_label_new("Bank LSB");
+ gtk_table_attach(numtable, label, 3, 4, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
+ bank_lsb_spin = gtk_spin_button_new_with_range(0, BANK_MAX, 1);
+ GTK_WIDGET_UNSET_FLAGS(bank_lsb_spin, GTK_CAN_FOCUS);
+ gtk_table_attach(numtable, bank_lsb_spin, 3, 4, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
+ g_signal_connect(G_OBJECT(bank_lsb_spin), "value-changed", G_CALLBACK(bank_lsb_event_handler), NULL);
/* Program label and spin. */
label = gtk_label_new("Prog");
- gtk_table_attach(numtable, label, 3, 4, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
+ gtk_table_attach(numtable, label, 4, 5, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
program_spin = gtk_spin_button_new_with_range(0, PROGRAM_MAX, 1);
GTK_WIDGET_UNSET_FLAGS(program_spin, GTK_CAN_FOCUS);
- gtk_table_attach(numtable, program_spin, 3, 4, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
+ gtk_table_attach(numtable, program_spin, 4, 5, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
g_signal_connect(G_OBJECT(program_spin), "value-changed", G_CALLBACK(program_event_handler), NULL);
@@ -1705,7 +1758,7 @@ init_gtk_2(void)
/* "Connected to" label and combo box. */
GtkCellRenderer *renderer;
label = gtk_label_new("Connect");
- gtk_table_attach(numtable, label, 4, 5, 0, 1, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
+ gtk_table_attach(numtable, label, 5, 6, 0, 1, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
connected_to_store = gtk_list_store_new(1, G_TYPE_STRING);
connected_to_combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(connected_to_store));
@@ -1716,18 +1769,18 @@ init_gtk_2(void)
GTK_WIDGET_UNSET_FLAGS(connected_to_combo, GTK_CAN_FOCUS);
gtk_combo_box_set_focus_on_click(GTK_COMBO_BOX(connected_to_combo), FALSE);
- gtk_table_attach(numtable, connected_to_combo, 4, 5, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
+ gtk_table_attach(numtable, connected_to_combo, 5, 6, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
gtk_widget_set_size_request(GTK_WIDGET(connected_to_combo), 160, -1);
g_signal_connect(G_OBJECT(connected_to_combo), "changed", G_CALLBACK(connected_to_event_handler), NULL);
/* "Grab keyboard" label and checkbutton. */
label = gtk_label_new("Grab Keyboard");
- gtk_table_attach(numtable, label, 5, 6, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
+ gtk_table_attach(numtable, label, 6, 7, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
grab_keyboard_checkbutton = gtk_check_button_new();
GTK_WIDGET_UNSET_FLAGS(grab_keyboard_checkbutton, GTK_CAN_FOCUS);
g_signal_connect(G_OBJECT(grab_keyboard_checkbutton), "toggled", G_CALLBACK(grab_keyboard_handler), NULL);
- gtk_table_attach(numtable, grab_keyboard_checkbutton, 5, 6, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
+ gtk_table_attach(numtable, grab_keyboard_checkbutton, 6, 7, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
/* Sustain. It's a toggle button, not an ordinary one, because we want gtk_whatever_set_active() to work.*/
@@ -1830,9 +1883,9 @@ show_version(void)
void
usage(void)
{
- fprintf(stderr, "usage: jack-keyboard [-CGKTVkturf] [ -a ] [-c ] [-b ] [-p ] [-l ]\n");
+ fprintf(stderr, "usage: jack-keyboard [-CGKTVkturf] [ -a ] [-c ] [-b ] [-d ] [-p ] [-l ]\n");
fprintf(stderr, " where is MIDI channel to use for output, from 1 to 16,\n");
- fprintf(stderr, " is MIDI bank to use, from 0 to 16383,\n");
+ fprintf(stderr, " is MIDI bank to use, from 0 to 127,\n");
fprintf(stderr, " is MIDI program to use, from 0 to 127,\n");
fprintf(stderr, " and is QWERTY.\n");
fprintf(stderr, "See manual page for details.\n");
@@ -1843,7 +1896,7 @@ usage(void)
int
main(int argc, char *argv[])
{
- int ch, enable_keyboard_cue = 0, initial_channel = 1, initial_bank = 0, initial_program = 0, full_midi_keyboard = 0;
+ int ch, enable_keyboard_cue = 0, initial_channel = 1, initial_bank_msb = 0, initial_bank_lsb = 0, initial_program = 0, full_midi_keyboard = 0;
char *keyboard_layout = NULL, *autoconnect_port_name = NULL;
#ifdef HAVE_LASH
@@ -1860,7 +1913,7 @@ main(int argc, char *argv[])
g_log_set_default_handler(log_handler, NULL);
- while ((ch = getopt(argc, argv, "CGKTVa:nktur:c:b:p:l:f")) != -1) {
+ while ((ch = getopt(argc, argv, "CGKTVa:nktur:c:b:d:p:l:f")) != -1) {
switch (ch) {
case 'C':
enable_keyboard_cue = 1;
@@ -1920,12 +1973,26 @@ main(int argc, char *argv[])
break;
case 'b':
- initial_bank = atoi(optarg);
+ initial_bank_msb = atoi(optarg);
send_program_change_once = 1;
- if (initial_bank < BANK_MIN || initial_bank > BANK_MAX) {
- g_critical("Invalid MIDI bank number specified on the command line; "
+ if (initial_bank_msb < BANK_MIN || initial_bank_msb > BANK_MAX) {
+ g_critical("Invalid MIDI MSB bank number specified on the command line; "
+ "valid values are %d-%d.", BANK_MIN, BANK_MAX);
+
+ exit(EX_USAGE);
+ }
+
+ break;
+
+ case 'd':
+ initial_bank_lsb = atoi(optarg);
+
+ send_program_change_once = 1;
+
+ if (initial_bank_lsb < BANK_MIN || initial_bank_lsb > BANK_MAX) {
+ g_critical("Invalid MIDI LSB bank number specified on the command line; "
"valid values are %d-%d.", BANK_MIN, BANK_MAX);
exit(EX_USAGE);
@@ -1999,7 +2066,8 @@ main(int argc, char *argv[])
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(grab_keyboard_checkbutton), grab_keyboard_at_startup);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(channel_spin), initial_channel);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(bank_spin), initial_bank);
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(bank_msb_spin), initial_bank_msb);
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(bank_lsb_spin), initial_bank_lsb);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(program_spin), initial_program);
piano_keyboard_set_keyboard_cue(keyboard, enable_keyboard_cue);