Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[VolumeControl] Rewrite and refactor VolumeControl code #3410

Merged
merged 2 commits into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions data/keymap.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@

<map context="GlobalActions">
<key id="KEY_VOLUMEUP" mapto="volumeUp" flags="mr" />
<key id="KEY_VOLUMEUP" mapto="volumeUpLong" flags="l" />
<key id="KEY_VOLUMEUP" mapto="volumeUpStop" flags="s" />
<key id="KEY_VOLUMEDOWN" mapto="volumeDown" flags="mr" />
<key id="KEY_VOLUMEDOWN" mapto="volumeDownLong" flags="l" />
<key id="KEY_VOLUMEDOWN" mapto="volumeDownStop" flags="s" />
<key id="KEY_MUTE" mapto="volumeMute" flags="m" />
<key id="KEY_MUTE" mapto="volumeMuteLong" flags="l" />
<key id="KEY_POWER" mapto="power_long" flags="l" />
Expand Down
8 changes: 3 additions & 5 deletions data/setup.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
<!-- This is just a placeholder, the Videomode plugin implements this sub menu. -->
</setup>
<setup key="Audio" title="Audio Settings" level="1" showOpenWebif="1">
<item level="1" text="Volume steps" description="Select the size of the volume step when the VOLUME buttons are pressed.">config.volumeControl.pressStep</item>
<item level="1" text="Long press volume steps" description="Select the size of the volume steps when the VOLUME buttons are held down.">config.volumeControl.longStep</item>
<item level="1" text="Volume/Mute display timer" description="Select how long, in seconds, that the volume and mute displays are shown before they automatically hide.">config.volumeControl.hideTimer</item>
<item level="1" text="PCM Multichannel" description="Choose whether multi channel sound tracks should be output as PCM." requires="CanPcmMultichannel">config.av.pcm_multichannel</item>
<item level="1" text="AC3 downmix" description="Choose whether AC3 sound tracks should be downmixed to stereo." requires="CanDownmixAC3">config.av.downmix_ac3</item>
<item level="1" text="AC3 plus transcoding" description="Choose whether AC3 Plus sound tracks should be transcoded to AC3." requires="CanAC3plusTranscode">config.av.transcodeac3plus</item>
Expand All @@ -18,11 +21,6 @@
<item level="1" text="3D Surround" description="This option allows you to enable 3D Surround Sound." requires="Can3DSurround">config.av.surround_3d</item>
<item level="1" text="3D Surround Speaker Position" description="This option allows you to change the virtual loudspeaker position." requires="Can3DSpeaker" conditional="config.av.surround_3d.value != 'none'">config.av.surround_3d_speaker</item>
<item level="1" text="Audio Auto Volume Level" description="This option configures you can set Auto Volume Level." requires="CanAutoVolume">config.av.autovolume</item>
<item level="1" text="Audio volume step size" description="Configure the general audio volume step size (limit 1-10).">config.av.volume_stepsize</item>
<item level="1" text="Audio volume step size fast mode" description="Configure the fast mode audio volume step size (limit 1-10). Activated when volume key permanent press or press fast in a row.">config.av.volume_stepsize_fastmode</item>
<item level="1" text="Use logarithmic steps" description="Select to use logarithmic step size with more steps at the lower volume levels.">config.audio.volumeLogSteps</item>
<item level="1" text="Volume display timer" description="Select how long, in seconds, that the volume display is shown before it automatically hides.">config.audio.volumeHideTimer</item>
<item level="1" text="Hide mute notification" description="If muted, hide mute icon or mute information after few seconds.">config.av.volume_hide_mute</item>
<item level="1" text="Enable BT Audio" description="This Option allows you to switch Audio to BT Speakers." requires="CanBTAudio">config.av.btaudio</item>
<item level="1" text="General BT Audio delay" description="This option configures the general audio delay for BT Speakers." requires="CanBTAudioDelay">config.av.btaudiodelay</item>
</setup>
Expand Down
9 changes: 1 addition & 8 deletions lib/python/Components/AVSwitch.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from os import W_OK, access, system
from time import sleep

from enigma import eAVControl, eDVBVolumecontrol, getDesktop
from enigma import eAVControl, getDesktop

from Components.config import ConfigBoolean, ConfigEnableDisable, ConfigInteger, ConfigNothing, ConfigOnOff, ConfigSelection, ConfigSelectionInteger, ConfigSelectionNumber, ConfigSlider, ConfigSubDict, ConfigSubsection, ConfigText, ConfigYesNo, NoSave, config
from Components.About import about
Expand Down Expand Up @@ -611,13 +611,6 @@ def setPCMMultichannel(configElement):
config.av.pcm_multichannel = ConfigYesNo(default=False)
config.av.pcm_multichannel.addNotifier(setPCMMultichannel)

