Patches from Jeff Snyder.
git-svn-id: svn://svn.code.sf.net/p/jack-keyboard/code/trunk@23 1fa2bf75-7d80-4145-9e94-f9b4e25a1cb2
This commit is contained in:
parent
b8c0445d75
commit
2367dcbebf
4
AUTHORS
4
AUTHORS
@ -1,2 +1,4 @@
|
||||
Edward Tomasz Napierała <trasz@FreeBSD.org>
|
||||
|
||||
Hans Petter Selasky <hselasky@FreeBSD.org>
|
||||
Jeff Snyder <jeff@caffeinated.me.uk>
|
||||
Dan Muresan <danmbox@gmail.com>
|
||||
|
@ -28,7 +28,7 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/")
|
||||
set(VERSION "2.6")
|
||||
set(VERSION "2.7.1")
|
||||
|
||||
set(JackEnable ON CACHE BOOL "Enable support for Jack")
|
||||
set(LashEnable ON CACHE BOOL "Enable support for Lash")
|
||||
|
2
Makefile
2
Makefile
@ -1,4 +1,4 @@
|
||||
VERSION?=2.6
|
||||
VERSION?=2.7.1
|
||||
|
||||
help:
|
||||
@echo "Targets: configure all clean install package"
|
||||
|
23
NEWS
23
NEWS
@ -1,3 +1,26 @@
|
||||
User-visible changes between 2.6 and 2.7.1 include:
|
||||
|
||||
- fix a warning regarding the redefinition of NNOTES
|
||||
|
||||
- raise NNOTES from 127 to 128 (only notes 0..125 were being shown
|
||||
because 127 was < NNOTES and 126 is black)
|
||||
|
||||
- only show the keys that exist on a real piano by default, and add a
|
||||
"-f" ('full midi keyboard') command line option to show all midi
|
||||
notes.
|
||||
|
||||
- make the dimensions slightly closer to a real piano by:
|
||||
> making the black key hight two third of the white key height
|
||||
> making the black key positions vary based on their position in
|
||||
the octave
|
||||
|
||||
- adding a QWERTY_REV layout that has the lower keys on the upper row
|
||||
of the keyboard
|
||||
|
||||
- adding QWERTY_UK and QWERTY_UK_REV layouts that extend the QWERTY
|
||||
and QWERTY_REV layouts with the punctuation keys available on those
|
||||
rows
|
||||
|
||||
User-visible changes between 2.5 and 2.6 include:
|
||||
|
||||
- Bugfix: A key volume of zero means key off.
|
||||
|
@ -61,8 +61,6 @@
|
||||
#include <gdk/gdkx.h>
|
||||
#endif
|
||||
|
||||
#define NNOTES 127
|
||||
|
||||
#define VELOCITY_MAX 127
|
||||
#define VELOCITY_HIGH 100
|
||||
#define VELOCITY_NORMAL 64
|
||||
@ -1699,11 +1697,11 @@ show_version(void)
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "usage: jack-keyboard [-CGKTVktur] [ -a <input port>] [-c <channel>] [-b <bank> ] [-p <program>] [-l <layout>]\n");
|
||||
fprintf(stderr, "usage: jack-keyboard [-CGKTVkturf] [ -a <input port>] [-c <channel>] [-b <bank> ] [-p <program>] [-l <layout>]\n");
|
||||
fprintf(stderr, " where <channel> is MIDI channel to use for output, from 1 to 16,\n");
|
||||
fprintf(stderr, " <bank> is MIDI bank to use, from 0 to 16383,\n");
|
||||
fprintf(stderr, " <program> is MIDI program to use, from 0 to 127,\n");
|
||||
fprintf(stderr, " and <layout> is QWERTY, QWERTZ, AZERTY or DVORAK.\n");
|
||||
fprintf(stderr, " and <layout> is QWERTY, QWERTY_REV, QWERTY_UK, QWERTY_UK_REV, QWERTZ, AZERTY or DVORAK.\n");
|
||||
fprintf(stderr, "See manual page for details.\n");
|
||||
|
||||
exit(EX_USAGE);
|
||||
@ -1712,7 +1710,7 @@ usage(void)
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int ch, enable_keyboard_cue = 0, initial_channel = 1, initial_bank = 0, initial_program = 0;
|
||||
int ch, enable_keyboard_cue = 0, initial_channel = 1, initial_bank = 0, initial_program = 0, full_midi_keyboard = 0;
|
||||
char *keyboard_layout = NULL, *autoconnect_port_name = NULL;
|
||||
|
||||
#ifdef HAVE_LASH
|
||||
@ -1729,7 +1727,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:")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "CGKTVa:nktur:c:b:p:l:f")) != -1) {
|
||||
switch (ch) {
|
||||
case 'C':
|
||||
enable_keyboard_cue = 1;
|
||||
@ -1826,6 +1824,10 @@ main(int argc, char *argv[])
|
||||
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
full_midi_keyboard = 1;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
@ -1837,11 +1839,14 @@ main(int argc, char *argv[])
|
||||
|
||||
init_gtk_2();
|
||||
|
||||
if (full_midi_keyboard)
|
||||
piano_keyboard_enable_all_midi_notes(keyboard);
|
||||
|
||||
if (keyboard_layout != NULL) {
|
||||
int ret = piano_keyboard_set_keyboard_layout(keyboard, keyboard_layout);
|
||||
|
||||
if (ret) {
|
||||
g_critical("Invalid layout, proper choices are QWERTY, QWERTZ, AZERTY and DVORAK.");
|
||||
g_critical("Invalid layout, proper choices are QWERTY, QWERTY_REV, QWERTY_UK, QWERTY_UK_REV, QWERTZ, AZERTY and DVORAK.");
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
}
|
||||
|
@ -77,6 +77,10 @@ draw_keyboard_cue(PianoKeyboard *pk)
|
||||
static void
|
||||
draw_note(PianoKeyboard *pk, int note)
|
||||
{
|
||||
if (note < pk->min_note)
|
||||
return;
|
||||
if (note > pk->max_note)
|
||||
return;
|
||||
int is_white, x, w, h;
|
||||
|
||||
GdkColor black = {0, 0, 0, 0};
|
||||
@ -256,7 +260,7 @@ bind_keys_qwerty(PianoKeyboard *pk)
|
||||
bind_key(pk, "m", 23);
|
||||
|
||||
/* Upper keyboard row, first octave - "qwertyu". */
|
||||
bind_key(pk, "q", 24);
|
||||
bind_key(pk, "q", 24); /* C1 */
|
||||
bind_key(pk, "2", 25);
|
||||
bind_key(pk, "w", 26);
|
||||
bind_key(pk, "3", 27);
|
||||
@ -270,13 +274,93 @@ bind_keys_qwerty(PianoKeyboard *pk)
|
||||
bind_key(pk, "u", 35);
|
||||
|
||||
/* Upper keyboard row, the rest - "iop". */
|
||||
bind_key(pk, "i", 36);
|
||||
bind_key(pk, "i", 36); /* C2 */
|
||||
bind_key(pk, "9", 37);
|
||||
bind_key(pk, "o", 38);
|
||||
bind_key(pk, "0", 39);
|
||||
bind_key(pk, "p", 40);
|
||||
}
|
||||
|
||||
static void
|
||||
bind_keys_qwerty_uk(PianoKeyboard *pk)
|
||||
{
|
||||
bind_keys_qwerty(pk);
|
||||
|
||||
/* Lower keyboard row - "zxcvbnm". */
|
||||
bind_key(pk, "backslash", 11); /* B0 */
|
||||
/* ... */
|
||||
bind_key(pk, "comma", 24); /* C1 */
|
||||
bind_key(pk, "l", 25);
|
||||
bind_key(pk, "period", 26);
|
||||
bind_key(pk, "semicolon", 27);
|
||||
bind_key(pk, "slash", 28);
|
||||
|
||||
/* Upper keyboard row, the rest - "iop". */
|
||||
bind_key(pk, "bracketleft", 41); /* F6 */
|
||||
bind_key(pk, "equal", 42);
|
||||
bind_key(pk, "bracketright", 43);
|
||||
}
|
||||
static void
|
||||
bind_keys_qwerty_rev(PianoKeyboard *pk)
|
||||
{
|
||||
clear_notes(pk);
|
||||
|
||||
/* Lower keyboard row - "zxcvbnm". */
|
||||
bind_key(pk, "z", 24); /* C1 */
|
||||
bind_key(pk, "s", 25);
|
||||
bind_key(pk, "x", 26);
|
||||
bind_key(pk, "d", 27);
|
||||
bind_key(pk, "c", 28);
|
||||
bind_key(pk, "v", 29);
|
||||
bind_key(pk, "g", 30);
|
||||
bind_key(pk, "b", 31);
|
||||
bind_key(pk, "h", 32);
|
||||
bind_key(pk, "n", 33);
|
||||
bind_key(pk, "j", 34);
|
||||
bind_key(pk, "m", 35);
|
||||
|
||||
/* Upper keyboard row, first octave - "qwertyu". */
|
||||
bind_key(pk, "q", 12); /* C0 */
|
||||
bind_key(pk, "2", 13);
|
||||
bind_key(pk, "w", 14);
|
||||
bind_key(pk, "3", 15);
|
||||
bind_key(pk, "e", 16);
|
||||
bind_key(pk, "r", 17);
|
||||
bind_key(pk, "5", 18);
|
||||
bind_key(pk, "t", 19);
|
||||
bind_key(pk, "6", 20);
|
||||
bind_key(pk, "y", 21);
|
||||
bind_key(pk, "7", 22);
|
||||
bind_key(pk, "u", 23);
|
||||
|
||||
/* Upper keyboard row, the rest - "iop". */
|
||||
bind_key(pk, "i", 24); /* C1 */
|
||||
bind_key(pk, "9", 25);
|
||||
bind_key(pk, "o", 26);
|
||||
bind_key(pk, "0", 27);
|
||||
bind_key(pk, "p", 28);
|
||||
}
|
||||
|
||||
static void
|
||||
bind_keys_qwerty_uk_rev(PianoKeyboard *pk)
|
||||
{
|
||||
bind_keys_qwerty_rev(pk);
|
||||
|
||||
/* Lower keyboard row - "zxcvbnm". */
|
||||
bind_key(pk, "backslash", 23); /* B-1 */
|
||||
/* ... */
|
||||
bind_key(pk, "comma", 36); /* C2 */
|
||||
bind_key(pk, "l", 37);
|
||||
bind_key(pk, "period", 38);
|
||||
bind_key(pk, "semicolon", 39);
|
||||
bind_key(pk, "slash", 40);
|
||||
|
||||
/* Upper keyboard row, the rest - "iop". */
|
||||
bind_key(pk, "bracketleft", 29);
|
||||
bind_key(pk, "equal", 30);
|
||||
bind_key(pk, "bracketright", 31);
|
||||
}
|
||||
|
||||
static void
|
||||
bind_keys_qwertz(PianoKeyboard *pk)
|
||||
{
|
||||
@ -431,8 +515,8 @@ get_note_for_xy(PianoKeyboard *pk, int x, int y)
|
||||
|
||||
height = GTK_WIDGET(pk)->allocation.height;
|
||||
|
||||
if (y <= height / 2) {
|
||||
for (note = 0; note < NNOTES - 1; note++) {
|
||||
if (y <= ((height * 2) / 3)) { /* might be a black key */
|
||||
for (note = 0; note <= pk->max_note; ++note) {
|
||||
if (pk->notes[note].white)
|
||||
continue;
|
||||
|
||||
@ -441,7 +525,7 @@ get_note_for_xy(PianoKeyboard *pk, int x, int y)
|
||||
}
|
||||
}
|
||||
|
||||
for (note = 0; note < NNOTES - 1; note++) {
|
||||
for (note = 0; note <= pk->max_note; ++note) {
|
||||
if (!pk->notes[note].white)
|
||||
continue;
|
||||
|
||||
@ -534,13 +618,48 @@ piano_keyboard_size_request(GtkWidget *widget, GtkRequisition *requisition)
|
||||
requisition->height = PIANO_KEYBOARD_DEFAULT_HEIGHT;
|
||||
}
|
||||
|
||||
static int is_black(int key)
|
||||
{
|
||||
int note_in_octave = key % 12;
|
||||
if( note_in_octave == 1 || note_in_octave == 3 ||
|
||||
note_in_octave == 6 || note_in_octave == 8 || note_in_octave == 10)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static double black_key_left_shift(int key)
|
||||
{
|
||||
int note_in_octave = key % 12;
|
||||
switch (note_in_octave)
|
||||
{
|
||||
case 1:
|
||||
return 2.0/3.0;
|
||||
case 3:
|
||||
return 1.0/3.0;
|
||||
case 6:
|
||||
return 2.0/3.0;
|
||||
case 8:
|
||||
return 0.5;
|
||||
case 10:
|
||||
return 1.0/3.0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
recompute_dimensions(PianoKeyboard *pk)
|
||||
{
|
||||
int number_of_white_keys, key_width, black_key_width, useful_width, note,
|
||||
white_key = 0, note_in_octave, width, height;
|
||||
int number_of_white_keys = 0, skipped_white_keys = 0, key_width, black_key_width, useful_width, note,
|
||||
white_key, width, height;
|
||||
|
||||
number_of_white_keys = (NNOTES - 1) * (7.0 / 12.0);
|
||||
for (note = pk->min_note; note <= pk->max_note; ++note)
|
||||
if (!is_black(note))
|
||||
++number_of_white_keys;
|
||||
for (note = 0; note < pk->min_note; ++note)
|
||||
if (!is_black(note))
|
||||
++skipped_white_keys;
|
||||
|
||||
width = GTK_WIDGET(pk)->allocation.width;
|
||||
height = GTK_WIDGET(pk)->allocation.height;
|
||||
@ -550,18 +669,15 @@ recompute_dimensions(PianoKeyboard *pk)
|
||||
useful_width = number_of_white_keys * key_width;
|
||||
pk->widget_margin = (width - useful_width) / 2;
|
||||
|
||||
for (note = 0, white_key = 0; note < NNOTES - 2; note++) {
|
||||
note_in_octave = note % 12;
|
||||
|
||||
if (note_in_octave == 1 || note_in_octave == 3 || note_in_octave == 6 ||
|
||||
note_in_octave == 8 || note_in_octave == 10) {
|
||||
|
||||
for (note = 0, white_key = -skipped_white_keys; note < NNOTES; note++) {
|
||||
if (is_black(note)) {
|
||||
/* This note is black key. */
|
||||
pk->notes[note].x = pk->widget_margin + white_key * key_width - black_key_width / 2;
|
||||
pk->notes[note].x = pk->widget_margin +
|
||||
(white_key * key_width) -
|
||||
(black_key_width * black_key_left_shift(note));
|
||||
pk->notes[note].w = black_key_width;
|
||||
pk->notes[note].h = height / 2;
|
||||
pk->notes[note].h = (height * 2) / 3;
|
||||
pk->notes[note].white = 0;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -663,6 +779,8 @@ piano_keyboard_new(void)
|
||||
pk->note_being_pressed_using_mouse = -1;
|
||||
memset((void *)pk->notes, 0, sizeof(struct Note) * NNOTES);
|
||||
pk->key_bindings = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
pk->min_note = PIANO_MIN_NOTE;
|
||||
pk->max_note = PIANO_MAX_NOTE;
|
||||
bind_keys_qwerty(pk);
|
||||
|
||||
return (widget);
|
||||
@ -727,6 +845,15 @@ piano_keyboard_set_keyboard_layout(PianoKeyboard *pk, const char *layout)
|
||||
if (!strcasecmp(layout, "QWERTY")) {
|
||||
bind_keys_qwerty(pk);
|
||||
|
||||
} else if (!strcasecmp(layout, "QWERTY_REV")) {
|
||||
bind_keys_qwerty_rev(pk);
|
||||
|
||||
} else if (!strcasecmp(layout, "QWERTY_UK")) {
|
||||
bind_keys_qwerty_uk(pk);
|
||||
|
||||
} else if (!strcasecmp(layout, "QWERTY_UK_REV")) {
|
||||
bind_keys_qwerty_uk_rev(pk);
|
||||
|
||||
} else if (!strcasecmp(layout, "QWERTZ")) {
|
||||
bind_keys_qwertz(pk);
|
||||
|
||||
@ -744,3 +871,11 @@ piano_keyboard_set_keyboard_layout(PianoKeyboard *pk, const char *layout)
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
piano_keyboard_enable_all_midi_notes(PianoKeyboard* pk)
|
||||
{
|
||||
pk->min_note = 0;
|
||||
pk->max_note = NNOTES-1;
|
||||
recompute_dimensions(pk);
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,17 @@ G_BEGIN_DECLS
|
||||
typedef struct _PianoKeyboard PianoKeyboard;
|
||||
typedef struct _PianoKeyboardClass PianoKeyboardClass;
|
||||
|
||||
#define NNOTES 127
|
||||
/* A note about note numbers:
|
||||
|
||||
0 = C-1 (midi minmum)
|
||||
21 = A0 (piano minimum)
|
||||
60 = C4 (middle C)
|
||||
108 = C7 (piano maximum)
|
||||
127 = G9 (midi maximum)
|
||||
*/
|
||||
#define NNOTES 128
|
||||
#define PIANO_MIN_NOTE 21
|
||||
#define PIANO_MAX_NOTE 108
|
||||
|
||||
#define OCTAVE_MIN -1
|
||||
#define OCTAVE_MAX 7
|
||||
@ -66,6 +76,8 @@ struct _PianoKeyboard
|
||||
int octave;
|
||||
int widget_margin;
|
||||
int note_being_pressed_using_mouse;
|
||||
int min_note;
|
||||
int max_note;
|
||||
volatile struct Note notes[NNOTES];
|
||||
/* Table used to translate from PC keyboard character to MIDI note number. */
|
||||
GHashTable *key_bindings;
|
||||
@ -85,6 +97,7 @@ void piano_keyboard_set_note_off (PianoKeyboard *pk, int note);
|
||||
void piano_keyboard_set_keyboard_cue (PianoKeyboard *pk, int enabled);
|
||||
void piano_keyboard_set_octave (PianoKeyboard *pk, int octave);
|
||||
gboolean piano_keyboard_set_keyboard_layout (PianoKeyboard *pk, const char *layout);
|
||||
void piano_keyboard_enable_all_midi_notes(PianoKeyboard* pk);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user