Skip to content

Commit

Permalink
Version 2019.05.5 changes:
Browse files Browse the repository at this point in the history
- Integrated part of the work from the volumeManager add-on.
- Fixed French translations.
- Added the ability to exit sound manager volume control with Escape key.
- When opening volume control, either the current app is being focused, or the master volume
  if the current app is not playing any audio.
  • Loading branch information
Yannick Plassiard committed May 23, 2019
1 parent a538f10 commit 16f93af
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 32 deletions.
65 changes: 53 additions & 12 deletions addon/globalPlugins/soundmanager/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@

# System modules
import sys, os
# Windows Specific
from comtypes import CLSCTX_ALL
from ctypes import POINTER, cast


# NVDA core requirements
import globalPluginHandler
Expand All @@ -21,10 +25,16 @@

sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from . import pycaw
from pycaw.pycaw import AudioUtilities
from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume
del sys.path[-1]
addonHandler.initTranslation()

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

class GlobalPlugin(globalPluginHandler.GlobalPlugin):
#. Translators: The name of the add-on presented to the user.
scriptCategory = _("Sound Manager")
Expand All @@ -33,11 +43,24 @@ class GlobalPlugin(globalPluginHandler.GlobalPlugin):
curAppName = None


def __init__(self, *args, **kwargs):
super(globalPluginHandler.GlobalPlugin, self).__init__(*args, **kwargs)
self.devices = AudioUtilities.GetSpeakers()
self.interface = self.devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None)
self.master_volume = cast(self.interface, POINTER(IAudioEndpointVolume))
self.master_volume.SetMasterVolume = self.master_volume.SetMasterVolumeLevelScalar
self.master_volume.GetMasterVolume = self.master_volume.GetMasterVolumeLevelScalar
self.master_volume.name = _('Master volume')
self.master_volume.Process = MasterVolumeFakeProcess(self.master_volume.name)
self.master_volume.getDisplayName = lambda: self.master_volume.name


def getAppNameFromSession(self, session):
"""Returns an application's name formatted to be presented to the user from a given audio session."""

name = None
if session is None:
return self.master_volume.name
try:
name = session.getDisplayName()
except Exception as e:
Expand All @@ -48,10 +71,16 @@ def getAppNameFromSession(self, session):
def script_muteApp(self, gesture):
"""Mutes or unmute the focused application."""
session,volume = self.findSessionByName(self.curAppName)
if session == 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."))
return
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."))
return
else:
#. Translators: Cannot mute the master volume.
ui.message(_("Cannot mute the master volume."))
return

muted = volume.GetMute()
volume.SetMute(not muted, None)
if not muted:
Expand All @@ -61,7 +90,7 @@ def script_muteApp(self, gesture):
#. Translators: Spoken message indicating that the app's audio is now unmuted.
ui.message(_("{app} unmuted").format(app=self.getAppNameFromSession(session)))

