volume: Expose the `volume-full-range` as another property
authorThibault Saunier <tsaunier@igalia.com>
Mon, 26 Feb 2024 15:38:55 +0000 (12:38 -0300)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Tue, 27 Feb 2024 12:33:44 +0000 (12:33 +0000)
In https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5063
the range of volume value has changed which breaks backward compatibility
when  using a GstDirectControlBinding which is not acceptable. To avoid
breaking compatibility add the feature of allowing the full range  using
another property with the full range. When using that full range, the
value of the `volume` property might end up being out of its valid
range but we do not really have a good solution for that.

Fixes: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3257
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6222>

subprojects/gst-plugins-base/docs/plugins/gst_plugins_cache.json
subprojects/gst-plugins-base/gst/volume/gstvolume.c
subprojects/gst-plugins-base/tests/check/elements/volume.c

index 571c0049117c0ac0f72baeb870591286adfecc32..cc5d060ab265782e18becfbf91ee7d485c7214de 100644 (file)
                         "construct-only": false,
                         "controllable": true,
                         "default": "1",
+                        "max": "10",
+                        "min": "0",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gdouble",
+                        "writable": true
+                    },
+                    "volume-full-range": {
+                        "blurb": "volume factor with a full range of values, 1.0=100%%",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": true,
+                        "default": "1",
                         "max": "1.79769e+308",
                         "min": "0",
                         "mutable": "null",
index a0427479b53ff1b17daea28d87d8a2789c3fc1e0..1e0e6c4763eecf8f5eb1936560538d08877d6818 100644 (file)
@@ -96,7 +96,8 @@ enum
 {
   PROP_0,
   PROP_MUTE,
-  PROP_VOLUME
+  PROP_VOLUME,
+  PROP_VOLUME_FULL_RANGE
 };
 
 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
@@ -380,13 +381,26 @@ gst_volume_class_init (GstVolumeClass * klass)
           DEFAULT_PROP_MUTE,
           G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
 
-  /* The volume factor is a range from 0.0 to G_MAXDOUBLE.
-   * The choice of G_MAXDOUBLE is somewhat arbitrary,
-   * but it should be *very* inclusive, e.g. gain of +48 dB is very reasonable.
+  /**
+   * GstVolume:volume-full-range:
+   *
+   * The volume-full-range factor is a range from 0.0 to G_MAXDOUBLE so
+   * it is *very* inclusive, e.g. gain of +48 dB is very reasonable. This
+   * property allows setting higher value than the #GstVolume:volume property.
+   *
+   * Since: 1.24
    */
+  /* This property has been exposed as another property to keep the backward compatibility
+   * when using #GstDirectControlBinding with GstDirectControlBinding:absolute set to FALSE. */
+  g_object_class_install_property (gobject_class, PROP_VOLUME_FULL_RANGE,
+      g_param_spec_double ("volume-full-range", "Volume",
+          "volume factor with a full range of values, 1.0=100%", 0.0,
+          G_MAXDOUBLE, DEFAULT_PROP_VOLUME,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
+
   g_object_class_install_property (gobject_class, PROP_VOLUME,
       g_param_spec_double ("volume", "Volume", "volume factor, 1.0=100%",
-          0.0, G_MAXDOUBLE, DEFAULT_PROP_VOLUME,
+          0.0, 10.0, DEFAULT_PROP_VOLUME,
           G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
 
   gst_element_class_set_static_metadata (element_class, "Volume",
@@ -981,6 +995,11 @@ volume_set_property (GObject * object, guint prop_id, const GValue * value,
       self->volume = g_value_get_double (value);
       GST_OBJECT_UNLOCK (self);
       break;
+    case PROP_VOLUME_FULL_RANGE:
+      GST_OBJECT_LOCK (self);
+      self->volume = g_value_get_double (value);
+      GST_OBJECT_UNLOCK (self);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1000,6 +1019,17 @@ volume_get_property (GObject * object, guint prop_id, GValue * value,
       GST_OBJECT_UNLOCK (self);
       break;
     case PROP_VOLUME:
+      GST_OBJECT_LOCK (self);
+      if (self->volume > 10.0) {
+        GST_WARNING_OBJECT (object,
+            "Volume is greater than its max value 10.0, reporting as 10.0");
+        g_value_set_double (value, 10.0);
+      } else {
+        g_value_set_double (value, self->volume);
+      }
+      GST_OBJECT_UNLOCK (self);
+      break;
+    case PROP_VOLUME_FULL_RANGE:
       GST_OBJECT_LOCK (self);
       g_value_set_double (value, self->volume);
       GST_OBJECT_UNLOCK (self);
index 1da0aa566365ec463d02e4e1307ebea7dd24a52e..303162ed319c76c52523ae7682018ebabb583728 100644 (file)
@@ -385,7 +385,7 @@ GST_START_TEST (test_fifteen_s8)
 
   volume = setup_volume ();
   // Maximal volume that is supported by the fixed point multiplication.
-  g_object_set (G_OBJECT (volume), "volume", 15.0, NULL);
+  g_object_set (G_OBJECT (volume), "volume-full-range", 15.0, NULL);
   fail_unless (gst_element_set_state (volume, GST_STATE_PLAYING) ==
       GST_STATE_CHANGE_SUCCESS, "could not set to playing");
 
@@ -436,7 +436,7 @@ GST_START_TEST (test_sixteen_s8)
 
   volume = setup_volume ();
   // No longer using fixed point multiplication.
-  g_object_set (G_OBJECT (volume), "volume", 16.0, NULL);
+  g_object_set (G_OBJECT (volume), "volume-full-range", 16.0, NULL);
   fail_unless (gst_element_set_state (volume, GST_STATE_PLAYING) ==
       GST_STATE_CHANGE_SUCCESS, "could not set to playing");
 
@@ -487,7 +487,7 @@ GST_START_TEST (test_max_s8)
 
   volume = setup_volume ();
   // No longer using fixed point multiplication.
-  g_object_set (G_OBJECT (volume), "volume", G_MAXDOUBLE, NULL);
+  g_object_set (G_OBJECT (volume), "volume-full-range", G_MAXDOUBLE, NULL);
   fail_unless (gst_element_set_state (volume, GST_STATE_PLAYING) ==
       GST_STATE_CHANGE_SUCCESS, "could not set to playing");
 
@@ -771,7 +771,7 @@ GST_START_TEST (test_fifteen_s16)
   GstMapInfo map;
 
   volume = setup_volume ();
-  g_object_set (G_OBJECT (volume), "volume", 15.0, NULL);
+  g_object_set (G_OBJECT (volume), "volume-full-range", 15.0, NULL);
   fail_unless (gst_element_set_state (volume, GST_STATE_PLAYING) ==
       GST_STATE_CHANGE_SUCCESS, "could not set to playing");
 
@@ -821,7 +821,7 @@ GST_START_TEST (test_sixteen_s16)
   GstMapInfo map;
 
   volume = setup_volume ();
-  g_object_set (G_OBJECT (volume), "volume", 16.0, NULL);
+  g_object_set (G_OBJECT (volume), "volume-full-range", 16.0, NULL);
   fail_unless (gst_element_set_state (volume, GST_STATE_PLAYING) ==
       GST_STATE_CHANGE_SUCCESS, "could not set to playing");
 
@@ -871,7 +871,7 @@ GST_START_TEST (test_max_s16)
   GstMapInfo map;
 
   volume = setup_volume ();
-  g_object_set (G_OBJECT (volume), "volume", G_MAXDOUBLE, NULL);
+  g_object_set (G_OBJECT (volume), "volume-full-range", G_MAXDOUBLE, NULL);
   fail_unless (gst_element_set_state (volume, GST_STATE_PLAYING) ==
       GST_STATE_CHANGE_SUCCESS, "could not set to playing");
 
@@ -1200,7 +1200,7 @@ GST_START_TEST (test_fifteen_s24)
   write_unaligned_u24 (in + 9, in_32[3]);
 
   volume = setup_volume ();
-  g_object_set (G_OBJECT (volume), "volume", 15.0, NULL);
+  g_object_set (G_OBJECT (volume), "volume-full-range", 15.0, NULL);
   fail_unless (gst_element_set_state (volume, GST_STATE_PLAYING) ==
       GST_STATE_CHANGE_SUCCESS, "could not set to playing");
 
@@ -1262,7 +1262,7 @@ GST_START_TEST (test_sixteen_s24)
   write_unaligned_u24 (in + 9, in_32[3]);
 
   volume = setup_volume ();
-  g_object_set (G_OBJECT (volume), "volume", 16.0, NULL);
+  g_object_set (G_OBJECT (volume), "volume-full-range", 16.0, NULL);
   fail_unless (gst_element_set_state (volume, GST_STATE_PLAYING) ==
       GST_STATE_CHANGE_SUCCESS, "could not set to playing");
 
@@ -1324,7 +1324,7 @@ GST_START_TEST (test_4095_s24)
   write_unaligned_u24 (in + 9, in_32[3]);
 
   volume = setup_volume ();
-  g_object_set (G_OBJECT (volume), "volume", 4095.0, NULL);
+  g_object_set (G_OBJECT (volume), "volume-full-range", 4095.0, NULL);
   fail_unless (gst_element_set_state (volume, GST_STATE_PLAYING) ==
       GST_STATE_CHANGE_SUCCESS, "could not set to playing");
 
@@ -1386,7 +1386,7 @@ GST_START_TEST (test_4096_s24)
   write_unaligned_u24 (in + 9, in_32[3]);
 
   volume = setup_volume ();
-  g_object_set (G_OBJECT (volume), "volume", 4096.0, NULL);
+  g_object_set (G_OBJECT (volume), "volume-full-range", 4096.0, NULL);
   fail_unless (gst_element_set_state (volume, GST_STATE_PLAYING) ==
       GST_STATE_CHANGE_SUCCESS, "could not set to playing");
 
@@ -1448,7 +1448,7 @@ GST_START_TEST (test_max_s24)
   write_unaligned_u24 (in + 9, in_32[3]);
 
   volume = setup_volume ();
-  g_object_set (G_OBJECT (volume), "volume", G_MAXDOUBLE, NULL);
+  g_object_set (G_OBJECT (volume), "volume-full-range", G_MAXDOUBLE, NULL);
   fail_unless (gst_element_set_state (volume, GST_STATE_PLAYING) ==
       GST_STATE_CHANGE_SUCCESS, "could not set to playing");
 
@@ -1746,7 +1746,7 @@ GST_START_TEST (test_fifteen_s32)
   GstMapInfo map;
 
   volume = setup_volume ();
-  g_object_set (G_OBJECT (volume), "volume", 15.0, NULL);
+  g_object_set (G_OBJECT (volume), "volume-full-range", 15.0, NULL);
   fail_unless (gst_element_set_state (volume, GST_STATE_PLAYING) ==
       GST_STATE_CHANGE_SUCCESS, "could not set to playing");
 
@@ -1796,7 +1796,7 @@ GST_START_TEST (test_sixteen_s32)
   GstMapInfo map;
 
   volume = setup_volume ();
-  g_object_set (G_OBJECT (volume), "volume", 16.0, NULL);
+  g_object_set (G_OBJECT (volume), "volume-full-range", 16.0, NULL);
   fail_unless (gst_element_set_state (volume, GST_STATE_PLAYING) ==
       GST_STATE_CHANGE_SUCCESS, "could not set to playing");
 
@@ -1846,7 +1846,7 @@ GST_START_TEST (test_max_s32)
   GstMapInfo map;
 
   volume = setup_volume ();
-  g_object_set (G_OBJECT (volume), "volume", G_MAXDOUBLE, NULL);
+  g_object_set (G_OBJECT (volume), "volume-full-range", G_MAXDOUBLE, NULL);
   fail_unless (gst_element_set_state (volume, GST_STATE_PLAYING) ==
       GST_STATE_CHANGE_SUCCESS, "could not set to playing");
 
@@ -2135,7 +2135,7 @@ GST_START_TEST (test_fifteen_f32)
   GstMapInfo map;
 
   volume = setup_volume ();
-  g_object_set (G_OBJECT (volume), "volume", 15.0, NULL);
+  g_object_set (G_OBJECT (volume), "volume-full-range", 15.0, NULL);
   fail_unless (gst_element_set_state (volume, GST_STATE_PLAYING) ==
       GST_STATE_CHANGE_SUCCESS, "could not set to playing");
 
@@ -2188,7 +2188,7 @@ GST_START_TEST (test_sixteen_f32)
   GstMapInfo map;
 
   volume = setup_volume ();
-  g_object_set (G_OBJECT (volume), "volume", 16.0, NULL);
+  g_object_set (G_OBJECT (volume), "volume-full-range", 16.0, NULL);
   fail_unless (gst_element_set_state (volume, GST_STATE_PLAYING) ==
       GST_STATE_CHANGE_SUCCESS, "could not set to playing");
 
@@ -2243,7 +2243,7 @@ GST_START_TEST (test_max_f32)
   GstMapInfo map;
 
   volume = setup_volume ();
-  g_object_set (G_OBJECT (volume), "volume", G_MAXDOUBLE, NULL);
+  g_object_set (G_OBJECT (volume), "volume-full-range", G_MAXDOUBLE, NULL);
   fail_unless (gst_element_set_state (volume, GST_STATE_PLAYING) ==
       GST_STATE_CHANGE_SUCCESS, "could not set to playing");
 
@@ -2536,7 +2536,7 @@ GST_START_TEST (test_fifteen_f64)
   GstMapInfo map;
 
   volume = setup_volume ();
-  g_object_set (G_OBJECT (volume), "volume", 15.0, NULL);
+  g_object_set (G_OBJECT (volume), "volume-full-range", 15.0, NULL);
   fail_unless (gst_element_set_state (volume, GST_STATE_PLAYING) ==
       GST_STATE_CHANGE_SUCCESS, "could not set to playing");
 
@@ -2589,7 +2589,7 @@ GST_START_TEST (test_sixteen_f64)
   GstMapInfo map;
 
   volume = setup_volume ();
-  g_object_set (G_OBJECT (volume), "volume", 16.0, NULL);
+  g_object_set (G_OBJECT (volume), "volume-full-range", 16.0, NULL);
   fail_unless (gst_element_set_state (volume, GST_STATE_PLAYING) ==
       GST_STATE_CHANGE_SUCCESS, "could not set to playing");
 
@@ -2644,7 +2644,7 @@ GST_START_TEST (test_max_f64)
   GstMapInfo map;
 
   volume = setup_volume ();
-  g_object_set (G_OBJECT (volume), "volume", G_MAXDOUBLE, NULL);
+  g_object_set (G_OBJECT (volume), "volume-full-range", G_MAXDOUBLE, NULL);
   fail_unless (gst_element_set_state (volume, GST_STATE_PLAYING) ==
       GST_STATE_CHANGE_SUCCESS, "could not set to playing");