commit/StationPlaylist: 23 new changesets

  • From: commits-noreply@xxxxxxxxxxxxx
  • To: nvda-addons-commits@xxxxxxxxxxxxx
  • Date: Fri, 25 Nov 2016 21:11:29 -0000

23 new commits in StationPlaylist:

https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/9da737069c02/
Changeset:   9da737069c02
Branch:      None
User:        josephsl
Date:        2016-11-07 15:17:15+00:00
Summary:     Studio 5.00 EOL: drop 'Artist' column detection in report focus 
function, delete key workaround removed.

The following were removed:
* ReportFocus: Artist is the name of the checkbox.
* Delete key caused focus boucing.

Affected #:  1 file

diff --git a/addon/appModules/splstudio/__init__.py 
b/addon/appModules/splstudio/__init__.py
index 8d3a2f3..50e822f 100755
--- a/addon/appModules/splstudio/__init__.py
+++ b/addon/appModules/splstudio/__init__.py
@@ -165,9 +165,6 @@ class SPLTrackItem(IAccessible):
                if splconfig._shouldBuildDescriptionPieces():
                        descriptionPieces = []
                        for header in 
splconfig.SPLConfig["ColumnAnnouncement"]["ColumnOrder"]:
-                               # Artist field should not be included in Studio 
5.0x, as the checkbox serves this role.
-                               if header == "Artist" and 
self.appModule.productVersion.startswith("5.0"):
-                                       continue
                                if header in 
splconfig.SPLConfig["ColumnAnnouncement"]["IncludedColumns"]:
                                        index = self.indexOf(header)
                                        if index is None: continue # Header not 
found, mostly encountered in Studio 5.0x.
@@ -1452,14 +1449,6 @@ class AppModule(appModuleHandler.AppModule):
        def script_deleteTrack(self, gesture):
                self.preTrackRemoval()
                gesture.send()
-               if self.productVersion.startswith("5.0"):
-                       if api.getForegroundObject().windowClassName == 
"TStudioForm":
-                               focus = api.getFocusObject()
-                               if focus.IAccessibleChildID < 
focus.parent.childCount:
-                                       self.deletedFocusObj = True
-                                       focus.setFocus()
-                                       self.deletedFocusObj = False
-                                       focus.setFocus()
 
        # When Escape is pressed, activate background library scan if 
conditions are right.
        def script_escape(self, gesture):


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/996ab09baf6d/
Changeset:   996ab09baf6d
Branch:      None
User:        josephsl
Date:        2016-11-09 16:57:13+00:00
Summary:     EOL for Studio 5.00: Column Search dialog will assume one is 
running Studio 5.10 and later.

In Studio 5.0x, only six columns were present, with 5.10 expanding this to 
eighteen (technically, seventeen). Thus assume that all seventeen columns are 
available to search for needed data.

Affected #:  1 file

diff --git a/addon/appModules/splstudio/splmisc.py 
b/addon/appModules/splstudio/splmisc.py
index fb3c340..27c0f99 100755
--- a/addon/appModules/splstudio/splmisc.py
+++ b/addon/appModules/splstudio/splmisc.py
@@ -96,8 +96,7 @@ class SPLFindDialog(wx.Dialog):
                        columnSizer = wx.BoxSizer(wx.HORIZONTAL)
                        # Translators: The label in track finder to search 
