diff -Naur vdr-1.5.8.org/device.c vdr-1.5.8/device.c --- vdr-1.5.8.org/device.c 2009-01-10 10:12:34.776620545 -0500 +++ vdr-1.5.8/device.c 2009-01-10 10:21:42.335871118 -0500 @@ -827,6 +827,28 @@ return mute; } +bool cDevice::ToggleAttenuate(void) +{ + int OldVolume = volume; + attenuate = !attenuate; + //XXX why is it necessary to use different sequences??? + if (attenuate) { + SetVolume(-VOLUMEATTENUATE); + } + else { + SetVolume(OldVolume, true); + } + volume = OldVolume; + return attenuate; +} + +void cDevice::UseAttenuateVol(void) +{ + int OldVolume = volume; + OldVolume-=VOLUMEATTENUATE; + volume = OldVolume; +} + int cDevice::GetAudioChannel(void) { int c = GetAudioChannelDevice(); diff -Naur vdr-1.5.8.org/device.h vdr-1.5.8/device.h --- vdr-1.5.8.org/device.h 2009-01-10 10:12:34.777626291 -0500 +++ vdr-1.5.8/device.h 2009-01-10 10:21:42.336870320 -0500 @@ -28,6 +28,7 @@ #define MAXRECEIVERS 16 // the maximum number of receivers per device #define MAXVOLUME 255 #define VOLUMEDELTA 5 // used to increase/decrease the volume +#define VOLUMEATTENUATE 45 // used to decrease the volume 'attenuate' #define TS_SIZE 188 #define TS_SYNC_BYTE 0x47 @@ -403,6 +404,7 @@ private: bool mute; + bool attenuate; int volume; protected: virtual int GetAudioChannelDevice(void); @@ -417,8 +419,13 @@ ///< on or off. public: bool IsMute(void) const { return mute; } + bool IsAttenuate(void) const { return attenuate; } bool ToggleMute(void); ///< Turns the volume off or on and returns the new mute state. + bool ToggleAttenuate(void); + ///< Lowers the volume or raises it back to last and returns the new volume state. + void UseAttenuateVol(void); + ///< Sets the volume variable to attenuated volume so that volume down lowers from attenuated state. int GetAudioChannel(void); ///< Gets the current audio channel, which is stereo (0), mono left (1) or ///< mono right (2). diff -Naur vdr-1.5.8.org/keys.c vdr-1.5.8/keys.c --- vdr-1.5.8.org/keys.c 2009-01-10 10:12:34.777626291 -0500 +++ vdr-1.5.8/keys.c 2009-01-10 10:21:42.336870320 -0500 @@ -50,6 +50,7 @@ { kVolUp, trNOOP("Key$Volume+") }, { kVolDn, trNOOP("Key$Volume-") }, { kMute, trNOOP("Key$Mute") }, + { kAttenuate, trNOOP("Key$Attenuate") }, { kAudio, trNOOP("Key$Audio") }, { kSchedule, trNOOP("Key$Schedule") }, { kChannels, trNOOP("Key$Channels") }, diff -Naur vdr-1.5.8.org/keys.h vdr-1.5.8/keys.h --- vdr-1.5.8.org/keys.h 2009-01-10 10:12:34.777626291 -0500 +++ vdr-1.5.8/keys.h 2009-01-10 10:21:42.336870320 -0500 @@ -44,6 +44,7 @@ kVolUp, kVolDn, kMute, + kAttenuate, kAudio, kSchedule, kChannels, diff -Naur vdr-1.5.8.org/menu.c vdr-1.5.8/menu.c --- vdr-1.5.8.org/menu.c 2009-01-10 10:20:00.906627848 -0500 +++ vdr-1.5.8/menu.c 2009-01-10 10:21:42.337870447 -0500 @@ -3940,7 +3940,11 @@ void cDisplayVolume::Show(void) { - displayVolume->SetVolume(cDevice::CurrentVolume(), MAXVOLUME, cDevice::PrimaryDevice()->IsMute()); + if (cDevice::PrimaryDevice()->IsAttenuate()) { + displayVolume->SetVolume(cDevice::CurrentVolume() - VOLUMEATTENUATE, MAXVOLUME - 1, cDevice::PrimaryDevice()->IsAttenuate()); + } + else + displayVolume->SetVolume(cDevice::CurrentVolume(), MAXVOLUME, cDevice::PrimaryDevice()->IsMute()); } cDisplayVolume *cDisplayVolume::Create(void) @@ -3974,6 +3978,14 @@ else timeout.Set(); break; + case kAttenuate: + if (cDevice::PrimaryDevice()->IsAttenuate()) { + Show(); + timeout.Set(VOLUMETIMEOUT); + } + else + timeout.Set(); + break; case kNone: break; default: if ((Key & k_Release) == 0) { cRemote::Put(Key); diff -Naur vdr-1.5.8.org/vdr.c vdr-1.5.8/vdr.c --- vdr-1.5.8.org/vdr.c 2009-01-10 10:20:00.907622131 -0500 +++ vdr-1.5.8/vdr.c 2009-01-10 10:21:42.338995479 -0500 @@ -990,11 +990,17 @@ key = kNone; // nobody else needs to see these keys break; // Volume control: - case kVolUp|k_Repeat: - case kVolUp: case kVolDn|k_Repeat: case kVolDn: + if (cDevice::PrimaryDevice()->IsAttenuate()) { + cDevice::PrimaryDevice()->UseAttenuateVol(); + } + case kVolUp|k_Repeat: + case kVolUp: case kMute: + if (cDevice::PrimaryDevice()->IsAttenuate()) { + cDevice::PrimaryDevice()->ToggleAttenuate(); + } if (key == kMute) { if (!cDevice::PrimaryDevice()->ToggleMute() && !Menu) { key = kNone; // nobody else needs to see these keys @@ -1008,6 +1014,21 @@ cDisplayVolume::Process(key); key = kNone; // nobody else needs to see these keys break; + case kAttenuate: + if (cDevice::PrimaryDevice()->IsMute()) { + cDevice::PrimaryDevice()->ToggleMute(); + } + if (key == kAttenuate) { + if (!cDevice::PrimaryDevice()->ToggleAttenuate() && !Menu) { + key = kNone; // nobody else needs to see these keys + break; // no need to display "mute off" + } + } + if (!Menu && !cOsd::IsOpen()) + Menu = cDisplayVolume::Create(); + cDisplayVolume::Process(key); + key = kNone; // nobody else needs to see these keys + break; // Audio track control: case kAudio: if (cControl::Control())