1 /* GSequencer - Advanced GTK Sequencer
2  * Copyright (C) 2005-2020 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/ags_acceleration.h>
21 
22 #include <stdlib.h>
23 
24 #include <ags/i18n.h>
25 
26 void ags_acceleration_class_init(AgsAccelerationClass *acceleration);
27 void ags_acceleration_init(AgsAcceleration *acceleration);
28 void ags_acceleration_set_property(GObject *gobject,
29 				   guint prop_id,
30 				   const GValue *value,
31 				   GParamSpec *param_spec);
32 void ags_acceleration_get_property(GObject *gobject,
33 				   guint prop_id,
34 				   GValue *value,
35 				   GParamSpec *param_spec);
36 void ags_acceleration_finalize(GObject *gobject);
37 
38 /**
39  * SECTION:ags_acceleration
40  * @short_description: Acceleration class
41  * @title: AgsAcceleration
42  * @section_id:
43  * @include: ags/audio/ags_acceleration.h
44  *
45  * #AgsAcceleration represents a downhill-grade.
46  */
47 
48 enum{
49   PROP_0,
50   PROP_X,
51   PROP_Y,
52   PROP_ACCELERATION_NAME,
53 };
54 
55 static gpointer ags_acceleration_parent_class = NULL;
56 
57 GType
ags_acceleration_get_type()58 ags_acceleration_get_type()
59 {
60   static volatile gsize g_define_type_id__volatile = 0;
61 
62   if(g_once_init_enter (&g_define_type_id__volatile)){
63     GType ags_type_acceleration = 0;
64 
65     static const GTypeInfo ags_acceleration_info = {
66       sizeof(AgsAccelerationClass),
67       NULL,
68       NULL,
69       (GClassInitFunc) ags_acceleration_class_init,
70       NULL,
71       NULL,
72       sizeof(AgsAcceleration),
73       0,
74       (GInstanceInitFunc) ags_acceleration_init,
75     };
76 
77     ags_type_acceleration = g_type_register_static(G_TYPE_OBJECT,
78 						   "AgsAcceleration",
79 						   &ags_acceleration_info,
80 						   0);
81 
82     g_once_init_leave(&g_define_type_id__volatile, ags_type_acceleration);
83   }
84 
85   return g_define_type_id__volatile;
86 }
87 
88 GType
ags_acceleration_flags_get_type()89 ags_acceleration_flags_get_type()
90 {
91   static volatile gsize g_flags_type_id__volatile;
92 
93   if(g_once_init_enter (&g_flags_type_id__volatile)){
94     static const GFlagsValue values[] = {
95       { AGS_ACCELERATION_DEFAULT_START, "AGS_ACCELERATION_DEFAULT_START", "acceleration-default-start" },
96       { AGS_ACCELERATION_DEFAULT_END, "AGS_ACCELERATION_DEFAULT_END", "acceleration-default-end" },
97       { AGS_ACCELERATION_GUI, "AGS_ACCELERATION_GUI", "acceleration-gui" },
98       { AGS_ACCELERATION_RUNTIME, "AGS_ACCELERATION_RUNTIME", "acceleration-runtime" },
99       { AGS_ACCELERATION_HUMAN_READABLE, "AGS_ACCELERATION_HUMAN_READABLE", "acceleration-human-readable" },
100       { AGS_ACCELERATION_DEFAULT_LENGTH, "AGS_ACCELERATION_DEFAULT_LENGTH", "acceleration-default-length" },
101       { AGS_ACCELERATION_IS_SELECTED, "AGS_ACCELERATION_IS_SELECTED", "acceleration-is-selected" },
102       { 0, NULL, NULL }
103     };
104 
105     GType g_flags_type_id = g_flags_register_static(g_intern_static_string("AgsAccelerationFlags"), values);
106 
107     g_once_init_leave (&g_flags_type_id__volatile, g_flags_type_id);
108   }
109 
110   return g_flags_type_id__volatile;
111 }
112 
113 void
ags_acceleration_class_init(AgsAccelerationClass * acceleration)114 ags_acceleration_class_init(AgsAccelerationClass *acceleration)
115 {
116   GObjectClass *gobject;
117 
118   GParamSpec *param_spec;
119 
120   ags_acceleration_parent_class = g_type_class_peek_parent(acceleration);
121 
122   gobject = (GObjectClass *) acceleration;
123 
124   gobject->set_property = ags_acceleration_set_property;
125   gobject->get_property = ags_acceleration_get_property;
126 
127   gobject->finalize = ags_acceleration_finalize;
128 
129   /* properties */
130   /**
131    * AgsAcceleration:x:
132    *
133    * Acceleration offset x.
134    *
135    * Since: 3.0.0
136    */
137   param_spec = g_param_spec_uint("x",
138 				 i18n_pspec("offset x"),
139 				 i18n_pspec("The x offset"),
140 				 0,
141 				 G_MAXUINT32,
142 				 0,
143 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
144   g_object_class_install_property(gobject,
145 				  PROP_X,
146 				  param_spec);
147 
148   /**
149    * AgsAcceleration:y:
150    *
151    * Acceleration value y.
152    *
153    * Since: 3.0.0
154    */
155   param_spec = g_param_spec_double("y",
156 				   i18n_pspec("offset y"),
157 				   i18n_pspec("The y offset"),
158 				   -1.0 * G_MAXDOUBLE,
159 				   G_MAXDOUBLE,
160 				   0.0,
161 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
162   g_object_class_install_property(gobject,
163 				  PROP_Y,
164 				  param_spec);
165 
166   /**
167    * AgsAcceleration:acceleration-name:
168    *
169    * The acceleration's name.
170    *
171    * Since: 3.0.0
172    */
173   param_spec = g_param_spec_string("acceleration-name",
174 				   i18n_pspec("acceleration name"),
175 				   i18n_pspec("The acceleration's name"),
176 				   NULL,
177 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
178   g_object_class_install_property(gobject,
179 				  PROP_ACCELERATION_NAME,
180 				  param_spec);
181 }
182 
183 void
ags_acceleration_init(AgsAcceleration * acceleration)184 ags_acceleration_init(AgsAcceleration *acceleration)
185 {
186   acceleration->flags = 0;
187 
188   /* acceleration mutex */
189   g_rec_mutex_init(&(acceleration->obj_mutex));
190 
191   /* fields */
192   acceleration->x = 0;
193   acceleration->y = 0.0;
194 
195   acceleration->acceleration_name = NULL;
196 }
197 
198 
199 void
ags_acceleration_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)200 ags_acceleration_set_property(GObject *gobject,
201 			      guint prop_id,
202 			      const GValue *value,
203 			      GParamSpec *param_spec)
204 {
205   AgsAcceleration *acceleration;
206 
207   GRecMutex *acceleration_mutex;
208 
209   acceleration = AGS_ACCELERATION(gobject);
210 
211   /* get acceleration mutex */
212   acceleration_mutex = AGS_ACCELERATION_GET_OBJ_MUTEX(acceleration);
213 
214   switch(prop_id){
215   case PROP_X:
216     {
217       g_rec_mutex_lock(acceleration_mutex);
218 
219       acceleration->x = g_value_get_uint(value);
220 
221       g_rec_mutex_unlock(acceleration_mutex);
222     }
223     break;
224   case PROP_Y:
225     {
226       g_rec_mutex_lock(acceleration_mutex);
227 
228       acceleration->y = g_value_get_double(value);
229 
230       g_rec_mutex_unlock(acceleration_mutex);
231     }
232     break;
233   case PROP_ACCELERATION_NAME:
234     {
235       gchar *acceleration_name;
236 
237       acceleration_name = g_value_get_string(value);
238 
239       g_rec_mutex_lock(acceleration_mutex);
240 
241       if(acceleration_name == acceleration->acceleration_name){
242 	g_rec_mutex_unlock(acceleration_mutex);
243 
244 	return;
245       }
246 
247       if(acceleration->acceleration_name != NULL){
248 	g_free(acceleration->acceleration_name);
249       }
250 
251       acceleration->acceleration_name = g_strdup(acceleration_name);
252 
253       g_rec_mutex_unlock(acceleration_mutex);
254     }
255     break;
256   default:
257     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
258     break;
259   }
260 }
261 
262 void
ags_acceleration_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)263 ags_acceleration_get_property(GObject *gobject,
264 			      guint prop_id,
265 			      GValue *value,
266 			      GParamSpec *param_spec)
267 {
268   AgsAcceleration *acceleration;
269 
270   GRecMutex *acceleration_mutex;
271 
272   acceleration = AGS_ACCELERATION(gobject);
273 
274   /* get acceleration mutex */
275   acceleration_mutex = AGS_ACCELERATION_GET_OBJ_MUTEX(acceleration);
276 
277   switch(prop_id){
278   case PROP_X:
279     {
280       g_rec_mutex_lock(acceleration_mutex);
281 
282       g_value_set_uint(value, acceleration->x);
283 
284       g_rec_mutex_unlock(acceleration_mutex);
285     }
286     break;
287   case PROP_Y:
288     {
289       g_rec_mutex_lock(acceleration_mutex);
290 
291       g_value_set_double(value, acceleration->y);
292 
293       g_rec_mutex_unlock(acceleration_mutex);
294     }
295     break;
296   case PROP_ACCELERATION_NAME:
297     {
298       g_rec_mutex_lock(acceleration_mutex);
299 
300       g_value_set_string(value, acceleration->acceleration_name);
301 
302       g_rec_mutex_unlock(acceleration_mutex);
303     }
304     break;
305   default:
306     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
307     break;
308   }
309 }
310 
311 void
ags_acceleration_finalize(GObject * gobject)312 ags_acceleration_finalize(GObject *gobject)
313 {
314   AgsAcceleration *acceleration;
315 
316   acceleration = AGS_ACCELERATION(gobject);
317 
318   if(acceleration->acceleration_name != NULL){
319     free(acceleration->acceleration_name);
320   }
321 
322   /* call parent */
323   G_OBJECT_CLASS(ags_acceleration_parent_class)->finalize(gobject);
324 }
325 
326 /**
327  * ags_acceleration_get_obj_mutex:
328  * @acceleration: the #AgsAcceleration
329  *
330  * Get object mutex.
331  *
332  * Returns: the #GRecMutex to lock @acceleration
333  *
334  * Since: 3.1.0
335  */
336 GRecMutex*
ags_acceleration_get_obj_mutex(AgsAcceleration * acceleration)337 ags_acceleration_get_obj_mutex(AgsAcceleration *acceleration)
338 {
339   if(!AGS_IS_ACCELERATION(acceleration)){
340     return(NULL);
341   }
342 
343   return(AGS_ACCELERATION_GET_OBJ_MUTEX(acceleration));
344 }
345 
346 /**
347  * ags_acceleration_test_flags:
348  * @acceleration: the #AgsAcceleration
349  * @flags: the flags
350  *
351  * Test @flags to be set on @acceleration.
352  *
353  * Returns: %TRUE if flags are set, else %FALSE
354  *
355  * Since: 3.0.0
356  */
357 gboolean
ags_acceleration_test_flags(AgsAcceleration * acceleration,guint flags)358 ags_acceleration_test_flags(AgsAcceleration *acceleration, guint flags)
359 {
360   gboolean retval;
361 
362   GRecMutex *acceleration_mutex;
363 
364   if(!AGS_IS_ACCELERATION(acceleration)){
365     return(FALSE);
366   }
367 
368   /* get acceleration mutex */
369   acceleration_mutex = AGS_ACCELERATION_GET_OBJ_MUTEX(acceleration);
370 
371   /* test */
372   g_rec_mutex_lock(acceleration_mutex);
373 
374   retval = (flags & (acceleration->flags)) ? TRUE: FALSE;
375 
376   g_rec_mutex_unlock(acceleration_mutex);
377 
378   return(retval);
379 }
380 
381 /**
382  * ags_acceleration_set_flags:
383  * @acceleration: the #AgsAcceleration
384  * @flags: the flags
385  *
386  * Set @flags on @acceleration.
387  *
388  * Since: 3.0.0
389  */
390 void
ags_acceleration_set_flags(AgsAcceleration * acceleration,guint flags)391 ags_acceleration_set_flags(AgsAcceleration *acceleration, guint flags)
392 {
393   GRecMutex *acceleration_mutex;
394 
395   if(!AGS_IS_ACCELERATION(acceleration)){
396     return;
397   }
398 
399   /* get acceleration mutex */
400   acceleration_mutex = AGS_ACCELERATION_GET_OBJ_MUTEX(acceleration);
401 
402   /* set */
403   g_rec_mutex_lock(acceleration_mutex);
404 
405   acceleration->flags |= flags;
406 
407   g_rec_mutex_unlock(acceleration_mutex);
408 }
409 
410 /**
411  * ags_acceleration_unset_flags:
412  * @acceleration: the #AgsAcceleration
413  * @flags: the flags
414  *
415  * Unset @flags on @acceleration.
416  *
417  * Since: 3.0.0
418  */
419 void
ags_acceleration_unset_flags(AgsAcceleration * acceleration,guint flags)420 ags_acceleration_unset_flags(AgsAcceleration *acceleration, guint flags)
421 {
422   GRecMutex *acceleration_mutex;
423 
424   if(!AGS_IS_ACCELERATION(acceleration)){
425     return;
426   }
427 
428   /* get acceleration mutex */
429   acceleration_mutex = AGS_ACCELERATION_GET_OBJ_MUTEX(acceleration);
430 
431   /* unset */
432   g_rec_mutex_lock(acceleration_mutex);
433 
434   acceleration->flags &= (~flags);
435 
436   g_rec_mutex_unlock(acceleration_mutex);
437 }
438 
439 /**
440  * ags_acceleration_sort_func:
441  * @a: an #AgsAcceleration
442  * @b: an other #AgsAcceleration
443  *
444  * Sort accelerations.
445  *
446  * Returns: 0 if equal, -1 if smaller and 1 if bigger offset
447  *
448  * Since: 3.0.0
449  */
450 gint
ags_acceleration_sort_func(gconstpointer a,gconstpointer b)451 ags_acceleration_sort_func(gconstpointer a, gconstpointer b)
452 {
453   guint a_x, b_x;
454 
455   if(a == NULL || b == NULL){
456     return(0);
457   }
458 
459   g_object_get(a,
460 	       "x", &a_x,
461 	       NULL);
462 
463   g_object_get(b,
464 	       "x", &b_x,
465 	       NULL);
466 
467   if(a_x == b_x){
468     return(0);
469   }
470 
471   if(a_x < b_x){
472     return(-1);
473   }else{
474     return(1);
475   }
476 }
477 
478 /**
479  * ags_acceleration_get_x:
480  * @acceleration: the #AgsAcceleration
481  *
482  * Gets x.
483  *
484  * Returns: the x
485  *
486  * Since: 3.1.0
487  */
488 guint
ags_acceleration_get_x(AgsAcceleration * acceleration)489 ags_acceleration_get_x(AgsAcceleration *acceleration)
490 {
491   guint x;
492 
493   if(!AGS_IS_ACCELERATION(acceleration)){
494     return(0);
495   }
496 
497   g_object_get(acceleration,
498 	       "x", &x,
499 	       NULL);
500 
501   return(x);
502 }
503 
504 /**
505  * ags_acceleration_set_x:
506  * @acceleration: the #AgsAcceleration
507  * @x: the x
508  *
509  * Sets x.
510  *
511  * Since: 3.1.0
512  */
513 void
ags_acceleration_set_x(AgsAcceleration * acceleration,guint x)514 ags_acceleration_set_x(AgsAcceleration *acceleration, guint x)
515 {
516   if(!AGS_IS_ACCELERATION(acceleration)){
517     return;
518   }
519 
520   g_object_set(acceleration,
521 	       "x", x,
522 	       NULL);
523 }
524 
525 /**
526  * ags_acceleration_get_y:
527  * @acceleration: the #AgsAcceleration
528  *
529  * Gets y.
530  *
531  * Returns: the y
532  *
533  * Since: 3.1.0
534  */
535 gdouble
ags_acceleration_get_y(AgsAcceleration * acceleration)536 ags_acceleration_get_y(AgsAcceleration *acceleration)
537 {
538   gdouble y;
539 
540   if(!AGS_IS_ACCELERATION(acceleration)){
541     return(0);
542   }
543 
544   g_object_get(acceleration,
545 	       "y", &y,
546 	       NULL);
547 
548   return(y);
549 }
550 
551 /**
552  * ags_acceleration_set_y:
553  * @acceleration: the #AgsAcceleration
554  * @y: the y
555  *
556  * Sets y.
557  *
558  * Since: 3.1.0
559  */
560 void
ags_acceleration_set_y(AgsAcceleration * acceleration,gdouble y)561 ags_acceleration_set_y(AgsAcceleration *acceleration, gdouble y)
562 {
563   if(!AGS_IS_ACCELERATION(acceleration)){
564     return;
565   }
566 
567   g_object_set(acceleration,
568 	       "y", y,
569 	       NULL);
570 }
571 
572 /**
573  * ags_acceleration_duplicate:
574  * @acceleration: an #AgsAcceleration
575  *
576  * Duplicate a acceleration.
577  *
578  * Returns: (transfer full): the duplicated #AgsAcceleration.
579  *
580  * Since: 3.0.0
581  */
582 AgsAcceleration*
ags_acceleration_duplicate(AgsAcceleration * acceleration)583 ags_acceleration_duplicate(AgsAcceleration *acceleration)
584 {
585   AgsAcceleration *acceleration_copy;
586 
587   GRecMutex *acceleration_mutex;
588 
589   if(!AGS_IS_ACCELERATION(acceleration)){
590     return(NULL);
591   }
592 
593   /* get acceleration mutex */
594   acceleration_mutex = AGS_ACCELERATION_GET_OBJ_MUTEX(acceleration);
595 
596   /* instantiate acceleration */
597   acceleration_copy = ags_acceleration_new();
598 
599   acceleration_copy->flags = 0;
600 
601   g_rec_mutex_lock(acceleration_mutex);
602 
603   acceleration_copy->x = acceleration->x;
604   acceleration_copy->y = acceleration->y;
605 
606   acceleration_copy->acceleration_name = g_strdup(acceleration->acceleration_name);
607 
608   g_rec_mutex_unlock(acceleration_mutex);
609 
610   return(acceleration_copy);
611 }
612 
613 /**
614  * ags_acceleration_new:
615  *
616  * Creates a new instance of #AgsAcceleration
617  *
618  * Returns: the new #AgsAcceleration
619  *
620  * Since: 3.0.0
621  */
622 AgsAcceleration*
ags_acceleration_new()623 ags_acceleration_new()
624 {
625   AgsAcceleration *acceleration;
626 
627   acceleration = (AgsAcceleration *) g_object_new(AGS_TYPE_ACCELERATION,
628 						  NULL);
629 
630   return(acceleration);
631 }
632