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.