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