Phonon + Volume Changes and feedback loops

Christian Esken esken at
Mon Mar 29 10:55:05 BST 2010

Am Samstag, 27. März 2010 22:43:25 schrieb Colin Guthrie:
> Hi,
> I'm working on integrating proper per-application volume controls
> provided by PulseAudio into Phonon.
> So far the work is going well and I've got things working quite nicely.
> I can now use KMix to change Amarok's volume and have this change
> reflected in the Amarok GUI. It all works rather nicely.
> However there is a major problem and that is one of feedback loops.
> In both Dragon (which uses the Phonon VolumeSlider widget) and Amarok
> (which rolls it's own volume widget) there is a bit of a problem when PA
> indicates a volume changes and when a change is triggered from with in
> the app itself. The two problems are different but related.
> To explain:
> If PA indicates a change (e.g. because KMix was used), then this will
> come to the application (Dragon, Amarok) via a volumeChanged signal.
> This will then be used to update a widget by calling e.g. setValue(). In
> both applications the widget's setValue signal is is connected to the
> engines setVolume slot.
> This means that a change from KMix will:
>  1. Set the volume to X.
>  2. Phonon application updates GUI to reflect X
>  3. Phonon application sets volume to GUI Value (which ~= X).
>  4. If GUI Value != X, Goto 2.

KMix faces exactly the same challenge (for the Slider), and it simply uses 
blockSignal() (see mdwslider.cpp).

The basic point is, that 2 -> 3 should be avoided. I don't see any reason to 
update the volume to the GUI after a change comes in from the Hardware or PA. 
We know that the value is already correct. Why is this done?

Would it be possible to run blockSignal() if the source is external?
External would mean, that it is coming from the slot connected to 

> The second problem is one of asynchronisity. In the current Phonon
> VolumeSlider, there is protection against a feedback loop in that when
> the volume is set from the widget, it set's an "ignoreVolumeChange" flag
> to true before calling the output's setVolume method and resets it
> afterwards. This flag is checked in the volumeChanged slot and the
> change is (obviously) ignored if the flag is set. In order for this to
> work correctly the setVolume call must be synchronous. With PulseAudio,
> all calls are asynchronous. This means that we request a volume change,
> and some time later we get information about that change. The
> information about the change comes in in the same way as if an external
> application (e.g. kmix) initiated the change. Therefore, this flag is
> simply not sufficient to deal with an async setVolume.

> Rather than a simple ignoreVolumeChange flag, I could implement an
> "ignoreVolumeCounter" and incrmeent it when a change is made and
> decrement it when a change is observed. only when the counter is 0
> should an observed event result in a GUI change. This would solve the
> problem of async volume changes although there is a small chance that
> the wrong volume changes are ignored. e.g. a GUI is used to make two
> volume changes before either one is observed. In between these two
> changes an other application also changes the volume externally to the
> GUI in question. This volume change *should* be observed, but because
> our counter is 2 it will be ignored and the second GUI change will
> actually be the one that is noticed. As it technically happened latest
> in time, it is perhaps desirable that this is the one that is noticed?
> On reflection I think this is OK.
> BUT, this only solved half the problem! It solves a feedback loop that
> starts at the GUI and comes full circle around an async change. If the
> change is started externally and begins with an observed volume change
> (as described above in the 4 point sequence), the feedback loop still
> exists. In theory I need two counters, one as described above that
> ignores feedback from a volume changes initiated by the GUI and a second
> that allows a GUI update to suppress the request for a volume change.

Any request coming in from Hardware or PA must never be reflected back. There 
is no need for a counter or flag, as far as i understood.

> I'm not sure I've described this very well, but it is ratherl(
> complicated. If anyone has any insights on this, I'm all ears. Otherwise
> I'll try and implement this with the phonon VolumeSlider first and test
> that it works and then try and make the Amarok one work in the same way.

I am aware of the complicated nature. Probably I missed an important point in 
your explanation.


More information about the kde-multimedia mailing list