1 /* GSequencer - Advanced GTK Sequencer
2  * Copyright (C) 2005-2020 Joël Krähemann
3  *
4  * This file is part of GSequencer.
5  *
6  * GSequencer is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GSequencer is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with GSequencer.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <ags/X/editor/ags_notation_edit.h>
21 #include <ags/X/editor/ags_notation_edit_callbacks.h>
22 
23 #include <ags/X/ags_ui_provider.h>
24 #include <ags/X/ags_notation_editor.h>
25 
26 #include <gdk/gdkkeysyms.h>
27 
28 #include <math.h>
29 
30 static GType ags_accessible_notation_edit_get_type(void);
31 void ags_notation_edit_class_init(AgsNotationEditClass *notation_edit);
32 void ags_accessible_notation_edit_class_init(AtkObject *object);
33 void ags_accessible_notation_edit_action_interface_init(AtkActionIface *action);
34 void ags_notation_edit_connectable_interface_init(AgsConnectableInterface *connectable);
35 void ags_notation_edit_init(AgsNotationEdit *notation_edit);
36 void ags_notation_edit_finalize(GObject *gobject);
37 
38 AtkObject* ags_notation_edit_get_accessible(GtkWidget *widget);
39 
40 void ags_notation_edit_connect(AgsConnectable *connectable);
41 void ags_notation_edit_disconnect(AgsConnectable *connectable);
42 
43 gboolean ags_accessible_notation_edit_do_action(AtkAction *action,
44 						gint i);
45 gint ags_accessible_notation_edit_get_n_actions(AtkAction *action);
46 const gchar* ags_accessible_notation_edit_get_description(AtkAction *action,
47 							  gint i);
48 const gchar* ags_accessible_notation_edit_get_name(AtkAction *action,
49 						   gint i);
50 const gchar* ags_accessible_notation_edit_get_keybinding(AtkAction *action,
51 							 gint i);
52 gboolean ags_accessible_notation_edit_set_description(AtkAction *action,
53 						      gint i);
54 gchar* ags_accessible_notation_edit_get_localized_name(AtkAction *action,
55 						       gint i);
56 
57 void ags_notation_edit_show(GtkWidget *widget);
58 void ags_notation_edit_show_all(GtkWidget *widget);
59 
60 gboolean ags_notation_edit_auto_scroll_timeout(GtkWidget *widget);
61 
62 /**
63  * SECTION:ags_notation_edit
64  * @short_description: edit notes
65  * @title: AgsNotationEdit
66  * @section_id:
67  * @include: ags/X/editor/ags_notation_edit.h
68  *
69  * The #AgsNotationEdit lets you edit notes.
70  */
71 
72 enum{
73   PROP_0,
74 };
75 
76 static gpointer ags_notation_edit_parent_class = NULL;
77 
78 static GQuark quark_accessible_object = 0;
79 
80 GHashTable *ags_notation_edit_auto_scroll = NULL;
81 
82 GType
ags_notation_edit_get_type(void)83 ags_notation_edit_get_type(void)
84 {
85   static volatile gsize g_define_type_id__volatile = 0;
86 
87   if(g_once_init_enter (&g_define_type_id__volatile)){
88     GType ags_type_notation_edit = 0;
89 
90     static const GTypeInfo ags_notation_edit_info = {
91       sizeof (AgsNotationEditClass),
92       NULL, /* base_init */
93       NULL, /* base_finalize */
94       (GClassInitFunc) ags_notation_edit_class_init,
95       NULL, /* class_finalize */
96       NULL, /* class_data */
97       sizeof (AgsNotationEdit),
98       0,    /* n_preallocs */
99       (GInstanceInitFunc) ags_notation_edit_init,
100     };
101 
102     static const GInterfaceInfo ags_connectable_interface_info = {
103       (GInterfaceInitFunc) ags_notation_edit_connectable_interface_init,
104       NULL, /* interface_finalize */
105       NULL, /* interface_data */
106     };
107 
108     ags_type_notation_edit = g_type_register_static(GTK_TYPE_TABLE,
109 						    "AgsNotationEdit", &ags_notation_edit_info,
110 						    0);
111 
112     g_type_add_interface_static(ags_type_notation_edit,
113 				AGS_TYPE_CONNECTABLE,
114 				&ags_connectable_interface_info);
115 
116     g_once_init_leave(&g_define_type_id__volatile, ags_type_notation_edit);
117   }
118 
119   return g_define_type_id__volatile;
120 }
121 
122 static GType
ags_accessible_notation_edit_get_type(void)123 ags_accessible_notation_edit_get_type(void)
124 {
125   static GType ags_type_accessible_notation_edit = 0;
126 
127   if(!ags_type_accessible_notation_edit){
128     const GTypeInfo ags_accesssible_notation_edit_info = {
129       sizeof(GtkAccessibleClass),
130       NULL,           /* base_init */
131       NULL,           /* base_finalize */
132       (GClassInitFunc) ags_accessible_notation_edit_class_init,
133       NULL,           /* class_finalize */
134       NULL,           /* class_data */
135       sizeof(GtkAccessible),
136       0,             /* n_preallocs */
137       NULL, NULL
138     };
139 
140     static const GInterfaceInfo atk_action_interface_info = {
141       (GInterfaceInitFunc) ags_accessible_notation_edit_action_interface_init,
142       NULL, /* interface_finalize */
143       NULL, /* interface_data */
144     };
145 
146     ags_type_accessible_notation_edit = g_type_register_static(GTK_TYPE_ACCESSIBLE,
147 							       "AgsAccessibleNotationEdit", &ags_accesssible_notation_edit_info,
148 							       0);
149 
150     g_type_add_interface_static(ags_type_accessible_notation_edit,
151 				ATK_TYPE_ACTION,
152 				&atk_action_interface_info);
153   }
154 
155   return(ags_type_accessible_notation_edit);
156 }
157 
158 void
ags_notation_edit_class_init(AgsNotationEditClass * notation_edit)159 ags_notation_edit_class_init(AgsNotationEditClass *notation_edit)
160 {
161   GtkWidgetClass *widget;
162 
163   GObjectClass *gobject;
164 
165   ags_notation_edit_parent_class = g_type_class_peek_parent(notation_edit);
166 
167   /* GObjectClass */
168   gobject = G_OBJECT_CLASS(notation_edit);
169 
170   gobject->finalize = ags_notation_edit_finalize;
171 
172   /* GtkWidgetClass */
173   widget = (GtkWidgetClass *) notation_edit;
174 
175   widget->show = ags_notation_edit_show;
176   widget->show_all = ags_notation_edit_show_all;
177 //  widget->draw = ags_notation_edit_draw;
178 }
179 
180 void
ags_accessible_notation_edit_class_init(AtkObject * object)181 ags_accessible_notation_edit_class_init(AtkObject *object)
182 {
183   quark_accessible_object = g_quark_from_static_string("ags-accessible-object");
184 }
185 
186 void
ags_accessible_notation_edit_action_interface_init(AtkActionIface * action)187 ags_accessible_notation_edit_action_interface_init(AtkActionIface *action)
188 {
189   action->do_action = ags_accessible_notation_edit_do_action;
190   action->get_n_actions = ags_accessible_notation_edit_get_n_actions;
191   action->get_description = ags_accessible_notation_edit_get_description;
192   action->get_name = ags_accessible_notation_edit_get_name;
193   action->get_keybinding = ags_accessible_notation_edit_get_keybinding;
194   action->set_description = ags_accessible_notation_edit_set_description;
195   action->get_localized_name = ags_accessible_notation_edit_get_localized_name;
196 }
197 
198 void
ags_notation_edit_connectable_interface_init(AgsConnectableInterface * connectable)199 ags_notation_edit_connectable_interface_init(AgsConnectableInterface *connectable)
200 {
201   connectable->is_ready = NULL;
202   connectable->is_connected = NULL;
203   connectable->connect = ags_notation_edit_connect;
204   connectable->disconnect = ags_notation_edit_disconnect;
205 }
206 
207 void
ags_notation_edit_init(AgsNotationEdit * notation_edit)208 ags_notation_edit_init(AgsNotationEdit *notation_edit)
209 {
210   GtkStyleContext *style_context;
211 
212   GtkAdjustment *adjustment;
213 
214   AgsApplicationContext *application_context;
215 
216   gdouble gui_scale_factor;
217 
218   notation_edit->flags = (AGS_NOTATION_EDIT_SHOW_RULER |
219 			  AGS_NOTATION_EDIT_SHOW_VSCROLLBAR |
220 			  AGS_NOTATION_EDIT_SHOW_HSCROLLBAR);
221   notation_edit->mode = AGS_NOTATION_EDIT_NO_EDIT_MODE;
222 
223   notation_edit->button_mask = 0;
224   notation_edit->key_mask = 0;
225 
226   application_context = ags_application_context_get_instance();
227 
228   /* scale factor */
229   gui_scale_factor = ags_ui_provider_get_gui_scale_factor(AGS_UI_PROVIDER(application_context));
230 
231   notation_edit->note_offset = 0;
232   notation_edit->note_offset_absolute = 0;
233 
234   notation_edit->control_width = (guint) (gui_scale_factor * AGS_NOTATION_EDIT_DEFAULT_CONTROL_WIDTH);
235   notation_edit->control_height = (guint) (gui_scale_factor * AGS_NOTATION_EDIT_DEFAULT_CONTROL_HEIGHT);
236 
237   notation_edit->control_margin_x = AGS_NOTATION_EDIT_DEFAULT_CONTROL_MARGIN_X;
238   notation_edit->control_margin_y = AGS_NOTATION_EDIT_DEFAULT_CONTROL_MARGIN_Y;
239 
240   notation_edit->cursor_position_x = AGS_NOTATION_EDIT_DEFAULT_CURSOR_POSITION_X;
241   notation_edit->cursor_position_y = AGS_NOTATION_EDIT_DEFAULT_CURSOR_POSITION_Y;
242 
243   notation_edit->selected_note_border = AGS_NOTATION_EDIT_DEFAULT_SELECTED_NOTE_BORDER;
244 
245   notation_edit->selection_x0 = 0;
246   notation_edit->selection_x1 = 0;
247   notation_edit->selection_y0 = 0;
248   notation_edit->selection_y1 = 0;
249 
250   notation_edit->current_note = NULL;
251 
252   gtk_table_set_homogeneous(notation_edit,
253 			    FALSE);
254 
255   notation_edit->ruler = ags_ruler_new();
256   g_object_set(notation_edit->ruler,
257 	       "height-request", (gint) (gui_scale_factor * AGS_RULER_DEFAULT_HEIGHT),
258 	       "font-size",  (guint) (gui_scale_factor * notation_edit->ruler->font_size),
259 	       "step", (guint) (gui_scale_factor * AGS_RULER_DEFAULT_STEP),
260 	       "large-step", (guint) (gui_scale_factor * AGS_RULER_DEFAULT_LARGE_STEP),
261 	       "small-step", (guint) (gui_scale_factor * AGS_RULER_DEFAULT_SMALL_STEP),
262 	       NULL);
263   gtk_table_attach(GTK_TABLE(notation_edit),
264 		   (GtkWidget *) notation_edit->ruler,
265 		   0, 1,
266 		   0, 1,
267 		   GTK_FILL | GTK_EXPAND, GTK_FILL,
268 		   0, 0);
269 
270   notation_edit->drawing_area = (GtkDrawingArea *) gtk_drawing_area_new();
271   gtk_widget_set_has_window(notation_edit->drawing_area,
272 			    TRUE);
273   gtk_widget_set_events(GTK_WIDGET(notation_edit->drawing_area), GDK_EXPOSURE_MASK
274 			| GDK_LEAVE_NOTIFY_MASK
275 			| GDK_BUTTON_PRESS_MASK
276 			| GDK_BUTTON_RELEASE_MASK
277 			| GDK_POINTER_MOTION_MASK
278 			| GDK_POINTER_MOTION_HINT_MASK
279 			| GDK_CONTROL_MASK
280 			| GDK_KEY_PRESS_MASK
281 			| GDK_KEY_RELEASE_MASK);
282   gtk_widget_set_can_focus((GtkWidget *) notation_edit->drawing_area,
283 			   TRUE);
284 
285   gtk_table_attach(GTK_TABLE(notation_edit),
286 		   (GtkWidget *) notation_edit->drawing_area,
287 		   0, 1,
288 		   1, 2,
289 		   GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND,
290 		   0, 0);
291 
292   /* vscrollbar */
293   adjustment = (GtkAdjustment *) gtk_adjustment_new(0.0, 0.0, 1.0, 1.0, notation_edit->control_height, 1.0);
294   notation_edit->vscrollbar = (GtkVScrollbar *) gtk_vscrollbar_new(adjustment);
295   g_object_set(notation_edit->vscrollbar,
296 	       "no-show-all", TRUE,
297 	       NULL);
298   gtk_table_attach(GTK_TABLE(notation_edit),
299 		   (GtkWidget *) notation_edit->vscrollbar,
300 		   1, 2,
301 		   1, 2,
302 		   GTK_FILL, GTK_FILL,
303 		   0, 0);
304 
305   /* hscrollbar */
306   adjustment = (GtkAdjustment *) gtk_adjustment_new(0.0, 0.0, 1.0, 1.0, (gdouble) notation_edit->control_width, 1.0);
307   notation_edit->hscrollbar = (GtkHScrollbar *) gtk_hscrollbar_new(adjustment);
308   g_object_set(notation_edit->hscrollbar,
309 	       "no-show-all", TRUE,
310 	       NULL);
311   gtk_table_attach(GTK_TABLE(notation_edit),
312 		   (GtkWidget *) notation_edit->hscrollbar,
313 		   0, 1,
314 		   2, 3,
315 		   GTK_FILL, GTK_FILL,
316 		   0, 0);
317 
318   /* style context */
319   style_context = gtk_widget_get_style_context(notation_edit);
320   gtk_style_context_add_class(style_context,
321 			      "editor");
322 
323   /* auto-scroll */
324   if(ags_notation_edit_auto_scroll == NULL){
325     ags_notation_edit_auto_scroll = g_hash_table_new_full(g_direct_hash, g_direct_equal,
326 							  NULL,
327 							  NULL);
328   }
329 
330   g_hash_table_insert(ags_notation_edit_auto_scroll,
331 		      notation_edit, ags_notation_edit_auto_scroll_timeout);
332   g_timeout_add(1000 / 30, (GSourceFunc) ags_notation_edit_auto_scroll_timeout, (gpointer) notation_edit);
333 }
334 
335 void
ags_notation_edit_finalize(GObject * gobject)336 ags_notation_edit_finalize(GObject *gobject)
337 {
338   AgsNotationEdit *notation_edit;
339 
340   notation_edit = AGS_NOTATION_EDIT(gobject);
341 
342   /* remove auto scroll */
343   g_hash_table_remove(ags_notation_edit_auto_scroll,
344 		      notation_edit);
345 
346   /* call parent */
347   G_OBJECT_CLASS(ags_notation_edit_parent_class)->finalize(gobject);
348 }
349 
350 AtkObject*
ags_notation_edit_get_accessible(GtkWidget * widget)351 ags_notation_edit_get_accessible(GtkWidget *widget)
352 {
353   AtkObject* accessible;
354 
355   accessible = g_object_get_qdata(G_OBJECT(widget),
356 				  quark_accessible_object);
357 
358   if(!accessible){
359     accessible = g_object_new(ags_accessible_notation_edit_get_type(),
360 			      NULL);
361 
362     g_object_set_qdata(G_OBJECT(widget),
363 		       quark_accessible_object,
364 		       accessible);
365     gtk_accessible_set_widget(GTK_ACCESSIBLE(accessible),
366 			      widget);
367   }
368 
369   return(accessible);
370 }
371 
372 void
ags_notation_edit_connect(AgsConnectable * connectable)373 ags_notation_edit_connect(AgsConnectable *connectable)
374 {
375   AgsNotationEdit *notation_edit;
376 
377   notation_edit = AGS_NOTATION_EDIT(connectable);
378 
379   if((AGS_NOTATION_EDIT_CONNECTED & (notation_edit->flags)) != 0){
380     return;
381   }
382 
383   notation_edit->flags |= AGS_NOTATION_EDIT_CONNECTED;
384 
385   /* drawing area */
386   g_signal_connect(G_OBJECT(notation_edit->drawing_area), "draw",
387 		   G_CALLBACK(ags_notation_edit_draw_callback), (gpointer) notation_edit);
388 
389   g_signal_connect_after((GObject *) notation_edit->drawing_area, "configure_event",
390 			 G_CALLBACK(ags_notation_edit_drawing_area_configure_event), (gpointer) notation_edit);
391 
392   g_signal_connect((GObject *) notation_edit->drawing_area, "button_press_event",
393 		   G_CALLBACK(ags_notation_edit_drawing_area_button_press_event), (gpointer) notation_edit);
394 
395   g_signal_connect((GObject *) notation_edit->drawing_area, "button_release_event",
396 		   G_CALLBACK(ags_notation_edit_drawing_area_button_release_event), (gpointer) notation_edit);
397 
398   g_signal_connect((GObject *) notation_edit->drawing_area, "motion_notify_event",
399 		   G_CALLBACK(ags_notation_edit_drawing_area_motion_notify_event), (gpointer) notation_edit);
400 
401   g_signal_connect((GObject *) notation_edit->drawing_area, "key_press_event",
402 		   G_CALLBACK(ags_notation_edit_drawing_area_key_press_event), (gpointer) notation_edit);
403 
404   g_signal_connect((GObject *) notation_edit->drawing_area, "key_release_event",
405 		   G_CALLBACK(ags_notation_edit_drawing_area_key_release_event), (gpointer) notation_edit);
406 
407   /* scrollbars */
408   g_signal_connect_after((GObject *) notation_edit->vscrollbar, "value-changed",
409 			 G_CALLBACK(ags_notation_edit_vscrollbar_value_changed), (gpointer) notation_edit);
410 
411   g_signal_connect_after((GObject *) notation_edit->hscrollbar, "value-changed",
412 			 G_CALLBACK(ags_notation_edit_hscrollbar_value_changed), (gpointer) notation_edit);
413 }
414 
415 void
ags_notation_edit_disconnect(AgsConnectable * connectable)416 ags_notation_edit_disconnect(AgsConnectable *connectable)
417 {
418   AgsNotationEdit *notation_edit;
419 
420   notation_edit = AGS_NOTATION_EDIT(connectable);
421 
422   if((AGS_NOTATION_EDIT_CONNECTED & (notation_edit->flags)) == 0){
423     return;
424   }
425 
426   notation_edit->flags &= (~AGS_NOTATION_EDIT_CONNECTED);
427 
428   /* drawing area */
429   g_object_disconnect(notation_edit->drawing_area,
430 		      "any_signal::draw",
431 		      G_CALLBACK(ags_notation_edit_draw_callback),
432 		      (gpointer) notation_edit,
433 		      "any_signal::configure_event",
434 		      G_CALLBACK(ags_notation_edit_drawing_area_configure_event),
435 		      (gpointer) notation_edit,
436 		      "any_signal::button_press_event",
437 		      G_CALLBACK(ags_notation_edit_drawing_area_button_press_event),
438 		      (gpointer) notation_edit,
439 		      "any_signal::button_release_event",
440 		      G_CALLBACK(ags_notation_edit_drawing_area_button_release_event),
441 		      (gpointer) notation_edit,
442 		      "any_signal::motion_notify_event",
443 		      G_CALLBACK(ags_notation_edit_drawing_area_motion_notify_event),
444 		      notation_edit,
445 		      "any_signal::key_press_event",
446 		      G_CALLBACK(ags_notation_edit_drawing_area_key_press_event),
447 		      (gpointer) notation_edit,
448 		      "any_signal::key_release_event",
449 		      G_CALLBACK(ags_notation_edit_drawing_area_key_release_event),
450 		      (gpointer) notation_edit,
451 		      NULL);
452 
453   /* scrollbars */
454   g_object_disconnect(notation_edit->vscrollbar,
455 		      "any_signal::value-changed",
456 		      G_CALLBACK(ags_notation_edit_vscrollbar_value_changed),
457 		      (gpointer) notation_edit,
458 		      NULL);
459 
460   g_object_disconnect(notation_edit->hscrollbar,
461 		      "any_signal::value-changed",
462 		      G_CALLBACK(ags_notation_edit_hscrollbar_value_changed),
463 		      (gpointer) notation_edit,
464 		      NULL);
465 }
466 
467 gboolean
ags_accessible_notation_edit_do_action(AtkAction * action,gint i)468 ags_accessible_notation_edit_do_action(AtkAction *action,
469 				       gint i)
470 {
471   AgsNotationEdit *notation_edit;
472 
473   GdkEventKey *key_press, *key_release;
474   GdkEventKey *modifier_press, *modifier_release;
475   GdkEventKey *second_level_press, *second_level_release;
476 
477   if(!(i >= 0 && i < 13)){
478     return(FALSE);
479   }
480 
481   notation_edit = (AgsNotationEdit *) gtk_accessible_get_widget(GTK_ACCESSIBLE(action));
482 
483   key_press = (GdkEventKey *) gdk_event_new(GDK_KEY_PRESS);
484   key_release = (GdkEventKey *) gdk_event_new(GDK_KEY_RELEASE);
485 
486   /* create modifier */
487   modifier_press = (GdkEventKey *) gdk_event_new(GDK_KEY_PRESS);
488   modifier_release = (GdkEventKey *) gdk_event_new(GDK_KEY_RELEASE);
489 
490   modifier_press->keyval =
491     modifier_release->keyval = GDK_KEY_Control_R;
492 
493   /* create second level */
494   second_level_press = (GdkEventKey *) gdk_event_new(GDK_KEY_PRESS);
495   second_level_release = (GdkEventKey *) gdk_event_new(GDK_KEY_RELEASE);
496 
497   second_level_press->keyval =
498     second_level_release->keyval = GDK_KEY_Shift_R;
499 
500   switch(i){
501   case 0:
502     {
503       key_press->keyval =
504 	key_release->keyval = GDK_KEY_Left;
505 
506       /* send event */
507       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
508 		       (GdkEvent *) key_press);
509       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
510 		       (GdkEvent *) key_release);
511     }
512     break;
513   case 1:
514     {
515       key_press->keyval =
516 	key_release->keyval = GDK_KEY_Right;
517 
518       /* send event */
519       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
520 		       (GdkEvent *) key_press);
521       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
522 		       (GdkEvent *) key_release);
523     }
524     break;
525   case 2:
526     {
527       key_press->keyval =
528 	key_release->keyval = GDK_KEY_Up;
529 
530       /* send event */
531       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
532 		       (GdkEvent *) key_press);
533       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
534 		       (GdkEvent *) key_release);
535     }
536     break;
537   case 3:
538     {
539       key_press->keyval =
540 	key_release->keyval = GDK_KEY_Down;
541 
542       /* send event */
543       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
544 		       (GdkEvent *) key_press);
545       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
546 		       (GdkEvent *) key_release);
547     }
548     break;
549   case 4:
550     {
551       key_press->keyval =
552 	key_release->keyval = GDK_KEY_space;
553 
554       /* send event */
555       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
556 		       (GdkEvent *) key_press);
557       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
558 		       (GdkEvent *) key_release);
559     }
560     break;
561   case 5:
562     {
563       key_press->keyval =
564 	key_release->keyval = GDK_KEY_Left;
565 
566       /* send event */
567       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
568 		       (GdkEvent *) second_level_press);
569       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
570 		       (GdkEvent *) key_press);
571       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
572 		       (GdkEvent *) key_release);
573       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
574 		       (GdkEvent *) second_level_release);
575     }
576     break;
577   case 6:
578     {
579       key_press->keyval =
580 	key_release->keyval = GDK_KEY_Right;
581 
582       /* send event */
583       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
584 		       (GdkEvent *) second_level_press);
585       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
586 		       (GdkEvent *) key_press);
587       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
588 		       (GdkEvent *) key_release);
589       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
590 		       (GdkEvent *) second_level_release);
591     }
592     break;
593   case 7:
594     {
595       key_press->keyval =
596 	key_release->keyval = GDK_KEY_Delete;
597 
598       /* send event */
599       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
600 		       (GdkEvent *) key_press);
601       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
602 		       (GdkEvent *) key_release);
603     }
604     break;
605   case 8:
606     {
607       key_press->keyval =
608 	key_release->keyval = GDK_KEY_c;
609 
610       /* send event */
611       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
612 		       (GdkEvent *) modifier_press);
613       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
614 		       (GdkEvent *) key_press);
615       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
616 		       (GdkEvent *) key_release);
617       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
618 		       (GdkEvent *) modifier_release);
619     }
620     break;
621   case 9:
622     {
623       key_press->keyval =
624 	key_release->keyval = GDK_KEY_x;
625 
626       /* send event */
627       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
628 		       (GdkEvent *) modifier_press);
629       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
630 		       (GdkEvent *) key_press);
631       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
632 		       (GdkEvent *) key_release);
633       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
634 		       (GdkEvent *) modifier_release);
635     }
636     break;
637   case 10:
638     {
639       key_press->keyval =
640 	key_release->keyval = GDK_KEY_v;
641 
642       /* send event */
643       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
644 		       (GdkEvent *) modifier_press);
645       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
646 		       (GdkEvent *) key_press);
647       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
648 		       (GdkEvent *) key_release);
649       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
650 		       (GdkEvent *) modifier_release);
651     }
652     break;
653   case 11:
654     {
655       key_press->keyval =
656 	key_release->keyval = GDK_KEY_a;
657 
658       /* send event */
659       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
660 		       (GdkEvent *) modifier_press);
661       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
662 		       (GdkEvent *) key_press);
663       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
664 		       (GdkEvent *) key_release);
665       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
666 		       (GdkEvent *) modifier_release);
667     }
668     break;
669   case 12:
670     {
671       key_press->keyval =
672 	key_release->keyval = GDK_KEY_i;
673 
674       /* send event */
675       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
676 		       (GdkEvent *) modifier_press);
677       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
678 		       (GdkEvent *) key_press);
679       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
680 		       (GdkEvent *) key_release);
681       gtk_widget_event((GtkWidget *) notation_edit->drawing_area,
682 		       (GdkEvent *) modifier_release);
683     }
684     break;
685   }
686 
687   return(TRUE);
688 }
689 
690 gint
ags_accessible_notation_edit_get_n_actions(AtkAction * action)691 ags_accessible_notation_edit_get_n_actions(AtkAction *action)
692 {
693   return(13);
694 }
695 
696 const gchar*
ags_accessible_notation_edit_get_description(AtkAction * action,gint i)697 ags_accessible_notation_edit_get_description(AtkAction *action,
698 					     gint i)
699 {
700   static const gchar *actions[] = {
701     "move cursor left",
702     "move cursor right",
703     "move cursor up",
704     "move cursor down",
705     "add audio note",
706     "shrink audio note",
707     "grow audio note",
708     "remove audio note",
709     "copy note to clipboard",
710     "cut note to clipboard",
711     "paste note from clipboard",
712     "select all note",
713     "invert note",
714   };
715 
716   if(i >= 0 && i < 13){
717     return(actions[i]);
718   }else{
719     return(NULL);
720   }
721 }
722 
723 const gchar*
ags_accessible_notation_edit_get_name(AtkAction * action,gint i)724 ags_accessible_notation_edit_get_name(AtkAction *action,
725 				      gint i)
726 {
727   static const gchar *actions[] = {
728     "left",
729     "right",
730     "up",
731     "down",
732     "add",
733     "shrink",
734     "grow",
735     "remove",
736     "copy",
737     "cut",
738     "paste",
739     "select-all",
740     "invert",
741   };
742 
743   if(i >= 0 && i < 13){
744     return(actions[i]);
745   }else{
746     return(NULL);
747   }
748 }
749 
750 const gchar*
ags_accessible_notation_edit_get_keybinding(AtkAction * action,gint i)751 ags_accessible_notation_edit_get_keybinding(AtkAction *action,
752 					    gint i)
753 {
754   static const gchar *actions[] = {
755     "left",
756     "right",
757     "up",
758     "down",
759     "space",
760     "Shft+Left",
761     "Shft+Right",
762     "Del"
763     "Ctrl+c"
764     "Ctrl+x",
765     "Ctrl+v",
766     "Ctrl+a",
767     "Ctrl+i",
768   };
769 
770   if(i >= 0 && i < 13){
771     return(actions[i]);
772   }else{
773     return(NULL);
774   }
775 }
776 
777 gboolean
ags_accessible_notation_edit_set_description(AtkAction * action,gint i)778 ags_accessible_notation_edit_set_description(AtkAction *action,
779 					     gint i)
780 {
781   //TODO:JK: implement me
782 
783   return(FALSE);
784 }
785 
786 gchar*
ags_accessible_notation_edit_get_localized_name(AtkAction * action,gint i)787 ags_accessible_notation_edit_get_localized_name(AtkAction *action,
788 						gint i)
789 {
790   //TODO:JK: implement me
791 
792   return(NULL);
793 }
794 
795 void
ags_notation_edit_show(GtkWidget * widget)796 ags_notation_edit_show(GtkWidget *widget)
797 {
798   AgsNotationEdit *notation_edit;
799 
800   notation_edit = AGS_NOTATION_EDIT(widget);
801 
802   /* call parent */
803   GTK_WIDGET_CLASS(ags_notation_edit_parent_class)->show(widget);
804 
805   if((AGS_NOTATION_EDIT_SHOW_RULER & (notation_edit->flags)) != 0){
806     gtk_widget_show((GtkWidget *) notation_edit->ruler);
807   }
808 
809   if((AGS_NOTATION_EDIT_SHOW_VSCROLLBAR & (notation_edit->flags)) != 0){
810     gtk_widget_show((GtkWidget *) notation_edit->vscrollbar);
811   }
812 
813   if((AGS_NOTATION_EDIT_SHOW_HSCROLLBAR & (notation_edit->flags)) != 0){
814     gtk_widget_show((GtkWidget *) notation_edit->hscrollbar);
815   }
816 
817   ags_notation_edit_reset_vscrollbar(notation_edit);
818   ags_notation_edit_reset_hscrollbar(notation_edit);
819 }
820 
821 void
ags_notation_edit_show_all(GtkWidget * widget)822 ags_notation_edit_show_all(GtkWidget *widget)
823 {
824   AgsNotationEdit *notation_edit;
825 
826   notation_edit = AGS_NOTATION_EDIT(widget);
827 
828   /* call parent */
829   GTK_WIDGET_CLASS(ags_notation_edit_parent_class)->show_all(widget);
830 
831   if((AGS_NOTATION_EDIT_SHOW_RULER & (notation_edit->flags)) != 0){
832     gtk_widget_show((GtkWidget *) notation_edit->ruler);
833   }
834 
835   if((AGS_NOTATION_EDIT_SHOW_VSCROLLBAR & (notation_edit->flags)) != 0){
836     gtk_widget_show((GtkWidget *) notation_edit->vscrollbar);
837   }
838 
839   if((AGS_NOTATION_EDIT_SHOW_HSCROLLBAR & (notation_edit->flags)) != 0){
840     gtk_widget_show((GtkWidget *) notation_edit->hscrollbar);
841   }
842 
843   ags_notation_edit_reset_vscrollbar(notation_edit);
844   ags_notation_edit_reset_hscrollbar(notation_edit);
845 }
846 
847 gboolean
ags_notation_edit_auto_scroll_timeout(GtkWidget * widget)848 ags_notation_edit_auto_scroll_timeout(GtkWidget *widget)
849 {
850   if(g_hash_table_lookup(ags_notation_edit_auto_scroll,
851 			 widget) != NULL){
852     AgsNotationEditor *notation_editor;
853     AgsNotationEdit *notation_edit;
854 
855     GtkAdjustment *hscrollbar_adjustment;
856 
857     GObject *output_soundcard;
858 
859     double x;
860 
861     notation_edit = AGS_NOTATION_EDIT(widget);
862 
863     if((AGS_NOTATION_EDIT_AUTO_SCROLL & (notation_edit->flags)) == 0){
864       return(TRUE);
865     }
866 
867     notation_editor = (AgsNotationEditor *) gtk_widget_get_ancestor((GtkWidget *) notation_edit,
868 								    AGS_TYPE_NOTATION_EDITOR);
869 
870     if(notation_editor->selected_machine == NULL){
871       return(TRUE);
872     }
873 
874     /* reset offset */
875     g_object_get(notation_editor->selected_machine->audio,
876 		 "output-soundcard", &output_soundcard,
877 		 NULL);
878 
879     notation_edit->note_offset = ags_soundcard_get_note_offset(AGS_SOUNDCARD(output_soundcard));
880     notation_edit->note_offset_absolute = ags_soundcard_get_note_offset_absolute(AGS_SOUNDCARD(output_soundcard));
881 
882     /* reset scrollbar */
883     hscrollbar_adjustment = gtk_range_get_adjustment(GTK_RANGE(notation_edit->hscrollbar));
884     x = ((notation_edit->note_offset * notation_edit->control_width) / (AGS_NOTATION_EDITOR_MAX_CONTROLS * notation_edit->control_width)) * gtk_adjustment_get_upper(hscrollbar_adjustment);
885 
886     gtk_range_set_value(GTK_RANGE(notation_edit->hscrollbar),
887 			x);
888 
889     g_object_unref(output_soundcard);
890 
891     return(TRUE);
892   }else{
893     return(FALSE);
894   }
895 }
896 
897 void
ags_notation_edit_reset_vscrollbar(AgsNotationEdit * notation_edit)898 ags_notation_edit_reset_vscrollbar(AgsNotationEdit *notation_edit)
899 {
900   AgsNotationEditor *notation_editor;
901 
902   GtkAdjustment *adjustment;
903   GtkAdjustment *piano_adjustment;
904 
905   GtkAllocation allocation;
906 
907   guint channel_count;
908   double varea_height;
909   gdouble upper, old_upper;
910 
911   if(!AGS_IS_NOTATION_EDIT(notation_edit)){
912     return;
913   }
914 
915   notation_editor = (AgsNotationEditor *) gtk_widget_get_ancestor((GtkWidget *) notation_edit,
916 								  AGS_TYPE_NOTATION_EDITOR);
917 
918   /* fix margin-bottom */
919   gtk_widget_get_allocation(notation_editor->notation_edit->hscrollbar, &allocation);
920 
921   g_object_set(notation_editor->scrolled_piano,
922 	       "margin-bottom", (gint) allocation.height,
923 	       NULL);
924 
925   if(notation_editor->selected_machine == NULL){
926     return;
927   }
928 
929   /* */
930   gtk_widget_get_allocation(GTK_WIDGET(notation_edit->drawing_area),
931 			    &allocation);
932 
933   /* adjustment */
934   adjustment = gtk_range_get_adjustment(GTK_RANGE(notation_edit->vscrollbar));
935 
936   g_object_get(notation_editor->scrolled_piano->viewport,
937 	       "vadjustment", &piano_adjustment,
938 	       NULL);
939 
940   /* get channel count */
941 #if 0
942   if(ags_audio_test_flags(notation_editor->selected_machine->audio, AGS_AUDIO_NOTATION_DEFAULT)){
943     g_object_get(notation_editor->selected_machine->audio,
944 		 "input-pads", &channel_count,
945 		 NULL);
946     channel_count = notation_editor->selected_machine->audio->input_pads;
947   }else{
948     g_object_get(notation_editor->selected_machine->audio,
949 		 "output-pads", &channel_count,
950 		 NULL);
951   }
952 #else
953   g_object_get(notation_editor->selected_machine->audio,
954 	       "input-pads", &channel_count,
955 	       NULL);
956 #endif
957 
958   /* upper */
959   old_upper = gtk_adjustment_get_upper(adjustment);
960 
961   varea_height = (channel_count * notation_edit->control_height);
962   upper = varea_height - allocation.height;
963 
964   if(upper < 0.0){
965     upper = 0.0;
966   }
967 
968   gtk_adjustment_set_upper(adjustment,
969 			   upper);
970 
971   /* piano - upper */
972   gtk_adjustment_set_lower(piano_adjustment,
973 			   gtk_adjustment_get_lower(adjustment));
974   gtk_adjustment_set_step_increment(piano_adjustment,
975 				    gtk_adjustment_get_step_increment(adjustment));
976   gtk_adjustment_set_page_increment(piano_adjustment,
977 				    gtk_adjustment_get_page_increment(adjustment));
978   gtk_adjustment_set_page_size(piano_adjustment,
979 			       gtk_adjustment_get_page_size(adjustment));
980   gtk_adjustment_set_upper(piano_adjustment,
981 			   gtk_adjustment_get_upper(adjustment));
982 
983   /* reset value */
984   if(old_upper != 0.0){
985     gtk_adjustment_set_value(adjustment,
986 			     gtk_adjustment_get_value(adjustment) / old_upper * upper);
987 
988     gtk_adjustment_set_value(piano_adjustment,
989 			     gtk_adjustment_get_value(adjustment));
990   }
991 }
992 
993 void
ags_notation_edit_reset_hscrollbar(AgsNotationEdit * notation_edit)994 ags_notation_edit_reset_hscrollbar(AgsNotationEdit *notation_edit)
995 {
996   AgsNotationEditor *notation_editor;
997   AgsNotationToolbar *notation_toolbar;
998 
999   GtkAdjustment *adjustment;
1000 
1001   AgsApplicationContext *application_context;
1002 
1003   GtkAllocation allocation;
1004 
1005   gdouble gui_scale_factor;
1006   double zoom_factor, zoom;
1007   double zoom_correction;
1008   guint map_width;
1009   gdouble upper, old_upper;
1010 
1011   if(!AGS_IS_NOTATION_EDIT(notation_edit)){
1012     return;
1013   }
1014 
1015   notation_editor = (AgsNotationEditor *) gtk_widget_get_ancestor((GtkWidget *) notation_edit,
1016 								  AGS_TYPE_NOTATION_EDITOR);
1017 
1018   if(notation_editor->selected_machine == NULL){
1019     return;
1020   }
1021 
1022   application_context = ags_application_context_get_instance();
1023 
1024   /* scale factor */
1025   gui_scale_factor = ags_ui_provider_get_gui_scale_factor(AGS_UI_PROVIDER(application_context));
1026 
1027   notation_toolbar = notation_editor->notation_toolbar;
1028 
1029   gtk_widget_get_allocation(GTK_WIDGET(notation_edit->drawing_area),
1030 			    &allocation);
1031 
1032   /* adjustment */
1033   adjustment = gtk_range_get_adjustment(GTK_RANGE(notation_edit->hscrollbar));
1034 
1035   /* zoom */
1036   zoom_factor = exp2(6.0 - (double) gtk_combo_box_get_active((GtkComboBox *) notation_toolbar->zoom));
1037   zoom = exp2((double) gtk_combo_box_get_active((GtkComboBox *) notation_toolbar->zoom) - 2.0);
1038 
1039   /* upper */
1040   old_upper = gtk_adjustment_get_upper(adjustment);
1041 
1042   zoom_correction = 1.0 / 16;
1043 
1044   map_width = ((64.0) * (16.0 * 16.0 * 1200.0) * zoom * zoom_correction);
1045   upper = map_width - allocation.width;
1046 
1047   if(upper < 0.0){
1048     upper = 0.0;
1049   }
1050 
1051   gtk_adjustment_set_upper(adjustment,
1052 			   upper);
1053 
1054   /* ruler */
1055   notation_edit->ruler->factor = zoom_factor;
1056   notation_edit->ruler->precision = zoom;
1057   notation_edit->ruler->scale_precision = 1.0 / zoom;
1058 
1059   gtk_adjustment_set_upper(notation_edit->ruler->adjustment,
1060 			   upper);
1061 
1062   /* reset value */
1063   if(old_upper != 0.0){
1064 #if 0
1065     gtk_adjustment_set_value(adjustment,
1066 			     gtk_adjustment_get_value(adjustment) / old_upper * upper);
1067 #endif
1068   }
1069 }
1070 
1071 void
ags_notation_edit_draw_segment(AgsNotationEdit * notation_edit,cairo_t * cr)1072 ags_notation_edit_draw_segment(AgsNotationEdit *notation_edit, cairo_t *cr)
1073 {
1074   AgsNotationEditor *notation_editor;
1075   AgsNotationToolbar *notation_toolbar;
1076 
1077   GtkStyleContext *notation_edit_style_context;
1078 
1079   GtkAdjustment *vscrollbar_adjustment;
1080   GtkAdjustment *hscrollbar_adjustment;
1081 
1082   GtkAllocation allocation;
1083 
1084   GdkRGBA *fg_color;
1085   GdkRGBA *bg_color;
1086   GdkRGBA *border_color;
1087 
1088   guint channel_count;
1089   guint width, height;
1090   gboolean width_fits, height_fits;
1091   double zoom;
1092   guint y0, x0;
1093   guint nth_x;
1094   guint i, j;
1095   guint j_set;
1096 
1097   GValue value = {0,};
1098 
1099   const static double segment_dashes = {
1100     0.5,
1101   };
1102 
1103   if(!AGS_IS_NOTATION_EDIT(notation_edit)){
1104     return;
1105   }
1106 
1107   notation_editor = (AgsNotationEditor *) gtk_widget_get_ancestor((GtkWidget *) notation_edit,
1108 								  AGS_TYPE_NOTATION_EDITOR);
1109 
1110   if(notation_editor->selected_machine == NULL){
1111     return;
1112   }
1113 
1114   notation_toolbar = notation_editor->notation_toolbar;
1115 
1116   gtk_widget_get_allocation(GTK_WIDGET(notation_edit->drawing_area),
1117 			    &allocation);
1118 
1119   /* style context */
1120   notation_edit_style_context = gtk_widget_get_style_context(GTK_WIDGET(notation_edit->drawing_area));
1121 
1122   gtk_style_context_get_property(notation_edit_style_context,
1123 				 "color",
1124 				 GTK_STATE_FLAG_NORMAL,
1125 				 &value);
1126 
1127   fg_color = g_value_dup_boxed(&value);
1128   g_value_unset(&value);
1129 
1130   gtk_style_context_get_property(notation_edit_style_context,
1131 				 "background-color",
1132 				 GTK_STATE_FLAG_NORMAL,
1133 				 &value);
1134 
1135   bg_color = g_value_dup_boxed(&value);
1136   g_value_unset(&value);
1137 
1138   gtk_style_context_get_property(notation_edit_style_context,
1139 				 "border-color",
1140 				 GTK_STATE_FLAG_NORMAL,
1141 				 &value);
1142 
1143   border_color = g_value_dup_boxed(&value);
1144   g_value_unset(&value);
1145 
1146   /* adjustment */
1147   vscrollbar_adjustment = gtk_range_get_adjustment(GTK_RANGE(notation_edit->vscrollbar));
1148   hscrollbar_adjustment = gtk_range_get_adjustment(GTK_RANGE(notation_edit->hscrollbar));
1149 
1150   /* get channel count */
1151 #if 0
1152   if(ags_audio_test_flags(notation_editor->selected_machine->audio, AGS_AUDIO_NOTATION_DEFAULT)){
1153     g_object_get(notation_editor->selected_machine->audio,
1154 		 "input-pads", &channel_count,
1155 		 NULL);
1156     channel_count = notation_editor->selected_machine->audio->input_pads;
1157   }else{
1158     g_object_get(notation_editor->selected_machine->audio,
1159 		 "output-pads", &channel_count,
1160 		 NULL);
1161   }
1162 #else
1163   g_object_get(notation_editor->selected_machine->audio,
1164 	       "input-pads", &channel_count,
1165 	       NULL);
1166 #endif
1167 
1168   /* get width */
1169   width = allocation.width;
1170   width_fits = FALSE;
1171 
1172   if(AGS_NOTATION_EDITOR_MAX_CONTROLS * notation_edit->control_width < width){
1173     width = AGS_NOTATION_EDITOR_MAX_CONTROLS * notation_edit->control_width;
1174     width_fits = TRUE;
1175   }
1176 
1177   /* get height */
1178   height = allocation.height;
1179   height_fits = FALSE;
1180 
1181   if(channel_count * notation_edit->control_height < height){
1182     height = channel_count * notation_edit->control_height;
1183     height_fits = TRUE;
1184   }
1185 
1186   /* zoom */
1187   zoom = exp2((double) gtk_combo_box_get_active((GtkComboBox *) notation_toolbar->zoom) - 2.0);
1188 
1189   /*  */
1190   if(width_fits){
1191     x0 = 0;
1192   }else{
1193     x0 = notation_edit->control_width - ((guint) gtk_adjustment_get_value(hscrollbar_adjustment) % notation_edit->control_width);
1194   }
1195 
1196   if(height_fits){
1197     y0 = 0;
1198   }else{
1199     y0 = notation_edit->control_height - ((guint) gtk_adjustment_get_value(vscrollbar_adjustment) % notation_edit->control_height);
1200   }
1201 
1202   nth_x = (guint) floor(gtk_adjustment_get_value(hscrollbar_adjustment) / notation_edit->control_width);
1203   nth_x += 1;
1204 
1205   /* push group */
1206   cairo_push_group(cr);
1207 
1208   /* clear with background color */
1209   cairo_set_source_rgba(cr,
1210 			bg_color->red,
1211 			bg_color->green,
1212 			bg_color->blue,
1213 			bg_color->alpha);
1214   cairo_rectangle(cr,
1215 		  0.0, 0.0,
1216 		  (double) allocation.width, (double) allocation.height);
1217   cairo_fill(cr);
1218 
1219   /* horizontal lines */
1220   cairo_set_line_width(cr,
1221 		       1.0);
1222 
1223   cairo_set_source_rgba(cr,
1224 			fg_color->red,
1225 			fg_color->blue,
1226 			fg_color->green,
1227 			fg_color->alpha);
1228 
1229   for(i = y0 ; i < height; ){
1230     cairo_move_to(cr,
1231 		  0.0, (double) i);
1232     cairo_line_to(cr,
1233 		  (double) width, (double) i);
1234     cairo_stroke(cr);
1235 
1236     i += notation_edit->control_height;
1237   }
1238 
1239   if(height_fits){
1240     cairo_move_to(cr,
1241 		  0.0, (double) i);
1242     cairo_line_to(cr,
1243 		  (double) width, (double) i);
1244     cairo_stroke(cr);
1245   }
1246 
1247   /* vertical lines */
1248   cairo_set_source_rgba(cr,
1249 			fg_color->red,
1250 			fg_color->blue,
1251 			fg_color->green,
1252 			fg_color->alpha);
1253 
1254   i = x0;
1255 
1256   if(i < width &&
1257      zoom > 1.0 ){
1258     j_set = nth_x % ((guint) zoom);
1259 
1260     /* thin lines */
1261     cairo_set_dash(cr,
1262 		   &segment_dashes,
1263 		   1,
1264 		   0.0);
1265 
1266     if(j_set != 0){
1267       j = j_set;
1268       goto ags_notation_edit_draw_segment0;
1269     }
1270   }
1271 
1272   for(; i < width; ){
1273     /* strong lines */
1274     cairo_set_dash(cr,
1275 		   NULL,
1276 		   0,
1277 		   0.0);
1278 
1279     cairo_move_to(cr,
1280 		  (double) i, 0.0);
1281     cairo_line_to(cr,
1282 		  (double) i, (double) height);
1283     cairo_stroke(cr);
1284 
1285     i += notation_edit->control_width;
1286 
1287     /* thin lines */
1288     cairo_set_dash(cr,
1289 		   &segment_dashes,
1290 		   1,
1291 		   0.0);
1292 
1293     for(j = 1; i < width && j < zoom; j++){
1294     ags_notation_edit_draw_segment0:
1295       cairo_move_to(cr, (double) i, 0.0);
1296       cairo_line_to(cr, (double) i, (double) height);
1297       cairo_stroke(cr);
1298 
1299       i += notation_edit->control_width;
1300     }
1301   }
1302 
1303   /* complete */
1304   cairo_pop_group_to_source(cr);
1305   cairo_paint(cr);
1306 
1307 //  cairo_surface_mark_dirty(cairo_get_target(cr));
1308 
1309   g_boxed_free(GDK_TYPE_RGBA, fg_color);
1310   g_boxed_free(GDK_TYPE_RGBA, bg_color);
1311   g_boxed_free(GDK_TYPE_RGBA, border_color);
1312 }
1313 
1314 void
ags_notation_edit_draw_position(AgsNotationEdit * notation_edit,cairo_t * cr)1315 ags_notation_edit_draw_position(AgsNotationEdit *notation_edit, cairo_t *cr)
1316 {
1317   AgsNotationEditor *notation_editor;
1318 
1319   GtkStyleContext *notation_edit_style_context;
1320 
1321   GtkAllocation allocation;
1322 
1323   GdkRGBA *fg_color_active;
1324 
1325   guint channel_count;
1326   double position;
1327   double x, y;
1328   double width, height;
1329   gboolean height_fits;
1330 
1331   GValue value = {0,};
1332 
1333   if(!AGS_IS_NOTATION_EDIT(notation_edit)){
1334     return;
1335   }
1336 
1337   notation_editor = (AgsNotationEditor *) gtk_widget_get_ancestor((GtkWidget *) notation_edit,
1338 								  AGS_TYPE_NOTATION_EDITOR);
1339 
1340   if(notation_editor->selected_machine == NULL){
1341     return;
1342   }
1343 
1344   gtk_widget_get_allocation(GTK_WIDGET(notation_edit->drawing_area),
1345 			    &allocation);
1346 
1347   /* style context */
1348   notation_edit_style_context = gtk_widget_get_style_context(GTK_WIDGET(notation_edit->drawing_area));
1349 
1350   gtk_style_context_get_property(notation_edit_style_context,
1351 				 "color",
1352 				 GTK_STATE_FLAG_ACTIVE,
1353 				 &value);
1354 
1355   fg_color_active = g_value_dup_boxed(&value);
1356   g_value_unset(&value);
1357 
1358   /* get channel count */
1359 #if 0
1360   if(ags_audio_test_flags(notation_editor->selected_machine->audio, AGS_AUDIO_NOTATION_DEFAULT)){
1361     g_object_get(notation_editor->selected_machine->audio,
1362 		 "input-pads", &channel_count,
1363 		 NULL);
1364     channel_count = notation_editor->selected_machine->audio->input_pads;
1365   }else{
1366     g_object_get(notation_editor->selected_machine->audio,
1367 		 "output-pads", &channel_count,
1368 		 NULL);
1369   }
1370 #else
1371   g_object_get(notation_editor->selected_machine->audio,
1372 	       "input-pads", &channel_count,
1373 	       NULL);
1374 #endif
1375 
1376   /* get offset and dimensions */
1377   position = ((double) notation_edit->note_offset) * ((double) notation_edit->control_width);
1378 
1379   y = 0.0;
1380   x = (position) - (gtk_range_get_value(GTK_RANGE(notation_edit->hscrollbar)));
1381 
1382   height = (double) allocation.height;
1383   width = (double) AGS_NOTATION_EDIT_DEFAULT_FADER_WIDTH;
1384 
1385   if(height < channel_count * notation_edit->control_height){
1386     height = channel_count * notation_edit->control_height;
1387   }
1388 
1389   /* push group */
1390   cairo_push_group(cr);
1391 
1392   /* draw fader */
1393   cairo_set_source_rgba(cr,
1394 			fg_color_active->red,
1395 			fg_color_active->blue,
1396 			fg_color_active->green,
1397 			fg_color_active->alpha);
1398 
1399   cairo_rectangle(cr,
1400 		  (double) x, (double) y,
1401 		  (double) width, (double) height);
1402   cairo_fill(cr);
1403 
1404   /* complete */
1405   cairo_pop_group_to_source(cr);
1406   cairo_paint(cr);
1407 
1408 //  cairo_surface_mark_dirty(cairo_get_target(cr));
1409 
1410   g_boxed_free(GDK_TYPE_RGBA, fg_color_active);
1411 }
1412 
1413 void
ags_notation_edit_draw_cursor(AgsNotationEdit * notation_edit,cairo_t * cr)1414 ags_notation_edit_draw_cursor(AgsNotationEdit *notation_edit, cairo_t *cr)
1415 {
1416   AgsNotationEditor *notation_editor;
1417   AgsNotationToolbar *notation_toolbar;
1418 
1419   GtkStyleContext *notation_edit_style_context;
1420 
1421   GtkAllocation allocation;
1422 
1423   GdkRGBA *fg_color_focused;
1424 
1425   double zoom_factor;
1426   double x, y;
1427   double width, height;
1428 
1429   GValue value = {0,};
1430 
1431   if(!AGS_IS_NOTATION_EDIT(notation_edit)){
1432     return;
1433   }
1434 
1435   notation_editor = (AgsNotationEditor *) gtk_widget_get_ancestor((GtkWidget *) notation_edit,
1436 								  AGS_TYPE_NOTATION_EDITOR);
1437 
1438   if(notation_editor->selected_machine == NULL){
1439     return;
1440   }
1441 
1442   notation_toolbar = notation_editor->notation_toolbar;
1443 
1444   gtk_widget_get_allocation(GTK_WIDGET(notation_edit->drawing_area),
1445 			    &allocation);
1446 
1447   /* style context */
1448   notation_edit_style_context = gtk_widget_get_style_context(GTK_WIDGET(notation_edit->drawing_area));
1449 
1450   gtk_style_context_get_property(notation_edit_style_context,
1451 				 "color",
1452 				 GTK_STATE_FLAG_FOCUSED,
1453 				 &value);
1454 
1455   fg_color_focused = g_value_dup_boxed(&value);
1456   g_value_unset(&value);
1457 
1458   /* zoom */
1459   zoom_factor = exp2(6.0 - (double) gtk_combo_box_get_active((GtkComboBox *) notation_toolbar->zoom));
1460 
1461   /* get offset */
1462   x = ((double) notation_edit->cursor_position_x * (double) notation_edit->control_width) - (gtk_range_get_value(GTK_RANGE(notation_edit->hscrollbar)) * zoom_factor);
1463   y = ((double) notation_edit->cursor_position_y * (double) notation_edit->control_height) - gtk_range_get_value(GTK_RANGE(notation_edit->vscrollbar));
1464 
1465   width = (double) notation_edit->control_width;
1466   height = (double) notation_edit->control_height;
1467 
1468   /* apply zoom */
1469   x /= zoom_factor;
1470 
1471   /* clip */
1472   if(x < 0.0){
1473     width += x;
1474 
1475     x = 0.0;
1476   }else if(x > allocation.width){
1477     g_boxed_free(GDK_TYPE_RGBA, fg_color_focused);
1478 
1479     return;
1480   }
1481 
1482   if(x + width > allocation.width){
1483     width = ((double) allocation.width) - x;
1484   }
1485 
1486   if(y < 0.0){
1487     height += y;
1488 
1489     y = 0.0;
1490   }else if(y > allocation.height){
1491     g_boxed_free(GDK_TYPE_RGBA, fg_color_focused);
1492 
1493     return;
1494   }
1495 
1496   if(y + height > allocation.height){
1497     height = ((double) allocation.height) - y;
1498   }
1499 
1500   /* push group */
1501   cairo_push_group(cr);
1502 
1503   /* draw cursor */
1504   cairo_set_source_rgba(cr,
1505 			fg_color_focused->red,
1506 			fg_color_focused->blue,
1507 			fg_color_focused->green,
1508 			fg_color_focused->alpha);
1509 
1510   cairo_rectangle(cr,
1511 		  x, y,
1512 		  width, height);
1513   cairo_fill(cr);
1514 
1515   /* complete */
1516   cairo_pop_group_to_source(cr);
1517   cairo_paint(cr);
1518 
1519 //  cairo_surface_mark_dirty(cairo_get_target(cr));
1520 
1521   g_boxed_free(GDK_TYPE_RGBA, fg_color_focused);
1522 }
1523 
1524 void
ags_notation_edit_draw_selection(AgsNotationEdit * notation_edit,cairo_t * cr)1525 ags_notation_edit_draw_selection(AgsNotationEdit *notation_edit, cairo_t *cr)
1526 {
1527   GtkAllocation allocation;
1528 
1529   GtkStyleContext *notation_edit_style_context;
1530 
1531   GdkRGBA *fg_color_prelight;
1532 
1533   double x, y;
1534   double width, height;
1535 
1536   GValue value = {0,};
1537 
1538   if(!AGS_IS_NOTATION_EDIT(notation_edit)){
1539     return;
1540   }
1541 
1542   gtk_widget_get_allocation(GTK_WIDGET(notation_edit->drawing_area),
1543 			    &allocation);
1544 
1545   /* style context */
1546   notation_edit_style_context = gtk_widget_get_style_context(GTK_WIDGET(notation_edit->drawing_area));
1547 
1548   gtk_style_context_get_property(notation_edit_style_context,
1549 				 "color",
1550 				 GTK_STATE_FLAG_PRELIGHT,
1551 				 &value);
1552 
1553   fg_color_prelight = g_value_dup_boxed(&value);
1554   g_value_unset(&value);
1555 
1556   gtk_widget_get_allocation(GTK_WIDGET(notation_edit->drawing_area),
1557 			    &allocation);
1558 
1559   /* get offset and dimensions */
1560   if(notation_edit->selection_x0 < notation_edit->selection_x1){
1561     x = ((double) notation_edit->selection_x0) - gtk_range_get_value(GTK_RANGE(notation_edit->hscrollbar));
1562     width = ((double) notation_edit->selection_x1 - (double) notation_edit->selection_x0);
1563   }else{
1564     x = ((double) notation_edit->selection_x1) - gtk_range_get_value(GTK_RANGE(notation_edit->hscrollbar));
1565     width = ((double) notation_edit->selection_x0 - (double) notation_edit->selection_x1);
1566   }
1567 
1568   if(notation_edit->selection_y0 < notation_edit->selection_y1){
1569     y = ((double) notation_edit->selection_y0) - gtk_range_get_value(GTK_RANGE(notation_edit->vscrollbar));
1570     height = ((double) notation_edit->selection_y1 - (double) notation_edit->selection_y0);
1571   }else{
1572     y = ((double) notation_edit->selection_y1) - gtk_range_get_value(GTK_RANGE(notation_edit->vscrollbar));
1573     height = ((double) notation_edit->selection_y0 - (double) notation_edit->selection_y1);
1574   }
1575 
1576   /* clip */
1577   if(x < 0.0){
1578     width += x;
1579 
1580     x = 0.0;
1581   }else if(x > allocation.width){
1582     g_boxed_free(GDK_TYPE_RGBA, fg_color_prelight);
1583 
1584     return;
1585   }
1586 
1587   if(x + width > allocation.width){
1588     width = ((double) allocation.width) - x;
1589   }
1590 
1591   if(y < 0.0){
1592     height += y;
1593 
1594     y = 0.0;
1595   }else if(y > allocation.height){
1596     g_boxed_free(GDK_TYPE_RGBA, fg_color_prelight);
1597 
1598     return;
1599   }
1600 
1601   if(y + height > allocation.height){
1602     height = ((double) allocation.height) - y;
1603   }
1604 
1605   /* push group */
1606   cairo_push_group(cr);
1607 
1608   /* draw selection */
1609   cairo_set_source_rgba(cr,
1610 			fg_color_prelight->red,
1611 			fg_color_prelight->blue,
1612 			fg_color_prelight->green,
1613 			1.0 / 3.0);
1614 
1615   cairo_rectangle(cr,
1616 		  x, y,
1617 		  width, height);
1618   cairo_fill(cr);
1619 
1620   /* complete */
1621   cairo_pop_group_to_source(cr);
1622   cairo_paint(cr);
1623 
1624 //  cairo_surface_mark_dirty(cairo_get_target(cr));
1625 
1626   g_boxed_free(GDK_TYPE_RGBA, fg_color_prelight);
1627 }
1628 
1629 void
ags_notation_edit_draw_note(AgsNotationEdit * notation_edit,AgsNote * note,cairo_t * cr,gdouble opacity)1630 ags_notation_edit_draw_note(AgsNotationEdit *notation_edit,
1631 			    AgsNote *note,
1632 			    cairo_t *cr,
1633 			    gdouble opacity)
1634 {
1635   AgsNotationEditor *notation_editor;
1636   AgsNotationToolbar *notation_toolbar;
1637 
1638   GtkStyleContext *notation_edit_style_context;
1639 
1640   GtkAllocation allocation;
1641 
1642   GdkRGBA *fg_color;
1643   GdkRGBA *fg_color_selected;
1644 
1645   double zoom_factor;
1646   guint channel_count;
1647   double viewport_x, viewport_y;
1648   double x, y;
1649   double width, height;
1650 
1651   GValue value = {0,};
1652 
1653   if(!AGS_IS_NOTATION_EDIT(notation_edit) ||
1654      !AGS_IS_NOTE(note)){
1655     return;
1656   }
1657 
1658   notation_editor = (AgsNotationEditor *) gtk_widget_get_ancestor((GtkWidget *) notation_edit,
1659 								  AGS_TYPE_NOTATION_EDITOR);
1660 
1661   if(notation_editor->selected_machine == NULL){
1662     return;
1663   }
1664 
1665   notation_toolbar = notation_editor->notation_toolbar;
1666 
1667   gtk_widget_get_allocation(GTK_WIDGET(notation_edit->drawing_area),
1668 			    &allocation);
1669 
1670   /* style context */
1671   notation_edit_style_context = gtk_widget_get_style_context(GTK_WIDGET(notation_edit->drawing_area));
1672 
1673   gtk_style_context_get_property(notation_edit_style_context,
1674 				 "color",
1675 				 GTK_STATE_FLAG_NORMAL,
1676 				 &value);
1677 
1678   fg_color = g_value_dup_boxed(&value);
1679   g_value_unset(&value);
1680 
1681   gtk_style_context_get_property(notation_edit_style_context,
1682 				 "color",
1683 				 GTK_STATE_FLAG_SELECTED,
1684 				 &value);
1685 
1686   fg_color_selected = g_value_dup_boxed(&value);
1687   g_value_unset(&value);
1688 
1689   /* get channel count */
1690 #if 0
1691   if(ags_audio_test_flags(notation_editor->selected_machine->audio, AGS_AUDIO_NOTATION_DEFAULT)){
1692     g_object_get(notation_editor->selected_machine->audio,
1693 		 "input-pads", &channel_count,
1694 		 NULL);
1695     channel_count = notation_editor->selected_machine->audio->input_pads;
1696   }else{
1697     g_object_get(notation_editor->selected_machine->audio,
1698 		 "output-pads", &channel_count,
1699 		 NULL);
1700   }
1701 #else
1702   g_object_get(notation_editor->selected_machine->audio,
1703 	       "input-pads", &channel_count,
1704 	       NULL);
1705 #endif
1706 
1707   /* zoom */
1708   zoom_factor = exp2(6.0 - (double) gtk_combo_box_get_active((GtkComboBox *) notation_toolbar->zoom));
1709 
1710   /* get offset and dimensions */
1711   if((AGS_NOTATION_EDITOR_MAX_CONTROLS * notation_edit->control_width) > allocation.width){
1712     viewport_x = zoom_factor * gtk_range_get_value(GTK_RANGE(notation_edit->hscrollbar));
1713   }else{
1714     viewport_x = 0.0;
1715   }
1716 
1717   if((channel_count * notation_edit->control_height) > allocation.height){
1718     viewport_y = gtk_range_get_value(GTK_RANGE(notation_edit->vscrollbar));
1719   }else{
1720     viewport_y = 0.0;
1721   }
1722 
1723   x = ((double) note->x[0]) * ((double) notation_edit->control_width) - viewport_x;
1724   y = ((double) note->y) * ((double) notation_edit->control_height) - viewport_y;
1725 
1726   width = ((double) (note->x[1] - note->x[0])) * ((double) notation_edit->control_width);
1727   height = ((double) notation_edit->control_height);
1728 
1729   /* apply zoom */
1730   x /= zoom_factor;
1731   x += ((double) notation_edit->control_margin_x);
1732 
1733   y += ((double) notation_edit->control_margin_y);
1734 
1735   width /= zoom_factor;
1736   width -= (2.0 * (double) notation_edit->control_margin_x);
1737 
1738   height -= (2.0 * (double) notation_edit->control_margin_y);
1739 
1740   /* clip */
1741   if(x < 0.0){
1742     if(x + width < 0.0){
1743       g_boxed_free(GDK_TYPE_RGBA, fg_color);
1744       g_boxed_free(GDK_TYPE_RGBA, fg_color_selected);
1745 
1746       return;
1747     }else{
1748       width += x;
1749       x = 0.0;
1750     }
1751   }else if(x > allocation.width){
1752     g_boxed_free(GDK_TYPE_RGBA, fg_color);
1753     g_boxed_free(GDK_TYPE_RGBA, fg_color_selected);
1754 
1755     return;
1756   }
1757 
1758   if(x + width > allocation.width){
1759     width = ((double) allocation.width) - x;
1760   }
1761 
1762   if(y < 0.0){
1763     if(y + height < 0.0){
1764       g_boxed_free(GDK_TYPE_RGBA, fg_color);
1765       g_boxed_free(GDK_TYPE_RGBA, fg_color_selected);
1766 
1767       return;
1768     }else{
1769       height += y;
1770       y = 0.0;
1771     }
1772   }else if(y > allocation.height){
1773     g_boxed_free(GDK_TYPE_RGBA, fg_color);
1774     g_boxed_free(GDK_TYPE_RGBA, fg_color_selected);
1775 
1776     return;
1777   }
1778 
1779   if(y + height > allocation.height){
1780     height = ((double) allocation.height) - y;
1781   }
1782 
1783   /* draw note */
1784   cairo_set_source_rgba(cr,
1785 			fg_color->red,
1786 			fg_color->blue,
1787 			fg_color->green,
1788 			opacity * fg_color->alpha);
1789 
1790   cairo_rectangle(cr,
1791 		  x, y,
1792 		  width, height);
1793   cairo_fill(cr);
1794 
1795   /* check note selected */
1796   if((AGS_NOTE_IS_SELECTED & (note->flags)) != 0){
1797     double selected_x, selected_y;
1798     double selected_width, selected_height;
1799 
1800     selected_x = x - notation_edit->selected_note_border;
1801     selected_y = y - notation_edit->selected_note_border;
1802 
1803     selected_width = width + (2.0 * (double) notation_edit->selected_note_border);
1804     selected_height = height + (2.0 * (double) notation_edit->selected_note_border);
1805 
1806     /* clip */
1807     if(selected_x < 0.0){
1808       selected_x = 0.0;
1809     }
1810 
1811     if(selected_x + selected_width > allocation.width){
1812       selected_width = ((double) allocation.width) - selected_x;
1813     }
1814 
1815     if(selected_y < 0.0){
1816       selected_y = 0.0;
1817     }
1818 
1819     if(selected_y + selected_height > allocation.height){
1820       selected_height = ((double) allocation.height) - selected_y;
1821     }
1822 
1823     /* draw selected note */
1824     cairo_set_source_rgba(cr,
1825 			  fg_color_selected->red,
1826 			  fg_color_selected->blue,
1827 			  fg_color_selected->green,
1828 			  opacity / 3.0);
1829 
1830     cairo_rectangle(cr,
1831 		    selected_x, selected_y,
1832 		    selected_width, selected_height);
1833     cairo_fill(cr);
1834   }
1835 
1836   g_boxed_free(GDK_TYPE_RGBA, fg_color);
1837   g_boxed_free(GDK_TYPE_RGBA, fg_color_selected);
1838 }
1839 
1840 void
ags_notation_edit_draw_notation(AgsNotationEdit * notation_edit,cairo_t * cr)1841 ags_notation_edit_draw_notation(AgsNotationEdit *notation_edit, cairo_t *cr)
1842 {
1843   AgsNotationEditor *notation_editor;
1844   AgsNotationToolbar *notation_toolbar;
1845 
1846   GtkAllocation allocation;
1847 
1848   AgsTimestamp *timestamp;
1849   AgsTimestamp *current_timestamp;
1850 
1851   GList *start_list_notation, *list_notation;
1852 
1853   gdouble opacity;
1854   gdouble zoom, zoom_factor;
1855   guint x0, x1;
1856   guint offset;
1857   guint audio_channel;
1858   gint i;
1859 
1860   if(!AGS_IS_NOTATION_EDIT(notation_edit)){
1861     return;
1862   }
1863 
1864   notation_editor = (AgsNotationEditor *) gtk_widget_get_ancestor((GtkWidget *) notation_edit,
1865 								  AGS_TYPE_NOTATION_EDITOR);
1866   notation_toolbar = notation_editor->notation_toolbar;
1867 
1868   if(notation_editor->selected_machine == NULL){
1869     return;
1870   }
1871 
1872   gtk_widget_get_allocation(GTK_WIDGET(notation_edit->drawing_area),
1873 			    &allocation);
1874 
1875   opacity = gtk_spin_button_get_value(notation_editor->notation_toolbar->opacity);
1876 
1877   /* zoom */
1878   zoom = exp2((double) gtk_combo_box_get_active((GtkComboBox *) notation_toolbar->zoom) - 2.0);
1879   zoom_factor = exp2(6.0 - (double) gtk_combo_box_get_active((GtkComboBox *) notation_toolbar->zoom));
1880 
1881   /* get visisble region */
1882   x0 = (zoom_factor * gtk_range_get_value(GTK_RANGE(notation_edit->hscrollbar))) / notation_edit->control_width;
1883   x1 = ((zoom_factor * gtk_range_get_value(GTK_RANGE(notation_edit->hscrollbar))) / notation_edit->control_width) + (allocation.width * zoom);
1884 
1885   /* draw notation */
1886   timestamp = ags_timestamp_new();
1887 
1888   timestamp->flags &= (~AGS_TIMESTAMP_UNIX);
1889   timestamp->flags |= AGS_TIMESTAMP_OFFSET;
1890 
1891   g_object_get(notation_editor->selected_machine->audio,
1892 	       "notation", &start_list_notation,
1893 	       NULL);
1894 
1895   timestamp->timer.ags_offset.offset = (guint64) AGS_NOTATION_DEFAULT_OFFSET * floor((double) x0 / (double) AGS_NOTATION_DEFAULT_OFFSET);
1896 
1897   i = 0;
1898 
1899   while((i = ags_notebook_next_active_tab(notation_editor->notebook,
1900 					  i)) != -1){
1901     list_notation = ags_notation_find_near_timestamp(start_list_notation, i,
1902 						     timestamp);
1903 
1904     while(list_notation != NULL){
1905       AgsNotation *notation;
1906 
1907       GList *start_list_note, *list_note;
1908 
1909       notation = AGS_NOTATION(list_notation->data);
1910 
1911       g_object_get(notation,
1912 		   "audio-channel", &audio_channel,
1913 		   "timestamp", &current_timestamp,
1914 		   NULL);
1915 
1916       g_object_unref(current_timestamp);
1917 
1918       if(ags_timestamp_get_ags_offset(current_timestamp) > AGS_NOTATION_DEFAULT_OFFSET * floor((double) x1 / (double) AGS_NOTATION_DEFAULT_OFFSET) + AGS_NOTATION_DEFAULT_OFFSET){
1919 	break;
1920       }
1921 
1922       if(ags_timestamp_get_ags_offset(current_timestamp) + AGS_NOTATION_DEFAULT_OFFSET < x0){
1923 	list_notation = list_notation->next;
1924 
1925 	continue;
1926       }
1927 
1928       if(i != audio_channel){
1929 	list_notation = list_notation->next;
1930 
1931 	continue;
1932       }
1933 
1934       g_object_get(notation,
1935 		   "note", &start_list_note,
1936 		   NULL);
1937 
1938       list_note = start_list_note;
1939 
1940       while(list_note != NULL){
1941 	ags_notation_edit_draw_note(notation_edit,
1942 				    list_note->data,
1943 				    cr,
1944 				    opacity);
1945 
1946 	list_note = list_note->next;
1947       }
1948 
1949       g_list_free_full(start_list_note,
1950 		       g_object_unref);
1951 
1952       list_notation = list_notation->next;
1953     }
1954 
1955     i++;
1956   }
1957 
1958   g_list_free_full(start_list_notation,
1959 		   g_object_unref);
1960 
1961   g_object_unref(timestamp);
1962 }
1963 
1964 void
ags_notation_edit_draw(AgsNotationEdit * notation_edit,cairo_t * cr)1965 ags_notation_edit_draw(AgsNotationEdit *notation_edit, cairo_t *cr)
1966 {
1967   /* segment */
1968   ags_notation_edit_draw_segment(notation_edit, cr);
1969 
1970   /* notation */
1971   ags_notation_edit_draw_notation(notation_edit, cr);
1972 
1973   /* edit mode */
1974   switch(notation_edit->mode){
1975   case AGS_NOTATION_EDIT_POSITION_CURSOR:
1976     {
1977       ags_notation_edit_draw_cursor(notation_edit, cr);
1978     }
1979     break;
1980   case AGS_NOTATION_EDIT_ADD_NOTE:
1981     {
1982       if(notation_edit->current_note != NULL){
1983 	if(cr != NULL){
1984 	  ags_notation_edit_draw_note(notation_edit,
1985 				      notation_edit->current_note,
1986 				      cr,
1987 				      1.0);
1988 
1989 	  cairo_surface_mark_dirty(cairo_get_target(cr));
1990 	}
1991       }
1992     }
1993     break;
1994   case AGS_NOTATION_EDIT_SELECT_NOTE:
1995     {
1996       ags_notation_edit_draw_selection(notation_edit, cr);
1997     }
1998     break;
1999   }
2000 
2001   /* fader */
2002   if((AGS_NOTATION_EDIT_AUTO_SCROLL & (notation_edit->flags)) != 0){
2003     ags_notation_edit_draw_position(notation_edit, cr);
2004   }
2005 }
2006 
2007 /**
2008  * ags_notation_edit_new:
2009  *
2010  * Create a new #AgsNotationEdit.
2011  *
2012  * Returns: a new #AgsNotationEdit
2013  *
2014  * Since: 3.0.0
2015  */
2016 AgsNotationEdit*
ags_notation_edit_new()2017 ags_notation_edit_new()
2018 {
2019   AgsNotationEdit *notation_edit;
2020 
2021   notation_edit = (AgsNotationEdit *) g_object_new(AGS_TYPE_NOTATION_EDIT,
2022 						   NULL);
2023 
2024   return(notation_edit);
2025 }
2026