libxputty  0.1
A damn tiny abstraction Layer to create X11 window/widgets with cairo surfaces
xmidi_keyboard.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 "xmidi_keyboard.h"
22 
23 
24 void keysym_azerty_to_midi_key(long inkey, float *midi_key) {
25  switch(inkey) {
26  case(XK_w) : (*midi_key) = 12.0; /* w = C0 */
27  break;
28  case(XK_s) : (*midi_key) = 13.0; /* s */
29  break;
30  case(XK_x) : (*midi_key) = 14.0; /* x */
31  break;
32  case(XK_d) : (*midi_key) = 15.0; /* d */
33  break;
34  case(XK_c) : (*midi_key) = 16.0; /* c */
35  break;
36  case(XK_v) : (*midi_key) = 17.0; /* v */
37  break;
38  case(XK_g) : (*midi_key) = 18.0; /* g */
39  break;
40  case(XK_b) : (*midi_key) = 19.0; /* b */
41  break;
42  case(XK_h) : (*midi_key) = 20.0; /* h */
43  break;
44  case(XK_n) : (*midi_key) = 21.0; /* n */
45  break;
46  case(XK_j) : (*midi_key) = 22.0; /* j */
47  break;
48  case(XK_comma) : (*midi_key) = 23.0; /* , */
49  break;
50  case(XK_a) : (*midi_key) = 24.0; /* a */
51  break;
52  case(XK_eacute) : (*midi_key) = 25.0; /* eacute */
53  break;
54  case(XK_z) : (*midi_key) = 26.0; /* z */
55  break;
56  case(XK_quotedbl) : (*midi_key) = 27.0; /* quotedbl */
57  break;
58  case(XK_e) : (*midi_key) = 28.0; /* e */
59  break;
60  case(XK_r) : (*midi_key) = 29.0; /* r */
61  break;
62  case(XK_parenleft) : (*midi_key) = 30.0; /* parenleft */
63  break;
64  case(XK_t) : (*midi_key) = 31.0; /* t */
65  break;
66  case(XK_minus) : (*midi_key) = 32.0; /* minus */
67  break;
68  case(XK_y) : (*midi_key) = 33.0; /* y */
69  break;
70  case(XK_egrave) : (*midi_key) = 34.0; /* egrave */
71  break;
72  case(XK_u) : (*midi_key) = 35.0; /* u */
73  break;
74  case(XK_i) : (*midi_key) = 36.0; /* i */
75  break;
76  case(XK_ccedilla) : (*midi_key) = 37.0; /* ccedilla */
77  break;
78  case(XK_o) : (*midi_key) = 38.0; /* o */
79  break;
80  case(XK_agrave) : (*midi_key) = 39.0; /* agrave */
81  break;
82  case(XK_p) : (*midi_key) = 40.0; /* p */
83  break;
84  case(XK_dead_diaeresis) :
85  case(XK_dead_circumflex) : (*midi_key) = 41.0; /* dead circumflex */
86  break;
87  }
88 }
89 
90 void keysym_qwertz_to_midi_key(long inkey, float *midi_key) {
91  switch(inkey) {
92  case(XK_y) : (*midi_key) = 12.0; /* y = C0 */
93  break;
94  case(XK_s) : (*midi_key) = 13.0; /* s */
95  break;
96  case(XK_x) : (*midi_key) = 14.0; /* x */
97  break;
98  case(XK_d) : (*midi_key) = 15.0; /* d */
99  break;
100  case(XK_c) : (*midi_key) = 16.0; /* c */
101  break;
102  case(XK_v) : (*midi_key) = 17.0; /* v */
103  break;
104  case(XK_g) : (*midi_key) = 18.0; /* g */
105  break;
106  case(XK_b) : (*midi_key) = 19.0; /* b */
107  break;
108  case(XK_h) : (*midi_key) = 20.0; /* h */
109  break;
110  case(XK_n) : (*midi_key) = 21.0; /* n */
111  break;
112  case(XK_j) : (*midi_key) = 22.0; /* j */
113  break;
114  case(XK_m) : (*midi_key) = 23.0; /* m */
115  break;
116  case(XK_q) : (*midi_key) = 24.0; /* q */
117  break;
118  case(XK_2) : (*midi_key) = 25.0; /* 2 */
119  break;
120  case(XK_w) : (*midi_key) = 26.0; /* w */
121  break;
122  case(XK_3) : (*midi_key) = 27.0; /* 3 */
123  break;
124  case(XK_e) : (*midi_key) = 28.0; /* e */
125  break;
126  case(XK_r) : (*midi_key) = 29.0; /* r */
127  break;
128  case(XK_5) : (*midi_key) = 30.0; /* 5 */
129  break;
130  case(XK_t) : (*midi_key) = 31.0; /* t */
131  break;
132  case(XK_6) : (*midi_key) = 32.0; /* 6 */
133  break;
134  case(XK_z) : (*midi_key) = 33.0; /* z */
135  break;
136  case(XK_7) : (*midi_key) = 34.0; /* 7 */
137  break;
138  case(XK_u) : (*midi_key) = 35.0; /* u */
139  break;
140  case(XK_i) : (*midi_key) = 36.0; /* i */
141  break;
142  case(XK_9) : (*midi_key) = 37.0; /* 9 */
143  break;
144  case(XK_o) : (*midi_key) = 38.0; /* o */
145  break;
146  case(XK_0) : (*midi_key) = 39.0; /* 0 */
147  break;
148  case(XK_p) : (*midi_key) = 40.0; /* p */
149  break;
150  case(XK_udiaeresis) : (*midi_key) = 41.0; /* ΓΌ */
151  break;
152  case(XK_plus) : (*midi_key) = 42.0; /* + */
153  break;
154  }
155 }
156 
157 void keysym_qwerty_to_midi_key(unsigned int inkey, float *midi_key) {
158  keysym_qwertz_to_midi_key(inkey,midi_key);
159  if ((*midi_key) == 12) (*midi_key) = 33;
160  else if ((*midi_key) == 33) (*midi_key) = 12;
161 }
162 
163 static void set_key_in_matrix(unsigned long *key_matrix, int key, bool set) {
164  unsigned long *use_matrix = &key_matrix[0];
165 
166  if(key>94) {
167  use_matrix = &key_matrix[3];
168  key -=94;
169  } else if(key>62) {
170  use_matrix = &key_matrix[2];
171  key -=62;
172  } else if(key>31) {
173  use_matrix = &key_matrix[1];
174  key -= 31;
175  }
176  if (set) {
177  (*use_matrix) |= (1 << key);
178  }else {
179  (*use_matrix) &= (~(1 << key));
180  }
181 }
182 
183 bool is_key_in_matrix(unsigned long *key_matrix, int key) {
184  unsigned long *use_matrix = &key_matrix[0];
185 
186 
187  if(key>94) {
188  use_matrix = &key_matrix[3];
189  key -=94;
190  } else if(key>62) {
191  use_matrix = &key_matrix[2];
192  key -=62;
193  } else if(key>31) {
194  use_matrix = &key_matrix[1];
195  key -= 31;
196  }
197  bool ret = false;
198  if((*use_matrix) & (1<<key)) {
199  ret = true;
200  }
201  return ret;
202 }
203 
204 bool have_key_in_matrix(unsigned long *key_matrix) {
205 
206  bool ret = false;
207  int i = 0;
208  int j = 0;
209  for(;j<4;j++) {
210  for(;i<32;i++) {
211  if(key_matrix[j] & (1<<i)) {
212  ret = true;
213  break;
214  }
215  }
216  i = 0;
217  }
218  return ret;
219 }
220 
221 void clear_key_matrix(unsigned long *key_matrix) {
222  int i = 0;
223  int j = 0;
224  for(;j<4;j++) {
225  for(;i<32;i++) {
226  key_matrix[j] &= (~(1 << i));
227  }
228  i = 0;
229  }
230 }
231 void mk_draw_knob(void *w_, void* user_data) {
232  Widget_t *w = (Widget_t*)w_;
233  XWindowAttributes attrs;
234  XGetWindowAttributes(w->app->dpy, (Window)w->widget, &attrs);
235  int width = attrs.width-2;
236  int height = attrs.height-2;
237 
238  const double scale_zero = 20 * (M_PI/180); // defines "dead zone" for knobs
239  int arc_offset = 2;
240  int knob_x = 0;
241  int knob_y = 0;
242 
243  int grow = (width > height) ? height:width;
244  knob_x = grow-1;
245  knob_y = grow-1;
246  /** get values for the knob **/
247 
248  int knobx = (width - knob_x) * 0.5;
249  int knobx1 = width* 0.5;
250 
251  int knoby = (height - knob_y) * 0.5;
252  int knoby1 = height * 0.5;
253 
254  double knobstate = adj_get_state(w->adj_y);
255  double angle = scale_zero + knobstate * 2 * (M_PI - scale_zero);
256 
257  double pointer_off =knob_x/3.5;
258  double radius = min(knob_x-pointer_off, knob_y-pointer_off) / 2;
259  double lengh_x = (knobx+radius+pointer_off/2) - radius * sin(angle);
260  double lengh_y = (knoby+radius+pointer_off/2) + radius * cos(angle);
261  double radius_x = (knobx+radius+pointer_off/2) - radius/ 1.18 * sin(angle);
262  double radius_y = (knoby+radius+pointer_off/2) + radius/ 1.18 * cos(angle);
263  cairo_pattern_t* pat;
264  cairo_new_path (w->crb);
265 
266  pat = cairo_pattern_create_linear (0, 0, 0, knob_y);
267  cairo_pattern_add_color_stop_rgba (pat, 1, 0.3, 0.3, 0.3, 1.0);
268  cairo_pattern_add_color_stop_rgba (pat, 0.75, 0.2, 0.2, 0.2, 1.0);
269  cairo_pattern_add_color_stop_rgba (pat, 0.5, 0.15, 0.15, 0.15, 1.0);
270  cairo_pattern_add_color_stop_rgba (pat, 0.25, 0.1, 0.1, 0.1, 1.0);
271  cairo_pattern_add_color_stop_rgba (pat, 0, 0.05, 0.05, 0.05, 1.0);
272 
273  cairo_scale (w->crb, 0.95, 1.05);
274  cairo_arc(w->crb,knobx1+arc_offset/2, knoby1-arc_offset, knob_x/2.2, 0, 2 * M_PI );
275  cairo_set_source (w->crb, pat);
276  cairo_fill_preserve (w->crb);
277  cairo_set_source_rgb (w->crb, 0.1, 0.1, 0.1);
278  cairo_set_line_width(w->crb,1);
279  cairo_stroke(w->crb);
280  cairo_scale (w->crb, 1.05, 0.95);
281  cairo_new_path (w->crb);
282  cairo_pattern_destroy (pat);
283  pat = NULL;
284 
285  pat = cairo_pattern_create_linear (0, 0, 0, knob_y);
286  cairo_pattern_add_color_stop_rgba (pat, 0, 0.3, 0.3, 0.3, 1.0);
287  cairo_pattern_add_color_stop_rgba (pat, 0.25, 0.2, 0.2, 0.2, 1.0);
288  cairo_pattern_add_color_stop_rgba (pat, 0.5, 0.15, 0.15, 0.15, 1.0);
289  cairo_pattern_add_color_stop_rgba (pat, 0.75, 0.1, 0.1, 0.1, 1.0);
290  cairo_pattern_add_color_stop_rgba (pat, 1, 0.05, 0.05, 0.05, 1.0);
291 
292  cairo_arc(w->crb,knobx1, knoby1, knob_x/2.6, 0, 2 * M_PI );
293  cairo_set_source (w->crb, pat);
294  cairo_fill_preserve (w->crb);
295  cairo_set_source_rgb (w->crb, 0.1, 0.1, 0.1);
296  cairo_set_line_width(w->crb,1);
297  cairo_stroke(w->crb);
298  cairo_new_path (w->crb);
299  cairo_pattern_destroy (pat);
300 
301  /** create a rotating pointer on the kob**/
302  cairo_set_line_cap(w->crb, CAIRO_LINE_CAP_ROUND);
303  cairo_set_line_join(w->crb, CAIRO_LINE_JOIN_BEVEL);
304  cairo_move_to(w->crb, radius_x, radius_y);
305  cairo_line_to(w->crb,lengh_x,lengh_y);
306  cairo_set_line_width(w->crb,3);
307  cairo_set_source_rgb (w->crb,0.63,0.63,0.63);
308  cairo_stroke(w->crb);
309  cairo_new_path (w->crb);
310 
311  cairo_text_extents_t extents;
312  /** show value on the kob**/
313  if (w->state) {
314  char s[64];
315  snprintf(s, 63,"%d", (int) w->adj_y->value);
316  cairo_set_source_rgb (w->crb, 0.6, 0.6, 0.6);
317  cairo_set_font_size (w->crb, knobx1/3);
318  cairo_text_extents(w->crb, s, &extents);
319  cairo_move_to (w->crb, knobx1-extents.width/2, knoby1+extents.height/2);
320  cairo_show_text(w->crb, s);
321  cairo_new_path (w->crb);
322  }
323 
324  /** show label below the knob**/
326  float font_size = ((height/2.2 < (width*0.5)/3) ? height/2.2 : (width*0.5)/3);
327  cairo_set_font_size (w->crb, font_size);
328  cairo_text_extents(w->crb,w->label , &extents);
329 
330  cairo_move_to (w->crb, knobx1-extents.width/2, height );
331  cairo_show_text(w->crb, w->label);
332  cairo_new_path (w->crb);
333 }
334 
335 static void draw_keyboard(void *w_, void* user_data) {
336  Widget_t *w = (Widget_t*)w_;
337  XWindowAttributes attrs;
338  XGetWindowAttributes(w->app->dpy, (Window)w->widget, &attrs);
339  int width_t = attrs.width;
340  int height_t = attrs.height;
341  if (attrs.map_state != IsViewable) return;
343 
344  cairo_rectangle(w->crb,0,0,width_t,height_t*0.4);
346  cairo_fill (w->crb);
347  //set_pattern(w,&w->app->color_scheme->normal,&w->app->color_scheme->selected,BACKGROUND_);
349  cairo_rectangle(w->crb,0,height_t*0.38,width_t,height_t*0.02);
350  cairo_fill_preserve (w->crb);
352 
353  cairo_set_line_width(w->crb, 1.0);
354  cairo_stroke(w->crb);
355  int space = 2;
356  int set = 0;
357  int i = 0;
358  int k = 0;
359 
360  for(;i<width_t;i++) {
361  cairo_rectangle(w->crb,i,height_t*0.4,25,height_t*0.6);
362  if ( k+keys->octave == keys->active_key || is_key_in_matrix(keys->key_matrix,k+keys->octave)) {
364  cairo_set_line_width(w->crb, 1.0);
365  } else if ( k+keys->octave == keys->prelight_key) {
367  cairo_set_line_width(w->crb, 2.0);
368  } else {
370  cairo_set_line_width(w->crb, 1.0);
371  }
372 
373  cairo_fill_preserve(w->crb);
375  cairo_stroke(w->crb);
376 
377  if (space!=4) {
378  k++;
379  } else {
380  if (set <= 3) {
381  space = 0;
382  set = 0;
383  } else if (set == 4) {
384  space = 1;
385  set = 0;
386  }
387  }
388 
389  if (k>127) break;
390  i+=24;
391  space++;
392  set++;
393  k++;
394  }
395 
396  space = 1;
397  set = 0;
398  k = 1;
399  i = 0;
400 
401  for(;i<width_t;i++) {
402 
403  if (space!=3) {
404  cairo_set_line_width(w->crb, 1.0);
405  cairo_rectangle(w->crb,i+15,height_t*0.4,20,height_t*0.39);
406  if ( k+keys->octave == keys->active_key || is_key_in_matrix(keys->key_matrix,k+keys->octave)) {
408  cairo_set_line_width(w->crb, 1.0);
409  } else if ( k+keys->octave == keys->prelight_key) {
411  cairo_set_line_width(w->crb, 2.0);
412  } else {
414  cairo_set_line_width(w->crb, 1.0);
415  }
416 
417  cairo_fill_preserve(w->crb);
419  cairo_stroke(w->crb);
420 
421  k++;
422  space++;
423  set++;
424 
425  } else {
426 
427  if (set == 2) {
428  space = 0;
429  set = 0;
430  } else if (set == 3) {
431  space = 1;
432  set = 0;
433  }
434 
435  }
436 
437  i+=24;
438  k++;
439  if(k>127)break;
440  }
441 }
442 
443 static void keyboard_motion(void *w_, void* xmotion_, void* user_data) {
444  Widget_t *w = (Widget_t*)w_;
445  Widget_t *p = (Widget_t *)w->parent;
447  XMotionEvent *xmotion = (XMotionEvent*)xmotion_;
448  XWindowAttributes attrs;
449  XGetWindowAttributes(w->app->dpy, (Window)w->widget, &attrs);
450  if (attrs.map_state != IsViewable) return;
451  int width = attrs.width;
452  int height = attrs.height;
453 
454  bool catchit = false;
455 
456  if(xmotion->y < height*0.4) {
457  keys->active_key = keys->prelight_key = -1;
458  expose_widget(w);
459  return;
460  }
461 
462  if(xmotion->y < height*0.8) {
463  int space = 1;
464  int set = 0;
465  int set_key = 1;
466  int i = 0;
467  for(;i<width;i++) {
468  if (space!=3) {
469  if(xmotion->x > i+15 && xmotion->x < i+35) {
470  keys->prelight_key = set_key+keys->octave;
471  if(xmotion->state & Button1Mask) {
472  if (keys->active_key != keys->prelight_key) {
473  keys->send_key = keys->active_key;
474  keys->mk_send_note(p, &keys->send_key,false);
475  keys->active_key = keys->prelight_key;
476  keys->send_key = keys->active_key;
477  keys->mk_send_note(p, &keys->send_key,true);
478  }
479  }
480  catchit = true;
481  expose_widget(w);
482  break;
483  }
484  space++;
485  set++;
486  set_key++;
487  } else {
488  if (set == 2) {
489  space = 0;
490  set = 0;
491  } else if (set == 3) {
492  space = 1;
493  set = 0;
494  }
495  }
496  i+=24;
497  set_key++;
498  }
499  }
500 
501  if (!catchit) {
502  int space = 2;
503  int set = 0;
504  int i = 0;
505  int k = 0;
506 
507  for(;i<width;i++) {
508  if(xmotion->x > i && xmotion->x < i+25) {
509  keys->prelight_key = k+keys->octave;
510  if(xmotion->state & Button1Mask) {
511  if (keys->active_key != keys->prelight_key) {
512  keys->send_key = keys->active_key;
513  keys->mk_send_note(p, &keys->send_key,false);
514  keys->active_key = keys->prelight_key;
515  keys->send_key = keys->active_key;
516  keys->mk_send_note(p, &keys->send_key,true);
517  }
518  }
519  expose_widget(w);
520  break;
521  }
522 
523  if (space!=4) {
524  k++;
525  } else {
526  if (set <= 3) {
527  space = 0;
528  set = 0;
529  } else if (set == 4) {
530  space = 1;
531  set = 0;
532  }
533  }
534 
535  i+=24;
536  space++;
537  set++;
538  k++;
539  }
540  }
541 }
542 
543 static void get_outkey(MidiKeyboard *keys, KeySym sym, float *outkey) {
544  switch(keys->layout) {
545  case(0):keysym_qwertz_to_midi_key(sym, outkey);
546  break;
547  case(1):keysym_qwerty_to_midi_key(sym, outkey);
548  break;
549  case(2):keysym_azerty_to_midi_key(sym, outkey);
550  break;
551  default:keysym_qwertz_to_midi_key(sym, outkey);
552  break;
553  }
554 }
555 
556 static void key_press(void *w_, void *key_, void *user_data) {
557  Widget_t *w = (Widget_t*)w_;
558  Widget_t *p = (Widget_t *)w->parent;
559  if (!w) return;
561  XKeyEvent *key = (XKeyEvent*)key_;
562  if (!key) return;
563  float outkey = 0.0;
564  KeySym sym = XLookupKeysym (key, 0);
565  get_outkey(keys, sym, &outkey);
566 
567  if ((int)outkey && !is_key_in_matrix(keys->key_matrix, (int)outkey+keys->octave)) {
568  set_key_in_matrix(keys->key_matrix,(int)outkey+keys->octave,true);
569  keys->send_key = (int)outkey+keys->octave;
570  keys->mk_send_note(p, &keys->send_key,true);
571  expose_widget(w);
572  }
573  if (sym == XK_space) {
574  clear_key_matrix(&keys->key_matrix[0]);
575  keys->mk_send_all_sound_off(p, NULL);
576  expose_widget(w);
577  }
578 }
579 
580 static void key_release(void *w_, void *key_, void *user_data) {
581  Widget_t *w = (Widget_t*)w_;
582  Widget_t *p = (Widget_t *)w->parent;
583  if (!w) return;
585  XKeyEvent *key = (XKeyEvent*)key_;
586  if (!key) return;
587  float outkey = 0.0;
588  KeySym sym = XLookupKeysym (key, 0);
589  get_outkey(keys, sym, &outkey);
590  if ((int)outkey && is_key_in_matrix(keys->key_matrix, (int)outkey+keys->octave)) {
591  set_key_in_matrix(keys->key_matrix,(int)outkey+keys->octave,false);
592  keys->send_key = (int)outkey+keys->octave;
593  keys->mk_send_note(p,&keys->send_key,false);
594  expose_widget(w);
595  }
596 }
597 
598 static void leave_keyboard(void *w_, void* user_data) {
599  Widget_t *w = (Widget_t*)w_;
601  keys->prelight_key = -1;
602  expose_widget(w);
603 }
604 
605 static void button_pressed_keyboard(void *w_, void* button_, void* user_data) {
606  Widget_t *w = (Widget_t*)w_;
607  Widget_t *p = (Widget_t *)w->parent;
608  if (w->flags & HAS_POINTER) {
610  XButtonEvent *xbutton = (XButtonEvent*)button_;
611  if(xbutton->button == Button1) {
612  keys->active_key = keys->prelight_key;
613  keys->send_key = keys->active_key;
614  keys->mk_send_note(p,&keys->send_key,true);
615  expose_widget(w);
616  }
617  }
618 }
619 
620 static void button_released_keyboard(void *w_, void* button_, void* user_data) {
621  Widget_t *w = (Widget_t*)w_;
622  Widget_t *p = (Widget_t *)w->parent;
623  if (w->flags & HAS_POINTER) {
625  XButtonEvent *xbutton = (XButtonEvent*)button_;
626  if(xbutton->button == Button1) {
627  keys->send_key = keys->active_key;
628  keys->mk_send_note(p,&keys->send_key,false);
629  keys->active_key = -1;
630  expose_widget(w);
631  }
632  }
633 }
634 
635 static void octave_callback(void *w_, void* user_data) {
636  Widget_t *w = (Widget_t*)w_;
637  Widget_t *p = (Widget_t *)w->parent;
639  keys->octave = (int)12*adj_get_value(w->adj);
640 }
641 
642 static void layout_callback(void *w_, void* user_data) {
643  Widget_t *w = (Widget_t*)w_;
644  Widget_t *p = (Widget_t *)w->parent;
646  keys->layout = (int)adj_get_value(w->adj);
647 }
648 
649 static void modwheel_callback(void *w_, void* user_data) {
650  Widget_t *w = (Widget_t*)w_;
651  Widget_t *p = (Widget_t *)w->parent;
652  Widget_t *pa = (Widget_t *)p->parent;
654  keys->modwheel = (int)adj_get_value(w->adj);
655  keys->mk_send_mod(pa, &keys->modwheel);
656 }
657 
658 static void detune_callback(void *w_, void* user_data) {
659  Widget_t *w = (Widget_t*)w_;
660  Widget_t *p = (Widget_t *)w->parent;
661  Widget_t *pa = (Widget_t *)p->parent;
663  keys->detune = (int)adj_get_value(w->adj);
664  keys->mk_send_detune(pa, &keys->detune);
665 }
666 
667 static void attack_callback(void *w_, void* user_data) {
668  Widget_t *w = (Widget_t*)w_;
669  Widget_t *p = (Widget_t *)w->parent;
670  Widget_t *pa = (Widget_t *)p->parent;
672  keys->attack = (int)adj_get_value(w->adj);
673  keys->mk_send_attack(pa, &keys->attack);
674 }
675 
676 static void sustain_callback(void *w_, void* user_data) {
677  Widget_t *w = (Widget_t*)w_;
678  Widget_t *p = (Widget_t *)w->parent;
679  Widget_t *pa = (Widget_t *)p->parent;
681  keys->sustain = (int)adj_get_value(w->adj);
682  keys->mk_send_sustain(pa, &keys->sustain);
683 }
684 
685 static void release_callback(void *w_, void* user_data) {
686  Widget_t *w = (Widget_t*)w_;
687  Widget_t *p = (Widget_t *)w->parent;
688  Widget_t *pa = (Widget_t *)p->parent;
690  keys->release = (int)adj_get_value(w->adj);
691  keys->mk_send_release(pa, &keys->release);
692 }
693 
694 static void volume_callback(void *w_, void* user_data) {
695  Widget_t *w = (Widget_t*)w_;
696  Widget_t *p = (Widget_t *)w->parent;
697  Widget_t *pa = (Widget_t *)p->parent;
699  keys->volume = (int)adj_get_value(w->adj);
700  keys->mk_send_volume(pa, &keys->volume);
701 }
702 
703 static void velocity_callback(void *w_, void* user_data) {
704  Widget_t *w = (Widget_t*)w_;
705  Widget_t *p = (Widget_t *)w->parent;
706  Widget_t *pa = (Widget_t *)p->parent;
708  keys->velocity = (int)adj_get_value(w->adj);
709  keys->mk_send_velocity(pa, &keys->velocity);
710 }
711 
712 static void pitchwheel_callback(void *w_, void* user_data) {
713  Widget_t *w = (Widget_t*)w_;
714  Widget_t *p = (Widget_t *)w->parent;
715  Widget_t *pa = (Widget_t *)p->parent;
717  keys->pitchwheel = (int)adj_get_value(w->adj);
718  keys->mk_send_pitch(pa,&keys->pitchwheel);
719 }
720 
721 static void pitchsensity_callback(void *w_, void* user_data) {
722  Widget_t *w = (Widget_t*)w_;
723  Widget_t *p = (Widget_t *)w->parent;
724  Widget_t *pa = (Widget_t *)p->parent;
726  keys->pitchsensity = (int)adj_get_value(w->adj);
727  keys->mk_send_pitchsensity(pa,&keys->pitchsensity);
728 }
729 
730 static void wheel_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  p->func.key_release_callback(p, key_, user_data);
734 }
735 
736 static void wheel_key_press(void *w_, void *key_, void *user_data) {
737  Widget_t *w = (Widget_t*)w_;
738  Widget_t *p = (Widget_t *)w->parent;
739  p->func.key_press_callback(p, key_, user_data);
740 }
741 
742 /**
743  * @brief keyboard_mem_free - release additional used memory when destroy the Widget_t
744  * @param *w_ - void pointer to the Widget_t
745  * @param *user_data - void pointer to attached user_data
746  * @return void
747  */
748 
749 static void keyboard_mem_free(void *w_, void* user_data) {
750  Widget_t *w = (Widget_t*)w_;
752  if(keys->icon) {
753  XFreePixmap(w->app->dpy, (*keys->icon));
754  keys->icon = NULL;
755  }
756  free(keys);
757 }
758 
759 static void map_keyboard(void *w_, void* user_data) {
760  Widget_t *w = (Widget_t*)w_;
761  Widget_t *pa = (Widget_t*)w->parent;
763  keys->mk_send_pitchsensity(pa,&keys->pitchsensity);
764  keys->mk_send_pitch(pa,&keys->pitchwheel);
765  keys->mk_send_velocity(pa, &keys->velocity);
766  keys->mk_send_volume(pa, &keys->volume);
767  keys->mk_send_sustain(pa, &keys->sustain);
768  keys->mk_send_mod(pa, &keys->modwheel);
769 }
770 
771 static void key_dummy(Widget_t *w,int *key, bool on_off) {
772  //if (on_off)
773  //fprintf(stderr, "send note on %i\n",(*key));
774  //else
775  //fprintf(stderr, "send note off %i\n",(*key));
776 }
777 
778 static void wheel_dummy(Widget_t *w,int *value) {
779  //fprintf(stderr, "send wheel value %i\n",(*value));
780 }
781 
782 Widget_t *add_keyboard_knob(Widget_t *parent, const char * label,
783  int x, int y, int width, int height) {
784  Widget_t *wid = add_knob(parent,label, x, y, width, height);
785  wid->flags |= NO_AUTOREPEAT;
786  set_adjustment(wid->adj,64.0, 64.0, 0.0, 127.0, 1.0, CL_CONTINUOS);
788  wid->func.key_press_callback = wheel_key_press;
789  wid->func.key_release_callback = wheel_key_release;
790  return wid;
791 }
792 
794  Widget_t *wid = create_window(w->app, DefaultRootWindow(w->app->dpy), 0, 0, 700, 200);
795  XSelectInput(wid->app->dpy, wid->widget,StructureNotifyMask|ExposureMask|KeyPressMask
796  |EnterWindowMask|LeaveWindowMask|ButtonReleaseMask|KeyReleaseMask
797  |ButtonPressMask|Button1MotionMask|PointerMotionMask);
798  MidiKeyboard *keys = (MidiKeyboard*)malloc(sizeof(MidiKeyboard));
799  wid->parent_struct = keys;
800  wid->parent = w;
801  wid->flags |= HAS_MEM | NO_AUTOREPEAT;
802  keys->prelight_key = -1;
803  keys->active_key = -1;
804  keys->send_key = -1;
805  keys->octave = 12*2;
806  keys->layout = 0;
807  keys->icon = NULL;
808  int j = 0;
809  for(;j<4;j++) {
810  keys->key_matrix[j] = 0;
811  }
812 
813  wid->func.expose_callback = draw_keyboard;
814  wid->func.motion_callback = keyboard_motion;
815  wid->func.leave_callback = leave_keyboard;
816  wid->func.button_press_callback = button_pressed_keyboard;
817  wid->func.button_release_callback = button_released_keyboard;
818  wid->func.key_press_callback = key_press;
819  wid->func.key_release_callback = key_release;
820  wid->func.mem_free_callback = keyboard_mem_free;
821  wid->func.map_notify_callback = map_keyboard;
822  widget_set_icon_from_png(wid,keys->icon,LDVAR(midikeyboard_png));
823  widget_set_title(wid, "Midi Keyboard");
824  keys->mk_send_note = key_dummy;
825  keys->mk_send_pitch = wheel_dummy;
826  keys->mk_send_pitchsensity = wheel_dummy;
827  keys->mk_send_mod = wheel_dummy;
828  keys->mk_send_detune = wheel_dummy;
829  keys->mk_send_attack = wheel_dummy;
830  keys->mk_send_sustain = wheel_dummy;
831  keys->mk_send_release = wheel_dummy;
832  keys->mk_send_volume = wheel_dummy;
833  keys->mk_send_velocity = wheel_dummy;
834  keys->mk_send_all_sound_off = wheel_dummy;
835 
836  Widget_t *p = add_keyboard_knob(wid, "PitchBend", 5, 0, 60, 75);
837  p->func.value_changed_callback = pitchwheel_callback;
838  keys->pitchwheel = (int)adj_get_value(p->adj);
839 
840  Widget_t *s = add_keyboard_knob(wid, "P.Sensity", 65, 0, 60, 75);
841  s->func.value_changed_callback = pitchsensity_callback;
842  keys->pitchsensity = (int)adj_get_value(s->adj);
843 
844  Widget_t *m = add_keyboard_knob(wid, "ModWheel", 125, 0, 60, 75);
845  m->func.value_changed_callback = modwheel_callback;
846  keys->modwheel = (int)adj_get_value(m->adj);
847 
848  Widget_t *de = add_keyboard_knob(wid, "Detune", 185, 0, 60, 75);
849  de->func.value_changed_callback = detune_callback;
850  keys->detune = (int)adj_get_value(de->adj);
851 
852  Widget_t *at = add_keyboard_knob(wid, "Attack", 245, 0, 60, 75);
853  at->func.value_changed_callback = attack_callback;
854  keys->attack = (int)adj_get_value(at->adj);
855 
856  Widget_t *su = add_keyboard_knob(wid, "Sustain", 305, 0, 60, 75);
857  su->func.value_changed_callback = sustain_callback;
858  keys->sustain = (int)adj_get_value(su->adj);
859 
860  Widget_t *re = add_keyboard_knob(wid, "Release", 365, 0, 60, 75);
861  re->func.value_changed_callback = release_callback;
862  keys->release = (int)adj_get_value(re->adj);
863 
864  Widget_t *v = add_keyboard_knob(wid, "Volume", 425, 0, 60, 75);
865  v->func.value_changed_callback = volume_callback;
866  keys->volume = (int)adj_get_value(v->adj);
867 
868  Widget_t *ve = add_keyboard_knob(wid, "Velocity", 485, 0, 60, 75);
869  set_adjustment(ve->adj,127.0, 127.0, 0.0, 127.0, 1.0, CL_CONTINUOS);
870  ve->func.value_changed_callback = velocity_callback;
871  keys->velocity = (int)adj_get_value(ve->adj);
872 
873  Widget_t *b = add_hslider(wid, "Keyboard mapping", 540, 40, 160, 35);
874  b->flags |= NO_AUTOREPEAT;
875  set_adjustment(b->adj,2.0, 2.0, 0.0, 4.0, 1.0, CL_CONTINUOS);
876  adj_set_scale(b->adj, 0.05);
877  b->func.value_changed_callback = octave_callback;
878 
879  Widget_t *layout = add_combobox(wid, "", 550, 2, 130, 30);
880  layout->flags |= NO_AUTOREPEAT;
881  layout->scale.gravity = ASPECT;
882  combobox_add_entry(layout,"qwertz");
883  combobox_add_entry(layout,"qwerty");
884  combobox_add_entry(layout,"azerty");
885  combobox_set_active_entry(layout, 0);
886  set_adjustment(layout->adj,0.0, 0.0, 0.0, 2.0, 1.0, CL_ENUM);
887  layout->func.value_changed_callback = layout_callback;
888 
889  return wid;
890 }
use_text_color_scheme
void use_text_color_scheme(Widget_t *w, Color_state st)
use_text_color_scheme - use text Colors to paint on Widget_t
Definition: xcolor.c:199
Func_t::leave_callback
xevfunc leave_callback
Definition: xwidget.h:83
MidiKeyboard::mk_send_volume
midiwheelfunc mk_send_volume
Definition: xmidi_keyboard.h:62
expose_widget
void expose_widget(Widget_t *w)
expose_widgets - send a expose event (EXPOSE) to a Widget_t
Definition: xwidget.c:461
MidiKeyboard::mk_send_detune
midiwheelfunc mk_send_detune
Definition: xmidi_keyboard.h:58
MidiKeyboard::icon
Pixmap * icon
Definition: xmidi_keyboard.h:36
Resize_t::gravity
Gravity gravity
Definition: xwidget.h:192
MidiKeyboard::velocity
int velocity
Definition: xmidi_keyboard.h:46
widget_set_title
void widget_set_title(Widget_t *w, const char *title)
widget_set_title - set window title for a Widget_t
Definition: xwidget.c:387
MidiKeyboard::modwheel
int modwheel
Definition: xmidi_keyboard.h:40
adj_get_state
float adj_get_state(Adjustment_t *adj)
adj_get_state - get the current state of the Adjustment_t
Definition: xadjustment.c:148
Adjustment_t::value
float value
Definition: xadjustment.h:86
MidiKeyboard::mk_send_velocity
midiwheelfunc mk_send_velocity
Definition: xmidi_keyboard.h:63
Widget_t::parent_struct
void * parent_struct
Definition: xwidget.h:306
min
#define min(x, y)
min - set a maximal value (x) as return value
Definition: xputty.h:78
get_color_state
Color_state get_color_state(Widget_t *wid)
get_color_state - get the Color_state to use in relation to the Widget_t state
Definition: xcolor.c:155
combobox_add_entry
Widget_t * combobox_add_entry(Widget_t *wid, const char *label)
combobox_add_entry - add a entry to the combobox
Definition: xcombobox.c:56
CL_ENUM
@ CL_ENUM
Definition: xadjustment.h:55
add_hslider
Widget_t * add_hslider(Widget_t *parent, const char *label, int x, int y, int width, int height)
add_hslider - add a horizontal slider to a Widget_t connect to func.value_changed_callback to impleme...
Definition: xslider.c:41
MidiKeyboard::attack
int attack
Definition: xmidi_keyboard.h:42
MidiKeyboard::detune
int detune
Definition: xmidi_keyboard.h:41
Func_t::key_release_callback
evfunc key_release_callback
Definition: xwidget.h:97
NO_AUTOREPEAT
@ NO_AUTOREPEAT
Definition: xwidget.h:253
Func_t::expose_callback
xevfunc expose_callback
Definition: xwidget.h:80
adj_get_value
float adj_get_value(Adjustment_t *adj)
adj_get_value - get the current value of the Adjustment_t
Definition: xadjustment.c:154
MidiKeyboard::mk_send_all_sound_off
midiwheelfunc mk_send_all_sound_off
Definition: xmidi_keyboard.h:64
keysym_qwertz_to_midi_key
void keysym_qwertz_to_midi_key(long inkey, float *midi_key)
Definition: xmidi_keyboard.c:90
MidiKeyboard::send_key
int send_key
Definition: xmidi_keyboard.h:51
have_key_in_matrix
bool have_key_in_matrix(unsigned long *key_matrix)
Definition: xmidi_keyboard.c:204
HAS_POINTER
@ HAS_POINTER
Definition: xwidget.h:247
Widget_t::crb
cairo_t * crb
Definition: xwidget.h:318
adj_set_scale
void adj_set_scale(Adjustment_t *adj, float value)
adj_set_scale - internal use to scale the pointer movement (0.1 -1.0)
Definition: xadjustment.c:179
MidiKeyboard::mk_send_release
midiwheelfunc mk_send_release
Definition: xmidi_keyboard.h:61
MidiKeyboard::octave
int octave
Definition: xmidi_keyboard.h:38
Func_t::motion_callback
evfunc motion_callback
Definition: xwidget.h:95
Widget_t::flags
long long flags
Definition: xwidget.h:324
Widget_t::adj
Adjustment_t * adj
Definition: xwidget.h:334
MidiKeyboard::pitchsensity
int pitchsensity
Definition: xmidi_keyboard.h:48
is_key_in_matrix
bool is_key_in_matrix(unsigned long *key_matrix, int key)
Definition: xmidi_keyboard.c:183
use_fg_color_scheme
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:178
Widget_t::scale
Resize_t scale
Definition: xwidget.h:356
mk_draw_knob
void mk_draw_knob(void *w_, void *user_data)
Definition: xmidi_keyboard.c:231
use_bg_color_scheme
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:185
BACKGROUND_
@ BACKGROUND_
Definition: xcolor.h:53
Func_t::key_press_callback
evfunc key_press_callback
Definition: xwidget.h:96
MidiKeyboard::mk_send_mod
midiwheelfunc mk_send_mod
Definition: xmidi_keyboard.h:57
keysym_azerty_to_midi_key
void keysym_azerty_to_midi_key(long inkey, float *midi_key)
Definition: xmidi_keyboard.c:24
MidiKeyboard::key_matrix
unsigned long key_matrix[4]
Definition: xmidi_keyboard.h:52
MidiKeyboard
Definition: xmidi_keyboard.h:35
HAS_MEM
@ HAS_MEM
Definition: xwidget.h:251
Widget_t::app
Xputty * app
Definition: xwidget.h:300
MidiKeyboard::mk_send_attack
midiwheelfunc mk_send_attack
Definition: xmidi_keyboard.h:59
Func_t::button_press_callback
evfunc button_press_callback
Definition: xwidget.h:93
Xputty::dpy
Display * dpy
Definition: xputty.h:181
add_keyboard_knob
Widget_t * add_keyboard_knob(Widget_t *parent, const char *label, int x, int y, int width, int height)
Definition: xmidi_keyboard.c:782
MidiKeyboard::sustain
int sustain
Definition: xmidi_keyboard.h:43
Widget_t::state
int state
Definition: xwidget.h:342
MidiKeyboard::release
int release
Definition: xmidi_keyboard.h:44
combobox_set_active_entry
void combobox_set_active_entry(Widget_t *w, int active)
combobox_set_active_entry - set the active combobox entry
Definition: xcombobox.c:25
Func_t::map_notify_callback
xevfunc map_notify_callback
Definition: xwidget.h:89
ACTIVE_
@ ACTIVE_
Definition: xcolor.h:42
MidiKeyboard::mk_send_pitchsensity
midiwheelfunc mk_send_pitchsensity
Definition: xmidi_keyboard.h:56
Widget_t::widget
Window widget
Definition: xwidget.h:302
XColor_t::selected
Colors selected
Definition: xcolor.h:91
Widget_t
Widget_t - struct to hold the basic Widget_t info.
Definition: xwidget.h:298
NORMAL_
@ NORMAL_
Definition: xcolor.h:39
ASPECT
@ ASPECT
Definition: xwidget.h:167
LDVAR
#define LDVAR(NAME)
Definition: xpngloader.h:71
keysym_qwerty_to_midi_key
void keysym_qwerty_to_midi_key(unsigned int inkey, float *midi_key)
Definition: xmidi_keyboard.c:157
PRELIGHT_
@ PRELIGHT_
Definition: xcolor.h:40
xmidi_keyboard.h
Func_t::mem_free_callback
xevfunc mem_free_callback
Definition: xwidget.h:87
MidiKeyboard::mk_send_note
midikeyfunc mk_send_note
Definition: xmidi_keyboard.h:54
Func_t::button_release_callback
evfunc button_release_callback
Definition: xwidget.h:94
create_window
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:145
MidiKeyboard::volume
int volume
Definition: xmidi_keyboard.h:45
set_adjustment
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 it will be created if it not exsits yet
Definition: xadjustment.c:80
add_knob
Widget_t * add_knob(Widget_t *parent, const char *label, int x, int y, int width, int height)
add_knob - add a knob to a Widget_t connect to func.value_changed_callback to implement your actions ...
Definition: xknob.c:26
MidiKeyboard::mk_send_sustain
midiwheelfunc mk_send_sustain
Definition: xmidi_keyboard.h:60
set_pattern
void set_pattern(Widget_t *w, Colors *from, Colors *to, Color_mod mod)
set_pattern - set pattern for the selected Colors
Definition: xcolor.c:227
MidiKeyboard::prelight_key
int prelight_key
Definition: xmidi_keyboard.h:49
MidiKeyboard::pitchwheel
int pitchwheel
Definition: xmidi_keyboard.h:47
Widget_t::adj_y
Adjustment_t * adj_y
Definition: xwidget.h:332
open_midi_keyboard
Widget_t * open_midi_keyboard(Widget_t *w)
Definition: xmidi_keyboard.c:793
Widget_t::func
Func_t func
Definition: xwidget.h:310
MidiKeyboard::mk_send_pitch
midiwheelfunc mk_send_pitch
Definition: xmidi_keyboard.h:55
widget_set_icon_from_png
void widget_set_icon_from_png(Widget_t *w, Pixmap *icon_, const unsigned char *name)
widget_set_icon_from_png - set icon image from png binary to Widget_t those icon will be used in the ...
Definition: xpngloader.c:124
MidiKeyboard::layout
int layout
Definition: xmidi_keyboard.h:39
Xputty::color_scheme
XColor_t * color_scheme
Definition: xputty.h:183
add_combobox
Widget_t * add_combobox(Widget_t *parent, const char *label, int x, int y, int width, int height)
add_combobox - add a combobox
Definition: xcombobox.c:32
MidiKeyboard::active_key
int active_key
Definition: xmidi_keyboard.h:50
Widget_t::parent
void * parent
Definition: xwidget.h:304
use_base_color_scheme
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:192
SELECTED_
@ SELECTED_
Definition: xcolor.h:41
Widget_t::label
const char * label
Definition: xwidget.h:326
Func_t::value_changed_callback
xevfunc value_changed_callback
Definition: xwidget.h:85
clear_key_matrix
void clear_key_matrix(unsigned long *key_matrix)
Definition: xmidi_keyboard.c:221
CL_CONTINUOS
@ CL_CONTINUOS
Definition: xadjustment.h:49
XColor_t::normal
Colors normal
Definition: xcolor.h:89