Re: Addon for Sonos Desktop V1.5 released


Hi Ralf, James and all,

It is certain that the hierarchy of objects can vary from one version to another of a software.

I already encountered this problem with mp3DirectCut, for example.

But there are also situations where the ControlID will vary from one version of a software to another, it is the case for the Poedit software and without doubt, many others.

So, it's always very important to check the position, name, and references of the different objects at each version change of a software, and update our NVDA add-ons accordingly.


You wrote:

Since I can't get the control by classname and controlID, is there a better way to get it by UIA?

According to the information you have given us about the mute button, yes, you have the UIA automationID which is unique for the mute button.

Here is a test to perform in the NVDA Python console after positioning the focus on the window containing this object.

import UIAHandler
client object = UIAHandler.handler.clientObject

condition = clientObject.CreatePropertyCondition(UIAHandler.UIA_AutomationIdPropertyId, 'muteButton')
mainElement = clientObject.ElementFromHandleBuildCache(fg.windowHandle, UIAHandler.handler.baseCacheRequest)
muteObject = mainElement.FindFirstBuildCache(UIAHandler.TreeScope_Descendants, condition, UIAHandler.handler.baseCacheRequest)

After the imports, the first statement creates the condition to find the Mute button according to its UIA automationID.

Then we point to the UIA main object find through the handle of the foreground window (fg.windowHandle).

Next, we browse all descending UIA objects to find the object representing the muteButton.

The muteObject variable should then point to this object.

If you type:


You should be informed that this is the muteButton.

Hope this helps.

Kind regards,

Le 27/10/2019 à 11:42, Ralf Kefferpuetz a écrit :
You wont get it to run, you need at least one wireless Sonos speaker to install it.
Your suggestion would work as well, thanks for that.
Here is the developer info for the Mute button as an example. Since I can't get the control by classname and controlID, is there a better way to get it by UIA?
Developer info for navigator object:
name: u'B\xfcro Ralf Mute'
isFocusable: True
hasFocus: True
Python object: <NVDAObjects.UIA.UIA object at 0x053231B0>
Python class mro: (<class 'NVDAObjects.UIA.UIA'>, <class 'NVDAObjects.window.Window'>, <class 'NVDAObjects.NVDAObject'>, <class 'documentBase.TextContainerObject'>, <class 'baseObject.ScriptableObject'>, <class 'baseObject.AutoPropertyObject'>, <type 'object'>)
description: u'Mute is off'
location: RectLTWH(left=265, top=218, width=34, height=34)
value: None
appModule: <'sonos' (appName u'sonos', process ID 11636) at address 5323370>
appModule.productName: u' Sonos Desktop Controller'
appModule.productVersion: u'6, 0, 0, 34230'
TextInfo: <class 'NVDAObjects.NVDAObjectTextInfo'>
windowHandle: 68456
windowClassName: u'HwndWrapper[WpfDomain;;b9afaecb-dbb7-4aeb-8905-7d8494db734d]'
windowControlID: 0
windowStyle: 382664704
extendedWindowStyle: 262400
windowThreadID: 16880
windowText: u'Sonos'
displayText: u''
UIAElement: <POINTER(IUIAutomationElement) ptr=0x82e7cc0 at 5176620>
UIA automationID: muteButton
UIA frameworkID: WPF
UIA runtimeID: (7, 11636, 66317337)
UIA providerDescription: [pid:11636,providerId:0x0 Main(parent link):Unidentified Provider (managed:MS.Internal.Automation.ElementProxy, PresentationCore, Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35)]
UIA className: Button
UIA patterns available: LegacyIAccessiblePattern, SynchronizedInputPattern, TogglePattern

-----Original Message-----
From: <> On Behalf Of Noelia Ruiz
Sent: Sonntag, 27. Oktober 2019 11:05
Subject: Re: [nvda-addons] Addon for Sonos Desktop V1.5 released

Hi, I can't help in basic review since I don't have the application and don't know it. Just if it is needed I would try to install it.
Anyway, in case it's useful, what about using obj.getChild(index), replacing index for the proper number, for instance, 0 for the first child, 1 for the second and so on?

El 27/10/2019 a las 10:52, James Scholes escribió:
So can you obtain a list of children and then index into it? That way
you can at least check that the correct number of controls is present
for your purposes, protect against IndexErrors, and so on. This is
hugely fragile currently, and there isn't any error handling whatsoever.


James Scholes

On 26/10/2019 at 9:28 pm, Ralf Kefferpuetz wrote:
No, there are no classnames, I would have choosen that way if available.

-----Original Message-----
<> On Behalf Of James Scholes
Sent: Samstag, 26. Oktober 2019 18:46
Subject: Re: [nvda-addons] Addon for Sonos Desktop V1.5 released

I have concerns about lines like this:

s8 =

Partly because s1 to s8 aren't descriptive variable names. But
mainly because a single change in object layout will render it useless.

Is there a better way of doing it, which involves looking for class
names or whatever?


James Scholes

On 26/10/2019 at 4:37 pm, Ralf Kefferpuetz wrote:

addon for Sonos Desktop V1.5 is released with some new features and
python 3 ready.
You can get it here:

I added a bunch of hotkeys and adjusted the song information for
several services.

- control-1 - speaks current roomname, stationname and title of the
- double press control-1 - copies song title to the clipboard
- control-2 - opens the song title in a virtual invisible window to
read it back
- control-3 - opens Youtube in your default browser with the search
results for currently playing song (opens in a new
- alt-shift-v - reports current volume
- alt-shift-m - reports mute status
- control-m - toggles mute
- alt-shift-r - reports repeat status
- control-r - toggles repeat
- alt-shift-e - reports shuffle status
- control-e - toggles shuffle
- alt-shift-t - reports crossfade status
- control-t - toggles crossfade
- alt-shift-u - reports time playing
- alt-shift-i - reports scrub
- alt-shift-o - reports play time left

Best regards,

Join to automatically receive all group messages.