Module DeviceManager
[hide private]
[frames] | no frames]

Source Code for Module DeviceManager

  1  ''' 
  2  Defines a class responsible for managing all input and output devices and 
  3  monitors. 
  4   
  5  @author: Larry Weiss 
  6  @author: Peter Parente 
  7  @author: Brett Clippingdale 
  8  @author: Scott Haeger 
  9  @organization: IBM Corporation 
 10  @copyright: Copyright (c) 2005, 2007 IBM Corporation 
 11  @license: The BSD License 
 12   
 13  All rights reserved. This program and the accompanying materials are made 
 14  available under the terms of the BSD license which accompanies 
 15  this distribution, and is available at 
 16  U{http://www.opensource.org/licenses/bsd-license.php} 
 17  ''' 
 18  import logging, sys 
 19  import AEConstants, AEOutput, AEInput, AEEvent, AEMonitor, UIRegistrar 
 20  from AEInterfaces import implements 
 21  from UIRegistrar import DEVICE, MONITOR 
 22  from i18n import _ 
 23   
 24  log = logging.getLogger('Device') 
 25   
26 -class DeviceManager(object):
27 ''' 28 Creates and manages the devices and monitors use by LSR. Keeps a list of each 29 and also defines a "default" for devices. Provides a common interface to all 30 output and input devices and mirrors I/O to the monitors. Provides a mapping 31 from output styles to semantic concepts in the user interface to allow 32 customization of how information is presented. 33 34 @ivar event_manager: L{EventManager} to which this L{DeviceManager} can post 35 L{AEEvent}s 36 @type event_manager: L{EventManager} 37 @ivar out_devs: All output devices registered and initialized 38 @type out_devs: list 39 @ivar in_devs: All input devices registered and initialized 40 @type in_devs: list 41 @ivar in_mons: Collection of monitors to notify about input 42 @type in_mons: L{AEMonitor.MonitorCollection} 43 @ivar out_mons: Collection of monitors to notify about output 44 @type out_mons: L{AEMonitor.MonitorCollection} 45 @ivar acc_eng: The AccessEngine reference that created this class 46 @type acc_eng: L{AccessEngine} 47 @ivar marks: Maps index markers on devices to 48 @type marks: dictionary 49 @ivar temp_devs: List of L{AEOutput} and L{AEInput} devices last removed in 50 L{unloadDevices} and held until the next call of L{loadDevices}. The 51 purpose of this list is to ensure strong references to all devices exist, 52 and thus weak references are not destroyed, until the the L{DeviceManager} 53 is repopulated with devices. 54 @type temp_devs: list 55 '''
56 - def __init__(self, acc_eng):
57 ''' 58 Creates the empty lists for devices and monitors. 59 60 @param acc_eng: The AccessEngine reference that created this class 61 @type acc_eng: L{AccessEngine} 62 ''' 63 self.out_devs = [] 64 self.in_devs = [] 65 self.in_mons = AEMonitor.MonitorCollection() 66 self.out_mons = AEMonitor.MonitorCollection() 67 self.acc_eng = acc_eng 68 self.event_manager = None 69 self.settings_manager = None 70 self.marks = {} 71 self.temp_devs = []
72
73 - def init(self, event_man, sett_man, **kwargs):
74 ''' 75 Called by L{AccessEngine} at startup. 76 77 @param event_man: L{EventManager} to which this L{DeviceManager} can 78 post L{AEEvent}s 79 @type event_man: L{EventManager} 80 @param sett_man: L{SettingsManager} which this L{DeviceManager} can use to 81 load and persist device settings 82 @type sett_man: L{EventManager} 83 @param kwargs: References to managers not of interest here 84 @type kwargs: dictionary 85 ''' 86 self.event_manager = event_man 87 self.settings_manager = sett_man 88 89 # load all I/O monitor classes to be created at startup 90 mons = UIRegistrar.loadAssociated(MONITOR, self.acc_eng.getProfile()) 91 self.addMonitors(*mons) 92 93 # load all device classes to be created at startup 94 self.loadDevices()
95
96 - def loadDevices(self):
97 ''' 98 Iterates over all devices in the active profile and loads ones that provide 99 functionality different from those already loaded. 100 ''' 101 devs = UIRegistrar.loadAssociated(DEVICE, self.acc_eng.getProfile()) 102 # register all devices, making the first input and output the defaults 103 for d in devs: 104 # call registerDevice which will automatically set defaults 105 try: 106 self.registerDevice(d) 107 except (AEOutput.AEOutputError, AEInput.AEInputError): 108 log.debug('could not initialize device: %s', d.getName()) 109 except NotImplementedError, e: 110 log.debug('device %s does not provide a new interface: %s' % 111 (d.getName(), str(e))) 112 113 # warn if we didn't initialize at least one output device 114 if not len(self.out_devs): 115 log.warn(_('no output available')) 116 if not len(self.in_devs): 117 log.warn(_('no input available')) 118 self.temp_devs = []
119
120 - def unloadDevices(self):
121 ''' 122 Unloads all devices from L{out_devs} and L{in_devs}, but keeps strong 123 references to all objects in L{temp_devs} until L{loadDevices} is called 124 again. Keeping strong references ensures weak references in L{Perk}s 125 continue to exist until the L{DeviceManager} has new devices available 126 for I/O. 127 128 ''' 129 for d in self.out_devs[:]: 130 self.temp_devs.append(d) 131 self.unregisterDevice(d)
132 #for d in self.in_devs: 133 #self.unregisterDevice(d) 134
135 - def close(self):
136 ''' 137 Shuts down this manager and all its registered L{AEOutput} and L{AEInput} 138 devices and L{AEMonitor}s. Saves all style information for currently 139 loaded devices. 140 ''' 141 for d in self.out_devs[:]: 142 self.unregisterDevice(d) 143 for d in self.in_devs[:]: 144 self.unregisterDevice(d) 145 self.in_mons.clear() 146 self.out_mons.clear()
147
148 - def send(self, dev, name, value, sem, layer):
149 ''' 150 Sends arbitrary data to a device. The device must recognize the name in 151 order to decide what to do with the value data. 152 153 This is a generic method which receives all content and commands to be 154 rendered and executed on a device. Standard name identifiers should be 155 used whenever possible. For instance, L{AEConstants.Output.CMD_STOP} and 156 L{AEConstants.Output.CMD_TALK}. However, device specific names and values 157 are certainly possible. 158 159 @param name: Descriptor of the data value sent 160 @type name: object 161 @param value: Content value 162 @type value: object 163 @param sem: The semantic stream on which to send output; defaults to None 164 for the default semantic. 165 @type sem: integer 166 @param layer: Layer on which the event occurred 167 @type layer: integer 168 @param dev: Device that should receive the command 169 @type dev: L{AEOutput} 170 @return: Return value specific to the given command 171 @rtype: object 172 ''' 173 # notify monitors 174 self.out_mons.show(OutputEvent(name), value=value, dev=dev, sem=sem, 175 layer=layer) 176 # quit if no device specified 177 if dev is None: return 178 if sem is None or layer is None: 179 try: 180 return dev.send(name, value, None) 181 except NotImplementedError: 182 return None 183 else: 184 style = dev.getStyle((sem, layer)) 185 # respect muting 186 if style.Mute: return 187 # send the data 188 try: 189 rv = dev.send(name, value, style) 190 except NotImplementedError: 191 # no return value when not implemented 192 rv = None 193 # mark the style as clean 194 style.makeClean() 195 return rv
196
197 - def sendStop(self, dev, sem, layer):
198 ''' 199 Sends the stop command to the referenced output device. 200 201 @param dev: Device that should receive the command 202 @type dev: L{AEOutput} 203 @param sem: Semantic description of the information to stop None to 204 indicate stopping all output 205 @type sem: integer 206 @param layer: Layer on which the event occurred 207 @type layer: integer 208 ''' 209 # notify monitors 210 self.out_mons.show(OutputEvent(AEConstants.CMD_STOP), dev=dev, sem=sem, 211 layer=layer) 212 if dev is None: return 213 if sem is None and layer is None: 214 # send a global stop 215 dev.send(AEConstants.CMD_STOP, None, None) 216 elif sem is None: 217 # find all styles associated with the given layer 218 all = set([dev.getStyle((sem, layer)) for sem in 219 AEConstants.SEMANTIC_STYLES.keys()]) 220 for style in all: 221 dev.send(AEConstants.CMD_STOP, None, style) 222 else: 223 style = dev.getStyle((sem, layer)) 224 dev.send(AEConstants.CMD_STOP, None, style)
225
226 - def sendTalk(self, dev, sem, layer):
227 ''' 228 Tells the specified output device to send buffered data. 229 230 @param dev: Device that should receive the command 231 @type dev: L{AEOutput} 232 @param sem: Semantic information to start outputting or None to indicate 233 that all buffered information should be output 234 @type sem: integer 235 @param layer: Layer on which the event occurred 236 @type layer: integer 237 ''' 238 # notify monitors 239 self.out_mons.show(OutputEvent(AEConstants.CMD_TALK), dev=dev, sem=sem, 240 layer=layer) 241 if dev is None: return 242 if sem is None: 243 style = None 244 else: 245 style = dev.getStyle((sem, layer)) 246 # send the command 247 dev.send(AEConstants.CMD_TALK, None, style)
248
249 - def sendFilename(self, dev, filename, sem, layer):
250 ''' 251 Sends the filename to the specified output device. 252 253 @param dev: Device that should receive the command 254 @type dev: L{AEOutput} 255 @param filename: The filename to send to the referenced device 256 @type filename: string 257 @param sem: Semantic description of the text to send or None to indicate the 258 information is void of any known semantic 259 @type sem: integer 260 @param layer: Layer on which the event occurred 261 @type layer: integer 262 ''' 263 # notify monitors 264 self.out_mons.show(OutputEvent(AEOutput.NAME_FILENAME), value=filename, 265 dev=dev, sem=sem, layer=layer) 266 if dev is None: return 267 # find the style 268 style = dev.getStyle((sem, layer)) 269 # respect muting 270 if style.Mute: return 271 try: 272 dev.send(AEConstants.CMD_FILENAME, filename, style) 273 except NotImplementedError: 274 pass 275 # make the style clean 276 style.makeClean()
277
278 - def sendString(self, dev, text, sem, layer, por=None):
279 ''' 280 Sends the string to the specified output device. 281 282 @param dev: Device that should receive the command 283 @type dev: L{AEOutput} 284 @param text: The text to send to the referenced device 285 @type text: string 286 @param sem: Semantic description of the text to send or None to indicate 287 the information is void of any known semantic 288 @type sem: integer 289 @param layer: Layer on which the event occurred 290 @type layer: integer 291 @param por: Point of regard to the start of the string if one exists or 292 None if the string did not originate from a L{POR} 293 @type por: L{POR} 294 ''' 295 # notify monitors 296 self.out_mons.show(OutputEvent(AEConstants.CMD_STRING), value=text, 297 dev=dev, sem=sem, layer=layer) 298 if dev is None: return 299 # get the style 300 style = dev.getStyle((sem, layer)) 301 # respect muting 302 if style.Mute: return 303 # parse the string using the current style 304 parsed = dev.parseString(text, style, por, sem) 305 # send all words, pors, and styles 306 for word, por, new_style in parsed: 307 dev.send(AEConstants.CMD_STRING, word, new_style) 308 # mark the style as clean 309 new_style.makeClean() 310 # mark the style clean 311 style.makeClean()
312
313 - def sendIndex(self, dev, value, sem, layer):
314 ''' 315 Sends the referenced index marker to the referenced device. 316 317 @param dev: Device that should receive the command 318 @type dev: L{AEOutput} 319 @param sem: Semantic description of the index text to send or None to 320 indicate the information is void of any known semantic 321 @type sem: integer 322 @param layer: Layer on which the event occurred 323 @type layer: integer 324 ''' 325 # notify registered monitors 326 self.out_mons.show(OutputEvent(AEConstants.CMD_INDEX), dev=dev, sem=sem, 327 layer=layer) 328 if dev is None: return 329 # get the style 330 style = dev.getStyle((sem, layer)) 331 # respect muting 332 if style.Mute: return 333 try: 334 # generate a new marker on the device 335 mark = dev.send(AEConstants.CMD_INDEX, None, style) 336 except NotImplementedError: 337 # do nothing when indexing not implemented 338 return
339 # store the mark and associated data for later retrieval 340 #self.marks[(dev, mark)] = (sem, layer, data) 341
342 - def sendWelcome(self):
343 '''Outputs the LSR welcome message on the default output device.''' 344 try: 345 dev = self.out_devs[0] 346 except IndexError: 347 # no output available 348 return 349 msg = _('welcome to %s version %s, revision %s') % \ 350 (AEConstants.NAME, AEConstants.PROG_VERSION, AEConstants.PROG_DATE) 351 st = dev.getStyle((AEConstants.SEM_ITEM, AEConstants.LAYER_FOCUS)) 352 dev.send(AEConstants.CMD_STRING, msg, st) 353 dev.send(AEConstants.CMD_TALK, None)
354
355 - def sendGoodbye(self):
356 '''Outputs the LSR goodbye message on the default output device.''' 357 try: 358 dev = self.out_devs[0] 359 except IndexError: 360 # no output available 361 return 362 st = dev.getStyle((AEConstants.SEM_ITEM, AEConstants.LAYER_FOCUS)) 363 dev.send(AEConstants.CMD_STRING_SYNC, _('lsr exiting'), st)
364
365 - def _isDuplicateDevice(self, dev, output):
366 ''' 367 Checks if the given device is a duplicate in that it provides no new 368 interfaces beyond those provided by the devices already registered. 369 370 @param dev: A device class 371 @type dev: L{AEInput} or L{AEOutput} class 372 @param output: Is the device an output device (True) or input (False)? 373 @type output: boolean 374 ''' 375 if output: 376 reg_devs = self.out_devs 377 else: 378 reg_devs = self.in_devs 379 # get interfaces device implements 380 dev_int = dev.getCapabilities() 381 # check if some registered device already implements all of these 382 # interfaces 383 for reg_dev in reg_devs: 384 reg_int = reg_dev.getCapabilities() 385 if set(reg_int).issuperset(dev_int): 386 return True 387 return False
388
389 - def _registerInputDevice(self, dev):
390 ''' 391 Registers the given device as an input device if the device implements the 392 L{AEInput} base class and provides some capabilities not already provided 393 by another registered input device. For instance, if a device reports it 394 supports the "system keyboard" capability, no other system keyboard device 395 will be loaded. 396 397 @param dev: Device to attempt to register 398 @type dev: L{AEInput.AEInput} 399 @return: True if the device was registered, False if it is not an 400 L{AEInput} device, and None if it provides no new interfaces 401 @rtype: boolean or None 402 ''' 403 if not implements(dev, AEInput.AEInput): 404 # don't register something that isn't an input device 405 return False 406 if self._isDuplicateDevice(dev, False): 407 # don't register a device that provides all the same interfaces as a 408 # previous device 409 return False 410 if dev not in self.out_devs: 411 # don't reinitialize a device that was added to out_devs 412 dev.init() 413 # add DeviceManager as a gesture listener 414 dev.addInputListener(self._onGesture) 415 # append to the in_devs list after successfully initialized 416 self.in_devs.append(dev) 417 log.debug('added input device %s', str(dev)) 418 return True
419
420 - def _unregisterInputDevice(self, dev):
421 ''' 422 Unregisters the given input device. Removes this manager from 423 the list of gesture listeners stored in the device. 424 425 @param dev: Device to unregister 426 @type dev: L{AEInput.AEInput} 427 ''' 428 try: 429 # remove from list of input devices 430 self.in_devs.remove(dev) 431 log.debug('removed input device %s', dev.getName()) 432 except ValueError: 433 pass 434 try: 435 # do not observe gestures 436 dev.removeInputListener(self._onGesture) 437 except AttributeError: 438 pass
439
440 - def _unregisterOutputDevice(self, dev):
441 ''' 442 Unregisters the given output device. Provides the device with a reference 443 to the L{SettingsManager} so it can save state. Removes this manager from 444 the list of index listeners stored in the device. 445 446 @param dev: Device to unregister 447 @type dev: L{AEOutput.AEOutput} 448 ''' 449 try: 450 # let an output device save its styles 451 dev.saveStyles(self.settings_manager) 452 except AttributeError: 453 pass 454 try: 455 # remove from list of output devices 456 self.out_devs.remove(dev) 457 log.debug('removed output device %s', dev.getName()) 458 except ValueError: 459 pass 460 try: 461 # do not observe indices 462 dev.removeIndexListener(self._onIndex) 463 except AttributeError: 464 pass
465
466 - def _registerOutputDevice(self, dev):
467 ''' 468 Registers the given device as an output device if the device implements the 469 L{AEOutput} base class and provides some subinterface not already provided 470 by another registered output device. For instance, if a device reports 471 having "audio" capability, no other device providing just this capability 472 will be loaded. 473 474 @param dev: Device to attempt to register 475 @type dev: L{AEOutput.AEOutput} 476 @return: True if the device was registered, False if it is not an 477 L{AEOutput} device, and None if it provides no new interfaces 478 @rtype: boolean or None 479 ''' 480 if not implements(dev, AEOutput.AEOutput): 481 # don't register something that isn't an output device 482 return False 483 dev = dev.getProxy() 484 if self._isDuplicateDevice(dev, True): 485 # don't register a device that provides all the same interfaces as a 486 # previous device 487 return None 488 if dev not in self.in_devs: 489 # don't reinitialize a device that was added to in_devs 490 dev.init() 491 # add DeviceManager as an index listener when implemented 492 try: 493 dev.addIndexListener(self._onIndex) 494 except (AttributeError, NotImplementedError): 495 # do nothing when indexing not implemented or supported 496 pass 497 # append to the out_devs list after successfully initialized 498 self.out_devs.append(dev) 499 log.debug('added output device %s', str(dev)) 500 # first output device registered is default 501 502 try: 503 # try to load styles for the device 504 dev.loadStyles(self.settings_manager) 505 except KeyError: 506 # or initialize new output styles 507 self._initOutputStyles(dev) 508 # finally, always call postInit to let the device do more initialization 509 # after the styles are available 510 dev.postInit() 511 return True
512
513 - def _initOutputStyles(self, dev):
514 ''' 515 Initializes styles for an L{AEOutput} device. Calls 516 L{AEOutput.Base.AEOutput.createDistinctStyles} on the device to get an 517 initial batch of styles to use to distinguish some types of information. If 518 that method is not implemented, the exception is ignored. Future requests 519 to use styles per semantic tag will resort to making flyweights for the 520 default style on the device. 521 522 @param dev: Device reference 523 @type dev: L{AEOutput} 524 ''' 525 # create styles based on the abilities of this device 526 num_layers = len(AEConstants.LAYERS_ALL) 527 num_groups = len(AEConstants.STYLE_GROUP_ALL) 528 try: 529 styles = dev.createDistinctStyles(num_groups, num_layers) 530 except NotImplementedError: 531 return 532 # create semantics, layer to styles mapping for device 533 for layer, i in enumerate(AEConstants.LAYERS_ALL): 534 # provide a default style for a semantic of None 535 s = styles[i*num_groups] 536 dev.setStyle((None, layer), s) 537 for sem, grp in AEConstants.SEMANTIC_STYLES.items(): 538 # provide a style for (semantic, layer, device) 539 s = styles[i*num_groups + (grp % num_groups)] 540 dev.setStyle((sem, layer), s)
541
542 - def registerDevice(self, dev):
543 ''' 544 Registers the referenced device based on its one or more interfaces. 545 When the interface is determined, the init() method is called on the device. 546 Returns true when the reference is of a known type that initializes 547 successfully. 548 549 @param dev: The device to register 550 @type dev: L{AEOutput} or L{AEInput} class 551 @raise NotImplementedError: When the device implements none of the required 552 interfaces 553 @raise AEOutputError: When output device initialization fails 554 @raise AEInputError: When input device initialization fails 555 ''' 556 is_out = self._registerOutputDevice(dev) 557 is_in = self._registerInputDevice(dev) 558 559 if is_out == False and is_in == False: 560 # raise an exception if none of the required interfaces was implemented 561 raise NotImplementedError
562
563 - def unregisterDevice(self, dev):
564 ''' 565 Unregisters a device from both the input and output lists based on its 566 capabilities. 567 568 @param dev: The device to unregister 569 @type dev: L{AEOutput} or L{AEInput} class 570 ''' 571 try: 572 dev.close() 573 except Exception: 574 pass 575 self._unregisterOutputDevice(dev) 576 self._unregisterInputDevice(dev)
577
578 - def addMonitors(self, *monitors):
579 ''' 580 Adds one or more L{AEMonitor}s to the list of monitors to be notified about 581 IO events. 582 583 @param monitors: L{AEMonitor}s to notify 584 @type monitors: tuple of L{AEMonitor}s 585 ''' 586 self.in_mons.add(InputEvent, monitors) 587 self.out_mons.add(OutputEvent, monitors)
588
589 - def getMonitors(self):
590 ''' 591 @return: Collections of all loaded input and output L{AEMonitor}s in that 592 order 593 @rtype: 2-tuple L{AEMonitor.MonitorCollection} 594 ''' 595 return self.in_mons, self.out_mons
596
597 - def getFirstOutput(self):
598 ''' 599 Gets the first L{AEOutput} device to successfully load. 600 601 @return: First loaded output device or None if no output is available 602 @rtype: L{AEOutput} 603 ''' 604 try: 605 return self.out_devs[0] 606 except IndexError: 607 return None
608
609 - def getOutputByName(self, name):
610 ''' 611 Gets the L{AEOutput} device registered under the given name. 612 613 @param name: Name of the output device 614 @type name: string 615 @return: Output device or None if not registered 616 @rtype: L{AEOutput} 617 ''' 618 for dev in self.out_devs: 619 if dev.getClassName() == name: 620 return dev 621 return None
622
623 - def getOutputByCaps(self, caps):
624 ''' 625 Gets the L{AEOutput} device registered with the given capabilities. 626 627 @param caps: Desired capabilities of the output device. 628 @type caps: list of string 629 @return: Output device or None if caps could not be satisfied 630 @rtype: L{AEOutput} 631 ''' 632 for dev in self.out_devs: 633 if set(dev.getCapabilities()).issuperset(caps): 634 return dev 635 return None
636
637 - def getInputByName(self, name):
638 ''' 639 Gets the L{AEInput} device registered under the given name. 640 641 @param name: Name of the input device 642 @type name: string 643 @return: Input device or None if not registered 644 @rtype: L{AEInput} 645 ''' 646 for dev in self.in_devs: 647 if dev.getClassName() == name: 648 return dev 649 return None
650
651 - def getInputByCaps(self, caps):
652 ''' 653 Gets the L{AEInput} device registered with the given capabilities. 654 655 @param caps: Desired capabilities of the input device. 656 @type caps: list of string 657 @return: Output device or None if caps could not be satisfied 658 @rtype: L{AEOutput} 659 ''' 660 for dev in self.in_devs: 661 if set(dev.getCapabilities()).issuperset(caps): 662 return dev 663 return None
664
665 - def _onGesture(self, gesture, timestamp, **kwargs):
666 ''' 667 Creates an L{AEEvent} indicating the given gesture was found on a 668 registered input device. When executed, the L{AEEvent} will notify the 669 L{TierManager} about the gesture and allow it to activate the appropriate 670 L{Task} registered to respond to the gesture in the active L{Tier}. 671 672 @param gesture: Gesture seen on an input device 673 @type gesture: L{AEInput.Gesture} 674 @param timestamp: Time at which the event occurred 675 @type timestamp: float 676 @param kwargs: Additional keyword arguments to pass to the L{Task} 677 @type kwargs: dictionary 678 ''' 679 event = AEEvent.InputGesture(gesture, timestamp, **kwargs) 680 self.event_manager.postEvents(event) 681 # notify monitors 682 self.in_mons.show(InputEvent(AEConstants.CMD_GESTURE), value=gesture, 683 dev=gesture.getDevice())
684
685 - def _onIndex(self, dev, index):
686 pass
687 # notify monitors 688 #self.out_mons.show(event=OutputEvent.MARKER) 689
690 - def getDevices(self):
691 ''' 692 @return: References to all loaded devices 693 @rtype: list of L{UIElement} 694 ''' 695 return list(set(self.in_devs).union(self.out_devs))
696
697 - def getStyle(self, dev, sem, layer):
698 ''' 699 Gets the style for semantic/layer of a given device. 700 701 @param dev: The device from which to get the style. 702 @type dev: L{AEOutput} 703 @param sem: The device semantic from which to get the style, or None to 704 get the device's default style. 705 @type sem: integer 706 @param layer: Layer on which the event occurred 707 @type layer: integer 708 @return: the L{AEOutput.Style} for the given semantic of a device 709 @rtype: L{AEOutput.Style} 710 @raise KeyError: When the semantic or layer is invalid 711 ''' 712 if dev is None: return None 713 if sem is None or layer is None: 714 return dev.getDefaultStyle() 715 return dev.getStyle((sem, layer))
716
717 -class DeviceEvent(object):
718 ''' 719 Base type for indicating IO events to monitors such that a monitor may 720 select whether to monitor input, output, both, or neither based on this 721 type and its subtypes. 722 723 The L{cmd} attribute of an instance of this class should be considered 724 public readable. 725 726 @ivar cmd: Command constant for this event 727 @type cmd: object 728 '''
729 - def __init__(self, cmd):
730 ''' 731 Stores the command constant. 732 733 @param cmd: Command constant for this event 734 @type cmd: object 735 ''' 736 self.cmd = cmd
737
738 -class InputEvent(DeviceEvent):
739 '''Event on an input device, wrapped for display by a L{AEMonitor}.'''
740 - def getName(self):
741 ''' 742 @return: Human readable name for the command 743 @rtype: string 744 ''' 745 return AEConstants.INPUT_COMMAND_NAMES[self.cmd]
746
747 -class OutputEvent(DeviceEvent):
748 '''Event on an output device, wrapped for display by a L{AEMonitor}.'''
749 - def getName(self):
750 ''' 751 @return: Human readable name for the command 752 @rtype: string 753 ''' 754 return AEConstants.OUTPUT_COMMAND_NAMES[self.cmd]
755