1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 import os
42 import glob
43 import random
44 from xdg import BaseDirectory
45
46 import backend
47 import services
48 import utils
49
50 import dbus
51 from stat import S_IRWXU, S_IRWXG, S_IRWXO
52 import gettext
53 import screenlets
54 gettext.textdomain('screenlets')
55 gettext.bindtextdomain('screenlets', screenlets.INSTALL_PREFIX + '/share/locale')
56
58 return gettext.gettext(s)
59
60
61
62 TMP_DIR = '/tmp/screenlets'
63 TMP_FILE = 'screenlets.' + os.environ['USER'] + '.running'
64
65
67 """The ScreenletSession manages instances of a Screenlet and handles
68 saving/restoring options. Each Screenlet contains a reference to its
69 session. Multiple instances of the same Screenlet share the same
70 session-object."""
71
72
73 - def __init__ (self, screenlet_classobj, backend_type='caching', name='default'):
114
116 """Connect to org.screenlets.ScreenletsDaemon."""
117 self.daemon_iface = None
118 bus = dbus.SessionBus()
119 if bus:
120 try:
121 proxy_obj = bus.get_object(screenlets.DAEMON_BUS, screenlets.DAEMON_PATH)
122 if proxy_obj:
123 self.daemon_iface = dbus.Interface(proxy_obj, screenlets.DAEMON_IFACE)
124 except Exception, ex:
125 print "Error in screenlets.session.connect_daemon: %s" % ex
126
128 """Create a new instance with ID 'id' and add it to this session. The
129 function returns either the new Screenlet-instance or None."""
130
131 if id==None or id=='' or self.get_instance_by_id(id) != None:
132 print "ID is unset or already in use - creating new one!"
133 id = self.__get_next_id()
134 dirlst = glob.glob(self.path + '*')
135 tdlen = len(self.path)
136 for filename in dirlst:
137 filename = filename[tdlen:]
138 print 'Loaded config from: %s' % filename
139 if filename.endswith(id + '.ini'):
140
141 sl = self.create_instance(id=filename[:-4], enable_saving=False)
142 if sl:
143
144 print "Set options in %s" % sl.__name__
145
146 self.__restore_options_from_backend(sl, self.path+filename)
147 sl.enable_saving(True)
148
149 sl.finish_loading()
150 return sl
151 sl = self.screenlet(id=id, session=self, **keyword_args)
152 if sl:
153 self.instances.append(sl)
154
155 sl.x = sl.x
156 return sl
157 return None
158
160 """Delete the given instance with ID 'id' and remove its session file.
161 When the last instance within the session is removed, the session dir
162 is completely removed."""
163 sl = self.get_instance_by_id(id)
164 if sl:
165
166 self.instances.remove(sl)
167
168 try:
169 self.backend.delete_instance(id)
170 except Exception:
171 print "Failed to remove INI-file for instance (not critical)."
172
173 if len(self.instances) == 0:
174
175 print "Removing last instance from session"
176
177 print "TODO: remove self.path: %s" % self.path
178 try:
179 os.rmdir(self.path)
180 except:
181 print "Failed to remove session dir '%s' - not empty?" % self.name
182
183
184 sl.quit_on_close = True
185 else:
186 print "Removing instance from session but staying alive"
187 sl.quit_on_close = False
188
189 sl.close()
190 del sl
191 return True
192 return False
193
195 """Return the instance with the given id from within this session."""
196 for inst in self.instances:
197 if inst.id == id:
198 return inst
199 return None
200
202 """quit the given instance with ID 'id'"""
203
204 sl = self.get_instance_by_id(id)
205 if sl:
206 print self.instances
207
208
209
210 if len(self.instances) == 1:
211 sl.quit_on_close = True
212 else:
213 print "Removing instance from session but staying alive"
214 sl.quit_on_close = False
215 self.backend.flush()
216 sl.close()
217 self.instances.remove(sl)
218
219
220 return True
221 return False
222
223
225 """Start a new session (or restore an existing session) for the
226 current Screenlet-class. Creates a new instance when none is found.
227 Returns True if everything worked well, else False."""
228
229
230
231 sln = self.screenlet.__name__[:-9]
232 running = utils.list_running_screenlets()
233 if running and running.count(self.screenlet.__name__) > 0:
234
235 print "Found a running session of %s, adding new instance by service." % sln
236 srvc = services.get_service_by_name(sln)
237 if srvc:
238 print "Adding new instance through: %s" % str(srvc)
239 srvc.add('')
240 return False
241
242 self.__register_screenlet()
243
244 print "Loading instances in: %s" % self.path
245 if self.__load_instances():
246
247 print "Restored instances from session '%s' ..." % self.name
248
249
250 self.__run_session(self.instances[0])
251 else:
252
253 print 'No instance(s) found in session-path, creating new one.'
254 sl = self.screenlet(session=self, id=self.__get_next_id())
255 if sl:
256
257 self.instances.append(sl)
258
259
260 self.backend.save_option(sl.id, 'x', sl.x)
261
262 sl.finish_loading()
263
264
265 self.__run_session(sl)
266 else:
267 print 'Failed creating instance of: %s' % self.classobj.__name__
268
269 self.__unregister_screenlet()
270 return False
271
272 return True
273
275 """Create new entry for this session in the global TMP_FILE."""
276
277
278 if not self.__create_tempdir():
279 return False
280
281
282 running = utils.list_running_screenlets()
283 if running == None : running = []
284 if running.count(self.screenlet.__name__) == 0:
285
286 try:
287 f = open(self.tempfile, 'a')
288 except IOError, e:
289 print "Unable to open %s" % self.tempfile
290 return False
291 else:
292 print "Creating new entry for %s in %s" % (self.screenlet.__name__, self.tempfile)
293 f.write(self.screenlet.__name__ + '\n')
294 f.close()
295 else: print "Screenlet has already been added to %s" % self.tempfile
296
297
298 if self.daemon_iface:
299 self.daemon_iface.register_screenlet(self.screenlet.__name__)
300
302 """Create the global temporary file for saving screenlets. The file is
303 used for indicating which screnlets are currently running."""
304
305
306 if not os.path.isdir(TMP_DIR):
307 try:
308 if os.path.exists(TMP_DIR):
309
310 os.remove(TMP_DIR)
311
312 print "No global tempdir found, creating new one."
313 os.mkdir(TMP_DIR)
314
315
316 os.chmod(TMP_DIR, S_IRWXU | S_IRWXG | S_IRWXO)
317 print 'Temp directory %s created.' % TMP_DIR
318 except OSError, e:
319 print 'Error: Unable to create temp directory %s - screenlets-manager will not work properly.' % TMP_DIR
320 print "Error was: %s"%e
321 return False
322 return True
323
324
326 """Delete this session's entry from the gloabl tempfile (and delete the
327 entire file if no more running screenlets are set."""
328 if not name:
329 name = self.screenlet.__name__
330
331
332 if self.daemon_iface:
333 try:
334 self.daemon_iface.unregister_screenlet(name)
335 except Exception, ex:
336 print "Failed to unregister from daemon: %s" % ex
337
338
339 running = utils.list_running_screenlets()
340 if running and len(running) > 0:
341 pass
342 try:
343 running.remove(name)
344 except:
345
346 print "Entry not found. Will (obviously) not be removed."
347 return True
348
349 if running and len(running) > 0:
350
351 f = open(self.tempfile, 'w')
352 if f:
353 for r in running:
354 f.write(r + '\n')
355 f.close()
356 return True
357 else:
358 print "Error global tempfile not found. Some error before?"
359 return False
360 else:
361 print 'No more screenlets running.'
362 self.__delete_tempfile(name)
363 else:
364 print 'No screenlets running?'
365 return False
366
368 """Delete the tempfile for this session."""
369 if self.tempfile and os.path.isfile(self.tempfile):
370 print "Deleting global tempfile %s" % self.tempfile
371 try:
372 os.remove(self.tempfile)
373 return True
374 except:
375 print "Error: Failed to delete global tempfile"
376 return False
377
379 """Get the next ID for an instance of the assigned Screenlet."""
380 num = 1
381 sln = self.screenlet.__name__[:-9]
382 id = sln + str(num)
383 while self.get_instance_by_id(id) != None:
384 id = sln + str(num)
385 num += 1
386 return id
387
389 """Check for existing instances in the current session, create them
390 and store them into self.instances if any are found. Returns True if
391 at least one instance was found, else False."""
392 dirlst = glob.glob(self.path + '*')
393 tdlen = len(self.path)
394 for filename in dirlst:
395 filename = filename[tdlen:]
396 print 'Loaded config from: %s' % filename
397 if filename.endswith('.ini'):
398
399 sl = self.create_instance(id=filename[:-4], enable_saving=False)
400 if sl:
401
402 print "Set options in %s" % sl.__name__
403
404 self.__restore_options_from_backend(sl, self.path+filename)
405 sl.enable_saving(True)
406
407 sl.finish_loading()
408 else:
409 print "Failed to create instance of '%s'!" % filename[:-4]
410
411 if len(self.instances) > 0:
412 return True
413 return False
414
415
435
437 """Run the session by calling the main handler of the given Screenlet-
438 instance. Handles sigkill (?) and keyboard interrupts."""
439
440 import signal
441 def on_kill(*args):
442
443 pass
444 signal.signal(signal.SIGTERM, on_kill)
445
446 tempfile = self.screenlet.__name__
447
448 try:
449
450 main_instance.main()
451 except KeyboardInterrupt:
452
453 self.backend.flush()
454 print "Screenlet '%s' has been interrupted by keyboard. TODO: make this an event" % self.screenlet.__name__
455 except Exception, ex:
456 print "Exception in ScreenletSession: " + ex
457
458 self.__unregister_screenlet(name=tempfile)
459
461 """Check commandline args for "--session" argument and set session
462 name if found. Runs only once during __init__.
463 TODO: handle more arguments and maybe allow setting options by
464 commandline"""
465 import sys
466 for arg in sys.argv[1:]:
467
468 if arg.startswith('--session=') and len(arg)>10:
469 self.name = arg[10:]
470
471
472
474 """A very simple utility-function to easily create/start a new session."""
475
476 if threading:
477 import gtk
478 gtk.gdk.threads_init()
479 session = ScreenletSession(classobj, backend_type=backend)
480 session.start()
481