Package sparked :: Module application
[hide private]
[frames] | no frames]

Source Code for Module sparked.application

  1  # Copyright (c) 2010 Arjan Scherpenisse 
  2  # See LICENSE for details. 
  3   
  4  """ 
  5  The base application class. 
  6  """ 
  7   
  8  import dbus 
  9  import time 
 10  import tempfile 
 11   
 12  from twisted.application import service 
 13  from twisted.python import log, usage, filepath 
 14  from twisted.internet import reactor 
 15   
 16  from sparked import monitors, __version__ 
17 18 19 -class Application(service.MultiService):
20 """ 21 The sparked base class. 22 23 Spark applications inherit from this class. 24 25 @ivar state: A L{StateMachine} instance which represents the main state of the Spark application. 26 @ivar baseOpts: the basic options that are given on the sparked commandline; instance of L{sparked.launcher.Options}. 27 @ivar appOpts: the additional applocation commandline options; instance of your application's C{yourapplication.Options}. 28 @ivar quitFlag: A L{launcher.QuitFlag} instance controlling the clean shutdown of the program. Set by L{tap.makeService}. 29 30 @ivar title: The human-readable title of the application. 31 32 @ivar monitors: the L{monitors.MonitorContainer} instance with system monitors. 33 @ivar statusWindow: the status window with information about the applictaion. 34 @ivar stage: the stage for the display of graphics 35 """ 36 37 state = None 38 baseOpts = None 39 appOpts = None 40 quitFlag = None 41 42 title = "Untitled" 43 44 monitors = None 45 statusWindow = None 46 stage = None 47 48
49 - def __init__(self, baseOpts, appOpts):
50 service.MultiService.__init__(self) 51 52 self.baseOpts = baseOpts 53 self.appOpts = appOpts 54 55 self.state = StateMachine(self) 56 57 self.createMonitors() 58 59 reactor.callLater(0, self.state.set, "start") 60 reactor.callLater(0, self.started)
61 62
63 - def started(self):
64 """ 65 The application has just been started. Add your own services, 66 create the stage, the status windows, etc, etc, here. 67 """
68 69
70 - def createMonitors(self):
71 m = monitors.MonitorContainer() 72 m.addMonitor(monitors.PowerMonitor()) 73 m.addMonitor(monitors.NetworkMonitor()) 74 m.addMonitor(monitors.NetworkWebMonitor()) 75 76 # Make sure the monitors talk to us in the log. 77 m.verbose = True 78 79 reactor.callLater(0, m.setServiceParent, self) 80 self.monitors = m 81 return m
82 83
84 - def stopService(self):
85 self.quitFlag.set()
86 87 88 89 screensaverInhibited = None 90 """ Flag which is non-zero when the screensaver has been inhibited. """ 91 92
93 - def screensaverInhibit(self, reason):
94 """ 95 Prevent the screen saver from starting. 96 """ 97 bus = dbus.SessionBus() 98 iface = dbus.Interface(bus.get_object('org.gnome.ScreenSaver', "/org/gnome/ScreenSaver"), 'org.gnome.ScreenSaver') 99 self.screensaverInhibited = iface.Inhibit(self.name, reason)
100 101
102 - def screensaverUnInhibit(self):
103 """ 104 Resume the screen saver. 105 """ 106 if not self.screensaverInhibited: 107 return 108 bus = dbus.SessionBus() 109 iface = dbus.Interface(bus.get_object('org.gnome.ScreenSaver', "/org/gnome/ScreenSaver"), 'org.gnome.ScreenSaver') 110 iface.UnInhibit(self.screensaverInhibited) 111 self.screensaverInhibited = None
112
113 114 115 116 -class Options (usage.Options):
117 """ 118 Option parser for sparked applications. 119 120 Spark applications which need their own commandline arguments can 121 inherit from this class: it takes care of the --version and --help 122 arguments, using the __version__ and docstring from the sparked 123 application:: 124 125 # sparked example --version 126 example 0.1.0 (sparked 0.1) 127 128 # sparked example --help 129 sparked [sparked options] example [options] 130 Options: 131 -f, --fast Run fast 132 --version 133 --help Display this help and exit. 134 135 Example runner class for sparked. 136 137 """ 138 139 appName = None
140 - def getSynopsis(self):
141 return "sparked [sparked options] %s [options]" % self.appName
142
143 - def opt_version(self):
144 if self.appName: 145 m = __import__(self.appName) 146 if hasattr(m, "__version__"): 147 v = m.__version__+" " 148 else: 149 v = "" 150 print "%s %s(sparked %s)" % (self.appName, v, __version__) 151 exit(0)
152
153 154 155 -def getTempPath(modulename, id=None):
156 if id: 157 path = id 158 else: 159 path = modulename 160 p = filepath.FilePath(tempfile.gettempdir()).child(path) 161 if not p.exists(): 162 p.createDirectory() 163 return p
164
165 166 -class StateMachine (object):
167 """ 168 A simple state machine. 169 170 This machine is linked to a parent class, on which it calls 171 enter_<state> and exit_<state> methods on state change. Also 172 provided is a mechanism for timed state changes. 173 174 @ivar nextStateAfter: nr of seconds after which the next state 175 change is triggered. If None, the timer is not active. 176 """ 177 178 _state = None 179 _statechanger = None 180 _listeners = None 181 182 nextStateAfter = None 183 184
185 - def __init__(self, parent):
186 self._listeners = [] 187 self.addListener(parent)
188 189
190 - def set(self, newstate):
191 """ 192 Sets a new state. Calls parent's state transition functions, 193 if they exist. 194 """ 195 196 if self._statechanger and self._statechanger.active(): 197 self._statechanger.cancel() 198 self._statechanger = None 199 self.nextStateAfter = None 200 201 if self._state: 202 self._call("exit_%s" % self._state) 203 204 log.msg("%s --> %s" % (self._state, newstate)) 205 self._state = newstate 206 207 self._call("enter_%s" % self._state)
208 209
210 - def setAfter(self, newstate, after):
211 """ 212 Make a state transition after a specified amount of time. 213 """ 214 self._afterStart = time.time() 215 self._afterStop = self._afterStart + after 216 self.nextStateAfter = after 217 self._statechanger = reactor.callLater(after, self.set, newstate)
218 219
220 - def bumpAfter(self, after=None):
221 """ 222 Change the state-changer timer to the specified nr of 223 seconds. If none given, resets the timer to the initial delay, 224 'bumping' it. 225 """ 226 if not after: 227 after = self.nextStateAfter 228 self.nextStateAfter = after 229 self._statechanger.reset(after)
230 231 232 @property
233 - def get(self):
234 """ 235 Get the current state. 236 """ 237 return self._state
238 239
240 - def _call(self, cb, *arg):
241 for l in self._listeners: 242 try: 243 getattr(l, cb)(*arg) 244 except AttributeError: 245 pass
246 247
248 - def addListener(self, l):
249 self._listeners.append(l)
250