Skip to content

Commit

Permalink
Publish 2019.05.6 release
Browse files Browse the repository at this point in the history
  • Loading branch information
Yannick Plassiard committed May 29, 2019
1 parent 8ca9c1d commit 721972e
Show file tree
Hide file tree
Showing 8 changed files with 173 additions and 90 deletions.
7 changes: 7 additions & 0 deletions addon/doc/en/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,10 @@ When activated the following shortcuts can be used:
- LeftArrow: Go to previous app that is playing audio
- RightArrow: Go to next app that is playing audio
- m: mute or unmute the focused app
- control + Up arrow: raises the current application's volume.
- control + Down arrow: lowers the current application's volume.

## Settings
A "Sound Manager" category within the NVDA Setting's dialog allows you to customize the addon behavior:
- Announce volume changes: Instructs the add-on to say the new volume values when changing it.
- Announce app change when cycling: Instructs the add-on to speak the application name when cycligng through app volumes.
8 changes: 8 additions & 0 deletions addon/doc/fr/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,11 @@ Lorsque le contrôle du volume est activé les raccourcis suivants sont disponib
- Flèche vers la gauche: Aller à l'application précédente jouant de l'audio.
- Flèche vers la droite: Aller à l'application suivante jouant de l'audio.
- m: Couper le son de l'application sélectionnée.
- Contrôle + Fl\che vers le haut: augmenter le volume de l'application en avant-plan.
- Contrôle + Flèche vers le bas: diminue le volume de l'application en avant-plan.

## Paramétrage
Dans le dialogue de paramétrage de NVDA, une catégorie "Sound Manager" permet de changer les paramètres suivants:
- Annoncer les changements de volume: Permet de vocaliser ou non les changements de volume des applications.
- Annoncer le nom des apps lors de la sélection des contrôles de volume.

138 changes: 93 additions & 45 deletions addon/globalPlugins/soundmanager/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# *-* coding: utf-8 *-*
# Sound Manager
#addon/globalPlugins/sound-manager/__init__.py
#A part of the NVDA Sound Manager add-on
#Copyright (C) 2019 Yannick PLASSIARD
Expand All @@ -19,9 +20,13 @@
import globalPluginHandler
import addonHandler
import api
from speech import cancelSpeech
import speech
import tones
import ui
import wx
import config

import gui
# Local requirements (Pycaw and its dependencies)

sys.path.append(os.path.dirname(os.path.abspath(__file__)))
Expand All @@ -30,22 +35,44 @@
del sys.path[-1]
addonHandler.initTranslation()

# Configuration specifications and default section name.
SM_CFG_SECTION = "soundManager"

confspec = {
"sayVolumeChange": "boolean(default=true)",
"sayAppChange": "boolean(default=true)",
}
config.conf.spec[SM_CFG_SECTION] = confspec

# message contexts
SM_CTX_ERROR = 1
SM_CTX_APP_CHANGE = 2
SM_CTX_VOLUME_CHANGE = 3

# A fake Process class with mininal implementation to comply to the cycleThroughApps plugin method.

class MasterVolumeFakeProcess(object):
def __init__(self, name):
self._name = name
def name(self):
return self._name

#
# Main global plugin class
#


class GlobalPlugin(globalPluginHandler.GlobalPlugin):
#. Translators: The name of the add-on presented to the user.
# Translators: The name of the add-on presented to the user.
scriptCategory = _("Sound Manager")
volumeChangeStep = 0.05
volumeChangeStep = 0.02
enabled = False
curAppName = None


def __init__(self, *args, **kwargs):
super(globalPluginHandler.GlobalPlugin, self).__init__(*args, **kwargs)
self.readConfiguration()
self.devices = AudioUtilities.GetSpeakers()
self.interface = self.devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None)
self.master_volume = cast(self.interface, POINTER(IAudioEndpointVolume))
Expand All @@ -54,7 +81,27 @@ def __init__(self, *args, **kwargs):
self.master_volume.name = _('Master volume')
self.master_volume.Process = MasterVolumeFakeProcess(self.master_volume.name)
self.master_volume.getDisplayName = lambda: self.master_volume.name

