commit/StationPlaylist: 2 new changesets

  • From: commits-noreply@xxxxxxxxxxxxx
  • To: nvda-addons-commits@xxxxxxxxxxxxx
  • Date: Fri, 08 Jan 2016 19:10:53 -0000

2 new commits in StationPlaylist:

https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/8d6e3b72f147/
Changeset:   8d6e3b72f147
Branch:      None
User:        josephsl
Date:        2016-01-08 19:05:26+00:00
Summary:     Merge branch 'master' into 7.0/amberCategorySounds

Affected #:  4 files

diff --git a/addon/appModules/splstudio/__init__.py 
b/addon/appModules/splstudio/__init__.py
index c6c7eb7..9f808c9 100755
--- a/addon/appModules/splstudio/__init__.py
+++ b/addon/appModules/splstudio/__init__.py
@@ -278,11 +278,11 @@ SPLAssistantHelp={
        "off":_("""After entering SPL Assistant, press:
 A: Automation.
 C: Announce name of the currently playing track.
-D (R if compatibility mode is on): Remaining time for the playlist.
+D: Remaining time for the playlist.
 E: Overall metadata streaming status.
 1 through 4, 0: Metadata streaming status for DSP encoder and four additional 
URL's.
 H: Duration of trakcs in this hour slot.
-Shift+H: Duration of selected tracks.
+Shift+H: Duration of remaining trakcs in this hour slot.
 I: Listener count.
 K: Move to place marker track.
 Control+K: Set place marker track.
@@ -291,9 +291,10 @@ M: Microphone status.
 N: Next track.
 P: Playback status.
 Shift+P: Pitch for the current track.
-R (Shift+E if compatibility mode is on): Record to file.
+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.
 U: Studio up time.
 W: Weather and temperature.
@@ -310,8 +311,9 @@ Shift+C: Announce name of the currently playing track.
 E: Overall metadata streaming status.
 1 through 4, 0: Metadata streaming status for DSP encoder and four additional 
URL's.
 Shift+E: Record to file.
+F: Track finder.
 H: Duration of trakcs in this hour slot.
-Shift+H: Duration of selected tracks.
+Shift+H: Duration of remaining trakcs in this hour slot.
 K: Move to place marker track.
 Control+K: Set place marker track.
 L: Listener count.
@@ -323,6 +325,7 @@ Shift+P: Pitch for the current track.
 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.
 U: Studio up time.
 W: Weather and temperature.
@@ -337,10 +340,13 @@ A: Automation.
 C: Toggle cart explorer.
 Shift+C: Announce name of the currently playing track.
 D: Remaining time for the playlist.
-E: Overall metadata streaming status.
+E: Elapsed time.
+F: Track finder.
+R: Remaining time for the currently playing track.
+G: Overall metadata streaming status.
 1 through 4, 0: Metadata streaming status for DSP encoder and four additional 
URL's.
 H: Duration of trakcs in this hour slot.
-Shift+H: Duration of selected tracks.
+Shift+H: Duration of remaining trakcs in this hour slot.
 K: Move to place marker track.
 Control+K: Set place marker track.
 L: Listener count.
@@ -352,6 +358,7 @@ Shift+P: Pitch for the current track.
 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.
 U: Studio up time.
 W: Weather and temperature.
@@ -534,14 +541,14 @@ class AppModule(appModuleHandler.AppModule):
                                        and 
splconfig.SPLConfig["IntroOutroAlarms"]["SaySongRamp"]):
                                                self.alarmAnnounce(obj.name, 
512, 400, intro=True)
                                # Hack: auto scroll in Studio itself might be 
broken (according to Brian Hartgen), so force NVDA to announce currently 
playing track automatically if told to do so.
-                               if 
splconfig.SPLConfig["SayStatus"]["SayPlayingTrackName"] == "True": # Had to do 
this to transform this key to something else later.
+                               if 
((splconfig.SPLConfig["SayStatus"]["SayPlayingTrackName"] == "True" and 
self.SPLCurVersion < "5.11")
+                               or 
(splconfig.SPLConfig["SayStatus"]["SayPlayingTrackName"] == "Background" and 
api.getForegroundObject().windowClassName != "TStudioForm")):
                                        try:
                                                statusBarFG = 
obj.parent.parent.parent
                                                if statusBarFG is not None:
                                                        statusBar = 
statusBarFG.previous.previous.previous
                                                        if statusBar is not 
None and statusBar.firstChild is not None and statusBar.firstChild.role == 
controlTypes.ROLE_STATUSBAR:
                                                                
ui.message(obj.name)
-                                                               
tones.beep(1000, 100)
                                        except AttributeError:
                                                pass
                nextHandler()
@@ -678,19 +685,6 @@ class AppModule(appModuleHandler.AppModule):
 
        # A few time related scripts (elapsed time, remaining time, etc.).
 
-       # Speak any time-related errors.
-       # Message type: error message.
-       timeMessageErrors={
-               # Translators: Presented when remaining time is unavailable.
-               1:_("Remaining time not available"),
-               # Translators: Presented when elapsed time is unavailable.
-               2:_("Elapsed time not available"),
-               # Translators: Presented when broadcaster time is unavailable.
-                       3:_("Broadcaster time not available"),
-               # Translators: Presented when time information is unavailable.
-               4:_("Cannot obtain time in hours, minutes and seconds")
-       }
-
        # 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.
@@ -724,54 +718,39 @@ class AppModule(appModuleHandler.AppModule):
 
        # Scripts which rely on API.
        def script_sayRemainingTime(self, gesture):
-               fgWindow = api.getForegroundObject()
-               if fgWindow.windowClassName == "TStudioForm":
-                       statusAPI(3, 105, self.announceTime, offset=1)
-               else:
-                       ui.message(self.timeMessageErrors[1])
+               statusAPI(3, 105, self.announceTime, offset=1)
        # Translators: Input help mode message for a command in Station 
Playlist Studio.
        script_sayRemainingTime.__doc__=_("Announces the remaining track time.")
 
        def script_sayElapsedTime(self, gesture):
-               fgWindow = api.getForegroundObject()
-               if fgWindow.windowClassName == "TStudioForm":
-                       statusAPI(0, 105, self.announceTime)
-               else:
-                       ui.message(self.timeMessageErrors[2])
+               statusAPI(0, 105, self.announceTime)
        # Translators: Input help mode message for a command in Station 
Playlist Studio.
        script_sayElapsedTime.__doc__=_("Announces the elapsed time for the 
currently playing track.")
 
        def script_sayBroadcasterTime(self, gesture):
                # Says things such as "25 minutes to 2" and "5 past 11".
-               fgWindow = api.getForegroundObject()
-               if fgWindow.windowClassName == "TStudioForm":
-                       # Parse the local time and say it similar to how Studio 
presents broadcaster time.
-                       h, m = time.localtime()[3], time.localtime()[4]
-                       if h not in (0, 12):
-                               h %= 12
-                       if m == 0:
-                               if h == 0: h+=12
-                               # Messages in this method should not be 
translated.
-                               broadcasterTime = "{hour} o'clock".format(hour 
= h)
-                       elif 1 <= m <= 30:
-                               if h == 0: h+=12
-                               broadcasterTime = "{minute} min past 
{hour}".format(minute = m, hour = h)
-                       else:
-                               if h == 12: h = 1
-                               m = 60-m
-                               broadcasterTime = "{minute} min to 
{hour}".format(minute = m, hour = h+1)
-                       ui.message(broadcasterTime)
+               # Parse the local time and say it similar to how Studio 
presents broadcaster time.
+               h, m = time.localtime()[3], time.localtime()[4]
+               if h not in (0, 12):
+                       h %= 12
+               if m == 0:
+                       if h == 0: h+=12
+                       # Messages in this method should not be translated.
+                       broadcasterTime = "{hour} o'clock".format(hour = h)
+               elif 1 <= m <= 30:
+                       if h == 0: h+=12
+                       broadcasterTime = "{minute} min past 
{hour}".format(minute = m, hour = h)
                else:
-                       ui.message(self.timeMessageErrors[3])
+                       if h == 12: h = 1
+                       m = 60-m
+                       broadcasterTime = "{minute} min to 
{hour}".format(minute = m, hour = h+1)
+               ui.message(broadcasterTime)
        # Translators: Input help mode message for a command in Station 
Playlist Studio.
        script_sayBroadcasterTime.__doc__=_("Announces broadcaster time.")
 
        def script_sayCompleteTime(self, gesture):
                # Says complete time in hours, minutes and seconds via 
kernel32's routines.
-               if api.getForegroundObject().windowClassName == "TStudioForm":
-                       
ui.message(winKernel.GetTimeFormat(winKernel.LOCALE_USER_DEFAULT, 0, None, 
None))
-               else:
-                       ui.message(self.timeMessageErrors[4])
+               
ui.message(winKernel.GetTimeFormat(winKernel.LOCALE_USER_DEFAULT, 0, None, 
None))
        # Translators: Input help mode message for a command in Station 
Playlist Studio.
        script_sayCompleteTime.__doc__=_("Announces time including seconds.")
 
@@ -1385,7 +1364,7 @@ class AppModule(appModuleHandler.AppModule):
        # Status table keys
        SPLPlayStatus = 0
        SPLSystemStatus = 1
-       SPLHourSelectedDuration = 3
+       SPLScheduledToPlay = 3
        SPLNextTrackTitle = 4
        SPLCurrentTrackTitle = 5
        SPLTemperature = 6
@@ -1397,7 +1376,7 @@ class AppModule(appModuleHandler.AppModule):
        statusObjs={
                SPLPlayStatus:[5, 6], # Play status, mic, etc.
                SPLSystemStatus:[-3, -2], # The second status bar containing 
system status such as up time.
-               SPLHourSelectedDuration:[18, 19], # In case the user selects 
one or more tracks in a given hour.
+               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.
@@ -1457,31 +1436,26 @@ class AppModule(appModuleHandler.AppModule):
        def script_sayHourTrackDuration(self, gesture):
                statusAPI(0, 27, self.announceTime)
 
-       def script_sayHourSelectedTrackDuration(self, gesture):
-               obj = self.status(self.SPLHourSelectedDuration).firstChild
-               ui.message(obj.name)
+       def script_sayHourRemaining(self, gesture):
+               # 7.0: Split from playlist remaining script (formerly the 
playlist remainder command).
+               statusAPI(1, 27, self.announceTime)
 
        def script_sayPlaylistRemainingDuration(self, gesture):
-               # 6.2: By default, remaining time for the hour will be 
announced.
-               if splconfig.SPLConfig["Advanced"]["PlaylistRemainder"] == 
"hour":
-                       statusAPI(1, 27, self.announceTime)
-               else:
-                       # 6.2: Manually go through all tracks, gathering segue 
information.
-                       tones.beep(1024, 30)
-                       obj = api.getFocusObject()
-                       if obj.role == controlTypes.ROLE_LIST:
-                               ui.message("00:00")
-                               return
-                       col = obj._indexOf("Duration")
-                       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])
-                               obj = obj.next
-                       # 6.2: For now, millisecond will be calculated manually.
-                       self.announceTime(totalDuration, ms=False)
+               # 7.0: Manually go through all tracks, calculationg total 
duration (a bit of discrepancy may result).
+               tones.beep(1024, 30)
+               obj = api.getFocusObject()
+               if obj.role == controlTypes.ROLE_LIST:
+                       ui.message("00:00")
+                       return
+               col = obj._indexOf("Duration")
+               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])
+                       obj = obj.next
+               self.announceTime(totalDuration, ms=False)
 
        def script_sayPlaylistModified(self, gesture):
                try:
@@ -1535,9 +1509,15 @@ class AppModule(appModuleHandler.AppModule):
                ui.message(obj.name)
 
        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)
 
+       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)
+
        def script_sayListenerCount(self, gesture):
                obj = self.status(self.SPLSystemStatus).children[3]
                # Translators: Presented when there is no listener count 
information.
@@ -1690,7 +1670,7 @@ class AppModule(appModuleHandler.AppModule):
                "kb:r":"sayRecToFileStatus",
                "kb:t":"sayCartEditStatus",
                "kb:h":"sayHourTrackDuration",
-               "kb:shift+h":"sayHourSelectedTrackDuration",
+               "kb:shift+h":"sayHourRemaining",
                "kb:d":"sayPlaylistRemainingDuration",
                "kb:y":"sayPlaylistModified",
                "kb:u":"sayUpTime",
@@ -1699,11 +1679,13 @@ class AppModule(appModuleHandler.AppModule):
                "kb:w":"sayTemperature",
                "kb:i":"sayListenerCount",
                "kb:s":"sayScheduledTime",
+               "kb:shift+s":"sayScheduledToPlay",
                "kb:shift+p":"sayTrackPitch",
                "kb:shift+r":"libraryScanMonitor",
                "kb:f9":"markTrackForAnalysis",
                "kb:f10":"trackTimeAnalysis",
                "kb:f12":"switchProfiles",
+               "kb:f":"findTrack",
                "kb:Control+k":"setPlaceMarker",
                "kb:k":"findPlaceMarker",
                "kb:e":"metadataStreamingAnnouncer",
@@ -1725,7 +1707,7 @@ class AppModule(appModuleHandler.AppModule):
                "kb:shift+e":"sayRecToFileStatus",
                "kb:t":"sayCartEditStatus",
                "kb:h":"sayHourTrackDuration",
-               "kb:shift+h":"sayHourSelectedTrackDuration",
+               "kb:shift+h":"sayHourRemaining",
                "kb:r":"sayPlaylistRemainingDuration",
                "kb:y":"sayPlaylistModified",
                "kb:u":"sayUpTime",
@@ -1735,11 +1717,13 @@ class AppModule(appModuleHandler.AppModule):
                "kb:w":"sayTemperature",
                "kb:l":"sayListenerCount",
                "kb:s":"sayScheduledTime",
+               "kb:shift+s":"sayScheduledToPlay",
                "kb:shift+p":"sayTrackPitch",
                "kb:shift+r":"libraryScanMonitor",
                "kb:f9":"markTrackForAnalysis",
                "kb:f10":"trackTimeAnalysis",
                "kb:f12":"switchProfiles",
+               "kb:f":"findTrack",
                "kb:Control+k":"setPlaceMarker",
                "kb:k":"findPlaceMarker",
                "kb:e":"metadataStreamingAnnouncer",
@@ -1759,9 +1743,11 @@ class AppModule(appModuleHandler.AppModule):
                "kb:shift+l":"sayLineInStatus",
                "kb:shift+e":"sayRecToFileStatus",
                "kb:t":"sayCartEditStatus",
+               "kb:e":"sayElapsedTime",
+               "kb:r":"sayRemainingTime",
                "kb:h":"sayHourTrackDuration",
-               "kb:shift+h":"sayHourSelectedTrackDuration",
-               "kb:r":"sayPlaylistRemainingDuration",
+               "kb:shift+h":"sayHourRemaining",
+               "kb:d":"sayPlaylistRemainingDuration",
                "kb:y":"sayPlaylistModified",
                "kb:u":"sayUpTime",
                "kb:n":"sayNextTrackTitle",
@@ -1770,14 +1756,16 @@ class AppModule(appModuleHandler.AppModule):
                "kb:w":"sayTemperature",
                "kb:l":"sayListenerCount",
                "kb:s":"sayScheduledTime",
+               "kb:shift+s":"sayScheduledToPlay",
                "kb:shift+p":"sayTrackPitch",
                "kb:shift+r":"libraryScanMonitor",
                "kb:f9":"markTrackForAnalysis",
                "kb:f10":"trackTimeAnalysis",
                "kb:f12":"switchProfiles",
+               "kb:f":"findTrack",
                "kb:Control+k":"setPlaceMarker",
                "kb:k":"findPlaceMarker",
-               "kb:e":"metadataStreamingAnnouncer",
+               "kb:g":"metadataStreamingAnnouncer",
                "kb:1":"metadataEnabled",
                "kb:2":"metadataEnabled",
                "kb:3":"metadataEnabled",

diff --git a/addon/appModules/splstudio/splconfig.py 
b/addon/appModules/splstudio/splconfig.py
index f150a3e..db1c6f6 100755
--- a/addon/appModules/splstudio/splconfig.py
+++ b/addon/appModules/splstudio/splconfig.py
@@ -183,7 +183,7 @@ def initConfig():
        # 7.0: Store the config as a dictionary.
        # This opens up many possibilities, including config caching, loading 
specific sections only and others (the latter saves memory).
        SPLConfig = dict(SPLConfigPool[0])
-       SPLConfig["ActiveIndex"] = 0 # Holds settings form normal profile.
+       SPLConfig["ActiveIndex"] = 0 # Holds settings from normal profile.
        if curInstantProfile != "": SPLConfig["InstantProfile"] = 
curInstantProfile
        # 7.0: Store add-on installer size in case one wishes to check for 
updates (default size is 0 or no update checked attempted).
        # Same goes to update check time and date (stored as Unix time stamp).
@@ -243,7 +243,7 @@ def unlockConfig(path, profileName=None, prefill=False):
                                                                if setting not 
in _mutatableSettings7:
                                                                        
SPLConfigCheckpoint[setting][failedKey] = SPLConfigPool[0][setting][failedKey]
                                                                else: 
SPLConfigCheckpoint[setting][failedKey] = _SPLDefaults7[setting][failedKey]
-                       # 7.0/magenta: Disqualified from being cached this time.
+                       # 7.0: Disqualified from being cached this time.
                        SPLConfigCheckpoint.write()
                        _configLoadStatus[profileName] = "partialReset"
        _extraInitSteps(SPLConfigCheckpoint, profileName=profileName)
@@ -325,11 +325,12 @@ def getProfileByName(name):
 # Merge sections when switching profiles.
 # This is also employed by the routine which saves changes to a profile when 
user selects a different profile from add-on settings dialog.
 # Profiles refer to indecies.
-def mergeSections(profile):
+# Active refers to whether this is a runtime switch (false if saving profiles).
+def mergeSections(profile, active=True):
        global SPLConfig, SPLConfigPool
        for section in _mutatableSettings7:
                SPLConfig[section] = dict(SPLConfigPool[profile][section])
-       SPLConfig["ActiveIndex"] = profile
+       if active: SPLConfig["ActiveIndex"] = profile
 
 # A reverse of the above.
 def applySections(profile, key=None):
@@ -372,18 +373,19 @@ def _preSave(conf):
        # 6.1: Transform column inclusion data structure now.
        conf["ColumnAnnouncement"]["IncludedColumns"] = 
list(conf["ColumnAnnouncement"]["IncludedColumns"])
        # Perform global setting processing only for the normal profile.
-       if getProfileIndexByName(conf.name) == 0:
+       # 7.0: if this is a second pass, index 0 may not be normal profile at 
all.
+       # Use profile path instead.
+       if conf.filename == SPLIni:
                # Cache instant profile for later use.
                if SPLSwitchProfile is not None:
                        conf["InstantProfile"] = SPLSwitchProfile
+                       # 7.0: Also update the runtime dictionary.
+                       SPLConfig["InstantProfile"] = SPLSwitchProfile
                else:
                        try:
                                del conf["InstantProfile"]
                        except KeyError:
                                pass
-               # 6.0 only: Remove obsolete keys.
-               if "MetadataURL" in conf:
-                       del conf["MetadataURL"]
                # 7.0: Check if updates are pending.
                if (("PSZ" in conf and splupdate.SPLAddonSize != conf["PSZ"])
                or ("PSZ" not in conf and splupdate.SPLAddonSize != 0x0)):
@@ -401,11 +403,26 @@ def _preSave(conf):
                        del conf["ColumnAnnouncement"]["ColumnOrder"]
                for setting in conf.keys():
                        for key in conf[setting].keys():
-                               if conf[setting][key] == 
_SPLDefaults7[setting][key]:
-                                       del conf[setting][key]
+                               try:
+                                       if conf[setting][key] == 
_SPLDefaults7[setting][key]:
+                                               del conf[setting][key]
+                               except KeyError:
+                                       pass
                        if setting in conf and not len(conf[setting]):
                                del conf[setting]
 
+# Check if the profile should be written to disk.
+# For the most part, no setting will be modified.
+def shouldSave(profile):
+       tree = None if profile.filename == SPLIni else profile.name
+       for section in profile.keys():
+               if isinstance(profile[section], dict):
+                       for key in profile[section]:
+                               if profile[section][key] != 
_SPLCache[tree][section][key]:
+                                       print key
+                                       return True # Setting modified.
+       return False
+
 
 # Save configuration database.
 def saveConfig():
@@ -414,48 +431,52 @@ def saveConfig():
        # 7.0: Turn off auto update check timer.
        if splupdate._SPLUpdateT is not None and 
splupdate._SPLUpdateT.IsRunning(): splupdate._SPLUpdateT.Stop()
        splupdate._SPLUpdateT = None
-       # Apply any global settings changed in profiles to normal configuration.
+       # Save profile-specific settings to appropriate dictionary if this is 
the case.
        activeIndex = SPLConfig["ActiveIndex"]
        del SPLConfig["ActiveIndex"]
        if activeIndex > 0:
-               for setting in SPLConfig:
-                       if setting not in _mutatableSettings7:
-                               SPLConfigPool[0][setting] = SPLConfig[setting]
-       # 7.0 hack: Due to Python internals, preserving profile-specific 
settings removes the corresponding keys from normal profile.
-       # Therefore, have a temporary place holder for mutatable settings until 
a more elegant solution is found.
-       tempNormalProfile = {}
-       for section in _mutatableSettings7:
-               tempNormalProfile[section] = dict(SPLConfigPool[0][section])
-       # Convert column inclusion set to list even for temp profile to prevent 
weird problems from coming up next time add-on loads.
-       tempNormalProfile["ColumnAnnouncement"]["IncludedColumns"] = 
list(tempNormalProfile["ColumnAnnouncement"]["IncludedColumns"])
+               applySections(activeIndex)
+       # 7.0: Save normal profile first.
+       # Step 1: temporarily merge normal profile.
+       mergeSections(0)
+       # Step 2: Perform presave routine.
+       _preSave(SPLConfigPool[0])
+       # Step 3: global flags, be gone.
+       if "Reset" in SPLConfigPool[0]:
+               del SPLConfigPool[0]["Reset"]
+       # Step 4: Convert keys back to 5.x format.
+       for section in SPLConfigPool[0].keys():
+               if isinstance(SPLConfigPool[0][section], dict):
+                       for key in SPLConfigPool[0][section]:
+                               SPLConfigPool[0][key] = 
SPLConfigPool[0][section][key]
+       # Step 5: Disk write optimization check please.
+       # Convert a few keys.
+       if "PDT" in _SPLCache[None]:
+               _SPLCache[None]["PDT"] = float(_SPLCache[None]["PDT"])
+       # Until update check dictionary is separated...
+       updateChecked = False
+       if ((splupdate.SPLAddonSize != SPLConfigPool[0]["PSZ"])
+       or (splupdate.SPLAddonCheck != SPLConfigPool[0]["PDT"])):
+               updateChecked = True
+       if shouldSave(SPLConfigPool[0]) or updateChecked:
+               SPLConfigPool[0].write()
+       del SPLConfigPool[0]
+       # Now save broadcast profiles.
        for configuration in SPLConfigPool:
                if configuration is not None:
                        _preSave(configuration)
-                       # Save broadcast profiles first.
-                       if getProfileIndexByName(configuration.name) > 0:
-                               # 7.0: Convert profile-specific settings back 
to 5.x format in case add-on 6.x will be installed later (not recommended).
-                               # This will be removed in add-on 7.2.
-                               if len(configuration) > 0:
-                                       for section in configuration.keys():
+                       profileIndex = getProfileIndexByName(configuration.name)
+                       # 7.0: Convert profile-specific settings back to 5.x 
format in case add-on 6.x will be installed later (not recommended).
+                       # This will be removed in add-on 7.2.
+                       if len(configuration) > 0:
+                               for section in configuration.keys():
+                                       if isinstance(configuration[section], 
dict):
                                                for key in 
configuration[section]:
                                                        configuration[key] = 
configuration[section][key]
+                       # 7.0: See if profiles themselves must be saved.
+                       if shouldSave(SPLConfigPool[profileIndex]):
                                configuration.write()
-       # Global flags, be gone.
-       if "Reset" in SPLConfigPool[0]:
-               del SPLConfigPool[0]["Reset"]
-       # Restore the possibly deleted sections.
-       for section in tempNormalProfile.keys():
-               SPLConfigPool[0][section] = tempNormalProfile[section]
-       # Perform same disk write optimization on normal profile now.
-       # Convert a few keys.
-       _SPLCache[None]["PDT"] = float(_SPLCache[None]["PDT"])
-       for setting in SPLConfigPool[0]:
-               try:
-                       if _SPLCache[None][setting] != 
SPLConfigPool[0][setting]:
-                               print setting
-               except KeyError: pass
-       if _SPLCache[None] != SPLConfigPool[0]:
-               SPLConfigPool[0].write()
+       SPLConfig.clear()
        SPLConfig = None
        SPLConfigPool = None
        SPLActiveProfile = None
@@ -887,7 +908,6 @@ class SPLConfigDialog(gui.SettingsDialog):
                SPLConfig["SayStatus"]["SayPlayingTrackName"] = 
self.trackAnnouncements[self.trackAnnouncementList.GetSelection()][0]
                SPLConfig["Advanced"]["SPLConPassthrough"] = 
self.splConPassthrough
                SPLConfig["Advanced"]["CompatibilityLayer"] = self.compLayer
-               SPLConfig["Advanced"]["PlaylistRemainder"] = 
self.playlistRemainder
                SPLConfig["Update"]["AutoUpdateCheck"] = self.autoUpdateCheck
                SPLConfig["ActiveIndex"] = profileIndex
                # Reverse of merge: save profile specific sections to 
individual config dictionaries.
@@ -1008,7 +1028,7 @@ class SPLConfigDialog(gui.SettingsDialog):
                NewProfileDialog(self, copy=True).Show()
 
        def onRename(self, evt):
-               global SPLConfigPool
+               global SPLConfigPool, _SPLCache
                oldDisplayName = self.profiles.GetStringSelection()
                state = oldDisplayName.split(" <")
                oldName = state[0]
@@ -1042,6 +1062,8 @@ class SPLConfigDialog(gui.SettingsDialog):
                self.profileNames[profilePos] = newName
                SPLConfigPool[configPos].name = newName
                SPLConfigPool[configPos].filename = newProfile
+               _SPLCache[newName] = _SPLCache[oldName]
+               del _SPLCache[oldName]
                if len(state) > 1: newName = " <".join([newName, state[1]])
                self.profiles.SetString(index, newName)
                self.profiles.Selection = index
@@ -1060,7 +1082,7 @@ class SPLConfigDialog(gui.SettingsDialog):
                        wx.YES | wx.NO | wx.ICON_QUESTION, self
                ) == wx.NO:
                        return
-               global SPLConfigPool, SPLSwitchProfile, SPLPrevProfile
+               global SPLConfigPool, SPLSwitchProfile, SPLPrevProfile, 
_SPLCache
                path = SPLConfigPool[configPos].filename
                del SPLConfigPool[configPos]
                try:
@@ -1073,6 +1095,7 @@ class SPLConfigDialog(gui.SettingsDialog):
                        self.switchProfileDeleted = True
                self.profiles.Delete(index)
                del self.profileNames[profilePos]
+               del _SPLCache[name]
                self.profiles.SetString(0, 
getProfileFlags(SPLConfigPool[0].name))
                self.activeProfile = SPLConfigPool[0].name
                self.profiles.Selection = 0
@@ -1574,23 +1597,6 @@ class AdvancedOptionsDialog(wx.Dialog):
                sizer.Add(self.compatibilityList)
                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 
control playlist remainder announcement command (SPL Assistant, D/R).
-               label = wx.StaticText(self, wx.ID_ANY, label=_("Playlist 
&remainder announcement:"))
-               # Translators: One of the playlist remainder announcement 
options.
-               self.playlistRemainderValues=[("hour",_("current hour only")),
-               # Translators: One of the playlist remainder announcement 
options.
-               ("playlist",_("entire playlist"))]
-               self.playlistRemainderList = wx.Choice(self, wx.ID_ANY, 
choices=[x[1] for x in self.playlistRemainderValues])
-               selection = (x for x,y in 
enumerate(self.playlistRemainderValues) if 
y[0]==self.Parent.playlistRemainder).next()  
-               try:
-                       self.playlistRemainderList.SetSelection(selection)
-               except:
-                       pass
-               sizer.Add(label)
-               sizer.Add(self.playlistRemainderList)
-               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)
                self.Bind(wx.EVT_BUTTON, self.onCancel, id=wx.ID_CANCEL)
@@ -1603,7 +1609,6 @@ class AdvancedOptionsDialog(wx.Dialog):
                parent = self.Parent
                parent.splConPassthrough = self.splConPassthroughCheckbox.Value
                parent.compLayer = 
self.compatibilityLayouts[self.compatibilityList.GetSelection()][0]
-               parent.playlistRemainder = 
self.playlistRemainderValues[self.playlistRemainderList.GetSelection()][0]
                parent.autoUpdateCheck = self.autoUpdateCheckbox.Value
                parent.profiles.SetFocus()
                parent.Enable()

diff --git a/addon/globalPlugins/SPLStudioUtils/encoders.py 
b/addon/globalPlugins/SPLStudioUtils/encoders.py
index 5e13012..5a9d874 100755
--- a/addon/globalPlugins/SPLStudioUtils/encoders.py
+++ b/addon/globalPlugins/SPLStudioUtils/encoders.py
@@ -439,6 +439,15 @@ class Encoder(IAccessible):
                        self.backgroundMonitor = encoderIdentifier in 
SPLBackgroundMonitor
                except KeyError:
                        pass
+               # 6.2: Make sure background monitor threads are started if the 
flag is set.
+               if self.backgroundMonitor:
+                       if self.encoderType == "SAM": threadPool = 
SAMMonitorThreads
+                       elif self.encoderType == "SPL": threadPool = 
SPLMonitorThreads
+                       if self.IAccessibleChildID not in threadPool:
+                               statusThread = 
threading.Thread(target=self.reportConnectionStatus)
+                               statusThread.name = "Connection Status Reporter 
" + str(self.IAccessibleChildID)
+                               statusThread.start()
+                               threadPool[self.IAccessibleChildID] = 
statusThread
                # Can I play connection beeps?
                try:
                        self.connectionTone = encoderIdentifier not in 
SPLNoConnectionTone

diff --git a/readme.md b/readme.md
index 2997240..d111428 100755
--- a/readme.md
+++ b/readme.md
@@ -74,23 +74,26 @@ This layer command set allows you to obtain various status 
on SPL Studio, such a
 The available commands are:
 
 * A: Automation.
-* C (NVDA layout): Title for the currently playing track.
-* C in JAWS or Window-Eyes layouts: Toggle cart explorer.
-* D (R in JAWS or Window-Eyes layouts): Remaining duration for the playlist.
-* E: Metadata streaming status.
+* C (Shift+C  in JAWS and Window-Eyes layouts): Title for the currently 
playing track.
+* C (JAWS and Window-Eyes layouts): Toggle cart explorer.
+* D (R in JAWS layout): Remaining duration for the playlist.
+* E (G in Window-Eyes layout): Metadata streaming status.
+* 1 through 4, 0: Status for individual metadata streaming URL's (0 is for DSP 
encoder).
+* E (Window-Eyes layout): Elapsed time for the currently playing track.
 * H: Duration of music for the current hour slot.
-* Shift+H: Total duration of selected tracks for this hour slot (from the 
track list, press SPACE to select or uncheck the track to play).
+* Shift+H: Remaining track duration for the hour slot.
 * I (L in JAWS or Window-Eyes layouts): Listener count.
 * K: Move to the marked track.
 * Control+K: Set the current track as the place marker track.
-* L (Shift+L in JAWS or Window-Eyes layouts): Line in.
+* L (Shift+L in JAWS and Window-Eyes layouts): Line in.
 * M: Microphone.
 * N: Title for the next scheduled track.
 * P: Playback status (playing or stopped).
 * Shift+P: Pitch of the current track.
-* R (Shift+E in JAWS or Window-Eyes layouts): Record to file enabled/disabled.
+* 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.
 * U: Studio up time.
 * Control+Shift+U: Check for add-on updates.
@@ -158,9 +161,12 @@ If you are using Studio on a touchscreen computer running 
Windows 8 or later and
 ## Changes for 7.0-dev
 
 * Added add-on update check feature. This can be done manually (SPL Assistant, 
Control+Shift+U) or automatically (configurable via advanced options dialog 
from add-on settings).
+* Changes to SPL Assistant commands, including playlist duration (D), 
reassignment of hour selection duration from Shift+H to Shift+S and Shift+H now 
used to announce duration of remaining tracks for the current hour slot.
+* It is now possible to invoke track finder via SPL Assistant (F).
 * It is now possible to use a different screen reader command layout for SPL 
Assistant commands. Go to advanced options dialog from add-on settings to 
configure this option between NVDA, JAWS and Window-Eyes layouts. See the SPL 
Assistant commands above for details.
 * Entries in profiles combo box in add-on settings dialog now shows profile 
flags such as active, whether it is an instant switch profile and so on.
 * In add-on settings dialog, the controls used to toggle announcement of 
scheduled time, listener count, cart name and track name has been moved to a 
dedicated status announcements dialog (select status announcement button to 
open this dialog).
+* It is no longer required to stay in the playlist viewer window in order to 
obtain time announcements such as remaining time for the track and broadcaster 
time.
 * In encoders, pressing Control+NVDA+0 will present encoder settings dialog 
for configuring various options such as stream label, focusing to Studio when 
connected and so on.
 * In encoders, it is now possible to turn off connection progress tone 
(configurable from encoder settings dialog).
 


https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/1a0329a519ec/
Changeset:   1a0329a519ec
Branch:      7.0/amberCategorySounds
User:        josephsl
Date:        2016-01-08 19:10:40+00:00
Summary:     Category sounds (7.0-dev): Settings UI added.

Affected #:  1 file

diff --git a/addon/appModules/splstudio/splconfig.py 
b/addon/appModules/splstudio/splconfig.py
index db1c6f6..7c01c7a 100755
--- a/addon/appModules/splstudio/splconfig.py
+++ b/addon/appModules/splstudio/splconfig.py
@@ -61,7 +61,7 @@ BrailleTimer = option("off", "intro", "outro", "both", 
default="off")
 AlarmAnnounce = option("beep", "message", "both", default="beep")
 LibraryScanAnnounce = option("off", "ending", "progress", "numbers", 
default="off")
 TrackDial = boolean(default=false)
-CategorySounds = boolean(default=true)
+CategorySounds = boolean(default=false)
 MetadataReminder = option("off", "startup", "instant", default="off")
 TimeHourAnnounce = boolean(default=false)
 [IntroOutroAlarms]
@@ -776,6 +776,11 @@ class SPLConfigDialog(gui.SettingsDialog):
                
self.trackDialCheckbox.SetValue(SPLConfig["General"]["TrackDial"])
                settingsSizer.Add(self.trackDialCheckbox, 
border=10,flag=wx.BOTTOM)
 
+               # Translators: the label for a setting in SPL add-on settings 
to toggle category sound announcement.
+               
self.categorySoundsCheckbox=wx.CheckBox(self,wx.NewId(),label=_("&Beep for 
different track categories"))
+               
self.categorySoundsCheckbox.SetValue(SPLConfig["General"]["CategorySounds"])
+               settingsSizer.Add(self.categorySoundsCheckbox, 
border=10,flag=wx.BOTTOM)
+
                sizer = wx.BoxSizer(wx.HORIZONTAL)
                # Translators: the label for a setting in SPL add-on settings 
to be notified that metadata streaming is enabled.
                label = wx.StaticText(self, wx.ID_ANY, label=_("&Metadata 
streaming notification and connection"))
@@ -897,6 +902,7 @@ class SPLConfigDialog(gui.SettingsDialog):
                SPLConfig["General"]["LibraryScanAnnounce"] = 
self.libScanValues[self.libScanList.GetSelection()][0]
                SPLConfig["General"]["TimeHourAnnounce"] = 
self.hourAnnounceCheckbox.Value
                SPLConfig["General"]["TrackDial"] = self.trackDialCheckbox.Value
+               SPLConfig["General"]["CategorySounds"] = 
self.categorySoundsCheckbox.Value
                SPLConfig["General"]["MetadataReminder"] = 
self.metadataValues[self.metadataList.GetSelection()][0]
                SPLConfig["MetadataStreaming"]["MetadataEnabled"] = 
self.metadataStreams
                SPLConfig["ColumnAnnouncement"]["UseScreenColumnOrder"] = 
self.columnOrderCheckbox.Value

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: