Commit 4f7ac8db authored by Christian Esken's avatar Christian Esken
Browse files

Fix volume switch for controls with a virtual/simulated mute switch.

CCBUGS: 309334
parent 8fb06fa8
......@@ -717,7 +717,17 @@ Mixer_ALSA::readVolumeFromHW( const QString& id, shared_ptr<MixDevice> md )
vol = Volume::MNONE;
// --- playback volume
if ( snd_mixer_selem_has_playback_volume( elem ) ) {
if ( snd_mixer_selem_has_playback_volume( elem ) )
{
if ( md->isVirtuallyMuted() )
{
// Special code path for controls w/o physical mute switch. Doing it in all backends is not perfect,
// but it saves a lot of code and removes a lot of complexity in the Volume and MixDevice classes.
// Don't feed back the actual 0 volume back from the device to KMix. Just do nothing!
}
else
{
foreach (VolumeChannel vc, volumePlayback.getVolumes() )
{
int ret = 0;
......@@ -739,6 +749,7 @@ Mixer_ALSA::readVolumeFromHW( const QString& id, shared_ptr<MixDevice> md )
volumePlayback.setVolume( vc.chid, vol);
//if (id== "Master:0" || id== "PCM:0" ) { kDebug() << "volumePlayback control=" << id << ", chid=" << i << ", vol=" << vol; }
}
}
} // has playback volume
// --- playback switch
......@@ -811,9 +822,32 @@ Mixer_ALSA::writeVolumeToHW( const QString& id, shared_ptr<MixDevice> md )
return 0;
}
// --- playback switch
bool hasPlaybackSwitch = snd_mixer_selem_has_playback_switch( elem ) || snd_mixer_selem_has_common_switch ( elem );
if (hasPlaybackSwitch)
{
int sw = 0;
if (!md->isMuted())
sw = !sw; // invert all bits
snd_mixer_selem_set_playback_switch_all(elem, sw);
}
// --- playback volume
if ( snd_mixer_selem_has_playback_volume( elem ) )
{
kDebug() << "phys=" << md->hasPhysicalMuteSwitch() << ", muted=" << md->isMuted();
if ( md->isVirtuallyMuted() )
{
// Special code path for controls w/o physical mute switch. Doing it in all backends is not perfect,
// but it saves a lot of code and removes a lot of complexity in the Volume and MixDevice classes.
int ret = snd_mixer_selem_set_playback_volume_all( elem, (long)0);
if ( ret != 0 )
kDebug() << "writeVolumeToHW(" << devnum << ") [set_playback_volume] failed, errno=" << ret;
}
else
{
foreach (VolumeChannel vc, volumePlayback.getVolumes() )
{
int ret = 0;
......@@ -830,20 +864,13 @@ Mixer_ALSA::writeVolumeToHW( const QString& id, shared_ptr<MixDevice> md )
case Volume::REARSIDERIGHT: ret = snd_mixer_selem_set_playback_volume( elem, SND_MIXER_SCHN_SIDE_RIGHT , vc.volume); break;
default: kDebug() << "FATAL: Unknown channel type for playback << " << vc.chid << " ... please report this"; break;
}
if ( ret != 0 ) kDebug() << "writeVolumeToHW(" << devnum << ") [set_playback_volume] failed, errno=" << ret;
if ( ret != 0 )
kDebug() << "writeVolumeToHW(" << devnum << ") [set_playback_volume] failed, errno=" << ret;
//if (id== "Master:0" || id== "PCM:0" ) { kDebug() << "volumePlayback control=" << id << ", chid=" << vc.chid << ", vol=" << vc.volume; }
}
}
} // has playback volume
// --- playback switch
if ( snd_mixer_selem_has_playback_switch( elem ) ||
snd_mixer_selem_has_common_switch ( elem ) )
{
int sw = 0;
if ( ! md->isMuted() )
sw = !sw; // invert all bits
snd_mixer_selem_set_playback_switch_all(elem, sw);
}
// --- capture volume
......
......@@ -240,6 +240,13 @@ const QString MixDevice::dbusPath() {
bool MixDevice::isMuted() { return ! _playbackVolume.isSwitchActivated(); }
/**
* Returns whether this MixDevice is virtually muted. Only MixDevice objects w/o a physical switch can be muted virtually.
*/
bool MixDevice::isVirtuallyMuted()
{
return !hasPhysicalMuteSwitch() && isMuted();
}
void MixDevice::setMuted(bool mute) { _playbackVolume.setSwitch(!mute); }
void MixDevice::toggleMute() { setMuted( !_playbackVolume.isSwitchActivated()); }
bool MixDevice::hasMuteSwitch() { return playbackVolume().hasVolume() || playbackVolume().hasSwitch(); }
......
......@@ -163,6 +163,7 @@ public:
// is an abstract concept. It places no interpretation on the meaning of the switch (e.g. does "switch set" mean
// "mute on", or does it mean "playback on", or "Capture active", or ...
virtual bool isMuted();
virtual bool isVirtuallyMuted();
virtual void setMuted(bool value);
virtual bool hasMuteSwitch();
virtual void toggleMute();
......
......@@ -107,7 +107,10 @@ void Volume::init( ChannelMask chmask, long maxVolume, long minVolume, bool hasS
_hasSwitch = hasSwitch;
_isCapture = isCapture;
//_muted = false;
_switchActivated = false;
// Presume that the switch is active. This will always work:
// a) Physical switches will be updated after start from the hardware.
// b) Emulated virtual/switches will not receive updates from the hardware, so they shouldn't disable the channels.
_switchActivated = true;
disallowSwitchDisallowRead = false;
}
......
......@@ -115,26 +115,18 @@ friend class MixDevice;
bool hasSwitch() const
{
if (isCapture())
{
return _hasSwitch;
}
else
{
if ( disallowSwitchDisallowRead )
{
kError() << "hasSwitch() must only be called for capture volumes. I will crash now to retreieve a stacktrace!!!";
QObject* obj = 0;
obj->blockSignals(true);
return _hasSwitch;
}
else
kDebug() << "Allow playback switch read once";
}
return _hasSwitch;
return _hasSwitch;
};
bool hasVolume() const { return (_maxVolume != _minVolume); }
bool isCapture() const { return _isCapture; } // -<- Query thsi, to find out whether this is a capture or a playback volume
/**
* Returns whether this is a playback or capture volume.
*
* @return true, if it is a capture volume
*/
bool isCapture() const
{
return _isCapture;
}
// Some playback switches control playback, and some are special.
// ALSA doesn't differentiate between playback, OnOff and special, so users can add this information in the profile.
......@@ -167,24 +159,7 @@ protected:
bool isSwitchActivated() const // TODO rename to isActive()
{
return _switchActivated;
if (isCapture())
{
return _switchActivated && hasSwitch();
}
else
{
if ( disallowSwitchDisallowRead )
{
kError() << "isSwitchActivated() must only be called for capture volumes. I will crash now to retreieve a stacktrace!!!";
QObject* obj = 0;
obj->blockSignals(true);
return _switchActivated && hasSwitch();
}
}
return _switchActivated && hasSwitch();
};
};
private:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment