1 new commit in StationPlaylist:
https://bitbucket.org/nvdaaddonteam/stationplaylist/commits/b336cc3950ba/
Changeset: b336cc3950ba
Branch: staging
User: josephsl
Date: 2016-01-25 17:29:12+00:00
Summary: Merge branch 'master' into staging
Affected #: 5 files
diff --git a/addon/appModules/splstudio/__init__.py
b/addon/appModules/splstudio/__init__.py
index 0877619..38137a7 100755
--- a/addon/appModules/splstudio/__init__.py
+++ b/addon/appModules/splstudio/__init__.py
@@ -1605,7 +1605,7 @@ class AppModule(appModuleHandler.AppModule):
script_trackTimeAnalysis.__doc__=_("Announces total length of tracks
between analysis start marker and the current track")
def script_switchProfiles(self, gesture):
- splconfig.triggerProfileSwitch() if
splconfig._SPLTriggerEndTimer.IsRunning() else splconfig.instantProfileSwitch()
+ splconfig.triggerProfileSwitch() if
splconfig._triggerProfileActive else splconfig.instantProfileSwitch()
def script_setPlaceMarker(self, gesture):
obj = api.getFocusObject()
diff --git a/addon/appModules/splstudio/splconfig.py
b/addon/appModules/splstudio/splconfig.py
index 7947260..ed21542 100755
--- a/addon/appModules/splstudio/splconfig.py
+++ b/addon/appModules/splstudio/splconfig.py
@@ -149,6 +149,7 @@ def resetAllConfig():
# In case one or more profiles had config issues, look up the error message
from the following map.
_configErrors ={
+ "fileReset":"Settings reset to defaults due to configuration file
coruption",
"completeReset":"All settings reset to defaults",
"partialReset":"Some settings reset to defaults",
"columnOrderReset":"Column announcement order reset to defaults",
@@ -163,7 +164,6 @@ _configErrors ={
_configLoadStatus = {} # Key = filename, value is pass or no pass.
def initConfig():
- t = time.time()
# 7.0: When add-on 7.0 starts for the first time, check if a conversion
file exists.
# To be removed in add-on 7.2.
curInstantProfile = ""
@@ -218,14 +218,20 @@ def initConfig():
initProfileTriggers()
# Let the update check begin.
splupdate.initialize()
- print time.time()-t
# Unlock (load) profiles from files.
def unlockConfig(path, profileName=None, prefill=False):
global _configLoadStatus # To be mutated only during unlock routine.
# Optimization: Profiles other than normal profile contains
profile-specific sections only.
# This speeds up profile loading routine significantly as there is no
need to call a function to strip global settings.
- SPLConfigCheckpoint = ConfigObj(path, configspec = confspec7 if prefill
else confspecprofiles, encoding="UTF-8")
+ # 7.0: What if profiles have parsing errors?
+ # If so, reset everything back to factory defaults.
+ try:
+ SPLConfigCheckpoint = ConfigObj(path, configspec = confspec7 if
prefill else confspecprofiles, encoding="UTF-8")
+ except:
+ open(path, "w").close()
+ SPLConfigCheckpoint = ConfigObj(path, configspec = confspec7 if
prefill else confspecprofiles, encoding="UTF-8")
+ _configLoadStatus[profileName] = "fileReset"
# 5.2 and later: check to make sure all values are correct.
# 7.0: Make sure errors are displayed as config keys are now sections
and may need to go through subkeys.
configTest = SPLConfigCheckpoint.validate(_val, copy=prefill,
preserve_errors=True)
@@ -684,9 +690,11 @@ def instantProfileSwitch():
# The triggers version of the above function.
# 7.0: Try consolidating this into one or some more functions.
_SPLTriggerEndTimer = None
+# Record if time-based profile is active or not.
+_triggerProfileActive = False
def triggerProfileSwitch():
- global SPLPrevProfile, SPLConfig, SPLActiveProfile, triggerTimer,
_SPLTriggerEndTimer
+ global SPLPrevProfile, SPLConfig, SPLActiveProfile, triggerTimer,
_SPLTriggerEndTimer, _triggerProfileActive
if _configDialogOpened:
# Translators: Presented when trying to switch profiles when
add-on settings dialog is active.
ui.message(_("Add-on settings dialog is open, cannot switch
profiles"))
@@ -706,6 +714,8 @@ def triggerProfileSwitch():
SPLPrevProfile = getProfileIndexByName(SPLActiveProfile)
# Pass in the prev profile, which will be None for
instant profile switch.
switchProfile(SPLPrevProfile, triggerProfileIndex)
+ # Set the global trigger flag to inform various
subsystems such as add-on settings dialog.
+ _triggerProfileActive = True
# Translators: Presented when switch to instant switch
profile was successful.
ui.message(_("Switching profiles"))
# Pause automatic update checking.
@@ -721,6 +731,7 @@ def triggerProfileSwitch():
_SPLTriggerEndTimer.Start(triggerSettings[6] *
60 * 1000, True)
else:
switchProfile(None, SPLPrevProfile)
+ _triggerProfileActive = False
SPLPrevProfile = None
# Translators: Presented when switching from instant
switch profile to a previous profile.
ui.message(_("Returning to previous profile"))
@@ -1108,7 +1119,7 @@ class SPLConfigDialog(gui.SettingsDialog):
self.profiles.SetFocus()
def onOk(self, evt):
- global SPLConfig, SPLActiveProfile, _configDialogOpened,
SPLSwitchProfile, SPLPrevProfile, profileTriggers
+ global SPLConfig, SPLActiveProfile, _configDialogOpened,
SPLSwitchProfile, SPLPrevProfile, profileTriggers, _triggerProfileActive
selectedProfile = self.profiles.GetStringSelection().split("
<")[0]
profileIndex = getProfileIndexByName(selectedProfile)
SPLConfig["General"]["BeepAnnounce"] =
self.beepAnnounceCheckbox.Value
@@ -1143,9 +1154,9 @@ class SPLConfigDialog(gui.SettingsDialog):
applySections(profileIndex)
SPLActiveProfile = selectedProfile
SPLSwitchProfile = self.switchProfile
- # Without nullifying prev profile while switch profile is
undefined, NVDA will assume it can switch back to that profile when it can't.
- # It also causes NVDA to display wrong label for switch button.
- if self.switchProfile is None:
+ # Make sure to nullify prev profile if instant switch profile
is gone.
+ # 7.0: Don't do the following in the midst of a broadcast.
+ if self.switchProfile is None and not _triggerProfileActive:
SPLPrevProfile = None
_configDialogOpened = False
# 7.0: Perform extra action such as restarting auto update
timer.
@@ -1158,11 +1169,12 @@ class SPLConfigDialog(gui.SettingsDialog):
super(SPLConfigDialog, self).onOk(evt)
def onCancel(self, evt):
- global _configDialogOpened, SPLActiveProfile, SPLSwitchProfile,
SPLConfig
+ global _configDialogOpened, SPLActiveProfile, SPLSwitchProfile,
SPLConfig, profileTriggers
# 6.1: Discard changes to included columns set.
self.includedColumns.clear()
self.includedColumns = None
- # Remove profile triggers as well.
+ # Apply profile trigger changes if any.
+ profileTriggers = dict(self._profileTriggersConfig)
self._profileTriggersConfig.clear()
self._profileTriggersConfig = None
triggerStart(restart=True)
@@ -1299,6 +1311,10 @@ class SPLConfigDialog(gui.SettingsDialog):
if self.switchProfile == oldName:
self.switchProfile = newName
self.switchProfileRenamed = True
+ # Be sure to update profile triggers.
+ if oldName in self._profileTriggersConfig:
+ self._profileTriggersConfig[newName] =
self._profileTriggersConfig[oldName]
+ del self._profileTriggersConfig[oldName]
if self.activeProfile == oldName:
self.activeProfile = newName
self.profileNames[profilePos] = newName
@@ -1312,6 +1328,13 @@ class SPLConfigDialog(gui.SettingsDialog):
self.profiles.SetFocus()
def onDelete(self, evt):
+ # Prevent profile deletion in the midst of a broadcast,
otherwise time-based profile switching flag will become inconsistent.
+ # 7.1: Find a way to safely proceed via two-step verification
if trying to delete currently active time-based profile.
+ global _SPLTriggerEndTimer, _triggerProfileActive
+ if (_SPLTriggerEndTimer is not None and
_SPLTriggerEndTimer.IsRunning()) or _triggerProfileActive:
+ gui.messageBox(_("Are you currently broadcasting a
show? If so, please press SPL Assistant, F12 to switch back to a previously
active profile before opening add-on settings to delete a profile."),
+ _("Midst of a broadcast"), wx.OK |
wx.ICON_ERROR, self)
+ return
index = self.profiles.Selection
name = self.profiles.GetStringSelection().split(" <")[0]
configPos = getProfileIndexByName(name)
@@ -1338,6 +1361,8 @@ class SPLConfigDialog(gui.SettingsDialog):
self.profiles.Delete(index)
del self.profileNames[profilePos]
del _SPLCache[name]
+ if name in self._profileTriggersConfig:
+ del self._profileTriggersConfig[name]
# 6.3: Select normal profile if the active profile is gone.
# 7.0: Consult profile names instead.
try:
@@ -1355,7 +1380,7 @@ class SPLConfigDialog(gui.SettingsDialog):
def onInstantSwitch(self, evt):
selection = self.profiles.GetSelection()
# More efficient to pull the name straight from the names pool.
- selectedName = self.profileNames.index(selection)
+ selectedName = self.profileNames[selection]
flag = _("instant switch")
if self.instantSwitchCheckbox.Value:
if self.switchProfile is not None and (selectedName !=
self.switchProfile):
diff --git a/addon/appModules/splstudio/splmisc.py
b/addon/appModules/splstudio/splmisc.py
index 8462ea7..8ef3962 100755
--- a/addon/appModules/splstudio/splmisc.py
+++ b/addon/appModules/splstudio/splmisc.py
@@ -332,7 +332,7 @@ class SPLCountdownTimer(object):
ui.message("Timer complete")
if self.func is not None:
self.func()
- self.stop()
+ self.Stop()
elif 0 < self.duration <= self.threshold:
ui.message(str(self.duration))
diff --git a/addon/installTasks.py b/addon/installTasks.py
index 34dd87e..14d7053 100755
--- a/addon/installTasks.py
+++ b/addon/installTasks.py
@@ -75,7 +75,12 @@ _conversionConfig = {
# Invoked when upgrading to 7.0 (to be removed in 7.2).
def config6to7(path):
- profile = ConfigObj(path, configspec = confspec, encoding="UTF-8")
+ # Sometimes, an exception could be thrown if ConfigObj says it cannot
parse the config file, so skip offending files.
+ # This means the unlock function in splconfig will handle this case.
+ try:
+ profile = ConfigObj(path, configspec = confspec,
encoding="UTF-8")
+ except:
+ return
# Optimization: no need to convert if sectionized.
for section in ["General", "IntroOutroAlarms", "MicrophoneAlarm",
"ColumnAnnouncement", "MetadataStreaming", "SayStatus", "Advanced", "Startup"]:
if section in profile:
diff --git a/readme.md b/readme.md
index 50befe7..5df12f9 100755
--- a/readme.md
+++ b/readme.md
@@ -171,6 +171,7 @@ If you are using Studio on a touchscreen computer running
Windows 8 or later and
* 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.
* NVDA can be configured to switch to a specific broadcast profile at a
specific day and time. Use the new triggers dialog in add-on settings to
configure this.
* 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.
+* If a serious problem with reading broadcast profile files are found, NVDA
will present an error dialog and reset settings to defaults instead of doing
nothing or sounding an error tone.
* 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).
* Added a new setting in add-on settings dialog to let NVDA play beep for
different track categories when moving between tracks in playlist viewer.
* 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.
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.