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

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