gui.settingsDialogs.NVDASettingsDialog.categoryClasses.append(SoundManagerPanel)
if hasattr(config, "post_configProfileSwitch"):
config.post_configProfileSwitch.register(self.handleConfigProfileSwitch)
else:
config.configProfileSwitched.register(self.handleConfigProfileSwitch)
def handleConfigProfileSwitch(self):
self.readConfiguration()
def readConfiguration(self):
self.sayAppChange = config.conf[SM_CFG_SECTION]["sayAppChange"]
self.sayVolumeChange = config.conf[SM_CFG_SECTION]["sayVolumeChange"]

def message(self, ctx, msg, interrupt=False):
if ctx == SM_CTX_VOLUME_CHANGE and self.sayVolumeChange:
speech.cancelSpeech() if interrupt else None
ui.message(msg)
elif ctx == SM_CTX_APP_CHANGE and self.sayAppChange:
speech.cancelSpeech() if interrupt else None
ui.message(msg)
elif ctx == SM_CTX_ERROR:
ui.message(msg)
return

def getAppNameFromSession(self, session):
"""Returns an application's name formatted to be presented to the user from a given audio session."""
Expand All @@ -70,45 +117,38 @@ def getAppNameFromSession(self, session):


def script_muteApp(self, gesture):
"""Mutes or unmute the focused application."""
session,volume = self.findSessionByName(self.curAppName)
if session is None:
if self.curAppName is not None:
#. Translators: Spoken message when unablee to change audio volume for the given application.
ui.message(_("Unable to retrieve current application."))
if self.curAppName != self.master_volume.name:
# Translators: Spoken message when unablee to change audio volume for the given application.
self.message(SM_CTX_ERROR, _("Unable to retrieve current application."))
return
else:
#. Translators: Cannot mute the master volume.
ui.message(_("Cannot mute the master volume."))
# Translators: Cannot mute the master volume.
self.message(SM_CTX_ERROR, _("Cannot mute the master volume."))
return

muted = volume.GetMute()
volume.SetMute(not muted, None)
if not muted:
#. Translator: Spoken message indicating that the app's sound is now muted.
ui.message(_("{app} muted").format(app=self.getAppNameFromSession(session)))
# Translator: Spoken message indicating that the app's sound is now muted.
self.message(SM_CTX_VOLUME_CHANGE, _("{app} muted").format(app=self.getAppNameFromSession(session)))
else:
#. Translators: Spoken message indicating that the app's audio is now unmuted.
ui.message(_("{app} unmuted").format(app=self.getAppNameFromSession(session)))
# Translators: Spoken message indicating that the app's audio is now unmuted.
self.message(SM_CTX_VOLUME_CHANGE, _("{app} unmuted").format(app=self.getAppNameFromSession(session)))

def focusCurrentApplication(self, silent=False):
"""Selects the audio control for the current alsplication."""
obj = api.getFocusObject()
appName = None
try:
appName = obj.appModule.appName
except AttributeError:
appName = None
if appName is None:
if not silent:
#. Translators: Unable to determine focused application's name.
ui.message_("Unable to retrieve current application's name.")
return False
session,volume = self.findSessionByName(appName)
if session is None:
if not silent:
#. Translators: The current application does not pay audio.
ui.message(_("{app} is not playing any sound.".format(app=appName)))
# Translators: The current application does not pay audio.
self.message(SM_CTX_ERROR, _("{app} is not playing any sound.".format(app=appName)))
return False
self.curAppName = appName
return True
Expand Down Expand Up @@ -137,18 +177,16 @@ def script_volumeDown(self, gesture):
"""Decreases the volume of the selected application."""
self.changeVolume(-self.volumeChangeStep)

def script_volume_changed(self, gesture):
def script_onVolumeChanged(self, gesture):
gesture.send()
cancelSpeech()
ui.message(str(int(round(round(self.master_volume.GetMasterVolume(), 2)*100, 0)))+'%')
self.message(SM_CTX_VOLUME_CHANGE, str(int(round(round(self.master_volume.GetMasterVolume(), 2)*100, 0)))+'%', True)

def changeVolume(self, volumeStep):
"""Adjusts the volume of the selected application using the given step value."""
session,volume = self.findSessionByName(self.curAppName)
selector = self.master_volume
if volume is None and self.curAppName is not None:
#. Translators: Spoken message when unablee to change audio volume for the given application
ui.message(_("Unable to retrieve current application."))
# Translators: Spoken message when unablee to change audio volume for the given application
self.message(SM_CTX_ERROR, _("Unable to retrieve current application."))
return
newVolume = volume.GetMasterVolume() + volumeStep
if volumeStep > 0 and newVolume > 1:
Expand All @@ -157,13 +195,10 @@ def changeVolume(self, volumeStep):
newVolume = 0.0

