1 /* GSequencer - Advanced GTK Sequencer
2  * Copyright (C) 2005-2019 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/audio/recall/ags_rt_stream_channel_run.h>
21 
22 #include <ags/audio/ags_audio.h>
23 #include <ags/audio/ags_recycling.h>
24 #include <ags/audio/ags_recall_id.h>
25 
26 #include <ags/audio/recall/ags_rt_stream_recycling.h>
27 
28 void ags_rt_stream_channel_run_class_init(AgsRtStreamChannelRunClass *rt_stream_channel_run);
29 void ags_rt_stream_channel_run_init(AgsRtStreamChannelRun *rt_stream_channel_run);
30 
31 void ags_rt_stream_channel_run_check_rt_data(AgsRecall *recall);
32 void ags_rt_stream_channel_run_done(AgsRecall *recall);
33 
34 /**
35  * SECTION:ags_rt_stream_channel_run
36  * @short_description: rt streams channel
37  * @title: AgsRtStreamChannelRun
38  * @section_id:
39  * @include: ags/audio/recall/ags_rt_stream_channel_run.h
40  *
41  * The #AgsRtStreamChannelRun class streams the audio signal template.
42  */
43 
44 static gpointer ags_rt_stream_channel_run_parent_class = NULL;
45 
46 GType
ags_rt_stream_channel_run_get_type()47 ags_rt_stream_channel_run_get_type()
48 {
49   static volatile gsize g_define_type_id__volatile = 0;
50 
51   if(g_once_init_enter (&g_define_type_id__volatile)){
52     GType ags_type_rt_stream_channel_run = 0;
53 
54     static const GTypeInfo ags_rt_stream_channel_run_info = {
55       sizeof (AgsRtStreamChannelRunClass),
56       NULL, /* base_init */
57       NULL, /* base_finalize */
58       (GClassInitFunc) ags_rt_stream_channel_run_class_init,
59       NULL, /* class_finalize */
60       NULL, /* class_data */
61       sizeof (AgsRtStreamChannelRun),
62       0,    /* n_preallocs */
63       (GInstanceInitFunc) ags_rt_stream_channel_run_init,
64     };
65 
66     ags_type_rt_stream_channel_run = g_type_register_static(AGS_TYPE_RECALL_CHANNEL_RUN,
67 							    "AgsRtStreamChannelRun",
68 							    &ags_rt_stream_channel_run_info,
69 							    0);
70 
71     g_once_init_leave(&g_define_type_id__volatile, ags_type_rt_stream_channel_run);
72   }
73 
74   return g_define_type_id__volatile;
75 }
76 
77 void
ags_rt_stream_channel_run_class_init(AgsRtStreamChannelRunClass * rt_stream_channel_run)78 ags_rt_stream_channel_run_class_init(AgsRtStreamChannelRunClass *rt_stream_channel_run)
79 {
80   GObjectClass *gobject;
81   AgsRecallClass *recall;
82 
83   ags_rt_stream_channel_run_parent_class = g_type_class_peek_parent(rt_stream_channel_run);
84 
85   /* GObjectClass */
86   gobject = (GObjectClass *) rt_stream_channel_run;
87 
88   /* AgsRecallClass */
89   recall = (AgsRecallClass *) rt_stream_channel_run;
90 
91   recall->check_rt_data = ags_rt_stream_channel_run_check_rt_data;
92   recall->done = ags_rt_stream_channel_run_done;
93 }
94 
95 void
ags_rt_stream_channel_run_init(AgsRtStreamChannelRun * rt_stream_channel_run)96 ags_rt_stream_channel_run_init(AgsRtStreamChannelRun *rt_stream_channel_run)
97 {
98   ags_recall_set_ability_flags((AgsRecall *) rt_stream_channel_run, (AGS_SOUND_ABILITY_PLAYBACK |
99 								     AGS_SOUND_ABILITY_SEQUENCER |
100 								     AGS_SOUND_ABILITY_NOTATION |
101 								     AGS_SOUND_ABILITY_WAVE |
102 								     AGS_SOUND_ABILITY_MIDI));
103 
104   AGS_RECALL(rt_stream_channel_run)->name = "ags-rt_stream";
105   AGS_RECALL(rt_stream_channel_run)->version = AGS_RECALL_DEFAULT_VERSION;
106   AGS_RECALL(rt_stream_channel_run)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
107   AGS_RECALL(rt_stream_channel_run)->xml_type = "ags-rt_stream-channel-run";
108   AGS_RECALL(rt_stream_channel_run)->port = NULL;
109 
110   AGS_RECALL(rt_stream_channel_run)->child_type = AGS_TYPE_RT_STREAM_RECYCLING;
111 }
112 
113 void
ags_rt_stream_channel_run_check_rt_data(AgsRecall * recall)114 ags_rt_stream_channel_run_check_rt_data(AgsRecall *recall)
115 {
116   AgsChannel *source;
117   AgsRecycling *first_recycling, *last_recycling;
118   AgsRecycling *end_recycling;
119   AgsRecycling *recycling, *next_recycling;
120   AgsRtStreamChannelRun *rt_stream_channel_run;
121   AgsRecallID *recall_id;
122 
123   GObject *output_soundcard;
124 
125   rt_stream_channel_run = (AgsRtStreamChannelRun *) recall;
126 
127   g_object_get(rt_stream_channel_run,
128 	       "source", &source,
129 	       "output-soundcard", &output_soundcard,
130 	       "recall-id", &recall_id,
131 	       NULL);
132 
133   /* get first and last recycling */
134   g_object_get(source,
135 	       "first-recycling", &first_recycling,
136 	       "last-recycling", &last_recycling,
137 	       NULL);
138 
139   /* get end */
140   end_recycling = ags_recycling_next(last_recycling);
141 
142   /* */
143   recycling = first_recycling;
144   g_object_ref(recycling);
145 
146   next_recycling = NULL;
147 
148   while(recycling != end_recycling){
149     AgsAudioSignal *audio_signal;
150     AgsAudioSignal *rt_template, *template;
151 
152     /* create rt template */
153     rt_template = ags_audio_signal_new(output_soundcard,
154 				       (GObject *) recycling,
155 				       (GObject *) recall_id);
156     rt_template->flags |= AGS_AUDIO_SIGNAL_RT_TEMPLATE;
157     ags_recycling_create_audio_signal_with_defaults(recycling,
158 						    rt_template,
159 						    0.0, 0);
160     ags_recycling_add_audio_signal(recycling,
161 				   rt_template);
162 
163     /* create buffer */
164     audio_signal = ags_audio_signal_new(output_soundcard,
165 					(GObject *) recycling,
166 					(GObject *) recall_id);
167 
168     g_object_set(audio_signal,
169 		 "rt-template", rt_template,
170 		 NULL);
171     ags_audio_signal_stream_resize(audio_signal,
172 				   3);
173     audio_signal->stream_current = audio_signal->stream;
174 
175     /* add buffer */
176     ags_recycling_add_audio_signal(recycling,
177 				   audio_signal);
178 
179     /* iterate */
180     next_recycling = ags_recycling_next(recycling);
181 
182     g_object_unref(recycling);
183 
184     recycling = next_recycling;
185   }
186 
187   /* unref */
188   g_object_unref(source);
189 
190   g_object_unref(output_soundcard);
191 
192   g_object_unref(recall_id);
193 
194   if(first_recycling != NULL){
195     g_object_unref(first_recycling);
196     g_object_unref(last_recycling);
197   }
198 
199   if(end_recycling != NULL){
200     g_object_unref(end_recycling);
201   }
202 }
203 
204 void
ags_rt_stream_channel_run_done(AgsRecall * recall)205 ags_rt_stream_channel_run_done(AgsRecall *recall)
206 {
207   AgsChannel *source;
208   AgsRecycling *first_recycling, *last_recycling;
209   AgsRecycling *end_recycling;
210   AgsRecycling *recycling, *next_recycling;
211   AgsRecallID *recall_id;
212   AgsRtStreamChannelRun *rt_stream_channel_run;
213 
214   void (*parent_class_done)(AgsRecall *recall);
215 
216   rt_stream_channel_run = (AgsRtStreamChannelRun *) recall;
217 
218   /* get parent class */
219   parent_class_done = AGS_RECALL_CLASS(ags_rt_stream_channel_run_parent_class)->done;
220 
221   /* get some fields */
222   g_object_get(rt_stream_channel_run,
223 	       "source", &source,
224 	       "recall-id", &recall_id,
225 	       NULL);
226 
227   /* get first and last recycling */
228   g_object_get(source,
229 	       "first-recycling", &first_recycling,
230 	       "last-recycling", &last_recycling,
231 	       NULL);
232 
233   /* get end */
234   end_recycling = ags_recycling_next(last_recycling);
235 
236   /* prepare */
237   recycling = first_recycling;
238   g_object_ref(recycling);
239 
240   next_recycling = NULL;
241 
242   while(recycling != end_recycling){
243     GList *start_audio_signal, *audio_signal;
244 
245     g_object_get(recycling,
246 		 "audio-signal", &start_audio_signal,
247 		 NULL);
248 
249     audio_signal = start_audio_signal;
250 
251     while((audio_signal = ags_audio_signal_find_by_recall_id(audio_signal,
252 							     (GObject *) recall_id)) != NULL){
253       ags_recycling_remove_audio_signal(recycling,
254 					audio_signal->data);
255 
256       audio_signal = audio_signal->next;
257     }
258 
259     g_list_free(start_audio_signal);
260 
261     /* iterate */
262     next_recycling = ags_recycling_next(recycling);
263 
264     g_object_unref(recycling);
265 
266     recycling = next_recycling;
267   }
268 
269   /* call parent */
270   parent_class_done(recall);
271 
272   /* unref */
273   g_object_unref(source);
274 
275   g_object_unref(recall_id);
276 
277   if(first_recycling != NULL){
278     g_object_unref(first_recycling);
279     g_object_unref(last_recycling);
280   }
281 
282   if(end_recycling != NULL){
283     g_object_unref(end_recycling);
284   }
285 
286   if(next_recycling != NULL){
287     g_object_unref(next_recycling);
288   }
289 }
290 
291 /**
292  * ags_rt_stream_channel_run_new:
293  * @source: the #AgsChannel
294  *
295  * Create a new instance of #AgsRtStreamChannelRun
296  *
297  * Returns: the new #AgsRtStreamChannelRun
298  *
299  * Since: 3.0.0
300  */
301 AgsRtStreamChannelRun*
ags_rt_stream_channel_run_new(AgsChannel * source)302 ags_rt_stream_channel_run_new(AgsChannel *source)
303 {
304   AgsRtStreamChannelRun *rt_stream_channel_run;
305 
306   rt_stream_channel_run = (AgsRtStreamChannelRun *) g_object_new(AGS_TYPE_RT_STREAM_CHANNEL_RUN,
307 								 "source", source,
308 								 NULL);
309 
310   return(rt_stream_channel_run);
311 }
312