columns.
                        label = wx.StaticText(self, wx.ID_ANY, label=_("C&olumn 
to search:"))
-                       section, key, pos = ("ColumnAnnouncement", 
"ColumnOrder", None) if obj.appModule.productVersion >= "5.10" else ("General", 
"ExploreColumns", 6)
-                       self.columnHeaders = wx.Choice(self, wx.ID_ANY, 
choices=splconfig._SPLDefaults7[section][key][:pos])
+                       self.columnHeaders = wx.Choice(self, wx.ID_ANY, 
choices=splconfig._SPLDefaults7["ColumnAnnouncement"]["ColumnOrder"])
                        self.columnHeaders.SetSelection(0)
                        columnSizer.Add(label)
                        columnSizer.Add(self.columnHeaders)
@@ -117,8 +116,7 @@ class SPLFindDialog(wx.Dialog):
                # Studio, are you alive?
                if user32.FindWindowA("SPLStudio", None) and text:
                        appMod = self.obj.appModule
-                       column = [self.columnHeaders.Selection] if 
self.columnSearch else None
-                       if column is not None and appMod.productVersion >= 
"5.10": column[0]+=1
+                       column = [self.columnHeaders.Selection+1] if 
self.columnSearch else None
                        startObj = self.obj
                        if text == appMod.findText: startObj = startObj.next
                        # If this is called right away, we land on an invisible 
window.
@@ -223,7 +221,7 @@ class SPLTimeRangeDialog(wx.Dialog):
                                obj = obj.next
                        if obj is not None:
                                # This time, set focus once, as doing it twice 
causes focus problems only if using Studio 5.10 or later.
-                               if obj.appModule.SPLCurVersion >= "5.10": 
obj.setFocus()
+                               obj.setFocus()
                                # 16.11: Select the desired track manually.
                                self.func(-1, 121)
                                self.func(obj.IAccessibleChildID-1, 121)


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/d9b24a26fc73/
Changeset:   d9b24a26fc73
Branch:      None
User:        josephsl
Date:        2016-11-11 06:57:54+00:00
Summary:     Studio 5.00 EOL: end of support for Studio 5.00 from library scan 
feature and track focus manipulator.

Affected #:  1 file

diff --git a/addon/appModules/splstudio/__init__.py 
b/addon/appModules/splstudio/__init__.py
index 50e822f..04fe5a3 100755
--- a/addon/appModules/splstudio/__init__.py
+++ b/addon/appModules/splstudio/__init__.py
@@ -631,7 +631,7 @@ class AppModule(appModuleHandler.AppModule):
                        # 7.0: Have a timer call the update function indirectly.
                        queueHandler.queueFunction(queueHandler.eventQueue, 
splconfig.updateInit)
                # Display startup dialogs if any.
-               wx.CallAfter(splconfig.showStartupDialogs, 
oldVer=self.SPLCurVersion < "5.10")
+               wx.CallAfter(splconfig.showStartupDialogs)
 
        # Locate the handle for main window for caching purposes.
        def _locateSPLHwnd(self):
@@ -1090,8 +1090,7 @@ class AppModule(appModuleHandler.AppModule):
                        # 16.10.1/15.2 LTS: Just select this track in order to 
prevent a dispute between NVDA and SPL in regards to focused track.
                        # 16.11: Call setFocus if it is post-5.01, as SPL API 
can be used to select the desired track.
                        selectTrack(track.IAccessibleChildID-1)
-                       if self.productVersion >= "5.10":
-                               track.setFocus(), track.setFocus()
+                       track.setFocus(), track.setFocus()
                else:
                        wx.CallAfter(gui.messageBox,
                        # Translators: Standard dialog message when an item one 
wishes to search is not found (copy this from main nvda.po).
@@ -1302,8 +1301,7 @@ class AppModule(appModuleHandler.AppModule):
                global libScanT
                if libScanT and libScanT.isAlive() and 
api.getForegroundObject().windowClassName == "TTrackInsertForm":
                        return
-               parem = 0 if self.SPLCurVersion < "5.10" else 1
-               countA = statusAPI(parem, 32, ret=True)
+               countA = statusAPI(1, 32, ret=True)
                if countA == 0:
                        self.libraryScanning = False
                        return
@@ -1311,15 +1309,15 @@ class AppModule(appModuleHandler.AppModule):
                if api.getForegroundObject().windowClassName == 
"TTrackInsertForm" and self.productVersion in noLibScanMonitor:
                        self.libraryScanning = False
                        return
-               countB = statusAPI(parem, 32, ret=True)
+               # Sometimes, a second call is needed to obtain the real scan 
count in Studio 5.10 and later.
+               countB = statusAPI(1, 32, ret=True)
                if countA == countB:
                        self.libraryScanning = False
-                       if self.SPLCurVersion >= "5.10":
-                               countB = statusAPI(0, 32, ret=True)
+                       countB = statusAPI(0, 32, ret=True)
                        # Translators: Presented when library scanning is 
finished.
                        ui.message(_("{itemCount} items in the 
library").format(itemCount = countB))
                else:
-                       libScanT = 
threading.Thread(target=self.libraryScanReporter, args=(_SPLWin, countA, 
countB, parem))
+                       libScanT = 
threading.Thread(target=self.libraryScanReporter, args=(_SPLWin, countA, 
countB, 1))
                        libScanT.daemon = True
                        libScanT.start()
 
@@ -1715,12 +1713,11 @@ class AppModule(appModuleHandler.AppModule):
 
        def script_libraryScanMonitor(self, gesture):
                if not self.libraryScanning:
-                       if self.productVersion >= "5.10":
-                               scanning = statusAPI(1, 32, ret=True)
-                               if scanning < 0:
-                                       items = statusAPI(0, 32, ret=True)
-                                       ui.message(_("{itemCount} items in the 
library").format(itemCount = items))
-                                       return
+                       scanning = statusAPI(1, 32, ret=True)
+                       if scanning < 0:
+                               items = statusAPI(0, 32, ret=True)
+                               ui.message(_("{itemCount} items in the 
library").format(itemCount = items))
+                               return
                        self.libraryScanning = True
                        # Translators: Presented when attempting to start 
library scan.
                        ui.message(_("Monitoring library scan"))
@@ -1805,8 +1802,7 @@ class AppModule(appModuleHandler.AppModule):
                        track = self._trackLocator(self.placeMarker[1], 
obj=api.getFocusObject().parent.firstChild, columns=[self.placeMarker[0]])
                        # 16.11: Just like Track Finder, use select track 
function to select the place marker track.
                        selectTrack(track.IAccessibleChildID-1)
-                       if self.productVersion >= "5.10":
-                               track.setFocus(), track.setFocus()
+                       track.setFocus(), track.setFocus()
 
        def script_metadataStreamingAnnouncer(self, gesture):
                # 8.0: Call the module-level function directly.


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/4a7d444dcbd7/
Changeset:   4a7d444dcbd7
Branch:      None
User:        josephsl
Date:        2016-11-13 01:49:05+00:00
Summary:     Studio 5.00 EOL: For some SPL Assistant commands, assume one is 
using studio 5.10.

Removed object placement index values for Studio 5.00 - all values are 5.10 
values.'

Affected #:  1 file

diff --git a/addon/appModules/splstudio/__init__.py 
b/addon/appModules/splstudio/__init__.py
index 04fe5a3..0036842 100755
--- a/addon/appModules/splstudio/__init__.py
+++ b/addon/appModules/splstudio/__init__.py
@@ -1544,13 +1544,13 @@ class AppModule(appModuleHandler.AppModule):
        # These are scattered throughout the screen, so one can use 
foreground.getChild(index) to fetch them (getChild tip from Jamie Teh (NV 
Access)).
        # Because 5.x (an perhaps future releases) uses different screen 
layout, look up the needed constant from the table below (row = info needed, 
column = version).
        statusObjs={
-               SPLPlayStatus:[5, 6], # Play status, mic, etc.
-               SPLSystemStatus:[-3, -2], # The second status bar containing 
system status such as up time.
-               SPLScheduledToPlay:[18, 19], # In case the user selects one or 
more tracks in a given hour.
-               SPLScheduled:[19, 20], # Time when the selected track will 
begin.
-               SPLNextTrackTitle:[7, 8], # Name and duration of the next track 
if any.
-               SPLCurrentTrackTitle:[8, 9], # Name of the currently playing 
track.
-               SPLTemperature:[6, 7], # Temperature for the current city.
+               SPLPlayStatus: 6, # Play status, mic, etc.
+               SPLSystemStatus: -2, # The second status bar containing system 
status such as up time.
+               SPLScheduledToPlay: 19, # In case the user selects one or more 
tracks in a given hour.
+               SPLScheduled: 20, # Time when the selected track will begin.
+               SPLNextTrackTitle: 8, # Name and duration of the next track if 
any.
+               SPLCurrentTrackTitle: 9, # Name of the currently playing track.
+               SPLTemperature: 7, # Temperature for the current city.
        }
 
        _cachedStatusObjs = {}
@@ -1564,8 +1564,7 @@ class AppModule(appModuleHandler.AppModule):
                        if fg is not None and fg.windowClassName != 
"TStudioForm":
                                # 6.1: Allow gesture-based functions to look up 
status information even if Studio window isn't focused.
                                fg = 
getNVDAObjectFromEvent(user32.FindWindowA("TStudioForm", None), OBJID_CLIENT, 0)
-                       if not self.productVersion >= "5.10": statusObj = 
self.statusObjs[infoIndex][0]
-                       else: statusObj = self.statusObjs[infoIndex][1]
+                       statusObj = self.statusObjs[infoIndex]
                        # 7.0: sometimes (especially when first loaded), 
OBJID_CLIENT fails, so resort to retrieving focused object instead.
                        if fg is not None and fg.childCount > 1:
                                self._cachedStatusObjs[infoIndex] = 
fg.getChild(statusObj)


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/77ee97a214c1/
Changeset:   77ee97a214c1
Branch:      None
User:        josephsl
Date:        2016-11-13 02:19:32+00:00
Summary:     Studio 5.00 EOL: officially end support for Studio 5.0x.

Minimum version is now 5.10. Overlay class for Studio 5.0x track item is no 
more.

Affected #:  1 file

diff --git a/addon/appModules/splstudio/__init__.py 
b/addon/appModules/splstudio/__init__.py
index 0036842..fcd2c43 100755
--- a/addon/appModules/splstudio/__init__.py
+++ b/addon/appModules/splstudio/__init__.py
@@ -56,7 +56,7 @@ def finally_(func, final):
        return wrap(final)
 
 # Make sure the broadcaster is running a compatible version.
-SPLMinVersion = "5.00"
+SPLMinVersion = "5.10"
 
 # Cache the handle to main Studio window.
 _SPLWin = None
@@ -679,8 +679,6 @@ class AppModule(appModuleHandler.AppModule):
                windowStyle = obj.windowStyle
                if obj.windowClassName == "TTntListView.UnicodeClass" and role 
== controlTypes.ROLE_LISTITEM and abs(windowStyle - 1443991625)%0x100000 == 0:
                        clsList.insert(0, SPL510TrackItem)
-               elif obj.windowClassName == "TListView" and role == 
controlTypes.ROLE_CHECKBOX and abs(windowStyle - 1442938953)%0x100000 == 0:
-                       clsList.insert(0, SPLTrackItem)
                # 7.2: Recognize known dialogs.
                elif obj.windowClassName in ("TDemoRegForm", "TOpenPlaylist"):
                        clsList.insert(0, Dialog)


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/62dc4a5304e6/
Changeset:   62dc4a5304e6
Branch:      None
User:        josephsl
Date:        2016-11-14 04:15:44+00:00
Summary:     Merge branch 'master' into eol500

Affected #:  10 files

diff --git a/addon/appModules/splstudio/__init__.py 
b/addon/appModules/splstudio/__init__.py
index fcd2c43..753b48e 100755
--- a/addon/appModules/splstudio/__init__.py
+++ b/addon/appModules/splstudio/__init__.py
@@ -441,7 +441,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.
@@ -473,7 +473,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.
@@ -507,7 +507,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.
@@ -920,22 +920,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.
@@ -1576,7 +1578,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).
@@ -1605,7 +1606,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)
@@ -1685,13 +1694,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/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)

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/1ba0e6b59e5b/
Changeset:   1ba0e6b59e5b
Branch:      None
User:        josephsl
Date:        2016-11-14 05:03:13+00:00
Summary:     Status announcement toggle command is removed.

Affected #:  1 file

diff --git a/addon/appModules/splstudio/__init__.py 
b/addon/appModules/splstudio/__init__.py
index d87f80f..6bad87c 100755
--- a/addon/appModules/splstudio/__init__.py
+++ b/addon/appModules/splstudio/__init__.py
@@ -1051,14 +1051,6 @@ class AppModule(appModuleHandler.AppModule):
 
        # Other commands (track finder and others)
 
-       # Toggle whether beeps should be heard instead of toggle announcements.
-       # Deprecated in 8.0, may come back later.
-
-       #def script_toggleBeepAnnounce(self, gesture):
-               #splconfig.SPLConfig["General"]["BeepAnnounce"] = not 
splconfig.SPLConfig["General"]["BeepAnnounce"]
-               #splconfig.message("BeepAnnounce", 
splconfig.SPLConfig["General"]["BeepAnnounce"])
-       #script_toggleBeepAnnounce.__doc__=_("Toggles status announcements 
between words and beeps.")
-
        # Braille timer.
        # Announce end of track and other info via braille.
 


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/8883d65c9435/
Changeset:   8883d65c9435
Branch:      None
User:        josephsl
Date:        2016-11-14 16:45:25+00:00
Summary:     Studio 5.00 EOL: end of support for Track Tool 5.0x.

Affected #:  1 file

diff --git a/addon/appModules/tracktool.py b/addon/appModules/tracktool.py
index d280215..b92bb46 100755
--- a/addon/appModules/tracktool.py
+++ b/addon/appModules/tracktool.py
@@ -22,11 +22,9 @@ 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.startswith("5.0"):
-               return 
("Artist","Title","Duration","Cue","Overlap","Intro","Segue","Album","CD 
Code","URL 1","URL 2","Filename")
-       elif ttVersion.startswith("5.1"):
+       if ttVersion < "5.2":
                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"):
+       else:
                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):
@@ -94,7 +92,7 @@ class TrackToolItem(IAccessible):
        def announceColumnContent(self, colNumber, columnHeader=None, 
individualColumns=False):
                if not columnHeader:
                        columnHeader = 
self.columnHeaders.children[colNumber].name
-               # LTS: Studio 5.10 data structure change is evident in Track 
Tool as well, so don't rely on column headers alone.
+                       # LTS: Studio 5.10 data structure change is evident in 
Track Tool as well, so don't rely on column headers alone.
                        internalHeaders = indexOf(self.appModule.productVersion)
                        if internalHeaders[colNumber] != columnHeader:
                                colNumber = internalHeaders.index(columnHeader)


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/41cb193cb7a0/
Changeset:   41cb193cb7a0
Branch:      None
User:        josephsl
Date:        2016-11-14 18:20:13+00:00
Summary:     Studio 5.00 EOL: NVDA 2016.4 or later will be required, removed 
indexOf function from 5.0x track item.

IndexOf and original IndexOf private function now returns NULL for abstract 
track item (remains fully implemented in 5.10 version). Also removed mention of 
Studio 5.0x from SPL Assistant helper command.

Affected #:  1 file

diff --git a/addon/appModules/splstudio/__init__.py 
b/addon/appModules/splstudio/__init__.py
index 753b48e..c4a3d0a 100755
--- a/addon/appModules/splstudio/__init__.py
+++ b/addon/appModules/splstudio/__init__.py
@@ -8,7 +8,7 @@
 # Additional work done by Joseph Lee and other contributors.
 # For SPL Studio Controller, focus movement, SAM Encoder support and other 
utilities, see the global plugin version of this app module.
 
-# Minimum version: SPL 5.00, NvDA 2015.3.
+# Minimum version: SPL 5.10, NvDA 2016.4.
 
 from functools import wraps
 import os
@@ -133,7 +133,7 @@ class SPLTrackItem(IAccessible):
        # This is response to a situation where columns were rearranged yet 
testing shows in-memory arrangement remains the same.
        # Subclasses must provide this function.
        def _origIndexOf(self, columnHeader):
-               return 
splconfig._SPLDefaults7["General"]["ExploreColumns"].index(columnHeader)
+               return None
 
        # Read selected columns.
        # But first, find where the requested column lives.
@@ -445,7 +445,7 @@ T: Cart edit/insert mode.
 U: Studio up time.
 W: Weather and temperature.
 Y: Playlist modification.
-1 through 0 (6 for Studio 5.01 and earlier): Announce columns via Columns 
Explorer (0 is tenth column slot).
+1 through 0: Announce columns via Columns Explorer (0 is tenth column slot).
 F9: Mark current track as start of track time analysis.
 F10: Perform track time analysis.
 F12: Switch to an instant switch profile.
@@ -477,7 +477,7 @@ T: Cart edit/insert mode.
 U: Studio up time.
 W: Weather and temperature.
 Y: Playlist modification.
-1 through 0 (6 for Studio 5.01 and earlier): Announce columns via Columns 
Explorer (0 is tenth column slot).
+1 through 0: Announce columns via Columns Explorer (0 is tenth column slot).
 F9: Mark current track as start of track time analysis.
 F10: Perform track time analysis.
 F12: Switch to an instant switch profile.
@@ -511,7 +511,7 @@ T: Cart edit/insert mode.
 U: Studio up time.
 W: Weather and temperature.
 Y: Playlist modification.
-1 through 0 (6 for Studio 5.01 and earlier): Announce columns via Columns 
Explorer (0 is tenth column slot).
+1 through 0: Announce columns via Columns Explorer (0 is tenth column slot).
 F9: Mark current track as start of track time analysis.
 F10: Perform track time analysis.
 F12: Switch to an instant switch profile.
@@ -1440,7 +1440,7 @@ class AppModule(appModuleHandler.AppModule):
 
        # Some handlers for native commands.
 
-       # In Studio 5.0x, when deleting a track, NVDA announces wrong track 
item due to focus bouncing.
+       # In Studio 5.0x, when deleting a track, NVDA announces wrong track 
item due to focus bouncing (not the case in 5.10 and later).
        # The below hack is sensitive to changes in NVDA core.
        deletedFocusObj = False
 


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/a20bfd60128a/
Changeset:   a20bfd60128a
Branch:      None
User:        josephsl
Date:        2016-11-14 23:00:51+00:00
Summary:     Studio 5.00 EOL: leftmostcol function now handles 5.10 columns 
only.

Leftmostcol function in SPL Track Item class should do nothing (it did 
something when it was responsible for handling 5.0x columns, but not anymore). 
Also, scheduled for item cache must be kept, as 5.20 still exhibits double 
announcement problem.

Affected #:  1 file

diff --git a/addon/appModules/splstudio/__init__.py 
b/addon/appModules/splstudio/__init__.py
index c4a3d0a..f1113ac 100755
--- a/addon/appModules/splstudio/__init__.py
+++ b/addon/appModules/splstudio/__init__.py
@@ -139,7 +139,6 @@ class SPLTrackItem(IAccessible):
        # But first, find where the requested column lives.
        # 8.0: Make this a public function.
        def indexOf(self, columnHeader):
-               # Handle both 5.0x and 5.10 column headers.
                try:
                        return self._origIndexOf(columnHeader)
                except ValueError:
@@ -224,15 +223,7 @@ class SPLTrackItem(IAccessible):
        # Some helper functions to handle corner cases.
        # Each track item provides its own version.
        def _leftmostcol(self):
-               if self.appModule._columnHeaders is None:
-                       self.appModule._columnHeaders = self.parent.children[-1]
-               leftmost = self.appModule._columnHeaders.firstChild.name
-               if not self.name or self.name == "":
-                       # Translators: Announced when leftmost column has no 
text while track dial is active.
-                       ui.message(_("{leftmostColumn} not 
found").format(leftmostColumn = leftmost))
-               else:
-                       # Translators: Standard message for announcing column 
content.
-                       ui.message(_("{leftmostColumn}: 
{leftmostContent}").format(leftmostColumn = leftmost, leftmostContent = 
self.name))
+               pass
 
        # Locate column content.
        # This is merely the proxy of the module level function defined in the 
misc module.
@@ -689,7 +680,7 @@ class AppModule(appModuleHandler.AppModule):
        # Keep an eye on library scans in insert tracks window.
        libraryScanning = False
        scanCount = 0
-       # For 5.0X and earlier: prevent NVDA from announcing scheduled time 
multiple times.
+       # Prevent NVDA from announcing scheduled time multiple times.
        scheduledTimeCache = ""
        # Track Dial (A.K.A. enhanced arrow keys)
        SPLColNumber = 0


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/4e5987f2b58d/
Changeset:   4e5987f2b58d
Branch:      None
User:        josephsl
Date:        2016-11-14 23:05:12+00:00
Summary:     Merge branch 'master' into eol500

Affected #:  1 file

diff --git a/addon/appModules/splstudio/__init__.py 
b/addon/appModules/splstudio/__init__.py
index f1113ac..6375956 100755
--- a/addon/appModules/splstudio/__init__.py
+++ b/addon/appModules/splstudio/__init__.py
@@ -1037,14 +1037,6 @@ class AppModule(appModuleHandler.AppModule):
 
        # Other commands (track finder and others)
 
-       # Toggle whether beeps should be heard instead of toggle announcements.
-       # Deprecated in 8.0, may come back later.
-
-       #def script_toggleBeepAnnounce(self, gesture):
-               #splconfig.SPLConfig["General"]["BeepAnnounce"] = not 
splconfig.SPLConfig["General"]["BeepAnnounce"]
-               #splconfig.message("BeepAnnounce", 
splconfig.SPLConfig["General"]["BeepAnnounce"])
-       #script_toggleBeepAnnounce.__doc__=_("Toggles status announcements 
between words and beeps.")
-
        # Braille timer.
        # Announce end of track and other info via braille.
 


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/f3badbef3f4a/
Changeset:   f3badbef3f4a
Branch:      None
User:        josephsl
Date:        2016-11-15 01:24:39+00:00
Summary:     Track Dial (17.1-dev): officially remove Track Dial, replaced by 
Columns Explorer and Column Navigator.

Affected #:  5 files

diff --git a/addon/appModules/splstudio/__init__.py 
b/addon/appModules/splstudio/__init__.py
index 6bad87c..af8b62d 100755
--- a/addon/appModules/splstudio/__init__.py
+++ b/addon/appModules/splstudio/__init__.py
@@ -121,9 +121,6 @@ class SPLTrackItem(IAccessible):
        """A base class for providing utility scripts when track entries are 
focused, such as track dial."""
 
        def initOverlayClass(self):
-               #if splconfig.SPLConfig["General"]["TrackDial"]:
-                       #self.bindGesture("kb:rightArrow", "nextColumn")
-                       #self.bindGesture("kb:leftArrow", "prevColumn")
                # LTS: Take a greater role in assigning enhanced Columns 
Explorer command at the expense of limiting where this can be invoked.
                # 8.0: Just assign number row.
                for i in xrange(10):
@@ -191,34 +188,6 @@ class SPLTrackItem(IAccessible):
        # This is similar to enhanced arrow keys in other screen readers.
 
        def script_toggleTrackDial(self, gesture):
-               #if not splconfig.SPLConfig["General"]["TrackDial"]:
-                       #splconfig.SPLConfig["General"]["TrackDial"] = True
-                       #self.bindGesture("kb:rightArrow", "nextColumn")
-                       #self.bindGesture("kb:leftArrow", "prevColumn")
-                       # Translators: Reported when track dial is on.
-                       #dialText = _("Track Dial on")
-                       #if self.appModule.SPLColNumber > 0:
-                               # Translators: Announced when located on a 
column other than the leftmost column while using track dial.
-                               #dialText+= _(", located at column 
{columnHeader}").format(columnHeader = self.appModule.SPLColNumber+1)
-                       #dialTone = 780
-               #else:
-                       #splconfig.SPLConfig["General"]["TrackDial"] = False
-                       #try:
-                               #self.removeGestureBinding("kb:rightArrow")
-                               #self.removeGestureBinding("kb:leftArrow")
-                       #except KeyError:
-                               #pass
-                       # Translators: Reported when track dial is off.
-                       #dialText = _("Track Dial off")
-                       #dialTone = 390
-               #if not splconfig.SPLConfig["General"]["BeepAnnounce"]:
-                       #ui.message(dialText)
-               #else:
-                       #tones.beep(dialTone, 100)
-                       #braille.handler.message(dialText)
-                       #if splconfig.SPLConfig["General"]["TrackDial"] and 
self.appModule.SPLColNumber > 0:
-                               # Translators: Spoken when enabling track dial 
while status message is set to beeps.
-                               #speech.speakMessage(_("Column 
{columnNumber}").format(columnNumber = self.appModule.SPLColNumber+1))
                ui.message("Track Dial is deprecated in 2017, please unassign 
Track Dial toggle command via Input Gestures dialog")
        # Translators: Input help mode message for SPL track item.
        script_toggleTrackDial.__doc__=_("Toggles track dial on and off.")

diff --git a/addon/appModules/splstudio/splconfig.py 
b/addon/appModules/splstudio/splconfig.py
index 207ee5a..1ad03aa 100755
--- a/addon/appModules/splstudio/splconfig.py
+++ b/addon/appModules/splstudio/splconfig.py
@@ -44,7 +44,6 @@ BrailleTimer = option("off", "intro", "outro", "both", 
default="off")
 AlarmAnnounce = option("beep", "message", "both", default="beep")
 TrackCommentAnnounce = option("off", "beep", "message", "both", default="off")
 LibraryScanAnnounce = option("off", "ending", "progress", "numbers", 
default="off")
-TrackDial = boolean(default=false)
 CategorySounds = boolean(default=false)
 TopBottomAnnounce = boolean(default=true)
 MetadataReminder = option("off", "startup", "instant", default="off")

diff --git a/addon/appModules/splstudio/splconfui.py 
b/addon/appModules/splstudio/splconfui.py
index db2de3b..548d612 100755
--- a/addon/appModules/splstudio/splconfui.py
+++ b/addon/appModules/splstudio/splconfui.py
@@ -232,11 +232,6 @@ class SPLConfigDialog(gui.SettingsDialog):
                
self.hourAnnounceCheckbox.SetValue(splconfig.SPLConfig["General"]["TimeHourAnnounce"])
                settingsSizer.Add(self.hourAnnounceCheckbox, 
border=10,flag=wx.BOTTOM)
 
-               # Translators: the label for a setting in SPL add-on settings 
to toggle track dial mode on and off.
-               
#self.trackDialCheckbox=wx.CheckBox(self,wx.NewId(),label=_("&Track Dial mode"))
-               
#self.trackDialCheckbox.SetValue(splconfig.SPLConfig["General"]["TrackDial"])
-               #settingsSizer.Add(self.trackDialCheckbox, 
border=10,flag=wx.BOTTOM)
-
                sizer = wx.BoxSizer(wx.HORIZONTAL)
                # Translators: The label for a setting in SPL add-on dialog to 
set vertical column.
                label = wx.StaticText(self, wx.ID_ANY, label=_("&Vertical 
column navigation announcement:"))
@@ -385,7 +380,6 @@ class SPLConfigDialog(gui.SettingsDialog):
                splconfig.SPLConfig["General"]["AlarmAnnounce"] = 
self.alarmAnnounceValues[self.alarmAnnounceList.GetSelection()][0]
                splconfig.SPLConfig["General"]["LibraryScanAnnounce"] = 
self.libScanValues[self.libScanList.GetSelection()][0]
                splconfig.SPLConfig["General"]["TimeHourAnnounce"] = 
self.hourAnnounceCheckbox.Value
-               #splconfig.SPLConfig["General"]["TrackDial"] = 
self.trackDialCheckbox.Value
                splconfig.SPLConfig["General"]["CategorySounds"] = 
self.categorySoundsCheckbox.Value
                splconfig.SPLConfig["General"]["TrackCommentAnnounce"] = 
self.trackCommentValues[self.trackCommentList.GetSelection()][0]
                splconfig.SPLConfig["General"]["TopBottomAnnounce"] = 
self.topBottomCheckbox.Value

diff --git a/addon/appModules/tracktool.py b/addon/appModules/tracktool.py
index d280215..58ef568 100755
--- a/addon/appModules/tracktool.py
+++ b/addon/appModules/tracktool.py
@@ -40,53 +40,9 @@ class TrackToolItem(IAccessible):
                super(TrackToolItem, self).reportFocus()
 
        def initOverlayClass(self):
-               if self.appModule.TTDial:
-                       self.bindGesture("kb:rightArrow", "nextColumn")
-                       self.bindGesture("kb:leftArrow", "prevColumn")
                # 8.0: Assign Control+NVDA+number row for Columns Explorer just 
like the main app module.
                for i in xrange(10):
                        self.bindGesture("kb:control+nvda+%s"%(i), 
"columnExplorer")
-               # See if Track Dial toggle for Studio is defined, and if so, 
pull it in.
-               import inputCore
-               userGestures = inputCore.manager.userGestureMap._map
-               for gesture in userGestures:
-                       if userGestures[gesture][0][2] == "toggleTrackDial":
-                               self.bindGesture(gesture, "toggleTrackDial")
-
-                       # Track Dial for Track Tool.
-
-       def script_toggleTrackDial(self, gesture):
-               if splconfig.SPLConfig is None:
-                       # Translators: Presented when only Track Tool is 
running (Track Dial requires Studio to be running as well).
-                       ui.message(_("Only Track Tool is running, Track Dial is 
unavailable"))
-                       return
-               if not self.appModule.TTDial:
-                       self.appModule.TTDial = True
-                       self.bindGesture("kb:rightArrow", "nextColumn")
-                       self.bindGesture("kb:leftArrow", "prevColumn")
-                       dialText = _("Track Dial on")
-                       if self.appModule.SPLColNumber > 0:
-                               dialText+= _(", located at column 
{columnHeader}").format(columnHeader = self.appModule.SPLColNumber+1)
-                       dialTone = 780
-               else:
-                       self.appModule.TTDial = False
-                       try:
-                               self.removeGestureBinding("kb:rightArrow")
-                               self.removeGestureBinding("kb:leftArrow")
-                       except KeyError:
-                               pass
-                       dialText = _("Track Dial off")
-                       dialTone = 390
-               if not splconfig.SPLConfig["General"]["BeepAnnounce"]:
-                       ui.message(dialText)
-               else:
-                       tones.beep(dialTone, 100)
-                       braille.handler.message(dialText)
-                       if self.appModule.TTDial and 
self.appModule.SPLColNumber > 0:
-                               speech.speakMessage(_("Column 
{columnNumber}").format(columnNumber = self.appModule.SPLColNumber+1))
-       # Translators: Input help mode message for SPL track item.
-       script_toggleTrackDial.__doc__=_("Toggles track dial on and off.")
-       script_toggleTrackDial.category = _("StationPlaylist Studio")
 
        # Tweak for Track Tool: Announce column header if given.
        # Also take care of this when specific columns are asked.
@@ -94,7 +50,7 @@ class TrackToolItem(IAccessible):
        def announceColumnContent(self, colNumber, columnHeader=None, 
individualColumns=False):
                if not columnHeader:
                        columnHeader = 
self.columnHeaders.children[colNumber].name
-               # LTS: Studio 5.10 data structure change is evident in Track 
Tool as well, so don't rely on column headers alone.
+                       # LTS: Studio 5.10 data structure change is evident in 
Track Tool as well, so don't rely on column headers alone.
                        internalHeaders = indexOf(self.appModule.productVersion)
                        if internalHeaders[colNumber] != columnHeader:
                                colNumber = internalHeaders.index(columnHeader)
@@ -155,7 +111,6 @@ class TrackToolItem(IAccessible):
                                ui.message(_("{headerText} not 
found").format(headerText = header))
 
        __gestures={
-               #"kb:control+`":"toggleTrackDial",
                "kb:control+alt+rightArrow":"nextColumn",
                "kb:control+alt+leftArrow":"prevColumn",
        }
@@ -163,7 +118,6 @@ class TrackToolItem(IAccessible):
 
 class AppModule(appModuleHandler.AppModule):
 
-       TTDial = False
        SPLColNumber = 0
 
        def chooseNVDAObjectOverlayClasses(self, obj, clsList):

diff --git a/readme.md b/readme.md
index 0cb0f1b..f48d62c 100755
--- a/readme.md
+++ b/readme.md
@@ -38,7 +38,6 @@ The following commands are not assigned by default; if you 
wish to assign it, us
 * SPL Controller layer.
 * SPL Assistant layer from SPL Studio.
 * Announce time including seconds from SPL Studio.
-* Toggling track dial on or off (works properly while a track is focused; to 
assign a command to this, move to a track in Studio, then open NVDA's input 
gestures dialog.).
 * Announcing temperature.
 * Announcing title of next track if scheduled.
 * Announcing title of the currently playing track.
@@ -174,6 +173,7 @@ 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.
+* Removed Track Dial (NVDA's version of enhanced arrow keys), replaced by 
Columns explorer and Column Navigator/table navigation commands). This affects 
Studio and Track Tool.
 
 ## Version 16.11/15.3-LTS
 


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/817f994b179c/
Changeset:   817f994b179c
Branch:      None
User:        josephsl
Date:        2016-11-15 01:25:22+00:00
Summary:     Merge branch 'master' into eol500

Affected #:  5 files

diff --git a/addon/appModules/splstudio/__init__.py 
b/addon/appModules/splstudio/__init__.py
index 6375956..be4b368 100755
--- a/addon/appModules/splstudio/__init__.py
+++ b/addon/appModules/splstudio/__init__.py
@@ -121,9 +121,6 @@ class SPLTrackItem(IAccessible):
        """A base class for providing utility scripts when track entries are 
focused, such as track dial."""
 
        def initOverlayClass(self):
-               #if splconfig.SPLConfig["General"]["TrackDial"]:
-                       #self.bindGesture("kb:rightArrow", "nextColumn")
-                       #self.bindGesture("kb:leftArrow", "prevColumn")
                # LTS: Take a greater role in assigning enhanced Columns 
Explorer command at the expense of limiting where this can be invoked.
                # 8.0: Just assign number row.
                for i in xrange(10):
@@ -187,34 +184,6 @@ class SPLTrackItem(IAccessible):
        # This is similar to enhanced arrow keys in other screen readers.
 
        def script_toggleTrackDial(self, gesture):
-               #if not splconfig.SPLConfig["General"]["TrackDial"]:
-                       #splconfig.SPLConfig["General"]["TrackDial"] = True
-                       #self.bindGesture("kb:rightArrow", "nextColumn")
-                       #self.bindGesture("kb:leftArrow", "prevColumn")
-                       # Translators: Reported when track dial is on.
-                       #dialText = _("Track Dial on")
-                       #if self.appModule.SPLColNumber > 0:
-                               # Translators: Announced when located on a 
column other than the leftmost column while using track dial.
-                               #dialText+= _(", located at column 
{columnHeader}").format(columnHeader = self.appModule.SPLColNumber+1)
-                       #dialTone = 780
-               #else:
-                       #splconfig.SPLConfig["General"]["TrackDial"] = False
-                       #try:
-                               #self.removeGestureBinding("kb:rightArrow")
-                               #self.removeGestureBinding("kb:leftArrow")
-                       #except KeyError:
-                               #pass
-                       # Translators: Reported when track dial is off.
-                       #dialText = _("Track Dial off")
-                       #dialTone = 390
-               #if not splconfig.SPLConfig["General"]["BeepAnnounce"]:
-                       #ui.message(dialText)
-               #else:
-                       #tones.beep(dialTone, 100)
-                       #braille.handler.message(dialText)
-                       #if splconfig.SPLConfig["General"]["TrackDial"] and 
self.appModule.SPLColNumber > 0:
-                               # Translators: Spoken when enabling track dial 
while status message is set to beeps.
-                               #speech.speakMessage(_("Column 
{columnNumber}").format(columnNumber = self.appModule.SPLColNumber+1))
                ui.message("Track Dial is deprecated in 2017, please unassign 
Track Dial toggle command via Input Gestures dialog")
        # Translators: Input help mode message for SPL track item.
        script_toggleTrackDial.__doc__=_("Toggles track dial on and off.")

diff --git a/addon/appModules/splstudio/splconfig.py 
b/addon/appModules/splstudio/splconfig.py
index 207ee5a..1ad03aa 100755
--- a/addon/appModules/splstudio/splconfig.py
+++ b/addon/appModules/splstudio/splconfig.py
@@ -44,7 +44,6 @@ BrailleTimer = option("off", "intro", "outro", "both", 
default="off")
 AlarmAnnounce = option("beep", "message", "both", default="beep")
 TrackCommentAnnounce = option("off", "beep", "message", "both", default="off")
 LibraryScanAnnounce = option("off", "ending", "progress", "numbers", 
default="off")
-TrackDial = boolean(default=false)
 CategorySounds = boolean(default=false)
 TopBottomAnnounce = boolean(default=true)
 MetadataReminder = option("off", "startup", "instant", default="off")

diff --git a/addon/appModules/splstudio/splconfui.py 
b/addon/appModules/splstudio/splconfui.py
index db2de3b..548d612 100755
--- a/addon/appModules/splstudio/splconfui.py
+++ b/addon/appModules/splstudio/splconfui.py
@@ -232,11 +232,6 @@ class SPLConfigDialog(gui.SettingsDialog):
                
self.hourAnnounceCheckbox.SetValue(splconfig.SPLConfig["General"]["TimeHourAnnounce"])
                settingsSizer.Add(self.hourAnnounceCheckbox, 
border=10,flag=wx.BOTTOM)
 
-               # Translators: the label for a setting in SPL add-on settings 
to toggle track dial mode on and off.
-               
#self.trackDialCheckbox=wx.CheckBox(self,wx.NewId(),label=_("&Track Dial mode"))
-               
#self.trackDialCheckbox.SetValue(splconfig.SPLConfig["General"]["TrackDial"])
-               #settingsSizer.Add(self.trackDialCheckbox, 
border=10,flag=wx.BOTTOM)
-
                sizer = wx.BoxSizer(wx.HORIZONTAL)
                # Translators: The label for a setting in SPL add-on dialog to 
set vertical column.
                label = wx.StaticText(self, wx.ID_ANY, label=_("&Vertical 
column navigation announcement:"))
@@ -385,7 +380,6 @@ class SPLConfigDialog(gui.SettingsDialog):
                splconfig.SPLConfig["General"]["AlarmAnnounce"] = 
self.alarmAnnounceValues[self.alarmAnnounceList.GetSelection()][0]
                splconfig.SPLConfig["General"]["LibraryScanAnnounce"] = 
self.libScanValues[self.libScanList.GetSelection()][0]
                splconfig.SPLConfig["General"]["TimeHourAnnounce"] = 
self.hourAnnounceCheckbox.Value
-               #splconfig.SPLConfig["General"]["TrackDial"] = 
self.trackDialCheckbox.Value
                splconfig.SPLConfig["General"]["CategorySounds"] = 
self.categorySoundsCheckbox.Value
                splconfig.SPLConfig["General"]["TrackCommentAnnounce"] = 
self.trackCommentValues[self.trackCommentList.GetSelection()][0]
                splconfig.SPLConfig["General"]["TopBottomAnnounce"] = 
self.topBottomCheckbox.Value

diff --git a/addon/appModules/tracktool.py b/addon/appModules/tracktool.py
index b92bb46..df79410 100755
--- a/addon/appModules/tracktool.py
+++ b/addon/appModules/tracktool.py
@@ -38,53 +38,9 @@ class TrackToolItem(IAccessible):
                super(TrackToolItem, self).reportFocus()
 
        def initOverlayClass(self):
-               if self.appModule.TTDial:
-                       self.bindGesture("kb:rightArrow", "nextColumn")
-                       self.bindGesture("kb:leftArrow", "prevColumn")
                # 8.0: Assign Control+NVDA+number row for Columns Explorer just 
like the main app module.
                for i in xrange(10):
                        self.bindGesture("kb:control+nvda+%s"%(i), 
"columnExplorer")
-               # See if Track Dial toggle for Studio is defined, and if so, 
pull it in.
-               import inputCore
-               userGestures = inputCore.manager.userGestureMap._map
-               for gesture in userGestures:
-                       if userGestures[gesture][0][2] == "toggleTrackDial":
-                               self.bindGesture(gesture, "toggleTrackDial")
-
-                       # Track Dial for Track Tool.
-
-       def script_toggleTrackDial(self, gesture):
-               if splconfig.SPLConfig is None:
-                       # Translators: Presented when only Track Tool is 
running (Track Dial requires Studio to be running as well).
-                       ui.message(_("Only Track Tool is running, Track Dial is 
unavailable"))
-                       return
-               if not self.appModule.TTDial:
-                       self.appModule.TTDial = True
-                       self.bindGesture("kb:rightArrow", "nextColumn")
-                       self.bindGesture("kb:leftArrow", "prevColumn")
-                       dialText = _("Track Dial on")
-                       if self.appModule.SPLColNumber > 0:
-                               dialText+= _(", located at column 
{columnHeader}").format(columnHeader = self.appModule.SPLColNumber+1)
-                       dialTone = 780
-               else:
-                       self.appModule.TTDial = False
-                       try:
-                               self.removeGestureBinding("kb:rightArrow")
-                               self.removeGestureBinding("kb:leftArrow")
-                       except KeyError:
-                               pass
-                       dialText = _("Track Dial off")
-                       dialTone = 390
-               if not splconfig.SPLConfig["General"]["BeepAnnounce"]:
-                       ui.message(dialText)
-               else:
-                       tones.beep(dialTone, 100)
-                       braille.handler.message(dialText)
-                       if self.appModule.TTDial and 
self.appModule.SPLColNumber > 0:
-                               speech.speakMessage(_("Column 
{columnNumber}").format(columnNumber = self.appModule.SPLColNumber+1))
-       # Translators: Input help mode message for SPL track item.
-       script_toggleTrackDial.__doc__=_("Toggles track dial on and off.")
-       script_toggleTrackDial.category = _("StationPlaylist Studio")
 
        # Tweak for Track Tool: Announce column header if given.
        # Also take care of this when specific columns are asked.
@@ -153,7 +109,6 @@ class TrackToolItem(IAccessible):
                                ui.message(_("{headerText} not 
found").format(headerText = header))
 
        __gestures={
-               #"kb:control+`":"toggleTrackDial",
                "kb:control+alt+rightArrow":"nextColumn",
                "kb:control+alt+leftArrow":"prevColumn",
        }
@@ -161,7 +116,6 @@ class TrackToolItem(IAccessible):
 
 class AppModule(appModuleHandler.AppModule):
 
-       TTDial = False
        SPLColNumber = 0
 
        def chooseNVDAObjectOverlayClasses(self, obj, clsList):

diff --git a/readme.md b/readme.md
index 0cb0f1b..f48d62c 100755
--- a/readme.md
+++ b/readme.md
@@ -38,7 +38,6 @@ The following commands are not assigned by default; if you 
wish to assign it, us
 * SPL Controller layer.
 * SPL Assistant layer from SPL Studio.
 * Announce time including seconds from SPL Studio.
-* Toggling track dial on or off (works properly while a track is focused; to 
assign a command to this, move to a track in Studio, then open NVDA's input 
gestures dialog.).
 * Announcing temperature.
 * Announcing title of next track if scheduled.
 * Announcing title of the currently playing track.
@@ -174,6 +173,7 @@ 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.
+* Removed Track Dial (NVDA's version of enhanced arrow keys), replaced by 
Columns explorer and Column Navigator/table navigation commands). This affects 
Studio and Track Tool.
 
 ## Version 16.11/15.3-LTS
 


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/5ab6c512d5e3/
Changeset:   5ab6c512d5e3
Branch:      None
User:        josephsl
Date:        2016-11-15 17:43:53+00:00
Summary:     GUI Helper services: revert to using checkbox.SetValue, as some 
checkboxes in NVDA Core uses this while others use checkbox.Value.

Affected #:  2 files

diff --git a/addon/appModules/splstudio/splconfig.py 
b/addon/appModules/splstudio/splconfig.py
index 1ad03aa..33d656e 100755
--- a/addon/appModules/splstudio/splconfig.py
+++ b/addon/appModules/splstudio/splconfig.py
@@ -911,7 +911,7 @@ class SPLAlarmDialog(wx.Dialog):
                        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"]
+                               
self.outroToggleCheckBox.SetValue(SPLConfig["IntroOutroAlarms"]["SayEndOfTrack"])
                        else:
                                alarmSizer = wx.BoxSizer(wx.HORIZONTAL)
                                alarmMessage = wx.StaticText(self, wx.ID_ANY, 
label=alarmLabel)
@@ -931,7 +931,7 @@ class SPLAlarmDialog(wx.Dialog):
                        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"]
+                               
self.introToggleCheckBox.SetValue(SPLConfig["IntroOutroAlarms"]["SaySongRamp"])
                        else:
                                alarmSizer = wx.BoxSizer(wx.HORIZONTAL)
                                alarmMessage = wx.StaticText(self, wx.ID_ANY, 
label=alarmLabel)

diff --git a/addon/appModules/splstudio/splconfui.py 
b/addon/appModules/splstudio/splconfui.py
index 548d612..dd7bd84 100755
--- a/addon/appModules/splstudio/splconfui.py
+++ b/addon/appModules/splstudio/splconfui.py
@@ -1253,13 +1253,13 @@ class SayStatusDialog(wx.Dialog):
                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
+                       self.scheduledForCheckbox.SetValue(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
+                       
self.listenerCountCheckbox.SetValue(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
+                       self.cartNameCheckbox.SetValue(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.
@@ -1340,7 +1340,7 @@ class AdvancedOptionsDialog(wx.Dialog):
                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
+                       
self.autoUpdateCheckbox.SetValue(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.
@@ -1351,7 +1351,7 @@ class AdvancedOptionsDialog(wx.Dialog):
                        
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
+                       
self.splConPassthroughCheckbox.SetValue(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"),


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/0fdbc22a485a/
Changeset:   0fdbc22a485a
Branch:      None
User:        josephsl
Date:        2016-11-16 18:27:13+00:00
Summary:     Track item column getter: fetch column inclusion set only once to 
prevent calling getitem method in ConfigHub multiple times.

Consider the following: display order is turned off, custom column order is 
set. When this happens, description pieces for track items will be built, but 
this means column inclusion set will be consulted every time a header is looked 
up. This causes ConfigHub.__getitem__ to be called multiple times (up to 
seventeen times, once per header). Thus store this set once in order to prevent 
this from happening. This optimization doesn't make sense if IAccessible builds 
description pieces, but provides some speedups if the above scenario is in use 
(particularly on slow computers).
This optimization is destined for 17.1-dev and later.

Affected #:  1 file

diff --git a/addon/appModules/splstudio/__init__.py 
b/addon/appModules/splstudio/__init__.py
index be4b368..367341f 100755
--- a/addon/appModules/splstudio/__init__.py
+++ b/addon/appModules/splstudio/__init__.py
@@ -160,8 +160,9 @@ class SPLTrackItem(IAccessible):
                # 17.1: Even if vertical column commands are performed, build 
description pieces for consistency.
                if splconfig._shouldBuildDescriptionPieces():
                        descriptionPieces = []
+                       columnsToInclude = 
splconfig.SPLConfig["ColumnAnnouncement"]["IncludedColumns"]
                        for header in 
splconfig.SPLConfig["ColumnAnnouncement"]["ColumnOrder"]:
-                               if header in 
splconfig.SPLConfig["ColumnAnnouncement"]["IncludedColumns"]:
+                               if header in columnsToInclude:
                                        index = self.indexOf(header)
                                        if index is None: continue # Header not 
found, mostly encountered in Studio 5.0x.
                                        content = self._getColumnContent(index)


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/42353c639d22/
Changeset:   42353c639d22
Branch:      None
User:        josephsl
Date:        2016-11-18 08:35:35+00:00
Summary:     Integer data optimization (17.1-dev): data conversion 
optimizations for playlist remaiing time script and toggle status announcement 
checker.

Code from old days: before validation routine was introduced, microphone alarm 
was converted from string to integer and back when settings were loaded and 
saved, respectively. With the introduction of the validation framework in 
add-on 6.0 and beyond, this is no longer necessary, as mic alarm value will 
always be an integer.
Playlist remainder script: instead of splitting segue value and adding 
converted values one by one, just build an integer list (split and convert data 
at the same time via list comprehension). Then add minutes and seconds, and 
then add hour if this is the case. Also, this whole operation will not happen 
if there's really no segue (00:00).
The integer data conversion optimizations are reserved for 17.1 and later (used 
dis.dis function for tracing bytecode cache).

Affected #:  1 file

diff --git a/addon/appModules/splstudio/__init__.py 
b/addon/appModules/splstudio/__init__.py
index 367341f..4d14dc9 100755
--- a/addon/appModules/splstudio/__init__.py
+++ b/addon/appModules/splstudio/__init__.py
@@ -708,7 +708,7 @@ class AppModule(appModuleHandler.AppModule):
                                        self._toggleMessage(obj.name)
                                else:
                                        ui.message(obj.name)
-                               if self.cartExplorer or 
int(splconfig.SPLConfig["MicrophoneAlarm"]["MicAlarm"]):
+                               if self.cartExplorer or 
splconfig.SPLConfig["MicrophoneAlarm"]["MicAlarm"]:
                                        # Activate mic alarm or announce when 
cart explorer is active.
                                        self.doExtraAction(obj.name)
                # Monitor the end of track and song intro time and announce it.
@@ -1588,9 +1588,11 @@ class AppModule(appModuleHandler.AppModule):
                totalDuration = 0
                while obj is not None:
                        segue = obj._getColumnContent(col)
-                       if segue is not None:
-                               hms = segue.split(":")
-                               totalDuration += (int(hms[0])*3600) + 
(int(hms[1])*60) + int(hms[2]) if len(hms) == 3 else (int(hms[0])*60) + 
int(hms[1])
+                       # 17.1 optimization: list comprehension and data 
conversion at the same time, then add minute/second (hour also if this is the 
case), forget it if it is 00:00.
+                       if segue not in (None, "00:00"):
+                               hms = [int(seg) for seg in segue.split(":")]
+                               totalDuration += (hms[-2]*60) + hms[-1]
+                               if len(hms) == 3: duration += hms[0]*3600
                        obj = obj.next
                self.announceTime(totalDuration, ms=False)
 


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/1e3776a30b65/
Changeset:   1e3776a30b65
Branch:      None
User:        josephsl
Date:        2016-11-18 08:44:51+00:00
Summary:     Oops, check variable name in playlist remainder script.

Affected #:  1 file

diff --git a/addon/appModules/splstudio/__init__.py 
b/addon/appModules/splstudio/__init__.py
index 4d14dc9..2a7d20d 100755
--- a/addon/appModules/splstudio/__init__.py
+++ b/addon/appModules/splstudio/__init__.py
@@ -1592,7 +1592,7 @@ class AppModule(appModuleHandler.AppModule):
                        if segue not in (None, "00:00"):
                                hms = [int(seg) for seg in segue.split(":")]
                                totalDuration += (hms[-2]*60) + hms[-1]
-                               if len(hms) == 3: duration += hms[0]*3600
+                               if len(hms) == 3: totalDuration += hms[0]*3600
                        obj = obj.next
                self.announceTime(totalDuration, ms=False)
 


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/bdc66773d9ec/
Changeset:   bdc66773d9ec
Branch:      None
User:        josephsl
Date:        2016-11-19 00:39:29+00:00
Summary:     Data conversion optimizations (17.1-dev): Just call int function 
instead of using list comprehension.

It turns out using int function uses less instructions and improves readability 
without resorting to using a variable.

Affected #:  1 file

diff --git a/addon/appModules/splstudio/__init__.py 
b/addon/appModules/splstudio/__init__.py
index 2a7d20d..00b365b 100755
--- a/addon/appModules/splstudio/__init__.py
+++ b/addon/appModules/splstudio/__init__.py
@@ -1588,11 +1588,10 @@ class AppModule(appModuleHandler.AppModule):
                totalDuration = 0
                while obj is not None:
                        segue = obj._getColumnContent(col)
-                       # 17.1 optimization: list comprehension and data 
conversion at the same time, then add minute/second (hour also if this is the 
case), forget it if it is 00:00.
                        if segue not in (None, "00:00"):
-                               hms = [int(seg) for seg in segue.split(":")]
-                               totalDuration += (hms[-2]*60) + hms[-1]
-                               if len(hms) == 3: totalDuration += hms[0]*3600
+                               hms = segue.split(":")
+                               totalDuration += (int(hms[-2])*60) + 
int(hms[-1])
+                               if len(hms) == 3: totalDuration += 
int(hms[0])*3600
                        obj = obj.next
                self.announceTime(totalDuration, ms=False)
 


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/1d59723a612c/
Changeset:   1d59723a612c
Branch:      None
User:        josephsl
Date:        2016-11-23 03:47:32+00:00
Summary:     Merge branch '16.10.x'

Affected #:  1 file

diff --git a/addon/appModules/splstudio/__init__.py 
b/addon/appModules/splstudio/__init__.py
index 00b365b..436f298 100755
--- a/addon/appModules/splstudio/__init__.py
+++ b/addon/appModules/splstudio/__init__.py
@@ -316,7 +316,8 @@ class SPLTrackItem(IAccessible):
                                # Translators: Presented when there is no track 
comment for the focused track.
                                ui.message(_("No comment"))
                        elif level >= 3:
-                               if filename is not None:
+                               # 16.12: timed break notes shows an odd value 
for filename (seconds in integers followed by a colon), potentially confusing 
users.)
+                               if filename and not filename.endswith(":"):
                                        self._trackCommentsEntry(filename, "")
                                else:
                                        # Translators: Presented when focused 
on a track other than an actual track (such as hour marker).
@@ -704,7 +705,8 @@ class AppModule(appModuleHandler.AppModule):
                                        if self.libraryScanning: 
self.libraryScanning = False
                                        self.scanCount = 0
                        else:
-                               if obj.name.endswith((" On", " Off")):
+                               # 16.12: Because cart edit text shows cart 
insert status, exclude this from toggle state announcement.
+                               if obj.name.endswith((" On", " Off")) and not 
obj.name.startswith("Cart "):
                                        self._toggleMessage(obj.name)
                                else:
                                        ui.message(obj.name)


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/cba673752a26/
Changeset:   cba673752a26
Branch:      None
User:        josephsl
Date:        2016-11-23 16:06:40+00:00
Summary:     GUi Helper (17.1-dev): converted column announcement dialog.

For column announcement dialog, it was found that it's gotten taller because 
the label for the list box (column announcement order) is above the list box 
itself, not to the left. This will necessitate moving move up/down buttons to 
the right of the list box (otherwise there is a huge whitespace). The button 
arrangement will be done once NVDA 2016.4 is released.

Affected #:  1 file

diff --git a/addon/appModules/splstudio/splconfui.py 
b/addon/appModules/splstudio/splconfui.py
index dd7bd84..9b4fc48 100755
--- a/addon/appModules/splstudio/splconfui.py
+++ b/addon/appModules/splstudio/splconfui.py
@@ -1047,35 +1047,70 @@ class ColumnAnnouncementsDialog(wx.Dialog):
                label = wx.StaticText(self, wx.ID_ANY, label=_("Select columns 
to be announced (artist and title are announced by default"))
                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 checkedColumn in self.checkedColumns:
-                       sizer.Add(checkedColumn)
-               mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
+                       if splconfig.useGUIHelper:
+                               sizer.addItem(checkedColumn)
+                       else:
+                               sizer.Add(checkedColumn)
+               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 checkedColumn in self.checkedColumns2:
-                       sizer.Add(checkedColumn)
-               mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
+                       if splconfig.useGUIHelper:
+                               sizer.addItem(checkedColumn)
+                       else:
+                               sizer.Add(checkedColumn)
+               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 checkedColumn in self.checkedColumns3:
-                       sizer.Add(checkedColumn)
-               mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
+                       if splconfig.useGUIHelper:
+                               sizer.addItem(checkedColumn)
+                       else:
+                               sizer.Add(checkedColumn)
+               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)
-               # Translators: The label for a setting in SPL add-on dialog to 
select column announcement order.
-               label = wx.StaticText(self, wx.ID_ANY, label=_("Column 
&order:"))
-               # WXPython Phoenix contains RearrangeList to allow item orders 
to be changed automatically.
-               # Because WXPython Classic doesn't include this, work around by 
using a variant of list box and move up/down buttons.
-               self.trackColumns= wx.ListBox(self, wx.ID_ANY, 
choices=parent.columnOrder)
-               self.trackColumns.Bind(wx.EVT_LISTBOX,self.onColumnSelection)
-               try:
+               if splconfig.useGUIHelper:
+                       sizer= gui.guiHelper.BoxSizerHelper(self, 
orientation=wx.VERTICAL)
+                       # Translators: The label for a setting in SPL add-on 
dialog to select column announcement order.
+                       self.trackColumns = sizer.addLabeledControl(_("Column 
&order:"), wx.ListBox, choices=parent.columnOrder)
+                       
self.trackColumns.Bind(wx.EVT_LISTBOX,self.onColumnSelection)
                        self.trackColumns.SetSelection(0)
-               except:
-                       pass
-               sizer.Add(label)
-               sizer.Add(self.trackColumns)
-               mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
+                       mainSizer.Add(sizer.sizer, border = 
gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
+               else:
+                       sizer = wx.BoxSizer(wx.HORIZONTAL)
+                       # Translators: The label for a setting in SPL add-on 
dialog to select column announcement order.
+                       label = wx.StaticText(self, wx.ID_ANY, label=_("Column 
&order:"))
+                       # WXPython Phoenix contains RearrangeList to allow item 
orders to be changed automatically.
+                       # Because WXPython Classic doesn't include this, work 
around by using a variant of list box and move up/down buttons.
+                       self.trackColumns= wx.ListBox(self, wx.ID_ANY, 
choices=parent.columnOrder)
+                       
self.trackColumns.Bind(wx.EVT_LISTBOX,self.onColumnSelection)
+                       try:
+                               self.trackColumns.SetSelection(0)
+                       except:
+                               pass
+                       sizer.Add(label)
+                       sizer.Add(self.trackColumns)
+                       mainSizer.Add(sizer, border=10, flag=wx.BOTTOM)
 
                sizer = wx.BoxSizer(wx.HORIZONTAL)
                # Translators: The label for a button in SPL add-on 
configuration dialog to reset settings to defaults.


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/dba708a69313/
Changeset:   dba708a69313
Branch:      None
User:        josephsl
Date:        2016-11-24 01:27:11+00:00
Summary:     Metadata streaming gatherer (17.1-dev): optimized metadata 
streaming status gatherers and config checkboxes.

Perhaps read the API wrong: when metadata URL is turned off 9including DSP 
encoder), it returns '0' not '-1'. This opens up rooms for optimizations, 
including:
* App module: metadata status scripts will now check the return value of the 
function instead of coercing a negative value to zero via a variable. This 
avoids creating a temp variable and improves readability.
* Metadata streaming checkboxes: Checkbox.SetValue can now work with return 
values directly instead of using a coerced view.
Also, when announcing overall metadata streaming status (on demand or when 
Studio starts), conditional list comprehension is used to build the flags for 
URL's (does not affect DSP encoder, which also was simplified by using the 
returned value from the SendMessage function). This speeds things, as it 
eliminates unnecessary for loop (comprehension does this automaticlaly) and 
condition checking can be included in list comprehension call.
Also, for presentation, the list of URL's will be built directly instead of 
kept in a variable.
These optimizations are destined for add-on 17.1.

Affected #:  3 files

diff --git a/addon/appModules/splstudio/__init__.py 
b/addon/appModules/splstudio/__init__.py
index 436f298..037b666 100755
--- a/addon/appModules/splstudio/__init__.py
+++ b/addon/appModules/splstudio/__init__.py
@@ -1787,8 +1787,7 @@ class AppModule(appModuleHandler.AppModule):
        # Gesture(s) for the following script cannot be changed by users.
        def script_metadataEnabled(self, gesture):
                url = int(gesture.displayName[-1])
-               checked = statusAPI(url, 36, ret=True)
-               if checked == 1:
+               if statusAPI(url, 36, ret=True):
                        # 0 is DSP encoder status, others are servers.
                        if url:
                                # Translators: Status message for metadata 
streaming.

diff --git a/addon/appModules/splstudio/splconfui.py 
b/addon/appModules/splstudio/splconfui.py
index 9b4fc48..7e92eb5 100755
--- a/addon/appModules/splstudio/splconfui.py
+++ b/addon/appModules/splstudio/splconfui.py
@@ -948,10 +948,7 @@ class MetadataStreamingDialog(wx.Dialog):
                # 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(stream, 36, ret=True)
-                               if streaming == -1: streaming += 1
-                               checkedStream.SetValue(streaming)
+                       if func: checkedStream.SetValue(func(stream, 36, 
ret=True))
                        else: 
checkedStream.SetValue(self.Parent.metadataStreams[stream])
                        self.checkedStreams.append(checkedStream)
 

diff --git a/addon/appModules/splstudio/splmisc.py 
b/addon/appModules/splstudio/splmisc.py
index 27c0f99..d7a9940 100755
--- a/addon/appModules/splstudio/splmisc.py
+++ b/addon/appModules/splstudio/splmisc.py
@@ -345,11 +345,12 @@ def _metadataAnnouncer(reminder=False, handle=None):
                for url in xrange(5):
                        dataLo = 0x00010000 if 
splconfig.SPLConfig["MetadataStreaming"]["MetadataEnabled"][url] else 0xffff0000
                        sendMessage(handle, 1024, dataLo | url, 36)
-       dsp = 1 if sendMessage(handle, 1024, 0, 36) == 1 else 0
-       streamCount = []
-       for pos in xrange(1, 5):
-               checked = sendMessage(handle, 1024, pos, 36)
-               if checked == 1: streamCount.append(pos)
+       # Gather stream flags.
+       # DSP is treated specially.
+       dsp = sendMessage(handle, 1024, 0, 36)
+       # For others, a simple list.append will do.
+       # 17.1: Use a conditional list comprehension.
+       streamCount = [str(pos) for pos in xrange(1, 5) if sendMessage(handle, 
1024, pos, 36)]
        # Announce streaming status when told to do so.
        status = None
        if not len(streamCount):
@@ -363,11 +364,10 @@ def _metadataAnnouncer(reminder=False, handle=None):
                # Translators: Status message for metadata streaming.
                else: status = _("Metadata streaming configured for URL 
{URL}").format(URL = streamCount[0])
        else:
-               urltext = ", ".join([str(stream) for stream in streamCount])
                # Translators: Status message for metadata streaming.
-               if dsp: status = _("Metadata streaming configured for DSP 
encoder and URL's {URL}").format(URL = urltext)
+               if dsp: status = _("Metadata streaming configured for DSP 
encoder and URL's {URL}").format(URL = ", ".join(streamCount))
                # Translators: Status message for metadata streaming.
-               else: status = _("Metadata streaming configured for URL's 
{URL}").format(URL = urltext)
+               else: status = _("Metadata streaming configured for URL's 
{URL}").format(URL = ", ".join(streamCount))
        if reminder:
                time.sleep(2)
                speech.cancelSpeech()


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/4abe99fc2b82/
Changeset:   4abe99fc2b82
Branch:      None
User:        josephsl
Date:        2016-11-25 21:07:21+00:00
Summary:     SPL add-on 16.12, including improved support for Studio and Track 
Tool 5.20, cart edit/insert mode announcement improvements.

Signed-off-by: Joseph Lee <joseph.lee22590@xxxxxxxxx>

Affected #:  2 files

diff --git a/buildVars.py b/buildVars.py
index fe022c6..5f12202 100755
--- a/buildVars.py
+++ b/buildVars.py
@@ -20,7 +20,7 @@ addon_info = {
        "addon_description" : _("""Enhances support for StationPlaylist Studio.
 In addition, adds global commands for the studio from everywhere."""),
        # version
-       "addon_version" : "16.11",
+       "addon_version" : "16.12",
        # Author(s)
        "addon_author" : u"Geoff Shang, Joseph Lee and other contributors",
        # URL for the add-on documentation support

diff --git a/readme.md b/readme.md
index 9208a82..93ae3d4 100755
--- a/readme.md
+++ b/readme.md
@@ -3,13 +3,13 @@
 * Authors: Geoff Shang, Joseph Lee and other contributors
 * Download [stable version][1]
 * Download [development version][2]
-* Download [long-term support version][3] - add-on 7.x for Studio 5.0x users
+* Download [long-term support version][3] - add-on 15.x for Studio 5.0x users
 
 This add-on package provides improved usage of StationPlaylist Studio, as well 
as providing utilities to control the Studio from anywhere.
 
 For more information about the add-on, read the [add-on guide][4]. For 
developers seeking to know how to build the add-on, see buildInstructions.txt 
located at the root of the add-on source code repository.
 
-IMPORTANT: This add-on requires NVDA 2015.3 or later and StationPlaylist 
Studio 5.00 or later. If you have installed NVDA 2016.1 or later on Windows 8 
and later, disable audio ducking mode. Also, add-on 8.0/16.10 requires Studio 
5.10 and later, and for broadcasters using Studio 5.0x, a long-term support 
version (7.x) is available.
+IMPORTANT: This add-on requires NVDA 2015.3 or later and StationPlaylist 
Studio 5.00 or later. If you have installed NVDA 2016.1 or later on Windows 8 
and later, disable audio ducking mode. Also, add-on 8.0/16.10 requires Studio 
5.10 and later, and for broadcasters using Studio 5.0x, a long-term support 
version (15.x) is available.
 
 ## Shortcut keys
 
@@ -170,6 +170,13 @@ From studio window, you can press Alt+NVDA+0 to open the 
add-on configuration di
 
 If you are using Studio on a touchscreen computer running Windows 8 or later 
and have NVDA 2012.3 or later installed, you can perform some Studio commands 
from the touchscreen. First use three finger tap to switch to SPL mode, then 
use the touch commands listed above to perform commands.
 
+## Version 16.12/15.4-LTS
+
+* More work on supporting Studio 5.20, including announcing cart insert mode 
status (if turned on) from SPL Assistant layer (T).
+* Cart edit/insert mode toggle is no longer affected by message verbosity nor 
status announcement type settings (this status will always be announced via 
speech and/or braille).
+* It is no longer possible to add comments to timed break notes.
+* Support for Track Tool 5.20, including fixed an issue where wrong 
information is announced when using Columns Explorer commands to announce 
column information.
+
 ## 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.


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/a5a8aaae97ee/
Changeset:   a5a8aaae97ee
Branch:      master
User:        josephsl
Date:        2016-11-25 21:09:18+00:00
Summary:     Merged stable

Affected #:  1 file

diff --git a/readme.md b/readme.md
index f48d62c..1b5fef6 100755
--- a/readme.md
+++ b/readme.md
@@ -3,13 +3,13 @@
 * Authors: Geoff Shang, Joseph Lee and other contributors
 * Download [stable version][1]
 * Download [development version][2]
-* Download [long-term support version][3] - add-on 7.x for Studio 5.0x users
+* Download [long-term support version][3] - add-on 15.x for Studio 5.0x users
 
 This add-on package provides improved usage of StationPlaylist Studio, as well 
as providing utilities to control the Studio from anywhere.
 
 For more information about the add-on, read the [add-on guide][4]. For 
developers seeking to know how to build the add-on, see buildInstructions.txt 
located at the root of the add-on source code repository.
 
-IMPORTANT: This add-on requires NVDA 2015.3 or later and StationPlaylist 
Studio 5.00 or later. If you have installed NVDA 2016.1 or later on Windows 8 
and later, disable audio ducking mode. Also, add-on 8.0/16.10 requires Studio 
5.10 and later, and for broadcasters using Studio 5.0x, a long-term support 
version (7.x) is available.
+IMPORTANT: This add-on requires NVDA 2015.3 or later and StationPlaylist 
Studio 5.00 or later. If you have installed NVDA 2016.1 or later on Windows 8 
and later, disable audio ducking mode. Also, add-on 8.0/16.10 requires Studio 
5.10 and later, and for broadcasters using Studio 5.0x, a long-term support 
version (15.x) is available.
 
 ## Shortcut keys
 
@@ -169,12 +169,20 @@ From studio window, you can press Alt+NVDA+0 to open the 
add-on configuration di
 
 If you are using Studio on a touchscreen computer running Windows 8 or later 
and have NVDA 2012.3 or later installed, you can perform some Studio commands 
from the touchscreen. First use three finger tap to switch to SPL mode, then 
use the touch commands listed above to perform commands.
 
+<<<<<<< HEAD
 ## Version 17.1-dev
 
 * 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.
 * Removed Track Dial (NVDA's version of enhanced arrow keys), replaced by 
Columns explorer and Column Navigator/table navigation commands). This affects 
Studio and Track Tool.
 
+## Version 16.12/15.4-LTS
+
+* More work on supporting Studio 5.20, including announcing cart insert mode 
status (if turned on) from SPL Assistant layer (T).
+* Cart edit/insert mode toggle is no longer affected by message verbosity nor 
status announcement type settings (this status will always be announced via 
speech and/or braille).
+* It is no longer possible to add comments to timed break notes.
+* Support for Track Tool 5.20, including fixed an issue where wrong 
information is announced when using Columns Explorer commands to announce 
column information.
+
 ## 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.

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:

  • » commit/StationPlaylist: 23 new changesets - commits-noreply