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_volume_audio_signal.h>
21
22 #include <ags/audio/ags_input.h>
23 #include <ags/audio/ags_port.h>
24 #include <ags/audio/ags_recall_channel_run.h>
25 #include <ags/audio/ags_audio_buffer_util.h>
26
27 #include <ags/audio/recall/ags_volume_channel.h>
28 #include <ags/audio/recall/ags_volume_channel_run.h>
29 #include <ags/audio/recall/ags_volume_recycling.h>
30
31 void ags_volume_audio_signal_class_init(AgsVolumeAudioSignalClass *volume_audio_signal);
32 void ags_volume_audio_signal_init(AgsVolumeAudioSignal *volume_audio_signal);
33 void ags_volume_audio_signal_finalize(GObject *gobject);
34
35 void ags_volume_audio_signal_run_inter(AgsRecall *recall);
36
37 /**
38 * SECTION:ags_volume_audio_signal
39 * @short_description: volumes audio signal
40 * @title: AgsVolumeAudioSignal
41 * @section_id:
42 * @include: ags/audio/recall/ags_volume_audio_signal.h
43 *
44 * The #AgsVolumeAudioSignal class volumes the audio signal.
45 */
46
47 static gpointer ags_volume_audio_signal_parent_class = NULL;
48
49 GType
ags_volume_audio_signal_get_type()50 ags_volume_audio_signal_get_type()
51 {
52 static volatile gsize g_define_type_id__volatile = 0;
53
54 if(g_once_init_enter (&g_define_type_id__volatile)){
55 GType ags_type_volume_audio_signal = 0;
56
57 static const GTypeInfo ags_volume_audio_signal_info = {
58 sizeof (AgsVolumeAudioSignalClass),
59 NULL, /* base_init */
60 NULL, /* base_finalize */
61 (GClassInitFunc) ags_volume_audio_signal_class_init,
62 NULL, /* class_finalize */
63 NULL, /* class_data */
64 sizeof (AgsVolumeAudioSignal),
65 0, /* n_preallocs */
66 (GInstanceInitFunc) ags_volume_audio_signal_init,
67 };
68
69 ags_type_volume_audio_signal = g_type_register_static(AGS_TYPE_RECALL_AUDIO_SIGNAL,
70 "AgsVolumeAudioSignal",
71 &ags_volume_audio_signal_info,
72 0);
73
74 g_once_init_leave(&g_define_type_id__volatile, ags_type_volume_audio_signal);
75 }
76
77 return g_define_type_id__volatile;
78 }
79
80 void
ags_volume_audio_signal_class_init(AgsVolumeAudioSignalClass * volume_audio_signal)81 ags_volume_audio_signal_class_init(AgsVolumeAudioSignalClass *volume_audio_signal)
82 {
83 GObjectClass *gobject;
84 AgsRecallClass *recall;
85
86 ags_volume_audio_signal_parent_class = g_type_class_peek_parent(volume_audio_signal);
87
88 /* GObjectClass */
89 gobject = (GObjectClass *) volume_audio_signal;
90
91 gobject->finalize = ags_volume_audio_signal_finalize;
92
93 /* AgsRecallClass */
94 recall = (AgsRecallClass *) volume_audio_signal;
95
96 recall->run_inter = ags_volume_audio_signal_run_inter;
97 }
98
99 void
ags_volume_audio_signal_init(AgsVolumeAudioSignal * volume_audio_signal)100 ags_volume_audio_signal_init(AgsVolumeAudioSignal *volume_audio_signal)
101 {
102 AGS_RECALL(volume_audio_signal)->name = "ags-volume";
103 AGS_RECALL(volume_audio_signal)->version = AGS_RECALL_DEFAULT_VERSION;
104 AGS_RECALL(volume_audio_signal)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
105 AGS_RECALL(volume_audio_signal)->xml_type = "ags-volume-audio-signal";
106 AGS_RECALL(volume_audio_signal)->port = NULL;
107 }
108
109 void
ags_volume_audio_signal_finalize(GObject * gobject)110 ags_volume_audio_signal_finalize(GObject *gobject)
111 {
112 /* call parent */
113 G_OBJECT_CLASS(ags_volume_audio_signal_parent_class)->finalize(gobject);
114 }
115
116 void
ags_volume_audio_signal_run_inter(AgsRecall * recall)117 ags_volume_audio_signal_run_inter(AgsRecall *recall)
118 {
119 AgsAudioSignal *source;
120 AgsVolumeAudioSignal *volume_audio_signal;
121 AgsRecallID *recall_id;
122 AgsRecyclingContext *recycling_context, *parent_recycling_context;
123
124 GList *start_note;
125
126 void (*parent_class_run_inter)(AgsRecall *recall);
127
128 volume_audio_signal = (AgsVolumeAudioSignal *) recall;
129
130 /* get parent class */
131 parent_class_run_inter = AGS_RECALL_CLASS(ags_volume_audio_signal_parent_class)->run_inter;
132
133 /* call parent */
134 parent_class_run_inter(recall);
135
136 g_object_get(volume_audio_signal,
137 "source", &source,
138 "recall-id", &recall_id,
139 NULL);
140
141 g_object_get(recall_id,
142 "recycling-context", &recycling_context,
143 NULL);
144
145 g_object_get(recycling_context,
146 "parent", &parent_recycling_context,
147 NULL);
148
149 g_object_get(source,
150 "note", &start_note,
151 NULL);
152
153 if(ags_recall_global_get_rt_safe() &&
154 parent_recycling_context != NULL &&
155 start_note == NULL){
156 g_object_unref(source);
157
158 g_object_unref(recall_id);
159
160 g_object_unref(recycling_context);
161 g_object_unref(parent_recycling_context);
162
163 return;
164 }
165
166 if(source->stream_current != NULL){
167 AgsPort *port;
168 AgsVolumeChannel *volume_channel;
169 AgsVolumeChannelRun *volume_channel_run;
170 AgsVolumeRecycling *volume_recycling;
171
172 void *buffer;
173
174 gdouble volume;
175 guint buffer_size;
176 guint format;
177 guint limit;
178 guint i;
179
180 GValue value = {0,};
181
182 g_object_get(volume_audio_signal,
183 "parent", &volume_recycling,
184 NULL);
185
186 g_object_get(volume_recycling,
187 "parent", &volume_channel_run,
188 NULL);
189
190 g_object_get(volume_channel_run,
191 "recall-channel", &volume_channel,
192 NULL);
193
194 g_object_get(source,
195 "buffer-size", &buffer_size,
196 "format", &format,
197 NULL);
198
199 buffer = source->stream_current->data;
200
201 g_object_get(volume_channel,
202 "volume", &port,
203 NULL);
204
205 g_value_init(&value,
206 G_TYPE_FLOAT);
207
208 ags_port_safe_read(port,
209 &value);
210
211 volume = g_value_get_float(&value);
212
213 g_value_unset(&value);
214
215 g_object_unref(port);
216
217 ags_audio_buffer_util_volume(buffer, 1,
218 ags_audio_buffer_util_format_from_soundcard(format),
219 buffer_size,
220 volume);
221
222 g_object_unref(volume_recycling);
223
224 g_object_unref(volume_channel_run);
225 g_object_unref(volume_channel);
226 }else{
227 ags_recall_done(recall);
228 }
229
230 /* unref */
231 g_object_unref(source);
232
233 g_object_unref(recall_id);
234
235 g_object_unref(recycling_context);
236
237 if(parent_recycling_context != NULL){
238 g_object_unref(parent_recycling_context);
239 }
240
241 g_list_free_full(start_note,
242 g_object_unref);
243 }
244
245 /**
246 * ags_volume_audio_signal_new:
247 * @source: the #AgsAudioSignal
248 *
249 * Create a new instance of #AgsVolumeAudioSignal
250 *
251 * Returns: the new #AgsVolumeAudioSignal
252 *
253 * Since: 3.0.0
254 */
255 AgsVolumeAudioSignal*
ags_volume_audio_signal_new(AgsAudioSignal * source)256 ags_volume_audio_signal_new(AgsAudioSignal *source)
257 {
258 AgsVolumeAudioSignal *volume_audio_signal;
259
260 volume_audio_signal = (AgsVolumeAudioSignal *) g_object_new(AGS_TYPE_VOLUME_AUDIO_SIGNAL,
261 "source", source,
262 NULL);
263
264 return(volume_audio_signal);
265 }
266