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", &current_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