1 /* GSequencer - Advanced GTK Sequencer
2 * Copyright (C) 2005-2020 Joël Krähemann
3 *
4 * This file is part of GSequencer.
5 *
6 * GSequencer is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * GSequencer is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GSequencer. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <ags/X/ags_input_listing_editor.h>
21 #include <ags/X/ags_input_listing_editor_callbacks.h>
22
23 #include <ags/X/ags_connection_editor.h>
24 #include <ags/X/ags_pad_editor.h>
25 #include <ags/X/ags_line_editor.h>
26 #include <ags/X/ags_input_editor.h>
27
28 void ags_input_listing_editor_class_init(AgsInputListingEditorClass *input_listing_editor);
29 void ags_input_listing_editor_connectable_interface_init(AgsConnectableInterface *connectable);
30 void ags_input_listing_editor_applicable_interface_init(AgsApplicableInterface *applicable);
31 void ags_input_listing_editor_init(AgsInputListingEditor *input_listing_editor);
32
33 void ags_input_listing_editor_connect(AgsConnectable *connectable);
34 void ags_input_listing_editor_disconnect(AgsConnectable *connectable);
35
36 void ags_input_listing_editor_set_update(AgsApplicable *applicable, gboolean update);
37 void ags_input_listing_editor_apply(AgsApplicable *applicable);
38 void ags_input_listing_editor_reset(AgsApplicable *applicable);
39
40 /**
41 * SECTION:ags_input_listing_editor
42 * @short_description: pack input editors
43 * @title: AgsInputListingEditor
44 * @section_id:
45 * @include: ags/X/ags_input_listing_editor.h
46 *
47 * #AgsInputListingEditor is a composite widget to pack #AgsInputEditor.
48 */
49
50 static gpointer ags_input_listing_editor_parent_class = NULL;
51 static AgsConnectableInterface* ags_input_listing_editor_parent_connectable_interface;
52
53 GType
ags_input_listing_editor_get_type()54 ags_input_listing_editor_get_type()
55 {
56 static volatile gsize g_define_type_id__volatile = 0;
57
58 if(g_once_init_enter (&g_define_type_id__volatile)){
59 GType ags_type_input_listing_editor = 0;
60
61 static const GTypeInfo ags_input_listing_editor_info = {
62 sizeof (AgsInputListingEditorClass),
63 NULL, /* base_init */
64 NULL, /* base_finalize */
65 (GClassInitFunc) ags_input_listing_editor_class_init,
66 NULL, /* class_finalize */
67 NULL, /* class_data */
68 sizeof (AgsInputListingEditor),
69 0, /* n_preallocs */
70 (GInstanceInitFunc) ags_input_listing_editor_init,
71 };
72
73 static const GInterfaceInfo ags_connectable_interface_info = {
74 (GInterfaceInitFunc) ags_input_listing_editor_connectable_interface_init,
75 NULL, /* interface_finalize */
76 NULL, /* interface_data */
77 };
78
79 static const GInterfaceInfo ags_applicable_interface_info = {
80 (GInterfaceInitFunc) ags_input_listing_editor_applicable_interface_init,
81 NULL, /* interface_finalize */
82 NULL, /* interface_data */
83 };
84
85 ags_type_input_listing_editor = g_type_register_static(AGS_TYPE_PROPERTY_LISTING_EDITOR,
86 "AgsInputListingEditor",
87 &ags_input_listing_editor_info,
88 0);
89
90 g_type_add_interface_static(ags_type_input_listing_editor,
91 AGS_TYPE_CONNECTABLE,
92 &ags_connectable_interface_info);
93
94 g_type_add_interface_static(ags_type_input_listing_editor,
95 AGS_TYPE_APPLICABLE,
96 &ags_applicable_interface_info);
97
98 g_once_init_leave(&g_define_type_id__volatile, ags_type_input_listing_editor);
99 }
100
101 return g_define_type_id__volatile;
102 }
103
104 void
ags_input_listing_editor_class_init(AgsInputListingEditorClass * input_listing_editor)105 ags_input_listing_editor_class_init(AgsInputListingEditorClass *input_listing_editor)
106 {
107 ags_input_listing_editor_parent_class = g_type_class_peek_parent(input_listing_editor);
108 }
109
110 void
ags_input_listing_editor_connectable_interface_init(AgsConnectableInterface * connectable)111 ags_input_listing_editor_connectable_interface_init(AgsConnectableInterface *connectable)
112 {
113 ags_input_listing_editor_parent_connectable_interface = g_type_interface_peek_parent(connectable);
114
115 connectable->is_ready = NULL;
116 connectable->is_connected = NULL;
117 connectable->connect = ags_input_listing_editor_connect;
118 connectable->disconnect = ags_input_listing_editor_disconnect;
119 }
120
121 void
ags_input_listing_editor_applicable_interface_init(AgsApplicableInterface * applicable)122 ags_input_listing_editor_applicable_interface_init(AgsApplicableInterface *applicable)
123 {
124 applicable->set_update = ags_input_listing_editor_set_update;
125 applicable->apply = ags_input_listing_editor_apply;
126 applicable->reset = ags_input_listing_editor_reset;
127 }
128
129 void
ags_input_listing_editor_init(AgsInputListingEditor * input_listing_editor)130 ags_input_listing_editor_init(AgsInputListingEditor *input_listing_editor)
131 {
132 g_signal_connect_after(G_OBJECT(input_listing_editor), "parent_set",
133 G_CALLBACK(ags_input_listing_editor_parent_set_callback), input_listing_editor);
134
135 input_listing_editor->channel_type = G_TYPE_NONE;
136
137 input_listing_editor->child = NULL;
138 }
139
140 void
ags_input_listing_editor_connect(AgsConnectable * connectable)141 ags_input_listing_editor_connect(AgsConnectable *connectable)
142 {
143 AgsConnectionEditor *connection_editor;
144 AgsInputListingEditor *input_listing_editor;
145
146 GList *pad_editor, *pad_editor_start;
147
148 input_listing_editor = AGS_INPUT_LISTING_EDITOR(connectable);
149
150 if((AGS_PROPERTY_EDITOR_CONNECTED & (AGS_PROPERTY_EDITOR(input_listing_editor)->flags)) != 0){
151 return;
152 }
153
154 ags_input_listing_editor_parent_connectable_interface->connect(connectable);
155
156 connection_editor = (AgsConnectionEditor *) gtk_widget_get_ancestor(GTK_WIDGET(input_listing_editor),
157 AGS_TYPE_CONNECTION_EDITOR);
158
159 if(connection_editor != NULL &&
160 connection_editor->machine != NULL){
161 g_signal_connect_after(G_OBJECT(connection_editor->machine), "resize-pads",
162 G_CALLBACK(ags_input_listing_editor_resize_pads_callback), input_listing_editor);
163 }
164
165 /* AgsPadEditor */
166 if(input_listing_editor->child != NULL){
167 pad_editor_start =
168 pad_editor = gtk_container_get_children(GTK_CONTAINER(input_listing_editor->child));
169
170 while(pad_editor != NULL){
171 ags_connectable_connect(AGS_CONNECTABLE(pad_editor->data));
172
173 pad_editor = pad_editor->next;
174 }
175
176 g_list_free(pad_editor_start);
177 }
178 }
179
180 void
ags_input_listing_editor_disconnect(AgsConnectable * connectable)181 ags_input_listing_editor_disconnect(AgsConnectable *connectable)
182 {
183 AgsConnectionEditor *connection_editor;
184 AgsInputListingEditor *input_listing_editor;
185
186 GList *pad_editor, *pad_editor_start;
187
188 input_listing_editor = AGS_INPUT_LISTING_EDITOR(connectable);
189
190 if((AGS_PROPERTY_EDITOR_CONNECTED & (AGS_PROPERTY_EDITOR(input_listing_editor)->flags)) == 0){
191 return;
192 }
193
194 ags_input_listing_editor_parent_connectable_interface->disconnect(connectable);
195
196 connection_editor = (AgsConnectionEditor *) gtk_widget_get_ancestor(GTK_WIDGET(input_listing_editor),
197 AGS_TYPE_CONNECTION_EDITOR);
198
199 if(connection_editor != NULL &&
200 connection_editor->machine != NULL){
201 g_object_disconnect(G_OBJECT(connection_editor->machine),
202 "any_signal::resize-pads",
203 G_CALLBACK(ags_input_listing_editor_resize_pads_callback),
204 input_listing_editor,
205 NULL);
206 }
207
208 /* AgsPadEditor */
209 if(input_listing_editor->child != NULL){
210 pad_editor_start =
211 pad_editor = gtk_container_get_children(GTK_CONTAINER(input_listing_editor->child));
212
213 while(pad_editor != NULL){
214 ags_connectable_disconnect(AGS_CONNECTABLE(pad_editor->data));
215
216 pad_editor = pad_editor->next;
217 }
218
219 g_list_free(pad_editor_start);
220 }
221 }
222
223 void
ags_input_listing_editor_set_update(AgsApplicable * applicable,gboolean update)224 ags_input_listing_editor_set_update(AgsApplicable *applicable, gboolean update)
225 {
226 AgsInputListingEditor *input_listing_editor;
227
228 GList *pad_editor, *pad_editor_start;
229
230 input_listing_editor = AGS_INPUT_LISTING_EDITOR(applicable);
231
232 if(input_listing_editor->child != NULL){
233 pad_editor_start =
234 pad_editor = gtk_container_get_children(GTK_CONTAINER(input_listing_editor->child));
235
236 while(pad_editor != NULL){
237 ags_applicable_set_update(AGS_APPLICABLE(pad_editor->data), update);
238
239 pad_editor = pad_editor->next;
240 }
241
242 g_list_free(pad_editor_start);
243 }
244 }
245
246 void
ags_input_listing_editor_apply(AgsApplicable * applicable)247 ags_input_listing_editor_apply(AgsApplicable *applicable)
248 {
249 AgsInputListingEditor *input_listing_editor;
250
251 GList *pad_editor, *pad_editor_start;
252
253 input_listing_editor = AGS_INPUT_LISTING_EDITOR(applicable);
254
255 if((AGS_PROPERTY_EDITOR_ENABLED & (AGS_PROPERTY_EDITOR(input_listing_editor)->flags)) == 0){
256 return;
257 }
258
259 if(input_listing_editor->child != NULL){
260 pad_editor_start =
261 pad_editor = gtk_container_get_children(GTK_CONTAINER(input_listing_editor->child));
262
263 while(pad_editor != NULL){
264 ags_applicable_apply(AGS_APPLICABLE(pad_editor->data));
265
266 pad_editor = pad_editor->next;
267 }
268
269 g_list_free(pad_editor_start);
270 }
271 }
272
273 void
ags_input_listing_editor_reset(AgsApplicable * applicable)274 ags_input_listing_editor_reset(AgsApplicable *applicable)
275 {
276 AgsInputListingEditor *input_listing_editor;
277
278 GList *pad_editor, *pad_editor_start;
279
280 input_listing_editor = AGS_INPUT_LISTING_EDITOR(applicable);
281
282 if(input_listing_editor->child != NULL){
283 pad_editor_start =
284 pad_editor = gtk_container_get_children(GTK_CONTAINER(input_listing_editor->child));
285
286 while(pad_editor != NULL){
287 ags_applicable_reset(AGS_APPLICABLE(pad_editor->data));
288
289 pad_editor = pad_editor->next;
290 }
291
292 g_list_free(pad_editor_start);
293 }
294 }
295
296 /**
297 * ags_input_listing_editor_add_children:
298 * @input_listing_editor: the #AgsInputListingEditor
299 * @audio: the #AgsAudio to use
300 * @nth: nth channel to start creation until end
301 * @connect: if %TRUE widget is connected and shown
302 *
303 * Creates new pad editors or destroys them.
304 *
305 * Since: 3.0.0
306 */
307 void
ags_input_listing_editor_add_children(AgsInputListingEditor * input_listing_editor,AgsAudio * audio,guint nth,gboolean connect)308 ags_input_listing_editor_add_children(AgsInputListingEditor *input_listing_editor,
309 AgsAudio *audio, guint nth,
310 gboolean connect)
311 {
312 AgsPadEditor *pad_editor;
313 GtkBox *vbox;
314
315 AgsChannel *start_channel;
316 AgsChannel *channel, *next_pad, *nth_channel;
317
318 if(nth == 0 &&
319 input_listing_editor->child != NULL){
320 vbox = input_listing_editor->child;
321 input_listing_editor->child = NULL;
322 gtk_widget_destroy(GTK_WIDGET(vbox));
323 }
324
325 if(audio == NULL){
326 return;
327 }
328
329 /* instantiate pad editor vbox */
330 if(nth == 0){
331 input_listing_editor->child = (GtkBox *) gtk_vbox_new(GTK_ORIENTATION_VERTICAL,
332 0);
333 gtk_box_pack_start((GtkBox *) input_listing_editor,
334 (GtkWidget *) input_listing_editor->child,
335 FALSE, FALSE,
336 0);
337 }
338
339 /* get current channel */
340 if(g_type_is_a(input_listing_editor->channel_type, AGS_TYPE_OUTPUT)){
341 g_object_get(audio,
342 "output", &start_channel,
343 NULL);
344 }else if(g_type_is_a(input_listing_editor->channel_type, AGS_TYPE_INPUT)){
345 g_object_get(audio,
346 "input", &start_channel,
347 NULL);
348 }else{
349 start_channel = NULL;
350 }
351
352 nth_channel = ags_channel_nth(start_channel,
353 nth);
354
355 channel = nth_channel;
356
357 next_pad = NULL;
358
359 while(channel != NULL){
360 /* instantiate pad editor */
361 pad_editor = ags_pad_editor_new(NULL);
362
363 pad_editor->editor_type_count = 1;
364 pad_editor->editor_type = (GType *) malloc(pad_editor->editor_type_count * sizeof(GType));
365 pad_editor->editor_type[0] = AGS_TYPE_INPUT_EDITOR;
366
367 g_object_set(pad_editor,
368 "channel", channel,
369 NULL);
370
371 gtk_box_pack_start((GtkBox *) input_listing_editor->child,
372 (GtkWidget *) pad_editor,
373 FALSE, FALSE,
374 0);
375
376 if(connect){
377 ags_connectable_connect(AGS_CONNECTABLE(pad_editor));
378 gtk_widget_show_all(GTK_WIDGET(pad_editor));
379 }
380
381 /* iterate */
382 next_pad = ags_channel_next_pad(channel);
383
384 g_object_unref(channel);
385
386 channel = next_pad;
387 }
388
389 if(next_pad != NULL){
390 g_object_unref(next_pad);
391 }
392
393 /* unref */
394 if(start_channel != NULL){
395 g_object_unref(start_channel);
396 }
397 }
398
399 /**
400 * ags_input_listing_editor_new:
401 * @channel_type: the channel type to represent
402 *
403 * Create a new instance of #AgsInputListingEditor
404 *
405 * Returns: the new #AgsInputListingEditor
406 *
407 * Since: 3.0.0
408 */
409 AgsInputListingEditor*
ags_input_listing_editor_new(GType channel_type)410 ags_input_listing_editor_new(GType channel_type)
411 {
412 AgsInputListingEditor *input_listing_editor;
413
414 input_listing_editor = (AgsInputListingEditor *) g_object_new(AGS_TYPE_INPUT_LISTING_EDITOR,
415 NULL);
416
417 input_listing_editor->channel_type = channel_type;
418
419 return(input_listing_editor);
420 }
421