def setVolumeStepSize(configElement):
eDVBVolumecontrol.getInstance().setVolumeSteps(int(configElement.value))

config.av.volume_stepsize = ConfigSelectionNumber(min=1, max=10, stepwidth=1, default=5)
config.av.volume_stepsize.addNotifier(setVolumeStepSize)
config.av.volume_stepsize_fastmode = ConfigSelectionNumber(min=1, max=10, stepwidth=1, default=5)
config.av.volume_hide_mute = ConfigYesNo(default=True)
if AMLOGIC:
downmixAC3 = True
BoxInfo.setItem("CanPcmMultichannel", True)
Expand Down
248 changes: 105 additions & 143 deletions lib/python/Components/VolumeControl.py
Original file line number Diff line number Diff line change
@@ -1,161 +1,123 @@
from enigma import eDVBVolumecontrol, eTimer

from GlobalActions import globalActionMap
from Components.config import ConfigInteger, ConfigSelectionNumber, ConfigSubsection, ConfigYesNo, config
from Screens.Mute import Mute
from Screens.Volume import Volume
from Components.config import ConfigBoolean, ConfigInteger, ConfigSelectionNumber, ConfigSubsection, config
from Screens.VolumeControl import Mute, Volume


# NOTE: This code does not remember the current volume as other code can change
# the volume directly. Always get the current volume from the driver.
#
class VolumeControl:
"""Volume control, handles volUp, volDown, volMute actions and display a corresponding dialog."""
"""Volume control, handles volumeUp, volumeDown, volumeMute, and other actions and display a corresponding dialog."""
instance = None

def __init__(self, session):
global globalActionMap
globalActionMap.actions["volumeUp"] = self.volUp
globalActionMap.actions["volumeDown"] = self.volDown
globalActionMap.actions["volumeMute"] = self.volMute
globalActionMap.actions["volumeMuteLong"] = self.volMuteLong
assert not VolumeControl.instance, "[VolumeControl] Error: Only one VolumeControl instance is allowed!"
VolumeControl.instance = self
config.audio = ConfigSubsection()
config.audio.volume = ConfigInteger(default=50, limits=(0, 100))
config.audio.volumeLogSteps = ConfigYesNo(default=True)
config.audio.volumeHideTimer = ConfigSelectionNumber(1, 10, 1, default=3)
self.volumeDialog = session.instantiateDialog(Volume)
self.volumeDialog.setAnimationMode(0)
self.muteDialog = session.instantiateDialog(Mute)
self.muteDialog.setAnimationMode(0)
self.hideVolTimer = eTimer()
self.hideVolTimer.callback.append(self.volHide)
self.stepVolTimer = eTimer()
self.repeat = 500
self.delay = 3000
vol = config.audio.volume.value
self.volumeDialog.setValue(vol)
self.volctrl = eDVBVolumecontrol.getInstance()
self.volctrl.setVolume(vol, vol)
self.last_vol = vol
def updateStep(configElement):
self.dvbVolumeControl.setVolumeSteps(configElement.value)

def volSave(self):
if self.volctrl.isMuted():
config.audio.volume.setValue(0)
if VolumeControl.instance:
print("[VolumeControl] Error: Only one VolumeControl instance is allowed!")
else:
config.audio.volume.setValue(self.volctrl.getVolume())
config.audio.volume.save()
VolumeControl.instance = self
global globalActionMap
globalActionMap.actions["volumeUp"] = self.keyVolumeUp
globalActionMap.actions["volumeUpLong"] = self.keyVolumeLong
globalActionMap.actions["volumeUpStop"] = self.keyVolumeStop
globalActionMap.actions["volumeDown"] = self.keyVolumeDown
globalActionMap.actions["volumeDownLong"] = self.keyVolumeLong
globalActionMap.actions["volumeDownStop"] = self.keyVolumeStop
globalActionMap.actions["volumeMute"] = self.keyVolumeMute
globalActionMap.actions["volumeMuteLong"] = self.keyVolumeMuteLong
self.dvbVolumeControl = eDVBVolumecontrol.getInstance()
config.volumeControl = ConfigSubsection()
config.volumeControl.volume = ConfigInteger(default=20, limits=(0, 100))
config.volumeControl.mute = ConfigBoolean(default=False)
config.volumeControl.pressStep = ConfigSelectionNumber(1, 10, 1, default=1)
config.volumeControl.pressStep.addNotifier(updateStep, initial_call=True, immediate_feedback=True)
config.volumeControl.longStep = ConfigSelectionNumber(1, 10, 1, default=5)
config.volumeControl.hideTimer = ConfigSelectionNumber(1, 10, 1, default=3)
self.muteDialog = session.instantiateDialog(Mute)
self.muteDialog.setAnimationMode(0)
self.volumeDialog = session.instantiateDialog(Volume)
self.volumeDialog.setAnimationMode(0)
self.hideTimer = eTimer()
self.hideTimer.callback.append(self.hideVolume)
if config.volumeControl.mute.value:
self.dvbVolumeControl.volumeMute()
self.muteDialog.show()
volume = config.volumeControl.volume.value
self.volumeDialog.setValue(volume)
self.dvbVolumeControl.setVolume(volume, volume)
# Compatibility interface for shared plugins.
self.volctrl = self.dvbVolumeControl
self.hideVolTimer = self.hideTimer

