Package AEOutput :: Module Base
[hide private]
[frames] | no frames]

Source Code for Module AEOutput.Base

  1  ''' 
  2  Defines the base class for all L{AEOutput} devices. 
  3   
  4  @author: Larry Weiss 
  5  @author: Peter Parente 
  6  @author: Brett Clippingdale 
  7  @organization: IBM Corporation 
  8  @copyright: Copyright (c) 2005, 2007 IBM Corporation 
  9  @license: The BSD License 
 10   
 11  All rights reserved. This program and the accompanying materials are made 
 12  available under the terms of the BSD license which accompanies 
 13  this distribution, and is available at 
 14  U{http://www.opensource.org/licenses/bsd-license.php} 
 15  ''' 
 16  import UIElement, Style, AEConstants 
 17   
18 -def getDefaults():
19 ''' 20 Suggests the default L{AEOutput}s events to be monitored. 21 22 @return: Names of defaults to monitor 23 @rtype: list of string 24 ''' 25 return AEConstants.OUTPUT_COMMAND_NAMES.values()
26
27 -def getNames():
28 ''' 29 Gets the names of all the L{AEOutput} command types. 30 31 @return: List of all known L{AEOutput} command names 32 @rtype: list of string 33 ''' 34 names = AEConstants.OUTPUT_COMMAND_NAMES 35 names = [names[i] for i in (AEConstants.CMD_STOP, 36 AEConstants.CMD_TALK, 37 AEConstants.CMD_STRING)] 38 names.sort() 39 return names
40
41 -class AEOutput(UIElement.UIE):
42 ''' 43 Defines the base class for all output devices. All output devices used by 44 LSR should derive from this class and should implement the methods defined 45 here. All methods defined here raise NotImplementedError to ensure that 46 derived classes create appropriate implementions. 47 48 @cvar STYLE: Style class to use when constructing style objects for this 49 device. A subclass with configurable device settings should 50 override the default value (L{AEOutput.Style}) with a reference to 51 its own default class defining default values for all device properties. 52 @type STYLE: L{AEOutput.Style} class 53 @cvar USE_THREAD: Should this device use a separate thread to queue output? 54 Devices that block while doing output (e.g. serial Braille device) should 55 use a thread to keep the main thread unlocked and responsive. Defaults to 56 None so a subclass must override it with an explicit boolean value. 57 @type USE_THREAD: boolean 58 @cvar COMMAND_CHARS: String of characters that are treated as commands on the 59 device implementing this interface. These characters are replaced with 60 blanks in any string sent to the device. 61 @type COMMAND_CHARS: string 62 @ivar styles: Mapping from arbitrary, immutable keys to style objects 63 @type styles: dictionary 64 ''' 65 USE_THREAD = None 66 COMMAND_CHARS = '' 67 STYLE = Style.Style 68
69 - def __init__(self):
70 ''' 71 Initializes the styles dictionary and default style object. 72 ''' 73 self.styles = {} 74 # instantiate an instance of the STYLE class; it may be filled with 75 # data when preInit is called 76 self.default_style = self.STYLE()
77
78 - def getCapabilities(self):
79 ''' 80 Gets a list of strings representing the capabilities of this device. 81 Typical output capabilities include "audio" and "braille" though others are 82 certainly possible. 83 84 The L{DeviceManager} will only load a device if another device doesn't 85 already provide all of its capabilities. 86 87 @return: Lowercase names of output capabilities 88 @rtype: list of string 89 ''' 90 raise NotImplementedError
91
92 - def loadStyles(self, sett_man):
93 ''' 94 Called after the L{init} method by the L{DeviceManager} to ensure that the 95 device is functioning before time is spent unserializing its style data. 96 97 Calls the init method on the default style object and provides it with a 98 reference to this initialized device. Then tries to load the persisted 99 setting values from disk. If that fails, the L{DeviceManager} will try to 100 call L{createDistinctStyles} instead. 101 102 @note: This method should not be overriden by a subclass. See L{postInit} 103 if you need to run code after the styles are created or restored from 104 disk. 105 @param sett_man: Instance of the settings manager 106 @type sett_man: L{SettingsManager} 107 @raise KeyError: When styles have not previously been persisted for this 108 device 109 @raise OSError: When the profile file cannot be opened or read 110 ''' 111 self.default_style.init(self) 112 # use the settings manager to try to load persisted styles 113 self.styles = sett_man.loadStyles(self, self.default_style, self.STYLE)
114
115 - def saveStyles(self, sett_man):
116 ''' 117 Persists styles to disk. Called after the L{close} method by the 118 L{DeviceManager} to ensure the device is properly shutdown before 119 serializing its data. 120 121 @note: This method should not be overriden by a subclass. 122 @param sett_man: Instance of the settings manager 123 @type sett_man: L{SettingsManager} 124 @raise KeyError: When styles have not previously been persisted for this 125 device 126 @raise OSError: When the profile file cannot be opened or read 127 ''' 128 # use the settings manager to try to persist styles 129 sett_man.saveStyles(self, self.default_style, self.styles)
130
131 - def setStyle(self, key, style):
132 ''' 133 Stores the style object under the given key. The style object should be 134 one previously generated by this device (e.g. using 135 L{createDistinctStyles}) but it is not an enforced requirement. Always 136 makes the style clean before storing it. 137 138 @param key: Any immutable object 139 @type key: immutable 140 @param style: L{AEOutput} subclass of L{AEState} 141 @type style: L{AEState} 142 ''' 143 style.makeClean() 144 self.styles[key] = style
145
146 - def getStyle(self, key):
147 ''' 148 Gets the style object stored under the given key. If the key is unknown, 149 returns an empty flyweight backed by the default style and stores the 150 new style in L{styles}. 151 152 @param key: Any immutable object 153 @type key: immutable 154 @return: L{AEOutput} subclass of L{AEState} 155 @rtype: L{AEState} 156 ''' 157 try: 158 return self.styles[key] 159 except KeyError: 160 # create a new style based on the default 161 st = self.STYLE(self.default_style) 162 # initialize the new style 163 st.init(self) 164 self.styles[key] = st 165 return st
166
167 - def getDefaultStyle(self):
168 ''' 169 Gets the default style of the device. 170 171 @return: Default style of the device 172 @rtype: L{AEOutput.Style} 173 ''' 174 return self.default_style
175
176 - def createDistinctStyles(self, num_groups, num_layers):
177 ''' 178 Creates a default set of distinct styles for this device. The device should 179 instantiate L{AEOutput.Style} objects having properties that reflect the 180 capabilities of this device, leaving any unsupported fields set to the 181 value of None. A total number of num_groups + num_layers style objects 182 should be returned. 183 184 The properties of the style object should be set so as to distinguish 185 content presented using the style. For instance, audio devices may 186 distinguish styles in the following recommended manner: 187 188 - Create a total of num_groups styles with different voices and pitches. 189 - If the device supports multiple channels, 190 - Duplicate the styles num_layers times assigning each set of 191 duplicates to the same channel. 192 - If the device does not support multiple channels, 193 - Duplicate the styles num_layers times. 194 195 For Braille and magnification devices, don't implement this method unless 196 you have some creative way of making the device respond differently to the 197 semantic tags defined in L{AEConstants}. 198 199 The total number of requested styles (num_groups * num_layers) must be 200 returned. If the device cannot honor the request for the number of distinct 201 styles it is asked to generate, it may duplicate styles it has already 202 created using L{AEState.Base.AEState.copy} to fulfill the quota. 203 204 The device is B{not} expected to create distinct styles across invocations 205 of this method. This method should only be called once by L{DeviceManager} 206 to create a default set of styles for the device if the manager cannot load 207 previously persisted settings from disk. If this method is not implemented, 208 calls to L{getStyle} during normal operation of the L{DeviceManager} will 209 end up making copies based on the default style. 210 211 @param num_groups: Number of sematic groups the requestor would like to 212 represent using distinct styles 213 @type num_groups: integer 214 @param num_layers: Number of content origins (e.g. output originating from 215 a background task versus the focus) the requestor would like to represent 216 using distinct styles 217 @type num_layers: integer 218 @return: New styles 219 @rtype: list of L{AEOutput.Style} 220 @raise NotImplementedError: When not overridden in a subclass 221 ''' 222 raise NotImplementedError
223
224 - def init(self):
225 ''' 226 Called after the instance is created to initialize the device. 227 May be called to re-initialize the device after a call to L{close}. 228 229 @raise NotImplementedError: When not overridden in a subclass 230 @raise Error.InitError: When a communication or state problem exists for 231 the specific device 232 ''' 233 raise NotImplementedError
234
235 - def postInit(self):
236 ''' 237 Called after the L{init} method and after either L{loadStyles} or 238 L{createDistinctStyles}. Override this method to perform additional 239 initilization after the setting values are available. 240 241 @raise Error.InitError: When a communication or state problem exists for 242 the specific device 243 ''' 244 pass
245
246 - def close(self):
247 ''' 248 Closes an initialized output device. 249 250 @raise NotImplementedError: When not overridden in a subclass 251 ''' 252 raise NotImplementedError
253
254 - def getProxy(self):
255 ''' 256 Gets the object that the L{DeviceManager} will use to communicate with this 257 device. The returned object may either be a proxy (e.g. a thread) or this 258 device itself. 259 260 @return: An output object that implements this class 261 @rtype: L{AEOutput} 262 @raise NotImplementedError: When not overridden in a subclass 263 ''' 264 raise NotImplementedError
265
266 - def send(self, name, value, style=None):
267 ''' 268 Sends arbitrary data to a device. The device must recognize the name in 269 order to decide what to do with the value data. If given, the style object 270 is used to decide how the data should be presented if it is content to be 271 rendered. 272 273 This is a generic method which receives all content and commands to be 274 rendered and executed on a device. Standard name identifiers should be 275 used whenever possible. For instance, L{AEConstants.Output.CMD_STOP} and 276 L{AEConstants.Output.CMD_TALK}. However, device specific names and values 277 are certainly possible. 278 279 @param name: Descriptor of the data value sent 280 @type name: object 281 @param value: Content value 282 @type value: object 283 @param style: Style with which this value should be output 284 @type style: L{AEOutput.Style} 285 @return: Return value specific to the given command 286 @rtype: object 287 @raise NotImplementedError: When not overridden in a subclass 288 ''' 289 raise NotImplementedError
290
291 - def isActive(self):
292 ''' 293 Indicates whether the device is active (e.g. giving output, has buffered 294 content to output, is otherwise busy) or not. 295 296 @return: True when active, False when not 297 @rtype: boolean 298 @raise NotImplementedError: When not overriden in a subclass 299 ''' 300 raise NotImplementedError
301