volume.SetMasterVolume(newVolume, None)
#. Translators: Message indicating the volume's percentage ("95%").
ui.message(_("{volume}%".format(volume=int(round(newVolume * 100)))))
# Translators: Message indicating the volume's percentage ("95%").
self.message(SM_CTX_VOLUME_CHANGE, _("{volume}%".format(volume=int(round(newVolume * 100)))))

def cycleThroughApps(self, goForward):
"""Cycles through apps that are currently playing audio.
The goForward parameter indicates whether we want to cycle forward or backward in the ring.
"""
audioSessions = AudioUtilities.GetAllSessions()
sessions = []
sessions.append(self.master_volume)
Expand All @@ -184,22 +219,15 @@ def cycleThroughApps(self, goForward):
if newSession is None:
newSession = sessions[0]
self.curAppName = newSession.Process.name() if newSession.Process is not None else newSession.name
ui.message(self.getAppNameFromSession(newSession))
self.message(SM_CTX_APP_CHANGE, self.getAppNameFromSession(newSession))

def script_nextApp(self, gesture):
"""Focus the next application that is playing audio."""
self.cycleThroughApps(True)

def script_previousApp(self, gesture):
"""Focus the previous application that is playing audio."""
self.cycleThroughApps(False)

def script_soundManager(self, gesture):
"""Activates or deactivates the sound manager mode.
When activated, this scripts dynamically binds other gestures to perform sound manager
commands (adjusting the volume for instance). When deactivating, gestures are restored to
their default behavior.
"""
self.enabled = not self.enabled
if self.enabled is True:
tones.beep(660, 100)
Expand All @@ -222,11 +250,10 @@ def script_soundManager(self, gesture):
self.clearGestureBindings()
self.bindGestures(self.__gestures)

#. Translators: Main script help message.
# Translators: Main script help message.
script_soundManager.__doc__ = _("""Toggle volume control adjustment on or off""")

def findSessionByName(self, name):
"""Finds an audio session according to the process's name ("chrome.exe")."""
if name == self.master_volume.name:
return None,self.master_volume
sessions = AudioUtilities.GetAllSessions()
Expand All @@ -240,7 +267,28 @@ def findSessionByName(self, name):

__gestures = {
"kb:nvda+shift+v": "soundManager",
"kb:volumeDown": "volume_changed",
"kb:volumeUp": "volume_changed"
"kb:volumeDown": "onVolumeChanged",
"kb:volumeUp": "onVolumeChanged"
}
# The next class has been adapted from the ScreenCurtain module.


class SoundManagerPanel(gui.SettingsPanel):
# Translators: This is the label for the Sound manager settings panel.
title = _("Sound Manager")

def makeSettings(self, settingsSizer):
sHelper = gui.guiHelper.BoxSizerHelper(self, sizer=settingsSizer)
self.smSayVolumeChange = sHelper.addItem(wx.CheckBox(self, label=_("&announce volume changes")))
self.smSayVolumeChange.SetValue(config.conf[SM_CFG_SECTION]["sayVolumeChange"])

self.smSayAppChange = sHelper.addItem(wx.CheckBox(self, label=_("Announce a&pp names when cycling")))
self.smSayAppChange.SetValue(config.conf[SM_CFG_SECTION]["sayAppChange"])

def onSave(self):
config.conf[SM_CFG_SECTION]["sayVolumeChange"] = self.smSayVolumeChange.IsChecked()
config.conf[SM_CFG_SECTION]["sayAppChange"] = self.smSayAppChange.IsChecked()
if hasattr(config, "post_configProfileSwitch"):
config.post_configProfileSwitch.notify()
else:
config.configProfileSwitched.notify()
52 changes: 31 additions & 21 deletions addon/locale/fr/LC_MESSAGES/nvda.po
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: soundmanager 2019.05.4\n"
"Report-Msgid-Bugs-To: [email protected]\n"
"POT-Creation-Date: 2019-05-23 09:32+0200\n"
"POT-Creation-Date: 2019-05-29 17:12+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email protected]>\n"
Expand All @@ -17,58 +17,68 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

