commit/StationPlaylist: 13 new changesets

  • From: commits-noreply@xxxxxxxxxxxxx
  • To: nvda-addons-commits@xxxxxxxxxxxxx
  • Date: Mon, 14 Nov 2016 04:17:30 -0000

13 new commits in StationPlaylist:

https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/4870a652cfda/
Changeset:   4870a652cfda
Branch:      None
User:        josephsl
Date:        2016-10-28 16:02:13+00:00
Summary:     GUI Helper (17.1-dev): Use GUI Helper services provided by NVDA 
2016.4 to make the UI presentation consistent with NVDA, with Alarms Center as 
a testbed.

In NVDA 2016.4, GUI Helper services were added that abstracts layout rendering 
away from vairous dialogs in hopes of making UI presentation consistent 
throughout NVDA. As an effort to do this for add-ons, GUI Helper will be used.
As stage 1, Alarms Center has been updated to use GUI Helper if available. This 
results in edit field for alarm settings moving to the right of the alarm 
prompt, with OK and Cancel buttons aligning to the right.
This change is destined for add-on 17.1. A full switchover to GUI Helper will 
happen later in 2017.

Affected #:  1 file

diff --git a/addon/appModules/splstudio/splconfig.py 
b/addon/appModules/splstudio/splconfig.py
index 38fe627..475b10a 100755
--- a/addon/appModules/splstudio/splconfig.py
+++ b/addon/appModules/splstudio/splconfig.py
@@ -21,6 +21,9 @@ import wx
 import splupdate
 from splmisc import SPLCountdownTimer, _metadataAnnouncer
 
+# 17.1: Is GUI Helper (running in 2016.4) available?
+useGUIHelper = hasattr(gui, "guiHelper")
+
 # Until NVDA Core uses Python 3 (preferably 3.3 or later), use a backported 
version of chain map class.
 # Backported by Jonathan Eunice.
 # Python Package Index: https://pypi.python.org/pypi/chainmap/1.0.2
@@ -898,34 +901,50 @@ class SPLAlarmDialog(wx.Dialog):
                super(SPLAlarmDialog, self).__init__(parent, wx.ID_ANY, 
titles[level])
                self.level = level
                mainSizer = wx.BoxSizer(wx.VERTICAL)
+               # 17.1: Utilize spin control enhancements from GUI helper 
(added in NVDA 2016.4).
+               # Only do this if 2016.4 is running, otherwise use classic mode 
for backward compatibility.)
+               if useGUIHelper:
+                       contentSizerHelper = gui.guiHelper.BoxSizerHelper(self, 
orientation=wx.VERTICAL)
 
                if level in (0, 1):
                        timeVal = 