def focusCurrentApplication(self):
def focusCurrentApplication(self, silent=False):
"""Selects the audio control for the current alsplication."""
obj = api.getFocusObject()
appName = None
Expand All @@ -70,13 +99,15 @@ def focusCurrentApplication(self):
except AttributeError:
appName = None
if appName is None:
#. Translators: Unable to determine focused application's name.
ui.message_("Unable to retrieve current application's name.")
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:
#. Translators: The current application does not pay audio.
ui.message(_("{app} is not playing any sound.".format(app=appName)))
if not silent:
#. Translators: The current application does not pay audio.
ui.message(_("{app} is not playing any sound.".format(app=appName)))
return False
self.curAppName = appName
return True
Expand Down Expand Up @@ -108,7 +139,8 @@ def script_volumeDown(self, gesture):
def changeVolume(self, volumeStep):
"""Adjusts the volume of the selected application using the given step value."""
session,volume = self.findSessionByName(self.curAppName)
if session == None and self.curAppName is not None:
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."))
return
Expand All @@ -128,6 +160,7 @@ def cycleThroughApps(self, goForward):
"""
audioSessions = AudioUtilities.GetAllSessions()
sessions = []
sessions.append(self.master_volume)
for session in audioSessions:
if session.Process is not None:
sessions.append(session)
Expand All @@ -144,7 +177,7 @@ def cycleThroughApps(self, goForward):
idx += 1
if newSession is None:
newSession = sessions[0]
self.curAppName = newSession.Process.name()
self.curAppName = newSession.Process.name() if newSession.Process is not None else newSession.name
ui.message(self.getAppNameFromSession(newSession))

def script_nextApp(self, gesture):
Expand All @@ -164,6 +197,9 @@ def script_soundManager(self, gesture):
self.enabled = not self.enabled
if self.enabled is True:
tones.beep(660, 100)

# Next gesture is bound to disable the volume control mode by pressing escape.
self.bindGesture("kb:escape", "soundManager")
self.bindGesture("kb:control+uparrow", "curAppVolumeUp")
self.bindGesture("kb:control+downarrow", "curAppVolumeDown")
self.bindGesture("kb:control+m", "curAppMute")
Expand All @@ -172,6 +208,9 @@ def script_soundManager(self, gesture):
self.bindGesture("kb:leftarrow", "previousApp")
self.bindGesture("kb:rightarrow", "nextApp")
self.bindGesture("kb:m", "muteApp")
if not self.focusCurrentApplication(True):
self.curAppName = self.master_volume.name

else:
tones.beep(440, 100)
self.clearGestureBindings()
Expand All @@ -182,6 +221,8 @@ def script_soundManager(self, gesture):

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()
for session in sessions:
if session.Process is not None:
Expand Down
46 changes: 37 additions & 9 deletions addon/locale/fr/LC_MESSAGES/nvda.po
Original file line number Diff line number Diff line change
@@ -1,43 +1,71 @@
# SoundManager French locale
# Copyright (C) 2019 Yannick Plassiard
# This file is distributed under the same license as the soundmanager package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
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"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email protected]>\n"
"Language: fr_FR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

#. . Translators: The name of the add-on presented to the user.
#. 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:30 buildVars.py:17
#: addon/globalPlugins/soundmanager/__init__.py:40 buildVars.py:17
msgid "Sound Manager"
msgstr "Sound Manager"

#: addon/globalPlugins/soundmanager/__init__.py:53
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:53
#: addon/globalPlugins/soundmanager/__init__.py:113
#: addon/globalPlugins/soundmanager/__init__.py:77
#: addon/globalPlugins/soundmanager/__init__.py:145
msgid "Unable to retrieve current application."
msgstr "Impossible de déterminer l'appliaction en avant-plan."
msgstr "Impossible de déterminer l'application en avant-plan."

#. . Translators: Cannot mute the master volume.
#: addon/globalPlugins/soundmanager/__init__.py:81
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:59
#: addon/globalPlugins/soundmanager/__init__.py:88
#, 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:62
#: addon/globalPlugins/soundmanager/__init__.py:91
#, python-brace-format
msgid "{app} unmuted"
msgstr "{app} non muette"

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

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

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

Expand Down
2 changes: 1 addition & 1 deletion buildVars.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
# version
"addon_version" : "2019.05.5",
# Author(s)
"addon_author" : u"Yannick PLASSIARD <[email protected]>",
"addon_author" : u"Yannick PLASSIARD <[email protected]>, Danstiv <[email protected]>, Beqa Gozalishvili <[email protected]>",
# URL for the add-on documentation support
"addon_url" : None,
# Documentation file name
Expand Down
Binary file removed soundmanager-2019.05.4.nvda-addon
Binary file not shown.
Binary file not shown.
29 changes: 19 additions & 10 deletions soundmanager.pot
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: soundmanager 2019.05.4\n"
"Project-Id-Version: soundmanager 2019.05.5\n"
"Report-Msgid-Bugs-To: [email protected]\n"
"POT-Creation-Date: 2019-05-20 15:10+0200\n"
"POT-Creation-Date: 2019-05-23 09:32+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 @@ -20,43 +20,52 @@ msgstr ""
#. . Translators: The name of the add-on presented to the user.
#. 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:30 buildVars.py:17
#: addon/globalPlugins/soundmanager/__init__.py:40 buildVars.py:17
msgid "Sound Manager"
msgstr ""

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

#. . 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:53
#: addon/globalPlugins/soundmanager/__init__.py:113
#: addon/globalPlugins/soundmanager/__init__.py:77
#: addon/globalPlugins/soundmanager/__init__.py:145
msgid "Unable to retrieve current application."
msgstr ""

#. . Translators: Cannot mute the master volume.
#: addon/globalPlugins/soundmanager/__init__.py:81
msgid "Cannot mute the master volume."
msgstr ""

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

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

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

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

#. . Translators: Main script help message.
#: addon/globalPlugins/soundmanager/__init__.py:181
#: addon/globalPlugins/soundmanager/__init__.py:220
msgid "Toggle volume control adjustment on or off"
msgstr ""

Expand Down

0 comments on commit 16f93af

Please sign in to comment.