#. . Translators: The name of the add-on presented to the user.
#. Translators: The name of the add-on presented to the user.
#. Translators: This is the label for the Sound manager settings panel.
#. Add-on summary, usually the user visible name of the addon.
#. Translators: Summary for this add-on to be shown on installation and add-on information.
#: addon/globalPlugins/soundmanager/__init__.py:40 buildVars.py:17
#: addon/globalPlugins/soundmanager/__init__.py:67
#: addon/globalPlugins/soundmanager/__init__.py:278 buildVars.py:17
msgid "Sound Manager"
msgstr "Sound Manager"

#: addon/globalPlugins/soundmanager/__init__.py:53
#: addon/globalPlugins/soundmanager/__init__.py:81
msgid "Master volume"
msgstr "Volume principal"

#. . Translators: Spoken message when unablee to change audio volume for the given application.
#. . Translators: Spoken message when unablee to change audio volume for the given application
#: addon/globalPlugins/soundmanager/__init__.py:77
#: addon/globalPlugins/soundmanager/__init__.py:145
#. Translators: Spoken message when unablee to change audio volume for the given application.
#. Translators: Spoken message when unablee to change audio volume for the given application
#: addon/globalPlugins/soundmanager/__init__.py:124
#: addon/globalPlugins/soundmanager/__init__.py:189
msgid "Unable to retrieve current application."
msgstr "Impossible de déterminer l'application en avant-plan."

#. . Translators: Cannot mute the master volume.
#: addon/globalPlugins/soundmanager/__init__.py:81
#. Translators: Cannot mute the master volume.
#: addon/globalPlugins/soundmanager/__init__.py:128
msgid "Cannot mute the master volume."
msgstr "Impossible de couper le volume principal."

#. . Translator: Spoken message indicating that the app's sound is now muted.
#: addon/globalPlugins/soundmanager/__init__.py:88
#. Translator: Spoken message indicating that the app's sound is now muted.
#: addon/globalPlugins/soundmanager/__init__.py:135
#, python-brace-format
msgid "{app} muted"
msgstr "{app} muette"

#. . Translators: Spoken message indicating that the app's audio is now unmuted.
#: addon/globalPlugins/soundmanager/__init__.py:91
#. Translators: Spoken message indicating that the app's audio is now unmuted.
#: addon/globalPlugins/soundmanager/__init__.py:138
#, python-brace-format
msgid "{app} unmuted"
msgstr "{app} non muette"

#. . Translators: The current application does not pay audio.
#: addon/globalPlugins/soundmanager/__init__.py:110
#. Translators: The current application does not pay audio.
#: addon/globalPlugins/soundmanager/__init__.py:151
#, python-brace-format
msgid "{app} is not playing any sound."
msgstr "L'application {app} ne joue aucun son."
msgstr "{app} ne joue aucun son."

#. . Translators: Message indicating the volume's percentage ("95%").
#: addon/globalPlugins/soundmanager/__init__.py:155
#. Translators: Message indicating the volume's percentage ("95%").
#: addon/globalPlugins/soundmanager/__init__.py:199
#, python-brace-format
msgid "{volume}%"
msgstr "{volume} %"

#. . Translators: Main script help message.
#: addon/globalPlugins/soundmanager/__init__.py:220
#. Translators: Main script help message.
#: addon/globalPlugins/soundmanager/__init__.py:254
msgid "Toggle volume control adjustment on or off"
msgstr "Active^désactive le contrôle du volume."

#: addon/globalPlugins/soundmanager/__init__.py:282
msgid "&announce volume changes"
msgstr "&annoncer les valeurs lors de changements de volume"

#: addon/globalPlugins/soundmanager/__init__.py:285
msgid "Announce a&pp names when cycling"
msgstr "Annoncer le nom des a&pps lors de la sélection des volumes"

#. Add-on description
#. Translators: Long description to be shown for this add-on on add-on information from add-ons manager
#: buildVars.py:20
Expand Down
4 changes: 2 additions & 2 deletions addon/manifest.ini
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name = soundmanager
summary = "Sound Manager"
description = """Manages Windows and applications volumes directly within NVDA"""
author = "Yannick PLASSIARD <[email protected]>"
author = "Yannick PLASSIARD <[email protected]>, Danstiv <[email protected]>, Beqa Gozalishvili <[email protected]>"
url = None
version = 2019.05.1
version = 2019.05.6
docFileName = readme.html
minimumNVDAVersion = 2019.1
lastTestedNVDAVersion = 2019.1
Expand Down
Loading

0 comments on commit 721972e

Please sign in to comment.