SPLConfig["IntroOutroAlarms"]["EndOfTrackTime"]
-                       alarmSizer = wx.BoxSizer(wx.HORIZONTAL)
-                       alarmMessage = wx.StaticText(self, wx.ID_ANY, 
label=_("Enter &end of track alarm time in seconds (currently 
{curAlarmSec})").format(curAlarmSec = timeVal))
-                       alarmSizer.Add(alarmMessage)
-                       self.outroAlarmEntry = wx.SpinCtrl(self, wx.ID_ANY, 
min=1, max=59)
-                       self.outroAlarmEntry.SetValue(timeVal)
-                       self.outroAlarmEntry.SetSelection(-1, -1)
-                       alarmSizer.Add(self.outroAlarmEntry)
-                       
mainSizer.Add(alarmSizer,border=20,flag=wx.LEFT|wx.RIGHT|wx.TOP)
-                       
self.outroToggleCheckBox=wx.CheckBox(self,wx.NewId(),label=_("&Notify when end 
of track is approaching"))
-                       
self.outroToggleCheckBox.SetValue(SPLConfig["IntroOutroAlarms"]["SayEndOfTrack"])
-                       
mainSizer.Add(self.outroToggleCheckBox,border=10,flag=wx.BOTTOM)
+                       alarmLabel = _("Enter &end of track alarm time in 
seconds (currently {curAlarmSec})").format(curAlarmSec = timeVal)
+                       if useGUIHelper:
+                               self.outroAlarmEntry = 
contentSizerHelper.addLabeledControl(alarmLabel, 
gui.nvdaControls.SelectOnFocusSpinCtrl, min=1, max=59, initial=timeVal)
+                               
self.outroToggleCheckBox=contentSizerHelper.addItem(wx.CheckBox(self, 
label=_("&Notify when end of track is approaching")))
+                               self.outroToggleCheckBox.Value = 
SPLConfig["IntroOutroAlarms"]["SayEndOfTrack"]
+                       else:
+                               alarmSizer = wx.BoxSizer(wx.HORIZONTAL)
+                               alarmMessage = wx.StaticText(self, wx.ID_ANY, 
label=alarmLabel)
+                               alarmSizer.Add(alarmMessage)
+                               self.outroAlarmEntry = wx.SpinCtrl(self, 
wx.ID_ANY, min=1, max=59)
+                               self.outroAlarmEntry.SetValue(timeVal)
+                               self.outroAlarmEntry.SetSelection(-1, -1)
+                               alarmSizer.Add(self.outroAlarmEntry)
+                               
mainSizer.Add(alarmSizer,border=20,flag=wx.LEFT|wx.RIGHT|wx.TOP)
+                               
self.outroToggleCheckBox=wx.CheckBox(self,wx.NewId(),label=_("&Notify when end 
of track is approaching"))
+                               
self.outroToggleCheckBox.SetValue(SPLConfig["IntroOutroAlarms"]["SayEndOfTrack"])
+                               
mainSizer.Add(self.outroToggleCheckBox,border=10,flag=wx.BOTTOM)
 
                if level in (0, 2):
                        rampVal = SPLConfig["IntroOutroAlarms"]["SongRampTime"]
-                       alarmSizer = wx.BoxSizer(wx.HORIZONTAL)
-                       alarmMessage = wx.StaticText(self, wx.ID_ANY, 
label=_("Enter song &intro alarm time in seconds (currently 
{curRampSec})").format(curRampSec = rampVal))
-                       alarmSizer.Add(alarmMessage)
-                       self.introAlarmEntry = wx.SpinCtrl(self, wx.ID_ANY, 
min=1, max=9)
-                       self.introAlarmEntry.SetValue(rampVal)
-                       self.introAlarmEntry.SetSelection(-1, -1)
-                       alarmSizer.Add(self.introAlarmEntry)
-                       
mainSizer.Add(alarmSizer,border=20,flag=wx.LEFT|wx.RIGHT|wx.TOP)
-                       
self.introToggleCheckBox=wx.CheckBox(self,wx.NewId(),label=_("&Notify when end 
of introduction is approaching"))
-                       
self.introToggleCheckBox.SetValue(SPLConfig["IntroOutroAlarms"]["SaySongRamp"])
-                       
mainSizer.Add(self.introToggleCheckBox,border=10,flag=wx.BOTTOM)
+                       alarmLabel = _("Enter song &intro alarm time in seconds 
(currently {curRampSec})").format(curRampSec = rampVal)
+                       if useGUIHelper:
+                               self.introAlarmEntry = 
contentSizerHelper.addLabeledControl(alarmLabel, 
gui.nvdaControls.SelectOnFocusSpinCtrl, min=1, max=9, initial=rampVal)
+                               
self.introToggleCheckBox=contentSizerHelper.addItem(wx.CheckBox(self, 
label=_("&Notify when end of introduction is approaching")))
+                               self.introToggleCheckBox.Value = 
SPLConfig["IntroOutroAlarms"]["SaySongRamp"]
+                       else:
+                               alarmSizer = wx.BoxSizer(wx.HORIZONTAL)
+                               alarmMessage = wx.StaticText(self, wx.ID_ANY, 
label=alarmLabel)
+                               alarmSizer.Add(alarmMessage)
+                               self.introAlarmEntry = wx.SpinCtrl(self, 
wx.ID_ANY, min=1, max=9)
+                               self.introAlarmEntry.SetValue(rampVal)
+                               self.introAlarmEntry.SetSelection(-1, -1)
+                               alarmSizer.Add(self.introAlarmEntry)
+                               
mainSizer.Add(alarmSizer,border=20,flag=wx.LEFT|wx.RIGHT|wx.TOP)
+                               
self.introToggleCheckBox=wx.CheckBox(self,wx.NewId(),label=_("&Notify when end 
of introduction is approaching"))
+                               
self.introToggleCheckBox.SetValue(SPLConfig["IntroOutroAlarms"]["SaySongRamp"])
+                               
mainSizer.Add(self.introToggleCheckBox,border=10,flag=wx.BOTTOM)
 
                if level in (0, 3):
                        micAlarm = SPLConfig["MicrophoneAlarm"]["MicAlarm"]
@@ -936,24 +955,34 @@ class SPLAlarmDialog(wx.Dialog):
                        else:
                                # Translators: A dialog message when microphone 
alarm is disabled (set to 0).
                                timeMSG = _("Enter microphone alarm time in 
seconds (currently disabled, 0 disables the alarm)")
-                       alarmSizer = wx.BoxSizer(wx.VERTICAL)
-                       alarmMessage = wx.StaticText(self, wx.ID_ANY, 
label=timeMSG)
-                       alarmSizer.Add(alarmMessage)
-                       self.micAlarmEntry = wx.SpinCtrl(self, wx.ID_ANY, 
min=0, max=7200)
-                       self.micAlarmEntry.SetValue(micAlarm)
-                       self.micAlarmEntry.SetSelection(-1, -1)
-                       alarmSizer.Add(self.micAlarmEntry)
-                       alarmMessage = wx.StaticText(self, wx.ID_ANY, 
label=_("Microphone alarm interval"))
-                       alarmSizer.Add(alarmMessage)
-                       self.micIntervalEntry = wx.SpinCtrl(self, wx.ID_ANY, 
min=0, max=60)
-                       self.micIntervalEntry.SetValue(micAlarmInterval)
-                       self.micIntervalEntry.SetSelection(-1, -1)
-                       alarmSizer.Add(self.micIntervalEntry)
-                       
mainSizer.Add(alarmSizer,border=20,flag=wx.LEFT|wx.RIGHT|wx.TOP)
-
-               mainSizer.AddSizer(self.CreateButtonSizer(wx.OK|wx.CANCEL))
+                       micIntervalMSG = _("Microphone alarm interval")
+                       if useGUIHelper:
+                               self.micAlarmEntry = 
contentSizerHelper.addLabeledControl(timeMSG, 
gui.nvdaControls.SelectOnFocusSpinCtrl, min=0, max=7200, initial=micAlarm)
+                               self.micIntervalEntry = 
contentSizerHelper.addLabeledControl(micIntervalMSG, 
gui.nvdaControls.SelectOnFocusSpinCtrl, min=0, max=60, initial=micAlarmInterval)
+                       else:
+                               alarmSizer = wx.BoxSizer(wx.VERTICAL)
+                               alarmMessage = wx.StaticText(self, wx.ID_ANY, 
label=timeMSG)
+                               alarmSizer.Add(alarmMessage)
+                               self.micAlarmEntry = wx.SpinCtrl(self, 
wx.ID_ANY, min=0, max=7200)
+                               self.micAlarmEntry.SetValue(micAlarm)
+                               self.micAlarmEntry.SetSelection(-1, -1)
+                               alarmSizer.Add(self.micAlarmEntry)
+                               alarmMessage = wx.StaticText(self, wx.ID_ANY, 
label=micIntervalMSG)
+                               alarmSizer.Add(alarmMessage)
+                               self.micIntervalEntry = wx.SpinCtrl(self, 
wx.ID_ANY, min=0, max=60)
+                               self.micIntervalEntry.SetValue(micAlarmInterval)
+                               self.micIntervalEntry.SetSelection(-1, -1)
+                               alarmSizer.Add(self.micIntervalEntry)
+                               
mainSizer.Add(alarmSizer,border=20,flag=wx.LEFT|wx.RIGHT|wx.TOP)
+
+               if useGUIHelper:
+                       contentSizerHelper.addItem( 
self.CreateButtonSizer(wx.OK | wx.CANCEL))
+               else:
+                       
mainSizer.AddSizer(self.CreateButtonSizer(wx.OK|wx.CANCEL))
                self.Bind(wx.EVT_BUTTON,self.onOk,id=wx.ID_OK)
                self.Bind(wx.EVT_BUTTON,self.onCancel,id=wx.ID_CANCEL)
+               if useGUIHelper:
+                       mainSizer.Add(contentSizerHelper.sizer, 
border=gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
                mainSizer.Fit(self)
                self.SetSizer(mainSizer)
                self.Center(wx.BOTH | wx.CENTER_ON_SCREEN)


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/0a76d248accc/
Changeset:   0a76d248accc
Branch:      None
User:        josephsl
Date:        2016-10-28 16:58:18+00:00
Summary:     GUI Helper (17.1-dev): Reove unused list from Alarms Center.

Settings list is no longer filled in, as SPLConfig will be modified directly 
from Alarms Center, hence remove this unused variable.

Affected #:  1 file

diff --git a/addon/appModules/splstudio/splconfig.py 
b/addon/appModules/splstudio/splconfig.py
index 475b10a..207ee5a 100755
--- a/addon/appModules/splstudio/splconfig.py
+++ b/addon/appModules/splstudio/splconfig.py
@@ -996,7 +996,6 @@ class SPLAlarmDialog(wx.Dialog):
                import winUser
                if winUser.user32.FindWindowA("SPLStudio", None):
                        # Gather settings to be applied in section/key format.
-                       settings = []
                        if self.level in (0, 1):
                                SPLConfig["IntroOutroAlarms"]["EndOfTrackTime"] 
= self.outroAlarmEntry.GetValue()
                                SPLConfig["IntroOutroAlarms"]["SayEndOfTrack"] 
= self.outroToggleCheckBox.GetValue()


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/ed88357dec59/
Changeset:   ed88357dec59
Branch:      None
User:        josephsl
Date:        2016-11-04 15:46:44+00:00
Summary:     New profiles and metadata streaming dialogs: convert some controls 
to use GUI Helper services.

New profile name field in new profiles diaog, as well as checkboxes in metadata 
streaming dialog were converted (partially) to use GUI Helper services.
Also, in metadata streaming dialog, DSP Encoder checkbox is no longer given 
special dtatus - the label for this one, along with labels for other URL's, are 
now fetched from a dedicated labels tuple, which simplifies the for loop. Once 
GUI Helper services are fully implemented, the two loops in there (checkbox 
creation and making them visible) will be combined into a single loop, as GUi 
HHelper returns just the control which then can be appeneded to stream 
checkboxes collection in one move.
This is destined for add-on 17.1.

Affected #:  1 file

diff --git a/addon/appModules/splstudio/splconfui.py 
b/addon/appModules/splstudio/splconfui.py
index 9e0c174..59c887e 100755
--- a/addon/appModules/splstudio/splconfui.py
+++ b/addon/appModules/splstudio/splconfui.py
@@ -699,13 +699,19 @@ class NewProfileDialog(wx.Dialog):
                        dialogTitle = _("Copy Profile")
                super(NewProfileDialog, self).__init__(parent, 
title=dialogTitle)
                mainSizer = wx.BoxSizer(wx.VERTICAL)
+               if splconfig.useGUIHelper:
+                       newProfileSizerHelper = 
gui.guiHelper.BoxSizerHelper(self, orientation=wx.VERTICAL)
 
-               sizer = wx.BoxSizer(wx.HORIZONTAL)
-               # Translators: The label of a field to enter the name of a new 
broadcast profile.
-               sizer.Add(wx.StaticText(self, label=_("Profile name:")))
-               item = self.profileName = wx.TextCtrl(self)
-               sizer.Add(item)
-               mainSizer.Add(sizer)
+               if splconfig.useGUIHelper:
+                       self.profileName = 
newProfileSizerHelper.addLabeledControl(_("Profile name:"), wx.TextCtrl)
+                       mainSizer.Add(newProfileSizerHelper.sizer, border = 
gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
+               else:
+                       sizer = wx.BoxSizer(wx.HORIZONTAL)
+                       # Translators: The label of a field to enter the name 
of a new broadcast profile.
+                       sizer.Add(wx.StaticText(self, label=_("Profile name:")))
+                       item = self.profileName = wx.TextCtrl(self)
+                       sizer.Add(item)
+                       mainSizer.Add(sizer)
 
                sizer = wx.BoxSizer(wx.HORIZONTAL)
                # Translators: The label for a setting in SPL add-on dialog to 
select a base  profile for copying.
@@ -941,24 +947,19 @@ class MetadataStreamingDialog(wx.Dialog):
 
                # WX's CheckListBox isn't user friendly.
                # Therefore use checkboxes laid out across the top.
+               # 17.1: instead of two loops, just use one loop, with labels 
deriving from the below tuple.
+               # Only one loop is needed as helper.addLabelControl returns the 
checkbox itself and that can be appended.
+               streamLabels = ("DSP encoder", "URL 1", "URL 2", "URL 3", "URL 
4")
                self.checkedStreams = []
-               # Add the DSP encoder checkbox first before adding other URL's.
-               checkedDSP=wx.CheckBox(self,wx.NewId(),label="DSP encoder")
-               if func:
-                       streaming = func(0, 36, ret=True)
-                       if streaming == -1: streaming += 1
-                       checkedDSP.SetValue(streaming)
-               else: checkedDSP.SetValue(self.Parent.metadataStreams[0])
-               self.checkedStreams.append(checkedDSP)
-               # Now the rest.
-               for url in xrange(1, 5):
-                       checkedURL=wx.CheckBox(self,wx.NewId(),label="URL 
{URL}".format(URL = url))
+               # Add checkboxes for each stream, beginning with the DSP 
encoder.
+               for stream in xrange(5):
+                       
checkedStream=wx.CheckBox(self,wx.NewId(),label=streamLabels[stream])
                        if func:
-                               streaming = func(url, 36, ret=True)
+                               streaming = func(stream, 36, ret=True)
                                if streaming == -1: streaming += 1
-                               checkedURL.SetValue(streaming)
-                       else: 
checkedURL.SetValue(self.Parent.metadataStreams[url])
-                       self.checkedStreams.append(checkedURL)
+                               checkedStream.SetValue(streaming)
+                       else: 
checkedStream.SetValue(self.Parent.metadataStreams[stream])
+                       self.checkedStreams.append(checkedStream)
 
                mainSizer = wx.BoxSizer(wx.VERTICAL)
                if func is None: labelText=_("Select the URL for metadata 
streaming upon request.")
@@ -966,10 +967,19 @@ class MetadataStreamingDialog(wx.Dialog):
                label = wx.StaticText(self, wx.ID_ANY, label=labelText)
                mainSizer.Add(label,border=20,flag=wx.LEFT|wx.RIGHT|wx.TOP)
 
-               sizer = wx.BoxSizer(wx.HORIZONTAL)
+               if splconfig.useGUIHelper:
+                       sizer = gui.guiHelper.BoxSizerHelper(self, 
orientation=wx.HORIZONTAL)
+               else:
+                       sizer = wx.BoxSizer(wx.HORIZONTAL)
                for checkedStream in self.checkedStreams:
-                       sizer.Add(checkedStream)
-               mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
+                       if splconfig.useGUIHelper:
+                               sizer.addItem(checkedStream)
+                       else:
+                               sizer.Add(checkedStream)
+               if splconfig.useGUIHelper:
+                       mainSizer.Add(sizer.sizer, border = 
gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
+               else:
+                       mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
 
                if self.func is not None:
                        # Translators: A checkbox to let metadata streaming 
status be applied to the currently active broadcast profile.
@@ -1038,7 +1048,6 @@ class ColumnAnnouncementsDialog(wx.Dialog):
                        checkedColumn.SetValue(column in 
self.Parent.includedColumns)
                        self.checkedColumns3.append(checkedColumn)
 
-
                mainSizer = wx.BoxSizer(wx.VERTICAL)
                # Translators: Help text to select columns to be announced.
                label = wx.StaticText(self, wx.ID_ANY, label=_("Select columns 
to be announced (artist and title are announced by default"))


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/0059d600ccc0/
Changeset:   0059d600ccc0
Branch:      None
User:        josephsl
Date:        2016-11-08 14:42:06+00:00
Summary:     GUI Helper/Say status dialog 1 (17.1-dev0: Let checkboxes use GUI 
Helper services.

For status announcement dialog, because checkboxes and combo boxes are present, 
it is best to work on converting controls to use GUI Helper over two commits. 
Part 1 is checkboxes, while the second is the track name announcement combo box.

Affected #:  1 file

diff --git a/addon/appModules/splstudio/splconfui.py 
b/addon/appModules/splstudio/splconfui.py
index 59c887e..438e166 100755
--- a/addon/appModules/splstudio/splconfui.py
+++ b/addon/appModules/splstudio/splconfui.py
@@ -1233,21 +1233,38 @@ class SayStatusDialog(wx.Dialog):
                super(SayStatusDialog, self).__init__(parent, title=_("Status 
announcements"))
 
                mainSizer = wx.BoxSizer(wx.VERTICAL)
+               if splconfig.useGUIHelper:
+                       contentSizerHelper = gui.guiHelper.BoxSizerHelper(self, 
orientation=wx.VERTICAL)
 
-               # Translators: the label for a setting in SPL add-on settings 
to announce scheduled time.
-               
self.scheduledForCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Announce 
&scheduled time for the selected track"))
-               self.scheduledForCheckbox.SetValue(parent.scheduledFor)
-               mainSizer.Add(self.scheduledForCheckbox, 
border=10,flag=wx.BOTTOM)
+               if splconfig.useGUIHelper:
+                       # Translators: the label for a setting in SPL add-on 
settings to announce scheduled time.
+                       
self.scheduledForCheckbox=contentSizerHelper.addItem(wx.CheckBox(self, 
label=_("Announce &scheduled time for the selected track")))
+                       self.scheduledForCheckbox.Value = parent.scheduledFor
+               else:
+                       
self.scheduledForCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Announce 
&scheduled time for the selected track"))
+                       self.scheduledForCheckbox.SetValue(parent.scheduledFor)
+                       mainSizer.Add(self.scheduledForCheckbox, 
border=10,flag=wx.BOTTOM)
 
-               # Translators: the label for a setting in SPL add-on settings 
to announce listener count.
-               
self.listenerCountCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Announce 
&listener count"))
-               self.listenerCountCheckbox.SetValue(parent.listenerCount)
-               mainSizer.Add(self.listenerCountCheckbox, 
border=10,flag=wx.BOTTOM)
+               if splconfig.useGUIHelper:
+                       # Translators: the label for a setting in SPL add-on 
settings to announce listener count.
+                       
self.listenerCountCheckbox=contentSizerHelper.addItem(wx.CheckBox(self, 
label=_("Announce &listener count")))
+                       self.listenerCountCheckbox.Value = parent.listenerCount
+               else:
+                       # Translators: the label for a setting in SPL add-on 
settings to announce listener count.
+                       
self.listenerCountCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Announce 
&listener count"))
+                       
self.listenerCountCheckbox.SetValue(parent.listenerCount)
+                       mainSizer.Add(self.listenerCountCheckbox, 
border=10,flag=wx.BOTTOM)
 
-               # Translators: the label for a setting in SPL add-on settings 
to announce currently playing cart.
-               
self.cartNameCheckbox=wx.CheckBox(self,wx.NewId(),label=_("&Announce name of 
the currently playing cart"))
-               self.cartNameCheckbox.SetValue(parent.cartName)
-               mainSizer.Add(self.cartNameCheckbox, border=10,flag=wx.BOTTOM)
+               if splconfig.useGUIHelper:
+                       # Translators: the label for a setting in SPL add-on 
settings to announce currently playing cart.
+                       
self.cartNameCheckbox=contentSizerHelper.addItem(wx.CheckBox(self, 
label=_("&Announce name of the currently playing cart")))
+                       self.cartNameCheckbox.Value = parent.cartName
+               else:
+                       
self.cartNameCheckbox=wx.CheckBox(self,wx.NewId(),label=_("&Announce name of 
the currently playing cart"))
+                       self.cartNameCheckbox.SetValue(parent.cartName)
+                       mainSizer.Add(self.cartNameCheckbox, 
border=10,flag=wx.BOTTOM)
+               if splconfig.useGUIHelper:
+                       mainSizer.Add(contentSizerHelper.sizer, 
border=gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
 
                sizer = wx.BoxSizer(wx.HORIZONTAL)
                # Translators: the label for a setting in SPL add-on settings 
to announce currently playing track name.


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/4a55f69fb457/
Changeset:   4a55f69fb457
Branch:      None
User:        josephsl
Date:        2016-11-10 05:57:16+00:00
Summary:     Merge branch 'master' into guiHelper

Affected #:  4 files

diff --git a/addon/appModules/splstudio/__init__.py 
b/addon/appModules/splstudio/__init__.py
index 913d4a1..8d3a2f3 100755
--- a/addon/appModules/splstudio/__init__.py
+++ b/addon/appModules/splstudio/__init__.py
@@ -544,7 +544,7 @@ class ReversedDialog(Dialog):
                        childStates=child.states
                        childRole=child.role
                        #We don't want to handle invisible or unavailable 
objects
-                       if controlTypes.STATE_INVISIBLE in childStates or 
controlTypes.STATE_UNAVAILABLE in childStates: 
+                       if controlTypes.STATE_INVISIBLE in childStates or 
controlTypes.STATE_UNAVAILABLE in childStates:
                                continue
                        #For particular objects, we want to descend in to them 
and get their children's message text
                        if childRole in 
(controlTypes.ROLE_PROPERTYPAGE,controlTypes.ROLE_PANE,controlTypes.ROLE_PANEL,controlTypes.ROLE_WINDOW,controlTypes.ROLE_GROUPING,controlTypes.ROLE_PARAGRAPH,controlTypes.ROLE_SECTION,controlTypes.ROLE_TEXTFRAME,controlTypes.ROLE_UNKNOWN):
@@ -1084,7 +1084,7 @@ class AppModule(appModuleHandler.AppModule):
 
        def trackFinder(self, text, obj, directionForward=True, column=None):
                speech.cancelSpeech()
-               if column is None: 
+               if column is None:
                        column = [obj.indexOf("Artist"), obj.indexOf("Title")]
                track = self._trackLocator(text, obj=obj, 
directionForward=directionForward, columns=column)
                if track:
@@ -1569,6 +1569,7 @@ class AppModule(appModuleHandler.AppModule):
        _cachedStatusObjs = {}
 
        # Called in the layer commands themselves.
+       # 16.11: in Studio 5.20, it is possible to obtain some of these via the 
API, hence the API method is used.
        def status(self, infoIndex):
                # Look up the cached objects first for faster response.
                if not infoIndex in self._cachedStatusObjs:
@@ -1584,40 +1585,43 @@ class AppModule(appModuleHandler.AppModule):
                        else: return api.getFocusObject()
                return self._cachedStatusObjs[infoIndex]
 
+       # Status flags for Studio 5.20 API.
+       _statusBarMessages=(
+               ("Play status: Stopped","Play status: Playing"),
+               ("Automation Off","Automation On"),
+               ("Microphone Off","Microphone On"),
+               ("Line-In Off","Line-In On"),
+               ("Record to file Off","Record to file On"),
+               ("Cart Edit Off","Cart Edit On"),
+       )
+
+       # In the layer commands below, sayStatus function is used if screen 
objects or API must be used (API is for Studio 5.20 and later).
+       def sayStatus(self, index):
+               if self.SPLCurVersion < "5.20":
+                       status = 
self.status(self.SPLPlayStatus).getChild(index).name
+               else:
+                       status = 
self._statusBarMessages[index][statusAPI(index, 39, ret=True)]
+               ui.message(status if 
splconfig.SPLConfig["General"]["MessageVerbosity"] == "beginner" else 
status.split()[-1])
+
        # The layer commands themselves.
 
        def script_sayPlayStatus(self, gesture):
-               # Please do not translate the following messages.
-               if statusAPI(0, 104, ret=True):
-                       msg = "Play status: Playing" if 
splconfig.SPLConfig["General"]["MessageVerbosity"] == "beginner" else "Playing"
-               else:
-                       msg = "Play status: Stopped" if 
splconfig.SPLConfig["General"]["MessageVerbosity"] == "beginner" else "Stopped"
-               ui.message(msg)
+               self.sayStatus(0)
 
        def script_sayAutomationStatus(self, gesture):
-               obj = self.status(self.SPLPlayStatus).getChild(1)
-               msg = obj.name if 
splconfig.SPLConfig["General"]["MessageVerbosity"] == "beginner" else 
obj.name.split()[-1]
-               ui.message(msg)
+               self.sayStatus(1)
 
        def script_sayMicStatus(self, gesture):
-               obj = self.status(self.SPLPlayStatus).getChild(2)
-               msg = obj.name if 
splconfig.SPLConfig["General"]["MessageVerbosity"] == "beginner" else 
obj.name.split()[-1]
-               ui.message(msg)
+               self.sayStatus(2)
 
        def script_sayLineInStatus(self, gesture):
-               obj = self.status(self.SPLPlayStatus).getChild(3)
-               msg = obj.name if 
splconfig.SPLConfig["General"]["MessageVerbosity"] == "beginner" else 
obj.name.split()[-1]
-               ui.message(msg)
+               self.sayStatus(3)
 
        def script_sayRecToFileStatus(self, gesture):
-               obj = self.status(self.SPLPlayStatus).getChild(4)
-               msg = obj.name if 
splconfig.SPLConfig["General"]["MessageVerbosity"] == "beginner" else 
obj.name.split()[-1]
-               ui.message(msg)
+               self.sayStatus(4)
 
        def script_sayCartEditStatus(self, gesture):
-               obj = self.status(self.SPLPlayStatus).getChild(5)
-               msg = obj.name if 
splconfig.SPLConfig["General"]["MessageVerbosity"] == "beginner" else 
obj.name.split()[-1]
-               ui.message(msg)
+               self.sayStatus(5)
 
        def script_sayHourTrackDuration(self, gesture):
                statusAPI(0, 27, self.announceTime)

diff --git a/addon/appModules/splstudio/splconfui.py 
b/addon/appModules/splstudio/splconfui.py
index 438e166..cec564f 100755
--- a/addon/appModules/splstudio/splconfui.py
+++ b/addon/appModules/splstudio/splconfui.py
@@ -103,7 +103,7 @@ class SPLConfigDialog(gui.SettingsDialog):
                ("advanced",_("advanced"))]
                self.verbosityList = wx.Choice(self, wx.ID_ANY, choices=[x[1] 
for x in self.verbosityLevels])
                
currentVerbosity=splconfig.SPLConfig["General"]["MessageVerbosity"]
-               selection = (x for x,y in enumerate(self.verbosityLevels) if 
y[0]==currentVerbosity).next()  
+               selection = (x for x,y in enumerate(self.verbosityLevels) if 
y[0]==currentVerbosity).next()
                try:
                        self.verbosityList.SetSelection(selection)
                except:
@@ -159,7 +159,7 @@ class SPLConfigDialog(gui.SettingsDialog):
                ("both",_("Track intro and ending"))]
                self.brailleTimerList = wx.Choice(self, wx.ID_ANY, 
choices=[x[1] for x in self.brailleTimerValues])
                
brailleTimerCurValue=splconfig.SPLConfig["General"]["BrailleTimer"]
-               selection = (x for x,y in enumerate(self.brailleTimerValues) if 
y[0]==brailleTimerCurValue).next()  
+               selection = (x for x,y in enumerate(self.brailleTimerValues) if 
y[0]==brailleTimerCurValue).next()
                try:
                        self.brailleTimerList.SetSelection(selection)
                except:
@@ -197,7 +197,7 @@ class SPLConfigDialog(gui.SettingsDialog):
                ("both",_("both beep and message"))]
                self.alarmAnnounceList = wx.Choice(self, wx.ID_ANY, 
choices=[x[1] for x in self.alarmAnnounceValues])
                
alarmAnnounceCurValue=splconfig.SPLConfig["General"]["AlarmAnnounce"]
-               selection = (x for x,y in enumerate(self.alarmAnnounceValues) 
if y[0]==alarmAnnounceCurValue).next()  
+               selection = (x for x,y in enumerate(self.alarmAnnounceValues) 
if y[0]==alarmAnnounceCurValue).next()
                try:
                        self.alarmAnnounceList.SetSelection(selection)
                except:
@@ -218,7 +218,7 @@ class SPLConfigDialog(gui.SettingsDialog):
                ("numbers",_("Scan count"))]
                self.libScanList = wx.Choice(self, wx.ID_ANY, choices=[x[1] for 
x in self.libScanValues])
                
libScanCurValue=splconfig.SPLConfig["General"]["LibraryScanAnnounce"]
-               selection = (x for x,y in enumerate(self.libScanValues) if 
y[0]==libScanCurValue).next()  
+               selection = (x for x,y in enumerate(self.libScanValues) if 
y[0]==libScanCurValue).next()
                try:
                        self.libScanList.SetSelection(selection)
                except:
@@ -269,7 +269,7 @@ class SPLConfigDialog(gui.SettingsDialog):
                ("both",_("Both"))]
                self.trackCommentList = wx.Choice(self, wx.ID_ANY, 
choices=[x[1] for x in self.trackCommentValues])
                
trackCommentCurValue=splconfig.SPLConfig["General"]["TrackCommentAnnounce"]
-               selection = (x for x,y in enumerate(self.trackCommentValues) if 
y[0]==trackCommentCurValue).next()  
+               selection = (x for x,y in enumerate(self.trackCommentValues) if 
y[0]==trackCommentCurValue).next()
                try:
                        self.trackCommentList.SetSelection(selection)
                except:
@@ -293,7 +293,7 @@ class SPLConfigDialog(gui.SettingsDialog):
                ("instant",_("When instant switch profile is active"))]
                self.metadataList = wx.Choice(self, wx.ID_ANY, choices=[x[1] 
for x in self.metadataValues])
                
metadataCurValue=splconfig.SPLConfig["General"]["MetadataReminder"]
-               selection = (x for x,y in enumerate(self.metadataValues) if 
y[0]==metadataCurValue).next()  
+               selection = (x for x,y in enumerate(self.metadataValues) if 
y[0]==metadataCurValue).next()
                try:
                        self.metadataList.SetSelection(selection)
                except:
@@ -1276,7 +1276,7 @@ class SayStatusDialog(wx.Dialog):
                # Translators: One of the track name announcement options.
                ("off",_("off"))]
                self.trackAnnouncementList= wx.Choice(self, wx.ID_ANY, 
choices=[x[1] for x in self.trackAnnouncements])
-               selection = (x for x,y in enumerate(self.trackAnnouncements) if 
y[0]==parent.playingTrackName).next()  
+               selection = (x for x,y in enumerate(self.trackAnnouncements) if 
y[0]==parent.playingTrackName).next()
                try:
                        self.trackAnnouncementList.SetSelection(selection)
                except:
@@ -1359,7 +1359,7 @@ class AdvancedOptionsDialog(wx.Dialog):
                ("jfw","JAWS for Windows"),
                ("wineyes","Window-Eyes")]
                self.compatibilityList= wx.Choice(self, wx.ID_ANY, 
choices=[x[1] for x in self.compatibilityLayouts])
-               selection = (x for x,y in enumerate(self.compatibilityLayouts) 
if y[0]==self.Parent.compLayer).next()  
+               selection = (x for x,y in enumerate(self.compatibilityLayouts) 
if y[0]==self.Parent.compLayer).next()
                try:
                        self.compatibilityList.SetSelection(selection)
                except:

diff --git a/addon/doc/fr/readme.md b/addon/doc/fr/readme.md
index 1c90552..2680cf8 100644
--- a/addon/doc/fr/readme.md
+++ b/addon/doc/fr/readme.md
@@ -300,8 +300,9 @@ ci-dessus pour exécuter des commandes.
 
 ## Version 16.10.1/15.2-LTS
 
-* You can now interact with the track that was found via Track Finder
-  (Control+NVDA+F) such as checking it for playback.
+* Vous pouvez maintenant interagir avec la piste qui a été trouvé via la
+  Recherche de Piste (Contrôle+NVDA+F) tel que la vérification pour la
+  lecture.
 * Mises à jour des traductions.
 
 ## Changements pour la version 8.0/16.10/15.0-LTS

diff --git a/readme.md b/readme.md
index d763c7b..0f695be 100755
--- a/readme.md
+++ b/readme.md
@@ -175,6 +175,13 @@ If you are using Studio on a touchscreen computer running 
Windows 8 or later and
 * Added ability to press Control+Alt+up or down arrow keys to move between 
tracks (specifically, track columns) vertically just as one is moving to next 
or previous row in a table.
 * Added a combo box in add-on settings dialog to set which column should be 
announced when moving through columns vertically.
 
+## Version 16.11/15.3-LTS
+
+* Initial support for StationPlaylist Studio 5.20, including improved 
responsiveness when obtaining status information such as automation status via 
SPL Assistant layer.
+* Fixed issues related to searching for tracks and interacting with them, 
including inability to check or uncheck place marker track or a track found via 
time range finder dialog.
+* Column announcement order will no longer revert to default order after 
changing it.
+* 16.11: If broadcast profiles have errors, error dialog will no longer fail 
to show up.
+
 ## Version 16.10.1/15.2-LTS
 
 * You can now interact with the track that was found via Track Finder 
(Control+NVDA+F) such as checking it for playback.


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/0401fd196f09/
Changeset:   0401fd196f09
Branch:      None
User:        josephsl
Date:        2016-11-11 02:14:36+00:00
Summary:     GUI Helper services: reset config dialog fully converted, advanced 
options partially converted.

Checkboxes in advanced options dialog and update interview spin control has 
been converted.
All checkboxes in reset config dialog has been converted.

Affected #:  1 file

diff --git a/addon/appModules/splstudio/splconfui.py 
b/addon/appModules/splstudio/splconfui.py
index cec564f..b86e9ba 100755
--- a/addon/appModules/splstudio/splconfui.py
+++ b/addon/appModules/splstudio/splconfui.py
@@ -1319,20 +1319,28 @@ class AdvancedOptionsDialog(wx.Dialog):
                super(AdvancedOptionsDialog, self).__init__(parent, 
title=_("Advanced options"))
 
                mainSizer = wx.BoxSizer(wx.VERTICAL)
+               if splconfig.useGUIHelper:
+                       contentSizerHelper = gui.guiHelper.BoxSizerHelper(self, 
orientation=wx.VERTICAL)
 
-               sizer = wx.BoxSizer(wx.VERTICAL)
-               # Translators: A checkbox to toggle automatic add-on updates.
-               
self.autoUpdateCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Automatically 
check for add-on &updates"))
-               self.autoUpdateCheckbox.SetValue(self.Parent.autoUpdateCheck)
-               sizer.Add(self.autoUpdateCheckbox, border=10,flag=wx.TOP)
-               # Translators: The label for a setting in SPL add-on 
settings/advanced options to select automatic update interval in days.
-               label = wx.StaticText(self, wx.ID_ANY, label=_("Update 
&interval in days"))
-               sizer.Add(label)
-               self.updateInterval= wx.SpinCtrl(self, wx.ID_ANY, min=1, max=30)
-               self.updateInterval.SetValue(long(parent.updateInterval))
-               self.updateInterval.SetSelection(-1, -1)
-               sizer.Add(self.updateInterval)
-               mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
+               if splconfig.useGUIHelper:
+                       # Translators: A checkbox to toggle automatic add-on 
updates.
+                       
self.autoUpdateCheckbox=contentSizerHelper.addItem(wx.CheckBox(self,label=_("Automatically
 check for add-on &updates")))
+                       self.autoUpdateCheckbox.Value = 
self.Parent.autoUpdateCheck
+                       # Translators: The label for a setting in SPL add-on 
settings/advanced options to select automatic update interval in days.
+                       
self.updateInterval=contentSizerHelper.addLabeledControl(_("Update &interval in 
days"), gui.nvdaControls.SelectOnFocusSpinCtrl, min=1, max=30, 
initial=parent.updateInterval)
+                       mainSizer.Add(contentSizerHelper.sizer, 
border=gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
+               else:
+                       sizer = wx.BoxSizer(wx.VERTICAL)
+                       
self.autoUpdateCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Automatically 
check for add-on &updates"))
+                       
self.autoUpdateCheckbox.SetValue(self.Parent.autoUpdateCheck)
+                       sizer.Add(self.autoUpdateCheckbox, 
border=10,flag=wx.TOP)
+                       label = wx.StaticText(self, wx.ID_ANY, label=_("Update 
&interval in days"))
+                       sizer.Add(label)
+                       self.updateInterval= wx.SpinCtrl(self, wx.ID_ANY, 
min=1, max=30)
+                       
self.updateInterval.SetValue(long(parent.updateInterval))
+                       self.updateInterval.SetSelection(-1, -1)
+                       sizer.Add(self.updateInterval)
+                       mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
 
                # LTS and 8.x only.
                sizer = wx.BoxSizer(wx.HORIZONTAL)
@@ -1400,26 +1408,32 @@ class ResetDialog(wx.Dialog):
                super(ResetDialog, self).__init__(parent, title=_("Reset 
settings"))
 
                mainSizer = wx.BoxSizer(wx.VERTICAL)
+               if splconfig.useGUIHelper:
+                       contentSizerHelper = gui.guiHelper.BoxSizerHelper(self, 
orientation=wx.VERTICAL)
 
-               # Translators: the label for resetting profile triggers.
-               
self.resetInstantProfileCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Reset 
instant switch profile"))
-               self.resetInstantProfileCheckbox.SetValue(False)
-               mainSizer.Add(self.resetInstantProfileCheckbox, 
border=10,flag=wx.BOTTOM)
-
-               # Translators: the label for resetting profile triggers.
-               
self.resetTimeProfileCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Delete 
time-based profile database"))
-               self.resetTimeProfileCheckbox.SetValue(False)
-               mainSizer.Add(self.resetTimeProfileCheckbox, 
border=10,flag=wx.BOTTOM)
-
-                               # Translators: the label for resetting encoder 
settings.
-               
self.resetEncodersCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Remove encoder 
settings"))
-               self.resetEncodersCheckbox.SetValue(False)
-               mainSizer.Add(self.resetEncodersCheckbox, 
border=10,flag=wx.BOTTOM)
-
-               # Translators: the label for resetting track comments.
-               
self.resetTrackCommentsCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Erase 
track comments"))
-               self.resetTrackCommentsCheckbox.SetValue(False)
-               mainSizer.Add(self.resetTrackCommentsCheckbox, 
border=10,flag=wx.BOTTOM)
+               if splconfig.useGUIHelper:
+                       # Translators: the label for resetting profile triggers.
+                       
self.resetInstantProfileCheckbox=contentSizerHelper.addItem(wx.CheckBox(self,label=_("Reset
 instant switch profile")))
+                       # Translators: the label for resetting profile triggers.
+                       
self.resetTimeProfileCheckbox=contentSizerHelper.addItem(wx.CheckBox(self,label=_("Delete
 time-based profile database")))
+                       # Translators: the label for resetting encoder settings.
+                       
self.resetEncodersCheckbox=contentSizerHelper.addItem(wx.CheckBox(self,label=_("Remove
 encoder settings")))
+                       # Translators: the label for resetting track comments.
+                       
self.resetTrackCommentsCheckbox=contentSizerHelper.addItem(wx.CheckBox(self,label=_("Erase
 track comments")))
+                       mainSizer.Add(contentSizerHelper.sizer, 
border=gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
+               else:
+                       
self.resetInstantProfileCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Reset 
instant switch profile"))
+                       self.resetInstantProfileCheckbox.SetValue(False)
+                       mainSizer.Add(self.resetInstantProfileCheckbox, 
border=10,flag=wx.BOTTOM)
+                       
self.resetTimeProfileCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Delete 
time-based profile database"))
+                       self.resetTimeProfileCheckbox.SetValue(False)
+                       mainSizer.Add(self.resetTimeProfileCheckbox, 
border=10,flag=wx.BOTTOM)
+                       
self.resetEncodersCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Remove encoder 
settings"))
+                       self.resetEncodersCheckbox.SetValue(False)
+                       mainSizer.Add(self.resetEncodersCheckbox, 
border=10,flag=wx.BOTTOM)
+                       
self.resetTrackCommentsCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Erase 
track comments"))
+                       self.resetTrackCommentsCheckbox.SetValue(False)
+                       mainSizer.Add(self.resetTrackCommentsCheckbox, 
border=10,flag=wx.BOTTOM)
 
                mainSizer.Add(self.CreateButtonSizer(wx.OK | wx.CANCEL))
                self.Bind(wx.EVT_BUTTON, self.onOk, id=wx.ID_OK)


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/0ffe9e5bebfe/
Changeset:   0ffe9e5bebfe
Branch:      None
User:        josephsl
Date:        2016-11-12 04:31:39+00:00
Summary:     16.12: Use Studio 5.20 API to locate scheduled for and track 
starts in values.

Studio 5.20 API provides a way to locate scheduled for (track starts) and track 
starts in value (in case of the latter, it'll take up to a second for the new 
value to appear via the API). This provides huge performance improvements 
compared to object navigation emulation.
To avoid regressions, this will be available in 16.12 stable only.

Affected #:  1 file

diff --git a/addon/appModules/splstudio/__init__.py 
b/addon/appModules/splstudio/__init__.py
index 614111f..6daa07c 100755
--- a/addon/appModules/splstudio/__init__.py
+++ b/addon/appModules/splstudio/__init__.py
@@ -892,22 +892,24 @@ class AppModule(appModuleHandler.AppModule):
        # Specific to time scripts using Studio API.
        # 6.0: Split this into two functions: the announcer (below) and 
formatter.
        # 7.0: The ms (millisecond) argument will be used when announcing 
playlist remainder.
-       def announceTime(self, t, offset = None, ms=True):
+       # 16.12: Include hours by default unless told not to do so.
+       def announceTime(self, t, offset = None, ms=True, includeHours=None):
                if t <= 0:
                        ui.message("00:00")
                else:
-                       ui.message(self._ms2time(t, offset = offset, ms=ms))
+                       ui.message(self._ms2time(t, offset = offset, ms=ms, 
includeHours=includeHours))
 
        # Formatter: given time in milliseconds, convert it to human-readable 
format.
        # 7.0: There will be times when one will deal with time in seconds.
-       def _ms2time(self, t, offset = None, ms=True):
+       # 16.12: For some cases, do not include hour slot when trying to 
conform to what Studio displays.)
+       def _ms2time(self, t, offset = None, ms=True, includeHours=None):
                if t <= 0:
                        return "00:00"
                else:
                        if ms:
                                t = (t/1000) if not offset else (t/1000)+offset
                        mm, ss = divmod(t, 60)
-                       if mm > 59 and 
splconfig.SPLConfig["General"]["TimeHourAnnounce"]:
+                       if mm > 59 and (includeHours or (includeHours is None 
and splconfig.SPLConfig["General"]["TimeHourAnnounce"])):
                                hh, mm = divmod(mm, 60)
                                # Hour value is also filled with leading zero's.
                                # 6.1: Optimize the string builder so it can 
return just one string.
@@ -1668,13 +1670,27 @@ class AppModule(appModuleHandler.AppModule):
 
        def script_sayScheduledTime(self, gesture):
                # 7.0: Scheduled is the time originally specified in Studio, 
scheduled to play is broadcast time based on current time.
-               obj = self.status(self.SPLScheduled).firstChild
-               ui.message(obj.name)
+               # 16.12: use Studio API if using 5.20.
+               if self.productVersion >= "5.20":
+                       # Sometimes, hour markers return seconds.999 due to 
rounding error, hence this must be taken care of here.
+                       trackStarts = divmod(statusAPI(3, 27, ret=True), 1000)
+                       # For this method, all three components of time display 
(hour, minute, second) must be present.
+                       # In case it is midnight (0.0 but sometimes shown as 
86399.999 due to rounding error), just say "midnight".
+                       if trackStarts in ((86399, 999), (0, 0)): 
ui.message("00:00:00")
+                       else: self.announceTime(trackStarts[0]+1 if 
trackStarts[1] == 999 else trackStarts[0], ms=False)
+               else:
+                       obj = self.status(self.SPLScheduled).firstChild
+                       ui.message(obj.name)
 
        def script_sayScheduledToPlay(self, gesture):
                # 7.0: This script announces length of time remaining until the 
selected track will play.
-               obj = self.status(self.SPLScheduledToPlay).firstChild
-               ui.message(obj.name)
+               # 16.12: Use Studio 5.20 API (faster and more reliable).
+               if self.productVersion >= "5.20":
+                       # This is the only time hour announcement should not be 
used in order to conform to what's displayed on screen.
+                       self.announceTime(statusAPI(4, 27, ret=True), 
includeHours=False)
+               else:
+                       obj = self.status(self.SPLScheduledToPlay).firstChild
+                       ui.message(obj.name)
 
        def script_sayListenerCount(self, gesture):
                obj = self.status(self.SPLSystemStatus).getChild(3)


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/68827597559d/
Changeset:   68827597559d
Branch:      None
User:        josephsl
Date:        2016-11-12 05:12:16+00:00
Summary:     16.12/15.4-LTS: In Studio 5.20, cart insert status is announced.

Cart insert status is also shown on the same text box as cart edit mode status 
(in Studio 5.20 API, it's a separate wparam), thus handle this case. This also 
means verbosity check cannot be done for cart edit/insert mode status (a 
necessary sacrifice unless a better way is found later).
This is destined for 16.12 and 15.4-LTS.

Affected #:  2 files

diff --git a/addon/appModules/splstudio/__init__.py 
b/addon/appModules/splstudio/__init__.py
index 6daa07c..a4312f0 100755
--- a/addon/appModules/splstudio/__init__.py
+++ b/addon/appModules/splstudio/__init__.py
@@ -412,7 +412,7 @@ R: Record to file.
 Shift+R: Monitor library scan.
 S: Scheduled time for the track.
 Shift+S: Time until the selected track will play.
-T: Cart edit mode.
+T: Cart edit/insert mode.
 U: Studio up time.
 W: Weather and temperature.
 Y: Playlist modification.
@@ -444,7 +444,7 @@ R: Remaining time for the playlist.
 Shift+R: Monitor library scan.
 S: Scheduled time for the track.
 Shift+S: Time until the selected track will play.
-T: Cart edit mode.
+T: Cart edit/insert mode.
 U: Studio up time.
 W: Weather and temperature.
 Y: Playlist modification.
@@ -478,7 +478,7 @@ Shift+E: Record to file.
 Shift+R: Monitor library scan.
 S: Scheduled time for the track.
 Shift+S: Time until the selected track will play.
-T: Cart edit mode.
+T: Cart edit/insert mode.
 U: Studio up time.
 W: Weather and temperature.
 Y: Playlist modification.
@@ -1561,7 +1561,6 @@ class AppModule(appModuleHandler.AppModule):
                ("Microphone Off","Microphone On"),
                ("Line-In Off","Line-In On"),
                ("Record to file Off","Record to file On"),
-               ("Cart Edit Off","Cart Edit On"),
        )
 
        # In the layer commands below, sayStatus function is used if screen 
objects or API must be used (API is for Studio 5.20 and later).
@@ -1590,7 +1589,15 @@ class AppModule(appModuleHandler.AppModule):
                self.sayStatus(4)
 
        def script_sayCartEditStatus(self, gesture):
-               self.sayStatus(5)
+               # 16.12: Because cart edit status also shows cart insert 
status, verbosity control will not apply.
+               if self.productVersion >= "5.20":
+                       cartEdit = statusAPI(5, 39, ret=True)
+                       cartInsert = statusAPI(6, 39, ret=True)
+                       if cartEdit: ui.message("Cart Edit On")
+                       elif not cartEdit and cartInsert: ui.message("Cart 
Insert On")
+                       else: ui.message("Cart Edit Off")
+               else:
+                       
ui.message(self.status(self.SPLPlayStatus).getChild(5).name)
 
        def script_sayHourTrackDuration(self, gesture):
                statusAPI(0, 27, self.announceTime)

diff --git a/readme.md b/readme.md
index 739094c..9208a82 100755
--- a/readme.md
+++ b/readme.md
@@ -98,9 +98,9 @@ The available commands are:
 * Shift+P: Pitch of the current track.
 * R (Shift+E in JAWS and Window-Eyes layouts): Record to file enabled/disabled.
 * Shift+R: Monitor library scan in progress.
-* S: Track starts in (scheduled).
-* Shift+S: Time until selected track will play.
-* T: Cart edit mode on/off.
+* S: Track starts (scheduled).
+* Shift+S: Time until selected track will play (track starts in).
+* T: Cart edit/insert mode on/off.
 * U: Studio up time.
 * Control+Shift+U: Check for add-on updates.
 * W: Weather and temperature if configured.


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/21712f4b5a2e/
Changeset:   21712f4b5a2e
Branch:      None
User:        josephsl
Date:        2016-11-13 02:44:01+00:00
Summary:     16.12/15.4-LTS: support for new columns added in Track Tool 5.20.

Studio 5.20 adds hook functionality, and as such, these columns are now part of 
Track Tool and can now be navigated via columns explorer.
This is destined for 16.12 and 15.4-LTS.

Affected #:  1 file

diff --git a/addon/appModules/tracktool.py b/addon/appModules/tracktool.py
index 9ecada2..d280215 100755
--- a/addon/appModules/tracktool.py
+++ b/addon/appModules/tracktool.py
@@ -22,10 +22,12 @@ addonHandler.initTranslation()
 # Return a tuple of column headers.
 # This is just a thinly disguised indexOf function from Studio's track item 
class.
 def indexOf(ttVersion):
-       if ttVersion < "5.10":
+       if ttVersion.startswith("5.0"):
                return 
("Artist","Title","Duration","Cue","Overlap","Intro","Segue","Album","CD 
Code","URL 1","URL 2","Filename")
-       else:
+       elif ttVersion.startswith("5.1"):
                return 
("Artist","Title","Duration","Cue","Overlap","Intro","Outro","Segue","Year","Album","CD
 Code","URL 1","URL 
2","Genre","Mood","Energy","Tempo","BPM","Gender","Rating","Filename","Client","Other","Intro
 Link","Outro Link")
+       elif ttVersion.startswith("5.2"):
+               return 
("Artist","Title","Duration","Cue","Overlap","Intro","Outro","Segue","Hook 
Start","Hook Len","Year","Album","CD Code","URL 1","URL 
2","Genre","Mood","Energy","Tempo","BPM","Gender","Rating","Filename","Client","Other","Intro
 Link","Outro Link","ReplayGain")
 
 class TrackToolItem(IAccessible):
        """An entry in Track Tool, used to implement some exciting features.


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/60f4372ba622/
Changeset:   60f4372ba622
Branch:      None
User:        josephsl
Date:        2016-11-13 08:57:34+00:00
Summary:     GUI Helper services (17.1-dev): Code alignment, some combo boxes 
converted.

Align the code so once NVDA 2016.4 comes out, the old code can be discarded 
safely.
Converted some combo boxes, namely keyboard command layout (advanced settings) 
and track name announcement combo box (say status announcements).

Affected #:  1 file

diff --git a/addon/appModules/splstudio/splconfui.py 
b/addon/appModules/splstudio/splconfui.py
index b86e9ba..5410a90 100755
--- a/addon/appModules/splstudio/splconfui.py
+++ b/addon/appModules/splstudio/splconfui.py
@@ -1165,7 +1165,7 @@ class ColumnsExplorerDialog(wx.Dialog):
                else:
                        # Translators: The title of Columns Explorer 
configuration dialog.
                        actualTitle = _("Columns Explorer for Track Tool")
-                       cols = cols = 
("Artist","Title","Duration","Cue","Overlap","Intro","Segue","Filename","Album","CD
 Code","Outro","Year","URL 1","URL 2","Genre")
+                       cols = 
("Artist","Title","Duration","Cue","Overlap","Intro","Segue","Filename","Album","CD
 Code","Outro","Year","URL 1","URL 2","Genre")
                super(ColumnsExplorerDialog, self).__init__(parent, 
title=actualTitle)
 
                # Gather column slots.
@@ -1240,50 +1240,51 @@ class SayStatusDialog(wx.Dialog):
                        # Translators: the label for a setting in SPL add-on 
settings to announce scheduled time.
                        
self.scheduledForCheckbox=contentSizerHelper.addItem(wx.CheckBox(self, 
label=_("Announce &scheduled time for the selected track")))
                        self.scheduledForCheckbox.Value = parent.scheduledFor
-               else:
-                       
self.scheduledForCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Announce 
&scheduled time for the selected track"))
-                       self.scheduledForCheckbox.SetValue(parent.scheduledFor)
-                       mainSizer.Add(self.scheduledForCheckbox, 
border=10,flag=wx.BOTTOM)
-
-               if splconfig.useGUIHelper:
                        # Translators: the label for a setting in SPL add-on 
settings to announce listener count.
                        
self.listenerCountCheckbox=contentSizerHelper.addItem(wx.CheckBox(self, 
label=_("Announce &listener count")))
                        self.listenerCountCheckbox.Value = parent.listenerCount
-               else:
-                       # Translators: the label for a setting in SPL add-on 
settings to announce listener count.
-                       
self.listenerCountCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Announce 
&listener count"))
-                       
self.listenerCountCheckbox.SetValue(parent.listenerCount)
-                       mainSizer.Add(self.listenerCountCheckbox, 
border=10,flag=wx.BOTTOM)
-
-               if splconfig.useGUIHelper:
                        # Translators: the label for a setting in SPL add-on 
settings to announce currently playing cart.
                        
self.cartNameCheckbox=contentSizerHelper.addItem(wx.CheckBox(self, 
label=_("&Announce name of the currently playing cart")))
                        self.cartNameCheckbox.Value = parent.cartName
+                       # Translators: the label for a setting in SPL add-on 
settings to announce currently playing track name.
+                       labelText = _("&Track name announcement:")
+                       # Translators: One of the track name announcement 
options.
+                       self.trackAnnouncements=[("auto",_("automatic")),
+                       # Translators: One of the track name announcement 
options.
+                       ("background",_("while using other programs")),
+                       # Translators: One of the track name announcement 
options.
+                       ("off",_("off"))]
+                       
self.trackAnnouncementList=contentSizerHelper.addLabeledControl(labelText, 
wx.Choice, choices=[x[1] for x in self.trackAnnouncements])
+                       selection = (x for x,y in 
enumerate(self.trackAnnouncements) if y[0]==parent.playingTrackName).next()
+                       try:
+                               
self.trackAnnouncementList.SetSelection(selection)
+                       except:
+                               pass
+                       mainSizer.Add(contentSizerHelper.sizer, 
border=gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
                else:
+                       
self.scheduledForCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Announce 
&scheduled time for the selected track"))
+                       self.scheduledForCheckbox.SetValue(parent.scheduledFor)
+                       mainSizer.Add(self.scheduledForCheckbox, 
border=10,flag=wx.BOTTOM)
+                       
self.listenerCountCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Announce 
&listener count"))
+                       
self.listenerCountCheckbox.SetValue(parent.listenerCount)
+                       mainSizer.Add(self.listenerCountCheckbox, 
border=10,flag=wx.BOTTOM)
                        
self.cartNameCheckbox=wx.CheckBox(self,wx.NewId(),label=_("&Announce name of 
the currently playing cart"))
                        self.cartNameCheckbox.SetValue(parent.cartName)
                        mainSizer.Add(self.cartNameCheckbox, 
border=10,flag=wx.BOTTOM)
-               if splconfig.useGUIHelper:
-                       mainSizer.Add(contentSizerHelper.sizer, 
border=gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
-
-               sizer = wx.BoxSizer(wx.HORIZONTAL)
-               # Translators: the label for a setting in SPL add-on settings 
to announce currently playing track name.
-               label = wx.StaticText(self, wx.ID_ANY, label=_("&Track name 
announcement:"))
-               # Translators: One of the track name announcement options.
-               self.trackAnnouncements=[("auto",_("automatic")),
-               # Translators: One of the track name announcement options.
-               ("background",_("while using other programs")),
-               # Translators: One of the track name announcement options.
-               ("off",_("off"))]
-               self.trackAnnouncementList= wx.Choice(self, wx.ID_ANY, 
choices=[x[1] for x in self.trackAnnouncements])
-               selection = (x for x,y in enumerate(self.trackAnnouncements) if 
y[0]==parent.playingTrackName).next()
-               try:
-                       self.trackAnnouncementList.SetSelection(selection)
-               except:
-                       pass
-               sizer.Add(label)
-               sizer.Add(self.trackAnnouncementList)
-               mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
+                       sizer = wx.BoxSizer(wx.HORIZONTAL)
+                       label = wx.StaticText(self, wx.ID_ANY, label=_("&Track 
name announcement:"))
+                       self.trackAnnouncements=[("auto",_("automatic")),
+                       ("background",_("while using other programs")),
+                       ("off",_("off"))]
+                       self.trackAnnouncementList= wx.Choice(self, wx.ID_ANY, 
choices=[x[1] for x in self.trackAnnouncements])
+                       selection = (x for x,y in 
enumerate(self.trackAnnouncements) if y[0]==parent.playingTrackName).next()
+                       try:
+                               
self.trackAnnouncementList.SetSelection(selection)
+                       except:
+                               pass
+                       sizer.Add(label)
+                       sizer.Add(self.trackAnnouncementList)
+                       mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
 
                mainSizer.Add(self.CreateButtonSizer(wx.OK | wx.CANCEL))
                self.Bind(wx.EVT_BUTTON, self.onOk, id=wx.ID_OK)
@@ -1353,28 +1354,44 @@ class AdvancedOptionsDialog(wx.Dialog):
                sizer.Add(self.channels)
                mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
 
-               sizer = wx.BoxSizer(wx.HORIZONTAL)
-               # Translators: A checkbox to toggle if SPL Controller command 
can be used to invoke Assistant layer.
-               
self.splConPassthroughCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Allow SPL 
C&ontroller command to invoke SPL Assistant layer"))
-               
self.splConPassthroughCheckbox.SetValue(self.Parent.splConPassthrough)
-               sizer.Add(self.splConPassthroughCheckbox, border=10,flag=wx.TOP)
-               mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
-
-               sizer = wx.BoxSizer(wx.HORIZONTAL)
-               # Translators: The label for a setting in SPL add-on dialog to 
set keyboard layout for SPL Assistant.
-               label = wx.StaticText(self, wx.ID_ANY, label=_("SPL Assistant 
command &layout:"))
-               self.compatibilityLayouts=[("off","NVDA"),
-               ("jfw","JAWS for Windows"),
-               ("wineyes","Window-Eyes")]
-               self.compatibilityList= wx.Choice(self, wx.ID_ANY, 
choices=[x[1] for x in self.compatibilityLayouts])
-               selection = (x for x,y in enumerate(self.compatibilityLayouts) 
if y[0]==self.Parent.compLayer).next()
-               try:
-                       self.compatibilityList.SetSelection(selection)
-               except:
-                       pass
-               sizer.Add(label)
-               sizer.Add(self.compatibilityList)
-               mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
+               if splconfig.useGUIHelper:
+                       contentSizerHelper2 = 
gui.guiHelper.BoxSizerHelper(self, orientation=wx.VERTICAL)
+                       # Translators: A checkbox to toggle if SPL Controller 
command can be used to invoke Assistant layer.
+                       
self.splConPassthroughCheckbox=contentSizerHelper2.addItem(wx.CheckBox(self, 
label=_("Allow SPL C&ontroller command to invoke SPL Assistant layer")))
+                       self.splConPassthroughCheckbox.Value = 
self.Parent.splConPassthrough
+                       # Translators: The label for a setting in SPL add-on 
dialog to set keyboard layout for SPL Assistant.
+                       labelText = _("SPL Assistant command &layout:")
+                       self.compatibilityLayouts=[("off","NVDA"),
+                       ("jfw","JAWS for Windows"),
+                       ("wineyes","Window-Eyes")]
+                       
self.compatibilityList=contentSizerHelper2.addLabeledControl(labelText, 
wx.Choice, choices=[x[1] for x in self.compatibilityLayouts])
+                       selection = (x for x,y in 
enumerate(self.compatibilityLayouts) if y[0]==self.Parent.compLayer).next()
+                       try:
+                               self.compatibilityList.SetSelection(selection)
+                       except:
+                               pass
+                       mainSizer.Add(contentSizerHelper2.sizer, 
border=gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
+               else:
+                       sizer = wx.BoxSizer(wx.HORIZONTAL)
+                       
self.splConPassthroughCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Allow SPL 
C&ontroller command to invoke SPL Assistant layer"))
+                       
self.splConPassthroughCheckbox.SetValue(self.Parent.splConPassthrough)
+                       sizer.Add(self.splConPassthroughCheckbox, 
border=10,flag=wx.TOP)
+                       mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
+                       sizer = wx.BoxSizer(wx.HORIZONTAL)
+                       # Translators: The label for a setting in SPL add-on 
dialog to set keyboard layout for SPL Assistant.
+                       label = wx.StaticText(self, wx.ID_ANY, label=_("SPL 
Assistant command &layout:"))
+                       self.compatibilityLayouts=[("off","NVDA"),
+                       ("jfw","JAWS for Windows"),
+                       ("wineyes","Window-Eyes")]
+                       self.compatibilityList= wx.Choice(self, wx.ID_ANY, 
choices=[x[1] for x in self.compatibilityLayouts])
+                       selection = (x for x,y in 
enumerate(self.compatibilityLayouts) if y[0]==self.Parent.compLayer).next()
+                       try:
+                               self.compatibilityList.SetSelection(selection)
+                       except:
+                               pass
+                       sizer.Add(label)
+                       sizer.Add(self.compatibilityList)
+                       mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
 
                mainSizer.Add(self.CreateButtonSizer(wx.OK | wx.CANCEL))
                self.Bind(wx.EVT_BUTTON, self.onOk, id=wx.ID_OK)


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/e4c7ae769fc4/
Changeset:   e4c7ae769fc4
Branch:      None
User:        josephsl
Date:        2016-11-13 18:05:42+00:00
Summary:     GUI Helper services (17.1-dev): Several more combo boxes 
converted, Columns Explorer dialog fully converted.

In advanced settings, update channel combo box has been converted, and code 
structure has changed to allow easy deletion once compatibility mode is off.
Columns Explorer dialog (which houses combo boxes for columns shown on Studio 
and Track Tool) has been fully converted.

Affected #:  1 file

diff --git a/addon/appModules/splstudio/splconfui.py 
b/addon/appModules/splstudio/splconfui.py
index 5410a90..db2de3b 100755
--- a/addon/appModules/splstudio/splconfui.py
+++ b/addon/appModules/splstudio/splconfui.py
@@ -1166,41 +1166,61 @@ class ColumnsExplorerDialog(wx.Dialog):
                        # Translators: The title of Columns Explorer 
configuration dialog.
                        actualTitle = _("Columns Explorer for Track Tool")
                        cols = 
("Artist","Title","Duration","Cue","Overlap","Intro","Segue","Filename","Album","CD
 Code","Outro","Year","URL 1","URL 2","Genre")
-               super(ColumnsExplorerDialog, self).__init__(parent, 
title=actualTitle)
-
                # Gather column slots.
                self.columnSlots = []
 
+               super(ColumnsExplorerDialog, self).__init__(parent, 
title=actualTitle)
                mainSizer = wx.BoxSizer(wx.VERTICAL)
 
                # 7.0: Studio 5.0x columns.
                # 17.1: Five by two grid layout as 5.0x is no longer supported.
-               sizer = wx.BoxSizer(wx.HORIZONTAL)
+               if splconfig.useGUIHelper:
+                       sizer = gui.guiHelper.BoxSizerHelper(self, 
orientation=wx.HORIZONTAL)
+               else:
+                       sizer = wx.BoxSizer(wx.HORIZONTAL)
                for slot in xrange(5):
+                       if splconfig.useGUIHelper:
                        # Translators: The label for a setting in SPL add-on 
dialog to select column for this column slot.
-                       label = wx.StaticText(self, wx.ID_ANY, label=_("Slot 
{position}").format(position = slot+1))
-                       columns = wx.Choice(self, wx.ID_ANY, choices=cols)
+                               labelText = _("Slot 
{position}").format(position = slot+1)
+                               columns = sizer.addLabeledControl(labelText, 
wx.Choice, choices=cols)
+                       else:
+                               label = wx.StaticText(self, wx.ID_ANY, 
label=_("Slot {position}").format(position = slot+1))
+                               columns = wx.Choice(self, wx.ID_ANY, 
choices=cols)
+                               sizer.Add(label)
+                               sizer.Add(columns)
                        try:
                                
columns.SetSelection(cols.index(parent.exploreColumns[slot] if not tt else 
parent.exploreColumnsTT[slot]))
                        except:
                                pass
-                       sizer.Add(label)
-                       sizer.Add(columns)
                        self.columnSlots.append(columns)
-               mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
+               if splconfig.useGUIHelper:
+                       mainSizer.Add(sizer.sizer, 
border=gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
+               else:
+                       mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
 
-               sizer = wx.BoxSizer(wx.HORIZONTAL)
+               if splconfig.useGUIHelper:
+                       sizer = gui.guiHelper.BoxSizerHelper(self, 
orientation=wx.HORIZONTAL)
+               else:
+                       sizer = wx.BoxSizer(wx.HORIZONTAL)
                for slot in xrange(5, 10):
-                       label = wx.StaticText(self, wx.ID_ANY, label=_("Slot 
{position}").format(position = slot+1))
-                       columns = wx.Choice(self, wx.ID_ANY, choices=cols)
+                       if splconfig.useGUIHelper:
+                       # Translators: The label for a setting in SPL add-on 
dialog to select column for this column slot.
+                               labelText = _("Slot 
{position}").format(position = slot+1)
+                               columns = sizer.addLabeledControl(labelText, 
wx.Choice, choices=cols)
+                       else:
+                               label = wx.StaticText(self, wx.ID_ANY, 
label=_("Slot {position}").format(position = slot+1))
+                               columns = wx.Choice(self, wx.ID_ANY, 
choices=cols)
+                               sizer.Add(label)
+                               sizer.Add(columns)
                        try:
                                
columns.SetSelection(cols.index(parent.exploreColumns[slot] if not tt else 
parent.exploreColumnsTT[slot]))
                        except:
                                pass
-                       sizer.Add(label)
-                       sizer.Add(columns)
                        self.columnSlots.append(columns)
-               mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
+               if splconfig.useGUIHelper:
+                       mainSizer.Add(sizer.sizer, 
border=gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
+               else:
+                       mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
 
                mainSizer.Add(self.CreateButtonSizer(wx.OK | wx.CANCEL))
                self.Bind(wx.EVT_BUTTON, self.onOk, id=wx.ID_OK)
@@ -1329,56 +1349,53 @@ class AdvancedOptionsDialog(wx.Dialog):
                        self.autoUpdateCheckbox.Value = 
self.Parent.autoUpdateCheck
                        # Translators: The label for a setting in SPL add-on 
settings/advanced options to select automatic update interval in days.
                        
self.updateInterval=contentSizerHelper.addLabeledControl(_("Update &interval in 
days"), gui.nvdaControls.SelectOnFocusSpinCtrl, min=1, max=30, 
initial=parent.updateInterval)
-                       mainSizer.Add(contentSizerHelper.sizer, 
border=gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
-               else:
-                       sizer = wx.BoxSizer(wx.VERTICAL)
-                       
self.autoUpdateCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Automatically 
check for add-on &updates"))
-                       
self.autoUpdateCheckbox.SetValue(self.Parent.autoUpdateCheck)
-                       sizer.Add(self.autoUpdateCheckbox, 
border=10,flag=wx.TOP)
-                       label = wx.StaticText(self, wx.ID_ANY, label=_("Update 
&interval in days"))
-                       sizer.Add(label)
-                       self.updateInterval= wx.SpinCtrl(self, wx.ID_ANY, 
min=1, max=30)
-                       
self.updateInterval.SetValue(long(parent.updateInterval))
-                       self.updateInterval.SetSelection(-1, -1)
-                       sizer.Add(self.updateInterval)
-                       mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
-
-               # LTS and 8.x only.
-               sizer = wx.BoxSizer(wx.HORIZONTAL)
-               # Translators: The label for a combo box to select update 
channel.
-               label = wx.StaticText(self, wx.ID_ANY, label=_("&Add-on update 
channel:"))
-               self.channels= wx.Choice(self, wx.ID_ANY, 
choices=["development", "stable"])
-               self.updateChannels = ("dev", "stable")
-               
self.channels.SetSelection(self.updateChannels.index(self.Parent.updateChannel))
-               sizer.Add(label)
-               sizer.Add(self.channels)
-               mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
-
-               if splconfig.useGUIHelper:
-                       contentSizerHelper2 = 
gui.guiHelper.BoxSizerHelper(self, orientation=wx.VERTICAL)
+                       # LTS and 8.x only.
+                       # Translators: The label for a combo box to select 
update channel.
+                       labelText = _("&Add-on update channel:")
+                       
self.channels=contentSizerHelper.addLabeledControl(labelText, wx.Choice, 
choices=["development", "stable"])
+                       self.updateChannels = ("dev", "stable")
+                       
self.channels.SetSelection(self.updateChannels.index(self.Parent.updateChannel))
                        # Translators: A checkbox to toggle if SPL Controller 
command can be used to invoke Assistant layer.
-                       
self.splConPassthroughCheckbox=contentSizerHelper2.addItem(wx.CheckBox(self, 
label=_("Allow SPL C&ontroller command to invoke SPL Assistant layer")))
+                       
self.splConPassthroughCheckbox=contentSizerHelper.addItem(wx.CheckBox(self, 
label=_("Allow SPL C&ontroller command to invoke SPL Assistant layer")))
                        self.splConPassthroughCheckbox.Value = 
self.Parent.splConPassthrough
                        # Translators: The label for a setting in SPL add-on 
dialog to set keyboard layout for SPL Assistant.
                        labelText = _("SPL Assistant command &layout:")
                        self.compatibilityLayouts=[("off","NVDA"),
                        ("jfw","JAWS for Windows"),
                        ("wineyes","Window-Eyes")]
-                       
self.compatibilityList=contentSizerHelper2.addLabeledControl(labelText, 
wx.Choice, choices=[x[1] for x in self.compatibilityLayouts])
+                       
self.compatibilityList=contentSizerHelper.addLabeledControl(labelText, 
wx.Choice, choices=[x[1] for x in self.compatibilityLayouts])
                        selection = (x for x,y in 
enumerate(self.compatibilityLayouts) if y[0]==self.Parent.compLayer).next()
                        try:
                                self.compatibilityList.SetSelection(selection)
                        except:
                                pass
-                       mainSizer.Add(contentSizerHelper2.sizer, 
border=gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
+                       mainSizer.Add(contentSizerHelper.sizer, 
border=gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
                else:
+                       sizer = wx.BoxSizer(wx.VERTICAL)
+                       
self.autoUpdateCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Automatically 
check for add-on &updates"))
+                       
self.autoUpdateCheckbox.SetValue(self.Parent.autoUpdateCheck)
+                       sizer.Add(self.autoUpdateCheckbox, 
border=10,flag=wx.TOP)
+                       label = wx.StaticText(self, wx.ID_ANY, label=_("Update 
&interval in days"))
+                       sizer.Add(label)
+                       self.updateInterval= wx.SpinCtrl(self, wx.ID_ANY, 
min=1, max=30)
+                       
self.updateInterval.SetValue(long(parent.updateInterval))
+                       self.updateInterval.SetSelection(-1, -1)
+                       sizer.Add(self.updateInterval)
+                       mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
+                       sizer = wx.BoxSizer(wx.HORIZONTAL)
+                       label = wx.StaticText(self, wx.ID_ANY, label=_("&Add-on 
update channel:"))
+                       self.channels= wx.Choice(self, wx.ID_ANY, 
choices=["development", "stable"])
+                       self.updateChannels = ("dev", "stable")
+                       
self.channels.SetSelection(self.updateChannels.index(self.Parent.updateChannel))
+                       sizer.Add(label)
+                       sizer.Add(self.channels)
+                       mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
                        sizer = wx.BoxSizer(wx.HORIZONTAL)
                        
self.splConPassthroughCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Allow SPL 
C&ontroller command to invoke SPL Assistant layer"))
                        
self.splConPassthroughCheckbox.SetValue(self.Parent.splConPassthrough)
                        sizer.Add(self.splConPassthroughCheckbox, 
border=10,flag=wx.TOP)
                        mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
                        sizer = wx.BoxSizer(wx.HORIZONTAL)
-                       # Translators: The label for a setting in SPL add-on 
dialog to set keyboard layout for SPL Assistant.
                        label = wx.StaticText(self, wx.ID_ANY, label=_("SPL 
Assistant command &layout:"))
                        self.compatibilityLayouts=[("off","NVDA"),
                        ("jfw","JAWS for Windows"),


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/7c6026610d74/
Changeset:   7c6026610d74
Branch:      None
User:        josephsl
Date:        2016-11-14 04:13:47+00:00
Summary:     Merge branch '16.10.x'

Affected #:  8 files

diff --git a/addon/appModules/splstudio/__init__.py 
b/addon/appModules/splstudio/__init__.py
index 8d3a2f3..d87f80f 100755
--- a/addon/appModules/splstudio/__init__.py
+++ b/addon/appModules/splstudio/__init__.py
@@ -444,7 +444,7 @@ R: Record to file.
 Shift+R: Monitor library scan.
 S: Scheduled time for the track.
 Shift+S: Time until the selected track will play.
-T: Cart edit mode.
+T: Cart edit/insert mode.
 U: Studio up time.
 W: Weather and temperature.
 Y: Playlist modification.
@@ -476,7 +476,7 @@ R: Remaining time for the playlist.
 Shift+R: Monitor library scan.
 S: Scheduled time for the track.
 Shift+S: Time until the selected track will play.
-T: Cart edit mode.
+T: Cart edit/insert mode.
 U: Studio up time.
 W: Weather and temperature.
 Y: Playlist modification.
@@ -510,7 +510,7 @@ Shift+E: Record to file.
 Shift+R: Monitor library scan.
 S: Scheduled time for the track.
 Shift+S: Time until the selected track will play.
-T: Cart edit mode.
+T: Cart edit/insert mode.
 U: Studio up time.
 W: Weather and temperature.
 Y: Playlist modification.
@@ -925,22 +925,24 @@ class AppModule(appModuleHandler.AppModule):
        # Specific to time scripts using Studio API.
        # 6.0: Split this into two functions: the announcer (below) and 
formatter.
        # 7.0: The ms (millisecond) argument will be used when announcing 
playlist remainder.
-       def announceTime(self, t, offset = None, ms=True):
+       # 16.12: Include hours by default unless told not to do so.
+       def announceTime(self, t, offset = None, ms=True, includeHours=None):
                if t <= 0:
                        ui.message("00:00")
                else:
-                       ui.message(self._ms2time(t, offset = offset, ms=ms))
+                       ui.message(self._ms2time(t, offset = offset, ms=ms, 
includeHours=includeHours))
 
        # Formatter: given time in milliseconds, convert it to human-readable 
format.
        # 7.0: There will be times when one will deal with time in seconds.
-       def _ms2time(self, t, offset = None, ms=True):
+       # 16.12: For some cases, do not include hour slot when trying to 
conform to what Studio displays.)
+       def _ms2time(self, t, offset = None, ms=True, includeHours=None):
                if t <= 0:
                        return "00:00"
                else:
                        if ms:
                                t = (t/1000) if not offset else (t/1000)+offset
                        mm, ss = divmod(t, 60)
-                       if mm > 59 and 
splconfig.SPLConfig["General"]["TimeHourAnnounce"]:
+                       if mm > 59 and (includeHours or (includeHours is None 
and splconfig.SPLConfig["General"]["TimeHourAnnounce"])):
                                hh, mm = divmod(mm, 60)
                                # Hour value is also filled with leading zero's.
                                # 6.1: Optimize the string builder so it can 
return just one string.
@@ -1592,7 +1594,6 @@ class AppModule(appModuleHandler.AppModule):
                ("Microphone Off","Microphone On"),
                ("Line-In Off","Line-In On"),
                ("Record to file Off","Record to file On"),
-               ("Cart Edit Off","Cart Edit On"),
        )
 
        # In the layer commands below, sayStatus function is used if screen 
objects or API must be used (API is for Studio 5.20 and later).
@@ -1621,7 +1622,15 @@ class AppModule(appModuleHandler.AppModule):
                self.sayStatus(4)
 
        def script_sayCartEditStatus(self, gesture):
-               self.sayStatus(5)
+               # 16.12: Because cart edit status also shows cart insert 
status, verbosity control will not apply.
+               if self.productVersion >= "5.20":
+                       cartEdit = statusAPI(5, 39, ret=True)
+                       cartInsert = statusAPI(6, 39, ret=True)
+                       if cartEdit: ui.message("Cart Edit On")
+                       elif not cartEdit and cartInsert: ui.message("Cart 
Insert On")
+                       else: ui.message("Cart Edit Off")
+               else:
+                       
ui.message(self.status(self.SPLPlayStatus).getChild(5).name)
 
        def script_sayHourTrackDuration(self, gesture):
                statusAPI(0, 27, self.announceTime)
@@ -1701,13 +1710,27 @@ class AppModule(appModuleHandler.AppModule):
 
        def script_sayScheduledTime(self, gesture):
                # 7.0: Scheduled is the time originally specified in Studio, 
scheduled to play is broadcast time based on current time.
-               obj = self.status(self.SPLScheduled).firstChild
-               ui.message(obj.name)
+               # 16.12: use Studio API if using 5.20.
+               if self.productVersion >= "5.20":
+                       # Sometimes, hour markers return seconds.999 due to 
rounding error, hence this must be taken care of here.
+                       trackStarts = divmod(statusAPI(3, 27, ret=True), 1000)
+                       # For this method, all three components of time display 
(hour, minute, second) must be present.
+                       # In case it is midnight (0.0 but sometimes shown as 
86399.999 due to rounding error), just say "midnight".
+                       if trackStarts in ((86399, 999), (0, 0)): 
ui.message("00:00:00")
+                       else: self.announceTime(trackStarts[0]+1 if 
trackStarts[1] == 999 else trackStarts[0], ms=False)
+               else:
+                       obj = self.status(self.SPLScheduled).firstChild
+                       ui.message(obj.name)
 
        def script_sayScheduledToPlay(self, gesture):
                # 7.0: This script announces length of time remaining until the 
selected track will play.
-               obj = self.status(self.SPLScheduledToPlay).firstChild
-               ui.message(obj.name)
+               # 16.12: Use Studio 5.20 API (faster and more reliable).
+               if self.productVersion >= "5.20":
+                       # This is the only time hour announcement should not be 
used in order to conform to what's displayed on screen.
+                       self.announceTime(statusAPI(4, 27, ret=True), 
includeHours=False)
+               else:
+                       obj = self.status(self.SPLScheduledToPlay).firstChild
+                       ui.message(obj.name)
 
        def script_sayListenerCount(self, gesture):
                obj = self.status(self.SPLSystemStatus).getChild(3)

diff --git a/addon/appModules/tracktool.py b/addon/appModules/tracktool.py
index 9ecada2..d280215 100755
--- a/addon/appModules/tracktool.py
+++ b/addon/appModules/tracktool.py
@@ -22,10 +22,12 @@ addonHandler.initTranslation()
 # Return a tuple of column headers.
 # This is just a thinly disguised indexOf function from Studio's track item 
class.
 def indexOf(ttVersion):
-       if ttVersion < "5.10":
+       if ttVersion.startswith("5.0"):
                return 
("Artist","Title","Duration","Cue","Overlap","Intro","Segue","Album","CD 
Code","URL 1","URL 2","Filename")
-       else:
+       elif ttVersion.startswith("5.1"):
                return 
("Artist","Title","Duration","Cue","Overlap","Intro","Outro","Segue","Year","Album","CD
 Code","URL 1","URL 
2","Genre","Mood","Energy","Tempo","BPM","Gender","Rating","Filename","Client","Other","Intro
 Link","Outro Link")
+       elif ttVersion.startswith("5.2"):
+               return 
("Artist","Title","Duration","Cue","Overlap","Intro","Outro","Segue","Hook 
Start","Hook Len","Year","Album","CD Code","URL 1","URL 
2","Genre","Mood","Energy","Tempo","BPM","Gender","Rating","Filename","Client","Other","Intro
 Link","Outro Link","ReplayGain")
 
 class TrackToolItem(IAccessible):
        """An entry in Track Tool, used to implement some exciting features.

diff --git a/addon/doc/ar/readme.md b/addon/doc/ar/readme.md
index d4932cc..582e9d4 100644
--- a/addon/doc/ar/readme.md
+++ b/addon/doc/ar/readme.md
@@ -249,6 +249,19 @@ broadcast profiles.
 استخدم لمسة ب3 أصابع للانتقال لنمط اللمس, ثم استخدم أوامر اللمس المسرودة
 أعلاه لأداء المهام.
 
+## Version 16.11/15.3-LTS
+
+* Initial support for StationPlaylist Studio 5.20, including improved
+  responsiveness when obtaining status information such as automation status
+  via SPL Assistant layer.
+* Fixed issues related to searching for tracks and interacting with them,
+  including inability to check or uncheck place marker track or a track
+  found via time range finder dialog.
+* Column announcement order will no longer revert to default order after
+  changing it.
+* 16.11: If broadcast profiles have errors, error dialog will no longer fail
+  to show up.
+
 ## Version 16.10.1/15.2-LTS
 
 * You can now interact with the track that was found via Track Finder

diff --git a/addon/doc/es/readme.md b/addon/doc/es/readme.md
index b4598a2..6802756 100644
--- a/addon/doc/es/readme.md
+++ b/addon/doc/es/readme.md
@@ -286,6 +286,19 @@ realizar algunas órdenes de Studio desde la pantalla 
táctil. Primero utiliza
 un toque con tres dedos para cambiar a modo SPL, entonces utiliza las
 órdenes táctiles listadas arriba para llevar a cabo tareas.
 
+## Versión 16.11/15.3-LTS
+
+* Soporte inicial para StationPlaylist Studio 5.20, incluyendo la
+  sensibilidad mejorada al obtener información de estado tal como estado de
+  la automatización a través de SPL Assistant layer.
+* Corregidos fallos relativos a la búsqueda de pistas e interactuación con
+  ellas, incluyendo la incapacidad para marcar o desmarcar marcadores de
+  pista o una pista encontrada a través del diálogo buscador de rango.
+* El orden del anunciado de columnas ya no se revertirá al orden
+  predeterminado después de cambiarlo.
+* 16.11: Si los perfiles de transmisión tienen errores, el diálogo error ya
+  no fallará al desplegarse.
+
 ## Versión 16.10.1/15.2-LTS
 
 * Ahora puedes interactuar con la pista que se encontró a través del

diff --git a/addon/doc/fr/readme.md b/addon/doc/fr/readme.md
index 2680cf8..cf647c5 100644
--- a/addon/doc/fr/readme.md
+++ b/addon/doc/fr/readme.md
@@ -298,6 +298,20 @@ un écran tactile. Tout d'abord utiliser une tape à trois 
doigts pour
 basculer en mode SPL, puis utilisez les commandes tactile énumérées
 ci-dessus pour exécuter des commandes.
 
+## Version 16.11/15.3-LTS
+
+* Premier support de StationPlaylist Studio 5.20, y compris une meilleure
+  réactivité lors de l'obtention des informations du statut telles que
+  l’automatisation du statut via la couche de l'Assistant SPL.
+* Correction des problèmes liés à la recherche de pistes et à l'interaction
+  avec celles-ci, y compris l'impossibilité de cocher ou de décocher le
+  marqueur de position de piste ou une piste trouvée via le dialogue
+  Recherche de l'intervalle de temps.
+* L'ordre d'annonce des colonnes ne revient plus à l'ordre par défaut après
+  modification.
+* 16.11: Si les profils de diffusion ont des erreurs, la boîte de dialogue
+  d'erreur ne cessera plus de s'afficher.
+
 ## Version 16.10.1/15.2-LTS
 
 * Vous pouvez maintenant interagir avec la piste qui a été trouvé via la

diff --git a/addon/doc/gl/readme.md b/addon/doc/gl/readme.md
index c342004..06ca2bd 100644
--- a/addon/doc/gl/readme.md
+++ b/addon/doc/gl/readme.md
@@ -278,6 +278,19 @@ realizar algunhas ordes do Studio dende a pantalla tactil. 
Primeiro usa un
 toque con tgres dedos para cambiar a modo SPL, logo usa as ordes tactiles
 listadas arriba para realizar ordes.
 
+## Versión 16.11/15.3-LTS
+
+* Soporte inicial para StationPlaylist Studio 5.20, incluindo melloras de
+  sensibilidade ao se opter información de estado coma estado de
+  automatización a través do SPL Assistant layer.
+* Correxidos fallos relativos á procura para pistas e interactuación con
+  eles, incluindo a incapacidade para marcar ou desmarcar marcadores de
+  pista ou unha pista atopada a través do diálogo atopar rango de tempo.
+* A orde de anunciado de columnas xa non se reverterá á orde por defecto
+  despois de cambiala.
+* 16.11: Se o perfil transmisión ten erros, o diálogo erro xa non fallará ao
+  despregarse.
+
 ## Versión 16.10.1/15.2-LTS
 
 * Agora podes interactuar coa pista que se atopou a través Do Buscador de

diff --git a/addon/doc/hu/readme.md b/addon/doc/hu/readme.md
index 8def088..9a703c2 100644
--- a/addon/doc/hu/readme.md
+++ b/addon/doc/hu/readme.md
@@ -260,6 +260,19 @@ Amennyiben érintőképernyős számítógépen használja a 
Studiot Windows 8,
 parancsokat végrehajthat az érintőképernyőn is. Először 3 ujjas koppintással
 váltson SPL módra, és utána már használhatók az alább felsorolt parancsok.
 
+## Version 16.11/15.3-LTS
+
+* Initial support for StationPlaylist Studio 5.20, including improved
+  responsiveness when obtaining status information such as automation status
+  via SPL Assistant layer.
+* Fixed issues related to searching for tracks and interacting with them,
+  including inability to check or uncheck place marker track or a track
+  found via time range finder dialog.
+* Column announcement order will no longer revert to default order after
+  changing it.
+* 16.11: If broadcast profiles have errors, error dialog will no longer fail
+  to show up.
+
 ## Version 16.10.1/15.2-LTS
 
 * You can now interact with the track that was found via Track Finder

diff --git a/readme.md b/readme.md
index 0f695be..0cb0f1b 100755
--- a/readme.md
+++ b/readme.md
@@ -98,9 +98,9 @@ The available commands are:
 * Shift+P: Pitch of the current track.
 * R (Shift+E in JAWS and Window-Eyes layouts): Record to file enabled/disabled.
 * Shift+R: Monitor library scan in progress.
-* S: Track starts in (scheduled).
-* Shift+S: Time until selected track will play.
-* T: Cart edit mode on/off.
+* S: Track starts (scheduled).
+* Shift+S: Time until selected track will play (track starts in).
+* T: Cart edit/insert mode on/off.
 * U: Studio up time.
 * Control+Shift+U: Check for add-on updates.
 * W: Weather and temperature if configured.


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/c53953900518/
Changeset:   c53953900518
Branch:      master
User:        josephsl
Date:        2016-11-14 04:14:22+00:00
Summary:     Merge branch 'guiHelper'

Affected #:  2 files

diff --git a/addon/appModules/splstudio/splconfig.py 
b/addon/appModules/splstudio/splconfig.py
index 38fe627..207ee5a 100755
--- a/addon/appModules/splstudio/splconfig.py
+++ b/addon/appModules/splstudio/splconfig.py
@@ -21,6 +21,9 @@ import wx
 import splupdate
 from splmisc import SPLCountdownTimer, _metadataAnnouncer
 
+# 17.1: Is GUI Helper (running in 2016.4) available?
+useGUIHelper = hasattr(gui, "guiHelper")
+
 # Until NVDA Core uses Python 3 (preferably 3.3 or later), use a backported 
version of chain map class.
 # Backported by Jonathan Eunice.
 # Python Package Index: https://pypi.python.org/pypi/chainmap/1.0.2
@@ -898,34 +901,50 @@ class SPLAlarmDialog(wx.Dialog):
                super(SPLAlarmDialog, self).__init__(parent, wx.ID_ANY, 
titles[level])
                self.level = level
                mainSizer = wx.BoxSizer(wx.VERTICAL)
+               # 17.1: Utilize spin control enhancements from GUI helper 
(added in NVDA 2016.4).
+               # Only do this if 2016.4 is running, otherwise use classic mode 
for backward compatibility.)
+               if useGUIHelper:
+                       contentSizerHelper = gui.guiHelper.BoxSizerHelper(self, 
orientation=wx.VERTICAL)
 
                if level in (0, 1):
                        timeVal = 
SPLConfig["IntroOutroAlarms"]["EndOfTrackTime"]
-                       alarmSizer = wx.BoxSizer(wx.HORIZONTAL)
-                       alarmMessage = wx.StaticText(self, wx.ID_ANY, 
label=_("Enter &end of track alarm time in seconds (currently 
{curAlarmSec})").format(curAlarmSec = timeVal))
-                       alarmSizer.Add(alarmMessage)
-                       self.outroAlarmEntry = wx.SpinCtrl(self, wx.ID_ANY, 
min=1, max=59)
-                       self.outroAlarmEntry.SetValue(timeVal)
-                       self.outroAlarmEntry.SetSelection(-1, -1)
-                       alarmSizer.Add(self.outroAlarmEntry)
-                       
mainSizer.Add(alarmSizer,border=20,flag=wx.LEFT|wx.RIGHT|wx.TOP)
-                       
self.outroToggleCheckBox=wx.CheckBox(self,wx.NewId(),label=_("&Notify when end 
of track is approaching"))
-                       
self.outroToggleCheckBox.SetValue(SPLConfig["IntroOutroAlarms"]["SayEndOfTrack"])
-                       
mainSizer.Add(self.outroToggleCheckBox,border=10,flag=wx.BOTTOM)
+                       alarmLabel = _("Enter &end of track alarm time in 
seconds (currently {curAlarmSec})").format(curAlarmSec = timeVal)
+                       if useGUIHelper:
+                               self.outroAlarmEntry = 
contentSizerHelper.addLabeledControl(alarmLabel, 
gui.nvdaControls.SelectOnFocusSpinCtrl, min=1, max=59, initial=timeVal)
+                               
self.outroToggleCheckBox=contentSizerHelper.addItem(wx.CheckBox(self, 
label=_("&Notify when end of track is approaching")))
+                               self.outroToggleCheckBox.Value = 
SPLConfig["IntroOutroAlarms"]["SayEndOfTrack"]
+                       else:
+                               alarmSizer = wx.BoxSizer(wx.HORIZONTAL)
+                               alarmMessage = wx.StaticText(self, wx.ID_ANY, 
label=alarmLabel)
+                               alarmSizer.Add(alarmMessage)
+                               self.outroAlarmEntry = wx.SpinCtrl(self, 
wx.ID_ANY, min=1, max=59)
+                               self.outroAlarmEntry.SetValue(timeVal)
+                               self.outroAlarmEntry.SetSelection(-1, -1)
+                               alarmSizer.Add(self.outroAlarmEntry)
+                               
mainSizer.Add(alarmSizer,border=20,flag=wx.LEFT|wx.RIGHT|wx.TOP)
+                               
self.outroToggleCheckBox=wx.CheckBox(self,wx.NewId(),label=_("&Notify when end 
of track is approaching"))
+                               
self.outroToggleCheckBox.SetValue(SPLConfig["IntroOutroAlarms"]["SayEndOfTrack"])
+                               
mainSizer.Add(self.outroToggleCheckBox,border=10,flag=wx.BOTTOM)
 
                if level in (0, 2):
                        rampVal = SPLConfig["IntroOutroAlarms"]["SongRampTime"]
-                       alarmSizer = wx.BoxSizer(wx.HORIZONTAL)
-                       alarmMessage = wx.StaticText(self, wx.ID_ANY, 
label=_("Enter song &intro alarm time in seconds (currently 
{curRampSec})").format(curRampSec = rampVal))
-                       alarmSizer.Add(alarmMessage)
-                       self.introAlarmEntry = wx.SpinCtrl(self, wx.ID_ANY, 
min=1, max=9)
-                       self.introAlarmEntry.SetValue(rampVal)
-                       self.introAlarmEntry.SetSelection(-1, -1)
-                       alarmSizer.Add(self.introAlarmEntry)
-                       
mainSizer.Add(alarmSizer,border=20,flag=wx.LEFT|wx.RIGHT|wx.TOP)
-                       
self.introToggleCheckBox=wx.CheckBox(self,wx.NewId(),label=_("&Notify when end 
of introduction is approaching"))
-                       
self.introToggleCheckBox.SetValue(SPLConfig["IntroOutroAlarms"]["SaySongRamp"])
-                       
mainSizer.Add(self.introToggleCheckBox,border=10,flag=wx.BOTTOM)
+                       alarmLabel = _("Enter song &intro alarm time in seconds 
(currently {curRampSec})").format(curRampSec = rampVal)
+                       if useGUIHelper:
+                               self.introAlarmEntry = 
contentSizerHelper.addLabeledControl(alarmLabel, 
gui.nvdaControls.SelectOnFocusSpinCtrl, min=1, max=9, initial=rampVal)
+                               
self.introToggleCheckBox=contentSizerHelper.addItem(wx.CheckBox(self, 
label=_("&Notify when end of introduction is approaching")))
+                               self.introToggleCheckBox.Value = 
SPLConfig["IntroOutroAlarms"]["SaySongRamp"]
+                       else:
+                               alarmSizer = wx.BoxSizer(wx.HORIZONTAL)
+                               alarmMessage = wx.StaticText(self, wx.ID_ANY, 
label=alarmLabel)
+                               alarmSizer.Add(alarmMessage)
+                               self.introAlarmEntry = wx.SpinCtrl(self, 
wx.ID_ANY, min=1, max=9)
+                               self.introAlarmEntry.SetValue(rampVal)
+                               self.introAlarmEntry.SetSelection(-1, -1)
+                               alarmSizer.Add(self.introAlarmEntry)
+                               
mainSizer.Add(alarmSizer,border=20,flag=wx.LEFT|wx.RIGHT|wx.TOP)
+                               
self.introToggleCheckBox=wx.CheckBox(self,wx.NewId(),label=_("&Notify when end 
of introduction is approaching"))
+                               
self.introToggleCheckBox.SetValue(SPLConfig["IntroOutroAlarms"]["SaySongRamp"])
+                               
mainSizer.Add(self.introToggleCheckBox,border=10,flag=wx.BOTTOM)
 
                if level in (0, 3):
                        micAlarm = SPLConfig["MicrophoneAlarm"]["MicAlarm"]
@@ -936,24 +955,34 @@ class SPLAlarmDialog(wx.Dialog):
                        else:
                                # Translators: A dialog message when microphone 
alarm is disabled (set to 0).
                                timeMSG = _("Enter microphone alarm time in 
seconds (currently disabled, 0 disables the alarm)")
-                       alarmSizer = wx.BoxSizer(wx.VERTICAL)
-                       alarmMessage = wx.StaticText(self, wx.ID_ANY, 
label=timeMSG)
-                       alarmSizer.Add(alarmMessage)
-                       self.micAlarmEntry = wx.SpinCtrl(self, wx.ID_ANY, 
min=0, max=7200)
-                       self.micAlarmEntry.SetValue(micAlarm)
-                       self.micAlarmEntry.SetSelection(-1, -1)
-                       alarmSizer.Add(self.micAlarmEntry)
-                       alarmMessage = wx.StaticText(self, wx.ID_ANY, 
label=_("Microphone alarm interval"))
-                       alarmSizer.Add(alarmMessage)
-                       self.micIntervalEntry = wx.SpinCtrl(self, wx.ID_ANY, 
min=0, max=60)
-                       self.micIntervalEntry.SetValue(micAlarmInterval)
-                       self.micIntervalEntry.SetSelection(-1, -1)
-                       alarmSizer.Add(self.micIntervalEntry)
-                       
mainSizer.Add(alarmSizer,border=20,flag=wx.LEFT|wx.RIGHT|wx.TOP)
-
-               mainSizer.AddSizer(self.CreateButtonSizer(wx.OK|wx.CANCEL))
+                       micIntervalMSG = _("Microphone alarm interval")
+                       if useGUIHelper:
+                               self.micAlarmEntry = 
contentSizerHelper.addLabeledControl(timeMSG, 
gui.nvdaControls.SelectOnFocusSpinCtrl, min=0, max=7200, initial=micAlarm)
+                               self.micIntervalEntry = 
contentSizerHelper.addLabeledControl(micIntervalMSG, 
gui.nvdaControls.SelectOnFocusSpinCtrl, min=0, max=60, initial=micAlarmInterval)
+                       else:
+                               alarmSizer = wx.BoxSizer(wx.VERTICAL)
+                               alarmMessage = wx.StaticText(self, wx.ID_ANY, 
label=timeMSG)
+                               alarmSizer.Add(alarmMessage)
+                               self.micAlarmEntry = wx.SpinCtrl(self, 
wx.ID_ANY, min=0, max=7200)
+                               self.micAlarmEntry.SetValue(micAlarm)
+                               self.micAlarmEntry.SetSelection(-1, -1)
+                               alarmSizer.Add(self.micAlarmEntry)
+                               alarmMessage = wx.StaticText(self, wx.ID_ANY, 
label=micIntervalMSG)
+                               alarmSizer.Add(alarmMessage)
+                               self.micIntervalEntry = wx.SpinCtrl(self, 
wx.ID_ANY, min=0, max=60)
+                               self.micIntervalEntry.SetValue(micAlarmInterval)
+                               self.micIntervalEntry.SetSelection(-1, -1)
+                               alarmSizer.Add(self.micIntervalEntry)
+                               
mainSizer.Add(alarmSizer,border=20,flag=wx.LEFT|wx.RIGHT|wx.TOP)
+
+               if useGUIHelper:
+                       contentSizerHelper.addItem( 
self.CreateButtonSizer(wx.OK | wx.CANCEL))
+               else:
+                       
mainSizer.AddSizer(self.CreateButtonSizer(wx.OK|wx.CANCEL))
                self.Bind(wx.EVT_BUTTON,self.onOk,id=wx.ID_OK)
                self.Bind(wx.EVT_BUTTON,self.onCancel,id=wx.ID_CANCEL)
+               if useGUIHelper:
+                       mainSizer.Add(contentSizerHelper.sizer, 
border=gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
                mainSizer.Fit(self)
                self.SetSizer(mainSizer)
                self.Center(wx.BOTH | wx.CENTER_ON_SCREEN)
@@ -967,7 +996,6 @@ class SPLAlarmDialog(wx.Dialog):
                import winUser
                if winUser.user32.FindWindowA("SPLStudio", None):
                        # Gather settings to be applied in section/key format.
-                       settings = []
                        if self.level in (0, 1):
                                SPLConfig["IntroOutroAlarms"]["EndOfTrackTime"] 
= self.outroAlarmEntry.GetValue()
                                SPLConfig["IntroOutroAlarms"]["SayEndOfTrack"] 
= self.outroToggleCheckBox.GetValue()

diff --git a/addon/appModules/splstudio/splconfui.py 
b/addon/appModules/splstudio/splconfui.py
index 4f7405b..db2de3b 100755
--- a/addon/appModules/splstudio/splconfui.py
+++ b/addon/appModules/splstudio/splconfui.py
@@ -699,13 +699,19 @@ class NewProfileDialog(wx.Dialog):
                        dialogTitle = _("Copy Profile")
                super(NewProfileDialog, self).__init__(parent, 
title=dialogTitle)
                mainSizer = wx.BoxSizer(wx.VERTICAL)
+               if splconfig.useGUIHelper:
+                       newProfileSizerHelper = 
gui.guiHelper.BoxSizerHelper(self, orientation=wx.VERTICAL)
 
-               sizer = wx.BoxSizer(wx.HORIZONTAL)
-               # Translators: The label of a field to enter the name of a new 
broadcast profile.
-               sizer.Add(wx.StaticText(self, label=_("Profile name:")))
-               item = self.profileName = wx.TextCtrl(self)
-               sizer.Add(item)
-               mainSizer.Add(sizer)
+               if splconfig.useGUIHelper:
+                       self.profileName = 
newProfileSizerHelper.addLabeledControl(_("Profile name:"), wx.TextCtrl)
+                       mainSizer.Add(newProfileSizerHelper.sizer, border = 
gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
+               else:
+                       sizer = wx.BoxSizer(wx.HORIZONTAL)
+                       # Translators: The label of a field to enter the name 
of a new broadcast profile.
+                       sizer.Add(wx.StaticText(self, label=_("Profile name:")))
+                       item = self.profileName = wx.TextCtrl(self)
+                       sizer.Add(item)
+                       mainSizer.Add(sizer)
 
                sizer = wx.BoxSizer(wx.HORIZONTAL)
                # Translators: The label for a setting in SPL add-on dialog to 
select a base  profile for copying.
@@ -941,24 +947,19 @@ class MetadataStreamingDialog(wx.Dialog):
 
                # WX's CheckListBox isn't user friendly.
                # Therefore use checkboxes laid out across the top.
+               # 17.1: instead of two loops, just use one loop, with labels 
deriving from the below tuple.
+               # Only one loop is needed as helper.addLabelControl returns the 
checkbox itself and that can be appended.
+               streamLabels = ("DSP encoder", "URL 1", "URL 2", "URL 3", "URL 
4")
                self.checkedStreams = []
-               # Add the DSP encoder checkbox first before adding other URL's.
-               checkedDSP=wx.CheckBox(self,wx.NewId(),label="DSP encoder")
-               if func:
-                       streaming = func(0, 36, ret=True)
-                       if streaming == -1: streaming += 1
-                       checkedDSP.SetValue(streaming)
-               else: checkedDSP.SetValue(self.Parent.metadataStreams[0])
-               self.checkedStreams.append(checkedDSP)
-               # Now the rest.
-               for url in xrange(1, 5):
-                       checkedURL=wx.CheckBox(self,wx.NewId(),label="URL 
{URL}".format(URL = url))
+               # Add checkboxes for each stream, beginning with the DSP 
encoder.
+               for stream in xrange(5):
+                       
checkedStream=wx.CheckBox(self,wx.NewId(),label=streamLabels[stream])
                        if func:
-                               streaming = func(url, 36, ret=True)
+                               streaming = func(stream, 36, ret=True)
                                if streaming == -1: streaming += 1
-                               checkedURL.SetValue(streaming)
-                       else: 
checkedURL.SetValue(self.Parent.metadataStreams[url])
-                       self.checkedStreams.append(checkedURL)
+                               checkedStream.SetValue(streaming)
+                       else: 
checkedStream.SetValue(self.Parent.metadataStreams[stream])
+                       self.checkedStreams.append(checkedStream)
 
                mainSizer = wx.BoxSizer(wx.VERTICAL)
                if func is None: labelText=_("Select the URL for metadata 
streaming upon request.")
@@ -966,10 +967,19 @@ class MetadataStreamingDialog(wx.Dialog):
                label = wx.StaticText(self, wx.ID_ANY, label=labelText)
                mainSizer.Add(label,border=20,flag=wx.LEFT|wx.RIGHT|wx.TOP)
 
-               sizer = wx.BoxSizer(wx.HORIZONTAL)
+               if splconfig.useGUIHelper:
+                       sizer = gui.guiHelper.BoxSizerHelper(self, 
orientation=wx.HORIZONTAL)
+               else:
+                       sizer = wx.BoxSizer(wx.HORIZONTAL)
                for checkedStream in self.checkedStreams:
-                       sizer.Add(checkedStream)
-               mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
+                       if splconfig.useGUIHelper:
+                               sizer.addItem(checkedStream)
+                       else:
+                               sizer.Add(checkedStream)
+               if splconfig.useGUIHelper:
+                       mainSizer.Add(sizer.sizer, border = 
gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
+               else:
+                       mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
 
                if self.func is not None:
                        # Translators: A checkbox to let metadata streaming 
status be applied to the currently active broadcast profile.
@@ -1038,7 +1048,6 @@ class ColumnAnnouncementsDialog(wx.Dialog):
                        checkedColumn.SetValue(column in 
self.Parent.includedColumns)
                        self.checkedColumns3.append(checkedColumn)
 
-
                mainSizer = wx.BoxSizer(wx.VERTICAL)
                # Translators: Help text to select columns to be announced.
                label = wx.StaticText(self, wx.ID_ANY, label=_("Select columns 
to be announced (artist and title are announced by default"))
@@ -1156,42 +1165,62 @@ class ColumnsExplorerDialog(wx.Dialog):
                else:
                        # Translators: The title of Columns Explorer 
configuration dialog.
                        actualTitle = _("Columns Explorer for Track Tool")
-                       cols = cols = 
("Artist","Title","Duration","Cue","Overlap","Intro","Segue","Filename","Album","CD
 Code","Outro","Year","URL 1","URL 2","Genre")
-               super(ColumnsExplorerDialog, self).__init__(parent, 
title=actualTitle)
-
+                       cols = 
("Artist","Title","Duration","Cue","Overlap","Intro","Segue","Filename","Album","CD
 Code","Outro","Year","URL 1","URL 2","Genre")
                # Gather column slots.
                self.columnSlots = []
 
+               super(ColumnsExplorerDialog, self).__init__(parent, 
title=actualTitle)
                mainSizer = wx.BoxSizer(wx.VERTICAL)
 
                # 7.0: Studio 5.0x columns.
                # 17.1: Five by two grid layout as 5.0x is no longer supported.
-               sizer = wx.BoxSizer(wx.HORIZONTAL)
+               if splconfig.useGUIHelper:
+                       sizer = gui.guiHelper.BoxSizerHelper(self, 
orientation=wx.HORIZONTAL)
+               else:
+                       sizer = wx.BoxSizer(wx.HORIZONTAL)
                for slot in xrange(5):
+                       if splconfig.useGUIHelper:
                        # Translators: The label for a setting in SPL add-on 
dialog to select column for this column slot.
-                       label = wx.StaticText(self, wx.ID_ANY, label=_("Slot 
{position}").format(position = slot+1))
-                       columns = wx.Choice(self, wx.ID_ANY, choices=cols)
+                               labelText = _("Slot 
{position}").format(position = slot+1)
+                               columns = sizer.addLabeledControl(labelText, 
wx.Choice, choices=cols)
+                       else:
+                               label = wx.StaticText(self, wx.ID_ANY, 
label=_("Slot {position}").format(position = slot+1))
+                               columns = wx.Choice(self, wx.ID_ANY, 
choices=cols)
+                               sizer.Add(label)
+                               sizer.Add(columns)
                        try:
                                
columns.SetSelection(cols.index(parent.exploreColumns[slot] if not tt else 
parent.exploreColumnsTT[slot]))
                        except:
                                pass
-                       sizer.Add(label)
-                       sizer.Add(columns)
                        self.columnSlots.append(columns)
-               mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
+               if splconfig.useGUIHelper:
+                       mainSizer.Add(sizer.sizer, 
border=gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
+               else:
+                       mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
 
-               sizer = wx.BoxSizer(wx.HORIZONTAL)
+               if splconfig.useGUIHelper:
+                       sizer = gui.guiHelper.BoxSizerHelper(self, 
orientation=wx.HORIZONTAL)
+               else:
+                       sizer = wx.BoxSizer(wx.HORIZONTAL)
                for slot in xrange(5, 10):
-                       label = wx.StaticText(self, wx.ID_ANY, label=_("Slot 
{position}").format(position = slot+1))
-                       columns = wx.Choice(self, wx.ID_ANY, choices=cols)
+                       if splconfig.useGUIHelper:
+                       # Translators: The label for a setting in SPL add-on 
dialog to select column for this column slot.
+                               labelText = _("Slot 
{position}").format(position = slot+1)
+                               columns = sizer.addLabeledControl(labelText, 
wx.Choice, choices=cols)
+                       else:
+                               label = wx.StaticText(self, wx.ID_ANY, 
label=_("Slot {position}").format(position = slot+1))
+                               columns = wx.Choice(self, wx.ID_ANY, 
choices=cols)
+                               sizer.Add(label)
+                               sizer.Add(columns)
                        try:
                                
columns.SetSelection(cols.index(parent.exploreColumns[slot] if not tt else 
parent.exploreColumnsTT[slot]))
                        except:
                                pass
-                       sizer.Add(label)
-                       sizer.Add(columns)
                        self.columnSlots.append(columns)
-               mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
+               if splconfig.useGUIHelper:
+                       mainSizer.Add(sizer.sizer, 
border=gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
+               else:
+                       mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
 
                mainSizer.Add(self.CreateButtonSizer(wx.OK | wx.CANCEL))
                self.Bind(wx.EVT_BUTTON, self.onOk, id=wx.ID_OK)
@@ -1224,40 +1253,58 @@ class SayStatusDialog(wx.Dialog):
                super(SayStatusDialog, self).__init__(parent, title=_("Status 
announcements"))
 
                mainSizer = wx.BoxSizer(wx.VERTICAL)
-
-               # Translators: the label for a setting in SPL add-on settings 
to announce scheduled time.
-               
self.scheduledForCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Announce 
&scheduled time for the selected track"))
-               self.scheduledForCheckbox.SetValue(parent.scheduledFor)
-               mainSizer.Add(self.scheduledForCheckbox, 
border=10,flag=wx.BOTTOM)
-
-               # Translators: the label for a setting in SPL add-on settings 
to announce listener count.
-               
self.listenerCountCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Announce 
&listener count"))
-               self.listenerCountCheckbox.SetValue(parent.listenerCount)
-               mainSizer.Add(self.listenerCountCheckbox, 
border=10,flag=wx.BOTTOM)
-
-               # Translators: the label for a setting in SPL add-on settings 
to announce currently playing cart.
-               
self.cartNameCheckbox=wx.CheckBox(self,wx.NewId(),label=_("&Announce name of 
the currently playing cart"))
-               self.cartNameCheckbox.SetValue(parent.cartName)
-               mainSizer.Add(self.cartNameCheckbox, border=10,flag=wx.BOTTOM)
-
-               sizer = wx.BoxSizer(wx.HORIZONTAL)
-               # Translators: the label for a setting in SPL add-on settings 
to announce currently playing track name.
-               label = wx.StaticText(self, wx.ID_ANY, label=_("&Track name 
announcement:"))
-               # Translators: One of the track name announcement options.
-               self.trackAnnouncements=[("auto",_("automatic")),
-               # Translators: One of the track name announcement options.
-               ("background",_("while using other programs")),
-               # Translators: One of the track name announcement options.
-               ("off",_("off"))]
-               self.trackAnnouncementList= wx.Choice(self, wx.ID_ANY, 
choices=[x[1] for x in self.trackAnnouncements])
-               selection = (x for x,y in enumerate(self.trackAnnouncements) if 
y[0]==parent.playingTrackName).next()
-               try:
-                       self.trackAnnouncementList.SetSelection(selection)
-               except:
-                       pass
-               sizer.Add(label)
-               sizer.Add(self.trackAnnouncementList)
-               mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
+               if splconfig.useGUIHelper:
+                       contentSizerHelper = gui.guiHelper.BoxSizerHelper(self, 
orientation=wx.VERTICAL)
+
+               if splconfig.useGUIHelper:
+                       # Translators: the label for a setting in SPL add-on 
settings to announce scheduled time.
+                       
self.scheduledForCheckbox=contentSizerHelper.addItem(wx.CheckBox(self, 
label=_("Announce &scheduled time for the selected track")))
+                       self.scheduledForCheckbox.Value = parent.scheduledFor
+                       # Translators: the label for a setting in SPL add-on 
settings to announce listener count.
+                       
self.listenerCountCheckbox=contentSizerHelper.addItem(wx.CheckBox(self, 
label=_("Announce &listener count")))
+                       self.listenerCountCheckbox.Value = parent.listenerCount
+                       # Translators: the label for a setting in SPL add-on 
settings to announce currently playing cart.
+                       
self.cartNameCheckbox=contentSizerHelper.addItem(wx.CheckBox(self, 
label=_("&Announce name of the currently playing cart")))
+                       self.cartNameCheckbox.Value = parent.cartName
+                       # Translators: the label for a setting in SPL add-on 
settings to announce currently playing track name.
+                       labelText = _("&Track name announcement:")
+                       # Translators: One of the track name announcement 
options.
+                       self.trackAnnouncements=[("auto",_("automatic")),
+                       # Translators: One of the track name announcement 
options.
+                       ("background",_("while using other programs")),
+                       # Translators: One of the track name announcement 
options.
+                       ("off",_("off"))]
+                       
self.trackAnnouncementList=contentSizerHelper.addLabeledControl(labelText, 
wx.Choice, choices=[x[1] for x in self.trackAnnouncements])
+                       selection = (x for x,y in 
enumerate(self.trackAnnouncements) if y[0]==parent.playingTrackName).next()
+                       try:
+                               
self.trackAnnouncementList.SetSelection(selection)
+                       except:
+                               pass
+                       mainSizer.Add(contentSizerHelper.sizer, 
border=gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
+               else:
+                       
self.scheduledForCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Announce 
&scheduled time for the selected track"))
+                       self.scheduledForCheckbox.SetValue(parent.scheduledFor)
+                       mainSizer.Add(self.scheduledForCheckbox, 
border=10,flag=wx.BOTTOM)
+                       
self.listenerCountCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Announce 
&listener count"))
+                       
self.listenerCountCheckbox.SetValue(parent.listenerCount)
+                       mainSizer.Add(self.listenerCountCheckbox, 
border=10,flag=wx.BOTTOM)
+                       
self.cartNameCheckbox=wx.CheckBox(self,wx.NewId(),label=_("&Announce name of 
the currently playing cart"))
+                       self.cartNameCheckbox.SetValue(parent.cartName)
+                       mainSizer.Add(self.cartNameCheckbox, 
border=10,flag=wx.BOTTOM)
+                       sizer = wx.BoxSizer(wx.HORIZONTAL)
+                       label = wx.StaticText(self, wx.ID_ANY, label=_("&Track 
name announcement:"))
+                       self.trackAnnouncements=[("auto",_("automatic")),
+                       ("background",_("while using other programs")),
+                       ("off",_("off"))]
+                       self.trackAnnouncementList= wx.Choice(self, wx.ID_ANY, 
choices=[x[1] for x in self.trackAnnouncements])
+                       selection = (x for x,y in 
enumerate(self.trackAnnouncements) if y[0]==parent.playingTrackName).next()
+                       try:
+                               
self.trackAnnouncementList.SetSelection(selection)
+                       except:
+                               pass
+                       sizer.Add(label)
+                       sizer.Add(self.trackAnnouncementList)
+                       mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
 
                mainSizer.Add(self.CreateButtonSizer(wx.OK | wx.CANCEL))
                self.Bind(wx.EVT_BUTTON, self.onOk, id=wx.ID_OK)
@@ -1293,54 +1340,75 @@ class AdvancedOptionsDialog(wx.Dialog):
                super(AdvancedOptionsDialog, self).__init__(parent, 
title=_("Advanced options"))
 
                mainSizer = wx.BoxSizer(wx.VERTICAL)
-
-               sizer = wx.BoxSizer(wx.VERTICAL)
-               # Translators: A checkbox to toggle automatic add-on updates.
-               
self.autoUpdateCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Automatically 
check for add-on &updates"))
-               self.autoUpdateCheckbox.SetValue(self.Parent.autoUpdateCheck)
-               sizer.Add(self.autoUpdateCheckbox, border=10,flag=wx.TOP)
-               # Translators: The label for a setting in SPL add-on 
settings/advanced options to select automatic update interval in days.
-               label = wx.StaticText(self, wx.ID_ANY, label=_("Update 
&interval in days"))
-               sizer.Add(label)
-               self.updateInterval= wx.SpinCtrl(self, wx.ID_ANY, min=1, max=30)
-               self.updateInterval.SetValue(long(parent.updateInterval))
-               self.updateInterval.SetSelection(-1, -1)
-               sizer.Add(self.updateInterval)
-               mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
-
-               # LTS and 8.x only.
-               sizer = wx.BoxSizer(wx.HORIZONTAL)
-               # Translators: The label for a combo box to select update 
channel.
-               label = wx.StaticText(self, wx.ID_ANY, label=_("&Add-on update 
channel:"))
-               self.channels= wx.Choice(self, wx.ID_ANY, 
choices=["development", "stable"])
-               self.updateChannels = ("dev", "stable")
-               
self.channels.SetSelection(self.updateChannels.index(self.Parent.updateChannel))
-               sizer.Add(label)
-               sizer.Add(self.channels)
-               mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
-
-               sizer = wx.BoxSizer(wx.HORIZONTAL)
-               # Translators: A checkbox to toggle if SPL Controller command 
can be used to invoke Assistant layer.
-               
self.splConPassthroughCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Allow SPL 
C&ontroller command to invoke SPL Assistant layer"))
-               
self.splConPassthroughCheckbox.SetValue(self.Parent.splConPassthrough)
-               sizer.Add(self.splConPassthroughCheckbox, border=10,flag=wx.TOP)
-               mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
-
-               sizer = wx.BoxSizer(wx.HORIZONTAL)
-               # Translators: The label for a setting in SPL add-on dialog to 
set keyboard layout for SPL Assistant.
-               label = wx.StaticText(self, wx.ID_ANY, label=_("SPL Assistant 
command &layout:"))
-               self.compatibilityLayouts=[("off","NVDA"),
-               ("jfw","JAWS for Windows"),
-               ("wineyes","Window-Eyes")]
-               self.compatibilityList= wx.Choice(self, wx.ID_ANY, 
choices=[x[1] for x in self.compatibilityLayouts])
-               selection = (x for x,y in enumerate(self.compatibilityLayouts) 
if y[0]==self.Parent.compLayer).next()
-               try:
-                       self.compatibilityList.SetSelection(selection)
-               except:
-                       pass
-               sizer.Add(label)
-               sizer.Add(self.compatibilityList)
-               mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
+               if splconfig.useGUIHelper:
+                       contentSizerHelper = gui.guiHelper.BoxSizerHelper(self, 
orientation=wx.VERTICAL)
+
+               if splconfig.useGUIHelper:
+                       # Translators: A checkbox to toggle automatic add-on 
updates.
+                       
self.autoUpdateCheckbox=contentSizerHelper.addItem(wx.CheckBox(self,label=_("Automatically
 check for add-on &updates")))
+                       self.autoUpdateCheckbox.Value = 
self.Parent.autoUpdateCheck
+                       # Translators: The label for a setting in SPL add-on 
settings/advanced options to select automatic update interval in days.
+                       
self.updateInterval=contentSizerHelper.addLabeledControl(_("Update &interval in 
days"), gui.nvdaControls.SelectOnFocusSpinCtrl, min=1, max=30, 
initial=parent.updateInterval)
+                       # LTS and 8.x only.
+                       # Translators: The label for a combo box to select 
update channel.
+                       labelText = _("&Add-on update channel:")
+                       
self.channels=contentSizerHelper.addLabeledControl(labelText, wx.Choice, 
choices=["development", "stable"])
+                       self.updateChannels = ("dev", "stable")
+                       
self.channels.SetSelection(self.updateChannels.index(self.Parent.updateChannel))
+                       # Translators: A checkbox to toggle if SPL Controller 
command can be used to invoke Assistant layer.
+                       
self.splConPassthroughCheckbox=contentSizerHelper.addItem(wx.CheckBox(self, 
label=_("Allow SPL C&ontroller command to invoke SPL Assistant layer")))
+                       self.splConPassthroughCheckbox.Value = 
self.Parent.splConPassthrough
+                       # Translators: The label for a setting in SPL add-on 
dialog to set keyboard layout for SPL Assistant.
+                       labelText = _("SPL Assistant command &layout:")
+                       self.compatibilityLayouts=[("off","NVDA"),
+                       ("jfw","JAWS for Windows"),
+                       ("wineyes","Window-Eyes")]
+                       
self.compatibilityList=contentSizerHelper.addLabeledControl(labelText, 
wx.Choice, choices=[x[1] for x in self.compatibilityLayouts])
+                       selection = (x for x,y in 
enumerate(self.compatibilityLayouts) if y[0]==self.Parent.compLayer).next()
+                       try:
+                               self.compatibilityList.SetSelection(selection)
+                       except:
+                               pass
+                       mainSizer.Add(contentSizerHelper.sizer, 
border=gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
+               else:
+                       sizer = wx.BoxSizer(wx.VERTICAL)
+                       
self.autoUpdateCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Automatically 
check for add-on &updates"))
+                       
self.autoUpdateCheckbox.SetValue(self.Parent.autoUpdateCheck)
+                       sizer.Add(self.autoUpdateCheckbox, 
border=10,flag=wx.TOP)
+                       label = wx.StaticText(self, wx.ID_ANY, label=_("Update 
&interval in days"))
+                       sizer.Add(label)
+                       self.updateInterval= wx.SpinCtrl(self, wx.ID_ANY, 
min=1, max=30)
+                       
self.updateInterval.SetValue(long(parent.updateInterval))
+                       self.updateInterval.SetSelection(-1, -1)
+                       sizer.Add(self.updateInterval)
+                       mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
+                       sizer = wx.BoxSizer(wx.HORIZONTAL)
+                       label = wx.StaticText(self, wx.ID_ANY, label=_("&Add-on 
update channel:"))
+                       self.channels= wx.Choice(self, wx.ID_ANY, 
choices=["development", "stable"])
+                       self.updateChannels = ("dev", "stable")
+                       
self.channels.SetSelection(self.updateChannels.index(self.Parent.updateChannel))
+                       sizer.Add(label)
+                       sizer.Add(self.channels)
+                       mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
+                       sizer = wx.BoxSizer(wx.HORIZONTAL)
+                       
self.splConPassthroughCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Allow SPL 
C&ontroller command to invoke SPL Assistant layer"))
+                       
self.splConPassthroughCheckbox.SetValue(self.Parent.splConPassthrough)
+                       sizer.Add(self.splConPassthroughCheckbox, 
border=10,flag=wx.TOP)
+                       mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
+                       sizer = wx.BoxSizer(wx.HORIZONTAL)
+                       label = wx.StaticText(self, wx.ID_ANY, label=_("SPL 
Assistant command &layout:"))
+                       self.compatibilityLayouts=[("off","NVDA"),
+                       ("jfw","JAWS for Windows"),
+                       ("wineyes","Window-Eyes")]
+                       self.compatibilityList= wx.Choice(self, wx.ID_ANY, 
choices=[x[1] for x in self.compatibilityLayouts])
+                       selection = (x for x,y in 
enumerate(self.compatibilityLayouts) if y[0]==self.Parent.compLayer).next()
+                       try:
+                               self.compatibilityList.SetSelection(selection)
+                       except:
+                               pass
+                       sizer.Add(label)
+                       sizer.Add(self.compatibilityList)
+                       mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
 
                mainSizer.Add(self.CreateButtonSizer(wx.OK | wx.CANCEL))
                self.Bind(wx.EVT_BUTTON, self.onOk, id=wx.ID_OK)
@@ -1374,26 +1442,32 @@ class ResetDialog(wx.Dialog):
                super(ResetDialog, self).__init__(parent, title=_("Reset 
settings"))
 
                mainSizer = wx.BoxSizer(wx.VERTICAL)
-
-               # Translators: the label for resetting profile triggers.
-               
self.resetInstantProfileCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Reset 
instant switch profile"))
-               self.resetInstantProfileCheckbox.SetValue(False)
-               mainSizer.Add(self.resetInstantProfileCheckbox, 
border=10,flag=wx.BOTTOM)
-
-               # Translators: the label for resetting profile triggers.
-               
self.resetTimeProfileCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Delete 
time-based profile database"))
-               self.resetTimeProfileCheckbox.SetValue(False)
-               mainSizer.Add(self.resetTimeProfileCheckbox, 
border=10,flag=wx.BOTTOM)
-
-                               # Translators: the label for resetting encoder 
settings.
-               
self.resetEncodersCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Remove encoder 
settings"))
-               self.resetEncodersCheckbox.SetValue(False)
-               mainSizer.Add(self.resetEncodersCheckbox, 
border=10,flag=wx.BOTTOM)
-
-               # Translators: the label for resetting track comments.
-               
self.resetTrackCommentsCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Erase 
track comments"))
-               self.resetTrackCommentsCheckbox.SetValue(False)
-               mainSizer.Add(self.resetTrackCommentsCheckbox, 
border=10,flag=wx.BOTTOM)
+               if splconfig.useGUIHelper:
+                       contentSizerHelper = gui.guiHelper.BoxSizerHelper(self, 
orientation=wx.VERTICAL)
+
+               if splconfig.useGUIHelper:
+                       # Translators: the label for resetting profile triggers.
+                       
self.resetInstantProfileCheckbox=contentSizerHelper.addItem(wx.CheckBox(self,label=_("Reset
 instant switch profile")))
+                       # Translators: the label for resetting profile triggers.
+                       
self.resetTimeProfileCheckbox=contentSizerHelper.addItem(wx.CheckBox(self,label=_("Delete
 time-based profile database")))
+                       # Translators: the label for resetting encoder settings.
+                       
self.resetEncodersCheckbox=contentSizerHelper.addItem(wx.CheckBox(self,label=_("Remove
 encoder settings")))
+                       # Translators: the label for resetting track comments.
+                       
self.resetTrackCommentsCheckbox=contentSizerHelper.addItem(wx.CheckBox(self,label=_("Erase
 track comments")))
+                       mainSizer.Add(contentSizerHelper.sizer, 
border=gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
+               else:
+                       
self.resetInstantProfileCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Reset 
instant switch profile"))
+                       self.resetInstantProfileCheckbox.SetValue(False)
+                       mainSizer.Add(self.resetInstantProfileCheckbox, 
border=10,flag=wx.BOTTOM)
+                       
self.resetTimeProfileCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Delete 
time-based profile database"))
+                       self.resetTimeProfileCheckbox.SetValue(False)
+                       mainSizer.Add(self.resetTimeProfileCheckbox, 
border=10,flag=wx.BOTTOM)
+                       
self.resetEncodersCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Remove encoder 
settings"))
+                       self.resetEncodersCheckbox.SetValue(False)
+                       mainSizer.Add(self.resetEncodersCheckbox, 
border=10,flag=wx.BOTTOM)
+                       
self.resetTrackCommentsCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Erase 
track comments"))
+                       self.resetTrackCommentsCheckbox.SetValue(False)
+                       mainSizer.Add(self.resetTrackCommentsCheckbox, 
border=10,flag=wx.BOTTOM)
 
                mainSizer.Add(self.CreateButtonSizer(wx.OK | wx.CANCEL))
                self.Bind(wx.EVT_BUTTON, self.onOk, id=wx.ID_OK)

Repository URL: https://bitbucket.org/nvdaaddonteam/stationplaylist/

--

This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.

Other related posts: