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 import os
36 import glob
37 import random
38 from xdg import BaseDirectory
39
40 import backend
41 import services
42 import utils
43
44 import dbus
45 from stat import S_IRWXU, S_IRWXG, S_IRWXO
46 import gettext
47 import screenlets
48 gettext.textdomain('screenlets')
49 gettext.bindtextdomain('screenlets', screenlets.INSTALL_PREFIX + '/share/locale')
50
52 return gettext.gettext(s)
53
54
55
56 TMP_DIR = '/tmp/screenlets'
57 TMP_FILE = 'screenlets.' + os.environ['USER'] + '.running'
58
59
61 """The ScreenletSession manages instances of a Screenlet and handles
62 saving/restoring options. Each Screenlet contains a reference to its
63 session. Multiple instances of the same Screenlet share the same
64 session-object."""
65
66
67 - def __init__ (self, screenlet_classobj, backend_type='caching', name='default'):
68 object.__init__(self)
69
70 if not screenlet_classobj.__name__.endswith('Screenlet'):
71
72 raise Exception(_("""ScreenletSession.__init__ has to be called with a
73 valid Screenlet-classobject as first argument!"""))
74
75 self.name = name
76 self.screenlet = screenlet_classobj
77 self.instances = []
78 self.tempfile = TMP_DIR + '/' + TMP_FILE
79
80 self.__parse_commandline()
81
82 p = screenlet_classobj.__name__[:-9] + '/' + self.name + '/'
83 self.path = BaseDirectory.load_first_config('Screenlets/' + p)
84 if self.path == None:
85 self.path = BaseDirectory.save_config_path('Screenlets/' + p)
86 if self.path == None: self.path = (os.environ['HOME'] + '.config/Screenlets/' + p)
87 if self.path:
88 if backend_type == 'caching':
89 self.backend = backend.CachingBackend(path=self.path)
90 elif backend_type == 'gconf':
91 self.backend = backend.GconfBackend()
92 else:
93
94 self.backend = backend.ScreenletsBackend()
95 print _("Unable to init backend - settings will not be saved!")
96
97
98
99 proc = os.popen("""ps axo "%p,%a" | grep "screenlets-daemon.py" | grep -v grep|cut -d',' -f1""").read()
100
101 procs = proc.split('\n')
102 if len(procs) <= 1:
103 os.system('python -u ' + screenlets.INSTALL_PREFIX + '/share/screenlets-manager/screenlets-daemon.py &')
104 print 'No Daemon, Launching Daemon'
105 self.connect_daemon()
106
108 """Connect to org.screenlets.ScreenletsDaemon."""
109 self.daemon_iface = None
110 bus = dbus.SessionBus()
111 if bus:
112 try:
113 proxy_obj = bus.get_object(screenlets.DAEMON_BUS, screenlets.DAEMON_PATH)
114 if proxy_obj:
115 self.daemon_iface = dbus.Interface(proxy_obj, screenlets.DAEMON_IFACE)
116 except Exception, ex:
117 print _("Error in screenlets.session.connect_daemon: %s") % ex
118
120 """Create a new instance with ID 'id' and add it to this session. The
121 function returns either the new Screenlet-instance or None."""
122
123 if id==None or id=='' or self.get_instance_by_id(id) != None:
124 print _("ID is unset or already in use - creating new one!")
125 id = self.__get_next_id()
126 dirlst = glob.glob(self.path + '*')
127 tdlen = len(self.path)
128 for filename in dirlst:
129 filename = filename[tdlen:]
130 print _('File: %s') % filename
131 if filename.endswith(id + '.ini'):
132
133 sl = self.create_instance(id=filename[:-4], enable_saving=False)
134 if sl:
135
136 print _("Set options in %s") % sl.__name__
137
138 self.__restore_options_from_backend(sl, self.path+filename)
139 sl.enable_saving(True)
140
141 sl.finish_loading()
142 return sl
143 sl = self.screenlet(id=id, session=self, **keyword_args)
144 if sl:
145 self.instances.append(sl)
146
147 sl.x = sl.x
148 return sl
149 return None
150
152 """Delete the given instance with ID 'id' and remove its session file.
153 When the last instance within the session is removed, the session dir
154 is completely removed."""
155 sl = self.get_instance_by_id(id)
156 if sl:
157
158 self.instances.remove(sl)
159
160 try:
161 self.backend.delete_instance(id)
162 except Exception:
163 print _("Failed to remove INI-file for instance (not critical).")
164
165 if len(self.instances) == 0:
166
167 print _("Removing last instance from session")
168
169 print _("TODO: remove self.path: %s") % self.path
170 try:
171 os.rmdir(self.path)
172 except:
173 print _("Failed to remove session dir '%s' - not empty?") % self.name
174
175
176 sl.quit_on_close = True
177 else:
178 print _("Removing instance from session but staying alive")
179 sl.quit_on_close = False
180
181 sl.close()
182 del sl
183 return True
184 return False
185
187 """Return the instance with the given id from within this session."""
188 for inst in self.instances:
189 if inst.id == id:
190 return inst
191 return None
192
194 """quit the given instance with ID 'id'"""
195
196 sl = self.get_instance_by_id(id)
197 if sl:
198 print self.instances
199
200
201
202 if len(self.instances) == 1:
203 sl.quit_on_close = True
204 else:
205 print _("Removing instance from session but staying alive")
206 sl.quit_on_close = False
207 self.backend.flush()
208 sl.close()
209 self.instances.remove(sl)
210
211
212 return True
213 return False
214
215
217 """Start a new session (or restore an existing session) for the
218 current Screenlet-class. Creates a new instance when none is found.
219 Returns True if everything worked well, else False."""
220
221
222
223 sln = self.screenlet.__name__[:-9]
224 running = utils.list_running_screenlets()
225 if running and running.count(self.screenlet.__name__) > 0:
226
227 print _("Found a running session of %s, adding new instance by service.") % sln
228 srvc = services.get_service_by_name(sln)
229 if srvc:
230 print _("Adding new instance through: %s") % str(srvc)
231 srvc.add('')
232 return False
233
234 self.__register_screenlet()
235
236 print _("Loading instances in: %s") % self.path
237 if self.__load_instances():
238
239 print _("Restored instances from session '%s' ...") % self.name
240
241
242 self.__run_session(self.instances[0])
243 else:
244
245 print _('No instance(s) found in session-path, creating new one.')
246 sl = self.screenlet(session=self, id=self.__get_next_id())
247 if sl:
248
249 self.instances.append(sl)
250
251
252 self.backend.save_option(sl.id, 'x', sl.x)
253
254 sl.finish_loading()
255
256
257 self.__run_session(sl)
258 else:
259 print _('Failed creating instance of: %s') % self.classobj.__name__
260
261 self.__unregister_screenlet()
262 return False
263
264 return True
265
267 """Create new entry for this session in the global TMP_FILE."""
268
269
270 if not self.__create_tempdir():
271 return False
272
273
274 running = utils.list_running_screenlets()
275 if running == None : running = []
276 if running.count(self.screenlet.__name__) == 0:
277
278 try:
279 f = open(self.tempfile, 'a')
280 except IOError, e:
281 print _("Unable to open %s") % self.tempfile
282 return False
283 else:
284 print _("Creating new entry for %s in %s") % (self.screenlet.__name__, self.tempfile)
285 f.write(self.screenlet.__name__ + '\n')
286 f.close()
287 else: print _("Screenlet has already been added to %s") % self.tempfile
288
289
290 if self.daemon_iface:
291 self.daemon_iface.register_screenlet(self.screenlet.__name__)
292
294 """Create the global temporary file for saving screenlets. The file is
295 used for indicating which screnlets are currently running."""
296
297
298 if not os.path.isdir(TMP_DIR):
299 try:
300 if os.path.exists(TMP_DIR):
301
302 os.remove(TMP_DIR)
303
304 print _("No global tempdir found, creating new one.")
305 os.mkdir(TMP_DIR)
306
307
308 os.chmod(TMP_DIR, S_IRWXU | S_IRWXG | S_IRWXO)
309 print _('Temp directory %s created.') % TMP_DIR
310 except OSError, e:
311 print _('Error: Unable to create temp directory %s - screenlets-manager will not work properly.') % TMP_DIR
312 print "Error was: %s"%e
313 return False
314 return True
315
316
318 """Delete this session's entry from the gloabl tempfile (and delete the
319 entire file if no more running screenlets are set."""
320 if not name:
321 name = self.screenlet.__name__
322
323
324 if self.daemon_iface:
325 try:
326 self.daemon_iface.unregister_screenlet(name)
327 except Exception, ex:
328 print _("Failed to unregister from daemon: %s") % ex
329
330
331 running = utils.list_running_screenlets()
332 if running and len(running) > 0:
333 pass
334 try:
335 running.remove(name)
336 except:
337
338 print _("Entry not found. Will (obviously) not be removed.")
339 return True
340
341 if running and len(running) > 0:
342
343 f = open(self.tempfile, 'w')
344 if f:
345 for r in running:
346 f.write(r + '\n')
347 f.close()
348 return True
349 else:
350 print _("Error global tempfile not found. Some error before?")
351 return False
352 else:
353 print _('No more screenlets running.')
354 self.__delete_tempfile(name)
355 else:
356 print _('No screenlets running?')
357 return False
358
360 """Delete the tempfile for this session."""
361 if self.tempfile and os.path.isfile(self.tempfile):
362 print _("Deleting global tempfile %s") % self.tempfile
363 try:
364 os.remove(self.tempfile)
365 return True
366 except:
367 print _("Error: Failed to delete global tempfile")
368 return False
369
371 """Get the next ID for an instance of the assigned Screenlet."""
372 num = 1
373 sln = self.screenlet.__name__[:-9]
374 id = sln + str(num)
375 while self.get_instance_by_id(id) != None:
376 id = sln + str(num)
377 num += 1
378 return id
379
381 """Check for existing instances in the current session, create them
382 and store them into self.instances if any are found. Returns True if
383 at least one instance was found, else False."""
384 dirlst = glob.glob(self.path + '*')
385 tdlen = len(self.path)
386 for filename in dirlst:
387 filename = filename[tdlen:]
388 print _('File: %s') % filename
389 if filename.endswith('.ini'):
390
391 sl = self.create_instance(id=filename[:-4], enable_saving=False)
392 if sl:
393
394 print _("Set options in %s") % sl.__name__
395
396 self.__restore_options_from_backend(sl, self.path+filename)
397 sl.enable_saving(True)
398
399 sl.finish_loading()
400 else:
401 print _("Failed to create instance of '%s'!") % filename[:-4]
402
403 if len(self.instances) > 0:
404 return True
405 return False
406
407
427
429 """Run the session by calling the main handler of the given Screenlet-
430 instance. Handles sigkill (?) and keyboard interrupts."""
431
432 import signal
433 def on_kill(*args):
434
435 pass
436 signal.signal(signal.SIGTERM, on_kill)
437
438 tempfile = self.screenlet.__name__
439
440 try:
441
442 main_instance.main()
443 except KeyboardInterrupt:
444
445 self.backend.flush()
446 print _("Screenlet '%s' has been interrupted by keyboard. TODO: make this an event") % self.screenlet.__name__
447 except Exception, ex:
448 print _("Exception in ScreenletSession: ") + ex
449
450 self.__unregister_screenlet(name=tempfile)
451
453 """Check commandline args for "--session" argument and set session
454 name if found. Runs only once during __init__.
455 TODO: handle more arguments and maybe allow setting options by
456 commandline"""
457 import sys
458 for arg in sys.argv[1:]:
459
460 if arg.startswith('--session=') and len(arg)>10:
461 self.name = arg[10:]
462
463
464
466 """A very simple utility-function to easily create/start a new session."""
467
468 if threading:
469 import gtk
470 gtk.gdk.threads_init()
471 session = ScreenletSession(classobj, backend_type=backend)
472 session.start()
473