1 /* GSequencer - Advanced GTK Sequencer
2 * Copyright (C) 2005-2021 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_automation_edit.h>
21 #include <ags/X/editor/ags_automation_edit_callbacks.h>
22
23 #include <ags/X/ags_ui_provider.h>
24 #include <ags/X/ags_automation_editor.h>
25
26 #include <gdk/gdkkeysyms.h>
27 #include <atk/atk.h>
28
29 #include <cairo.h>
30 #include <math.h>
31
32 #include <ags/i18n.h>
33
34 static GType ags_accessible_automation_edit_get_type(void);
35 void ags_automation_edit_class_init(AgsAutomationEditClass *automation_edit);
36 void ags_accessible_automation_edit_class_init(AtkObject *object);
37 void ags_accessible_automation_edit_action_interface_init(AtkActionIface *action);
38 void ags_automation_edit_connectable_interface_init(AgsConnectableInterface *connectable);
39 void ags_automation_edit_init(AgsAutomationEdit *automation_edit);
40 void ags_automation_edit_set_property(GObject *gobject,
41 guint prop_id,
42 const GValue *value,
43 GParamSpec *param_spec);
44 void ags_automation_edit_get_property(GObject *gobject,
45 guint prop_id,
46 GValue *value,
47 GParamSpec *param_spec);
48 void ags_automation_edit_finalize(GObject *gobject);
49
50 void ags_automation_edit_connect(AgsConnectable *connectable);
51 void ags_automation_edit_disconnect(AgsConnectable *connectable);
52 AtkObject* ags_automation_edit_get_accessible(GtkWidget *widget);
53
54 gboolean ags_accessible_automation_edit_do_action(AtkAction *action,
55 gint i);
56 gint ags_accessible_automation_edit_get_n_actions(AtkAction *action);
57 const gchar* ags_accessible_automation_edit_get_description(AtkAction *action,
58 gint i);
59 const gchar* ags_accessible_automation_edit_get_name(AtkAction *action,
60 gint i);
61 const gchar* ags_accessible_automation_edit_get_keybinding(AtkAction *action,
62 gint i);
63 gboolean ags_accessible_automation_edit_set_description(AtkAction *action,
64 gint i);
65 gchar* ags_accessible_automation_edit_get_localized_name(AtkAction *action,
66 gint i);
67
68 void ags_automation_edit_get_preferred_width(GtkWidget *widget,
69 gint *minimal_width,
70 gint *natural_width);
71 void ags_automation_edit_get_preferred_height(GtkWidget *widget,
72 gint *minimal_height,
73 gint *natural_height);
74 void ags_automation_edit_size_allocate(GtkWidget *widget,
75 GtkAllocation *allocation);
76 void ags_automation_edit_show(GtkWidget *widget);
77 void ags_automation_edit_show_all(GtkWidget *widget);
78
79 gboolean ags_automation_edit_auto_scroll_timeout(GtkWidget *widget);
80
81 /**
82 * SECTION:ags_automation_edit
83 * @short_description: edit automations
84 * @title: AgsAutomationEdit
85 * @section_id:
86 * @include: ags/X/editor/ags_automation_edit.h
87 *
88 * The #AgsAutomationEdit lets you edit automations.
89 */
90
91 enum{
92 PROP_0,
93 PROP_CHANNEL_TYPE,
94 PROP_FILENAME,
95 PROP_EFFECT,
96 PROP_CONTROL_SPECIFIER,
97 PROP_CONTROL_NAME,
98 PROP_LOWER,
99 PROP_UPPER,
100 PROP_DEFAULT_VALUE,
101 };
102
103 static gpointer ags_automation_edit_parent_class = NULL;
104
105 static GQuark quark_accessible_object = 0;
106
107 GHashTable *ags_automation_edit_auto_scroll = NULL;
108
109 GType
ags_automation_edit_get_type(void)110 ags_automation_edit_get_type(void)
111 {
112 static volatile gsize g_define_type_id__volatile = 0;
113
114 if(g_once_init_enter (&g_define_type_id__volatile)){
115 GType ags_type_automation_edit = 0;
116
117 static const GTypeInfo ags_automation_edit_info = {
118 sizeof (AgsAutomationEditClass),
119 NULL, /* base_init */
120 NULL, /* base_finalize */
121 (GClassInitFunc) ags_automation_edit_class_init,
122 NULL, /* class_finalize */
123 NULL, /* class_data */
124 sizeof (AgsAutomationEdit),
125 0, /* n_preallocs */
126 (GInstanceInitFunc) ags_automation_edit_init,
127 };
128
129 static const GInterfaceInfo ags_connectable_interface_info = {
130 (GInterfaceInitFunc) ags_automation_edit_connectable_interface_init,
131 NULL, /* interface_finalize */
132 NULL, /* interface_data */
133 };
134
135 ags_type_automation_edit = g_type_register_static(GTK_TYPE_TABLE,
136 "AgsAutomationEdit", &ags_automation_edit_info,
137 0);
138
139 g_type_add_interface_static(ags_type_automation_edit,
140 AGS_TYPE_CONNECTABLE,
141 &ags_connectable_interface_info);
142
143 g_once_init_leave(&g_define_type_id__volatile, ags_type_automation_edit);
144 }
145
146 return g_define_type_id__volatile;
147 }
148
149 static GType
ags_accessible_automation_edit_get_type(void)150 ags_accessible_automation_edit_get_type(void)
151 {
152 static GType ags_type_accessible_automation_edit = 0;
153
154 if(!ags_type_accessible_automation_edit){
155 const GTypeInfo ags_accesssible_automation_edit_info = {
156 sizeof(GtkAccessibleClass),
157 NULL, /* base_init */
158 NULL, /* base_finalize */
159 (GClassInitFunc) ags_accessible_automation_edit_class_init,
160 NULL, /* class_finalize */
161 NULL, /* class_data */
162 sizeof(GtkAccessible),
163 0, /* n_preallocs */
164 NULL, NULL
165 };
166
167 static const GInterfaceInfo atk_action_interface_info = {
168 (GInterfaceInitFunc) ags_accessible_automation_edit_action_interface_init,
169 NULL, /* interface_finalize */
170 NULL, /* interface_data */
171 };
172
173 ags_type_accessible_automation_edit = g_type_register_static(GTK_TYPE_ACCESSIBLE,
174 "AgsAccessibleAutomationEdit", &ags_accesssible_automation_edit_info,
175 0);
176
177 g_type_add_interface_static(ags_type_accessible_automation_edit,
178 ATK_TYPE_ACTION,
179 &atk_action_interface_info);
180 }
181
182 return(ags_type_accessible_automation_edit);
183 }
184
185
186 void
ags_automation_edit_class_init(AgsAutomationEditClass * automation_edit)187 ags_automation_edit_class_init(AgsAutomationEditClass *automation_edit)
188 {
189 GtkWidgetClass *widget;
190
191 GObjectClass *gobject;
192
193 GParamSpec *param_spec;
194
195 ags_automation_edit_parent_class = g_type_class_peek_parent(automation_edit);
196
197 /* GObjectClass */
198 gobject = G_OBJECT_CLASS(automation_edit);
199
200 gobject->set_property = ags_automation_edit_set_property;
201 gobject->get_property = ags_automation_edit_get_property;
202
203 gobject->finalize = ags_automation_edit_finalize;
204
205 /* properties */
206 /**
207 * AgsAutomationArea:channel-type:
208 *
209 * The target channel.
210 *
211 * Since: 3.0.0
212 */
213 param_spec = g_param_spec_gtype("channel-type",
214 i18n_pspec("assigned channel type"),
215 i18n_pspec("The channel type it is assigned with"),
216 G_TYPE_NONE,
217 G_PARAM_READABLE | G_PARAM_WRITABLE);
218 g_object_class_install_property(gobject,
219 PROP_CHANNEL_TYPE,
220 param_spec);
221
222 /**
223 * AgsChannel:filename:
224 *
225 * The assigned #AgsFilename representing this channel.
226 *
227 * Since: 3.0.0
228 */
229 param_spec = g_param_spec_string("filename",
230 i18n_pspec("filename assigned with"),
231 i18n_pspec("The filename it is assigned with"),
232 NULL,
233 G_PARAM_READABLE | G_PARAM_WRITABLE);
234 g_object_class_install_property(gobject,
235 PROP_FILENAME,
236 param_spec);
237
238 /**
239 * AgsChannel:effect:
240 *
241 * The assigned #AgsEffect representing this channel.
242 *
243 * Since: 3.0.0
244 */
245 param_spec = g_param_spec_string("effect",
246 i18n_pspec("effect assigned with"),
247 i18n_pspec("The effect name it is assigned with"),
248 NULL,
249 G_PARAM_READABLE | G_PARAM_WRITABLE);
250 g_object_class_install_property(gobject,
251 PROP_EFFECT,
252 param_spec);
253
254 /**
255 * AgsChannel:control-specifier:
256 *
257 * The assigned #AgsControl-Specifier representing this channel.
258 *
259 * Since: 3.0.0
260 */
261 param_spec = g_param_spec_string("control-specifier",
262 i18n_pspec("assigned control specifier"),
263 i18n_pspec("The control specifier it is assigned with"),
264 NULL,
265 G_PARAM_READABLE | G_PARAM_WRITABLE);
266 g_object_class_install_property(gobject,
267 PROP_CONTROL_SPECIFIER,
268 param_spec);
269
270 /**
271 * AgsChannel:control-name:
272 *
273 * The assigned #AgsControl-Name representing this channel.
274 *
275 * Since: 3.0.0
276 */
277 param_spec = g_param_spec_string("control-name",
278 i18n_pspec("displayed control name"),
279 i18n_pspec("The control name to display"),
280 NULL,
281 G_PARAM_READABLE | G_PARAM_WRITABLE);
282 g_object_class_install_property(gobject,
283 PROP_CONTROL_NAME,
284 param_spec);
285
286 /**
287 * AgsAutomationEdit:lower:
288 *
289 * The automation edit's lower range.
290 *
291 * Since: 3.0.0
292 */
293 param_spec = g_param_spec_double("lower",
294 "lower",
295 "The lower of automation edit",
296 -G_MAXDOUBLE,
297 G_MAXDOUBLE,
298 AGS_AUTOMATION_EDIT_DEFAULT_LOWER,
299 G_PARAM_READABLE | G_PARAM_WRITABLE);
300 g_object_class_install_property(gobject,
301 PROP_LOWER,
302 param_spec);
303
304 /**
305 * AgsAutomationEdit:upper:
306 *
307 * The automation edit's upper range.
308 *
309 * Since: 3.0.0
310 */
311 param_spec = g_param_spec_double("upper",
312 "upper",
313 "The upper of automation edit",
314 -G_MAXDOUBLE,
315 G_MAXDOUBLE,
316 AGS_AUTOMATION_EDIT_DEFAULT_UPPER,
317 G_PARAM_READABLE | G_PARAM_WRITABLE);
318 g_object_class_install_property(gobject,
319 PROP_UPPER,
320 param_spec);
321
322 /**
323 * AgsAutomationEdit:default-value:
324 *
325 * The automation edit's default value.
326 *
327 * Since: 3.0.0
328 */
329 param_spec = g_param_spec_double("default-value",
330 "default value",
331 "The default value of automation edit",
332 -G_MAXDOUBLE,
333 G_MAXDOUBLE,
334 AGS_AUTOMATION_EDIT_DEFAULT_VALUE,
335 G_PARAM_READABLE | G_PARAM_WRITABLE);
336 g_object_class_install_property(gobject,
337 PROP_DEFAULT_VALUE,
338 param_spec);
339
340 /* GtkWidgetClass */
341 widget = (GtkWidgetClass *) automation_edit;
342
343 // widget->get_preferred_width = ags_automation_edit_get_preferred_width;
344 widget->get_preferred_height = ags_automation_edit_get_preferred_height;
345 // widget->size_allocate = ags_automation_edit_size_allocate;
346 // widget->draw = ags_automation_edit_draw;
347 widget->show = ags_automation_edit_show;
348 widget->show_all = ags_automation_edit_show_all;
349 }
350
351 void
ags_accessible_automation_edit_class_init(AtkObject * object)352 ags_accessible_automation_edit_class_init(AtkObject *object)
353 {
354 quark_accessible_object = g_quark_from_static_string("ags-accessible-object");
355 }
356
357 void
ags_accessible_automation_edit_action_interface_init(AtkActionIface * action)358 ags_accessible_automation_edit_action_interface_init(AtkActionIface *action)
359 {
360 action->do_action = ags_accessible_automation_edit_do_action;
361 action->get_n_actions = ags_accessible_automation_edit_get_n_actions;
362 action->get_description = ags_accessible_automation_edit_get_description;
363 action->get_name = ags_accessible_automation_edit_get_name;
364 action->get_keybinding = ags_accessible_automation_edit_get_keybinding;
365 action->set_description = ags_accessible_automation_edit_set_description;
366 action->get_localized_name = ags_accessible_automation_edit_get_localized_name;
367 }
368
369 void
ags_automation_edit_connectable_interface_init(AgsConnectableInterface * connectable)370 ags_automation_edit_connectable_interface_init(AgsConnectableInterface *connectable)
371 {
372 connectable->is_ready = NULL;
373 connectable->is_connected = NULL;
374 connectable->connect = ags_automation_edit_connect;
375 connectable->disconnect = ags_automation_edit_disconnect;
376 }
377
378 void
ags_automation_edit_init(AgsAutomationEdit * automation_edit)379 ags_automation_edit_init(AgsAutomationEdit *automation_edit)
380 {
381 GtkAdjustment *adjustment;
382
383 AgsApplicationContext *application_context;
384
385 gdouble gui_scale_factor;
386
387 application_context = ags_application_context_get_instance();
388
389 g_object_set(automation_edit,
390 "can-focus", FALSE,
391 "n-columns", 3,
392 "n-rows", 4,
393 "homogeneous", FALSE,
394 NULL);
395
396 automation_edit->flags = 0;
397 automation_edit->mode = AGS_AUTOMATION_EDIT_NO_EDIT_MODE;
398
399 automation_edit->button_mask = 0;
400 automation_edit->key_mask = 0;
401
402 /* scale factor */
403 gui_scale_factor = ags_ui_provider_get_gui_scale_factor(AGS_UI_PROVIDER(application_context));
404
405 automation_edit->note_offset = 0;
406 automation_edit->note_offset_absolute = 0;
407
408 automation_edit->point_radius = (guint) (gui_scale_factor * AGS_AUTOMATION_EDIT_DEFAULT_POINT_RADIUS);
409
410 automation_edit->scan_width = (guint) (gui_scale_factor * AGS_AUTOMATION_EDIT_DEFAULT_SCAN_WIDTH);
411 automation_edit->scan_height = (guint) (gui_scale_factor * AGS_AUTOMATION_EDIT_DEFAULT_SCAN_HEIGHT);
412
413 automation_edit->control_width = (guint) (gui_scale_factor * AGS_AUTOMATION_EDIT_DEFAULT_CONTROL_WIDTH);
414 automation_edit->control_height = (guint) (gui_scale_factor * AGS_AUTOMATION_EDIT_DEFAULT_CONTROL_HEIGHT);
415
416 automation_edit->step_count = (guint) (AGS_AUTOMATION_EDIT_DEFAULT_STEP_COUNT);
417
418 automation_edit->cursor_position_x = AGS_AUTOMATION_EDIT_DEFAULT_CURSOR_POSITION_X;
419 automation_edit->cursor_position_y = AGS_AUTOMATION_EDIT_DEFAULT_CURSOR_POSITION_Y;
420
421 automation_edit->selected_acceleration_border = AGS_AUTOMATION_EDIT_DEFAULT_SELECTED_ACCELERATION_BORDER;
422
423 automation_edit->selection_x0 = 0;
424 automation_edit->selection_x1 = 0;
425 automation_edit->selection_y0 = 0;
426 automation_edit->selection_y1 = 0;
427
428 automation_edit->current_acceleration = NULL;
429
430 automation_edit->ruler = ags_ruler_new();
431 g_object_set(automation_edit->ruler,
432 "height-request", (gint) (gui_scale_factor * AGS_RULER_DEFAULT_HEIGHT),
433 "font-size", (guint) (gui_scale_factor * automation_edit->ruler->font_size),
434 "step", (guint) (AGS_RULER_DEFAULT_STEP),
435 "large-step", (guint) (gui_scale_factor * AGS_RULER_DEFAULT_LARGE_STEP),
436 "small-step", (guint) (gui_scale_factor * AGS_RULER_DEFAULT_SMALL_STEP),
437 "no-show-all", TRUE,
438 NULL);
439 gtk_table_attach(GTK_TABLE(automation_edit),
440 (GtkWidget *) automation_edit->ruler,
441 0, 1,
442 0, 1,
443 GTK_FILL | GTK_EXPAND, GTK_FILL,
444 0, 0);
445
446 automation_edit->channel_type = G_TYPE_NONE;
447
448 automation_edit->filename = NULL;
449 automation_edit->effect = NULL;
450
451 automation_edit->control_specifier = NULL;
452 automation_edit->control_name = NULL;
453
454 automation_edit->lower = AGS_AUTOMATION_EDIT_DEFAULT_LOWER;
455 automation_edit->upper = AGS_AUTOMATION_EDIT_DEFAULT_UPPER;
456
457 automation_edit->default_value = AGS_AUTOMATION_EDIT_DEFAULT_VALUE;
458
459 automation_edit->drawing_area = (GtkDrawingArea *) gtk_drawing_area_new();
460 gtk_widget_set_has_window(automation_edit->drawing_area,
461 TRUE);
462 gtk_widget_set_events(GTK_WIDGET (automation_edit->drawing_area), GDK_EXPOSURE_MASK
463 | GDK_LEAVE_NOTIFY_MASK
464 | GDK_BUTTON_PRESS_MASK
465 | GDK_BUTTON_RELEASE_MASK
466 | GDK_POINTER_MOTION_MASK
467 | GDK_POINTER_MOTION_HINT_MASK
468 | GDK_CONTROL_MASK
469 | GDK_KEY_PRESS_MASK
470 | GDK_KEY_RELEASE_MASK);
471 gtk_widget_set_can_focus((GtkWidget *) automation_edit->drawing_area,
472 TRUE);
473
474 gtk_table_attach(GTK_TABLE(automation_edit),
475 (GtkWidget *) automation_edit->drawing_area,
476 0, 1,
477 1, 2,
478 GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND,
479 0, 0);
480
481 /* vscrollbar */
482 adjustment = (GtkAdjustment *) gtk_adjustment_new(0.0, 0.0, 1.0, 1.0, automation_edit->control_height, 1.0);
483 automation_edit->vscrollbar = (GtkVScrollbar *) gtk_vscrollbar_new(adjustment);
484 g_object_set(automation_edit->vscrollbar,
485 "no-show-all", TRUE,
486 NULL);
487 gtk_widget_set_size_request((GtkWidget *) automation_edit->vscrollbar,
488 -1, (guint) (gui_scale_factor * AGS_SCALE_DEFAULT_SCALE_HEIGHT));
489 gtk_table_attach(GTK_TABLE(automation_edit),
490 (GtkWidget *) automation_edit->vscrollbar,
491 1, 2,
492 1, 2,
493 GTK_FILL, GTK_FILL,
494 0, 0);
495
496 /* hscrollbar */
497 adjustment = (GtkAdjustment *) gtk_adjustment_new(0.0, 0.0, 1.0, 1.0, (gdouble) automation_edit->control_width, 1.0);
498 automation_edit->hscrollbar = (GtkHScrollbar *) gtk_hscrollbar_new(adjustment);
499 g_object_set(automation_edit->hscrollbar,
500 "no-show-all", TRUE,
501 NULL);
502 gtk_widget_set_size_request((GtkWidget *) automation_edit->hscrollbar,
503 -1, -1);
504 gtk_table_attach(GTK_TABLE(automation_edit),
505 (GtkWidget *) automation_edit->hscrollbar,
506 0, 1,
507 2, 3,
508 GTK_FILL, GTK_FILL,
509 0, 0);
510
511 /* auto-scroll */
512 if(ags_automation_edit_auto_scroll == NULL){
513 ags_automation_edit_auto_scroll = g_hash_table_new_full(g_direct_hash, g_direct_equal,
514 NULL,
515 NULL);
516 }
517
518 g_hash_table_insert(ags_automation_edit_auto_scroll,
519 automation_edit, ags_automation_edit_auto_scroll_timeout);
520 g_timeout_add(1000 / 30, (GSourceFunc) ags_automation_edit_auto_scroll_timeout, (gpointer) automation_edit);
521 }
522
523 void
ags_automation_edit_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)524 ags_automation_edit_set_property(GObject *gobject,
525 guint prop_id,
526 const GValue *value,
527 GParamSpec *param_spec)
528 {
529 AgsAutomationEdit *automation_edit;
530
531 automation_edit = AGS_AUTOMATION_EDIT(gobject);
532
533 switch(prop_id){
534 case PROP_CHANNEL_TYPE:
535 {
536 automation_edit->channel_type = g_value_get_gtype(value);
537 }
538 break;
539 case PROP_FILENAME:
540 {
541 gchar *filename;
542
543 filename = g_value_get_string(value);
544
545 if(automation_edit->filename == filename){
546 return;
547 }
548
549 automation_edit->filename = g_strdup(filename);
550 }
551 break;
552 case PROP_EFFECT:
553 {
554 gchar *effect;
555
556 effect = g_value_get_string(value);
557
558 if(automation_edit->effect == effect){
559 return;
560 }
561
562 automation_edit->effect = g_strdup(effect);
563 }
564 break;
565 case PROP_CONTROL_SPECIFIER:
566 {
567 gchar *control_specifier;
568
569 control_specifier = g_value_get_string(value);
570
571 if(automation_edit->control_specifier == control_specifier){
572 return;
573 }
574
575 automation_edit->control_specifier = g_strdup(control_specifier);
576 }
577 break;
578 case PROP_CONTROL_NAME:
579 {
580 gchar *control_name;
581
582 control_name = g_value_get_string(value);
583
584 if(automation_edit->control_name == control_name){
585 return;
586 }
587
588 automation_edit->control_name = g_strdup(control_name);
589 }
590 break;
591 case PROP_LOWER:
592 {
593 automation_edit->lower = g_value_get_double(value);
594
595 gtk_widget_queue_draw((GtkWidget *) automation_edit);
596 }
597 break;
598 case PROP_UPPER:
599 {
600 automation_edit->upper = g_value_get_double(value);
601
602 gtk_widget_queue_draw((GtkWidget *) automation_edit);
603 }
604 break;
605 case PROP_DEFAULT_VALUE:
606 {
607 automation_edit->default_value = g_value_get_double(value);
608
609 gtk_widget_queue_draw((GtkWidget *) automation_edit);
610 }
611 break;
612 default:
613 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
614 break;
615 }
616 }
617
618 void
ags_automation_edit_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)619 ags_automation_edit_get_property(GObject *gobject,
620 guint prop_id,
621 GValue *value,
622 GParamSpec *param_spec)
623 {
624 AgsAutomationEdit *automation_edit;
625
626 automation_edit = AGS_AUTOMATION_EDIT(gobject);
627
628 switch(prop_id){
629 case PROP_CHANNEL_TYPE:
630 {
631 g_value_set_gtype(value, automation_edit->channel_type);
632 }
633 break;
634 case PROP_FILENAME:
635 {
636 g_value_set_string(value, automation_edit->filename);
637 }
638 break;
639 case PROP_EFFECT:
640 {
641 g_value_set_string(value, automation_edit->effect);
642 }
643 break;
644 case PROP_CONTROL_SPECIFIER:
645 {
646 g_value_set_string(value, automation_edit->control_specifier);
647 }
648 break;
649 case PROP_CONTROL_NAME:
650 {
651 g_value_set_string(value, automation_edit->control_name);
652 }
653 break;
654 case PROP_LOWER:
655 {
656 g_value_set_double(value,
657 automation_edit->lower);
658 }
659 break;
660 case PROP_UPPER:
661 {
662 g_value_set_double(value,
663 automation_edit->upper);
664 }
665 break;
666 case PROP_DEFAULT_VALUE:
667 {
668 g_value_set_double(value,
669 automation_edit->default_value);
670 }
671 break;
672 default:
673 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
674 break;
675 }
676 }
677
678 void
ags_automation_edit_finalize(GObject * gobject)679 ags_automation_edit_finalize(GObject *gobject)
680 {
681 AgsAutomationEdit *automation_edit;
682
683 automation_edit = AGS_AUTOMATION_EDIT(gobject);
684
685 /* remove auto scroll */
686 g_hash_table_remove(ags_automation_edit_auto_scroll,
687 automation_edit);
688
689 /* call parent */
690 G_OBJECT_CLASS(ags_automation_edit_parent_class)->finalize(gobject);
691 }
692
693 void
ags_automation_edit_connect(AgsConnectable * connectable)694 ags_automation_edit_connect(AgsConnectable *connectable)
695 {
696 AgsAutomationEditor *automation_editor;
697 AgsAutomationEdit *automation_edit;
698
699 automation_edit = AGS_AUTOMATION_EDIT(connectable);
700
701 if((AGS_AUTOMATION_EDIT_CONNECTED & (automation_edit->flags)) != 0){
702 return;
703 }
704
705 automation_edit->flags |= AGS_AUTOMATION_EDIT_CONNECTED;
706
707 /* drawing area */
708 g_signal_connect(G_OBJECT(automation_edit->drawing_area), "draw",
709 G_CALLBACK(ags_automation_edit_draw_callback), (gpointer) automation_edit);
710
711 g_signal_connect_after((GObject *) automation_edit->drawing_area, "configure_event",
712 G_CALLBACK(ags_automation_edit_drawing_area_configure_event), (gpointer) automation_edit);
713
714 g_signal_connect((GObject *) automation_edit->drawing_area, "button_press_event",
715 G_CALLBACK(ags_automation_edit_drawing_area_button_press_event), (gpointer) automation_edit);
716
717 g_signal_connect((GObject *) automation_edit->drawing_area, "button_release_event",
718 G_CALLBACK(ags_automation_edit_drawing_area_button_release_event), (gpointer) automation_edit);
719
720 g_signal_connect((GObject *) automation_edit->drawing_area, "motion_notify_event",
721 G_CALLBACK(ags_automation_edit_drawing_area_motion_notify_event), (gpointer) automation_edit);
722
723 g_signal_connect((GObject *) automation_edit->drawing_area, "key_press_event",
724 G_CALLBACK(ags_automation_edit_drawing_area_key_press_event), (gpointer) automation_edit);
725
726 g_signal_connect((GObject *) automation_edit->drawing_area, "key_release_event",
727 G_CALLBACK(ags_automation_edit_drawing_area_key_release_event), (gpointer) automation_edit);
728
729 /* scrollbars */
730 g_signal_connect_after((GObject *) automation_edit->vscrollbar, "value-changed",
731 G_CALLBACK(ags_automation_edit_vscrollbar_value_changed), (gpointer) automation_edit);
732
733 g_signal_connect_after((GObject *) automation_edit->hscrollbar, "value-changed",
734 G_CALLBACK(ags_automation_edit_hscrollbar_value_changed), (gpointer) automation_edit);
735 }
736
737 void
ags_automation_edit_disconnect(AgsConnectable * connectable)738 ags_automation_edit_disconnect(AgsConnectable *connectable)
739 {
740 AgsAutomationEditor *automation_editor;
741 AgsAutomationEdit *automation_edit;
742
743 automation_edit = AGS_AUTOMATION_EDIT(connectable);
744
745 if((AGS_AUTOMATION_EDIT_CONNECTED & (automation_edit->flags)) == 0){
746 return;
747 }
748
749 automation_edit->flags &= (~AGS_AUTOMATION_EDIT_CONNECTED);
750
751 /* drawing area */
752 g_object_disconnect((GObject *) automation_edit->drawing_area,
753 "any_signal::draw",
754 G_CALLBACK(ags_automation_edit_draw_callback),
755 (gpointer) automation_edit,
756 "any_signal::configure_event",
757 G_CALLBACK(ags_automation_edit_drawing_area_configure_event),
758 automation_edit,
759 "any_signal::button_press_event",
760 G_CALLBACK(ags_automation_edit_drawing_area_button_press_event),
761 automation_edit,
762 "any_signal::button_release_event",
763 G_CALLBACK(ags_automation_edit_drawing_area_button_release_event),
764 automation_edit,
765 "any_signal::motion_notify_event",
766 G_CALLBACK(ags_automation_edit_drawing_area_motion_notify_event),
767 automation_edit,
768 "any_signal::key_press_event",
769 G_CALLBACK(ags_automation_edit_drawing_area_key_press_event),
770 automation_edit,
771 "any_signal::key_release_event",
772 G_CALLBACK(ags_automation_edit_drawing_area_key_release_event),
773 automation_edit,
774 NULL);
775
776 /* scrollbars */
777 g_object_disconnect((GObject *) automation_edit->vscrollbar,
778 "any_signal::value-changed",
779 G_CALLBACK(ags_automation_edit_vscrollbar_value_changed),
780 (gpointer) automation_edit,
781 NULL);
782
783 g_object_disconnect((GObject *) automation_edit->hscrollbar,
784 "any_signal::value-changed",
785 G_CALLBACK(ags_automation_edit_hscrollbar_value_changed),
786 (gpointer) automation_edit,
787 NULL);
788 }
789
790 AtkObject*
ags_automation_edit_get_accessible(GtkWidget * widget)791 ags_automation_edit_get_accessible(GtkWidget *widget)
792 {
793 AtkObject* accessible;
794
795 accessible = g_object_get_qdata(G_OBJECT(widget),
796 quark_accessible_object);
797
798 if(!accessible){
799 accessible = g_object_new(ags_accessible_automation_edit_get_type(),
800 NULL);
801
802 g_object_set_qdata(G_OBJECT(widget),
803 quark_accessible_object,
804 accessible);
805 gtk_accessible_set_widget(GTK_ACCESSIBLE(accessible),
806 widget);
807 }
808
809 return(accessible);
810 }
811
812 gboolean
ags_accessible_automation_edit_do_action(AtkAction * action,gint i)813 ags_accessible_automation_edit_do_action(AtkAction *action,
814 gint i)
815 {
816 AgsAutomationEdit *automation_edit;
817
818 GdkEventKey *key_press, *key_release;
819 GdkEventKey *modifier_press, *modifier_release;
820 GdkEventKey *second_level_press, *second_level_release;
821
822 if(!(i >= 0 && i < 13)){
823 return(FALSE);
824 }
825
826 automation_edit = (AgsAutomationEdit *) gtk_accessible_get_widget(GTK_ACCESSIBLE(action));
827
828 key_press = (GdkEventKey *) gdk_event_new(GDK_KEY_PRESS);
829 key_release = (GdkEventKey *) gdk_event_new(GDK_KEY_RELEASE);
830
831 /* create modifier */
832 modifier_press = (GdkEventKey *) gdk_event_new(GDK_KEY_PRESS);
833 modifier_release = (GdkEventKey *) gdk_event_new(GDK_KEY_RELEASE);
834
835 modifier_press->keyval =
836 modifier_release->keyval = GDK_KEY_Control_R;
837
838 /* create second level */
839 second_level_press = (GdkEventKey *) gdk_event_new(GDK_KEY_PRESS);
840 second_level_release = (GdkEventKey *) gdk_event_new(GDK_KEY_RELEASE);
841
842 second_level_press->keyval =
843 second_level_release->keyval = GDK_KEY_Shift_R;
844
845 switch(i){
846 case 0:
847 {
848 key_press->keyval =
849 key_release->keyval = GDK_KEY_Left;
850
851 /* send event */
852 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
853 (GdkEvent *) key_press);
854 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
855 (GdkEvent *) key_release);
856 }
857 break;
858 case 1:
859 {
860 key_press->keyval =
861 key_release->keyval = GDK_KEY_Right;
862
863 /* send event */
864 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
865 (GdkEvent *) key_press);
866 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
867 (GdkEvent *) key_release);
868 }
869 break;
870 case 2:
871 {
872 key_press->keyval =
873 key_release->keyval = GDK_KEY_Up;
874
875 /* send event */
876 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
877 (GdkEvent *) key_press);
878 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
879 (GdkEvent *) key_release);
880 }
881 break;
882 case 3:
883 {
884 key_press->keyval =
885 key_release->keyval = GDK_KEY_Down;
886
887 /* send event */
888 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
889 (GdkEvent *) key_press);
890 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
891 (GdkEvent *) key_release);
892 }
893 break;
894 case 4:
895 {
896 key_press->keyval =
897 key_release->keyval = GDK_KEY_Left;
898
899 /* send event */
900 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
901 (GdkEvent *) second_level_press);
902 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
903 (GdkEvent *) key_press);
904 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
905 (GdkEvent *) key_release);
906 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
907 (GdkEvent *) second_level_release);
908 }
909 break;
910 case 5:
911 {
912 key_press->keyval =
913 key_release->keyval = GDK_KEY_Right;
914
915 /* send event */
916 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
917 (GdkEvent *) second_level_press);
918 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
919 (GdkEvent *) key_press);
920 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
921 (GdkEvent *) key_release);
922 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
923 (GdkEvent *) second_level_release);
924 }
925 break;
926 case 6:
927 {
928 key_press->keyval =
929 key_release->keyval = GDK_KEY_Up;
930
931 /* send event */
932 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
933 (GdkEvent *) second_level_press);
934 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
935 (GdkEvent *) key_press);
936 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
937 (GdkEvent *) key_release);
938 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
939 (GdkEvent *) second_level_release);
940 }
941 break;
942 case 7:
943 {
944 key_press->keyval =
945 key_release->keyval = GDK_KEY_Down;
946
947 /* send event */
948 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
949 (GdkEvent *) second_level_press);
950 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
951 (GdkEvent *) key_press);
952 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
953 (GdkEvent *) key_release);
954 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
955 (GdkEvent *) second_level_release);
956 }
957 break;
958 case 8:
959 {
960 key_press->keyval =
961 key_release->keyval = GDK_KEY_space;
962
963 /* send event */
964 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
965 (GdkEvent *) key_press);
966 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
967 (GdkEvent *) key_release);
968 }
969 break;
970 case 9:
971 {
972 key_press->keyval =
973 key_release->keyval = GDK_KEY_Delete;
974
975 /* send event */
976 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
977 (GdkEvent *) key_press);
978 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
979 (GdkEvent *) key_release);
980 }
981 break;
982 case 10:
983 {
984 key_press->keyval =
985 key_release->keyval = GDK_KEY_c;
986
987 /* send event */
988 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
989 (GdkEvent *) modifier_press);
990 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
991 (GdkEvent *) key_press);
992 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
993 (GdkEvent *) key_release);
994 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
995 (GdkEvent *) modifier_release);
996 }
997 break;
998 case 11:
999 {
1000 key_press->keyval =
1001 key_release->keyval = GDK_KEY_x;
1002
1003 /* send event */
1004 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
1005 (GdkEvent *) modifier_press);
1006 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
1007 (GdkEvent *) key_press);
1008 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
1009 (GdkEvent *) key_release);
1010 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
1011 (GdkEvent *) modifier_release);
1012 }
1013 break;
1014 case 12:
1015 {
1016 key_press->keyval =
1017 key_release->keyval = GDK_KEY_v;
1018
1019 /* send event */
1020 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
1021 (GdkEvent *) modifier_press);
1022 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
1023 (GdkEvent *) key_press);
1024 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
1025 (GdkEvent *) key_release);
1026 gtk_widget_event((GtkWidget *) automation_edit->drawing_area,
1027 (GdkEvent *) modifier_release);
1028 }
1029 break;
1030 }
1031
1032 return(TRUE);
1033 }
1034
1035 gint
ags_accessible_automation_edit_get_n_actions(AtkAction * action)1036 ags_accessible_automation_edit_get_n_actions(AtkAction *action)
1037 {
1038 return(13);
1039 }
1040
1041 const gchar*
ags_accessible_automation_edit_get_description(AtkAction * action,gint i)1042 ags_accessible_automation_edit_get_description(AtkAction *action,
1043 gint i)
1044 {
1045 static const gchar *actions[] = {
1046 "move cursor left",
1047 "move cursor right",
1048 "move cursor up",
1049 "move cursor down",
1050 "move cursor relative up",
1051 "move cursor relative down",
1052 "move cursor small left",
1053 "move cursor small right",
1054 "add acceleration",
1055 "remove acceleration",
1056 "copy automation to clipboard",
1057 "cut automation to clipboard",
1058 "paste automation from clipboard",
1059 };
1060
1061 if(i >= 0 && i < 13){
1062 return(actions[i]);
1063 }else{
1064 return(NULL);
1065 }
1066 }
1067
1068 const gchar*
ags_accessible_automation_edit_get_name(AtkAction * action,gint i)1069 ags_accessible_automation_edit_get_name(AtkAction *action,
1070 gint i)
1071 {
1072 static const gchar *actions[] = {
1073 "left",
1074 "right",
1075 "up",
1076 "down",
1077 "small-left",
1078 "small-right",
1079 "relative-up",
1080 "relative-down",
1081 "add",
1082 "remove",
1083 "copy",
1084 "cut",
1085 "paste",
1086 };
1087
1088 if(i >= 0 && i < 13){
1089 return(actions[i]);
1090 }else{
1091 return(NULL);
1092 }
1093 }
1094
1095 const gchar*
ags_accessible_automation_edit_get_keybinding(AtkAction * action,gint i)1096 ags_accessible_automation_edit_get_keybinding(AtkAction *action,
1097 gint i)
1098 {
1099 static const gchar *actions[] = {
1100 "left",
1101 "right",
1102 "up",
1103 "down",
1104 "Shft+Left",
1105 "Shft+Right",
1106 "Shft+up",
1107 "Schft+down",
1108 "space",
1109 "Del"
1110 "Ctrl+c"
1111 "Ctrl+x",
1112 "Ctrl+v",
1113 };
1114
1115 if(i >= 0 && i < 13){
1116 return(actions[i]);
1117 }else{
1118 return(NULL);
1119 }
1120 }
1121
1122 gboolean
ags_accessible_automation_edit_set_description(AtkAction * action,gint i)1123 ags_accessible_automation_edit_set_description(AtkAction *action,
1124 gint i)
1125 {
1126 //TODO:JK: implement me
1127
1128 return(FALSE);
1129 }
1130
1131 gchar*
ags_accessible_automation_edit_get_localized_name(AtkAction * action,gint i)1132 ags_accessible_automation_edit_get_localized_name(AtkAction *action,
1133 gint i)
1134 {
1135 //TODO:JK: implement me
1136
1137 return(NULL);
1138 }
1139
1140 void
ags_automation_edit_get_preferred_width(GtkWidget * widget,gint * minimal_width,gint * natural_width)1141 ags_automation_edit_get_preferred_width(GtkWidget *widget,
1142 gint *minimal_width,
1143 gint *natural_width)
1144 {
1145 minimal_width =
1146 natural_width = NULL;
1147 }
1148
1149 void
ags_automation_edit_get_preferred_height(GtkWidget * widget,gint * minimal_height,gint * natural_height)1150 ags_automation_edit_get_preferred_height(GtkWidget *widget,
1151 gint *minimal_height,
1152 gint *natural_height)
1153 {
1154 AgsApplicationContext *application_context;
1155
1156 gdouble gui_scale_factor;
1157
1158 application_context = ags_application_context_get_instance();
1159
1160 /* scale factor */
1161 gui_scale_factor = ags_ui_provider_get_gui_scale_factor(AGS_UI_PROVIDER(application_context));
1162
1163 minimal_height[0] =
1164 natural_height[0] = (gint) (gui_scale_factor * AGS_SCALE_DEFAULT_SCALE_HEIGHT);
1165 }
1166
1167 void
ags_automation_edit_size_allocate(GtkWidget * widget,GtkAllocation * allocation)1168 ags_automation_edit_size_allocate(GtkWidget *widget,
1169 GtkAllocation *allocation)
1170 {
1171 AgsAutomationEdit *automation_edit;
1172
1173 GtkAllocation child_allocation;
1174
1175 GdkWindow *window;
1176
1177 AgsApplicationContext *application_context;
1178
1179 gdouble gui_scale_factor;
1180
1181 automation_edit = AGS_AUTOMATION_EDIT(widget);
1182
1183 application_context = ags_application_context_get_instance();
1184
1185 /* scale factor */
1186 gui_scale_factor = ags_ui_provider_get_gui_scale_factor(AGS_UI_PROVIDER(application_context));
1187
1188 // widget->allocation = *allocation;
1189
1190 // widget->allocation.height = (gint) (gui_scale_factor * AGS_SCALE_DEFAULT_SCALE_HEIGHT);
1191 allocation->height = (gint) (gui_scale_factor * AGS_SCALE_DEFAULT_SCALE_HEIGHT);
1192
1193 child_allocation.x = allocation->x;
1194 child_allocation.y = allocation->y;
1195
1196 child_allocation.width = allocation->width;
1197 child_allocation.height = (gint) (gui_scale_factor * AGS_SCALE_DEFAULT_SCALE_HEIGHT);
1198
1199 gtk_widget_size_allocate((GtkWidget *) automation_edit->drawing_area,
1200 &child_allocation);
1201
1202 window = gtk_widget_get_window((GtkWidget *) automation_edit->drawing_area);
1203 gdk_window_move(window,
1204 allocation->x, allocation->y);
1205 }
1206
1207 void
ags_automation_edit_show(GtkWidget * widget)1208 ags_automation_edit_show(GtkWidget *widget)
1209 {
1210 AgsAutomationEdit *automation_edit;
1211
1212 automation_edit = AGS_AUTOMATION_EDIT(widget);
1213
1214 /* call parent */
1215 GTK_WIDGET_CLASS(ags_automation_edit_parent_class)->show(widget);
1216
1217 gtk_widget_show((GtkWidget *) automation_edit->drawing_area);
1218
1219 if((AGS_AUTOMATION_EDIT_SHOW_RULER & (automation_edit->flags)) != 0){
1220 gtk_widget_show((GtkWidget *) automation_edit->ruler);
1221 }
1222
1223 if((AGS_AUTOMATION_EDIT_SHOW_VSCROLLBAR & (automation_edit->flags)) != 0){
1224 gtk_widget_show((GtkWidget *) automation_edit->vscrollbar);
1225 }
1226
1227 if((AGS_AUTOMATION_EDIT_SHOW_HSCROLLBAR & (automation_edit->flags)) != 0){
1228 gtk_widget_show((GtkWidget *) automation_edit->hscrollbar);
1229 }
1230 }
1231
1232 void
ags_automation_edit_show_all(GtkWidget * widget)1233 ags_automation_edit_show_all(GtkWidget *widget)
1234 {
1235 AgsAutomationEdit *automation_edit;
1236
1237 automation_edit = AGS_AUTOMATION_EDIT(widget);
1238
1239 /* call parent */
1240 GTK_WIDGET_CLASS(ags_automation_edit_parent_class)->show_all(widget);
1241
1242 gtk_widget_show_all((GtkWidget *) automation_edit->drawing_area);
1243
1244 if((AGS_AUTOMATION_EDIT_SHOW_RULER & (automation_edit->flags)) != 0){
1245 gtk_widget_show((GtkWidget *) automation_edit->ruler);
1246 }
1247
1248 if((AGS_AUTOMATION_EDIT_SHOW_VSCROLLBAR & (automation_edit->flags)) != 0){
1249 gtk_widget_show((GtkWidget *) automation_edit->vscrollbar);
1250 }
1251
1252 if((AGS_AUTOMATION_EDIT_SHOW_HSCROLLBAR & (automation_edit->flags)) != 0){
1253 gtk_widget_show((GtkWidget *) automation_edit->hscrollbar);
1254 }
1255 }
1256
1257 gboolean
ags_automation_edit_auto_scroll_timeout(GtkWidget * widget)1258 ags_automation_edit_auto_scroll_timeout(GtkWidget *widget)
1259 {
1260 if(g_hash_table_lookup(ags_automation_edit_auto_scroll,
1261 widget) != NULL){
1262 AgsAutomationEditor *automation_editor;
1263 AgsAutomationEdit *automation_edit;
1264
1265 GtkAdjustment *hscrollbar_adjustment;
1266
1267 GObject *output_soundcard;
1268
1269 double x;
1270
1271 automation_edit = AGS_AUTOMATION_EDIT(widget);
1272
1273 if((AGS_AUTOMATION_EDIT_AUTO_SCROLL & (automation_edit->flags)) == 0){
1274 return(TRUE);
1275 }
1276
1277 automation_editor = (AgsAutomationEditor *) gtk_widget_get_ancestor((GtkWidget *) automation_edit,
1278 AGS_TYPE_AUTOMATION_EDITOR);
1279
1280 if(automation_editor->selected_machine == NULL){
1281 return(TRUE);
1282 }
1283
1284 /* reset offset */
1285 g_object_get(automation_editor->selected_machine->audio,
1286 "output-soundcard", &output_soundcard,
1287 NULL);
1288
1289 automation_edit->note_offset = ags_soundcard_get_note_offset(AGS_SOUNDCARD(output_soundcard));
1290 automation_edit->note_offset_absolute = ags_soundcard_get_note_offset_absolute(AGS_SOUNDCARD(output_soundcard));
1291
1292 /* reset scrollbar */
1293 hscrollbar_adjustment = gtk_range_get_adjustment(GTK_RANGE(automation_edit->hscrollbar));
1294 x = ((automation_edit->note_offset * automation_edit->control_width) / (AGS_AUTOMATION_EDITOR_MAX_CONTROLS * automation_edit->control_width)) * gtk_adjustment_get_upper(hscrollbar_adjustment);
1295
1296 gtk_range_set_value(GTK_RANGE(automation_edit->hscrollbar),
1297 x);
1298
1299 g_object_unref(output_soundcard);
1300
1301 return(TRUE);
1302 }else{
1303 return(FALSE);
1304 }
1305 }
1306
1307 void
ags_automation_edit_reset_vscrollbar(AgsAutomationEdit * automation_edit)1308 ags_automation_edit_reset_vscrollbar(AgsAutomationEdit *automation_edit)
1309 {
1310 AgsAutomationEditor *automation_editor;
1311
1312 GtkAdjustment *adjustment;
1313
1314 GtkAllocation allocation;
1315
1316 double varea_height;
1317 gdouble upper, old_upper;
1318
1319 if(!AGS_IS_AUTOMATION_EDIT(automation_edit)){
1320 return;
1321 }
1322
1323 automation_editor = (AgsAutomationEditor *) gtk_widget_get_ancestor((GtkWidget *) automation_edit,
1324 AGS_TYPE_AUTOMATION_EDITOR);
1325
1326 if(automation_editor->selected_machine == NULL){
1327 return;
1328 }
1329
1330 /* adjustment and allocation */
1331 adjustment = gtk_range_get_adjustment(GTK_RANGE(automation_edit->vscrollbar));
1332
1333 gtk_widget_get_allocation(GTK_WIDGET(automation_edit->drawing_area),
1334 &allocation);
1335
1336 /* upper */
1337 old_upper = gtk_adjustment_get_upper(adjustment);
1338
1339 varea_height = (automation_edit->step_count * automation_edit->control_height);
1340 upper = varea_height - allocation.height;
1341
1342 if(upper < 0.0){
1343 upper = 0.0;
1344 }
1345
1346 gtk_adjustment_set_upper(adjustment,
1347 upper);
1348
1349 /* reset value */
1350 if(old_upper != 0.0){
1351 gtk_adjustment_set_value(adjustment,
1352 gtk_adjustment_get_value(adjustment) / old_upper * upper);
1353 }
1354 }
1355
1356 void
ags_automation_edit_reset_hscrollbar(AgsAutomationEdit * automation_edit)1357 ags_automation_edit_reset_hscrollbar(AgsAutomationEdit *automation_edit)
1358 {
1359 AgsAutomationEditor *automation_editor;
1360 AgsAutomationToolbar *automation_toolbar;
1361
1362 GtkAdjustment *adjustment;
1363
1364 AgsApplicationContext *application_context;
1365
1366 GtkAllocation allocation;
1367
1368 gdouble gui_scale_factor;
1369 double zoom_factor, zoom;
1370 double zoom_correction;
1371 guint map_width;
1372 gdouble upper, old_upper;
1373
1374 if(!AGS_IS_AUTOMATION_EDIT(automation_edit)){
1375 return;
1376 }
1377
1378 automation_editor = (AgsAutomationEditor *) gtk_widget_get_ancestor((GtkWidget *) automation_edit,
1379 AGS_TYPE_AUTOMATION_EDITOR);
1380
1381 if(automation_editor->selected_machine == NULL){
1382 return;
1383 }
1384
1385 automation_toolbar = automation_editor->automation_toolbar;
1386
1387 application_context = ags_application_context_get_instance();
1388
1389 /* scale factor */
1390 gui_scale_factor = ags_ui_provider_get_gui_scale_factor(AGS_UI_PROVIDER(application_context));
1391
1392 /* adjustment and allocation */
1393 adjustment = gtk_range_get_adjustment(GTK_RANGE(automation_edit->hscrollbar));
1394
1395 gtk_widget_get_allocation(GTK_WIDGET(automation_edit->drawing_area),
1396 &allocation);
1397
1398 /* zoom */
1399 zoom_factor = exp2(6.0 - (double) gtk_combo_box_get_active((GtkComboBox *) automation_toolbar->zoom));
1400 zoom = exp2((double) gtk_combo_box_get_active((GtkComboBox *) automation_toolbar->zoom) - 2.0);
1401
1402 /* upper */
1403 old_upper = gtk_adjustment_get_upper(adjustment);
1404
1405 zoom_correction = 1.0 / 16;
1406
1407 // map_width = ((double) AGS_AUTOMATION_EDITOR_MAX_CONTROLS * zoom * zoom_correction);
1408 map_width = ((64.0) * (16.0 * 16.0 * 1200.0) * zoom * zoom_correction);
1409 upper = map_width - allocation.width;
1410
1411 if(upper < 0.0){
1412 upper = 0.0;
1413 }
1414
1415 gtk_adjustment_set_upper(adjustment,
1416 upper);
1417
1418 /* ruler */
1419 automation_edit->ruler->factor = zoom_factor;
1420 automation_edit->ruler->precision = zoom;
1421 automation_edit->ruler->scale_precision = 1.0 / zoom;
1422
1423 gtk_adjustment_set_upper(automation_edit->ruler->adjustment,
1424 upper);
1425
1426 /* reset value */
1427 if(old_upper != 0.0){
1428 #if 0
1429 gtk_adjustment_set_value(adjustment,
1430 gtk_adjustment_get_value(adjustment) / old_upper * upper);
1431 #endif
1432 }
1433 }
1434
1435 void
ags_automation_edit_draw_segment(AgsAutomationEdit * automation_edit,cairo_t * cr)1436 ags_automation_edit_draw_segment(AgsAutomationEdit *automation_edit, cairo_t *cr)
1437 {
1438 AgsAutomationEditor *automation_editor;
1439 AgsAutomationToolbar *automation_toolbar;
1440
1441 GtkStyleContext *automation_edit_style_context;
1442
1443 GtkAdjustment *hscrollbar_adjustment;
1444
1445 AgsApplicationContext *application_context;
1446
1447 GtkAllocation allocation;
1448
1449 GdkRGBA *fg_color;
1450 GdkRGBA *bg_color;
1451 GdkRGBA *border_color;
1452
1453 gdouble gui_scale_factor;
1454 gdouble x_offset;
1455 gdouble translated_ground;
1456 double tact;
1457 gdouble y;
1458 gdouble map_height;
1459 gdouble width, height;
1460 guint control_width;
1461 guint i, j;
1462 guint j_set;
1463
1464 GValue value = {0,};
1465
1466 const static double quarter_dashes = {
1467 0.25,
1468 };
1469
1470 const static double segment_dashes = {
1471 0.5,
1472 };
1473
1474 if(!AGS_IS_AUTOMATION_EDIT(automation_edit)){
1475 return;
1476 }
1477
1478 application_context = ags_application_context_get_instance();
1479
1480 automation_editor = (AgsAutomationEditor *) gtk_widget_get_ancestor((GtkWidget *) automation_edit,
1481 AGS_TYPE_AUTOMATION_EDITOR);
1482
1483 if(automation_editor->selected_machine == NULL){
1484 return;
1485 }
1486
1487 automation_toolbar = automation_editor->automation_toolbar;
1488
1489 gtk_widget_get_allocation(GTK_WIDGET(automation_edit->drawing_area),
1490 &allocation);
1491
1492 /* scale factor */
1493 gui_scale_factor = ags_ui_provider_get_gui_scale_factor(AGS_UI_PROVIDER(application_context));
1494
1495 /* dimension and offset */
1496 width = (gdouble) allocation.width;
1497 height = (gdouble) allocation.height;
1498
1499 hscrollbar_adjustment = gtk_range_get_adjustment(GTK_RANGE(automation_edit->hscrollbar));
1500
1501 x_offset = gtk_adjustment_get_value(hscrollbar_adjustment);
1502
1503 y = 0.0;
1504
1505 /* style context */
1506 automation_edit_style_context = gtk_widget_get_style_context(GTK_WIDGET(automation_edit->drawing_area));
1507
1508 gtk_style_context_get_property(automation_edit_style_context,
1509 "color",
1510 GTK_STATE_FLAG_NORMAL,
1511 &value);
1512
1513 fg_color = g_value_dup_boxed(&value);
1514 g_value_unset(&value);
1515
1516 gtk_style_context_get_property(automation_edit_style_context,
1517 "background-color",
1518 GTK_STATE_FLAG_NORMAL,
1519 &value);
1520
1521 bg_color = g_value_dup_boxed(&value);
1522 g_value_unset(&value);
1523
1524 gtk_style_context_get_property(automation_edit_style_context,
1525 "border-color",
1526 GTK_STATE_FLAG_NORMAL,
1527 &value);
1528
1529 border_color = g_value_dup_boxed(&value);
1530 g_value_unset(&value);
1531
1532 /* push group */
1533 cairo_push_group(cr);
1534
1535 /* background */
1536 cairo_set_source_rgba(cr,
1537 bg_color->red,
1538 bg_color->green,
1539 bg_color->blue,
1540 bg_color->alpha);
1541
1542 cairo_rectangle(cr, 0.0, y, width, height);
1543 cairo_fill(cr);
1544
1545 /* border */
1546 cairo_set_source_rgba(cr,
1547 border_color->red,
1548 border_color->green,
1549 border_color->blue,
1550 border_color->alpha);
1551
1552 cairo_set_line_width(cr, 1.0);
1553 cairo_rectangle(cr, 0.0, y, width, height);
1554 cairo_stroke(cr);
1555
1556 cairo_set_line_width(cr, 1.0);
1557
1558 tact = exp2((double) gtk_combo_box_get_active(automation_toolbar->zoom) - 2.0);
1559
1560 y = (gdouble) 0.0;
1561
1562 map_height = (gdouble) height;
1563
1564 control_width = (gint) (gui_scale_factor * (gdouble) AGS_AUTOMATION_EDIT_DEFAULT_CONTROL_WIDTH) * (tact / (gui_scale_factor * tact));
1565 i = control_width - (guint) x_offset % control_width;
1566
1567 cairo_set_source_rgba(cr,
1568 fg_color->red,
1569 fg_color->blue,
1570 fg_color->green,
1571 fg_color->alpha);
1572
1573 if(i < width &&
1574 tact > 1.0 ){
1575 j_set = ((guint) x_offset / control_width + 1) % ((guint) tact);
1576
1577 cairo_set_dash(cr,
1578 &segment_dashes,
1579 1,
1580 0.0);
1581
1582 if(j_set != 0){
1583 j = j_set;
1584 goto ags_automation_edit_draw_segment0;
1585 }
1586 }
1587
1588 for(; i < width; ){
1589 cairo_set_dash(cr,
1590 NULL,
1591 0,
1592 0.0);
1593
1594 cairo_move_to(cr, (double) i, y);
1595 cairo_line_to(cr, (double) i, y + height);
1596 cairo_stroke(cr);
1597
1598 i += control_width;
1599
1600 cairo_set_dash(cr,
1601 &segment_dashes,
1602 1,
1603 0.0);
1604
1605 for(j = 1; i < width && j < tact; j++){
1606 ags_automation_edit_draw_segment0:
1607 cairo_move_to(cr, (double) i, y);
1608 cairo_line_to(cr, (double) i, y + height);
1609 cairo_stroke(cr);
1610
1611 i += control_width;
1612 }
1613 }
1614
1615 cairo_set_source_rgba(cr,
1616 fg_color->red,
1617 fg_color->green,
1618 fg_color->blue,
1619 fg_color->alpha);
1620
1621 /* middle */
1622 if(map_height * 0.5 < height){
1623 cairo_move_to(cr,
1624 0.0, y + map_height * 0.5);
1625 cairo_line_to(cr,
1626 width, y + map_height * 0.5);
1627 cairo_stroke(cr);
1628 }
1629
1630 /* set dash */
1631 cairo_set_dash(cr,
1632 &quarter_dashes,
1633 1,
1634 0.0);
1635
1636 /* lower quarter */
1637 if(map_height * 0.25 < height){
1638 cairo_move_to(cr,
1639 0.0, y + map_height * 0.25);
1640 cairo_line_to(cr,
1641 width, y + map_height * 0.25);
1642 cairo_stroke(cr);
1643 }
1644
1645 /* upper quarter */
1646 if(map_height * 0.75 < height){
1647 cairo_move_to(cr,
1648 0.0, y + map_height * 0.75);
1649 cairo_line_to(cr,
1650 width, y + map_height * 0.75);
1651 cairo_stroke(cr);
1652 }
1653
1654 /* complete */
1655 cairo_pop_group_to_source(cr);
1656 cairo_paint(cr);
1657
1658 // cairo_surface_mark_dirty(cairo_get_target(cr));
1659
1660 g_boxed_free(GDK_TYPE_RGBA, fg_color);
1661 g_boxed_free(GDK_TYPE_RGBA, bg_color);
1662 g_boxed_free(GDK_TYPE_RGBA, border_color);
1663 }
1664
1665 void
ags_automation_edit_draw_position(AgsAutomationEdit * automation_edit,cairo_t * cr)1666 ags_automation_edit_draw_position(AgsAutomationEdit *automation_edit, cairo_t *cr)
1667 {
1668 AgsAutomationEditor *automation_editor;
1669 AgsAutomationToolbar *automation_toolbar;
1670
1671 GtkStyleContext *automation_edit_style_context;
1672
1673 AgsApplicationContext *application_context;
1674
1675 GdkRGBA *fg_color_active;
1676
1677 gdouble gui_scale_factor;
1678 gdouble tact;
1679 guint control_width;
1680 double position;
1681 double x, y;
1682 double width, height;
1683 gboolean height_fits;
1684
1685 GValue value = {0,};
1686
1687 if(!AGS_IS_AUTOMATION_EDIT(automation_edit)){
1688 return;
1689 }
1690
1691 application_context = ags_application_context_get_instance();
1692
1693 automation_editor = (AgsAutomationEditor *) gtk_widget_get_ancestor((GtkWidget *) automation_edit,
1694 AGS_TYPE_AUTOMATION_EDITOR);
1695
1696 if(automation_editor->selected_machine == NULL){
1697 return;
1698 }
1699
1700 automation_toolbar = automation_editor->automation_toolbar;
1701
1702 /* scale factor */
1703 gui_scale_factor = ags_ui_provider_get_gui_scale_factor(AGS_UI_PROVIDER(application_context));
1704
1705 /* style context */
1706 automation_edit_style_context = gtk_widget_get_style_context(GTK_WIDGET(automation_edit->drawing_area));
1707
1708 gtk_style_context_get_property(automation_edit_style_context,
1709 "color",
1710 GTK_STATE_FLAG_ACTIVE,
1711 &value);
1712
1713 fg_color_active = g_value_dup_boxed(&value);
1714 g_value_unset(&value);
1715
1716 tact = exp2((double) gtk_combo_box_get_active(automation_toolbar->zoom) - 2.0);
1717
1718 /* get offset and dimensions */
1719 control_width = (gint) (gui_scale_factor * (gdouble) AGS_AUTOMATION_EDIT_DEFAULT_CONTROL_WIDTH) * (tact / (gui_scale_factor * tact));
1720
1721 position = ((double) automation_edit->note_offset) * ((double) control_width);
1722
1723 y = 0.0;
1724 x = (position) - (gtk_range_get_value(GTK_RANGE(automation_edit->hscrollbar)));
1725
1726 width = (double) ((guint) (gui_scale_factor * AGS_AUTOMATION_EDIT_DEFAULT_FADER_WIDTH));
1727 height = automation_edit->step_count * automation_edit->control_height;
1728
1729 /* push group */
1730 cairo_push_group(cr);
1731
1732 /* draw fader */
1733 cairo_set_source_rgba(cr,
1734 fg_color_active->red,
1735 fg_color_active->blue,
1736 fg_color_active->green,
1737 fg_color_active->alpha);
1738
1739 cairo_rectangle(cr,
1740 (double) x, (double) y,
1741 (double) width, (double) height);
1742 cairo_fill(cr);
1743
1744 /* complete */
1745 cairo_pop_group_to_source(cr);
1746 cairo_paint(cr);
1747
1748 //cairo_surface_mark_dirty(cairo_get_target(cr));
1749
1750 g_boxed_free(GDK_TYPE_RGBA, fg_color_active);
1751 }
1752
1753 void
ags_automation_edit_draw_cursor(AgsAutomationEdit * automation_edit,cairo_t * cr)1754 ags_automation_edit_draw_cursor(AgsAutomationEdit *automation_edit, cairo_t *cr)
1755 {
1756 AgsAutomationEditor *automation_editor;
1757 AgsAutomationToolbar *automation_toolbar;
1758
1759 GtkStyleContext *automation_edit_style_context;
1760
1761 AgsApplicationContext *application_context;
1762
1763 GtkAllocation allocation;
1764
1765 GdkRGBA *fg_color_focused;
1766
1767 gdouble gui_scale_factor;
1768 double zoom_factor;
1769 gdouble val, step;
1770 gdouble upper, lower, step_count;
1771 gdouble c_range;
1772 double x, y;
1773 double width, height;
1774
1775 GValue value = {0,};
1776
1777 if(!AGS_IS_AUTOMATION_EDIT(automation_edit)){
1778 return;
1779 }
1780
1781 application_context = ags_application_context_get_instance();
1782
1783 automation_editor = (AgsAutomationEditor *) gtk_widget_get_ancestor((GtkWidget *) automation_edit,
1784 AGS_TYPE_AUTOMATION_EDITOR);
1785
1786 if(automation_editor->selected_machine == NULL){
1787 return;
1788 }
1789
1790 automation_toolbar = automation_editor->automation_toolbar;
1791
1792 /* scale factor */
1793 gui_scale_factor = ags_ui_provider_get_gui_scale_factor(AGS_UI_PROVIDER(application_context));
1794
1795 /* style context */
1796 automation_edit_style_context = gtk_widget_get_style_context(GTK_WIDGET(automation_edit->drawing_area));
1797
1798 gtk_style_context_get_property(automation_edit_style_context,
1799 "color",
1800 GTK_STATE_FLAG_FOCUSED,
1801 &value);
1802
1803 fg_color_focused = g_value_dup_boxed(&value);
1804 g_value_unset(&value);
1805
1806 gtk_widget_get_allocation(GTK_WIDGET(automation_edit->drawing_area),
1807 &allocation);
1808
1809 if((AGS_AUTOMATION_EDIT_LOGARITHMIC & (automation_edit->flags)) != 0){
1810 c_range = (gdouble) ((guint) (gui_scale_factor * AGS_AUTOMATION_EDIT_DEFAULT_HEIGHT));
1811 }else{
1812 c_range = automation_edit->upper - automation_edit->lower;
1813 }
1814
1815 /* zoom */
1816 zoom_factor = exp2(6.0 - (double) gtk_combo_box_get_active((GtkComboBox *) automation_toolbar->zoom));
1817
1818 /* get offset */
1819 x = ((double) automation_edit->cursor_position_x) - (gtk_range_get_value(GTK_RANGE(automation_edit->hscrollbar)) * zoom_factor);
1820
1821 if((AGS_AUTOMATION_EDIT_LOGARITHMIC & (automation_edit->flags)) != 0){
1822 lower = automation_edit->lower;
1823 upper = automation_edit->upper;
1824
1825 step_count = ((guint) (gui_scale_factor * AGS_AUTOMATION_EDIT_DEFAULT_HEIGHT)) + 1.0;
1826
1827 val = automation_edit->cursor_position_y;
1828
1829 y = (step_count - 1) * log(val / lower) / log(upper / lower);
1830 }else{
1831 y = allocation.height - ((((double) automation_edit->cursor_position_y / c_range) * allocation.height) - gtk_range_get_value(GTK_RANGE(automation_edit->vscrollbar)));
1832 }
1833
1834 width = (double) AGS_AUTOMATION_EDIT_CURSOR_WIDTH;
1835 height = (double) AGS_AUTOMATION_EDIT_CURSOR_HEIGHT;
1836
1837 /* apply zoom */
1838 x /= zoom_factor;
1839
1840 /* clip */
1841 if(x < 0.0){
1842 width += x;
1843
1844 x = 0.0;
1845 }else if(x > allocation.width){
1846 g_boxed_free(GDK_TYPE_RGBA, fg_color_focused);
1847
1848 return;
1849 }
1850
1851 if(x + width > allocation.width){
1852 width = ((double) allocation.width) - x;
1853 }
1854
1855 if(y < 0.0){
1856 height += y;
1857
1858 y = 0.0;
1859 }else if(y > allocation.height){
1860 g_boxed_free(GDK_TYPE_RGBA, fg_color_focused);
1861
1862 return;
1863 }
1864
1865 if(y + height > allocation.height){
1866 height = ((double) allocation.height) - y;
1867 }
1868
1869 /* push group */
1870 cairo_push_group(cr);
1871
1872 /* draw cursor */
1873 cairo_set_source_rgba(cr,
1874 fg_color_focused->red,
1875 fg_color_focused->blue,
1876 fg_color_focused->green,
1877 fg_color_focused->alpha);
1878
1879 cairo_move_to(cr,
1880 x, y);
1881 cairo_line_to(cr,
1882 x + width, y);
1883 cairo_stroke(cr);
1884
1885 cairo_move_to(cr,
1886 x, y);
1887 cairo_line_to(cr,
1888 x, y + height);
1889 cairo_stroke(cr);
1890
1891 /* complete */
1892 cairo_pop_group_to_source(cr);
1893 cairo_paint(cr);
1894
1895 //cairo_surface_mark_dirty(cairo_get_target(cr));
1896
1897 g_boxed_free(GDK_TYPE_RGBA, fg_color_focused);
1898 }
1899
1900 void
ags_automation_edit_draw_selection(AgsAutomationEdit * automation_edit,cairo_t * cr)1901 ags_automation_edit_draw_selection(AgsAutomationEdit *automation_edit, cairo_t *cr)
1902 {
1903 GtkStyleContext *automation_edit_style_context;
1904
1905 AgsApplicationContext *application_context;
1906
1907 GtkAllocation allocation;
1908
1909 GdkRGBA *fg_color_prelight;
1910
1911 double x, y;
1912 double width, height;
1913
1914 GValue value = {0,};
1915
1916 if(!AGS_IS_AUTOMATION_EDIT(automation_edit)){
1917 return;
1918 }
1919
1920 application_context = ags_application_context_get_instance();
1921
1922 /* style context */
1923 automation_edit_style_context = gtk_widget_get_style_context(GTK_WIDGET(automation_edit->drawing_area));
1924
1925 gtk_style_context_get_property(automation_edit_style_context,
1926 "color",
1927 GTK_STATE_FLAG_PRELIGHT,
1928 &value);
1929
1930 fg_color_prelight = g_value_dup_boxed(&value);
1931 g_value_unset(&value);
1932
1933 gtk_widget_get_allocation(GTK_WIDGET(automation_edit->drawing_area),
1934 &allocation);
1935
1936 /* get offset and dimensions */
1937 if(automation_edit->selection_x0 < automation_edit->selection_x1){
1938 x = ((double) automation_edit->selection_x0) - gtk_range_get_value(GTK_RANGE(automation_edit->hscrollbar));
1939 width = ((double) automation_edit->selection_x1 - (double) automation_edit->selection_x0);
1940 }else{
1941 x = ((double) automation_edit->selection_x1) - gtk_range_get_value(GTK_RANGE(automation_edit->hscrollbar));
1942 width = ((double) automation_edit->selection_x0 - (double) automation_edit->selection_x1);
1943 }
1944
1945 if(automation_edit->selection_y0 < automation_edit->selection_y1){
1946 y = ((double) automation_edit->selection_y0) - gtk_range_get_value(GTK_RANGE(automation_edit->vscrollbar));
1947 height = ((double) automation_edit->selection_y1 - (double) automation_edit->selection_y0);
1948 }else{
1949 y = ((double) automation_edit->selection_y1) - gtk_range_get_value(GTK_RANGE(automation_edit->vscrollbar));
1950 height = ((double) automation_edit->selection_y0 - (double) automation_edit->selection_y1);
1951 }
1952
1953 /* clip */
1954 if(x < 0.0){
1955 width += x;
1956
1957 x = 0.0;
1958 }else if(x > allocation.width){
1959 g_boxed_free(GDK_TYPE_RGBA, fg_color_prelight);
1960
1961 return;
1962 }
1963
1964 if(x + width > allocation.width){
1965 width = ((double) allocation.width) - x;
1966 }
1967
1968 if(y < 0.0){
1969 height += y;
1970
1971 y = 0.0;
1972 }else if(y > allocation.height){
1973 g_boxed_free(GDK_TYPE_RGBA, fg_color_prelight);
1974
1975 return;
1976 }
1977
1978 if(y + height > allocation.height){
1979 height = ((double) allocation.height) - y;
1980 }
1981
1982 /* push group */
1983 cairo_push_group(cr);
1984
1985 /* draw selection */
1986 cairo_set_source_rgba(cr,
1987 fg_color_prelight->red,
1988 fg_color_prelight->blue,
1989 fg_color_prelight->green,
1990 1.0 / 3.0);
1991
1992 cairo_rectangle(cr,
1993 x, y,
1994 width, height);
1995 cairo_fill(cr);
1996
1997 /* complete */
1998 cairo_pop_group_to_source(cr);
1999 cairo_paint(cr);
2000
2001 //cairo_surface_mark_dirty(cairo_get_target(cr));
2002
2003 g_boxed_free(GDK_TYPE_RGBA, fg_color_prelight);
2004 }
2005
2006 void
ags_automation_edit_draw_acceleration(AgsAutomationEdit * automation_edit,AgsAcceleration * acceleration_a,AgsAcceleration * acceleration_b,cairo_t * cr,gdouble opacity)2007 ags_automation_edit_draw_acceleration(AgsAutomationEdit *automation_edit,
2008 AgsAcceleration *acceleration_a, AgsAcceleration *acceleration_b,
2009 cairo_t *cr,
2010 gdouble opacity)
2011 {
2012 AgsAutomationEditor *automation_editor;
2013 AgsAutomationToolbar *automation_toolbar;
2014
2015 GtkStyleContext *automation_edit_style_context;
2016
2017 AgsApplicationContext *application_context;
2018
2019 GtkAllocation allocation;
2020
2021 GdkRGBA *fg_color;
2022 GdkRGBA *fg_color_selected;
2023
2024 gdouble gui_scale_factor;
2025 double zoom_factor;
2026 double viewport_x, viewport_y;
2027 gdouble val, step;
2028 gdouble upper, lower, step_count;
2029 gdouble c_range;
2030 gint x, y;
2031 gint a_x, b_x;
2032 gdouble a_y, b_y;
2033 double width, height;
2034
2035 GValue value = {0};
2036
2037 if(!AGS_IS_AUTOMATION_EDIT(automation_edit) ||
2038 !AGS_IS_ACCELERATION(acceleration_a) ||
2039 cr == NULL){
2040 return;
2041 }
2042
2043 automation_editor = (AgsAutomationEditor *) gtk_widget_get_ancestor((GtkWidget *) automation_edit,
2044 AGS_TYPE_AUTOMATION_EDITOR);
2045
2046 if(automation_editor->selected_machine == NULL){
2047 return;
2048 }
2049
2050 application_context = ags_application_context_get_instance();
2051
2052 automation_toolbar = automation_editor->automation_toolbar;
2053
2054 /* scale factor */
2055 gui_scale_factor = ags_ui_provider_get_gui_scale_factor(AGS_UI_PROVIDER(application_context));
2056
2057 /* style context */
2058 automation_edit_style_context = gtk_widget_get_style_context(GTK_WIDGET(automation_edit->drawing_area));
2059
2060 gtk_style_context_get_property(automation_edit_style_context,
2061 "color",
2062 GTK_STATE_FLAG_NORMAL,
2063 &value);
2064
2065 fg_color = g_value_dup_boxed(&value);
2066 g_value_unset(&value);
2067
2068 gtk_style_context_get_property(automation_edit_style_context,
2069 "color",
2070 GTK_STATE_FLAG_SELECTED,
2071 &value);
2072
2073 fg_color_selected = g_value_dup_boxed(&value);
2074 g_value_unset(&value);
2075
2076 gtk_widget_get_allocation(GTK_WIDGET(automation_edit->drawing_area),
2077 &allocation);
2078
2079 if((AGS_AUTOMATION_EDIT_LOGARITHMIC & (automation_edit->flags)) != 0){
2080 c_range = (gdouble) ((guint) (gui_scale_factor * AGS_AUTOMATION_EDIT_DEFAULT_HEIGHT));
2081 }else{
2082 c_range = automation_edit->upper - automation_edit->lower;
2083 }
2084
2085 /* zoom */
2086 zoom_factor = exp2(6.0 - (double) gtk_combo_box_get_active((GtkComboBox *) automation_toolbar->zoom));
2087
2088 /* get offset and dimensions */
2089 if(AGS_AUTOMATION_EDITOR_MAX_CONTROLS > allocation.width){
2090 viewport_x = zoom_factor * gtk_range_get_value(GTK_RANGE(automation_edit->hscrollbar));
2091 }else{
2092 viewport_x = 0.0;
2093 }
2094
2095 viewport_y = gtk_range_get_value(GTK_RANGE(automation_edit->vscrollbar));
2096
2097 g_object_get(acceleration_a,
2098 "x", &a_x,
2099 "y", &a_y,
2100 NULL);
2101
2102 x = ((double) a_x) - viewport_x;
2103
2104 if((AGS_AUTOMATION_EDIT_LOGARITHMIC & (automation_edit->flags)) != 0){
2105 lower = automation_edit->lower;
2106 upper = automation_edit->upper;
2107
2108 step_count = ((guint) (gui_scale_factor * AGS_AUTOMATION_EDIT_DEFAULT_HEIGHT)) + 1.0;
2109
2110 val = a_y;
2111
2112 y = (step_count - 1.0) * log(val / lower) / log(upper / lower);
2113 }else{
2114 y = allocation.height - ((double) a_y / c_range) * allocation.height - viewport_y;
2115 }
2116
2117 if(acceleration_b != NULL){
2118 g_object_get(acceleration_b,
2119 "x", &b_x,
2120 NULL);
2121
2122 width = ((double) b_x - a_x);
2123 }else{
2124 width = ((double) allocation.width) - x;
2125 }
2126
2127 height = allocation.height - y;
2128
2129 if((AGS_AUTOMATION_EDIT_LOGARITHMIC & (automation_edit->flags)) != 0){
2130 gdouble tmp;
2131
2132 tmp = height;
2133
2134 height = y;
2135 y = tmp;
2136 }
2137
2138 /* apply zoom */
2139 x /= zoom_factor;
2140
2141 width /= zoom_factor;
2142
2143 /* clip */
2144 if(x < 0.0){
2145 if(x + width < 0.0){
2146 g_boxed_free(GDK_TYPE_RGBA, fg_color);
2147 g_boxed_free(GDK_TYPE_RGBA, fg_color_selected);
2148
2149 return;
2150 }else{
2151 width += x;
2152 x = 0.0;
2153 }
2154 }else if(x > allocation.width){
2155 g_boxed_free(GDK_TYPE_RGBA, fg_color);
2156 g_boxed_free(GDK_TYPE_RGBA, fg_color_selected);
2157
2158 return;
2159 }
2160
2161 if(x + width > allocation.width){
2162 width = ((double) allocation.width) - x;
2163 }
2164
2165 if(acceleration_b == NULL){
2166 width = ((double) allocation.width - x);
2167 }
2168
2169 if(y < 0.0){
2170 if(y + height < 0.0){
2171 g_boxed_free(GDK_TYPE_RGBA, fg_color);
2172 g_boxed_free(GDK_TYPE_RGBA, fg_color_selected);
2173
2174 return;
2175 }else{
2176 height += y;
2177 y = 0.0;
2178 }
2179 }else if(y > allocation.height){
2180 g_boxed_free(GDK_TYPE_RGBA, fg_color);
2181 g_boxed_free(GDK_TYPE_RGBA, fg_color_selected);
2182
2183 return;
2184 }
2185
2186 if(y + height > allocation.height){
2187 height = ((double) allocation.height) - y;
2188 }
2189
2190 /* draw acceleration - dot */
2191 cairo_set_source_rgba(cr,
2192 fg_color->red,
2193 fg_color->blue,
2194 fg_color->green,
2195 opacity * fg_color->alpha);
2196
2197 cairo_arc(cr,
2198 x, y,
2199 automation_edit->point_radius,
2200 0.0,
2201 2.0 * M_PI);
2202
2203 cairo_stroke(cr);
2204
2205 /* draw acceleration - area */
2206 cairo_set_source_rgba(cr,
2207 fg_color->red,
2208 fg_color->blue,
2209 fg_color->green,
2210 opacity * fg_color->alpha);
2211 cairo_rectangle(cr,
2212 x, y,
2213 width, height);
2214 cairo_fill(cr);
2215
2216 /* check acceleration selected */
2217 if(ags_acceleration_test_flags(acceleration_a, AGS_ACCELERATION_IS_SELECTED)){
2218 double selected_x, selected_y;
2219 double selected_width, selected_height;
2220
2221 selected_x = x - automation_edit->selected_acceleration_border;
2222 selected_y = y - automation_edit->selected_acceleration_border;
2223
2224 selected_width = width + (2.0 * (double) automation_edit->selected_acceleration_border);
2225 selected_height = height + (2.0 * (double) automation_edit->selected_acceleration_border);
2226
2227 /* clip */
2228 if(selected_x < 0.0){
2229 selected_x = 0.0;
2230 }
2231
2232 if(selected_x + selected_width > allocation.width){
2233 selected_width = ((double) allocation.width) - selected_x;
2234 }
2235
2236 if(selected_y < 0.0){
2237 selected_y = 0.0;
2238 }
2239
2240 if(selected_y + selected_height > allocation.height){
2241 selected_height = ((double) allocation.height) - selected_y;
2242 }
2243
2244 /* draw selected acceleration - dot */
2245 cairo_set_source_rgba(cr,
2246 fg_color_selected->red,
2247 fg_color_selected->blue,
2248 fg_color_selected->green,
2249 opacity / 3.0);
2250
2251 cairo_arc(cr,
2252 selected_x, selected_y,
2253 automation_edit->point_radius + (2.0 * (double) automation_edit->selected_acceleration_border),
2254 0.0,
2255 2.0 * M_PI);
2256
2257 cairo_stroke(cr);
2258
2259 /* draw selected acceleration - area */
2260 cairo_rectangle(cr,
2261 selected_x, selected_y,
2262 selected_width, selected_height);
2263 cairo_fill(cr);
2264 }
2265
2266 g_boxed_free(GDK_TYPE_RGBA, fg_color);
2267 g_boxed_free(GDK_TYPE_RGBA, fg_color_selected);
2268 }
2269
2270 void
ags_automation_edit_draw_automation(AgsAutomationEdit * automation_edit,cairo_t * cr)2271 ags_automation_edit_draw_automation(AgsAutomationEdit *automation_edit, cairo_t *cr)
2272 {
2273 AgsAutomationEditor *automation_editor;
2274 AgsNotebook *notebook;
2275
2276 AgsTimestamp *timestamp;
2277 AgsTimestamp *current_timestamp;
2278
2279 GtkAllocation allocation;
2280
2281 GType channel_type;
2282
2283 GList *start_list_automation, *list_automation;
2284 GList *start_list_acceleration, *list_acceleration;
2285
2286 gchar *control_name;
2287
2288 gdouble opacity;
2289 guint x0, x1;
2290 guint offset;
2291 guint line;
2292 gint i;
2293
2294 if(!AGS_IS_AUTOMATION_EDIT(automation_edit)){
2295 return;
2296 }
2297
2298 automation_editor = (AgsAutomationEditor *) gtk_widget_get_ancestor((GtkWidget *) automation_edit,
2299 AGS_TYPE_AUTOMATION_EDITOR);
2300
2301 if(automation_editor->selected_machine == NULL){
2302 return;
2303 }
2304
2305 notebook = NULL;
2306
2307 if(automation_edit->channel_type == G_TYPE_NONE){
2308 notebook = NULL;
2309 }else if(automation_edit->channel_type == AGS_TYPE_OUTPUT){
2310 notebook = automation_editor->output_notebook;
2311 }else if(automation_edit->channel_type == AGS_TYPE_INPUT){
2312 notebook = automation_editor->input_notebook;
2313 }
2314
2315 gtk_widget_get_allocation(GTK_WIDGET(automation_edit->drawing_area),
2316 &allocation);
2317
2318 opacity = gtk_spin_button_get_value(automation_editor->automation_toolbar->opacity);
2319
2320 /* get visisble region */
2321 x0 = gtk_range_get_value(GTK_RANGE(automation_edit->hscrollbar));
2322 x1 = (gtk_range_get_value(GTK_RANGE(automation_edit->hscrollbar)) + allocation.width);
2323
2324 /* draw automation */
2325 timestamp = ags_timestamp_new();
2326
2327 timestamp->flags &= (~AGS_TIMESTAMP_UNIX);
2328 timestamp->flags |= AGS_TIMESTAMP_OFFSET;
2329
2330 g_object_get(automation_editor->selected_machine->audio,
2331 "automation", &start_list_automation,
2332 NULL);
2333
2334 timestamp->timer.ags_offset.offset = (guint64) AGS_NOTATION_DEFAULT_OFFSET * floor((double) x0 / (double) AGS_NOTATION_DEFAULT_OFFSET);
2335
2336 i = 0;
2337
2338 while(notebook == NULL ||
2339 (i = ags_notebook_next_active_tab(notebook,
2340 i)) != -1){
2341 list_automation = ags_automation_find_near_timestamp_extended(start_list_automation, i,
2342 automation_edit->channel_type, automation_edit->control_name,
2343 timestamp);
2344
2345 while(list_automation != NULL){
2346 AgsAutomation *automation;
2347
2348 GList *start_list_acceleration, *list_acceleration;
2349
2350 automation = AGS_AUTOMATION(list_automation->data);
2351
2352 g_object_get(automation,
2353 "timestamp", ¤t_timestamp,
2354 "line", &line,
2355 "channel-type", &channel_type,
2356 "control-name", &control_name,
2357 NULL);
2358
2359 g_object_unref(current_timestamp);
2360
2361 if(i != line ||
2362 channel_type != automation_editor->focused_automation_edit->channel_type ||
2363 !g_strcmp0(control_name,
2364 automation_editor->focused_automation_edit->control_name) != TRUE ||
2365 current_timestamp == NULL){
2366 list_automation = list_automation->next;
2367
2368 continue;
2369 }
2370
2371 if(ags_timestamp_get_ags_offset(current_timestamp) > x1){
2372 break;
2373 }
2374
2375 if(ags_timestamp_get_ags_offset(current_timestamp) + AGS_AUTOMATION_DEFAULT_OFFSET < x0){
2376 list_automation = list_automation->next;
2377
2378 continue;
2379 }
2380
2381 g_object_get(automation,
2382 "acceleration", &start_list_acceleration,
2383 NULL);
2384
2385 list_acceleration = start_list_acceleration;
2386
2387 while(list_acceleration != NULL){
2388 ags_automation_edit_draw_acceleration(automation_edit,
2389 list_acceleration->data, ((list_acceleration->next != NULL) ? list_acceleration->next->data: NULL),
2390 cr,
2391 opacity);
2392
2393 /* iterate */
2394 list_acceleration = list_acceleration->next;
2395 }
2396
2397 g_list_free_full(start_list_acceleration,
2398 g_object_unref);
2399
2400 /* iterate */
2401 list_automation = list_automation->next;
2402 }
2403
2404 if(notebook == NULL){
2405 break;
2406 }
2407
2408 i++;
2409 }
2410
2411 g_list_free_full(start_list_automation,
2412 g_object_unref);
2413 }
2414
2415 void
ags_automation_edit_draw(AgsAutomationEdit * automation_edit,cairo_t * cr)2416 ags_automation_edit_draw(AgsAutomationEdit *automation_edit, cairo_t *cr)
2417 {
2418 AgsAutomationEditor *automation_editor;
2419
2420 automation_editor = (AgsAutomationEditor *) gtk_widget_get_ancestor((GtkWidget *) automation_edit,
2421 AGS_TYPE_AUTOMATION_EDITOR);
2422
2423 ags_automation_editor_reset_audio_scrollbar(automation_editor);
2424 ags_automation_editor_reset_output_scrollbar(automation_editor);
2425 ags_automation_editor_reset_input_scrollbar(automation_editor);
2426
2427 ags_automation_edit_reset_vscrollbar(automation_edit);
2428 ags_automation_edit_reset_hscrollbar(automation_edit);
2429
2430 /* segment */
2431 ags_automation_edit_draw_segment(automation_edit, cr);
2432
2433 /* automation */
2434 ags_automation_edit_draw_automation(automation_edit, cr);
2435
2436 /* edit mode */
2437 switch(automation_edit->mode){
2438 case AGS_AUTOMATION_EDIT_POSITION_CURSOR:
2439 {
2440 ags_automation_edit_draw_cursor(automation_edit, cr);
2441 }
2442 break;
2443 case AGS_AUTOMATION_EDIT_ADD_ACCELERATION:
2444 {
2445 if(automation_edit->current_acceleration != NULL){
2446 ags_automation_edit_draw_acceleration(automation_edit,
2447 automation_edit->current_acceleration, NULL,
2448 cr,
2449 1.0);
2450
2451 cairo_surface_mark_dirty(cairo_get_target(cr));
2452 }
2453 }
2454 break;
2455 case AGS_AUTOMATION_EDIT_SELECT_ACCELERATION:
2456 {
2457 ags_automation_edit_draw_selection(automation_edit, cr);
2458 }
2459 break;
2460 }
2461
2462 /* fader */
2463 if((AGS_AUTOMATION_EDIT_AUTO_SCROLL & (automation_edit->flags)) != 0){
2464 ags_automation_edit_draw_position(automation_edit, cr);
2465 }
2466 }
2467
2468 /**
2469 * ags_automation_edit_new:
2470 *
2471 * Create a new #AgsAutomationEdit.
2472 *
2473 * Returns: a new #AgsAutomationEdit
2474 *
2475 * Since: 3.0.0
2476 */
2477 AgsAutomationEdit*
ags_automation_edit_new()2478 ags_automation_edit_new()
2479 {
2480 AgsAutomationEdit *automation_edit;
2481
2482 automation_edit = (AgsAutomationEdit *) g_object_new(AGS_TYPE_AUTOMATION_EDIT, NULL);
2483
2484 return(automation_edit);
2485 }
2486