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