GstControlBinding... doesn't?

I am trying to control the volume on an audiomixer sinkpad using the control bindings from Python. In a small standalone program, I am using:

...
mixer = pipeline.append("audiomixer")
cs = GstController.InterpolationControlSource()
cs.set_property("mode", GstController.InterpolationMode.LINEAR)
mixer_pad = mixer.sinkpads[0]
main_control_binding = GstController.DirectControlBinding.new_absolute(mixer_pad, "volume", cs)
mixer_pad.add_control_binding(main_control_binding)

cs.set(0, 1)
cs.set(5*Gst.SECOND, 0)
cs.set(10*Gst.SECOND, 1)

pipeline.append("queue")
pipeline.append("audioconvert")
pipeline.append("alsasink")

This works! In the logs, I see (with GST_DEBUG=3,*control*=9):

INFO       gstcontrolbinding gstcontrolbinding.c:139:gst_control_binding_constructor:<audiomixer0:sink_0> trying to put property 'volume' under control
DEBUG      gstcontrolbinding gstcontrolbinding.c:146:gst_control_binding_constructor:<audiomixer0:sink_0>   psec->flags : 0x000002e3
DEBUG   gstdirectcontrolbinding gstdirectcontrolbinding.c:239:gst_direct_control_binding_constructor:   using type gdouble
INFO    timed value control source gsttimedvaluecontrolsource.c:207:gst_timed_value_control_source_set_internal: create new timed value sequence

followed by lots of

gstdirectcontrolbinding gstdirectcontrolbinding.c:371:gst_direct_control_binding_sync_values:<audiomixer0:sink_0> property 'volume' at ts=0:00:00.085333334
gstdirectcontrolbinding gstdirectcontrolbinding.c:376:gst_direct_control_binding_sync_values:<audiomixer0:sink_0>   new value 0.982933

However, when I try to do the same in my actual application, I do get the initial bits, that seem to indicate everything’s set up successfully:

INFO       gstcontrolbinding gstcontrolbinding.c:139:gst_control_binding_constructor:<audiomixer:main:sink_1> trying to put property 'volume' under control
DEBUG      gstcontrolbinding gstcontrolbinding.c:146:gst_control_binding_constructor:<audiomixer:main:sink_1>   psec->flags : 0x000002e3
DEBUG   gstdirectcontrolbinding gstdirectcontrolbinding.c:239:gst_direct_control_binding_constructor:   using type gdouble
INFO    timed value control source gsttimedvaluecontrolsource.c:207:gst_timed_value_control_source_set_internal: create new timed value sequence

But after I set the same control points (full to zero to full over 10 seconds), nothing happens: there are no gst_direct_control_binding_sync_values lines in the log.

I’ve gone over the two programs repeatedly, but I can’t find anything that would make them behave differently. After setting up the binding, I’ve checked with

cb = main_mixer_pad.get_control_binding("volume")
cs = cb.get_property("control-source")

and I get back the configured control source. I am also able to control the volume of the pad just by setting its volume property, so it’s definitely the correct pad.

Any pointers on where to start looking why the control source is not affecting the property?

Oh, to avoid confusion this is from my own pipeline wrapper; it’s just shorthand for adding and linking to the previous element.

mixer_pad.has_active_control_bindings() also returns True in both cases.

I thought maybe the two programs use different pipeline clocks, but both use GstSystemClock. And the clock times passed to GstTimedValueControlSource.set() should be play times, not absolute clock times, right? As in, what pipeline.get_clock().get_time() would return, starting from zero.