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.h>
21 #include <ags/X/ags_machine_callbacks.h>
22
23 #include <ags/X/ags_ui_provider.h>
24 #include <ags/X/ags_window.h>
25 #include <ags/X/ags_pad.h>
26 #include <ags/X/ags_effect_bridge.h>
27
28 #include <ags/i18n.h>
29
30 void ags_machine_class_init(AgsMachineClass *machine);
31 void ags_machine_connectable_interface_init(AgsConnectableInterface *connectable);
32 void ags_machine_init(AgsMachine *machine);
33 void ags_machine_set_property(GObject *gobject,
34 guint prop_id,
35 const GValue *value,
36 GParamSpec *param_spec);
37 void ags_machine_get_property(GObject *gobject,
38 guint prop_id,
39 GValue *value,
40 GParamSpec *param_spec);
41 static void ags_machine_finalize(GObject *gobject);
42
43 void ags_machine_connect(AgsConnectable *connectable);
44 void ags_machine_disconnect(AgsConnectable *connectable);
45
46 void ags_machine_real_resize_audio_channels(AgsMachine *machine,
47 guint new_size, guint old_size);
48 void ags_machine_real_resize_pads(AgsMachine *machine,
49 GType channel_type,
50 guint new_size, guint old_size);
51 void ags_machine_real_map_recall(AgsMachine *machine);
52 GList* ags_machine_real_find_port(AgsMachine *machine);
53
54 GtkMenu* ags_machine_popup_new(AgsMachine *machine);
55
56 xmlNode* ags_machine_copy_pattern_to_notation(AgsMachine *machine,
57 AgsChannel *start_current,
58 guint input_pads);
59
60
61
62 /**
63 * SECTION:ags_machine
64 * @short_description: visualize audio object.
65 * @title: AgsMachine
66 * @section_id:
67 * @include: ags/X/ags_machine.h
68 *
69 * #AgsMachine is a composite widget to act as base class to visualize #AgsAudio.
70 */
71
72 #define AGS_DEFAULT_MACHINE "ags-default-machine"
73
74 enum{
75 SAMPLERATE_CHANGED,
76 BUFFER_SIZE_CHANGED,
77 FORMAT_CHANGED,
78 RESIZE_AUDIO_CHANNELS,
79 RESIZE_PADS,
80 MAP_RECALL,
81 FIND_PORT,
82 STOP,
83 LAST_SIGNAL,
84 };
85
86 enum{
87 PROP_0,
88 PROP_SAMPLERATE,
89 PROP_BUFFER_SIZE,
90 PROP_FORMAT,
91 PROP_AUDIO,
92 PROP_MACHINE_NAME,
93 };
94
95 static gpointer ags_machine_parent_class = NULL;
96 static guint machine_signals[LAST_SIGNAL];
97
98 GType
ags_machine_get_type(void)99 ags_machine_get_type(void)
100 {
101 static volatile gsize g_define_type_id__volatile = 0;
102
103 if(g_once_init_enter (&g_define_type_id__volatile)){
104 GType ags_type_machine = 0;
105
106 static const GTypeInfo ags_machine_info = {
107 sizeof (AgsMachineClass),
108 NULL, /* base_init */
109 NULL, /* base_finalize */
110 (GClassInitFunc) ags_machine_class_init,
111 NULL, /* class_finalize */
112 NULL, /* class_data */
113 sizeof (AgsMachine),
114 0, /* n_preallocs */
115 (GInstanceInitFunc) ags_machine_init,
116 };
117
118 static const GInterfaceInfo ags_connectable_interface_info = {
119 (GInterfaceInitFunc) ags_machine_connectable_interface_init,
120 NULL, /* interface_finalize */
121 NULL, /* interface_data */
122 };
123
124 ags_type_machine = g_type_register_static(GTK_TYPE_BIN,
125 "AgsMachine", &ags_machine_info,
126 0);
127
128 g_type_add_interface_static(ags_type_machine,
129 AGS_TYPE_CONNECTABLE,
130 &ags_connectable_interface_info);
131
132 g_once_init_leave(&g_define_type_id__volatile, ags_type_machine);
133 }
134
135 return g_define_type_id__volatile;
136 }
137
138 void
ags_machine_class_init(AgsMachineClass * machine)139 ags_machine_class_init(AgsMachineClass *machine)
140 {
141 GObjectClass *gobject;
142
143 GParamSpec *param_spec;
144
145 ags_machine_parent_class = g_type_class_peek_parent(machine);
146
147 /* GObjectClass */
148 gobject = (GObjectClass *) machine;
149
150 gobject->set_property = ags_machine_set_property;
151 gobject->get_property = ags_machine_get_property;
152
153 gobject->finalize = ags_machine_finalize;
154
155 /* properties */
156 /**
157 * AgsMachine:samplerate:
158 *
159 * The samplerate.
160 *
161 * Since: 3.0.0
162 */
163 param_spec = g_param_spec_uint("samplerate",
164 i18n_pspec("samplerate"),
165 i18n_pspec("The samplerate"),
166 0,
167 G_MAXUINT32,
168 AGS_SOUNDCARD_DEFAULT_SAMPLERATE,
169 G_PARAM_READABLE | G_PARAM_WRITABLE);
170 g_object_class_install_property(gobject,
171 PROP_SAMPLERATE,
172 param_spec);
173
174 /**
175 * AgsMachine:buffer-size:
176 *
177 * The buffer length.
178 *
179 * Since: 3.0.0
180 */
181 param_spec = g_param_spec_uint("buffer-size",
182 i18n_pspec("buffer size"),
183 i18n_pspec("The buffer size"),
184 0,
185 G_MAXUINT32,
186 AGS_SOUNDCARD_DEFAULT_BUFFER_SIZE,
187 G_PARAM_READABLE | G_PARAM_WRITABLE);
188 g_object_class_install_property(gobject,
189 PROP_BUFFER_SIZE,
190 param_spec);
191
192 /**
193 * AgsMachine:format:
194 *
195 * The format.
196 *
197 * Since: 3.0.0
198 */
199 param_spec = g_param_spec_uint("format",
200 i18n_pspec("format"),
201 i18n_pspec("The format"),
202 0,
203 G_MAXUINT32,
204 AGS_SOUNDCARD_DEFAULT_FORMAT,
205 G_PARAM_READABLE | G_PARAM_WRITABLE);
206 g_object_class_install_property(gobject,
207 PROP_FORMAT,
208 param_spec);
209
210 /**
211 * AgsMachine:audio:
212 *
213 * The assigned #AgsAudio to visualize.
214 *
215 * Since: 3.0.0
216 */
217 param_spec = g_param_spec_object("audio",
218 i18n_pspec("assigned audio"),
219 i18n_pspec("The audio it is assigned to"),
220 AGS_TYPE_AUDIO,
221 G_PARAM_READABLE | G_PARAM_WRITABLE);
222 g_object_class_install_property(gobject,
223 PROP_AUDIO,
224 param_spec);
225
226 /**
227 * AgsMachine:machine-name:
228 *
229 * The machine's name.
230 *
231 * Since: 3.0.0
232 */
233 param_spec = g_param_spec_string("machine-name",
234 i18n_pspec("machine name"),
235 i18n_pspec("The machine's name"),
236 NULL,
237 G_PARAM_READABLE | G_PARAM_WRITABLE);
238 g_object_class_install_property(gobject,
239 PROP_MACHINE_NAME,
240 param_spec);
241
242 /* AgsMachineClass */
243 machine->samplerate_changed = NULL;
244 machine->buffer_size_changed = NULL;
245 machine->format_changed = NULL;
246
247 machine->resize_pads = ags_machine_real_resize_pads;
248 machine->resize_audio_channels = ags_machine_real_resize_audio_channels;
249 machine->map_recall = ags_machine_real_map_recall;
250 machine->find_port = ags_machine_real_find_port;
251 machine->stop = NULL;
252
253 /* signals */
254 /**
255 * AgsMachine::samplerate-changed:
256 * @machine: the #AgsMachine
257 * @samplerate: the samplerate
258 * @old_samplerate: the old samplerate
259 *
260 * The ::samplerate-changed signal notifies about changed samplerate.
261 *
262 * Since: 3.0.0
263 */
264 machine_signals[SAMPLERATE_CHANGED] =
265 g_signal_new("samplerate-changed",
266 G_TYPE_FROM_CLASS(machine),
267 G_SIGNAL_RUN_LAST,
268 G_STRUCT_OFFSET(AgsMachineClass, samplerate_changed),
269 NULL, NULL,
270 ags_cclosure_marshal_VOID__UINT_UINT,
271 G_TYPE_NONE, 2,
272 G_TYPE_UINT,
273 G_TYPE_UINT);
274
275 /**
276 * AgsMachine::buffer-size-changed:
277 * @machine: the #AgsMachine
278 * @buffer_size: the buffer size
279 * @old_buffer_size: the old buffer size
280 *
281 * The ::buffer-size-changed signal notifies about changed buffer size.
282 *
283 * Since: 3.0.0
284 */
285 machine_signals[BUFFER_SIZE_CHANGED] =
286 g_signal_new("buffer-size-changed",
287 G_TYPE_FROM_CLASS(machine),
288 G_SIGNAL_RUN_LAST,
289 G_STRUCT_OFFSET(AgsMachineClass, buffer_size_changed),
290 NULL, NULL,
291 ags_cclosure_marshal_VOID__UINT_UINT,
292 G_TYPE_NONE, 2,
293 G_TYPE_UINT,
294 G_TYPE_UINT);
295
296 /**
297 * AgsMachine::format-changed:
298 * @machine: the #AgsMachine
299 * @format: the format
300 * @old_format: the old format
301 *
302 * The ::format-changed signal notifies about changed format.
303 *
304 * Since: 3.0.0
305 */
306 machine_signals[FORMAT_CHANGED] =
307 g_signal_new("format-changed",
308 G_TYPE_FROM_CLASS(machine),
309 G_SIGNAL_RUN_LAST,
310 G_STRUCT_OFFSET(AgsMachineClass, format_changed),
311 NULL, NULL,
312 ags_cclosure_marshal_VOID__UINT_UINT,
313 G_TYPE_NONE, 2,
314 G_TYPE_UINT,
315 G_TYPE_UINT);
316
317 /**
318 * AgsMachine::resize-audio-channels:
319 * @machine: the #AgsMachine to modify
320 * @new_size: the new size
321 * @old_size: the old size
322 *
323 * The ::resize-audio-channels signal notifies about changed channel allocation within
324 * audio.
325 *
326 * Since: 3.0.0
327 */
328 machine_signals[RESIZE_AUDIO_CHANNELS] =
329 g_signal_new("resize-audio-channels",
330 G_TYPE_FROM_CLASS(machine),
331 G_SIGNAL_RUN_LAST,
332 G_STRUCT_OFFSET(AgsMachineClass, resize_audio_channels),
333 NULL, NULL,
334 ags_cclosure_marshal_VOID__UINT_UINT,
335 G_TYPE_NONE, 2,
336 G_TYPE_UINT,
337 G_TYPE_UINT);
338
339 /**
340 * AgsMachine::resize-pads:
341 * @machine: the #AgsMachine to modify
342 * @channel_type: either %AGS_TYPE_INPUT or %AGS_TYPE_OUTPUT
343 * @new_size: the new size
344 * @old_size: the old size
345 *
346 * The ::resize-pads signal notifies about changed channel allocation within
347 * audio.
348 *
349 * Since: 3.0.0
350 */
351 machine_signals[RESIZE_PADS] =
352 g_signal_new("resize-pads",
353 G_TYPE_FROM_CLASS(machine),
354 G_SIGNAL_RUN_LAST,
355 G_STRUCT_OFFSET(AgsMachineClass, resize_pads),
356 NULL, NULL,
357 ags_cclosure_marshal_VOID__ULONG_UINT_UINT,
358 G_TYPE_NONE, 3,
359 G_TYPE_ULONG,
360 G_TYPE_UINT,
361 G_TYPE_UINT);
362
363 /**
364 * AgsMachine::map-recall:
365 * @machine: the #AgsMachine
366 *
367 * The ::map-recall should be used to add the machine's default recall.
368 *
369 * Since: 3.0.0
370 */
371 machine_signals[MAP_RECALL] =
372 g_signal_new("map-recall",
373 G_TYPE_FROM_CLASS(machine),
374 G_SIGNAL_RUN_LAST,
375 G_STRUCT_OFFSET(AgsMachineClass, map_recall),
376 NULL, NULL,
377 g_cclosure_marshal_VOID__VOID,
378 G_TYPE_NONE, 0);
379
380 /**
381 * AgsMachine::find-port:
382 * @machine: the #AgsMachine to resize
383 * Returns: a #GList with associated ports
384 *
385 * The ::find-port signal emits as recall should be mapped.
386 *
387 * Since: 3.0.0
388 */
389 machine_signals[FIND_PORT] =
390 g_signal_new("find-port",
391 G_TYPE_FROM_CLASS(machine),
392 G_SIGNAL_RUN_LAST,
393 G_STRUCT_OFFSET(AgsMachineClass, find_port),
394 NULL, NULL,
395 ags_cclosure_marshal_POINTER__VOID,
396 G_TYPE_POINTER, 0);
397
398 /**
399 * AgsMachine::stop:
400 * @machine: the #AgsMachine
401 * @recall_id: the #GList-struct containing #AgsRecallID
402 * @sound_scope: the sound scope
403 *
404 * The ::stop signal gets emited as audio stops playback.
405 *
406 * Since: 3.0.0
407 */
408 machine_signals[STOP] =
409 g_signal_new("stop",
410 G_TYPE_FROM_CLASS(machine),
411 G_SIGNAL_RUN_LAST,
412 G_STRUCT_OFFSET(AgsMachineClass, stop),
413 NULL, NULL,
414 ags_cclosure_marshal_VOID__POINTER_INT,
415 G_TYPE_NONE, 2,
416 G_TYPE_POINTER, G_TYPE_INT);
417 }
418
419 void
ags_machine_connectable_interface_init(AgsConnectableInterface * connectable)420 ags_machine_connectable_interface_init(AgsConnectableInterface *connectable)
421 {
422 connectable->is_ready = NULL;
423 connectable->is_connected = NULL;
424 connectable->connect = ags_machine_connect;
425 connectable->disconnect = ags_machine_disconnect;
426 }
427
428 void
ags_machine_init(AgsMachine * machine)429 ags_machine_init(AgsMachine *machine)
430 {
431 GtkBox *vbox;
432 GtkFrame *frame;
433
434 AgsApplicationContext *application_context;
435
436 application_context = ags_application_context_get_instance();
437
438 g_signal_connect(application_context, "check-message",
439 G_CALLBACK(ags_machine_check_message_callback), machine);
440
441 g_signal_connect_after((GObject *) machine, "parent_set",
442 G_CALLBACK(ags_machine_parent_set_callback), (gpointer) machine);
443
444 machine->machine_name = NULL;
445
446 machine->version = AGS_MACHINE_DEFAULT_VERSION;
447 machine->build_id = AGS_MACHINE_DEFAULT_BUILD_ID;
448
449 machine->flags = 0;
450 machine->file_input_flags = 0;
451 machine->mapping_flags = 0;
452 machine->connection_flags = 0;
453
454 machine->output_pad_type = G_TYPE_NONE;
455 machine->input_pad_type = G_TYPE_NONE;
456
457 machine->bank_0 = 0;
458 machine->bank_1 = 0;
459
460 gtk_widget_set_vexpand((GtkWidget *) machine,
461 FALSE);
462 gtk_widget_set_hexpand((GtkWidget *) machine,
463 TRUE);
464
465 gtk_widget_set_valign((GtkWidget *) machine,
466 GTK_ALIGN_START);
467
468 vbox = (GtkBox *) gtk_box_new(GTK_ORIENTATION_VERTICAL,
469 0);
470
471 frame = (GtkFrame *) gtk_frame_new(NULL);
472
473 gtk_widget_set_hexpand((GtkWidget *) frame,
474 TRUE);
475
476 gtk_container_add((GtkContainer *) machine,
477 (GtkWidget *) frame);
478
479 machine->audio = ags_audio_new(NULL);
480 g_object_ref(G_OBJECT(machine->audio));
481
482 machine->samplerate = machine->audio->samplerate;
483 machine->buffer_size = machine->audio->buffer_size;
484 machine->format = machine->audio->format;
485
486 machine->audio_channels = machine->audio->audio_channels;
487
488 machine->output_pads = machine->audio->output_pads;
489 machine->input_pads = machine->audio->input_pads;
490
491 machine->audio->flags |= AGS_AUDIO_CAN_NEXT_ACTIVE;
492 machine->audio->machine_widget = (GObject *) machine;
493
494 machine->active_playback = NULL;
495
496 /* AgsAudio related forwarded signals */
497 g_signal_connect_after(G_OBJECT(machine), "resize-audio-channels",
498 G_CALLBACK(ags_machine_resize_audio_channels_callback), NULL);
499
500 g_signal_connect_after(G_OBJECT(machine), "resize-pads",
501 G_CALLBACK(ags_machine_resize_pads_callback), NULL);
502
503 g_signal_connect_after(G_OBJECT(machine), "stop",
504 G_CALLBACK(ags_machine_stop_callback), NULL);
505
506 machine->play = NULL;
507
508 machine->output = NULL;
509 machine->selected_output_pad = NULL;
510
511 machine->input = NULL;
512 machine->selected_input_pad = NULL;
513
514 machine->bridge = NULL;
515
516 machine->port = NULL;
517 machine->enabled_automation_port = NULL;
518
519 machine->popup = ags_machine_popup_new(machine);
520 g_object_ref(machine->popup);
521
522 machine->menu_tool_button = (GtkMenuToolButton *) g_object_new(GTK_TYPE_MENU_TOOL_BUTTON,
523 "label", "machine",
524 "menu", machine->popup,
525 NULL);
526 gtk_frame_set_label_widget(frame,
527 (GtkWidget *) machine->menu_tool_button);
528 machine->properties = NULL;
529 machine->rename = NULL;
530 machine->rename_audio = NULL;
531 machine->reposition_audio = NULL;
532 machine->connection_editor = NULL;
533 machine->midi_dialog = NULL;
534 machine->envelope_dialog = NULL;
535
536 machine->midi_export_dialog = NULL;
537 machine->wave_export_dialog = NULL;
538 machine->midi_import_dialog = NULL;
539 machine->wave_import_dialog = NULL;
540 }
541
542 void
ags_machine_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)543 ags_machine_set_property(GObject *gobject,
544 guint prop_id,
545 const GValue *value,
546 GParamSpec *param_spec)
547 {
548 AgsWindow *window;
549 AgsMachine *machine;
550
551 machine = AGS_MACHINE(gobject);
552 window = (AgsWindow *) gtk_widget_get_ancestor((GtkWidget *) machine,
553 AGS_TYPE_WINDOW);
554
555 switch(prop_id){
556 case PROP_SAMPLERATE:
557 {
558 GList *start_list, *list;
559
560 guint samplerate, old_samplerate;
561
562 samplerate = g_value_get_uint(value);
563 old_samplerate = machine->samplerate;
564
565 if(samplerate == old_samplerate){
566 return;
567 }
568
569 machine->samplerate = samplerate;
570
571 ags_machine_samplerate_changed(machine,
572 samplerate, old_samplerate);
573
574 if(machine->output != NULL){
575 list =
576 start_list = gtk_container_get_children(GTK_CONTAINER(machine->output));
577
578 while(list != NULL){
579 if(AGS_IS_PAD(list->data)){
580 g_object_set(list->data,
581 "samplerate", samplerate,
582 NULL);
583 }
584
585 list = list->next;
586 }
587
588 g_list_free(start_list);
589 }
590
591 if(machine->input != NULL){
592 list =
593 start_list = gtk_container_get_children(GTK_CONTAINER(machine->input));
594
595 while(list != NULL){
596 if(AGS_IS_PAD(list->data)){
597 g_object_set(list->data,
598 "samplerate", samplerate,
599 NULL);
600 }
601
602 list = list->next;
603 }
604
605 g_list_free(start_list);
606 }
607
608 if(machine->bridge != NULL){
609 g_object_set(machine->bridge,
610 "samplerate", samplerate,
611 NULL);
612 }
613 }
614 break;
615 case PROP_BUFFER_SIZE:
616 {
617 GList *start_list, *list;
618
619 guint buffer_size, old_buffer_size;
620
621 buffer_size = g_value_get_uint(value);
622 old_buffer_size = machine->buffer_size;
623
624 if(buffer_size == old_buffer_size){
625 return;
626 }
627
628 machine->buffer_size = buffer_size;
629
630 ags_machine_buffer_size_changed(machine,
631 buffer_size, old_buffer_size);
632
633
634 if(machine->output != NULL){
635 list =
636 start_list = gtk_container_get_children(GTK_CONTAINER(machine->output));
637
638 while(list != NULL){
639 if(AGS_IS_PAD(list->data)){
640 g_object_set(list->data,
641 "buffer-size", buffer_size,
642 NULL);
643 }
644
645 list = list->next;
646 }
647
648 g_list_free(start_list);
649 }
650
651 if(machine->input != NULL){
652 list =
653 start_list = gtk_container_get_children(GTK_CONTAINER(machine->input));
654
655 while(list != NULL){
656 if(AGS_IS_PAD(list->data)){
657 g_object_set(list->data,
658 "buffer-size", buffer_size,
659 NULL);
660 }
661
662 list = list->next;
663 }
664
665 g_list_free(start_list);
666 }
667
668 if(machine->bridge != NULL){
669 g_object_set(machine->bridge,
670 "buffer-size", buffer_size,
671 NULL);
672 }
673 }
674 break;
675 case PROP_FORMAT:
676 {
677 GList *start_list, *list;
678
679 guint format, old_format;
680
681 format = g_value_get_uint(value);
682 old_format = machine->format;
683
684 if(format == old_format){
685 return;
686 }
687
688 machine->format = format;
689
690 ags_machine_format_changed(machine,
691 format, old_format);
692
693
694 if(machine->output != NULL){
695 list =
696 start_list = gtk_container_get_children(GTK_CONTAINER(machine->output));
697
698 while(list != NULL){
699 if(AGS_IS_PAD(list->data)){
700 g_object_set(list->data,
701 "format", format,
702 NULL);
703 }
704
705 list = list->next;
706 }
707
708 g_list_free(start_list);
709 }
710
711 if(machine->input != NULL){
712 list =
713 start_list = gtk_container_get_children(GTK_CONTAINER(machine->input));
714
715 while(list != NULL){
716 if(AGS_IS_PAD(list->data)){
717 g_object_set(list->data,
718 "format", format,
719 NULL);
720 }
721
722 list = list->next;
723 }
724
725 g_list_free(start_list);
726 }
727
728 if(machine->bridge != NULL){
729 g_object_set(machine->bridge,
730 "format", format,
731 NULL);
732 }
733 }
734 break;
735 case PROP_AUDIO:
736 {
737 AgsAudio *audio;
738 gboolean reset;
739
740 audio = (AgsAudio *) g_value_get_object(value);
741
742 reset = TRUE;
743
744 if(machine->audio != NULL){
745 GList *pad;
746
747 g_object_unref(G_OBJECT(machine->audio));
748
749 if(audio == NULL){
750 /* destroy pad */
751 pad = gtk_container_get_children(machine->output);
752 // pad = g_list_nth(pad, audio->output_pads);
753
754 while(pad != NULL){
755 gtk_widget_destroy(pad->data);
756
757 pad = pad->next;
758 }
759
760 pad = gtk_container_get_children(machine->input);
761 // pad = g_list_nth(pad, audio->input_pads);
762
763 while(pad != NULL){
764 gtk_widget_destroy(pad->data);
765
766 pad = pad->next;
767 }
768
769 reset = FALSE;
770 }
771 }
772
773 if(audio != NULL){
774 g_object_ref(G_OBJECT(audio));
775 machine->audio = audio;
776
777 if(reset){
778 AgsChannel *start_input, *start_output;
779 AgsChannel *input, *next_pad_input, *output, *next_pad_output;
780
781 GList *start_pad, *pad;
782 GList *start_line, *line;
783
784 guint audio_channels;
785 guint output_pads, input_pads;
786 guint i;
787
788 g_object_get(audio,
789 "audio-channels", &audio_channels,
790 "output-pads", &output_pads,
791 "input-pads", &input_pads,
792 "output", &start_output,
793 "input", &start_input,
794 NULL);
795
796 /* set channel and resize for AgsOutput */
797 output = start_output;
798
799 if(output != NULL){
800 g_object_ref(output);
801 }
802
803 next_pad_output = NULL;
804
805 if(machine->output_pad_type != G_TYPE_NONE){
806 pad =
807 start_pad = gtk_container_get_children(machine->output);
808
809 i = 0;
810
811 while(pad != NULL && output != NULL){
812 line =
813 start_line = gtk_container_get_children(GTK_CONTAINER(AGS_PAD(pad->data)->expander_set));
814
815 ags_pad_resize_lines(AGS_PAD(pad->data), machine->output_line_type,
816 audio_channels, g_list_length(line));
817 g_object_set(G_OBJECT(pad->data),
818 "channel", output,
819 NULL);
820
821 g_list_free(start_line);
822
823 /* iterate */
824 next_pad_output = ags_channel_next_pad(output);
825
826 g_object_unref(output);
827
828 output = next_pad_output;
829
830 pad = pad->next;
831 i++;
832 }
833
834 g_list_free(start_pad);
835
836 if(output != NULL){
837 AgsPad *pad;
838
839 /* add pad */
840 for(; i < audio->output_pads; i++){
841 pad = g_object_new(machine->output_pad_type,
842 "channel", output,
843 NULL);
844 gtk_container_add(machine->output,
845 GTK_WIDGET(pad));
846
847 ags_pad_resize_lines(pad, machine->output_line_type,
848 audio_channels, 0);
849 }
850 }else{
851 /* destroy pad */
852 pad =
853 start_pad = gtk_container_get_children(machine->output);
854 pad = g_list_nth(pad,
855 output_pads);
856
857 while(pad != NULL){
858 gtk_widget_destroy(pad->data);
859
860 pad = pad->next;
861 }
862
863 g_list_free(start_pad);
864 }
865 }
866
867 if(start_output != NULL){
868 g_object_unref(start_output);
869 }
870
871 if(next_pad_output != NULL){
872 g_object_unref(next_pad_output);
873 }
874
875 /* set channel and resize for AgsOutput */
876 input = start_input;
877
878 if(input != NULL){
879 g_object_ref(input);
880 }
881
882 next_pad_input = NULL;
883
884 if(machine->input_pad_type != G_TYPE_NONE){
885 pad =
886 start_pad = gtk_container_get_children(machine->input);
887
888 i = 0;
889
890 while(pad != NULL && input != NULL){
891 line = gtk_container_get_children(GTK_CONTAINER(AGS_PAD(pad->data)->expander_set));
892
893 ags_pad_resize_lines(AGS_PAD(pad->data), machine->input_line_type,
894 audio_channels, g_list_length(line));
895 g_object_set(G_OBJECT(pad->data),
896 "channel", input,
897 NULL);
898
899 g_list_free(line);
900
901 /* iterate */
902 next_pad_output = ags_channel_next_pad(output);
903
904 g_object_unref(output);
905
906 output = next_pad_output;
907
908 pad = pad->next;
909 i++;
910 }
911
912 g_list_free(start_pad);
913
914 if(input != NULL){
915 AgsPad *pad;
916
917 /* add pad */
918 for(; i < audio->input_pads; i++){
919 pad = g_object_new(machine->input_pad_type,
920 "channel", input,
921 NULL);
922 gtk_container_add(machine->input,
923 GTK_WIDGET(pad));
924
925 ags_pad_resize_lines(pad, machine->input_line_type,
926 audio_channels, 0);
927 }
928 }else{
929 /* destroy pad */
930 pad =
931 start_pad = gtk_container_get_children(machine->input);
932 pad = g_list_nth(pad, audio->input_pads);
933
934 while(pad != NULL){
935 gtk_widget_destroy(pad->data);
936
937 pad = pad->next;
938 }
939
940 g_list_free(start_pad);
941 }
942 }
943
944 if(start_input != NULL){
945 g_object_unref(start_input);
946 }
947
948 if(next_pad_input != NULL){
949 g_object_unref(next_pad_input);
950 }
951 }else{
952 AgsPad *pad;
953
954 AgsChannel *start_input, *start_output;
955 AgsChannel *input, *next_pad_input, *output, *next_pad_output;
956
957 guint audio_channels;
958 guint output_pads, input_pads;
959 guint i;
960
961 g_object_get(audio,
962 "audio-channels", &audio_channels,
963 "output-pads", &output_pads,
964 "input-pads", &input_pads,
965 "output", &start_output,
966 "input", &start_input,
967 NULL);
968
969 /* add pad */
970 output = start_output;
971
972 if(output != NULL){
973 g_object_ref(output);
974 }
975
976 next_pad_output = NULL;
977
978 if(machine->output_pad_type != G_TYPE_NONE){
979 for(i = 0; i < output_pads; i++){
980 pad = g_object_new(machine->output_pad_type,
981 "channel", output,
982 NULL);
983 gtk_container_add(machine->output,
984 GTK_WIDGET(pad));
985 ags_pad_resize_lines(pad, machine->output_line_type,
986 audio_channels, 0);
987
988 /* iterate */
989 next_pad_output = ags_channel_next_pad(output);
990
991 g_object_unref(output);
992
993 output = next_pad_output;
994 }
995 }
996
997 if(start_output != NULL){
998 g_object_unref(start_output);
999 }
1000
1001 if(next_pad_output != NULL){
1002 g_object_unref(next_pad_output);
1003 }
1004
1005 /* add pad */
1006 input = start_input;
1007
1008 if(input != NULL){
1009 g_object_ref(input);
1010 }
1011
1012 next_pad_input = NULL;
1013
1014 if(machine->input_pad_type != G_TYPE_NONE){
1015 for(i = 0; i < input_pads; i++){
1016 pad = g_object_new(machine->input_pad_type,
1017 "channel", input,
1018 NULL);
1019 gtk_container_add(machine->input,
1020 GTK_WIDGET(pad));
1021 ags_pad_resize_lines(pad, machine->input_line_type,
1022 audio_channels, 0);
1023
1024 /* iterate */
1025 next_pad_input = ags_channel_next_pad(input);
1026
1027 g_object_unref(input);
1028
1029 input = next_pad_input;
1030 }
1031 }
1032
1033 if(start_input != NULL){
1034 g_object_unref(start_input);
1035 }
1036
1037 if(next_pad_input != NULL){
1038 g_object_unref(next_pad_input);
1039 }
1040 }
1041 }else{
1042 machine->audio = NULL;
1043 }
1044 }
1045 break;
1046 case PROP_MACHINE_NAME:
1047 {
1048 gchar *machine_name;
1049 gchar *str;
1050
1051 machine_name = g_value_get_string(value);
1052
1053 if(machine_name == machine->machine_name){
1054 return;
1055 }
1056
1057 if(machine->machine_name != NULL){
1058 g_free(machine->machine_name);
1059 }
1060
1061 machine->machine_name = g_strdup(machine_name);
1062
1063 /* update UI */
1064 str = g_strdup_printf("%s: %s",
1065 G_OBJECT_TYPE_NAME(machine),
1066 machine_name);
1067
1068 g_object_set(machine->menu_tool_button,
1069 "label", str,
1070 NULL);
1071
1072 g_free(str);
1073 }
1074 break;
1075 default:
1076 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
1077 break;
1078 }
1079 }
1080
1081 void
ags_machine_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)1082 ags_machine_get_property(GObject *gobject,
1083 guint prop_id,
1084 GValue *value,
1085 GParamSpec *param_spec)
1086 {
1087 AgsMachine *machine;
1088
1089 machine = AGS_MACHINE(gobject);
1090
1091 switch(prop_id){
1092 case PROP_SAMPLERATE:
1093 {
1094 g_value_set_uint(value,
1095 machine->samplerate);
1096 }
1097 break;
1098 case PROP_BUFFER_SIZE:
1099 {
1100 g_value_set_uint(value,
1101 machine->buffer_size);
1102 }
1103 break;
1104 case PROP_FORMAT:
1105 {
1106 g_value_set_uint(value,
1107 machine->format);
1108 }
1109 break;
1110 case PROP_AUDIO:
1111 {
1112 g_value_set_object(value, machine->audio);
1113 }
1114 break;
1115 case PROP_MACHINE_NAME:
1116 {
1117 g_value_set_string(value, machine->machine_name);
1118 }
1119 break;
1120 default:
1121 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
1122 break;
1123 }
1124 }
1125
1126 static void
ags_machine_finalize(GObject * gobject)1127 ags_machine_finalize(GObject *gobject)
1128 {
1129 AgsMachine *machine;
1130
1131 AgsAudio *audio;
1132
1133 AgsApplicationContext *application_context;
1134
1135 GList *start_list;
1136
1137 application_context = ags_application_context_get_instance();
1138
1139 machine = (AgsMachine *) gobject;
1140
1141 g_object_disconnect(application_context,
1142 "any_signal::check-message",
1143 G_CALLBACK(ags_machine_check_message_callback),
1144 machine,
1145 NULL);
1146
1147 /* remove from sound provider */
1148 start_list = ags_sound_provider_get_audio(AGS_SOUND_PROVIDER(application_context));
1149
1150 start_list = g_list_remove(start_list,
1151 machine->audio);
1152 ags_sound_provider_set_audio(AGS_SOUND_PROVIDER(application_context),
1153 start_list);
1154
1155 g_object_unref(machine->audio);
1156 g_list_foreach(start_list,
1157 (GFunc) g_object_unref,
1158 NULL);
1159
1160 g_list_free_full(machine->enabled_automation_port,
1161 (GDestroyNotify) ags_machine_automation_port_free);
1162
1163 //TODO:JK: better clean-up of audio
1164
1165 if(machine->properties != NULL){
1166 gtk_widget_destroy((GtkWidget *) machine->properties);
1167 }
1168
1169 if(machine->rename != NULL){
1170 gtk_widget_destroy((GtkWidget *) machine->rename);
1171 }
1172
1173 if(machine->rename_audio != NULL){
1174 gtk_widget_destroy((GtkWidget *) machine->rename_audio);
1175 }
1176
1177 if(machine->reposition_audio != NULL){
1178 gtk_widget_destroy((GtkWidget *) machine->reposition_audio);
1179 }
1180
1181 if(machine->machine_name != NULL){
1182 g_free(machine->machine_name);
1183 }
1184
1185 audio = machine->audio;
1186
1187 /* call parent */
1188 G_OBJECT_CLASS(ags_machine_parent_class)->finalize(gobject);
1189
1190 if(audio != NULL){
1191 g_object_unref(G_OBJECT(audio));
1192 }
1193 }
1194
1195 void
ags_machine_connect(AgsConnectable * connectable)1196 ags_machine_connect(AgsConnectable *connectable)
1197 {
1198 AgsMachine *machine;
1199
1200 GList *list_start, *list;
1201
1202 /* AgsMachine */
1203 machine = AGS_MACHINE(connectable);
1204
1205 if((AGS_MACHINE_CONNECTED & (machine->flags)) != 0){
1206 return;
1207 }
1208
1209 machine->flags |= AGS_MACHINE_CONNECTED;
1210
1211 g_signal_connect_after(G_OBJECT(machine), "map-recall",
1212 G_CALLBACK(ags_machine_map_recall_callback), NULL);
1213
1214 if((AGS_MACHINE_PREMAPPED_RECALL & (machine->flags)) == 0){
1215 if((AGS_MACHINE_MAPPED_RECALL & (machine->flags)) == 0){
1216 ags_machine_map_recall(machine);
1217 }
1218 }else{
1219 // machine->flags &= ~AGS_MACHINE_PREMAPPED_RECALL;
1220 #ifdef AGS_DEBUG
1221 g_message("find port");
1222 #endif
1223
1224 ags_machine_find_port(machine);
1225 }
1226
1227 if(machine->bridge != NULL){
1228 ags_connectable_connect(AGS_CONNECTABLE(machine->bridge));
1229 }
1230
1231 if(machine->play != NULL){
1232 g_signal_connect(G_OBJECT(machine->play), "clicked",
1233 G_CALLBACK(ags_machine_play_callback), (gpointer) machine);
1234 }
1235
1236 /* GtkWidget */
1237 // g_signal_connect(G_OBJECT (machine), "button_press_event",
1238 // G_CALLBACK(ags_machine_button_press_callback), (gpointer) machine);
1239
1240 /* AgsPad - input */
1241 if(machine->input != NULL){
1242 list_start =
1243 list = gtk_container_get_children(GTK_CONTAINER(machine->input));
1244
1245 while(list != NULL){
1246 ags_connectable_connect(AGS_CONNECTABLE(list->data));
1247
1248 list = list->next;
1249 }
1250
1251 g_list_free(list_start);
1252 }
1253
1254 /* AgsPad - output */
1255 if(machine->output != NULL){
1256 list_start =
1257 list = gtk_container_get_children(GTK_CONTAINER(machine->output));
1258
1259 while(list != NULL){
1260 ags_connectable_connect(AGS_CONNECTABLE(list->data));
1261
1262 list = list->next;
1263 }
1264
1265 g_list_free(list_start);
1266 }
1267 }
1268
1269 void
ags_machine_disconnect(AgsConnectable * connectable)1270 ags_machine_disconnect(AgsConnectable *connectable)
1271 {
1272 AgsMachine *machine;
1273
1274 GList *list_start, *list;
1275
1276 /* AgsMachine */
1277 machine = AGS_MACHINE(connectable);
1278
1279 if((AGS_MACHINE_CONNECTED & (machine->flags)) == 0){
1280 return;
1281 }
1282
1283 machine->flags &= (~AGS_MACHINE_CONNECTED);
1284
1285 g_object_disconnect(G_OBJECT(machine),
1286 "any_signal::map-recall",
1287 G_CALLBACK(ags_machine_map_recall_callback),
1288 NULL,
1289 NULL);
1290
1291 if(machine->bridge != NULL){
1292 ags_connectable_disconnect(AGS_CONNECTABLE(machine->bridge));
1293 }
1294
1295 /* AgsPad - input */
1296 if(machine->input != NULL){
1297 list_start =
1298 list = gtk_container_get_children(GTK_CONTAINER(machine->input));
1299
1300 while(list != NULL){
1301 ags_connectable_disconnect(AGS_CONNECTABLE(list->data));
1302
1303 list = list->next;
1304 }
1305
1306 g_list_free(list_start);
1307 }
1308
1309 /* AgsPad - output */
1310 if(machine->output != NULL){
1311 list_start =
1312 list = gtk_container_get_children(GTK_CONTAINER(machine->output));
1313
1314 while(list != NULL){
1315 ags_connectable_disconnect(AGS_CONNECTABLE(list->data));
1316
1317 list = list->next;
1318 }
1319
1320 g_list_free(list_start);
1321 }
1322
1323 //TODO:JK: implement me
1324 g_signal_handlers_disconnect_by_data(machine->audio,
1325 machine);
1326 }
1327
1328 /**
1329 * ags_machine_reset_pattern_envelope:
1330 * @machine: the #AgsMachine
1331 *
1332 * Reset pattern envelope from preset.
1333 *
1334 * Since: 3.6.20
1335 */
1336 void
ags_machine_reset_pattern_envelope(AgsMachine * machine)1337 ags_machine_reset_pattern_envelope(AgsMachine *machine)
1338 {
1339 AgsAudio *audio;
1340 AgsChannel *start_input, *input, *next_input;
1341
1342 GList *start_preset, *preset;
1343
1344 guint audio_channels;
1345
1346 if(!AGS_IS_MACHINE(machine)){
1347 return;
1348 }
1349
1350 audio = machine->audio;
1351
1352 start_input = NULL;
1353
1354 start_preset = NULL;
1355
1356 audio_channels = 0;
1357
1358 g_object_get(audio,
1359 "input", &start_input,
1360 "preset", &start_preset,
1361 "audio-channels", &audio_channels,
1362 NULL);
1363
1364 /* unset all envelope */
1365 if(start_input != NULL){
1366 input = start_input;
1367 g_object_ref(input);
1368
1369 while(input != NULL){
1370 GList *start_pattern, *pattern;
1371
1372 start_pattern = NULL;
1373
1374 g_object_get(input,
1375 "pattern", &start_pattern,
1376 NULL);
1377
1378 pattern = start_pattern;
1379
1380 while(pattern != NULL){
1381 guint length;
1382 guint k;
1383
1384 ags_pattern_get_dim(pattern->data,
1385 NULL,
1386 NULL,
1387 &length);
1388
1389 for(k = 0; k < length; k++){
1390 AgsNote *note;
1391
1392 note = ags_pattern_get_note(pattern->data,
1393 k);
1394
1395 if(note != NULL){
1396 ags_note_unset_flags(note,
1397 AGS_NOTE_ENVELOPE);
1398 }
1399 }
1400
1401 pattern = pattern->next;
1402 }
1403
1404 /* iterate */
1405 next_input = ags_channel_next(input);
1406
1407 g_object_unref(input);
1408
1409 input = next_input;
1410 }
1411 }
1412
1413 /* apply envelope */
1414 preset = start_preset;
1415
1416 while(preset != NULL){
1417 AgsPreset *current_preset;
1418
1419 gchar *scope;
1420
1421 guint pad_start;
1422 guint pad_end;
1423 guint audio_channel_start;
1424 guint audio_channel_end;
1425 guint x_start;
1426 guint x_end;
1427
1428 GValue attack = G_VALUE_INIT;
1429 GValue decay = G_VALUE_INIT;
1430 GValue sustain = G_VALUE_INIT;
1431 GValue release = G_VALUE_INIT;
1432 GValue ratio = G_VALUE_INIT;
1433
1434 GError *error;
1435
1436 current_preset = preset->data;
1437
1438 scope = NULL;
1439
1440 g_object_get(current_preset,
1441 "scope", &scope,
1442 NULL);
1443
1444 if(!g_strcmp0(scope,
1445 "ags-envelope")){
1446 gboolean success;
1447
1448 success = TRUE;
1449
1450 audio_channel_start = 0;
1451 audio_channel_end = 0;
1452
1453 pad_start = 0;
1454 pad_end = 0;
1455
1456 x_start = 0;
1457 x_end = 0;
1458
1459 g_object_get(current_preset,
1460 "audio-channel-start", &audio_channel_start,
1461 "audio-channel-end", &audio_channel_end,
1462 "pad-start", &pad_start,
1463 "pad-end", &pad_end,
1464 "x-start", &x_start,
1465 "x-end", &x_end,
1466 NULL);
1467
1468 g_value_init(&attack, AGS_TYPE_COMPLEX);
1469
1470 error = NULL;
1471 ags_preset_get_parameter(current_preset,
1472 "attack", &attack,
1473 &error);
1474
1475 if(error != NULL){
1476 success = FALSE;
1477
1478 g_error_free(error);
1479 }
1480
1481 g_value_init(&decay, AGS_TYPE_COMPLEX);
1482
1483 error = NULL;
1484 ags_preset_get_parameter(current_preset,
1485 "decay", &decay,
1486 &error);
1487
1488 if(error != NULL){
1489 success = FALSE;
1490
1491 g_error_free(error);
1492 }
1493
1494 g_value_init(&sustain, AGS_TYPE_COMPLEX);
1495
1496 error = NULL;
1497 ags_preset_get_parameter(current_preset,
1498 "sustain", &sustain,
1499 &error);
1500
1501 if(error != NULL){
1502 success = FALSE;
1503
1504 g_error_free(error);
1505 }
1506
1507 g_value_init(&release, AGS_TYPE_COMPLEX);
1508
1509 error = NULL;
1510 ags_preset_get_parameter(current_preset,
1511 "release", &release,
1512 &error);
1513
1514 if(error != NULL){
1515 success = FALSE;
1516
1517 g_error_free(error);
1518 }
1519
1520 g_value_init(&ratio, AGS_TYPE_COMPLEX);
1521
1522 error = NULL;
1523 ags_preset_get_parameter(current_preset,
1524 "ratio", &ratio,
1525 &error);
1526
1527 if(error != NULL){
1528 success = FALSE;
1529
1530 g_error_free(error);
1531 }
1532
1533 if(success){
1534 guint i, i_start, i_stop;
1535 guint j, j_start, j_stop;
1536 guint k, k_start, k_stop;
1537
1538 i_start = pad_start;
1539 i_stop = pad_end + 1;
1540
1541 j_start = audio_channel_start;
1542 j_stop = audio_channel_end + 1;
1543
1544 k_start = x_start;
1545 k_stop = x_end + 1;
1546
1547 for(i = i_start; i < i_stop; i++){
1548 for(j = j_start; j < j_stop; j++){
1549 AgsChannel *channel;
1550
1551 GList *start_pattern, *pattern;
1552
1553 channel = ags_channel_nth(start_input,
1554 i * audio_channels + j);
1555
1556 start_pattern = NULL;
1557
1558 g_object_get(channel,
1559 "pattern", &start_pattern,
1560 NULL);
1561
1562 pattern = start_pattern;
1563
1564 while(pattern != NULL){
1565 for(k = k_start; k < k_stop; k++){
1566 AgsNote *note;
1567
1568 note = ags_pattern_get_note(pattern->data,
1569 k);
1570
1571 if(note != NULL){
1572 g_object_set(note,
1573 "attack", g_value_get_boxed(&attack),
1574 "decay", g_value_get_boxed(&decay),
1575 "sustain", g_value_get_boxed(&sustain),
1576 "release", g_value_get_boxed(&release),
1577 "ratio", g_value_get_boxed(&ratio),
1578 NULL);
1579
1580 ags_note_set_flags(note,
1581 AGS_NOTE_ENVELOPE);
1582
1583 g_object_unref(note);
1584 }
1585 }
1586
1587 pattern = pattern->next;
1588 }
1589
1590 if(channel != NULL){
1591 g_object_unref(channel);
1592 }
1593
1594 g_list_free_full(start_pattern,
1595 g_object_unref);
1596 }
1597 }
1598 }
1599
1600 g_value_unset(&attack);
1601 g_value_unset(&decay);
1602 g_value_unset(&sustain);
1603 g_value_unset(&release);
1604 g_value_unset(&ratio);
1605 }
1606
1607 g_free(scope);
1608
1609 preset = preset->next;
1610 }
1611
1612 if(start_input != NULL){
1613 g_object_unref(start_input);
1614 }
1615
1616 g_list_free_full(start_preset,
1617 g_object_unref);
1618 }
1619
1620 /**
1621 * ags_machine_automation_port_alloc:
1622 * @channel_type: the #GType of channel
1623 * @control_name: the control name as string
1624 *
1625 * Allocate #AgsMachineAutomationPort
1626 *
1627 * Returns: the new allocated #AgsMachineAutomationPort
1628 *
1629 * Since: 3.0.0
1630 */
1631 AgsMachineAutomationPort*
ags_machine_automation_port_alloc(GType channel_type,gchar * control_name)1632 ags_machine_automation_port_alloc(GType channel_type, gchar *control_name)
1633 {
1634 AgsMachineAutomationPort *automation_port;
1635
1636 automation_port = (AgsMachineAutomationPort *) malloc(sizeof(AgsMachineAutomationPort));
1637
1638 automation_port->channel_type = channel_type;
1639 automation_port->control_name = g_strdup(control_name);
1640
1641 return(automation_port);
1642 }
1643
1644 /**
1645 * ags_machine_automation_port_free:
1646 * @automation_port: the #AgsAutomationPort
1647 *
1648 * Free @automation_port
1649 *
1650 * Since: 3.0.0
1651 */
1652 void
ags_machine_automation_port_free(AgsMachineAutomationPort * automation_port)1653 ags_machine_automation_port_free(AgsMachineAutomationPort *automation_port)
1654 {
1655 if(automation_port == NULL){
1656 return;
1657 }
1658
1659 g_free(automation_port->control_name);
1660
1661 g_free(automation_port);
1662 }
1663
1664 /**
1665 * ags_machine_automation_port_find_channel_type_with_control_name:
1666 * @list: a #GList-struct containing #AgsAutomationPort
1667 * @channel_type: the #GType to match
1668 * @control_name: the control name as string to match
1669 *
1670 * Find #AgsAutomationPort by specifying channel type and control name.
1671 *
1672 * Returns: the matching #AgsAutomationPort or %NULL
1673 *
1674 * Since: 3.0.0
1675 */
1676 GList*
ags_machine_automation_port_find_channel_type_with_control_name(GList * list,GType channel_type,gchar * control_name)1677 ags_machine_automation_port_find_channel_type_with_control_name(GList *list,
1678 GType channel_type, gchar *control_name)
1679 {
1680 while(list != NULL){
1681 if(AGS_MACHINE_AUTOMATION_PORT(list->data)->channel_type == channel_type &&
1682 !g_strcmp0(AGS_MACHINE_AUTOMATION_PORT(list->data)->control_name,
1683 control_name)){
1684 return(list);
1685 }
1686
1687 list = list->next;
1688 }
1689
1690 return(NULL);
1691 }
1692
1693 /**
1694 * ags_machine_samplerate_changed:
1695 * @machine: the #AgsMachine
1696 * @samplerate: the samplerate
1697 * @old_samplerate: the old samplerate
1698 *
1699 * Notify about samplerate changed.
1700 *
1701 * Since: 3.0.0
1702 */
1703 void
ags_machine_samplerate_changed(AgsMachine * machine,guint samplerate,guint old_samplerate)1704 ags_machine_samplerate_changed(AgsMachine *machine,
1705 guint samplerate, guint old_samplerate)
1706 {
1707 g_return_if_fail(AGS_IS_MACHINE(machine));
1708
1709 g_object_ref((GObject *) machine);
1710 g_signal_emit(G_OBJECT(machine),
1711 machine_signals[SAMPLERATE_CHANGED], 0,
1712 samplerate,
1713 old_samplerate);
1714 g_object_unref((GObject *) machine);
1715 }
1716
1717 /**
1718 * ags_machine_buffer_size_changed:
1719 * @machine: the #AgsMachine
1720 * @buffer_size: the buffer_size
1721 * @old_buffer_size: the old buffer_size
1722 *
1723 * Notify about buffer_size changed.
1724 *
1725 * Since: 3.0.0
1726 */
1727 void
ags_machine_buffer_size_changed(AgsMachine * machine,guint buffer_size,guint old_buffer_size)1728 ags_machine_buffer_size_changed(AgsMachine *machine,
1729 guint buffer_size, guint old_buffer_size)
1730 {
1731 g_return_if_fail(AGS_IS_MACHINE(machine));
1732
1733 g_object_ref((GObject *) machine);
1734 g_signal_emit(G_OBJECT(machine),
1735 machine_signals[BUFFER_SIZE_CHANGED], 0,
1736 buffer_size,
1737 old_buffer_size);
1738 g_object_unref((GObject *) machine);
1739 }
1740
1741 /**
1742 * ags_machine_format_changed:
1743 * @machine: the #AgsMachine
1744 * @format: the format
1745 * @old_format: the old format
1746 *
1747 * Notify about format changed.
1748 *
1749 * Since: 3.0.0
1750 */
1751 void
ags_machine_format_changed(AgsMachine * machine,guint format,guint old_format)1752 ags_machine_format_changed(AgsMachine *machine,
1753 guint format, guint old_format)
1754 {
1755 g_return_if_fail(AGS_IS_MACHINE(machine));
1756
1757 g_object_ref((GObject *) machine);
1758 g_signal_emit(G_OBJECT(machine),
1759 machine_signals[FORMAT_CHANGED], 0,
1760 format,
1761 old_format);
1762 g_object_unref((GObject *) machine);
1763 }
1764
1765 void
ags_machine_real_resize_audio_channels(AgsMachine * machine,guint audio_channels,guint audio_channels_old)1766 ags_machine_real_resize_audio_channels(AgsMachine *machine,
1767 guint audio_channels, guint audio_channels_old)
1768 {
1769 AgsAudio *audio;
1770 AgsChannel *start_channel;
1771 AgsChannel *channel;
1772
1773 GList *list_output_pad, *list_output_pad_start;
1774 GList *list_input_pad, *list_input_pad_start;
1775 GList *list_output_pad_next, *list_output_pad_next_start;
1776 GList *list_input_pad_next, *list_input_pad_next_start;
1777
1778 guint i;
1779
1780 audio = machine->audio;
1781
1782 list_output_pad =
1783 list_output_pad_start = NULL;
1784
1785 list_input_pad =
1786 list_input_pad_start = NULL;
1787
1788 if(audio_channels > audio_channels_old){
1789 /* grow lines */
1790 AgsPad *pad;
1791
1792 guint input_pads, output_pads;
1793 guint audio_audio_channels;
1794 guint audio_input_pads, audio_output_pads;
1795
1796 output_pads = machine->output_pads;
1797 input_pads = machine->input_pads;
1798
1799 if(machine->input != NULL){
1800 list_input_pad_start =
1801 list_input_pad = g_list_reverse(gtk_container_get_children((GtkContainer *) machine->input));
1802 }
1803
1804 if(machine->output != NULL){
1805 list_output_pad_start =
1806 list_output_pad = g_list_reverse(gtk_container_get_children((GtkContainer *) machine->output));
1807 }
1808
1809 /* AgsInput */
1810 if(machine->input != NULL){
1811 /* get input */
1812 start_channel = NULL;
1813
1814 audio_audio_channels = 0;
1815
1816 audio_input_pads = 0;
1817 audio_output_pads = 0;
1818
1819 g_object_get(audio,
1820 "input", &start_channel,
1821 "audio-channels", &audio_audio_channels,
1822 "input-pads", &audio_input_pads,
1823 "output-pads", &audio_output_pads,
1824 NULL);
1825
1826 for(i = 0; i < input_pads; i++){
1827 /* create AgsPad's if necessary or resize */
1828 if(audio_audio_channels > 0 &&
1829 i < audio_input_pads){
1830 channel = ags_channel_nth(start_channel, i * audio_audio_channels);
1831 }else{
1832 channel = NULL;
1833 }
1834
1835 if(audio_channels_old == 0){
1836 pad = g_object_new(machine->input_pad_type,
1837 "channel", channel,
1838 NULL);
1839 gtk_box_pack_start((GtkBox *) machine->input,
1840 (GtkWidget *) pad,
1841 FALSE, FALSE,
1842 0);
1843
1844 ags_pad_resize_lines((AgsPad *) pad, machine->input_line_type,
1845 audio_channels, 0);
1846 }else{
1847 pad = AGS_PAD(list_input_pad->data);
1848
1849 ags_pad_resize_lines((AgsPad *) pad, machine->input_line_type,
1850 audio_channels, audio_channels_old);
1851 }
1852
1853 if(channel != NULL){
1854 g_object_unref(channel);
1855 }
1856
1857 /* iterate */
1858 if(audio_channels_old != 0){
1859 list_input_pad = list_input_pad->next;
1860 }
1861 }
1862
1863 if(start_channel != NULL){
1864 g_object_unref(start_channel);
1865 }
1866 }
1867
1868 /* AgsOutput */
1869 if(machine->output != NULL){
1870 /* get output */
1871 start_channel = NULL;
1872
1873 g_object_get(audio,
1874 "output", &start_channel,
1875 NULL);
1876
1877 for(i = 0; i < output_pads; i++){
1878 /* create AgsPad's if necessary or resize */
1879 if(audio_audio_channels > 0 &&
1880 i < audio_output_pads){
1881 channel = ags_channel_nth(start_channel, i * audio_audio_channels);
1882 }else{
1883 channel = NULL;
1884 }
1885
1886 if(audio_channels_old == 0){
1887 pad = g_object_new(machine->output_pad_type,
1888 "channel", channel,
1889 NULL);
1890 gtk_box_pack_start((GtkBox *) machine->output,
1891 (GtkWidget *) pad,
1892 FALSE, FALSE,
1893 0);
1894 ags_pad_resize_lines((AgsPad *) pad, machine->output_line_type,
1895 audio_channels, 0);
1896 }else{
1897 pad = AGS_PAD(list_output_pad->data);
1898
1899 ags_pad_resize_lines((AgsPad *) pad, machine->output_line_type,
1900 audio_channels, audio_channels_old);
1901 }
1902
1903 if(channel != NULL){
1904 g_object_unref(channel);
1905 }
1906
1907 /* iterate */
1908 if(audio_channels_old != 0){
1909 list_output_pad = list_output_pad->next;
1910 }
1911 }
1912
1913 if(start_channel != NULL){
1914 g_object_unref(start_channel);
1915 }
1916 }
1917
1918 /* show all */
1919 if(audio_channels_old == 0){
1920 if(machine->input != NULL){
1921 list_input_pad_start =
1922 list_input_pad = g_list_reverse(gtk_container_get_children((GtkContainer *) machine->input));
1923 }
1924
1925 if(machine->output != NULL){
1926 list_output_pad_start =
1927 list_output_pad = g_list_reverse(gtk_container_get_children((GtkContainer *) machine->output));
1928 }
1929 }
1930
1931 if(gtk_widget_get_visible((GtkWidget *) machine)){
1932 if(audio_channels_old == 0){
1933 /* AgsInput */
1934 if(machine->input != NULL){
1935 list_input_pad = list_input_pad_start;
1936
1937 while(list_input_pad != NULL){
1938 gtk_widget_show_all(GTK_WIDGET(list_input_pad->data));
1939
1940 list_input_pad = list_input_pad->next;
1941 }
1942 }
1943
1944 /* AgsOutput */
1945 if(machine->output != NULL){
1946 list_output_pad = list_output_pad_start;
1947
1948 while(list_input_pad != NULL){
1949 gtk_widget_show_all(GTK_WIDGET(list_input_pad->data));
1950
1951 list_input_pad = list_input_pad->next;
1952 }
1953 }
1954 }else{
1955 if(machine->input != NULL){
1956 GList *start_list_input_line, *list_input_line;
1957
1958 list_input_pad = list_input_pad_start;
1959
1960 while(list_input_pad != NULL){
1961 start_list_input_line = g_list_reverse(gtk_container_get_children(GTK_CONTAINER(AGS_PAD(list_input_pad->data)->expander_set)));
1962
1963 list_input_line = g_list_nth(start_list_input_line,
1964 audio_channels_old);
1965
1966 while(list_input_line != NULL){
1967 gtk_widget_show_all(GTK_WIDGET(list_input_line->data));
1968
1969 list_input_line = list_input_line->next;
1970 }
1971
1972 g_list_free(start_list_input_line);
1973
1974 list_input_pad = list_input_pad->next;
1975 }
1976 }
1977
1978 /* AgsOutput */
1979 if(machine->output != NULL){
1980 GList *start_list_output_line, *list_output_line;
1981
1982 list_output_pad = list_output_pad_start;
1983
1984 while(list_output_pad != NULL){
1985 start_list_output_line = g_list_reverse(gtk_container_get_children(GTK_CONTAINER(AGS_PAD(list_output_pad->data)->expander_set)));
1986
1987 list_output_line = g_list_nth(start_list_output_line,
1988 audio_channels_old);
1989
1990 while(list_output_line != NULL){
1991 gtk_widget_show_all(GTK_WIDGET(list_output_line->data));
1992
1993 list_output_line = list_output_line->next;
1994 }
1995
1996 g_list_free(start_list_output_line);
1997
1998 list_output_pad = list_output_pad->next;
1999 }
2000 }
2001 }
2002 }
2003
2004 g_list_free(list_input_pad_start);
2005 g_list_free(list_output_pad_start);
2006 }else if(audio_channels < audio_channels_old){
2007 /* shrink lines */
2008 if(machine->output != NULL){
2009 list_output_pad_start =
2010 list_output_pad = gtk_container_get_children((GtkContainer *) machine->output);
2011 }
2012
2013 if(machine->input != NULL){
2014 list_input_pad_start =
2015 list_input_pad = gtk_container_get_children((GtkContainer *) machine->input);
2016 }
2017
2018 if(audio_channels == 0){
2019 /* AgsInput */
2020 if(machine->input != NULL){
2021 while(list_input_pad != NULL){
2022 list_input_pad_next = list_input_pad->next;
2023
2024 gtk_widget_destroy(GTK_WIDGET(list_input_pad->data));
2025
2026 list_input_pad = list_input_pad_next;
2027 }
2028 }
2029
2030 /* AgsOutput */
2031 if(machine->output != NULL){
2032 while(list_output_pad != NULL){
2033 list_output_pad_next = list_output_pad->next;
2034
2035 gtk_widget_destroy(GTK_WIDGET(list_output_pad->data));
2036
2037 list_output_pad = list_output_pad_next;
2038 }
2039 }
2040 }else{
2041 /* AgsInput */
2042 if(machine->input != NULL){
2043 for(i = 0; list_input_pad != NULL; i++){
2044 ags_pad_resize_lines(AGS_PAD(list_input_pad->data), machine->input_pad_type,
2045 audio_channels, audio_channels_old);
2046
2047 list_input_pad = list_input_pad->next;
2048 }
2049 }
2050
2051 /* AgsOutput */
2052 if(machine->output != NULL){
2053 for(i = 0; list_output_pad != NULL; i++){
2054 ags_pad_resize_lines(AGS_PAD(list_output_pad->data), machine->output_pad_type,
2055 audio_channels, audio_channels_old);
2056
2057 list_output_pad = list_output_pad->next;
2058 }
2059 }
2060 }
2061
2062 g_list_free(list_output_pad_start);
2063 g_list_free(list_input_pad_start);
2064 }
2065
2066 machine->audio_channels = audio_channels;
2067 }
2068
2069 /**
2070 * ags_machine_resize_audio_channels:
2071 * @machine: the #AgsMachine
2072 * @new_size: new allocation
2073 * @old_size: old allocation
2074 *
2075 * Resize audio channel allocation.
2076 *
2077 * Since: 3.0.0
2078 */
2079 void
ags_machine_resize_audio_channels(AgsMachine * machine,guint new_size,guint old_size)2080 ags_machine_resize_audio_channels(AgsMachine *machine,
2081 guint new_size,
2082 guint old_size)
2083 {
2084 g_return_if_fail(AGS_IS_MACHINE(machine));
2085
2086 g_object_ref((GObject *) machine);
2087 g_signal_emit(G_OBJECT(machine),
2088 machine_signals[RESIZE_AUDIO_CHANNELS], 0,
2089 new_size,
2090 old_size);
2091 g_object_unref((GObject *) machine);
2092 }
2093
2094 void
ags_machine_real_resize_pads(AgsMachine * machine,GType channel_type,guint pads,guint pads_old)2095 ags_machine_real_resize_pads(AgsMachine *machine, GType channel_type,
2096 guint pads, guint pads_old)
2097 {
2098 AgsPad *pad;
2099
2100 AgsAudio *audio;
2101 AgsChannel *start_input, *start_output;
2102 AgsChannel *input, *output;
2103
2104 GList *list_pad_start, *list_pad;
2105
2106 guint audio_channels;
2107 guint audio_audio_channels;
2108 guint audio_input_pads, audio_output_pads;
2109 guint i;
2110
2111 audio = machine->audio;
2112
2113 audio_channels = machine->audio_channels;
2114
2115 if(pads_old < pads){
2116 start_output = NULL;
2117 start_input = NULL;
2118
2119 audio_audio_channels = 0;
2120
2121 audio_input_pads = 0;
2122 audio_output_pads = 0;
2123
2124 g_object_get(audio,
2125 "output", &start_output,
2126 "input", &start_input,
2127 "audio-channels", &audio_audio_channels,
2128 "input-pads", &audio_input_pads,
2129 "output-pads", &audio_output_pads,
2130 NULL);
2131
2132 /* grow input */
2133 if(machine->input != NULL){
2134 if(g_type_is_a(channel_type, AGS_TYPE_INPUT)){
2135 for(i = pads_old; i < pads; i++){
2136 /* instantiate pad */
2137 if(audio_audio_channels > 0 &&
2138 i < audio_input_pads){
2139 input = ags_channel_nth(start_input, i * audio_audio_channels);
2140 }else{
2141 input = NULL;
2142 }
2143
2144 pad = g_object_new(machine->input_pad_type,
2145 "channel", input,
2146 NULL);
2147 gtk_box_pack_start((GtkBox *) machine->input,
2148 (GtkWidget *) pad, FALSE, FALSE, 0);
2149
2150 /* resize lines */
2151 ags_pad_resize_lines((AgsPad *) pad, machine->input_line_type,
2152 audio_channels, 0);
2153
2154 if(input != NULL){
2155 g_object_unref(input);
2156 }
2157 }
2158
2159 /* show all */
2160 list_pad_start =
2161 list_pad = gtk_container_get_children(GTK_CONTAINER(machine->input));
2162 list_pad = g_list_nth(list_pad,
2163 pads_old);
2164
2165 while(list_pad != NULL){
2166 gtk_widget_show_all(GTK_WIDGET(list_pad->data));
2167
2168 list_pad = list_pad->next;
2169 }
2170
2171 g_list_free(list_pad_start);
2172 }
2173 }
2174
2175 if(start_input != NULL){
2176 g_object_unref(start_input);
2177 }
2178
2179 /* grow output */
2180 if(machine->output != NULL){
2181 if(g_type_is_a(channel_type, AGS_TYPE_OUTPUT)){
2182 for(i = pads_old; i < pads; i++){
2183 /* instantiate pad */
2184 if(audio_audio_channels > 0 &&
2185 i < audio_output_pads){
2186 output = ags_channel_nth(start_output, i * audio_audio_channels);
2187 }else{
2188 output = NULL;
2189 }
2190
2191 pad = g_object_new(machine->output_pad_type,
2192 "channel", output,
2193 NULL);
2194 gtk_box_pack_start((GtkBox *) machine->output, (GtkWidget *) pad, FALSE, FALSE, 0);
2195
2196 /* resize lines */
2197 ags_pad_resize_lines((AgsPad *) pad, machine->output_line_type,
2198 audio_channels, 0);
2199
2200 if(output != NULL){
2201 g_object_unref(output);
2202 }
2203 }
2204
2205 /* show all */
2206 list_pad_start =
2207 list_pad = gtk_container_get_children(GTK_CONTAINER(machine->output));
2208 list_pad = g_list_nth(list_pad,
2209 pads_old);
2210
2211 while(list_pad != NULL){
2212 gtk_widget_show_all(GTK_WIDGET(list_pad->data));
2213
2214 list_pad = list_pad->next;
2215 }
2216
2217 g_list_free(list_pad_start);
2218 }
2219 }
2220
2221 if(start_output != NULL){
2222 g_object_unref(start_output);
2223 }
2224 }else if(pads_old > pads){
2225 GList *list, *list_start;
2226
2227 /* input - destroy AgsPad's */
2228 if(channel_type == AGS_TYPE_INPUT &&
2229 machine->input != NULL){
2230 for(i = 0; i < pads_old - pads; i++){
2231 list_start = gtk_container_get_children(GTK_CONTAINER(machine->input));
2232 list = g_list_nth(list_start, pads);
2233
2234 if(list != NULL){
2235 gtk_widget_destroy(GTK_WIDGET(list->data));
2236 }
2237
2238 g_list_free(list_start);
2239 }
2240 }
2241
2242 /* output - destroy AgsPad's */
2243 if(channel_type == AGS_TYPE_OUTPUT &&
2244 machine->output != NULL){
2245 for(i = 0; i < pads_old - pads; i++){
2246 list_start = gtk_container_get_children(GTK_CONTAINER(machine->output));
2247 list = g_list_nth(list_start, pads);
2248
2249 if(list != NULL){
2250 gtk_widget_destroy(GTK_WIDGET(list->data));
2251 }
2252
2253 g_list_free(list_start);
2254 }
2255 }
2256 }
2257
2258 if(g_type_is_a(channel_type, AGS_TYPE_OUTPUT)){
2259 machine->output_pads = pads;
2260 }else{
2261 machine->input_pads = pads;
2262 }
2263 }
2264
2265 /**
2266 * ags_machine_resize_pads:
2267 * @machine: the #AgsMachine
2268 * @channel_type: the channel #GType
2269 * @new_size: new allocation
2270 * @old_size: old allocation
2271 *
2272 * Resize pad allocation.
2273 *
2274 * Since: 3.0.0
2275 */
2276 void
ags_machine_resize_pads(AgsMachine * machine,GType channel_type,guint new_size,guint old_size)2277 ags_machine_resize_pads(AgsMachine *machine,
2278 GType channel_type,
2279 guint new_size,
2280 guint old_size)
2281 {
2282 g_return_if_fail(AGS_IS_MACHINE(machine));
2283
2284 g_object_ref((GObject *) machine);
2285 g_signal_emit(G_OBJECT(machine),
2286 machine_signals[RESIZE_PADS], 0,
2287 channel_type,
2288 new_size,
2289 old_size);
2290 g_object_unref((GObject *) machine);
2291 }
2292
2293 void
ags_machine_real_map_recall(AgsMachine * machine)2294 ags_machine_real_map_recall(AgsMachine *machine)
2295 {
2296 if((AGS_MACHINE_MAPPED_RECALL & (machine->flags)) != 0){
2297 return;
2298 }
2299
2300 machine->flags |= AGS_MACHINE_MAPPED_RECALL;
2301
2302 ags_machine_find_port(machine);
2303 }
2304
2305 /**
2306 * ags_machine_map_recall:
2307 * @machine: the #AgsMachine to add its default recall.
2308 *
2309 * You may want the @machine to add its default recall.
2310 *
2311 * Since: 3.0.0
2312 */
2313 void
ags_machine_map_recall(AgsMachine * machine)2314 ags_machine_map_recall(AgsMachine *machine)
2315 {
2316 g_return_if_fail(AGS_IS_MACHINE(machine));
2317
2318 g_object_ref((GObject *) machine);
2319 g_signal_emit((GObject *) machine,
2320 machine_signals[MAP_RECALL], 0);
2321 g_object_unref((GObject *) machine);
2322 }
2323
2324 GList*
ags_machine_real_find_port(AgsMachine * machine)2325 ags_machine_real_find_port(AgsMachine *machine)
2326 {
2327 GList *pad, *pad_start;
2328
2329 GList *port, *tmp_port;
2330
2331 port = NULL;
2332
2333 /* find output ports */
2334 if(machine->output != NULL){
2335 pad_start =
2336 pad = gtk_container_get_children(machine->output);
2337
2338 while(pad != NULL){
2339 tmp_port = ags_pad_find_port(AGS_PAD(pad->data));
2340
2341 if(port != NULL){
2342 port = g_list_concat(port,
2343 tmp_port);
2344 }else{
2345 port = tmp_port;
2346 }
2347
2348 pad = pad->next;
2349 }
2350
2351 g_list_free(pad_start);
2352 }
2353
2354 /* find input ports */
2355 if(machine->input != NULL){
2356 pad_start =
2357 pad = gtk_container_get_children(machine->input);
2358
2359 while(pad != NULL){
2360 tmp_port = ags_pad_find_port(AGS_PAD(pad->data));
2361
2362 if(port != NULL){
2363 port = g_list_concat(port,
2364 tmp_port);
2365 }else{
2366 port = tmp_port;
2367 }
2368
2369 pad = pad->next;
2370 }
2371
2372 g_list_free(pad_start);
2373 }
2374
2375 /* find bridge ports */
2376 if(machine->bridge != NULL){
2377 tmp_port = ags_effect_bridge_find_port((AgsEffectBridge *) machine->bridge);
2378
2379 if(port != NULL){
2380 port = g_list_concat(port,
2381 tmp_port);
2382 }else{
2383 port = tmp_port;
2384 }
2385 }
2386
2387 return(port);
2388 }
2389
2390 /**
2391 * ags_machine_find_port:
2392 * @machine: the #AgsMachine
2393 * Returns: an #GList containing all related #AgsPort
2394 *
2395 * Lookup ports of associated recalls.
2396 *
2397 * Since: 3.0.0
2398 */
2399 GList*
ags_machine_find_port(AgsMachine * machine)2400 ags_machine_find_port(AgsMachine *machine)
2401 {
2402 GList *list;
2403
2404 list = NULL;
2405 g_return_val_if_fail(AGS_IS_MACHINE(machine),
2406 NULL);
2407
2408 g_object_ref((GObject *) machine);
2409 g_signal_emit((GObject *) machine,
2410 machine_signals[FIND_PORT], 0,
2411 &list);
2412 g_object_unref((GObject *) machine);
2413
2414 return(list);
2415 }
2416
2417 /**
2418 * ags_machine_stop:
2419 * @machine: the #AgsMachine
2420 * @recall_id: the #GList-struct containing #AgsRecallID
2421 * @sound_scope: the sound scope
2422 *
2423 * Notify about to stop playback of @recall_id.
2424 *
2425 * Since: 3.0.0
2426 */
2427 void
ags_machine_stop(AgsMachine * machine,GList * recall_id,gint sound_scope)2428 ags_machine_stop(AgsMachine *machine, GList *recall_id, gint sound_scope)
2429 {
2430 g_return_if_fail(AGS_IS_MACHINE(machine));
2431
2432 g_object_ref((GObject *) machine);
2433 g_signal_emit((GObject *) machine,
2434 machine_signals[STOP], 0,
2435 recall_id, sound_scope);
2436 g_object_unref((GObject *) machine);
2437 }
2438
2439 /**
2440 * ags_machine_find_by_name:
2441 * @list: a #GList of #AgsMachine
2442 * @name: the name of machine
2443 *
2444 * Find the specified by @name machine.
2445 *
2446 * Returns: the matching #AgsMachine, or %NULL
2447 *
2448 * Since: 3.0.0
2449 */
2450 AgsMachine*
ags_machine_find_by_name(GList * list,char * name)2451 ags_machine_find_by_name(GList *list, char *name)
2452 {
2453 while(list != NULL){
2454 if(!g_strcmp0(AGS_MACHINE(list->data)->machine_name, name))
2455 return((AgsMachine *) list->data);
2456
2457 list = list->next;
2458 }
2459
2460 return(NULL);
2461 }
2462
2463 /**
2464 * ags_machine_playback_set_active:
2465 * @machine: the #AgsMachine
2466 * @playback: the #AgsPlayback
2467 * @is_active: if %TRUE playback is started, otherwise stopped
2468 *
2469 * Start/stop @playback of @machine.
2470 *
2471 * Since: 3.0.0
2472 */
2473 void
ags_machine_playback_set_active(AgsMachine * machine,AgsPlayback * playback,gboolean is_active)2474 ags_machine_playback_set_active(AgsMachine *machine,
2475 AgsPlayback *playback,
2476 gboolean is_active)
2477 {
2478 AgsChannel *channel;
2479 AgsNote *play_note;
2480
2481 AgsStartSoundcard *start_soundcard;
2482 AgsStartChannel *start_channel;
2483 AgsCancelChannel *cancel_channel;
2484 AgsResetNote *reset_note;
2485
2486 AgsApplicationContext *application_context;
2487
2488 GList *start_task;
2489
2490 if(!AGS_IS_MACHINE(machine) ||
2491 !AGS_IS_PLAYBACK(playback)){
2492 return;
2493 }
2494
2495 application_context = ags_application_context_get_instance();
2496
2497 start_task = NULL;
2498
2499 if(is_active){
2500 if(g_list_find(machine->active_playback, playback) != NULL){
2501 return;
2502 }
2503
2504 machine->active_playback = g_list_prepend(machine->active_playback,
2505 playback);
2506 g_object_ref(playback);
2507
2508 /* start playback of channel */
2509 g_object_get(playback,
2510 "channel", &channel,
2511 NULL);
2512
2513 start_channel = ags_start_channel_new(channel,
2514 AGS_SOUND_SCOPE_PLAYBACK);
2515 g_signal_connect_after(G_OBJECT(start_channel), "launch",
2516 G_CALLBACK(ags_machine_active_playback_start_channel_launch_callback), playback);
2517 start_task = g_list_prepend(start_task,
2518 start_channel);
2519
2520 /* start soundcard */
2521 start_soundcard = ags_start_soundcard_new(application_context);
2522 start_task = g_list_prepend(start_task,
2523 start_soundcard);
2524
2525 /* launch task */
2526 start_task = g_list_reverse(start_task);
2527
2528 ags_ui_provider_schedule_task_all(AGS_UI_PROVIDER(application_context),
2529 start_task);
2530
2531 /* feed note */
2532 g_object_get(playback,
2533 "play-note", &play_note,
2534 NULL);
2535
2536 if(ags_note_test_flags(play_note, AGS_NOTE_FEED)){
2537 reset_note = ags_reset_note_get_instance();
2538 ags_reset_note_add(reset_note,
2539 play_note);
2540 }
2541
2542 /* unref */
2543 g_object_unref(channel);
2544
2545 g_object_unref(play_note);
2546 }else{
2547 if(g_list_find(machine->active_playback, playback) == NULL){
2548 return;
2549 }
2550
2551 machine->active_playback = g_list_remove(machine->active_playback,
2552 playback);
2553 g_object_unref(playback);
2554
2555 /* cancel playback of channel */
2556 g_object_get(playback,
2557 "channel", &channel,
2558 NULL);
2559
2560 cancel_channel = ags_cancel_channel_new(channel,
2561 AGS_SOUND_SCOPE_PLAYBACK);
2562 start_task = g_list_prepend(start_task,
2563 cancel_channel);
2564
2565 /* launch task */
2566 start_task = g_list_reverse(start_task);
2567
2568 ags_ui_provider_schedule_task_all(AGS_UI_PROVIDER(application_context),
2569 start_task);
2570
2571 /* feed note */
2572 g_object_get(playback,
2573 "play-note", &play_note,
2574 NULL);
2575
2576 if(ags_note_test_flags(play_note, AGS_NOTE_FEED)){
2577 reset_note = ags_reset_note_get_instance();
2578 ags_reset_note_remove(reset_note,
2579 play_note);
2580 }
2581
2582 /* unref */
2583 g_object_unref(channel);
2584
2585 g_object_unref(play_note);
2586 }
2587 }
2588
2589 /**
2590 * ags_machine_set_run:
2591 * @machine: the #AgsMachine
2592 * @run: if %TRUE playback is started, otherwise stopped
2593 *
2594 * Start/stop playback of @machine.
2595 *
2596 * Since: 3.0.0
2597 */
2598 void
ags_machine_set_run(AgsMachine * machine,gboolean run)2599 ags_machine_set_run(AgsMachine *machine,
2600 gboolean run)
2601 {
2602 ags_machine_set_run_extended(machine,
2603 run,
2604 TRUE, TRUE, TRUE, TRUE);
2605 }
2606
2607 /**
2608 * ags_machine_set_run_extended:
2609 * @machine: the #AgsMachine
2610 * @run: if %TRUE playback is started, otherwise stopped
2611 * @sequencer: if doing sequencer
2612 * @notation: if doing notation
2613 * @wave: if doing wave
2614 * @midi: if doing midi
2615 *
2616 * Start/stop playback of @machine.
2617 *
2618 * Since: 3.0.0
2619 */
2620 void
ags_machine_set_run_extended(AgsMachine * machine,gboolean run,gboolean sequencer,gboolean notation,gboolean wave,gboolean midi)2621 ags_machine_set_run_extended(AgsMachine *machine,
2622 gboolean run,
2623 gboolean sequencer, gboolean notation, gboolean wave, gboolean midi)
2624 {
2625 AgsApplicationContext *application_context;
2626
2627 GList *start_list;
2628
2629 gboolean no_soundcard;
2630
2631 if(!AGS_IS_MACHINE(machine)){
2632 return;
2633 }
2634
2635 application_context = ags_application_context_get_instance();
2636
2637 no_soundcard = FALSE;
2638
2639 if((start_list = ags_sound_provider_get_soundcard(AGS_SOUND_PROVIDER(application_context))) == NULL){
2640 no_soundcard = TRUE;
2641 }
2642
2643 g_list_free_full(start_list,
2644 g_object_unref);
2645
2646 if(no_soundcard){
2647 g_message("No soundcard available");
2648
2649 return;
2650 }
2651
2652 if(run){
2653 AgsStartAudio *start_audio;
2654 AgsStartSoundcard *start_soundcard;
2655 AgsStartSequencer *start_sequencer;
2656
2657 GList *list;
2658
2659 list = NULL;
2660
2661 if(sequencer){
2662 /* create start task */
2663 start_audio = ags_start_audio_new(machine->audio,
2664 AGS_SOUND_SCOPE_SEQUENCER);
2665 list = g_list_prepend(list,
2666 start_audio);
2667 }
2668
2669 if(notation){
2670 /* create start task */
2671 start_audio = ags_start_audio_new(machine->audio,
2672 AGS_SOUND_SCOPE_NOTATION);
2673 list = g_list_prepend(list,
2674 start_audio);
2675 }
2676
2677 if(wave){
2678 /* create start task */
2679 start_audio = ags_start_audio_new(machine->audio,
2680 AGS_SOUND_SCOPE_WAVE);
2681 list = g_list_prepend(list,
2682 start_audio);
2683 }
2684
2685 if(midi){
2686 /* create start task */
2687 start_audio = ags_start_audio_new(machine->audio,
2688 AGS_SOUND_SCOPE_MIDI);
2689 list = g_list_prepend(list,
2690 start_audio);
2691 }
2692
2693 /* create start task */
2694 if(list != NULL){
2695 /* start soundcard */
2696 start_soundcard = ags_start_soundcard_new(application_context);
2697 list = g_list_prepend(list,
2698 start_soundcard);
2699
2700 /* start sequencer */
2701 start_sequencer = ags_start_sequencer_new(application_context);
2702 list = g_list_prepend(list,
2703 start_sequencer);
2704
2705 /* append AgsStartSoundcard and AgsStartSequencer */
2706 list = g_list_reverse(list);
2707
2708 ags_ui_provider_schedule_task_all(AGS_UI_PROVIDER(application_context),
2709 list);
2710 }
2711 }else{
2712 AgsCancelAudio *cancel_audio;
2713
2714 if(sequencer){
2715 /* create cancel task */
2716 cancel_audio = ags_cancel_audio_new(machine->audio,
2717 AGS_SOUND_SCOPE_SEQUENCER);
2718
2719 /* append AgsCancelAudio */
2720 ags_ui_provider_schedule_task(AGS_UI_PROVIDER(application_context),
2721 (AgsTask *) cancel_audio);
2722 }
2723
2724 if(notation){
2725 /* create cancel task */
2726 cancel_audio = ags_cancel_audio_new(machine->audio,
2727 AGS_SOUND_SCOPE_NOTATION);
2728
2729 /* append AgsCancelAudio */
2730 ags_ui_provider_schedule_task(AGS_UI_PROVIDER(application_context),
2731 (AgsTask *) cancel_audio);
2732 }
2733
2734 if(wave){
2735 /* create cancel task */
2736 cancel_audio = ags_cancel_audio_new(machine->audio,
2737 AGS_SOUND_SCOPE_WAVE);
2738
2739 /* append AgsCancelAudio */
2740 ags_ui_provider_schedule_task(AGS_UI_PROVIDER(application_context),
2741 (AgsTask *) cancel_audio);
2742 }
2743
2744 if(midi){
2745 /* create cancel task */
2746 cancel_audio = ags_cancel_audio_new(machine->audio,
2747 AGS_SOUND_SCOPE_MIDI);
2748
2749 /* append AgsCancelAudio */
2750 ags_ui_provider_schedule_task(AGS_UI_PROVIDER(application_context),
2751 (AgsTask *) cancel_audio);
2752 }
2753 }
2754 }
2755
2756 /**
2757 * ags_machine_get_possible_audio_output_connections:
2758 * @machine: the #AgsMachine
2759 *
2760 * Find audio output connections suitable for @machine.
2761 *
2762 * Returns: a #GtkListStore containing one column with a string representing
2763 * machines by its type and name.
2764 *
2765 * Since: 3.0.0
2766 */
2767 GtkListStore*
ags_machine_get_possible_audio_output_connections(AgsMachine * machine)2768 ags_machine_get_possible_audio_output_connections(AgsMachine *machine)
2769 {
2770 AgsApplicationContext *application_context;
2771
2772 GtkListStore *model;
2773
2774 GList *start_list, *list;
2775 GtkTreeIter iter;
2776
2777 application_context = ags_application_context_get_instance();
2778
2779 model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);
2780
2781 gtk_list_store_append(model, &iter);
2782 gtk_list_store_set(model, &iter,
2783 0, "NULL",
2784 1, NULL,
2785 -1);
2786
2787 if(application_context != NULL){
2788 list =
2789 start_list = ags_sound_provider_get_soundcard(AGS_SOUND_PROVIDER(application_context));
2790
2791 while(list != NULL){
2792 guint soundcard_capability;
2793
2794 soundcard_capability = ags_soundcard_get_capability(AGS_SOUNDCARD(list->data));
2795
2796 if((AGS_SOUNDCARD_CAPABILITY_PLAYBACK & (soundcard_capability)) != 0 ||
2797 (AGS_SOUNDCARD_CAPABILITY_DUPLEX & (soundcard_capability)) != 0){
2798 gchar *tmp_device;
2799
2800 tmp_device = ags_soundcard_get_device(AGS_SOUNDCARD(list->data));
2801
2802 gtk_list_store_append(model, &iter);
2803 gtk_list_store_set(model, &iter,
2804 0, g_strdup_printf("%s: %s",
2805 G_OBJECT_TYPE_NAME(G_OBJECT(list->data)),
2806 (tmp_device != NULL ? tmp_device: "(null)")),
2807 1, list->data,
2808 -1);
2809
2810 g_free(tmp_device);
2811 }
2812
2813 list = list->next;
2814 }
2815
2816 g_list_free_full(start_list,
2817 g_object_unref);
2818 }
2819
2820 return(model);
2821 }
2822
2823 /**
2824 * ags_machine_get_possible_audio_input_connections:
2825 * @machine: the #AgsMachine
2826 *
2827 * Find audio input connections suitable for @machine.
2828 *
2829 * Returns: a #GtkListStore containing one column with a string representing
2830 * machines by its type and name.
2831 *
2832 * Since: 3.0.0
2833 */
2834 GtkListStore*
ags_machine_get_possible_audio_input_connections(AgsMachine * machine)2835 ags_machine_get_possible_audio_input_connections(AgsMachine *machine)
2836 {
2837 AgsApplicationContext *application_context;
2838
2839 GtkListStore *model;
2840
2841 GList *start_list, *list;
2842 GtkTreeIter iter;
2843
2844 application_context = ags_application_context_get_instance();
2845
2846 model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);
2847
2848 gtk_list_store_append(model, &iter);
2849 gtk_list_store_set(model, &iter,
2850 0, "NULL",
2851 1, NULL,
2852 -1);
2853
2854 if(application_context != NULL){
2855 list =
2856 start_list = ags_sound_provider_get_soundcard(AGS_SOUND_PROVIDER(application_context));
2857
2858 while(list != NULL){
2859 guint soundcard_capability;
2860
2861 soundcard_capability = ags_soundcard_get_capability(AGS_SOUNDCARD(list->data));
2862
2863 if((AGS_SOUNDCARD_CAPABILITY_CAPTURE & (soundcard_capability)) != 0 ||
2864 (AGS_SOUNDCARD_CAPABILITY_DUPLEX & (soundcard_capability)) != 0){
2865 gchar *tmp_device;
2866
2867 tmp_device = ags_soundcard_get_device(AGS_SOUNDCARD(list->data));
2868
2869 gtk_list_store_append(model, &iter);
2870 gtk_list_store_set(model, &iter,
2871 0, g_strdup_printf("%s: %s",
2872 G_OBJECT_TYPE_NAME(G_OBJECT(list->data)),
2873 (tmp_device != NULL ? tmp_device: "(null)")),
2874 1, list->data,
2875 -1);
2876
2877 g_free(tmp_device);
2878 }
2879
2880 list = list->next;
2881 }
2882
2883 g_list_free_full(start_list,
2884 g_object_unref);
2885 }
2886
2887 return(model);
2888 }
2889
2890 /**
2891 * ags_machine_get_possible_links:
2892 * @machine: the #AgsMachine
2893 *
2894 * Find links suitable for @machine.
2895 *
2896 * Returns: a #GtkListStore containing one column with a string representing
2897 * machines by its type and name.
2898 *
2899 * Since: 3.0.0
2900 */
2901 GtkListStore*
ags_machine_get_possible_links(AgsMachine * machine)2902 ags_machine_get_possible_links(AgsMachine *machine)
2903 {
2904 GtkListStore *model;
2905
2906 GList *list;
2907 GtkTreeIter iter;
2908
2909 model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);
2910
2911 gtk_list_store_append(model, &iter);
2912 gtk_list_store_set(model, &iter,
2913 0, "NULL",
2914 1, NULL,
2915 -1);
2916
2917 if(gtk_widget_get_parent(GTK_WIDGET(machine)) != NULL){
2918 list = gtk_container_get_children(GTK_CONTAINER(gtk_widget_get_parent(GTK_WIDGET(machine))));
2919
2920 while(list != NULL){
2921 if(list->data != machine){
2922 gtk_list_store_append(model, &iter);
2923 gtk_list_store_set(model, &iter,
2924 0, g_strdup_printf("%s: %s",
2925 G_OBJECT_TYPE_NAME(G_OBJECT(list->data)),
2926 AGS_MACHINE(list->data)->machine_name),
2927 1, list->data,
2928 -1);
2929 }
2930
2931 list = list->next;
2932 }
2933 }
2934
2935 return(model);
2936 }
2937
2938 /**
2939 * ags_machine_file_chooser_dialog_new:
2940 * @machine: the #AgsMachine
2941 *
2942 * Creates a new machine file chooser dialog in order to
2943 * open audio files.
2944 *
2945 * Returns: a new #GtkFileChooserDialog
2946 *
2947 * Since: 3.0.0
2948 */
2949 GtkFileChooserDialog*
ags_machine_file_chooser_dialog_new(AgsMachine * machine)2950 ags_machine_file_chooser_dialog_new(AgsMachine *machine)
2951 {
2952 GtkFileChooserDialog *file_chooser;
2953 GtkCheckButton *check_button;
2954
2955 file_chooser = (GtkFileChooserDialog *) gtk_file_chooser_dialog_new(i18n("Open audio files"),
2956 (GtkWindow *) gtk_widget_get_toplevel((GtkWidget *) machine),
2957 GTK_FILE_CHOOSER_ACTION_OPEN,
2958 "_OK", GTK_RESPONSE_ACCEPT,
2959 "_Cancel", GTK_RESPONSE_CANCEL,
2960 NULL);
2961 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(file_chooser), TRUE);
2962
2963 check_button = (GtkCheckButton *) gtk_check_button_new_with_label(i18n("open in new channel"));
2964 gtk_toggle_button_set_active((GtkToggleButton *) check_button,
2965 TRUE);
2966 gtk_box_pack_start((GtkBox *) gtk_dialog_get_content_area(GTK_DIALOG(file_chooser)),
2967 (GtkWidget *) check_button,
2968 FALSE, FALSE,
2969 0);
2970 g_object_set_data((GObject *) file_chooser,
2971 "create", (gpointer) check_button);
2972
2973 check_button = (GtkCheckButton *) gtk_check_button_new_with_label(i18n("overwrite existing links"));
2974 gtk_toggle_button_set_active((GtkToggleButton *) check_button,
2975 TRUE);
2976 gtk_box_pack_start((GtkBox *) gtk_dialog_get_content_area(GTK_DIALOG(file_chooser)),
2977 (GtkWidget *) check_button,
2978 FALSE, FALSE,
2979 0);
2980 g_object_set_data((GObject *) file_chooser,
2981 "overwrite", (gpointer) check_button);
2982
2983 return(file_chooser);
2984 }
2985
2986 /**
2987 * ags_machine_open_files:
2988 * @machine: the #AgsMachine
2989 * @filenames: the filenames
2990 * @overwrite_channels: reset channels
2991 * @create_channels: instantiate new channels
2992 *
2993 * Opens audio files and modifies or creates new channels if wished.
2994 *
2995 * Since: 3.0.0
2996 */
2997 void
ags_machine_open_files(AgsMachine * machine,GSList * filenames,gboolean overwrite_channels,gboolean create_channels)2998 ags_machine_open_files(AgsMachine *machine,
2999 GSList *filenames,
3000 gboolean overwrite_channels,
3001 gboolean create_channels)
3002 {
3003 AgsOpenFile *open_file;
3004
3005 AgsApplicationContext *application_context;
3006
3007 application_context = ags_application_context_get_instance();
3008
3009 /* instantiate open file task */
3010 open_file = ags_open_file_new(machine->audio,
3011 filenames,
3012 overwrite_channels,
3013 create_channels);
3014
3015 ags_ui_provider_schedule_task(AGS_UI_PROVIDER(application_context),
3016 (AgsTask *) open_file);
3017 }
3018
3019 xmlNode*
ags_machine_copy_pattern_to_notation(AgsMachine * machine,AgsChannel * start_current,guint input_pads)3020 ags_machine_copy_pattern_to_notation(AgsMachine *machine,
3021 AgsChannel *start_current,
3022 guint input_pads)
3023 {
3024 AgsChannel *current, *next_current;
3025 AgsPattern *pattern;
3026
3027 xmlNode *notation_node, *current_note;
3028
3029 GList *start_list;
3030
3031 gchar *str;
3032
3033 guint audio_channel;
3034 guint x_boundary, y_boundary;
3035 guint bank_0, bank_1, k;
3036
3037 current = start_current;
3038
3039 audio_channel = 0;
3040
3041 if(current != NULL){
3042 g_object_ref(current);
3043
3044 g_object_get(current,
3045 "audio-channel", &audio_channel,
3046 NULL);
3047 }
3048
3049 next_current = NULL;
3050
3051 /* create root node */
3052 notation_node = xmlNewNode(NULL, BAD_CAST "notation");
3053
3054 xmlNewProp(notation_node, BAD_CAST "program", BAD_CAST "ags");
3055 xmlNewProp(notation_node, BAD_CAST "type", BAD_CAST AGS_NOTATION_CLIPBOARD_TYPE);
3056 xmlNewProp(notation_node, BAD_CAST "version", BAD_CAST AGS_NOTATION_CLIPBOARD_VERSION);
3057 xmlNewProp(notation_node, BAD_CAST "format", BAD_CAST AGS_NOTATION_CLIPBOARD_FORMAT);
3058 xmlNewProp(notation_node, BAD_CAST "base_frequency", BAD_CAST "0");
3059
3060 str = g_strdup_printf("%u",
3061 audio_channel);
3062 xmlNewProp(notation_node, BAD_CAST "audio-channel", BAD_CAST str);
3063
3064 g_free(str);
3065
3066 bank_0 = machine->bank_0;
3067 bank_1 = machine->bank_1;
3068
3069 x_boundary = G_MAXUINT;
3070 y_boundary = G_MAXUINT;
3071
3072 while(current != NULL){
3073 guint length;
3074
3075 GRecMutex *pattern_mutex;
3076
3077 g_object_get(current,
3078 "pattern", &start_list,
3079 NULL);
3080
3081 pattern = start_list->data;
3082 g_object_ref(pattern);
3083
3084 g_list_free_full(start_list,
3085 g_object_unref);
3086
3087 /* get pattern mutex */
3088 pattern_mutex = AGS_PATTERN_GET_OBJ_MUTEX(pattern);
3089
3090 /* get length */
3091 g_rec_mutex_lock(pattern_mutex);
3092
3093 length = pattern->dim[2];
3094
3095 g_rec_mutex_unlock(pattern_mutex);
3096
3097 for(k = 0; k < length; k++){
3098 guint current_pad;
3099
3100 g_object_get(current,
3101 "pad", ¤t_pad,
3102 NULL);
3103
3104 if(ags_pattern_get_bit(pattern, bank_0, bank_1, k)){
3105 current_note = xmlNewChild(notation_node, NULL, BAD_CAST "note", NULL);
3106
3107 xmlNewProp(current_note, BAD_CAST "x", BAD_CAST g_strdup_printf("%u", k));
3108 xmlNewProp(current_note, BAD_CAST "x1", BAD_CAST g_strdup_printf("%u", k + 1));
3109
3110 if((AGS_MACHINE_REVERSE_NOTATION & (machine->flags)) != 0){
3111 xmlNewProp(current_note, BAD_CAST "y", BAD_CAST g_strdup_printf("%u", input_pads - current_pad - 1));
3112 }else{
3113 xmlNewProp(current_note, BAD_CAST "y", BAD_CAST g_strdup_printf("%u", current_pad));
3114 }
3115
3116 if(x_boundary > k){
3117 x_boundary = k;
3118 }
3119
3120 if((AGS_MACHINE_REVERSE_NOTATION & (machine->flags)) != 0){
3121 guint tmp;
3122
3123 tmp = input_pads - current_pad - 1;
3124
3125 if(y_boundary > tmp){
3126 y_boundary = tmp;
3127 }
3128 }else{
3129 if(y_boundary > current->pad){
3130 y_boundary = current->pad;
3131 }
3132 }
3133 }
3134 }
3135
3136 g_object_unref(pattern);
3137
3138 /* iterate */
3139 next_current = ags_channel_next(current);
3140
3141 g_object_unref(current);
3142
3143 current = next_current;
3144 }
3145
3146 xmlNewProp(notation_node, BAD_CAST "x_boundary", BAD_CAST g_strdup_printf("%u", x_boundary));
3147 xmlNewProp(notation_node, BAD_CAST "y_boundary", BAD_CAST g_strdup_printf("%u", y_boundary));
3148
3149 return(notation_node);
3150 }
3151
3152 void
ags_machine_copy_pattern(AgsMachine * machine)3153 ags_machine_copy_pattern(AgsMachine *machine)
3154 {
3155 AgsAudio *audio;
3156 AgsChannel *start_channel;
3157 AgsChannel *channel, *next_channel;
3158
3159 xmlDoc *clipboard;
3160 xmlNode *audio_node, *notation_list_node, *notation_node;
3161
3162 xmlChar *buffer;
3163
3164 guint audio_channels;
3165 guint input_pads;
3166 int size;
3167 gint i;
3168
3169 /* create document */
3170 clipboard = xmlNewDoc(BAD_CAST XML_DEFAULT_VERSION);
3171
3172 /* create root node */
3173 audio_node = xmlNewNode(NULL,
3174 BAD_CAST "audio");
3175 xmlDocSetRootElement(clipboard, audio_node);
3176
3177 notation_list_node = xmlNewNode(NULL,
3178 BAD_CAST "notation-list");
3179 xmlAddChild(audio_node,
3180 notation_list_node);
3181
3182 audio = machine->audio;
3183
3184 /* copy to clipboard */
3185 g_object_get(audio,
3186 "audio-channels", &audio_channels,
3187 "input-pads", &input_pads,
3188 "input", &start_channel,
3189 NULL);
3190
3191 channel = start_channel;
3192
3193 if(channel != NULL){
3194 g_object_ref(channel);
3195 }
3196
3197 next_channel = NULL;
3198
3199 for(i = 0; i < audio_channels; i++){
3200 /* do it so */
3201 notation_node = ags_machine_copy_pattern_to_notation(machine,
3202 channel,
3203 input_pads);
3204 xmlAddChild(notation_list_node,
3205 notation_node);
3206
3207 /* iterate */
3208 next_channel = ags_channel_next(channel);
3209
3210 g_object_unref(channel);
3211
3212 channel = next_channel;
3213 }
3214
3215 /* write to clipboard */
3216 xmlDocDumpFormatMemoryEnc(clipboard, &buffer, &size, "UTF-8", TRUE);
3217 gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD),
3218 (gchar *) buffer, size);
3219 gtk_clipboard_store(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD));
3220
3221 xmlFreeDoc(clipboard);
3222
3223 if(start_channel != NULL){
3224 g_object_unref(start_channel);
3225 }
3226
3227 if(next_channel != NULL){
3228 g_object_unref(next_channel);
3229 }
3230 }
3231
3232 /**
3233 * ags_machine_check_message:
3234 * @machine: the #AgsMachine
3235 *
3236 * Check message queue for message envelopes.
3237 *
3238 * Since: 3.0.0
3239 */
3240 void
ags_machine_check_message(AgsMachine * machine)3241 ags_machine_check_message(AgsMachine *machine)
3242 {
3243 AgsMessageDelivery *message_delivery;
3244
3245 GList *start_message_envelope, *message_envelope;
3246 GList *start_active_playback, *active_playback;
3247
3248 if(!AGS_IS_MACHINE(machine)){
3249 return;
3250 }
3251
3252 /* retrieve message */
3253 message_delivery = ags_message_delivery_get_instance();
3254
3255 message_envelope =
3256 start_message_envelope = ags_message_delivery_find_sender(message_delivery,
3257 "libgsequencer",
3258 (GObject *) machine->audio);
3259
3260 while(message_envelope != NULL){
3261 xmlNode *root_node;
3262
3263 root_node = xmlDocGetRootElement(AGS_MESSAGE_ENVELOPE(message_envelope->data)->doc);
3264
3265 if(!xmlStrncmp(root_node->name,
3266 BAD_CAST "ags-command",
3267 12)){
3268 if(!xmlStrncmp(xmlGetProp(root_node,
3269 "method"),
3270 BAD_CAST "AgsAudio::set-samplerate",
3271 25)){
3272 guint samplerate;
3273 gint position;
3274
3275 position = ags_strv_index(AGS_MESSAGE_ENVELOPE(message_envelope->data)->parameter_name,
3276 "samplerate");
3277 samplerate = g_value_get_uint(&(AGS_MESSAGE_ENVELOPE(message_envelope->data)->value[position]));
3278
3279 /* set samplerate */
3280 g_object_set(machine,
3281 "samplerate", samplerate,
3282 NULL);
3283 }else if(!xmlStrncmp(xmlGetProp(root_node,
3284 "method"),
3285 BAD_CAST "AgsAudio::set-buffer-size",
3286 26)){
3287 guint buffer_size;
3288 gint position;
3289
3290 position = ags_strv_index(AGS_MESSAGE_ENVELOPE(message_envelope->data)->parameter_name,
3291 "buffer-size");
3292 buffer_size = g_value_get_uint(&(AGS_MESSAGE_ENVELOPE(message_envelope->data)->value[position]));
3293
3294 /* set buffer size */
3295 g_object_set(machine,
3296 "buffer-size", buffer_size,
3297 NULL);
3298 }else if(!xmlStrncmp(xmlGetProp(root_node,
3299 "method"),
3300 BAD_CAST "AgsAudio::set-format",
3301 21)){
3302 guint format;
3303 gint position;
3304
3305 position = ags_strv_index(AGS_MESSAGE_ENVELOPE(message_envelope->data)->parameter_name,
3306 "format");
3307 format = g_value_get_uint(&(AGS_MESSAGE_ENVELOPE(message_envelope->data)->value[position]));
3308
3309 /* set format */
3310 g_object_set(machine,
3311 "format", format,
3312 NULL);
3313 }else if(!xmlStrncmp(xmlGetProp(root_node,
3314 "method"),
3315 BAD_CAST "AgsAudio::set-audio-channels",
3316 29)){
3317 guint audio_channels, audio_channels_old;
3318 gint position;
3319
3320 position = ags_strv_index(AGS_MESSAGE_ENVELOPE(message_envelope->data)->parameter_name,
3321 "audio-channels");
3322 audio_channels = g_value_get_uint(&(AGS_MESSAGE_ENVELOPE(message_envelope->data)->value[position]));
3323
3324 position = ags_strv_index(AGS_MESSAGE_ENVELOPE(message_envelope->data)->parameter_name,
3325 "audio-channels-old");
3326 audio_channels_old = g_value_get_uint(&(AGS_MESSAGE_ENVELOPE(message_envelope->data)->value[position]));
3327
3328 /* resize audio channels */
3329 ags_machine_resize_audio_channels(machine,
3330 audio_channels, audio_channels_old);
3331 }else if(!xmlStrncmp(xmlGetProp(root_node,
3332 "method"),
3333 BAD_CAST "AgsAudio::set-pads",
3334 19)){
3335 GType channel_type;
3336
3337 guint pads, pads_old;
3338 gint position;
3339
3340 position = ags_strv_index(AGS_MESSAGE_ENVELOPE(message_envelope->data)->parameter_name,
3341 "channel-type");
3342 channel_type = g_value_get_ulong(&(AGS_MESSAGE_ENVELOPE(message_envelope->data)->value[position]));
3343
3344 position = ags_strv_index(AGS_MESSAGE_ENVELOPE(message_envelope->data)->parameter_name,
3345 "pads");
3346 pads = g_value_get_uint(&(AGS_MESSAGE_ENVELOPE(message_envelope->data)->value[position]));
3347
3348 position = ags_strv_index(AGS_MESSAGE_ENVELOPE(message_envelope->data)->parameter_name,
3349 "pads-old");
3350 pads_old = g_value_get_uint(&(AGS_MESSAGE_ENVELOPE(message_envelope->data)->value[position]));
3351
3352 /* resize pads */
3353 ags_machine_resize_pads(machine,
3354 channel_type,
3355 pads, pads_old);
3356 }else if(!xmlStrncmp(xmlGetProp(root_node,
3357 "method"),
3358 BAD_CAST "AgsAudio::stop",
3359 15)){
3360 GList *recall_id;
3361
3362 gint sound_scope;
3363 gint position;
3364
3365 position = ags_strv_index(AGS_MESSAGE_ENVELOPE(message_envelope->data)->parameter_name,
3366 "recall-id");
3367 recall_id = g_value_get_pointer(&(AGS_MESSAGE_ENVELOPE(message_envelope->data)->value[position]));
3368
3369 position = ags_strv_index(AGS_MESSAGE_ENVELOPE(message_envelope->data)->parameter_name,
3370 "sound-scope");
3371 sound_scope = g_value_get_int(&(AGS_MESSAGE_ENVELOPE(message_envelope->data)->value[position]));
3372
3373 /* stop */
3374 ags_machine_stop(machine,
3375 recall_id, sound_scope);
3376 }
3377 }
3378
3379 message_envelope = message_envelope->next;
3380 }
3381
3382 g_list_free_full(start_message_envelope,
3383 (GDestroyNotify) g_object_unref);
3384
3385 /* */
3386 active_playback =
3387 start_active_playback = g_list_copy(machine->active_playback);
3388
3389 while(active_playback != NULL){
3390 AgsChannel *channel;
3391 AgsPlayback *playback;
3392
3393 playback = active_playback->data;
3394 g_object_ref(playback);
3395
3396 g_object_get(playback,
3397 "channel", &channel,
3398 NULL);
3399
3400 message_envelope =
3401 start_message_envelope = ags_message_delivery_find_sender(message_delivery,
3402 "libgsequencer",
3403 (GObject *) channel);
3404
3405 while(message_envelope != NULL){
3406 xmlNode *root_node;
3407
3408 root_node = xmlDocGetRootElement(AGS_MESSAGE_ENVELOPE(message_envelope->data)->doc);
3409
3410 if(!xmlStrncmp(root_node->name,
3411 BAD_CAST "ags-command",
3412 12)){
3413 if(!xmlStrncmp(xmlGetProp(root_node,
3414 "method"),
3415 BAD_CAST "AgsChannel::stop",
3416 18)){
3417 ags_machine_playback_set_active(machine,
3418 playback,
3419 FALSE);
3420 }
3421 }
3422
3423 message_envelope = message_envelope->next;
3424 }
3425
3426 g_list_free_full(start_message_envelope,
3427 (GDestroyNotify) g_object_unref);
3428
3429 g_object_unref(channel);
3430 g_object_unref(playback);
3431
3432 active_playback = active_playback->next;
3433 }
3434
3435 g_list_free(start_active_playback);
3436 }
3437
3438 /**
3439 * ags_machine_new:
3440 * @soundcard: the assigned soundcard.
3441 *
3442 * Creates an #AgsMachine
3443 *
3444 * Returns: a new #AgsMachine
3445 *
3446 * Since: 3.0.0
3447 */
3448 AgsMachine*
ags_machine_new(GObject * soundcard)3449 ags_machine_new(GObject *soundcard)
3450 {
3451 AgsMachine *machine;
3452
3453 machine = (AgsMachine *) g_object_new(AGS_TYPE_MACHINE,
3454 NULL);
3455
3456 g_object_set(machine->audio,
3457 "output-soundcard", soundcard,
3458 NULL);
3459
3460 return(machine);
3461 }
3462
3463 /**
3464 * ags_machine_popup_new:
3465 * @machine: the assigned machine.
3466 *
3467 * Creates #GtkMenu to use as @machine's popup context menu.
3468 *
3469 * Returns: a new #GtkMenu containing basic actions.
3470 *
3471 * Since: 3.0.0
3472 */
3473 GtkMenu*
ags_machine_popup_new(AgsMachine * machine)3474 ags_machine_popup_new(AgsMachine *machine)
3475 {
3476 GtkMenu *popup;
3477 GtkMenuItem *item;
3478 GList *list, *list_start;
3479
3480 popup = (GtkMenu *) gtk_menu_new();
3481
3482 item = (GtkMenuItem *) gtk_menu_item_new_with_label(i18n("move up"));
3483 gtk_menu_shell_append((GtkMenuShell *) popup, (GtkWidget*) item);
3484
3485 item = (GtkMenuItem *) gtk_menu_item_new_with_label(i18n("move down"));
3486 gtk_menu_shell_append((GtkMenuShell *) popup, (GtkWidget*) item);
3487
3488 item = (GtkMenuItem *) gtk_menu_item_new_with_label(i18n("hide"));
3489 gtk_menu_shell_append((GtkMenuShell *) popup, (GtkWidget*) item);
3490
3491 item = (GtkMenuItem *) gtk_menu_item_new_with_label(i18n("show"));
3492 gtk_menu_shell_append((GtkMenuShell *) popup, (GtkWidget*) item);
3493
3494 item = (GtkMenuItem *) gtk_menu_item_new_with_label(i18n("destroy"));
3495 gtk_menu_shell_append((GtkMenuShell *) popup, (GtkWidget*) item);
3496
3497 item = (GtkMenuItem *) gtk_menu_item_new_with_label(i18n("rename"));
3498 gtk_menu_shell_append((GtkMenuShell *) popup, (GtkWidget*) item);
3499
3500 item = (GtkMenuItem *) gtk_menu_item_new_with_label(i18n("rename audio"));
3501 gtk_menu_shell_append((GtkMenuShell *) popup, (GtkWidget*) item);
3502
3503 item = (GtkMenuItem *) gtk_menu_item_new_with_label(i18n("reposition audio"));
3504 gtk_menu_shell_append((GtkMenuShell *) popup, (GtkWidget*) item);
3505
3506 item = (GtkMenuItem *) gtk_menu_item_new_with_label(i18n("properties"));
3507 gtk_menu_shell_append((GtkMenuShell *) popup, (GtkWidget*) item);
3508
3509 item = (GtkMenuItem *) gtk_check_menu_item_new_with_label(i18n("sticky controls"));
3510 gtk_menu_shell_append((GtkMenuShell *) popup, (GtkWidget*) item);
3511
3512 list_start =
3513 list = gtk_container_get_children((GtkContainer *) popup);
3514
3515 g_signal_connect((GObject*) list->data, "activate",
3516 G_CALLBACK(ags_machine_popup_move_up_activate_callback), (gpointer) machine);
3517 list = list->next;
3518
3519 g_signal_connect((GObject*) list->data, "activate",
3520 G_CALLBACK(ags_machine_popup_move_down_activate_callback), (gpointer) machine);
3521 list = list->next;
3522
3523 g_signal_connect((GObject*) list->data, "activate",
3524 G_CALLBACK(ags_machine_popup_hide_activate_callback), (gpointer) machine);
3525 list = list->next;
3526
3527 g_signal_connect((GObject*) list->data, "activate",
3528 G_CALLBACK(ags_machine_popup_show_activate_callback), (gpointer) machine);
3529 list = list->next;
3530
3531 g_signal_connect((GObject*) list->data, "activate",
3532 G_CALLBACK(ags_machine_popup_destroy_activate_callback), (gpointer) machine);
3533 list = list->next;
3534
3535 g_signal_connect((GObject*) list->data, "activate",
3536 G_CALLBACK(ags_machine_popup_rename_activate_callback), (gpointer) machine);
3537 list = list->next;
3538
3539 g_signal_connect((GObject*) list->data, "activate",
3540 G_CALLBACK(ags_machine_popup_rename_audio_activate_callback), (gpointer) machine);
3541 list = list->next;
3542
3543 g_signal_connect((GObject*) list->data, "activate",
3544 G_CALLBACK(ags_machine_popup_reposition_audio_activate_callback), (gpointer) machine);
3545 list = list->next;
3546
3547 g_signal_connect((GObject*) list->data, "activate",
3548 G_CALLBACK(ags_machine_popup_properties_activate_callback), (gpointer) machine);
3549 list = list->next;
3550
3551 g_signal_connect_after((GObject*) list->data, "toggled",
3552 G_CALLBACK(ags_machine_popup_sticky_controls_toggled_callback), (gpointer) machine);
3553
3554 g_list_free(list_start);
3555 gtk_widget_show_all((GtkWidget*) popup);
3556
3557 return(popup);
3558 }
3559
3560 /**
3561 * ags_machine_popup_add_edit_options:
3562 * @machine: the assigned machine.
3563 * @edit_options: the options to set
3564 *
3565 * Add options to edit submenu
3566 *
3567 * Since: 3.0.0
3568 */
3569 void
ags_machine_popup_add_edit_options(AgsMachine * machine,guint edit_options)3570 ags_machine_popup_add_edit_options(AgsMachine *machine, guint edit_options)
3571 {
3572 GtkMenu *edit;
3573 GtkMenuItem *item;
3574
3575 item = (GtkMenuItem *) gtk_menu_item_new_with_label(i18n("edit"));
3576 gtk_menu_shell_append((GtkMenuShell *) machine->popup, (GtkWidget*) item);
3577 gtk_widget_show((GtkWidget *) item);
3578
3579 edit = (GtkMenu *) gtk_menu_new();
3580 gtk_menu_item_set_submenu(item,
3581 (GtkWidget *) edit);
3582
3583 gtk_widget_show((GtkWidget *) edit);
3584
3585 if((AGS_MACHINE_POPUP_COPY_PATTERN & edit_options) != 0){
3586 item = (GtkMenuItem *) gtk_menu_item_new_with_label(i18n("copy pattern"));
3587 gtk_menu_shell_append((GtkMenuShell *) edit, (GtkWidget*) item);
3588
3589 g_signal_connect((GObject*) item, "activate",
3590 G_CALLBACK(ags_machine_popup_copy_pattern_callback), (gpointer) machine);
3591
3592 gtk_widget_show((GtkWidget *) item);
3593 }
3594
3595 if((AGS_MACHINE_POPUP_PASTE_PATTERN & edit_options) != 0){
3596 item = (GtkMenuItem *) gtk_menu_item_new_with_label(i18n("paste pattern"));
3597 gtk_menu_shell_append((GtkMenuShell *) edit, (GtkWidget*) item);
3598
3599 g_signal_connect((GObject*) item, "activate",
3600 G_CALLBACK(ags_machine_popup_paste_pattern_callback), (gpointer) machine);
3601
3602 gtk_widget_show((GtkWidget *) item);
3603 }
3604
3605 if((AGS_MACHINE_POPUP_ENVELOPE & edit_options) != 0){
3606 item = (GtkMenuItem *) gtk_menu_item_new_with_label(i18n("envelope"));
3607 gtk_menu_shell_append((GtkMenuShell *) edit, (GtkWidget*) item);
3608
3609 g_signal_connect((GObject*) item, "activate",
3610 G_CALLBACK(ags_machine_popup_envelope_callback), (gpointer) machine);
3611
3612 gtk_widget_show((GtkWidget *) item);
3613 }
3614
3615 gtk_widget_show_all((GtkWidget *) machine->popup);
3616 }
3617
3618 /**
3619 * ags_machine_popup_add_connection_options:
3620 * @machine: the assigned machine.
3621 * @connection_options: the options to set
3622 *
3623 * Add options to connection submenu
3624 *
3625 * Since: 3.0.0
3626 */
3627 void
ags_machine_popup_add_connection_options(AgsMachine * machine,guint connection_options)3628 ags_machine_popup_add_connection_options(AgsMachine *machine, guint connection_options)
3629 {
3630 GtkMenu *connection;
3631 GtkMenuItem *item;
3632
3633 item = (GtkMenuItem *) gtk_menu_item_new_with_label(i18n("connection"));
3634 gtk_menu_shell_append((GtkMenuShell *) machine->popup, (GtkWidget*) item);
3635 gtk_widget_show((GtkWidget *) item);
3636
3637 connection = (GtkMenu *) gtk_menu_new();
3638 gtk_menu_item_set_submenu(item,
3639 (GtkWidget *) connection);
3640
3641 gtk_widget_show((GtkWidget *) connection);
3642
3643 if((AGS_MACHINE_POPUP_CONNECTION_EDITOR & connection_options) != 0){
3644 item = (GtkMenuItem *) gtk_menu_item_new_with_label(i18n("audio connection"));
3645 gtk_menu_shell_append((GtkMenuShell *) connection, (GtkWidget*) item);
3646
3647 g_signal_connect((GObject*) item, "activate",
3648 G_CALLBACK(ags_machine_popup_connection_editor_callback), (gpointer) machine);
3649
3650 gtk_widget_show((GtkWidget *) item);
3651 }
3652
3653 if((AGS_MACHINE_POPUP_MIDI_DIALOG & connection_options) != 0){
3654 item = (GtkMenuItem *) gtk_menu_item_new_with_label(i18n("MIDI dialog"));
3655 gtk_menu_shell_append((GtkMenuShell *) connection, (GtkWidget*) item);
3656
3657 g_signal_connect((GObject*) item, "activate",
3658 G_CALLBACK(ags_machine_popup_midi_dialog_callback), (gpointer) machine);
3659
3660 gtk_widget_show((GtkWidget *) item);
3661 }
3662
3663 gtk_widget_show_all((GtkWidget *) machine->popup);
3664 }
3665
3666 void
ags_machine_popup_add_export_options(AgsMachine * machine,guint export_options)3667 ags_machine_popup_add_export_options(AgsMachine *machine, guint export_options)
3668 {
3669 GtkMenu *export;
3670 GtkMenuItem *item;
3671
3672 item = (GtkMenuItem *) gtk_menu_item_new_with_label(i18n("export"));
3673 gtk_menu_shell_append((GtkMenuShell *) machine->popup, (GtkWidget*) item);
3674 gtk_widget_show((GtkWidget *) item);
3675
3676 export = (GtkMenu *) gtk_menu_new();
3677 gtk_menu_item_set_submenu(item,
3678 (GtkWidget *) export);
3679
3680 gtk_widget_show((GtkWidget *) export);
3681
3682 if((AGS_MACHINE_POPUP_MIDI_EXPORT & export_options) != 0){
3683 item = (GtkMenuItem *) gtk_menu_item_new_with_label(i18n("MIDI export"));
3684 gtk_menu_shell_append((GtkMenuShell *) export, (GtkWidget*) item);
3685
3686 g_signal_connect((GObject*) item, "activate",
3687 G_CALLBACK(ags_machine_popup_midi_export_callback), (gpointer) machine);
3688
3689 gtk_widget_show((GtkWidget *) item);
3690 }
3691
3692 if((AGS_MACHINE_POPUP_WAVE_EXPORT & export_options) != 0){
3693 item = (GtkMenuItem *) gtk_menu_item_new_with_label(i18n("Audio export"));
3694 gtk_menu_shell_append((GtkMenuShell *) export, (GtkWidget*) item);
3695
3696 g_signal_connect((GObject*) item, "activate",
3697 G_CALLBACK(ags_machine_popup_wave_export_callback), (gpointer) machine);
3698
3699 gtk_widget_show((GtkWidget *) item);
3700 }
3701
3702 gtk_widget_show_all((GtkWidget *) machine->popup);
3703 }
3704
3705 void
ags_machine_popup_add_import_options(AgsMachine * machine,guint import_options)3706 ags_machine_popup_add_import_options(AgsMachine *machine, guint import_options)
3707 {
3708 GtkMenu *import;
3709 GtkMenuItem *item;
3710
3711 item = (GtkMenuItem *) gtk_menu_item_new_with_label(i18n("import"));
3712 gtk_menu_shell_append((GtkMenuShell *) machine->popup, (GtkWidget*) item);
3713 gtk_widget_show((GtkWidget *) item);
3714
3715 import = (GtkMenu *) gtk_menu_new();
3716 gtk_menu_item_set_submenu(item,
3717 (GtkWidget *) import);
3718
3719 gtk_widget_show((GtkWidget *) import);
3720
3721 if((AGS_MACHINE_POPUP_MIDI_IMPORT & import_options) != 0){
3722 item = (GtkMenuItem *) gtk_menu_item_new_with_label(i18n("MIDI import"));
3723 gtk_menu_shell_append((GtkMenuShell *) import, (GtkWidget*) item);
3724
3725 g_signal_connect((GObject*) item, "activate",
3726 G_CALLBACK(ags_machine_popup_midi_import_callback), (gpointer) machine);
3727
3728 gtk_widget_show((GtkWidget *) item);
3729 }
3730
3731 if((AGS_MACHINE_POPUP_WAVE_IMPORT & import_options) != 0){
3732 item = (GtkMenuItem *) gtk_menu_item_new_with_label(i18n("Audio import"));
3733 gtk_menu_shell_append((GtkMenuShell *) import, (GtkWidget*) item);
3734
3735 g_signal_connect((GObject*) item, "activate",
3736 G_CALLBACK(ags_machine_popup_wave_import_callback), (gpointer) machine);
3737
3738 gtk_widget_show((GtkWidget *) item);
3739 }
3740
3741 gtk_widget_show_all((GtkWidget *) machine->popup);
3742 }
3743