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/ags_composite_editor.h>
21 #include <ags/X/ags_composite_editor_callbacks.h>
22
23 #include <libxml/tree.h>
24 #include <libxml/xpath.h>
25
26 #include <ags/i18n.h>
27
28 void ags_composite_editor_class_init(AgsCompositeEditorClass *composite_editor);
29 void ags_composite_editor_connectable_interface_init(AgsConnectableInterface *connectable);
30 void ags_composite_editor_init(AgsCompositeEditor *composite_editor);
31
32 AgsUUID* ags_composite_editor_get_uuid(AgsConnectable *connectable);
33 gboolean ags_composite_editor_has_resource(AgsConnectable *connectable);
34 gboolean ags_composite_editor_is_ready(AgsConnectable *connectable);
35 void ags_composite_editor_add_to_registry(AgsConnectable *connectable);
36 void ags_composite_editor_remove_from_registry(AgsConnectable *connectable);
37 xmlNode* ags_composite_editor_list_resource(AgsConnectable *connectable);
38 xmlNode* ags_composite_editor_xml_compose(AgsConnectable *connectable);
39 void ags_composite_editor_xml_parse(AgsConnectable *connectable,
40 xmlNode *node);
41 gboolean ags_composite_editor_is_connected(AgsConnectable *connectable);
42 void ags_composite_editor_connect(AgsConnectable *connectable);
43 void ags_composite_editor_disconnect(AgsConnectable *connectable);
44
45 void ags_composite_editor_real_machine_changed(AgsCompositeEditor *composite_editor,
46 AgsMachine *machine);
47
48 enum{
49 MACHINE_CHANGED,
50 LAST_SIGNAL,
51 };
52
53 static gpointer ags_composite_editor_parent_class = NULL;
54 static guint composite_editor_signals[LAST_SIGNAL];
55
56 /**
57 * SECTION:ags_composite_editor
58 * @short_description: composite editor
59 * @title: AgsCompositeEditor
60 * @section_id:
61 * @include: ags/X/ags_composite_editor.h
62 *
63 * The #AgsCompositeEditor is a composite abstraction of edit implementation.
64 */
65
66 GType
ags_composite_editor_get_type(void)67 ags_composite_editor_get_type(void)
68 {
69 static volatile gsize g_define_type_id__volatile = 0;
70
71 if(g_once_init_enter (&g_define_type_id__volatile)){
72 GType ags_type_composite_editor = 0;
73
74 static const GTypeInfo ags_composite_editor_info = {
75 sizeof (AgsCompositeEditorClass),
76 NULL, /* base_init */
77 NULL, /* base_finalize */
78 (GClassInitFunc) ags_composite_editor_class_init,
79 NULL, /* class_finalize */
80 NULL, /* class_data */
81 sizeof (AgsCompositeEditor),
82 0, /* n_preallocs */
83 (GInstanceInitFunc) ags_composite_editor_init,
84 };
85
86 static const GInterfaceInfo ags_connectable_interface_info = {
87 (GInterfaceInitFunc) ags_composite_editor_connectable_interface_init,
88 NULL, /* interface_finalize */
89 NULL, /* interface_data */
90 };
91
92 ags_type_composite_editor = g_type_register_static(GTK_TYPE_BOX,
93 "AgsCompositeEditor", &ags_composite_editor_info,
94 0);
95
96 g_type_add_interface_static(ags_type_composite_editor,
97 AGS_TYPE_CONNECTABLE,
98 &ags_connectable_interface_info);
99
100 g_once_init_leave(&g_define_type_id__volatile, ags_type_composite_editor);
101 }
102
103 return g_define_type_id__volatile;
104 }
105
106 void
ags_composite_editor_class_init(AgsCompositeEditorClass * composite_editor)107 ags_composite_editor_class_init(AgsCompositeEditorClass *composite_editor)
108 {
109 ags_composite_editor_parent_class = g_type_class_peek_parent(composite_editor);
110
111 /* AgsCompositeEditorClass */
112 composite_editor->machine_changed = ags_composite_editor_real_machine_changed;
113
114 /* signals */
115 /**
116 * AgsCompositeEditor::machine-changed:
117 * @editor: the object to change machine.
118 * @machine: the #AgsMachine to set
119 *
120 * The ::machine-changed signal notifies about changed machine.
121 *
122 * Since: 3.8.0
123 */
124 composite_editor_signals[MACHINE_CHANGED] =
125 g_signal_new("machine-changed",
126 G_TYPE_FROM_CLASS(composite_editor),
127 G_SIGNAL_RUN_LAST,
128 G_STRUCT_OFFSET(AgsCompositeEditorClass, machine_changed),
129 NULL, NULL,
130 g_cclosure_marshal_VOID__OBJECT,
131 G_TYPE_NONE, 1,
132 G_TYPE_OBJECT);
133 }
134
135 void
ags_composite_editor_connectable_interface_init(AgsConnectableInterface * connectable)136 ags_composite_editor_connectable_interface_init(AgsConnectableInterface *connectable)
137 {
138 connectable->get_uuid = ags_composite_editor_get_uuid;
139 connectable->has_resource = ags_composite_editor_has_resource;
140
141 connectable->is_ready = ags_composite_editor_is_ready;
142 connectable->add_to_registry = ags_composite_editor_add_to_registry;
143 connectable->remove_from_registry = ags_composite_editor_remove_from_registry;
144
145 connectable->list_resource = ags_composite_editor_list_resource;
146 connectable->xml_compose = ags_composite_editor_xml_compose;
147 connectable->xml_parse = ags_composite_editor_xml_parse;
148
149 connectable->is_connected = ags_composite_editor_is_connected;
150 connectable->connect = ags_composite_editor_connect;
151 connectable->disconnect = ags_composite_editor_disconnect;
152
153 connectable->connect_connection = NULL;
154 connectable->disconnect_connection = NULL;
155 }
156
157 void
ags_composite_editor_init(AgsCompositeEditor * composite_editor)158 ags_composite_editor_init(AgsCompositeEditor *composite_editor)
159 {
160 GtkViewport *viewport;
161 GtkScrolledWindow *scrolled_window;
162
163 gtk_orientable_set_orientation(GTK_ORIENTABLE(composite_editor),
164 GTK_ORIENTATION_VERTICAL);
165
166 composite_editor->flags = 0;
167 composite_editor->edit = 0;
168
169 composite_editor->version = g_strdup(AGS_COMPOSITE_EDITOR_DEFAULT_VERSION);
170 composite_editor->build_id = g_strdup(AGS_COMPOSITE_EDITOR_DEFAULT_BUILD_ID);
171
172 /* uuid */
173 composite_editor->uuid = ags_uuid_alloc();
174 ags_uuid_generate(composite_editor->uuid);
175
176 /* widgets */
177 composite_editor->toolbar = ags_composite_toolbar_new();
178 gtk_box_pack_start((GtkBox *) composite_editor,
179 (GtkWidget *) composite_editor->toolbar,
180 FALSE, FALSE,
181 0);
182
183 /* paned */
184 composite_editor->paned = (GtkPaned *) gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
185 gtk_box_pack_start((GtkBox *) composite_editor,
186 (GtkWidget *) composite_editor->paned,
187 FALSE, FALSE,
188 0);
189
190 /* machine selector */
191 viewport = (GtkViewport *) gtk_viewport_new(NULL,
192 NULL);
193 g_object_set(viewport,
194 "shadow-type", GTK_SHADOW_NONE,
195 NULL);
196 gtk_paned_pack1((GtkPaned *) composite_editor->paned,
197 (GtkWidget *) viewport,
198 FALSE, TRUE);
199
200 scrolled_window = (GtkScrolledWindow *) gtk_scrolled_window_new(NULL, NULL);
201 gtk_container_add(GTK_CONTAINER(viewport),
202 GTK_WIDGET(scrolled_window));
203
204 composite_editor->machine_selector = g_object_new(AGS_TYPE_MACHINE_SELECTOR,
205 "homogeneous", FALSE,
206 "spacing", 0,
207 NULL);
208 gtk_label_set_label(composite_editor->machine_selector->label,
209 i18n("composite selector"));
210
211 composite_editor->machine_selector->popup = ags_machine_selector_popup_new(composite_editor->machine_selector);
212 g_object_set(composite_editor->machine_selector->menu_button,
213 "menu", composite_editor->machine_selector->popup,
214 NULL);
215
216 gtk_container_add((GtkContainer *) scrolled_window,
217 (GtkWidget *) composite_editor->machine_selector);
218 }
219
220 AgsUUID*
ags_composite_editor_get_uuid(AgsConnectable * connectable)221 ags_composite_editor_get_uuid(AgsConnectable *connectable)
222 {
223 AgsCompositeEditor *composite_editor;
224
225 AgsUUID *ptr;
226
227 composite_editor = AGS_COMPOSITE_EDITOR(connectable);
228
229 ptr = composite_editor->uuid;
230
231 return(ptr);
232 }
233
234 gboolean
ags_composite_editor_has_resource(AgsConnectable * connectable)235 ags_composite_editor_has_resource(AgsConnectable *connectable)
236 {
237 return(FALSE);
238 }
239
240 gboolean
ags_composite_editor_is_ready(AgsConnectable * connectable)241 ags_composite_editor_is_ready(AgsConnectable *connectable)
242 {
243 AgsCompositeEditor *composite_editor;
244
245 gboolean is_ready;
246
247 composite_editor = AGS_COMPOSITE_EDITOR(connectable);
248
249 /* check is added */
250 is_ready = ags_composite_editor_test_flags(composite_editor, AGS_COMPOSITE_EDITOR_ADDED_TO_REGISTRY);
251
252 return(is_ready);
253 }
254
255 void
ags_composite_editor_add_to_registry(AgsConnectable * connectable)256 ags_composite_editor_add_to_registry(AgsConnectable *connectable)
257 {
258 AgsCompositeEditor *composite_editor;
259
260 AgsRegistry *registry;
261 AgsRegistryEntry *entry;
262
263 AgsApplicationContext *application_context;
264
265 if(ags_connectable_is_ready(connectable)){
266 return;
267 }
268
269 composite_editor = AGS_COMPOSITE_EDITOR(connectable);
270
271 ags_composite_editor_set_flags(composite_editor, AGS_COMPOSITE_EDITOR_ADDED_TO_REGISTRY);
272
273 application_context = ags_application_context_get_instance();
274
275 registry = (AgsRegistry *) ags_service_provider_get_registry(AGS_SERVICE_PROVIDER(application_context));
276
277 if(registry != NULL){
278 entry = ags_registry_entry_alloc(registry);
279
280 entry->id = composite_editor->uuid;
281 g_value_set_object(entry->entry,
282 (gpointer) composite_editor);
283
284 ags_registry_add_entry(registry,
285 entry);
286 }
287 }
288
289 void
ags_composite_editor_remove_from_registry(AgsConnectable * connectable)290 ags_composite_editor_remove_from_registry(AgsConnectable *connectable)
291 {
292 if(!ags_connectable_is_ready(connectable)){
293 return;
294 }
295
296 //TODO:JK: implement me
297 }
298
299 xmlNode*
ags_composite_editor_list_resource(AgsConnectable * connectable)300 ags_composite_editor_list_resource(AgsConnectable *connectable)
301 {
302 xmlNode *node;
303
304 node = NULL;
305
306 //TODO:JK: implement me
307
308 return(node);
309 }
310
311 xmlNode*
ags_composite_editor_xml_compose(AgsConnectable * connectable)312 ags_composite_editor_xml_compose(AgsConnectable *connectable)
313 {
314 xmlNode *node;
315
316 node = NULL;
317
318 //TODO:JK: implement me
319
320 return(node);
321 }
322
323 void
ags_composite_editor_xml_parse(AgsConnectable * connectable,xmlNode * node)324 ags_composite_editor_xml_parse(AgsConnectable *connectable,
325 xmlNode *node)
326 {
327 //TODO:JK: implement me
328 }
329
330 gboolean
ags_composite_editor_is_connected(AgsConnectable * connectable)331 ags_composite_editor_is_connected(AgsConnectable *connectable)
332 {
333 AgsCompositeEditor *composite_editor;
334
335 gboolean is_connected;
336
337 composite_editor = AGS_COMPOSITE_EDITOR(connectable);
338
339 /* check is connected */
340 is_connected = ags_composite_editor_test_flags(composite_editor, AGS_COMPOSITE_EDITOR_CONNECTED);
341
342 return(is_connected);
343 }
344
345 void
ags_composite_editor_connect(AgsConnectable * connectable)346 ags_composite_editor_connect(AgsConnectable *connectable)
347 {
348 AgsCompositeEditor *composite_editor;
349
350 composite_editor = AGS_COMPOSITE_EDITOR(connectable);
351
352 if((AGS_COMPOSITE_EDITOR_CONNECTED & (composite_editor->flags)) != 0){
353 return;
354 }
355
356 composite_editor->flags |= AGS_COMPOSITE_EDITOR_CONNECTED;
357
358 //TODO:JK: implement me
359 }
360
361 void
ags_composite_editor_disconnect(AgsConnectable * connectable)362 ags_composite_editor_disconnect(AgsConnectable *connectable)
363 {
364 AgsCompositeEditor *composite_editor;
365
366 composite_editor = AGS_COMPOSITE_EDITOR(connectable);
367
368 if((AGS_COMPOSITE_EDITOR_CONNECTED & (composite_editor->flags)) == 0){
369 return;
370 }
371
372 composite_editor->flags &= (~AGS_COMPOSITE_EDITOR_CONNECTED);
373
374 //TODO:JK: implement me
375 }
376
377 /**
378 * ags_composite_editor_test_flags:
379 * @composite_editor: the #AgsCompositeEditor
380 * @flags: the flags
381 *
382 * Test @flags to be set on @composite_editor.
383 *
384 * Returns: %TRUE if flags are set, else %FALSE
385 *
386 * Since: 3.8.0
387 */
388 gboolean
ags_composite_editor_test_flags(AgsCompositeEditor * composite_editor,guint flags)389 ags_composite_editor_test_flags(AgsCompositeEditor *composite_editor, guint flags)
390 {
391 gboolean retval;
392
393 if(!AGS_IS_COMPOSITE_EDITOR(composite_editor)){
394 return(FALSE);
395 }
396
397 /* test */
398 retval = (flags & (composite_editor->flags)) ? TRUE: FALSE;
399
400 return(retval);
401 }
402
403 /**
404 * ags_composite_editor_set_flags:
405 * @composite_editor: the #AgsCompositeEditor
406 * @flags: see enum AgsCompositeEditorFlags
407 *
408 * Enable a feature of #AgsCompositeEditor.
409 *
410 * Since: 3.8.0
411 */
412 void
ags_composite_editor_set_flags(AgsCompositeEditor * composite_editor,guint flags)413 ags_composite_editor_set_flags(AgsCompositeEditor *composite_editor, guint flags)
414 {
415 if(!AGS_IS_COMPOSITE_EDITOR(composite_editor)){
416 return;
417 }
418
419 /* set flags */
420 composite_editor->flags |= flags;
421 }
422
423 /**
424 * ags_composite_editor_unset_flags:
425 * @composite_editor: the #AgsCompositeEditor
426 * @flags: see enum AgsCompositeEditorFlags
427 *
428 * Disable a feature of AgsCompositeEditor.
429 *
430 * Since: 3.8.0
431 */
432 void
ags_composite_editor_unset_flags(AgsCompositeEditor * composite_editor,guint flags)433 ags_composite_editor_unset_flags(AgsCompositeEditor *composite_editor, guint flags)
434 {
435 if(!AGS_IS_COMPOSITE_EDITOR(composite_editor)){
436 return;
437 }
438
439 /* unset flags */
440 composite_editor->flags &= (~flags);
441 }
442
443 void
ags_composite_editor_real_machine_changed(AgsCompositeEditor * composite_editor,AgsMachine * machine)444 ags_composite_editor_real_machine_changed(AgsCompositeEditor *composite_editor,
445 AgsMachine *machine)
446 {
447 //TODO:JK: implement me
448 }
449
450 /**
451 * ags_composite_editor_machine_changed:
452 * @composite_editor: the #AgsCompositeEditor
453 * @machine: the new #AgsMachine
454 *
455 * Is emitted as machine changed of composite_editor.
456 *
457 * Since: 3.8.0
458 */
459 void
ags_composite_editor_machine_changed(AgsCompositeEditor * composite_editor,AgsMachine * machine)460 ags_composite_editor_machine_changed(AgsCompositeEditor *composite_editor,
461 AgsMachine *machine)
462 {
463 g_return_if_fail(AGS_IS_COMPOSITE_EDITOR(composite_editor));
464
465 g_object_ref((GObject *) composite_editor);
466 g_signal_emit((GObject *) composite_editor,
467 composite_editor_signals[MACHINE_CHANGED], 0,
468 machine);
469 g_object_unref((GObject *) composite_editor);
470 }
471
472 /**
473 * ags_composite_editor_paste:
474 * @composite_editor: the #AgsCompositeEditor
475 *
476 * Paste to @composite_editor from clipboard.
477 *
478 * Since: 3.8.0
479 */
480 void
ags_composite_editor_paste(AgsCompositeEditor * composite_editor)481 ags_composite_editor_paste(AgsCompositeEditor *composite_editor)
482 {
483 //TODO:JK: implement me
484 }
485
486 /**
487 * ags_composite_editor_copy:
488 * @composite_editor: the #AgsCompositeEditor
489 *
490 * Copy to clipboard from @composite_editor.
491 *
492 * Since: 3.8.0
493 */
494 void
ags_composite_editor_copy(AgsCompositeEditor * composite_editor)495 ags_composite_editor_copy(AgsCompositeEditor *composite_editor)
496 {
497 //TODO:JK: implement me
498 }
499
500 /**
501 * ags_composite_editor_cut:
502 * @composite_editor: the #AgsCompositeEditor
503 *
504 * Copy to clipboard from @composite_editor.
505 *
506 * Since: 3.8.0
507 */
508 void
ags_composite_editor_cut(AgsCompositeEditor * composite_editor)509 ags_composite_editor_cut(AgsCompositeEditor *composite_editor)
510 {
511 //TODO:JK: implement me
512 }
513
514 /**
515 * ags_composite_editor_invert:
516 * @composite_editor: the #AgsCompositeEditor
517 *
518 * Invert selected region of @composite_editor.
519 *
520 * Since: 3.8.0
521 */
522 void
ags_composite_editor_invert(AgsCompositeEditor * composite_editor)523 ags_composite_editor_invert(AgsCompositeEditor *composite_editor)
524 {
525 //TODO:JK: implement me
526 }
527
528 /**
529 * ags_composite_editor_new:
530 *
531 * Create a new #AgsCompositeEditor.
532 *
533 * Returns: a new #AgsCompositeEditor
534 *
535 * Since: 3.8.0
536 */
537 AgsCompositeEditor*
ags_composite_editor_new()538 ags_composite_editor_new()
539 {
540 AgsCompositeEditor *composite_editor;
541
542 composite_editor = (AgsCompositeEditor *) g_object_new(AGS_TYPE_COMPOSITE_EDITOR,
543 NULL);
544
545 return(composite_editor);
546 }
547