+ /* Get the volume levels as GValues */
+ GValue current_volume = { 0 };
+ GValue target_volume = { 0 };
+ g_value_init(¤t_volume, G_TYPE_DOUBLE);
+ g_value_init(&target_volume, G_TYPE_DOUBLE);
+ g_object_get_property(G_OBJECT(chan->filter), "volume", ¤t_volume);
+ g_value_set_double(&target_volume, volume);
+
+ /* Make a controller for the volume */
+ GstController *controller = gst_object_control_properties(G_OBJECT(chan->filter), "volume", NULL);
+ if(controller == NULL) {
+ WARNING(_("Couldn't get controller for volume change"));
+ goto fail;
+ }
+ GstInterpolationControlSource *csource = gst_interpolation_control_source_new();
+ gst_interpolation_control_source_set_interpolation_mode(csource, GST_INTERPOLATE_LINEAR);
+ if(!gst_controller_set_control_source(controller, "volume", GST_CONTROL_SOURCE(csource))) {
+ WARNING(_("Couldn't set control source for volume change"));
+ goto fail;
+ }
+
+ /* Get the current time on the pipeline */
+ GstClock *clock = gst_pipeline_get_clock(GST_PIPELINE(chan->pipeline));
+ GstClockTime current = gst_clock_get_time(clock);
+ g_object_unref(clock);
+
+ if(!gst_interpolation_control_source_set(csource, current, ¤t_volume)) {
+ WARNING(_("Couldn't program volume change"));
+ goto fail;
+ }
+ if(!gst_interpolation_control_source_set(csource, current + duration * GST_MSECOND, &target_volume)) {
+ WARNING(_("Couldn't program volume change"));
+ goto fail;
+ }
+
+ /* TODO: SET UP NOTIFICATION */
+
+ return;
+
+fail:
+ /* Changing the volume dynamically didn't work; just do it immediately. */
+ channel_set_volume_immediately(chan, volume, notify);
+#endif