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_loop_channel.h>
21
22 #include <math.h>
23
24 void ags_loop_channel_class_init(AgsLoopChannelClass *loop_channel);
25 void ags_loop_channel_init(AgsLoopChannel *loop_channel);
26 void ags_loop_channel_set_property(GObject *gobject,
27 guint prop_id,
28 const GValue *value,
29 GParamSpec *param_spec);
30 void ags_loop_channel_get_property(GObject *gobject,
31 guint prop_id,
32 GValue *value,
33 GParamSpec *param_spec);
34 void ags_loop_channel_dispose(GObject *gobject);
35 void ags_loop_channel_finalize(GObject *gobject);
36
37 /**
38 * SECTION:ags_loop_channel
39 * @short_description: loops channel
40 * @title: AgsLoopChannel
41 * @section_id:
42 * @include: ags/audio/recall/ags_loop_channel.h
43 *
44 * The #AgsLoopChannel class provides ports to the effect processor.
45 */
46
47 static gpointer ags_loop_channel_parent_class = NULL;
48
49 enum{
50 PROP_0,
51 PROP_DELAY_AUDIO,
52 };
53
54 GType
ags_loop_channel_get_type()55 ags_loop_channel_get_type()
56 {
57 static volatile gsize g_define_type_id__volatile = 0;
58
59 if(g_once_init_enter (&g_define_type_id__volatile)){
60 GType ags_type_loop_channel = 0;
61
62 static const GTypeInfo ags_loop_channel_info = {
63 sizeof (AgsLoopChannelClass),
64 NULL, /* base_init */
65 NULL, /* base_finalize */
66 (GClassInitFunc) ags_loop_channel_class_init,
67 NULL, /* class_finalize */
68 NULL, /* class_data */
69 sizeof (AgsLoopChannel),
70 0, /* n_preallocs */
71 (GInstanceInitFunc) ags_loop_channel_init,
72 };
73
74 ags_type_loop_channel = g_type_register_static(AGS_TYPE_RECALL_CHANNEL,
75 "AgsLoopChannel",
76 &ags_loop_channel_info,
77 0);
78
79 g_once_init_leave(&g_define_type_id__volatile, ags_type_loop_channel);
80 }
81
82 return g_define_type_id__volatile;
83 }
84
85 void
ags_loop_channel_class_init(AgsLoopChannelClass * loop_channel)86 ags_loop_channel_class_init(AgsLoopChannelClass *loop_channel)
87 {
88 GObjectClass *gobject;
89 AgsRecallClass *recall;
90
91 GParamSpec *param_spec;
92
93 ags_loop_channel_parent_class = g_type_class_peek_parent(loop_channel);
94
95 /* GObjectClass */
96 gobject = (GObjectClass *) loop_channel;
97
98 gobject->set_property = ags_loop_channel_set_property;
99 gobject->get_property = ags_loop_channel_get_property;
100
101 gobject->dispose = ags_loop_channel_dispose;
102 gobject->finalize = ags_loop_channel_finalize;
103
104 /* properties */
105 /**
106 * AgsLoopChannel:delay-audio:
107 *
108 * The assigned #AgsDelayAudio.
109 *
110 * Since: 3.0.0
111 */
112 param_spec = g_param_spec_object("delay-audio",
113 "assigned delay audio",
114 "The delay audio it is assigned with",
115 AGS_TYPE_DELAY_AUDIO,
116 G_PARAM_READABLE | G_PARAM_WRITABLE);
117 g_object_class_install_property(gobject,
118 PROP_DELAY_AUDIO,
119 param_spec);
120 }
121
122 void
ags_loop_channel_init(AgsLoopChannel * loop_channel)123 ags_loop_channel_init(AgsLoopChannel *loop_channel)
124 {
125 AGS_RECALL(loop_channel)->name = "ags-loop";
126 AGS_RECALL(loop_channel)->version = AGS_RECALL_DEFAULT_VERSION;
127 AGS_RECALL(loop_channel)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
128 AGS_RECALL(loop_channel)->xml_type = "ags-loop-channel";
129
130 loop_channel->delay_audio = NULL;
131 }
132
133 void
ags_loop_channel_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)134 ags_loop_channel_set_property(GObject *gobject,
135 guint prop_id,
136 const GValue *value,
137 GParamSpec *param_spec)
138 {
139 AgsLoopChannel *loop_channel;
140
141 GRecMutex *recall_mutex;
142
143 loop_channel = AGS_LOOP_CHANNEL(gobject);
144
145 /* get recall mutex */
146 recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(loop_channel);
147
148 switch(prop_id){
149 case PROP_DELAY_AUDIO:
150 {
151 AgsDelayAudio *delay_audio;
152
153 delay_audio = (AgsDelayAudio *) g_value_get_object(value);
154
155 g_rec_mutex_lock(recall_mutex);
156
157 if(loop_channel->delay_audio == delay_audio){
158 g_rec_mutex_unlock(recall_mutex);
159
160 return;
161 }
162
163 if(loop_channel->delay_audio != NULL){
164 g_object_unref(G_OBJECT(loop_channel->delay_audio));
165 }
166
167 if(delay_audio != NULL){
168 g_object_ref(G_OBJECT(delay_audio));
169 }
170
171 loop_channel->delay_audio = delay_audio;
172
173 g_rec_mutex_unlock(recall_mutex);
174 }
175 break;
176 default:
177 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
178 break;
179 }
180 }
181
182 void
ags_loop_channel_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)183 ags_loop_channel_get_property(GObject *gobject,
184 guint prop_id,
185 GValue *value,
186 GParamSpec *param_spec)
187 {
188 AgsLoopChannel *loop_channel;
189
190 GRecMutex *recall_mutex;
191
192 loop_channel = AGS_LOOP_CHANNEL(gobject);
193
194 /* get recall mutex */
195 recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(loop_channel);
196
197 switch(prop_id){
198 case PROP_DELAY_AUDIO:
199 {
200 g_rec_mutex_lock(recall_mutex);
201
202 g_value_set_object(value, loop_channel->delay_audio);
203
204 g_rec_mutex_unlock(recall_mutex);
205 }
206 break;
207 default:
208 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
209 break;
210 }
211 }
212
213 void
ags_loop_channel_dispose(GObject * gobject)214 ags_loop_channel_dispose(GObject *gobject)
215 {
216 AgsLoopChannel *loop_channel;
217
218 loop_channel = AGS_LOOP_CHANNEL(gobject);
219
220 /* delay audio */
221 if(loop_channel->delay_audio != NULL){
222 g_object_unref(G_OBJECT(loop_channel->delay_audio));
223
224 loop_channel->delay_audio = NULL;
225 }
226
227 /* call parent */
228 G_OBJECT_CLASS(ags_loop_channel_parent_class)->dispose(gobject);
229 }
230
231 void
ags_loop_channel_finalize(GObject * gobject)232 ags_loop_channel_finalize(GObject *gobject)
233 {
234 AgsLoopChannel *loop_channel;
235
236 loop_channel = AGS_LOOP_CHANNEL(gobject);
237
238 /* delay audio */
239 if(loop_channel->delay_audio != NULL){
240 g_object_unref(G_OBJECT(loop_channel->delay_audio));
241 }
242
243 /* call parent */
244 G_OBJECT_CLASS(ags_loop_channel_parent_class)->finalize(gobject);
245 }
246
247 /**
248 * ags_loop_channel_new:
249 * @source: the #AgsChannel
250 *
251 * Create a new instance of #AgsLoopChannel
252 *
253 * Returns: the new #AgsLoopChannel
254 *
255 * Since: 3.0.0
256 */
257 AgsLoopChannel*
ags_loop_channel_new(AgsChannel * source)258 ags_loop_channel_new(AgsChannel *source)
259 {
260 AgsLoopChannel *loop_channel;
261
262 loop_channel = (AgsLoopChannel *) g_object_new(AGS_TYPE_LOOP_CHANNEL,
263 "source", source,
264 NULL);
265
266 return(loop_channel);
267 }
268