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/ags_machine_callbacks.h>
21
22 #include <ags/X/ags_ui_provider.h>
23 #include <ags/X/ags_window.h>
24 #include <ags/X/ags_pad.h>
25 #include <ags/X/ags_automation_editor.h>
26 #include <ags/X/ags_notation_editor.h>
27 #include <ags/X/ags_machine_editor.h>
28 #include <ags/X/ags_connection_editor.h>
29 #include <ags/X/ags_midi_dialog.h>
30
31 #include <ags/X/export/ags_wave_export_dialog.h>
32
33 #include <ags/X/editor/ags_envelope_dialog.h>
34 #include <ags/X/editor/ags_machine_radio_button.h>
35
36 #include <ags/i18n.h>
37
38 #define AGS_RENAME_ENTRY "AgsRenameEntry"
39
40 void ags_machine_recall_set_loop(AgsMachine *machine,
41 AgsRecall *recall);
42
43 int ags_machine_popup_rename_response_callback(GtkWidget *widget, gint response, AgsMachine *machine);
44 int ags_machine_popup_rename_audio_response_callback(GtkWidget *widget, gint response, AgsMachine *machine);
45 int ags_machine_popup_reposition_audio_response_callback(GtkWidget *widget, gint response, AgsMachine *machine);
46 int ags_machine_popup_properties_destroy_callback(GtkWidget *widget, AgsMachine *machine);
47
48 void
ags_machine_parent_set_callback(GtkWidget * widget,GtkWidget * old_parent,AgsMachine * machine)49 ags_machine_parent_set_callback(GtkWidget *widget, GtkWidget *old_parent, AgsMachine *machine)
50 {
51 AgsAudio *audio;
52 AgsPlaybackDomain *playback_domain;
53
54 guint i;
55
56 static const guint staging_program[] = {
57 (AGS_SOUND_STAGING_AUTOMATE | AGS_SOUND_STAGING_RUN_INTER | AGS_SOUND_STAGING_FX),
58 };
59
60 if(old_parent != NULL){
61 return;
62 }
63
64 audio = machine->audio;
65
66 g_object_get(audio,
67 "playback-domain", &playback_domain,
68 NULL);
69
70 if(playback_domain != NULL){
71 for(i = 0; i < AGS_SOUND_SCOPE_LAST; i++){
72 AgsThread *audio_thread;
73
74 audio_thread = ags_playback_domain_get_audio_thread(playback_domain,
75 i);
76
77 if(audio_thread != NULL){
78 ags_audio_thread_set_do_fx_staging((AgsAudioThread *) audio_thread,
79 TRUE);
80 ags_audio_thread_set_staging_program((AgsAudioThread *) audio_thread,
81 staging_program,
82 1);
83
84 g_object_unref(audio_thread);
85 }
86 }
87
88 g_object_unref(playback_domain);
89 }
90 }
91
92 void
ags_machine_check_message_callback(GObject * application_context,AgsMachine * machine)93 ags_machine_check_message_callback(GObject *application_context, AgsMachine *machine)
94 {
95 ags_machine_check_message(machine);
96 }
97
98 void
ags_machine_recall_set_loop(AgsMachine * machine,AgsRecall * recall)99 ags_machine_recall_set_loop(AgsMachine *machine,
100 AgsRecall *recall)
101 {
102 AgsNavigation *navigation;
103 AgsPort *port;
104
105 AgsApplicationContext *application_context;
106
107 GValue value = G_VALUE_INIT;
108
109 application_context = ags_application_context_get_instance();
110
111 navigation = ags_ui_provider_get_navigation(AGS_UI_PROVIDER(application_context));
112
113 /* loop */
114 port = NULL;
115
116 g_object_get(recall,
117 "loop", &port,
118 NULL);
119
120 g_value_init(&value,
121 G_TYPE_BOOLEAN);
122
123 g_value_set_boolean(&value,
124 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(navigation->loop)));
125
126 ags_port_safe_write(port,
127 &value);
128
129 if(port != NULL){
130 g_object_unref(port);
131 }
132
133 /* loop start */
134 port = NULL;
135
136 g_object_get(recall,
137 "loop-start", &port,
138 NULL);
139
140 g_value_unset(&value);
141 g_value_init(&value,
142 G_TYPE_UINT64);
143
144 g_value_set_uint64(&value,
145 16 * gtk_spin_button_get_value_as_int(navigation->loop_left_tact));
146
147 ags_port_safe_write(port,
148 &value);
149
150 if(port != NULL){
151 g_object_unref(port);
152 }
153
154 /* loop end */
155 port = NULL;
156
157 g_object_get(recall,
158 "loop-end", &port,
159 NULL);
160
161 g_value_unset(&value);
162 g_value_init(&value,
163 G_TYPE_UINT64);
164
165 g_value_set_uint64(&value,
166 16 * gtk_spin_button_get_value_as_int(navigation->loop_right_tact));
167
168 ags_port_safe_write(port,
169 &value);
170
171 if(port != NULL){
172 g_object_unref(port);
173 }
174 }
175
176 void
ags_machine_map_recall_callback(AgsMachine * machine,gpointer user_data)177 ags_machine_map_recall_callback(AgsMachine *machine,
178 gpointer user_data)
179 {
180 GList *start_play;
181 GList *start_recall;
182 GList *list;
183
184 start_play = NULL;
185 start_recall = NULL;
186
187 g_object_get(machine->audio,
188 "play", &start_play,
189 "recall", &start_recall,
190 NULL);
191
192 list = start_play;
193
194 while((list = ags_recall_template_find_type(list, AGS_TYPE_FX_NOTATION_AUDIO)) != NULL){
195 ags_machine_recall_set_loop(machine,
196 list->data);
197
198 /* iterate */
199 list = list->next;
200 }
201
202 list = start_play;
203
204 while((list = ags_recall_template_find_type(list, AGS_TYPE_FX_PLAYBACK_AUDIO)) != NULL){
205 ags_machine_recall_set_loop(machine,
206 list->data);
207
208 /* iterate */
209 list = list->next;
210 }
211
212 list = start_recall;
213
214 while((list = ags_recall_template_find_type(list, AGS_TYPE_FX_NOTATION_AUDIO)) != NULL){
215 ags_machine_recall_set_loop(machine,
216 list->data);
217
218 /* iterate */
219 list = list->next;
220 }
221
222 list = start_recall;
223
224 while((list = ags_recall_template_find_type(list, AGS_TYPE_FX_PLAYBACK_AUDIO)) != NULL){
225 ags_machine_recall_set_loop(machine,
226 list->data);
227
228 /* iterate */
229 list = list->next;
230 }
231
232 g_list_free_full(start_play,
233 (GDestroyNotify) g_object_unref);
234
235 g_list_free_full(start_recall,
236 (GDestroyNotify) g_object_unref);
237 }
238
239 int
ags_machine_button_press_callback(GtkWidget * handle_box,GdkEventButton * event,AgsMachine * machine)240 ags_machine_button_press_callback(GtkWidget *handle_box, GdkEventButton *event, AgsMachine *machine)
241 {
242 if(event->button == 3){
243 gtk_menu_popup_at_widget(GTK_MENU(machine->popup),
244 handle_box,
245 GDK_GRAVITY_SOUTH_EAST,
246 GDK_GRAVITY_NORTH_WEST,
247 NULL);
248 }else if(event->button == 1){
249 AgsWindow *window;
250
251 AgsApplicationContext *application_context;
252
253 application_context = ags_application_context_get_instance();
254
255 window = ags_ui_provider_get_window(AGS_UI_PROVIDER(application_context));
256
257 window->selected = machine;
258 }
259
260 return(0);
261 }
262
263 void
ags_machine_popup_move_up_activate_callback(GtkWidget * widget,AgsMachine * machine)264 ags_machine_popup_move_up_activate_callback(GtkWidget *widget, AgsMachine *machine)
265 {
266 GValue val = G_VALUE_INIT;
267
268 g_value_init(&val,
269 G_TYPE_INT);
270
271 gtk_container_child_get_property(GTK_CONTAINER(gtk_widget_get_parent(GTK_WIDGET(machine))),
272 GTK_WIDGET(machine),
273 "position", &val);
274
275 if(g_value_get_int (&val) > 0){
276 gtk_box_reorder_child(GTK_BOX(gtk_widget_get_parent(GTK_WIDGET(machine))),
277 GTK_WIDGET(machine),
278 g_value_get_int (&val) - 1);
279 }
280
281 g_value_unset (&val);
282 }
283
284 void
ags_machine_popup_move_down_activate_callback(GtkWidget * widget,AgsMachine * machine)285 ags_machine_popup_move_down_activate_callback(GtkWidget *widget, AgsMachine *machine)
286 {
287 GList *start_list;
288
289 GValue val={0,};
290
291 g_value_init (&val, G_TYPE_INT);
292
293 gtk_container_child_get_property(GTK_CONTAINER(gtk_widget_get_parent(GTK_WIDGET(machine))),
294 GTK_WIDGET(machine),
295 "position", &val);
296
297 start_list = gtk_container_get_children((GtkContainer *) gtk_widget_get_parent(GTK_WIDGET(machine)));
298
299 if(g_value_get_int (&val) < g_list_length(start_list) - 1){
300 gtk_box_reorder_child(GTK_BOX(gtk_widget_get_parent(GTK_WIDGET(machine))),
301 GTK_WIDGET(machine),
302 g_value_get_int (&val) + 1);
303 }
304
305 g_value_unset (&val);
306
307 g_list_free(start_list);
308 }
309
310 void
ags_machine_popup_hide_activate_callback(GtkWidget * widget,AgsMachine * machine)311 ags_machine_popup_hide_activate_callback(GtkWidget *widget, AgsMachine *machine)
312 {
313 GList *start_list;
314
315 start_list = gtk_container_get_children((GtkContainer *) machine);
316
317 gtk_widget_hide(gtk_bin_get_child(GTK_BIN(start_list->data)));
318
319 g_list_free(start_list);
320 }
321
322 void
ags_machine_popup_show_activate_callback(GtkWidget * widget,AgsMachine * machine)323 ags_machine_popup_show_activate_callback(GtkWidget *widget, AgsMachine *machine)
324 {
325 GList *start_list;
326
327 start_list = gtk_container_get_children((GtkContainer *) machine);
328
329 gtk_widget_show(gtk_bin_get_child(GTK_BIN(start_list->data)));
330
331 g_list_free(start_list);
332 }
333
334 void
ags_machine_popup_destroy_activate_callback(GtkWidget * widget,AgsMachine * machine)335 ags_machine_popup_destroy_activate_callback(GtkWidget *widget, AgsMachine *machine)
336 {
337 AgsWindow *window;
338
339 AgsAudio *audio;
340
341 AgsRemoveAudio *remove_audio;
342
343 AgsApplicationContext *application_context;
344
345 GList *list, *list_start;
346
347 window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) machine);
348
349 application_context = ags_application_context_get_instance();
350
351 ags_machine_set_run(machine,
352 FALSE);
353
354 /* destroy editor */
355 list =
356 list_start = gtk_container_get_children((GtkContainer *) window->notation_editor->machine_selector);
357
358 list = list->next;
359
360 while(list != NULL){
361 if(AGS_IS_MACHINE_RADIO_BUTTON(list->data) && AGS_MACHINE_RADIO_BUTTON(list->data)->machine == machine){
362 gtk_widget_destroy(list->data);
363 break;
364 }
365
366 list = list->next;
367 }
368
369 g_list_free(list_start);
370
371 /* destroy automation editor */
372 list =
373 list_start = gtk_container_get_children((GtkContainer *) window->automation_window->automation_editor->machine_selector);
374
375 list = list->next;
376
377 while(list != NULL){
378 if(AGS_IS_MACHINE_RADIO_BUTTON(list->data) && AGS_MACHINE_RADIO_BUTTON(list->data)->machine == machine){
379 gtk_widget_destroy(list->data);
380 break;
381 }
382
383 list = list->next;
384 }
385
386 g_list_free(list_start);
387
388 /* destroy machine */
389 audio = machine->audio;
390 g_object_ref(audio);
391
392 ags_connectable_disconnect(AGS_CONNECTABLE(machine));
393 gtk_widget_destroy((GtkWidget *) machine);
394
395 /* get task thread */
396 remove_audio = ags_remove_audio_new(audio);
397
398 ags_ui_provider_schedule_task(AGS_UI_PROVIDER(application_context),
399 (AgsTask *) remove_audio);
400 }
401
402 void
ags_machine_popup_rename_activate_callback(GtkWidget * widget,AgsMachine * machine)403 ags_machine_popup_rename_activate_callback(GtkWidget *widget, AgsMachine *machine)
404 {
405 GtkDialog *dialog;
406 GtkEntry *entry;
407
408 if(machine->rename != NULL){
409 return;
410 }
411
412 machine->rename =
413 dialog = (GtkDialog *) gtk_dialog_new_with_buttons(i18n("rename"),
414 (GtkWindow *) gtk_widget_get_toplevel(GTK_WIDGET(machine)),
415 GTK_DIALOG_DESTROY_WITH_PARENT,
416 "_OK", GTK_RESPONSE_ACCEPT,
417 "_Cancel", GTK_RESPONSE_REJECT,
418 NULL);
419
420 entry = (GtkEntry *) gtk_entry_new();
421 gtk_entry_set_text(entry, machine->machine_name);
422 gtk_box_pack_start((GtkBox *) gtk_dialog_get_content_area(dialog),
423 (GtkWidget *) entry,
424 FALSE, FALSE,
425 0);
426
427 gtk_widget_show_all((GtkWidget *) dialog);
428
429 g_signal_connect((GObject *) dialog, "response",
430 G_CALLBACK(ags_machine_popup_rename_response_callback), (gpointer) machine);
431 }
432
433 int
ags_machine_popup_rename_response_callback(GtkWidget * widget,gint response,AgsMachine * machine)434 ags_machine_popup_rename_response_callback(GtkWidget *widget, gint response, AgsMachine *machine)
435 {
436 if(response == GTK_RESPONSE_ACCEPT){
437 GList *children;
438
439 gchar *str;
440
441 children = gtk_container_get_children((GtkContainer *) gtk_dialog_get_content_area(GTK_DIALOG(widget)));
442
443 str = gtk_editable_get_chars(GTK_EDITABLE(children->data),
444 0, -1);
445 g_object_set(machine,
446 "machine-name", str,
447 NULL);
448
449 g_list_free(children);
450 }
451
452 machine->rename = NULL;
453 gtk_widget_destroy(widget);
454
455 return(0);
456 }
457
458 void
ags_machine_popup_rename_audio_activate_callback(GtkWidget * widget,AgsMachine * machine)459 ags_machine_popup_rename_audio_activate_callback(GtkWidget *widget, AgsMachine *machine)
460 {
461 GtkDialog *dialog;
462 GtkEntry *entry;
463
464 AgsAudio *audio;
465
466 gchar *audio_name;
467
468 if(machine->rename_audio != NULL){
469 return;
470 }
471
472 audio = machine->audio;
473
474 machine->rename_audio =
475 dialog = (GtkDialog *) gtk_dialog_new_with_buttons(i18n("rename audio"),
476 (GtkWindow *) gtk_widget_get_toplevel(GTK_WIDGET(machine)),
477 GTK_DIALOG_DESTROY_WITH_PARENT,
478 "_OK", GTK_RESPONSE_ACCEPT,
479 "_Cancel", GTK_RESPONSE_REJECT,
480 NULL);
481
482 g_object_get(audio,
483 "audio-name", &audio_name,
484 NULL);
485
486 entry = (GtkEntry *) gtk_entry_new();
487 gtk_entry_set_text(entry, audio_name);
488 gtk_box_pack_start((GtkBox *) gtk_dialog_get_content_area(dialog),
489 (GtkWidget *) entry,
490 FALSE, FALSE,
491 0);
492
493 g_free(audio_name);
494
495 gtk_widget_show_all((GtkWidget *) dialog);
496
497 g_signal_connect((GObject *) dialog, "response",
498 G_CALLBACK(ags_machine_popup_rename_audio_response_callback), (gpointer) machine);
499 }
500
501 int
ags_machine_popup_rename_audio_response_callback(GtkWidget * widget,gint response,AgsMachine * machine)502 ags_machine_popup_rename_audio_response_callback(GtkWidget *widget, gint response, AgsMachine *machine)
503 {
504 if(response == GTK_RESPONSE_ACCEPT){
505 GList *children;
506
507 gchar *str;
508
509 children = gtk_container_get_children((GtkContainer *) gtk_dialog_get_content_area(GTK_DIALOG(widget)));
510
511 str = gtk_editable_get_chars(GTK_EDITABLE(children->data),
512 0, -1);
513 g_object_set(machine->audio,
514 "audio-name", str,
515 NULL);
516
517 g_list_free(children);
518 }
519
520 machine->rename_audio = NULL;
521 gtk_widget_destroy(widget);
522
523 return(0);
524 }
525
526 void
ags_machine_popup_reposition_audio_activate_callback(GtkWidget * widget,AgsMachine * machine)527 ags_machine_popup_reposition_audio_activate_callback(GtkWidget *widget, AgsMachine *machine)
528 {
529 GtkDialog *dialog;
530 GtkSpinButton *spin_button;
531
532 AgsAudio *audio;
533
534 AgsApplicationContext *application_context;
535
536 GList *start_list;
537
538 gint length;
539 gint position;
540
541 if(machine->reposition_audio != NULL){
542 return;
543 }
544
545 application_context = ags_application_context_get_instance();
546
547 audio = machine->audio;
548
549 start_list = ags_sound_provider_get_audio(AGS_SOUND_PROVIDER(application_context));
550
551 length = g_list_length(start_list);
552 position = g_list_index(start_list,
553 audio);
554
555 machine->reposition_audio =
556 dialog = (GtkDialog *) gtk_dialog_new_with_buttons(i18n("reposition audio"),
557 (GtkWindow *) gtk_widget_get_toplevel(GTK_WIDGET(machine)),
558 GTK_DIALOG_DESTROY_WITH_PARENT,
559 "_OK", GTK_RESPONSE_ACCEPT,
560 "_Cancel", GTK_RESPONSE_REJECT,
561 NULL);
562
563 if(position >= 0){
564 spin_button = (GtkSpinButton *) gtk_spin_button_new_with_range(0.0, (gdouble) (length - 1), 1.0);
565 }else{
566 spin_button = (GtkSpinButton *) gtk_spin_button_new_with_range(-1.0, -1.0, 0.0);
567 }
568
569 gtk_spin_button_set_value(spin_button,
570 (gdouble) position);
571 gtk_box_pack_start((GtkBox *) gtk_dialog_get_content_area(dialog),
572 (GtkWidget *) spin_button,
573 FALSE, FALSE,
574 0);
575
576 gtk_widget_show_all((GtkWidget *) dialog);
577
578 g_signal_connect((GObject *) dialog, "response",
579 G_CALLBACK(ags_machine_popup_reposition_audio_response_callback), (gpointer) machine);
580
581 g_list_free_full(start_list,
582 g_object_unref);
583 }
584
585 int
ags_machine_popup_reposition_audio_response_callback(GtkWidget * widget,gint response,AgsMachine * machine)586 ags_machine_popup_reposition_audio_response_callback(GtkWidget *widget, gint response, AgsMachine *machine)
587 {
588 if(response == GTK_RESPONSE_ACCEPT){
589 AgsAudio *audio;
590
591 AgsApplicationContext *application_context;
592
593 GList *children;
594 GList *start_list;
595
596 gint new_position;
597
598 application_context = ags_application_context_get_instance();
599
600 audio = machine->audio;
601
602 start_list = ags_sound_provider_get_audio(AGS_SOUND_PROVIDER(application_context));
603
604 children = gtk_container_get_children((GtkContainer *) gtk_dialog_get_content_area(GTK_DIALOG(widget)));
605
606 new_position = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(children->data));
607
608 start_list = g_list_remove(start_list,
609 audio);
610 start_list = g_list_insert(start_list,
611 audio,
612 new_position);
613
614 ags_sound_provider_set_audio(AGS_SOUND_PROVIDER(application_context),
615 start_list);
616 g_list_foreach(start_list,
617 (GFunc) g_object_unref,
618 NULL);
619
620 g_list_free(children);
621 }
622
623 machine->reposition_audio = NULL;
624 gtk_widget_destroy(widget);
625
626 return(0);
627 }
628
629 void
ags_machine_popup_properties_activate_callback(GtkWidget * widget,AgsMachine * machine)630 ags_machine_popup_properties_activate_callback(GtkWidget *widget, AgsMachine *machine)
631 {
632 machine->properties = (GtkDialog *) ags_machine_editor_new(machine);
633 g_signal_connect_after(machine->properties, "destroy",
634 G_CALLBACK(ags_machine_popup_properties_destroy_callback), machine);
635
636 gtk_window_set_default_size((GtkWindow *) machine->properties, -1, 400);
637
638 ags_connectable_connect(AGS_CONNECTABLE(machine->properties));
639
640 ags_applicable_reset(AGS_APPLICABLE(machine->properties));
641
642 gtk_widget_show_all((GtkWidget *) machine->properties);
643 }
644
645 void
ags_machine_popup_sticky_controls_toggled_callback(GtkWidget * widget,AgsMachine * machine)646 ags_machine_popup_sticky_controls_toggled_callback(GtkWidget *widget, AgsMachine *machine)
647 {
648 if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))){
649 machine->flags |= AGS_MACHINE_STICKY_CONTROLS;
650 }else{
651 machine->flags &= (~AGS_MACHINE_STICKY_CONTROLS);
652 }
653 }
654
655 int
ags_machine_popup_properties_destroy_callback(GtkWidget * widget,AgsMachine * machine)656 ags_machine_popup_properties_destroy_callback(GtkWidget *widget, AgsMachine *machine)
657 {
658 machine->properties = NULL;
659
660 return(0);
661 }
662
663 void
ags_machine_popup_copy_pattern_callback(GtkWidget * widget,AgsMachine * machine)664 ags_machine_popup_copy_pattern_callback(GtkWidget *widget, AgsMachine *machine)
665 {
666 ags_machine_copy_pattern(machine);
667 }
668
669 void
ags_machine_popup_paste_pattern_callback(GtkWidget * widget,AgsMachine * machine)670 ags_machine_popup_paste_pattern_callback(GtkWidget *widget, AgsMachine *machine)
671 {
672 //TODO:JK: implement me
673 }
674
675 void
ags_machine_popup_envelope_callback(GtkWidget * widget,AgsMachine * machine)676 ags_machine_popup_envelope_callback(GtkWidget *widget, AgsMachine *machine)
677 {
678 AgsEnvelopeDialog *envelope_dialog;
679
680 if(machine->envelope_dialog == NULL){
681 envelope_dialog = ags_envelope_dialog_new(machine);
682
683 if((AGS_MACHINE_IS_SEQUENCER & (machine->flags)) != 0){
684 ags_envelope_dialog_add_pattern_tab(envelope_dialog);
685 }
686
687 machine->envelope_dialog = (GtkDialog *) envelope_dialog;
688
689 ags_connectable_connect(AGS_CONNECTABLE(envelope_dialog));
690 ags_applicable_reset(AGS_APPLICABLE(envelope_dialog));
691
692 gtk_widget_show_all((GtkWidget *) envelope_dialog);
693 }
694 }
695
696 void
ags_machine_popup_connection_editor_callback(GtkWidget * widget,AgsMachine * machine)697 ags_machine_popup_connection_editor_callback(GtkWidget *widget, AgsMachine *machine)
698 {
699 AgsConnectionEditor *connection_editor;
700
701 if(machine->connection_editor == NULL){
702 connection_editor = ags_connection_editor_new(NULL);
703
704 if((AGS_MACHINE_SHOW_AUDIO_OUTPUT_CONNECTION & (machine->connection_flags)) != 0){
705 connection_editor->flags |= AGS_CONNECTION_EDITOR_SHOW_OUTPUT;
706 }
707
708 if((AGS_MACHINE_SHOW_AUDIO_INPUT_CONNECTION & (machine->connection_flags)) != 0){
709 connection_editor->flags |= AGS_CONNECTION_EDITOR_SHOW_INPUT;
710 }
711
712 ags_connection_editor_set_machine(connection_editor, machine);
713
714 machine->connection_editor = (GtkDialog *) connection_editor;
715
716 ags_connectable_connect(AGS_CONNECTABLE(connection_editor));
717 ags_applicable_reset(AGS_APPLICABLE(connection_editor));
718
719 gtk_widget_show_all((GtkWidget *) connection_editor);
720 }else{
721 connection_editor = (AgsConnectionEditor *) machine->connection_editor;
722 }
723
724 gtk_widget_show_all((GtkWidget *) connection_editor);
725 }
726
727 void
ags_machine_popup_midi_dialog_callback(GtkWidget * widget,AgsMachine * machine)728 ags_machine_popup_midi_dialog_callback(GtkWidget *widget, AgsMachine *machine)
729 {
730 AgsMidiDialog *midi_dialog;
731
732 if(machine->midi_dialog == NULL){
733 midi_dialog = ags_midi_dialog_new(machine);
734 machine->midi_dialog = (GtkDialog *) midi_dialog;
735 midi_dialog->flags |= (AGS_MIDI_DIALOG_IO_OPTIONS |
736 AGS_MIDI_DIALOG_MAPPING |
737 AGS_MIDI_DIALOG_DEVICE);
738
739 ags_connectable_connect(AGS_CONNECTABLE(midi_dialog));
740 ags_applicable_reset(AGS_APPLICABLE(midi_dialog));
741
742 gtk_widget_show_all((GtkWidget *) midi_dialog);
743 }else{
744 midi_dialog = (AgsMidiDialog *) machine->midi_dialog;
745 }
746
747 gtk_widget_show_all((GtkWidget *) midi_dialog);
748 }
749
750 void
ags_machine_popup_midi_export_callback(GtkWidget * widget,AgsMachine * machine)751 ags_machine_popup_midi_export_callback(GtkWidget *widget, AgsMachine *machine)
752 {
753 //TODO:JK: implement me
754 }
755
756 void
ags_machine_popup_wave_export_callback(GtkWidget * widget,AgsMachine * machine)757 ags_machine_popup_wave_export_callback(GtkWidget *widget, AgsMachine *machine)
758 {
759 AgsWaveExportDialog *wave_export_dialog;
760
761 if(machine->wave_export_dialog == NULL){
762 wave_export_dialog = ags_wave_export_dialog_new(machine);
763 machine->wave_export_dialog = (GtkDialog *) wave_export_dialog;
764
765 ags_connectable_connect(AGS_CONNECTABLE(wave_export_dialog));
766 ags_applicable_reset(AGS_APPLICABLE(wave_export_dialog));
767
768 gtk_widget_show_all((GtkWidget *) wave_export_dialog);
769 }else{
770 wave_export_dialog = (AgsWaveExportDialog *) machine->wave_export_dialog;
771 }
772
773 gtk_widget_show_all((GtkWidget *) wave_export_dialog);
774 }
775
776 void
ags_machine_popup_midi_import_callback(GtkWidget * widget,AgsMachine * machine)777 ags_machine_popup_midi_import_callback(GtkWidget *widget, AgsMachine *machine)
778 {
779 //TODO:JK: implement me
780 }
781
782 void
ags_machine_popup_wave_import_callback(GtkWidget * widget,AgsMachine * machine)783 ags_machine_popup_wave_import_callback(GtkWidget *widget, AgsMachine *machine)
784 {
785 //TODO:JK: implement me
786 }
787
788 void
ags_machine_open_response_callback(GtkDialog * dialog,gint response,AgsMachine * machine)789 ags_machine_open_response_callback(GtkDialog *dialog, gint response, AgsMachine *machine)
790 {
791 GtkFileChooserDialog *file_chooser;
792 GtkCheckButton *overwrite;
793 GtkCheckButton *create;
794 GSList *filenames;
795
796 file_chooser = GTK_FILE_CHOOSER_DIALOG(dialog);
797
798 if(response == GTK_RESPONSE_ACCEPT){
799 filenames = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(file_chooser));
800 overwrite = g_object_get_data(G_OBJECT(dialog), "overwrite");
801 create = g_object_get_data(G_OBJECT(dialog), "create");
802
803 ags_machine_open_files(machine,
804 filenames,
805 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(overwrite)),
806 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(create)));
807 }
808
809 gtk_widget_destroy(GTK_WIDGET(file_chooser));
810 }
811
812 void
ags_machine_play_callback(GtkWidget * toggle_button,AgsMachine * machine)813 ags_machine_play_callback(GtkWidget *toggle_button, AgsMachine *machine)
814 {
815 if(machine == NULL){
816 return;
817 }
818
819 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button))){
820 if((AGS_MACHINE_BLOCK_PLAY & (machine->flags)) != 0){
821 return;
822 }
823
824 g_message("machine: on");
825
826 machine->flags |= AGS_MACHINE_BLOCK_PLAY;
827
828 ags_machine_set_run_extended(machine,
829 TRUE,
830 TRUE, FALSE, FALSE, FALSE);
831
832 machine->flags &= (~AGS_MACHINE_BLOCK_PLAY);
833 }else{
834 if((AGS_MACHINE_BLOCK_STOP & (machine->flags)) != 0){
835 return;
836 }
837
838 g_message("machine: off");
839
840 machine->flags |= AGS_MACHINE_BLOCK_STOP;
841
842 ags_machine_set_run_extended(machine,
843 FALSE,
844 TRUE, FALSE, FALSE, FALSE);
845
846 machine->flags &= (~AGS_MACHINE_BLOCK_STOP);
847 }
848 }
849
850 void
ags_machine_resize_audio_channels_callback(AgsMachine * machine,guint audio_channels,guint audio_channels_old,gpointer data)851 ags_machine_resize_audio_channels_callback(AgsMachine *machine,
852 guint audio_channels, guint audio_channels_old,
853 gpointer data)
854 {
855 AgsAudio *audio;
856 AgsPlayback *playback;
857 AgsChannel *start_output;
858 AgsChannel *start_input;
859 AgsChannel *channel, *next_pad, *next_channel;
860
861 GList *pad_list;
862 GList *line_list;
863
864 guint i;
865
866 static const guint staging_program[] = {
867 (AGS_SOUND_STAGING_AUTOMATE | AGS_SOUND_STAGING_RUN_INTER | AGS_SOUND_STAGING_FX),
868 };
869
870 audio = machine->audio;
871
872 start_output = NULL;
873 start_input = NULL;
874
875 g_object_get(audio,
876 "output", &start_output,
877 "input", &start_input,
878 NULL);
879
880 if(audio_channels > audio_channels_old){
881 /* AgsOutput */
882 channel = start_output;
883
884 if(channel != NULL){
885 g_object_ref(channel);
886 }
887
888 next_pad = NULL;
889
890 while(channel != NULL){
891 /* get some fields */
892 next_pad = ags_channel_next_pad(channel);
893
894 next_channel = ags_channel_nth(channel,
895 audio_channels_old);
896
897 if(channel != NULL){
898 g_object_unref(channel);
899 }
900
901 channel = next_channel;
902
903 while(channel != next_pad && channel != NULL){
904 /* fx engine */
905 g_object_get(channel,
906 "playback", &playback,
907 NULL);
908
909 if(playback != NULL){
910 for(i = 0; i < AGS_SOUND_SCOPE_LAST; i++){
911 AgsThread *channel_thread;
912
913 channel_thread = ags_playback_get_channel_thread(playback,
914 i);
915
916 if(channel_thread != NULL){
917 ags_channel_thread_set_do_fx_staging((AgsChannelThread *) channel_thread,
918 TRUE);
919 ags_channel_thread_set_staging_program((AgsChannelThread *) channel_thread,
920 staging_program,
921 1);
922
923 g_object_unref(channel_thread);
924 }
925 }
926
927 g_object_unref(playback);
928 }
929
930 /* iterate */
931 next_channel = ags_channel_next(channel);
932
933 g_object_unref(channel);
934
935 channel = next_channel;
936 }
937
938 if(next_pad != NULL){
939 g_object_unref(next_pad);
940 }
941 }
942
943 if(channel != NULL){
944 g_object_unref(channel);
945 }
946
947 /* AgsInput */
948 channel = start_input;
949
950 if(channel != NULL){
951 g_object_ref(channel);
952 }
953
954 next_pad = NULL;
955
956 while(channel != NULL){
957 /* get some fields */
958 next_pad = ags_channel_next_pad(channel);
959
960 next_channel = ags_channel_nth(channel,
961 audio_channels_old);
962
963 if(channel != NULL){
964 g_object_unref(channel);
965 }
966
967 channel = next_channel;
968
969 while(channel != next_pad && channel != NULL){
970 /* fx engine */
971 g_object_get(channel,
972 "playback", &playback,
973 NULL);
974
975 if(playback != NULL){
976 for(i = 0; i < AGS_SOUND_SCOPE_LAST; i++){
977 AgsThread *channel_thread;
978
979 channel_thread = ags_playback_get_channel_thread(playback,
980 i);
981
982 if(channel_thread != NULL){
983 ags_channel_thread_set_do_fx_staging((AgsChannelThread *) channel_thread,
984 TRUE);
985 ags_channel_thread_set_staging_program((AgsChannelThread *) channel_thread,
986 staging_program,
987 1);
988
989 g_object_unref(channel_thread);
990 }
991 }
992
993 g_object_unref(playback);
994 }
995
996 /* iterate */
997 next_channel = ags_channel_next(channel);
998
999 g_object_unref(channel);
1000
1001 channel = next_channel;
1002 }
1003
1004 if(next_pad != NULL){
1005 g_object_unref(next_pad);
1006 }
1007 }
1008
1009 if(channel != NULL){
1010 g_object_unref(channel);
1011 }
1012 }
1013
1014 /* unref */
1015 if(start_output != NULL){
1016 g_object_unref(start_output);
1017 }
1018
1019 if(start_input != NULL){
1020 g_object_unref(start_input);
1021 }
1022
1023 /* resize */
1024 if((AGS_MACHINE_CONNECTED & (machine->flags)) != 0){
1025 if(audio_channels > audio_channels_old){
1026 if(machine->input != NULL){
1027 pad_list = gtk_container_get_children(GTK_CONTAINER(machine->input));
1028
1029 while(pad_list != NULL){
1030 line_list = gtk_container_get_children((GtkContainer *) AGS_PAD(pad_list->data)->expander_set);
1031 line_list = g_list_nth(line_list,
1032 audio_channels_old);
1033
1034 for(i = 0; i < audio_channels - audio_channels_old; i++){
1035 ags_connectable_connect(AGS_CONNECTABLE(line_list->data));
1036
1037 line_list = line_list->next;
1038 }
1039
1040 pad_list = pad_list->next;
1041 }
1042 }
1043
1044 if(machine->output != NULL){
1045 pad_list = gtk_container_get_children(GTK_CONTAINER(machine->output));
1046
1047 while(pad_list != NULL){
1048 line_list = gtk_container_get_children((GtkContainer *) AGS_PAD(pad_list->data)->expander_set);
1049 line_list = g_list_nth(line_list,
1050 audio_channels_old);
1051
1052 for(i = 0; i < audio_channels - audio_channels_old; i++){
1053 ags_connectable_connect(AGS_CONNECTABLE(line_list->data));
1054
1055 line_list = line_list->next;
1056 }
1057
1058 pad_list = pad_list->next;
1059 }
1060 }
1061 }
1062 }
1063 }
1064
1065 void
ags_machine_resize_pads_callback(AgsMachine * machine,GType channel_type,guint pads,guint pads_old,gpointer data)1066 ags_machine_resize_pads_callback(AgsMachine *machine,
1067 GType channel_type,
1068 guint pads, guint pads_old,
1069 gpointer data)
1070 {
1071 AgsAudio *audio;
1072 AgsPlayback *playback;
1073 AgsChannel *start_output;
1074 AgsChannel *start_input;
1075 AgsChannel *channel, *next_channel;
1076
1077 GList *pad_list;
1078
1079 guint audio_channels;
1080 guint i;
1081
1082 static const guint staging_program[] = {
1083 (AGS_SOUND_STAGING_AUTOMATE | AGS_SOUND_STAGING_RUN_INTER | AGS_SOUND_STAGING_FX),
1084 };
1085
1086 audio = machine->audio;
1087
1088 start_output = NULL;
1089 start_input = NULL;
1090
1091 audio_channels = 0;
1092
1093 if(g_type_is_a(channel_type, AGS_TYPE_INPUT)){
1094 if(pads > pads_old){
1095 /* get some fields */
1096 g_object_get(audio,
1097 "input", &start_input,
1098 "audio-channels", &audio_channels,
1099 NULL);
1100
1101 /* AgsOutput */
1102 channel = ags_channel_pad_nth(start_input,
1103 pads_old);
1104
1105 while(channel != NULL){
1106 /* fx engine */
1107 g_object_get(channel,
1108 "playback", &playback,
1109 NULL);
1110
1111 if(playback != NULL){
1112 for(i = 0; i < AGS_SOUND_SCOPE_LAST; i++){
1113 AgsThread *channel_thread;
1114
1115 channel_thread = ags_playback_get_channel_thread(playback,
1116 i);
1117
1118 if(channel_thread != NULL){
1119 ags_channel_thread_set_do_fx_staging((AgsChannelThread *) channel_thread,
1120 TRUE);
1121 ags_channel_thread_set_staging_program((AgsChannelThread *) channel_thread,
1122 staging_program,
1123 1);
1124
1125 g_object_unref(channel_thread);
1126 }
1127 }
1128
1129 g_object_unref(playback);
1130 }
1131
1132 /* iterate */
1133 next_channel = ags_channel_next(channel);
1134
1135 g_object_unref(channel);
1136
1137 channel = next_channel;
1138 }
1139
1140 if(start_input != NULL){
1141 g_object_unref(start_input);
1142 }
1143
1144 if(channel != NULL){
1145 g_object_unref(channel);
1146 }
1147 }
1148 }else{
1149 if(pads > pads_old){
1150 /* get some fields */
1151 g_object_get(audio,
1152 "output", &start_output,
1153 "audio-channels", &audio_channels,
1154 NULL);
1155
1156 /* AgsOutput */
1157 channel = ags_channel_pad_nth(start_output,
1158 pads_old);
1159
1160 while(channel != NULL){
1161 /* fx engine */
1162 g_object_get(channel,
1163 "playback", &playback,
1164 NULL);
1165
1166 if(playback != NULL){
1167 for(i = 0; i < AGS_SOUND_SCOPE_LAST; i++){
1168 AgsThread *channel_thread;
1169
1170 channel_thread = ags_playback_get_channel_thread(playback,
1171 i);
1172
1173 if(channel_thread != NULL){
1174 ags_channel_thread_set_do_fx_staging((AgsChannelThread *) channel_thread,
1175 TRUE);
1176 ags_channel_thread_set_staging_program((AgsChannelThread *) channel_thread,
1177 staging_program,
1178 1);
1179
1180 g_object_unref(channel_thread);
1181 }
1182 }
1183
1184 g_object_unref(playback);
1185 }
1186
1187 /* iterate */
1188 next_channel = ags_channel_next(channel);
1189
1190 g_object_unref(channel);
1191
1192 channel = next_channel;
1193 }
1194
1195 if(start_output != NULL){
1196 g_object_unref(start_output);
1197 }
1198
1199 if(channel != NULL){
1200 g_object_unref(channel);
1201 }
1202 }
1203 }
1204
1205 /* resize */
1206 if((AGS_MACHINE_CONNECTED & (machine->flags)) != 0){
1207 if(pads > pads_old){
1208 if(g_type_is_a(channel_type,
1209 AGS_TYPE_INPUT)){
1210 if(machine->input != NULL){
1211 pad_list = gtk_container_get_children(GTK_CONTAINER(machine->input));
1212 pad_list = g_list_nth(pad_list,
1213 pads_old);
1214
1215 while(pad_list != NULL){
1216 ags_connectable_connect(AGS_CONNECTABLE(pad_list->data));
1217
1218 pad_list = pad_list->next;
1219 }
1220 }
1221 }
1222
1223 if(g_type_is_a(channel_type,
1224 AGS_TYPE_OUTPUT)){
1225 if(machine->output != NULL){
1226 pad_list = gtk_container_get_children(GTK_CONTAINER(machine->output));
1227 pad_list = g_list_nth(pad_list,
1228 pads_old);
1229
1230 while(pad_list != NULL){
1231 ags_connectable_connect(AGS_CONNECTABLE(pad_list->data));
1232
1233 pad_list = pad_list->next;
1234 }
1235 }
1236 }
1237 }
1238 }
1239 }
1240
1241 void
ags_machine_stop_callback(AgsMachine * machine,GList * recall_id,gint sound_scope,gpointer data)1242 ags_machine_stop_callback(AgsMachine *machine,
1243 GList *recall_id, gint sound_scope,
1244 gpointer data)
1245 {
1246 gboolean reset_active;
1247
1248 if((AGS_MACHINE_BLOCK_STOP_CALLBACK & (machine->flags)) != 0){
1249 return;
1250 }
1251
1252 machine->flags |= AGS_MACHINE_BLOCK_STOP_CALLBACK;
1253
1254 /* play button - check reset active */
1255 reset_active = (sound_scope == AGS_SOUND_SCOPE_SEQUENCER) ? TRUE: FALSE;
1256
1257 if(reset_active){
1258 gtk_toggle_button_set_active(machine->play, FALSE);
1259 }
1260
1261 #if 0
1262 if(sound_scope == AGS_SOUND_SCOPE_SEQUENCER){
1263 ags_machine_set_run_extended(machine,
1264 FALSE,
1265 TRUE, FALSE, FALSE, FALSE);
1266 }
1267
1268 if(sound_scope == AGS_SOUND_SCOPE_NOTATION){
1269 ags_machine_set_run_extended(machine,
1270 FALSE,
1271 FALSE, TRUE, FALSE, FALSE);
1272 }
1273
1274 if(sound_scope == AGS_SOUND_SCOPE_WAVE){
1275 ags_machine_set_run_extended(machine,
1276 FALSE,
1277 FALSE, FALSE, TRUE, FALSE);
1278 }
1279
1280 if(sound_scope == AGS_SOUND_SCOPE_MIDI){
1281 ags_machine_set_run_extended(machine,
1282 FALSE,
1283 FALSE, FALSE, FALSE, TRUE);
1284 }
1285 #endif
1286
1287 machine->flags &= (~AGS_MACHINE_BLOCK_STOP_CALLBACK);
1288 }
1289
1290 void
ags_machine_active_playback_start_channel_launch_callback(AgsTask * task,AgsPlayback * playback)1291 ags_machine_active_playback_start_channel_launch_callback(AgsTask *task,
1292 AgsPlayback *playback)
1293 {
1294 AgsAudio *audio;
1295 AgsChannel *channel;
1296 AgsRecycling *first_recycling, *last_recycling;
1297 AgsRecycling *recycling, *next_recycling, *end_recycling;
1298 AgsAudioSignal *template, *audio_signal;
1299 AgsRecallID *recall_id;
1300 AgsNote *play_note;
1301 AgsFxPlaybackAudio *fx_playback_audio;
1302
1303 GObject *output_soundcard;
1304
1305 GList *start_recall, *recall;
1306
1307 GRecMutex *recycling_mutex;
1308
1309 audio = NULL;
1310
1311 channel = NULL;
1312
1313 first_recycling = NULL;
1314 last_recycling = NULL;
1315
1316 play_note = NULL;
1317
1318 fx_playback_audio = NULL;
1319
1320 start_recall = NULL;
1321
1322 g_object_get(playback,
1323 "channel", &channel,
1324 "play-note", &play_note,
1325 NULL);
1326
1327 g_object_get(channel,
1328 "audio", &audio,
1329 NULL);
1330
1331 g_object_get(audio,
1332 "play", &start_recall,
1333 NULL);
1334
1335 recall = ags_recall_template_find_type(start_recall, AGS_TYPE_FX_PLAYBACK_AUDIO);
1336
1337 if(recall != NULL){
1338 fx_playback_audio = recall->data;
1339 }
1340
1341 recall_id = ags_playback_get_recall_id(playback,
1342 AGS_SOUND_SCOPE_PLAYBACK);
1343
1344 /* get some fields */
1345 g_object_get(channel,
1346 "first-recycling", &first_recycling,
1347 "last-recycling", &last_recycling,
1348 NULL);
1349
1350 end_recycling = ags_recycling_next(last_recycling);
1351
1352 recycling = first_recycling;
1353 g_object_ref(recycling);
1354
1355 next_recycling = NULL;
1356
1357 while(recycling != end_recycling){
1358 output_soundcard = NULL;
1359
1360 g_object_get(recycling,
1361 "output-soundcard", &output_soundcard,
1362 NULL);
1363
1364 recycling_mutex = AGS_RECYCLING_GET_OBJ_MUTEX(recycling);
1365
1366 g_rec_mutex_lock(recycling_mutex);
1367
1368 template = ags_audio_signal_get_template(recycling->audio_signal);
1369
1370 g_rec_mutex_unlock(recycling_mutex);
1371
1372 /* instantiate audio signal */
1373 audio_signal = ags_audio_signal_new((GObject *) output_soundcard,
1374 (GObject *) recycling,
1375 (GObject *) recall_id);
1376 ags_audio_signal_set_flags(audio_signal, (AGS_AUDIO_SIGNAL_FEED |
1377 AGS_AUDIO_SIGNAL_STREAM));
1378 g_object_set(audio_signal,
1379 "template", template,
1380 "note", play_note,
1381 NULL);
1382
1383 /* add audio signal */
1384 if(ags_audio_test_behaviour_flags(audio, AGS_SOUND_BEHAVIOUR_PATTERN_MODE)){
1385 ags_recycling_create_audio_signal_with_defaults(recycling,
1386 audio_signal,
1387 0.0, 0);
1388 }else{
1389 gdouble notation_delay;
1390 guint buffer_size;
1391 guint note_x0, note_x1;
1392
1393 notation_delay = ags_soundcard_get_absolute_delay(AGS_SOUNDCARD(output_soundcard));
1394
1395 g_object_get(recycling,
1396 "buffer-size", &buffer_size,
1397 NULL);
1398
1399 g_object_get(play_note,
1400 "x0", ¬e_x0,
1401 "x1", ¬e_x1,
1402 NULL);
1403
1404 ags_recycling_create_audio_signal_with_frame_count(recycling,
1405 audio_signal,
1406 (guint) (((gdouble) buffer_size * notation_delay) * (gdouble) (note_x1 - note_x0)),
1407 0.0, 0);
1408 }
1409
1410 audio_signal->stream_current = audio_signal->stream;
1411 ags_connectable_connect(AGS_CONNECTABLE(audio_signal));
1412
1413 ags_fx_playback_audio_add_feed_audio_signal(fx_playback_audio, audio_signal);
1414
1415 /*
1416 * emit add_audio_signal on AgsRecycling
1417 */
1418 ags_recycling_add_audio_signal(recycling,
1419 audio_signal);
1420
1421 g_object_unref(output_soundcard);
1422
1423 /* iterate */
1424 next_recycling = ags_recycling_next(recycling);
1425
1426 g_object_unref(recycling);
1427
1428 recycling = next_recycling;
1429 }
1430
1431 if(next_recycling != NULL){
1432 g_object_unref(next_recycling);
1433 }
1434
1435 /* unref */
1436 g_object_unref(audio);
1437
1438 g_object_unref(channel);
1439
1440 if(first_recycling != NULL){
1441 g_object_unref(first_recycling);
1442 g_object_unref(last_recycling);
1443 }
1444
1445 if(end_recycling != NULL){
1446 g_object_unref(end_recycling);
1447 }
1448
1449 g_object_unref(recall_id);
1450
1451 g_object_unref(play_note);
1452 }
1453