libxputty 0.1
Loading...
Searching...
No Matches
xkeyboard.c
Go to the documentation of this file.
1/*
2 * 0BSD
3 *
4 * BSD Zero Clause License
5 *
6 * Copyright (c) 2019 Hermann Meyer
7 *
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted.
10
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 *
19 */
20
21#include "xkeyboard.h"
22#include <unistd.h>
23
24void keysym_azerty_to_midi_key(long inkey, float *midi_key) {
25 /* these keys are common to all types of azerty keyboards */
26 switch(inkey) {
27 case(XK_w) : (*midi_key) = 12.0; /* w = C0 */
28 break;
29 case(XK_s) : (*midi_key) = 13.0; /* s */
30 break;
31 case(XK_x) : (*midi_key) = 14.0; /* x */
32 break;
33 case(XK_d) : (*midi_key) = 15.0; /* d */
34 break;
35 case(XK_c) : (*midi_key) = 16.0; /* c */
36 break;
37 case(XK_v) : (*midi_key) = 17.0; /* v */
38 break;
39 case(XK_g) : (*midi_key) = 18.0; /* g */
40 break;
41 case(XK_b) : (*midi_key) = 19.0; /* b */
42 break;
43 case(XK_h) : (*midi_key) = 20.0; /* h */
44 break;
45 case(XK_n) : (*midi_key) = 21.0; /* n */
46 break;
47 case(XK_j) : (*midi_key) = 22.0; /* j */
48 break;
49 case(XK_a) : (*midi_key) = 24.0; /* a = C1 */
50 break;
51 case(XK_l) : (*midi_key) = 25.0; /* l */
52 break;
53 case(XK_z) : (*midi_key) = 26.0; /* z */
54 break;
55 case(XK_m) : (*midi_key) = 27.0; /* m */
56 break;
57 case(XK_e) : (*midi_key) = 28.0; /* e */
58 break;
59 case(XK_r) : (*midi_key) = 29.0; /* r */
60 break;
61 case(XK_t) : (*midi_key) = 31.0; /* t */
62 break;
63 case(XK_y) : (*midi_key) = 33.0; /* y */
64 break;
65 case(XK_u) : (*midi_key) = 35.0; /* u */
66 break;
67 case(XK_i) : (*midi_key) = 36.0; /* i */
68 break;
69 case(XK_o) : (*midi_key) = 38.0; /* o */
70 break;
71 case(XK_p) : (*midi_key) = 40.0; /* p */
72 break;
73 }
74}
75
76void keysym_azerty_fr_to_midi_key(long inkey, float *midi_key) {
77 /* common azerty keyboards sell in France */
78 switch(inkey) {
79 case(XK_less) : (*midi_key) = 11.0; /* "<" = B-1 */
80 break;
81 case(XK_comma) : (*midi_key) = 23.0; /* , */
82 break;
83 case(XK_semicolon) : (*midi_key) = 24.0; /* ; = C1 */
84 break;
85 case(XK_eacute) : (*midi_key) = 25.0; /* é */
86 break;
87 case(XK_colon) : (*midi_key) = 26.0; /* : */
88 break;
89 case(XK_quotedbl) : (*midi_key) = 27.0; /* " */
90 break;
91 case(XK_exclam) : (*midi_key) = 28.0; /* ! */
92 break;
93 case(XK_ugrave) : (*midi_key) = 29.0; /* ù = F1 */
94 break;
95 case(XK_asterisk) : (*midi_key) = 30.0; /* * */
96 break;
97 case(XK_parenleft) : (*midi_key) = 30.0; /* ( */
98 break;
99 case(XK_minus) : (*midi_key) = 32.0; /* - */
100 break;
101 case(XK_egrave) : (*midi_key) = 34.0; /* è */
102 break;
103 case(XK_ccedilla) : (*midi_key) = 37.0; /* ç */
104 break;
105 case(XK_agrave) : (*midi_key) = 39.0; /* à */
106 break;
107 case (XK_parenright) : (*midi_key) = 41.0; /* ) = F2 */
108 break;
109 case (XK_equal) : (*midi_key) = 42.0; /* = */
110 break;
111 case (XK_dollar) : (*midi_key) = 43.0; /* $ */
112 break;
113 default: keysym_azerty_to_midi_key(inkey, midi_key);
114 }
115}
116
117void keysym_azerty_be_to_midi_key(long inkey, float *midi_key) {
118 /* common azerty keyboards sell in Belgium (Wallonia) */
119 switch(inkey) {
120 case(XK_less) : (*midi_key) = 11.0; /* "<" = B-1 */
121 break;
122 case(XK_comma) : (*midi_key) = 23.0; /* , */
123 break;
124 case(XK_semicolon) : (*midi_key) = 24.0; /* ; = C1 */
125 break;
126 case(XK_eacute) : (*midi_key) = 25.0; /* é */
127 break;
128 case(XK_colon) : (*midi_key) = 26.0; /* : */
129 break;
130 case(XK_quotedbl) : (*midi_key) = 27.0; /* " */
131 break;
132 case(XK_equal) : (*midi_key) = 28.0; /* = */
133 break;
134 case(XK_ugrave) : (*midi_key) = 29.0; /* ù = F1 */
135 break;
136 case(XK_mu) : (*midi_key) = 30.0; /* µ */
137 break;
138 case(XK_parenleft) : (*midi_key) = 30.0; /* ( */
139 break;
140 case(XK_section) : (*midi_key) = 32.0; /* § */
141 break;
142 case(XK_egrave) : (*midi_key) = 34.0; /* è */
143 break;
144 case(XK_ccedilla) : (*midi_key) = 37.0; /* ç */
145 break;
146 case(XK_agrave) : (*midi_key) = 39.0; /* à */
147 break;
148 case (XK_parenright) : (*midi_key) = 41.0; /* ) = F2 */
149 break;
150 case (XK_minus) : (*midi_key) = 42.0; /* - */
151 break;
152 case (XK_dollar) : (*midi_key) = 43.0; /* $ */
153 break;
154 default: keysym_azerty_to_midi_key(inkey, midi_key);
155 }
156}
157
158void keysym_azerty_afnor_to_midi_key(long inkey, float *midi_key) {
159 /* probably a future standard for azerty keyboards */
160 switch(inkey) {
161 case(XK_less) : (*midi_key) = 11.0; /* "<" = B-1 */
162 break;
163 case(XK_KP_Decimal) : (*midi_key) = 23.0; /* . */
164 break;
165 case(XK_semicolon) : (*midi_key) = 24.0; /* ; = C1 */
166 break;
167 case(XK_eacute) : (*midi_key) = 25.0; /* é */
168 break;
169 case(XK_colon) : (*midi_key) = 26.0; /* : */
170 break;
171 case(XK_quotedbl) : (*midi_key) = 27.0; /* " */
172 break;
173 case(XK_exclam) : (*midi_key) = 28.0; /* ! */
174 break;
175 case(XK_ugrave) : (*midi_key) = 29.0; /* ù = F1 */
176 break;
177 case(XK_asterisk) : (*midi_key) = 30.0; /* * */
178 break;
179 case(XK_parenleft) : (*midi_key) = 30.0; /* ( */
180 break;
181 case(XK_minus) : (*midi_key) = 32.0; /* - */
182 break;
183 case(XK_egrave) : (*midi_key) = 34.0; /* è */
184 break;
185 case(XK_ccedilla) : (*midi_key) = 37.0; /* ç */
186 break;
187 case(XK_agrave) : (*midi_key) = 39.0; /* à */
188 break;
189 case (XK_parenright) : (*midi_key) = 41.0; /* ) = F2 */
190 break;
191 case (XK_equal) : (*midi_key) = 42.0; /* = */
192 break;
193 case (XK_dollar) : (*midi_key) = 43.0; /* $ */
194 break;
195 default: keysym_azerty_to_midi_key(inkey, midi_key);
196 }
197}
198
199void keysym_qwertz_to_midi_key(long inkey, float *midi_key) {
200 switch(inkey) {
201 case(XK_y) : (*midi_key) = 12.0; /* y = C0 */
202 break;
203 case(XK_s) : (*midi_key) = 13.0; /* s */
204 break;
205 case(XK_x) : (*midi_key) = 14.0; /* x */
206 break;
207 case(XK_d) : (*midi_key) = 15.0; /* d */
208 break;
209 case(XK_c) : (*midi_key) = 16.0; /* c */
210 break;
211 case(XK_v) : (*midi_key) = 17.0; /* v */
212 break;
213 case(XK_g) : (*midi_key) = 18.0; /* g */
214 break;
215 case(XK_b) : (*midi_key) = 19.0; /* b */
216 break;
217 case(XK_h) : (*midi_key) = 20.0; /* h */
218 break;
219 case(XK_n) : (*midi_key) = 21.0; /* n */
220 break;
221 case(XK_j) : (*midi_key) = 22.0; /* j */
222 break;
223 case(XK_m) : (*midi_key) = 23.0; /* m */
224 break;
225 case(XK_q) : (*midi_key) = 24.0; /* q */
226 break;
227 case(XK_2) : (*midi_key) = 25.0; /* 2 */
228 break;
229 case(XK_w) : (*midi_key) = 26.0; /* w */
230 break;
231 case(XK_3) : (*midi_key) = 27.0; /* 3 */
232 break;
233 case(XK_e) : (*midi_key) = 28.0; /* e */
234 break;
235 case(XK_r) : (*midi_key) = 29.0; /* r */
236 break;
237 case(XK_5) : (*midi_key) = 30.0; /* 5 */
238 break;
239 case(XK_t) : (*midi_key) = 31.0; /* t */
240 break;
241 case(XK_6) : (*midi_key) = 32.0; /* 6 */
242 break;
243 case(XK_z) : (*midi_key) = 33.0; /* z */
244 break;
245 case(XK_7) : (*midi_key) = 34.0; /* 7 */
246 break;
247 case(XK_u) : (*midi_key) = 35.0; /* u */
248 break;
249 case(XK_i) : (*midi_key) = 36.0; /* i */
250 break;
251 case(XK_9) : (*midi_key) = 37.0; /* 9 */
252 break;
253 case(XK_o) : (*midi_key) = 38.0; /* o */
254 break;
255 case(XK_0) : (*midi_key) = 39.0; /* 0 */
256 break;
257 case(XK_p) : (*midi_key) = 40.0; /* p */
258 break;
259 case(XK_udiaeresis) : (*midi_key) = 41.0; /* ü */
260 break;
261 case(XK_plus) : (*midi_key) = 42.0; /* + */
262 break;
263 }
264}
265
266void keysym_qwerty_to_midi_key(unsigned int inkey, float *midi_key) {
267 keysym_qwertz_to_midi_key(inkey,midi_key);
268 if ((*midi_key) == 12) (*midi_key) = 33;
269 else if ((*midi_key) == 33) (*midi_key) = 12;
270}
271
272void custom_to_midi_key(long custom_keys[128][2], long inkey, float *midi_key) {
273 int i = 0;
274 for(;i<129;i++) {
275 int j = 0;
276 for(;j<2;j++) {
277 if (inkey == custom_keys[i][j]) {
278 (*midi_key) = (float)i;
279 return;
280 }
281 }
282 }
283}
284
285void set_key_in_matrix(unsigned long *key_matrix, int key, bool set) {
286 unsigned long *use_matrix = &key_matrix[0];
287
288 if(key>94) {
289 use_matrix = &key_matrix[3];
290 key -=94;
291 } else if(key>62) {
292 use_matrix = &key_matrix[2];
293 key -=62;
294 } else if(key>31) {
295 use_matrix = &key_matrix[1];
296 key -= 31;
297 }
298 if (set) {
299 (*use_matrix) |= (1 << key);
300 }else {
301 (*use_matrix) &= (~(1 << key));
302 }
303}
304
305bool is_key_in_matrix(unsigned long *key_matrix, int key) {
306 unsigned long *use_matrix = &key_matrix[0];
307
308
309 if(key>94) {
310 use_matrix = &key_matrix[3];
311 key -=94;
312 } else if(key>62) {
313 use_matrix = &key_matrix[2];
314 key -=62;
315 } else if(key>31) {
316 use_matrix = &key_matrix[1];
317 key -= 31;
318 }
319 bool ret = false;
320 if((*use_matrix) & (1<<key)) {
321 ret = true;
322 }
323 return ret;
324}
325
327 int i = 0;
328 for(;i<16;i++) {
329 if (is_key_in_matrix(keys->in_key_matrix[i], key)) {
330 return i;
331 }
332 }
333 return -1;
334}
335
336bool have_key_in_matrix(unsigned long *key_matrix) {
337
338 bool ret = false;
339 int i = 0;
340 int j = 0;
341 for(;j<4;j++) {
342 for(;i<32;i++) {
343 if(key_matrix[j] & (1<<i)) {
344 ret = true;
345 break;
346 }
347 }
348 i = 0;
349 }
350 return ret;
351}
352
353void clear_key_matrix(unsigned long *key_matrix) {
354 int i = 0;
355 int j = 0;
356 for(;j<4;j++) {
357 for(;i<32;i++) {
358 key_matrix[j] &= (~(1 << i));
359 }
360 i = 0;
361 }
362}
363
364void use_matrix_color(Widget_t *w, int c) {
365 double ci = ((c+1)/100.0)*12.0;
366 if (c<4)
367 cairo_set_source_rgba(w->crb, ci, 0.2, 0.4, 1.00);
368 else if (c<8)
369 cairo_set_source_rgba(w->crb, 0.6, 0.2+ci-0.48, 0.4, 1.00);
370 else if (c<12)
371 cairo_set_source_rgba(w->crb, 0.6-(ci-0.96), 0.68-(ci-1.08), 0.4, 1.00);
372 else
373 cairo_set_source_rgba(w->crb, 0.12+(ci-1.56), 0.32, 0.4-(ci-1.44), 1.00);
374}
375
376static void draw_keyboard(void *w_, void* user_data) {
377 Widget_t *w = (Widget_t*)w_;
378 Metrics_t m;
379 int width_t, height_t;
381 width_t = m.width;
382 height_t = m.height;
383 if (!m.visible) return;
385
386 int space = 2;
387 int set = 0;
388 int i = 0;
389 int k = 0;
390 int ik = -1;
391 int octave_ofset = keys->key_size/6;
392 if (keys->key_size<24)
393 cairo_set_font_size (w->crb, w->app->small_font);
394 else
395 cairo_set_font_size (w->crb, w->app->normal_font);
396
397 for(;i<width_t;i++) {
398 ik = is_key_in_in_matrix(keys, k+keys->octave);
399 cairo_rectangle(w->crb,i,0,keys->key_size+1,height_t);
400 if ( k+keys->octave == keys->active_key || is_key_in_matrix(keys->key_matrix,k+keys->octave)) {
401 //use_base_color_scheme(w, ACTIVE_);
402 use_matrix_color(w, keys->channel);
403 cairo_set_line_width(w->crb, 1.0);
404 } else if (ik > -1) {
405 use_matrix_color(w, ik);
406 cairo_set_line_width(w->crb, 2.0);
407 } else if ( k+keys->octave == keys->prelight_key) {
409 cairo_set_line_width(w->crb, 2.0);
410 } else {
412 cairo_set_line_width(w->crb, 1.0);
413 }
414
415 cairo_fill_preserve(w->crb);
417 cairo_stroke(w->crb);
418
419 if(k+keys->octave == 0) {
420 cairo_move_to (w->crb, i+octave_ofset, height_t*0.9);
422 cairo_show_text(w->crb, "C-1");
423 } else if(k+keys->octave == 12) {
424 cairo_move_to (w->crb, i+octave_ofset, height_t*0.9);
426 cairo_show_text(w->crb, "C0");
427 } else if(k+keys->octave == 24) {
428 cairo_move_to (w->crb, i+octave_ofset, height_t*0.9);
430 cairo_show_text(w->crb, "C1");
431 } else if(k+keys->octave == 36) {
432 cairo_move_to (w->crb, i+octave_ofset, height_t*0.9);
434 cairo_show_text(w->crb, "C2");
435 } else if(k+keys->octave == 48) {
436 cairo_move_to (w->crb, i+octave_ofset, height_t*0.9);
438 cairo_show_text(w->crb, "C3");
439 } else if(k+keys->octave == 60) {
440 cairo_move_to (w->crb, i+octave_ofset, height_t*0.9);
442 cairo_show_text(w->crb, "C4");
443 } else if(k+keys->octave == 72) {
444 cairo_move_to (w->crb, i+octave_ofset, height_t*0.9);
446 cairo_show_text(w->crb, "C5");
447 } else if(k+keys->octave == 84) {
448 cairo_move_to (w->crb, i+octave_ofset, height_t*0.9);
450 cairo_show_text(w->crb, "C6");
451 } else if(k+keys->octave == 96) {
452 cairo_move_to (w->crb, i+octave_ofset, height_t*0.9);
454 cairo_show_text(w->crb, "C7");
455 } else if(k+keys->octave == 108) {
456 cairo_move_to (w->crb, i+octave_ofset, height_t*0.9);
458 cairo_show_text(w->crb, "C8");
459 } else if(k+keys->octave == 120) {
460 cairo_move_to (w->crb, i+octave_ofset, height_t*0.9);
462 cairo_show_text(w->crb, "C9");
463 }
464
465 if (space!=4) {
466 k++;
467 } else {
468 if (set <= 3) {
469 space = 0;
470 set = 0;
471 } else if (set == 4) {
472 space = 1;
473 set = 0;
474 }
475 }
476
477 if (k>127) break;
478 i+=keys->key_size;
479 space++;
480 set++;
481 k++;
482 }
483
484 space = 1;
485 set = 0;
486 k = 1;
487 ik = -1;
488 i = 0;
489 cairo_pattern_t *pat = cairo_pattern_create_linear (0, 0, 0, height_t*0.59);
490 cairo_pattern_add_color_stop_rgba(pat, 0.0, 0.85, 0.85, 0.85, 0.4);
491 cairo_pattern_add_color_stop_rgba(pat, 0.2, 0.0, 0.0, 0.0, 0.0);
492 cairo_pattern_add_color_stop_rgba(pat, 1.0, 0.0, 0.0, 0.0, 0.0);
493
494 for(;i<width_t;i++) {
495
496 if (space!=3) {
497 ik = is_key_in_in_matrix(keys, k+keys->octave);
498 cairo_set_line_width(w->crb, 1.0);
499 cairo_rectangle(w->crb,i+keys->key_offset,0,keys->key_size-4,height_t*0.59);
500 if ( k+keys->octave == keys->active_key || is_key_in_matrix(keys->key_matrix,k+keys->octave)) {
501 //use_base_color_scheme(w, ACTIVE_);
502 use_matrix_color(w, keys->channel);
503 cairo_set_line_width(w->crb, 1.0);
504 } else if (ik > -1) {
505 use_matrix_color(w, ik);
506 cairo_set_line_width(w->crb, 2.0);
507 } else if ( k+keys->octave == keys->prelight_key) {
509 cairo_set_line_width(w->crb, 2.0);
510 } else {
512 cairo_set_line_width(w->crb, 1.0);
513 }
514
515 cairo_fill_preserve(w->crb);
516 cairo_set_source(w->crb, pat);
517 cairo_fill_preserve(w->crb);
519 cairo_stroke(w->crb);
520
521 k++;
522 space++;
523 set++;
524
525 } else {
526
527 if (set == 2) {
528 space = 0;
529 set = 0;
530 } else if (set == 3) {
531 space = 1;
532 set = 0;
533 }
534
535 }
536
537 i+=keys->key_size;
538 k++;
539 if(k>127)break;
540 }
541 cairo_pattern_destroy (pat);
542 pat = cairo_pattern_create_linear (0, 0, 0, height_t);
543 cairo_pattern_add_color_stop_rgba(pat, 1.0, 0.0, 0.0, 0.0, 0.4);
544 cairo_pattern_add_color_stop_rgba(pat, 0.8, 0.0, 0.0, 0.0, 0.0);
545 cairo_pattern_add_color_stop_rgba(pat, 0.0, 0.0, 0.0, 0.0, 0.0);
546 cairo_set_source(w->crb, pat);
547 cairo_rectangle(w->crb,0,0,width_t,height_t);
548 cairo_fill(w->crb);
549 cairo_pattern_destroy (pat);
550}
551
552static void keyboard_motion(void *w_, void* xmotion_, void* user_data) {
553 Widget_t *w = (Widget_t*)w_;
554 Widget_t *p = (Widget_t *)w->parent;
556 XMotionEvent *xmotion = (XMotionEvent*)xmotion_;
557 Metrics_t m;
558 int width, height;
560 if (!m.visible) return;
561 width = m.width;
562 height = m.height;
563
564 bool catchit = false;
565
566 if(xmotion->y < height*0.59) {
567 keys->in_motion = 1;
568 int space = 1;
569 int set = 0;
570 int set_key = 1;
571 int i = 0;
572 for(;i<width;i++) {
573 if (space!=3) {
574 if(xmotion->x > i+keys->key_offset && xmotion->x < i+keys->key_size+keys->key_offset-3) {
575 keys->prelight_key = set_key+keys->octave;
576 if(xmotion->state & Button1Mask) {
577 if (keys->active_key != keys->prelight_key) {
578 keys->send_key = keys->active_key;
579 if (keys->send_key>=0 && keys->send_key<128) {
580 if (is_key_in_matrix(keys->in_key_matrix[keys->channel], keys->send_key))
581 set_key_in_matrix(keys->in_key_matrix[keys->channel], keys->send_key,false);
582 keys->mk_send_note(p, &keys->send_key,0x80);
583 }
584 keys->active_key = keys->prelight_key;
585 keys->send_key = keys->active_key;
586 keys->last_active_key = keys->active_key;
587 if (keys->send_key>=0 && keys->send_key<128)
588 keys->mk_send_note(p, &keys->send_key,0x90);
589 }
590 }
591 catchit = true;
592 if (keys->prelight_key != keys->new_prelight_key ||
593 keys->active_key != keys->new_active_key ) {
594 expose_widget(w);
595 keys->new_prelight_key = keys->prelight_key;
596 keys->new_active_key = keys->active_key;
597 }
598 break;
599 }
600 space++;
601 set++;
602 set_key++;
603 } else {
604 if (set == 2) {
605 space = 0;
606 set = 0;
607 } else if (set == 3) {
608 space = 1;
609 set = 0;
610 }
611 }
612 i+=keys->key_size;
613 set_key++;
614 }
615 }
616
617 if (!catchit) {
618 int space = 2;
619 int set = 0;
620 int i = 0;
621 int k = 0;
622
623 for(;i<width;i++) {
624 if(xmotion->x > i && xmotion->x < i+keys->key_size) {
625 keys->prelight_key = k+keys->octave;
626 if(xmotion->state & Button1Mask) {
627 if (keys->active_key != keys->prelight_key) {
628 keys->send_key = keys->active_key;
629 if (keys->send_key>=0 && keys->send_key<128) {
630 if (is_key_in_matrix(keys->in_key_matrix[keys->channel], keys->send_key))
631 set_key_in_matrix(keys->in_key_matrix[keys->channel], keys->send_key,false);
632 keys->mk_send_note(p, &keys->send_key,0x80);
633 }
634 keys->active_key = keys->prelight_key;
635 keys->send_key = keys->active_key;
636 keys->last_active_key = keys->active_key;
637 if (keys->send_key>=0 && keys->send_key<128)
638 keys->mk_send_note(p, &keys->send_key,0x90);
639 }
640 }
641 if (keys->prelight_key != keys->new_prelight_key ||
642 keys->active_key != keys->new_active_key ) {
643 expose_widget(w);
644 keys->new_prelight_key = keys->prelight_key;
645 keys->new_active_key = keys->active_key;
646 }
647 break;
648 }
649
650 if (space!=4) {
651 k++;
652 } else {
653 if (set <= 3) {
654 space = 0;
655 set = 0;
656 } else if (set == 4) {
657 space = 1;
658 set = 0;
659 }
660 }
661
662 i+=keys->key_size;
663 space++;
664 set++;
665 k++;
666 }
667 }
668}
669
670static void get_outkey(MidiKeyboard *keys, KeySym sym, float *outkey) {
671 switch(keys->layout) {
672 case(0):keysym_qwertz_to_midi_key(sym, outkey);
673 break;
674 case(1):keysym_qwerty_to_midi_key(sym, outkey);
675 break;
676 case(2):keysym_azerty_fr_to_midi_key(sym, outkey);
677 break;
678 case(3):keysym_azerty_be_to_midi_key(sym, outkey);
679 break;
680 case(4):custom_to_midi_key(keys->custom_keys, sym, outkey);
681 break;
682 default:keysym_qwertz_to_midi_key(sym, outkey);
683 break;
684 }
685}
686
687static void key_press(void *w_, void *key_, void *user_data) {
688 Widget_t *w = (Widget_t*)w_;
689 Widget_t *p = (Widget_t *)w->parent;
690 if (!w) return;
692 XKeyEvent *key = (XKeyEvent*)key_;
693 if (!key) return;
694#ifdef __linux__
695 if (adj_get_value(keys->grab_keyboard->adj)) {
696 char xkeys[32];
697 XQueryKeymap(w->app->dpy, xkeys);
698 if (!(xkeys[key->keycode>>3] & (0x1 << (key->keycode % 8)))) return;
699 }
700#endif
701 // if (key->state & ControlMask) {
702 // p->func.key_press_callback(p, key_, user_data);
703 // } else {
704 float outkey = 0.0;
705#ifdef _WIN32 //KeybHandler
706 KeySym sym = key->keycode;
707 if (key->vk_is_final_char) return; // only real KEY_DOWN, dead-key support not required/wanted
708#else
709 KeySym sym = XLookupKeysym (key, 0);
710#endif
711 get_outkey(keys, sym, &outkey);
712
713 if ((int)outkey && !is_key_in_matrix(keys->key_matrix, (int)outkey+keys->octave)) {
714 set_key_in_matrix(keys->key_matrix,(int)outkey+keys->octave,true);
715 keys->send_key = (int)outkey+keys->octave;
716 if (keys->send_key>=0 && keys->send_key<128)
717 keys->mk_send_note(p, &keys->send_key,0x90);
718 expose_widget(w);
719 }
720 if (sym == XK_space) {
721 clear_key_matrix(&keys->key_matrix[0]);
722 int i = 0;
723 for (;i<16;i++) clear_key_matrix(&keys->in_key_matrix[i][0]);
724 keys->mk_send_all_sound_off(p, NULL);
725 expose_widget(w);
726 }
727 //}
728}
729
730static void key_release(void *w_, void *key_, void *user_data) {
731 Widget_t *w = (Widget_t*)w_;
732 Widget_t *p = (Widget_t *)w->parent;
733 if (!w) return;
735 XKeyEvent *key = (XKeyEvent*)key_;
736 if (!key) return;
737#ifdef __linux__
738 if (adj_get_value(keys->grab_keyboard->adj)) {
739 char xkeys[32];
740 XQueryKeymap(w->app->dpy, xkeys);
741 if ((xkeys[key->keycode>>3] & (0x1 << (key->keycode % 8)))) return;
742 }
743 KeySym sym = XLookupKeysym (key, 0);
744#else
745 KeySym sym = key->keycode;
746#endif
747 float outkey = 0.0;
748 get_outkey(keys, sym, &outkey);
749 if ((int)outkey && is_key_in_matrix(keys->key_matrix, (int)outkey+keys->octave)) {
750 set_key_in_matrix(keys->key_matrix,(int)outkey+keys->octave,false);
751 keys->send_key = (int)outkey+keys->octave;
752 if (keys->send_key>=0 && keys->send_key<128)
753 keys->mk_send_note(p, &keys->send_key,0x80);
754 expose_widget(w);
755 }
756}
757
758static void leave_keyboard(void *w_, void* user_data) {
759 Widget_t *w = (Widget_t*)w_;
761 keys->prelight_key = -1;
762 keys->active_key = -1;
763 keys->in_motion = 0;
764 expose_widget(w);
765}
766
767static void button_pressed_keyboard(void *w_, void* button_, void* user_data) {
768 Widget_t *w = (Widget_t*)w_;
769 Widget_t *p = (Widget_t *)w->parent;
770 if (w->flags & HAS_POINTER) {
772 XButtonEvent *xbutton = (XButtonEvent*)button_;
773 if(xbutton->button == Button1) {
774 keys->active_key = keys->prelight_key;
775 keys->send_key = keys->active_key;
776 keys->last_active_key = keys->active_key;
777 if (keys->send_key>=0 && keys->send_key<128)
778 keys->mk_send_note(p, &keys->send_key,0x90);
779 expose_widget(w);
780 } else if (xbutton->button == Button3) {
781 keys->send_key = keys->prelight_key;
782 if (keys->send_key>=0 && keys->send_key<128) {
783 if (is_key_in_matrix(keys->in_key_matrix[keys->channel], keys->send_key)) {
784 set_key_in_matrix(keys->in_key_matrix[keys->channel], keys->send_key,false);
785 keys->mk_send_note(p, &keys->send_key,0x80);
786 } else {
787 set_key_in_matrix(keys->in_key_matrix[keys->channel], keys->send_key,true);
788 keys->mk_send_note(p, &keys->send_key,0x90);
789 }
790 }
791 }
792 }
793}
794
795static void button_released_keyboard(void *w_, void* button_, void* user_data) {
796 Widget_t *w = (Widget_t*)w_;
797 Widget_t *p = (Widget_t *)w->parent;
799 XButtonEvent *xbutton = (XButtonEvent*)button_;
800 if (w->flags & HAS_POINTER) {
801 if(xbutton->button == Button1) {
802 keys->send_key = keys->active_key;
803 if (keys->send_key>=0 && keys->send_key<128) {
804 keys->mk_send_note(p, &keys->send_key,0x80);
805 if (is_key_in_matrix(keys->in_key_matrix[keys->channel], keys->send_key))
806 set_key_in_matrix(keys->in_key_matrix[keys->channel], keys->send_key,false);
807 }
808 keys->active_key = -1;
809 expose_widget(w);
810 } else if (xbutton->button == Button2) {
811 pop_menu_show(w, keys->context_menu, 4, false);
812 }
813 } else {
814 if(xbutton->button == Button1) {
815 keys->send_key = keys->last_active_key;
816 if (keys->send_key>=0 && keys->send_key<128) {
817 keys->mk_send_note(p, &keys->send_key,0x80);
818 }
819 keys->last_active_key = -1;
820 }
821 }
822}
823
824static void keyboard_mem_free(void *w_, void* user_data) {
825 Widget_t *w = (Widget_t*)w_;
827 free(keys);
828}
829
831 bool have = false;
832 int i = 0;
833 for(;i<16;i++) {
834 if (have_key_in_matrix(keys->in_key_matrix[i])) {
835 have = true;
836 break;
837 }
838 }
839
840 return (keys->active_key > 0 ? 1 : 0) |
841 (keys->prelight_key > 0 ? 1 : 0) |
843 have;
844}
845
846static void octave_callback(void *w_, void* user_data) {
847 Widget_t *w = (Widget_t*)w_;
849 keys->octave = (int)12*adj_get_value(w->adj);
850 expose_widget(keys->keyboard);
851}
852
853static void layout_callback(void *w_, void* user_data) {
854 Widget_t *w = (Widget_t*)w_;
856 keys->layout = (int)adj_get_value(w->adj);
857}
858
859static void velocity_changed(void *w_, void* user_data) {
860 Widget_t *w = (Widget_t*)w_;
862 keys->velocity = (int)adj_get_value(w->adj);
863}
864
865static void grab_callback(void *w_, void* user_data) {
866#ifdef __linux__
867 Widget_t *w = (Widget_t*)w_;
869 if (adj_get_value(w->adj)) {
870 XGrabKeyboard(w->app->dpy, keys->keyboard->widget, true,
871 GrabModeAsync, GrabModeAsync, CurrentTime);
872 } else {
873 XUngrabKeyboard(w->app->dpy, CurrentTime);
874 }
875#endif
876}
877
878void read_keymap(const char* keymapfile, long keys[128][2]) {
879 if( access(keymapfile, F_OK ) != -1 ) {
880 FILE *fp;
881 if((fp=fopen(keymapfile, "rb"))==NULL) {
882 fprintf(stderr,"Cannot open file.\n");
883 }
884
885 if(fread(keys, sizeof(long), 128*2, fp) != 128*2) {
886 if(feof(fp))
887 fprintf(stderr,"Premature end of file.");
888 else
889 fprintf(stderr,"File read error.");
890 }
891 fclose(fp);
892 }
893}
894
895static void key_dummy(Widget_t *w, const int *key, const int on_off) {
896 if (on_off == 0x90)
897 fprintf(stderr, "Send note on %i\n",(*key));
898 else
899 fprintf(stderr, "Send note off %i\n",(*key));
900}
901
902static void wheel_dummy(Widget_t *w, const int *value) {
903 fprintf(stderr, "send all sound off\n");
904}
905
906Widget_t *add_midi_keyboard(Widget_t *parent, const char * label,
907 int x, int y, int width, int height) {
908 Widget_t *wid = create_widget(parent->app, parent, x, y, width, height);
909 wid->label = label;
911 add_keyboard(wid, label);
912 return wid;
913}
914
915Widget_t *open_midi_keyboard(Widget_t *w, const char * label) {
916 Widget_t *wid = create_window(w->app, os_get_root_window(w->app, IS_WINDOW), 0, 0, 700, 200);
918 add_keyboard(wid, label);
919 wid->parent = w;
920 return wid;
921}
922
923void add_keyboard(Widget_t *wid, const char * label) {
924 MidiKeyboard *keys = (MidiKeyboard*)malloc(sizeof(MidiKeyboard));
925 wid->private_struct = keys;
926 wid->flags |= HAS_MEM | NO_AUTOREPEAT;
927 wid->scale.gravity = EASTSOUTH;
928 keys->prelight_key = -1;
929 keys->active_key = -1;
930 keys->new_prelight_key = -1;
931 keys->new_active_key = -1;
932 keys->last_active_key = -1;
933 keys->in_motion = 0;
934 keys->send_key = -1;
935 keys->octave = 12*2;
936 keys->layout = 0;
937 keys->channel = 0;
938 keys->velocity = 64;
939 keys->key_size = 20;
940 keys->key_offset = 15;
941 keys->keyboard = wid;
942 memset(keys->custom_keys, 0, 128*2*sizeof keys->custom_keys[0][0]);
943 int j = 0;
944 for(;j<4;j++) {
945 keys->key_matrix[j] = 0;
946 }
947 int i = 0;
948 for(;i<16;i++) {
949 j = 0;
950 for(;j<4;j++) {
951 keys->in_key_matrix[i][j] = 0;
952 }
953 }
954 read_keymap(label, keys->custom_keys);
955
956 wid->func.expose_callback = draw_keyboard;
957 wid->func.motion_callback = keyboard_motion;
958 wid->func.leave_callback = leave_keyboard;
959 wid->func.button_press_callback = button_pressed_keyboard;
960 wid->func.button_release_callback = button_released_keyboard;
961 wid->func.double_click_callback = button_released_keyboard;
962 wid->func.key_press_callback = key_press;
963 wid->func.key_release_callback = key_release;
964 wid->func.mem_free_callback = keyboard_mem_free;
965
966 keys->mk_send_note = key_dummy;
967 keys->mk_send_all_sound_off = wheel_dummy;
968
969 keys->context_menu = create_menu(wid,25);
970 Widget_t* keymap = cmenu_add_submenu(keys->context_menu,_("Keyboard"));
971 keymap->private_struct = keys;
972 menu_add_radio_entry(keymap,_("qwertz"));
973 menu_add_radio_entry(keymap,_("qwerty"));
974 menu_add_radio_entry(keymap,_("azerty (fr)"));
975 menu_add_radio_entry(keymap,_("azerty (be)"));
976 set_active_radio_entry_num(keymap, keys->layout);
977 keymap->func.value_changed_callback = layout_callback;
978
979 Widget_t* octavemap = cmenu_add_submenu(keys->context_menu,_("Octave"));
980 octavemap->private_struct = keys;
981 menu_add_radio_entry(octavemap,_("C 0"));
982 menu_add_radio_entry(octavemap,_("C 1"));
983 menu_add_radio_entry(octavemap,_("C 2"));
984 menu_add_radio_entry(octavemap,_("C 3"));
985 menu_add_radio_entry(octavemap,_("C 4"));
986 set_active_radio_entry_num(octavemap, keys->octave/12);
987 octavemap->func.value_changed_callback = octave_callback;
988
989 Widget_t* velocity = cmenu_add_submenu(keys->context_menu,_("Velocity"));
990 velocity->private_struct = keys;
991 Widget_t* vel = menu_add_value_entry(velocity, "128");
992 vel->private_struct = keys;
993 set_adjustment(vel->adj, 0.0, 0.0, 0.0, 127.0, 1.0, CL_CONTINUOS);
994 adj_set_value(vel->adj, keys->velocity);
995 vel->func.value_changed_callback = velocity_changed;
996
997 keys->grab_keyboard = menu_add_check_item(keys->context_menu,_("Grab Keyboard"));
998 keys->grab_keyboard->private_struct = keys;
999 keys->grab_keyboard->func.value_changed_callback = grab_callback;
1000}
evfunc button_release_callback
Definition xwidget.h:101
xevfunc expose_callback
Definition xwidget.h:85
evfunc key_release_callback
Definition xwidget.h:105
evfunc key_press_callback
Definition xwidget.h:104
evfunc double_click_callback
Definition xwidget.h:102
xevfunc leave_callback
Definition xwidget.h:88
xevfunc value_changed_callback
Definition xwidget.h:90
xevfunc mem_free_callback
Definition xwidget.h:92
evfunc motion_callback
Definition xwidget.h:103
evfunc button_press_callback
Definition xwidget.h:100
Metrics_t - struct to receive window size, position & visibility Pass this struct to os_get_window_...
int prelight_key
Definition xkeyboard.h:44
Widget_t * context_menu
Definition xkeyboard.h:37
int new_active_key
Definition xkeyboard.h:47
unsigned long in_key_matrix[16][4]
Definition xkeyboard.h:54
int last_active_key
Definition xkeyboard.h:48
unsigned long key_matrix[4]
Definition xkeyboard.h:53
midiwheelfunc mk_send_all_sound_off
Definition xkeyboard.h:58
Widget_t * grab_keyboard
Definition xkeyboard.h:39
long custom_keys[128][2]
Definition xkeyboard.h:55
int new_prelight_key
Definition xkeyboard.h:45
Widget_t * keyboard
Definition xkeyboard.h:38
midikeyfunc mk_send_note
Definition xkeyboard.h:57
Gravity gravity
Definition xwidget.h:347
Widget_t - struct to hold the basic Widget_t info.
Definition xwidget.h:457
Resize_t scale
Definition xwidget.h:525
Adjustment_t * adj
Definition xwidget.h:497
void * parent
Definition xwidget.h:471
Window widget
Definition xwidget.h:469
cairo_t * crb
Definition xwidget.h:489
long long flags
Definition xwidget.h:461
void * private_struct
Definition xwidget.h:475
const char * label
Definition xwidget.h:463
Func_t func
Definition xwidget.h:481
Xputty * app
Definition xwidget.h:465
bool vk_is_final_char
unsigned int state
int button
int keycode
int normal_font
Definition xputty.h:248
Display * dpy
Definition xputty.h:232
int small_font
Definition xputty.h:246
void adj_set_value(Adjustment_t *adj, float value)
adj_set_value - set the current value to the Adjustment_t
float adj_get_value(Adjustment_t *adj)
adj_get_value - get the current value of the Adjustment_t
void set_adjustment(Adjustment_t *adj, float std_value, float value, float min_value, float max_value, float step, CL_type type)
*set_adjustment - set a new range to a existing Adjustment_t or create if it not exists yet
Definition xadjustment.c:80
@ CL_CONTINUOS
Definition xadjustment.h:49
void use_bg_color_scheme(Widget_t *w, Color_state st)
use_bg_color_scheme - use background Colors to paint on Widget_t
Definition xcolor.c:252
void use_fg_color_scheme(Widget_t *w, Color_state st)
use_fg_color_scheme - use forground Colors to paint on Widget_t
Definition xcolor.c:245
void use_base_color_scheme(Widget_t *w, Color_state st)
use_base_color_scheme - use base Colors to paint on Widget_t
Definition xcolor.c:259
@ NORMAL_
Definition xcolor.h:44
@ PRELIGHT_
Definition xcolor.h:45
void keysym_qwerty_to_midi_key(unsigned int inkey, float *midi_key)
Definition xkeyboard.c:266
bool is_key_in_matrix(unsigned long *key_matrix, int key)
Definition xkeyboard.c:305
void add_keyboard(Widget_t *wid, const char *label)
Definition xkeyboard.c:923
void clear_key_matrix(unsigned long *key_matrix)
Definition xkeyboard.c:353
void read_keymap(const char *keymapfile, long keys[128][2])
Definition xkeyboard.c:878
Widget_t * add_midi_keyboard(Widget_t *parent, const char *label, int x, int y, int width, int height)
Definition xkeyboard.c:906
void keysym_azerty_to_midi_key(long inkey, float *midi_key)
Definition xkeyboard.c:24
void keysym_qwertz_to_midi_key(long inkey, float *midi_key)
Definition xkeyboard.c:199
Widget_t * open_midi_keyboard(Widget_t *w, const char *label)
Definition xkeyboard.c:915
void set_key_in_matrix(unsigned long *key_matrix, int key, bool set)
Definition xkeyboard.c:285
void use_matrix_color(Widget_t *w, int c)
Definition xkeyboard.c:364
int is_key_in_in_matrix(MidiKeyboard *keys, int key)
Definition xkeyboard.c:326
void custom_to_midi_key(long custom_keys[128][2], long inkey, float *midi_key)
Definition xkeyboard.c:272
void keysym_azerty_fr_to_midi_key(long inkey, float *midi_key)
Definition xkeyboard.c:76
bool need_redraw(MidiKeyboard *keys)
Definition xkeyboard.c:830
void keysym_azerty_be_to_midi_key(long inkey, float *midi_key)
Definition xkeyboard.c:117
bool have_key_in_matrix(unsigned long *key_matrix)
Definition xkeyboard.c:336
void keysym_azerty_afnor_to_midi_key(long inkey, float *midi_key)
Definition xkeyboard.c:158
void pop_menu_show(Widget_t *parent, Widget_t *menu, int elem, bool above)
pop_menu_show - pop up a menu to a Widget_t
Definition xmenu.c:27
Widget_t * menu_add_check_item(Widget_t *menu, const char *label)
menu_add_check_item - add a item to menu
Definition xmenu.c:317
Widget_t * menu_add_value_entry(Widget_t *wid, const char *label)
menu_add_value_entry- add a value entry to menu
Definition xmenu.c:169
Widget_t * create_menu(Widget_t *parent, int height)
create_menu - create a menu to a Widget_t
Definition xmenu.c:256
Widget_t * cmenu_add_submenu(Widget_t *wid, const char *label)
cmenu_add_submenu - add a submenu to a cmenu
Definition xmenu.c:226
Widget_t * menu_add_radio_entry(Widget_t *wid, const char *label)
menu_add_radio_entry- add a radio entry to menu
Definition xmenu.c:141
void set_active_radio_entry_num(Widget_t *w, int active)
set_active_radio_item - activate selected radio item by number
Definition xmenu.c:78
XID KeySym
void os_get_window_metrics(Widget_t *w, Metrics_t *metrics)
os_get_window_metrics - Get the Merics_t struct related to a Widget_t
Window os_get_root_window(Xputty *main, int flag)
os_get_root_window - get a pointer to the root window (desktop)
void os_set_input_mask(Widget_t *w)
os_set_input_mask - set the Event mask to a Widget_t only work on linux, stub on Windows
Widget_t * create_widget(Xputty *app, Widget_t *win, int x, int y, int width, int height)
*create_widget - create a widget A Widget_t could only be created as child of a other Widget_t To...
Definition xwidget.c:265
void expose_widget(Widget_t *w)
expose_widgets - send a expose event (EXPOSE) to a Widget_t
Definition xwidget.c:445
Widget_t * create_window(Xputty *app, Window win, int x, int y, int width, int height)
*create_window - create a Window You need to create as least minimun one Window to get started....
Definition xwidget.c:163
@ EASTSOUTH
Definition xwidget.h:314
@ HAS_POINTER
Definition xwidget.h:402
@ NO_AUTOREPEAT
Definition xwidget.h:408
@ HAS_MEM
Definition xwidget.h:406
@ IS_WINDOW
Definition xwidget.h:390