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", ¤t_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