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