def volUp(self):
vol = self.volctrl.getVolume()
step = self.stepVolume()
if config.audio.volumeLogSteps.value:
if vol < 3:
step = 1
elif vol < 9:
if step > 2:
step = 2
elif vol < 18:
if step > 3:
step = 3
elif vol < 30:
if step > 4:
step = 4
self.setVolume(vol + step)
def keyVolumeUp(self):
self.dvbVolumeControl.volumeUp(0, 0)
self.updateVolume()

def volDown(self):
vol = self.volctrl.getVolume()
step = self.stepVolume()
if config.audio.volumeLogSteps.value:
if vol <= 3:
step = 1
elif vol <= 9:
if step > 2:
step = 2
elif vol <= 18:
if step > 3:
step = 3
elif vol <= 30:
if step > 4:
step = 4
self.setVolume(vol - step)

def stepVolume(self):
if self.stepVolTimer.isActive():
step = config.av.volume_stepsize_fastmode.value
else:
self.getInputConfig()
step = config.av.volume_stepsize.value
self.stepVolTimer.start(self.repeat, True)
return step

def getInputConfig(self):
if self.hideVolTimer.isActive():
return
try:
inputconfig = config.inputDevices.getSavedValue()
except KeyError:
return
delay = 0
repeat = 0

for device in inputconfig.values():
if "enabled" in device and bool(device["enabled"]):
if "delay" in device:
val = int(device["delay"])
if val > delay:
delay = val
if "repeat" in device:
val = int(device["repeat"])
if val > repeat:
repeat = val
if repeat + 100 > self.repeat:
self.repeat = repeat + 100
if delay + 100 > self.delay:
self.delay = delay + 100

def setVolume(self, newvol):
self.volctrl.setVolume(newvol, newvol)
is_muted = self.volctrl.isMuted()
vol = self.volctrl.getVolume()
self.last_vol = vol
self.volumeDialog.show()
if is_muted:
self.volMute() # Unmute.
elif not vol:
self.volMute(False, True) # Mute but don't show mute symbol.
if self.volctrl.isMuted():
self.volumeDialog.setValue(0)
else:
self.volumeDialog.setValue(self.volctrl.getVolume())
self.volSave()
self.hideVolTimer.start(self.delay, True)
def keyVolumeDown(self):
self.dvbVolumeControl.volumeDown(0, 0)
self.updateVolume()

def volHide(self):
self.volumeDialog.hide()
# Set volume on if muted and volume is changed in OpenWebif.
vol = self.volctrl.getVolume()
if self.volctrl.isMuted() and self.last_vol != vol:
self.volctrl.volumeUnMute()
self.last_vol = vol
#
if not self.volctrl.isMuted() or config.av.volume_hide_mute.value:
self.muteDialog.hide()

def showMute(self):
if self.volctrl.isMuted():
self.muteDialog.show()
self.hideVolTimer.start(int(config.audio.volumeHideTimer.value) * 1000, True)

def volMute(self, showMuteSymbol=True, force=False):
vol = self.volctrl.getVolume()
if vol or force:
self.volctrl.volumeToggleMute()
if self.volctrl.isMuted():
if showMuteSymbol:
self.showMute()
self.volumeDialog.setValue(0)
def keyVolumeLong(self):
self.dvbVolumeControl.setVolumeSteps(config.volumeControl.longStep.value)

def keyVolumeStop(self):
self.dvbVolumeControl.setVolumeSteps(config.volumeControl.pressStep.value)

def keyVolumeMute(self): # This will toggle the current mute status. Mute will not be activated if the volume is at 0.
volume = self.dvbVolumeControl.getVolume()
isMuted = self.dvbVolumeControl.isMuted()
if volume or (volume == 0 and isMuted):
self.dvbVolumeControl.volumeToggleMute()
if self.dvbVolumeControl.isMuted():
self.muteDialog.show()
self.volumeDialog.hide()
else:
self.muteDialog.hide()
self.volumeDialog.setValue(vol)
self.volumeDialog.setValue(volume)
self.volumeDialog.show()
self.hideTimer.start(config.volumeControl.hideTimer.value * 1000, True)

def keyVolumeMuteLong(self): # Long press MUTE will keep the mute icon on-screen without a timeout.
if self.dvbVolumeControl.isMuted():
self.hideTimer.stop()

def updateVolume(self):
if self.dvbVolumeControl.isMuted():
self.keyVolumeMute() # Unmute.
else:
self.volumeDialog.setValue(self.dvbVolumeControl.getVolume())
self.volumeDialog.show()
self.hideTimer.start(config.volumeControl.hideTimer.value * 1000, True)

def volMuteLong(self):
def hideVolume(self):
self.muteDialog.hide()
self.volumeDialog.hide()

def saveVolumeState(self):
config.volumeControl.mute.value = self.dvbVolumeControl.isMuted()
config.volumeControl.volume.setValue(self.dvbVolumeControl.getVolume())
config.volumeControl.save()

def showMute(self): # This method is only called by InfoBarGenerics.py:
if self.dvbVolumeControl.isMuted():
self.muteDialog.show()
self.hideTimer.start(config.volumeControl.hideTimer.value * 1000, True)

# These methods are provided for compatibly with shared plugins.
#
def volUp(self):
self.keyVolumeUp()

def volDown(self):
self.keyVolumeDown()

def volMute(self):
self.keyVolumeMute()

def volSave(self):
# Volume (and mute) saving is now done when Enigma2 shuts down.
pass
6 changes: 3 additions & 3 deletions lib/python/Screens/InfoBarGenerics.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from sys import maxsize
from time import localtime, strftime, time

from enigma import eActionMap, eAVControl, eDBoxLCD, eDVBDB, eDVBServicePMTHandler, eDVBVolumecontrol, eEPGCache, eServiceCenter, eServiceReference, eTimer, getBsodCounter, getDesktop, iPlayableService, iServiceInformation, quitMainloop, resetBsodCounter, eDVBVolumecontrol
from enigma import eActionMap, eAVControl, eDBoxLCD, eDVBDB, eDVBServicePMTHandler, eDVBVolumecontrol, eEPGCache, eServiceCenter, eServiceReference, eTimer, getBsodCounter, getDesktop, iPlayableService, iServiceInformation, quitMainloop, resetBsodCounter

from keyids import KEYFLAGS, KEYIDNAMES, KEYIDS
from RecordTimer import AFTEREVENT, RecordTimer, RecordTimerEntry, findSafeRecordPath, parseEvent
Expand Down Expand Up @@ -1756,10 +1756,10 @@ def zapDown(self):
self["SeekActionsPTS"].setEnabled(True)

def volumeUp(self): # Called from ButtonSetup
VolumeControl.instance.volUp()
VolumeControl.instance.keyVolumeUp()

def volumeDown(self): # Called from ButtonSetup
VolumeControl.instance.volDown()
VolumeControl.instance.keyVolumeDown()


class InfoBarMenu:
Expand Down
5 changes: 0 additions & 5 deletions lib/python/Screens/Mute.py

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@
from Screens.Screen import Screen


class Mute(Screen):
pass


class Volume(Screen):
def __init__(self, session):
Screen.__init__(self, session)
self["Volume"] = VolumeBar()
self["VolumeText"] = Label()
self["Volume"] = VolumeBar()

def setValue(self, volume):
print(f"[Volume] Volume set to {volume}.")
self["Volume"].setValue(volume)
self["VolumeText"].setText(str(volume))
self["Volume"].setValue(volume)
1 change: 1 addition & 0 deletions lib/python/StartEnigma.py
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,7 @@ def runNextScreen(session, screensToRun, *result):
print("=" * 100)
session.nav.stopService()
session.nav.shutdown()
VolumeControl.instance.saveVolumeState()
configfile.save()
from Screens.InfoBarGenerics import saveResumePoints
saveResumePoints()
Expand Down
Loading