2 * registry - zavai resource registry
4 * Copyright (C) 2009 Enrico Zini <enrico@enricozini.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 public interface Resource : Object {
28 * Shut down this resource.
30 * Normally one does nothing here, but it is important to give resources a
31 * chance to do cleanup when the program quits.
33 * This can be used for tasks like closing the tags on a GPX track,
34 * releasing a FSO resource, restoring mixer settings and so on.
36 public abstract void shutdown();
39 public abstract class Service : Object, Resource {
40 public string name { get; construct; }
44 get { return _started; }
45 set { _started = value; }
49 public signal void toggled(bool new_state);
51 protected HashMap<string, int> requests;
54 requests = new HashMap<string, int>(str_hash, str_equal);
57 public void shutdown()
62 /// Activate the service
63 protected virtual void start()
67 stderr.printf("SERVICE %s started\n", name);
73 /// Deactivate the service
74 protected virtual void stop()
78 stderr.printf("SERVICE %s stopped\n", name);
85 Request a resource using the given ID.
87 * If it is the first time the resource is requested, start it and
88 * return true. Else, take note of the request and return false.
90 * If a resource is requested multiple times with the same ID, it will
91 * need to be released multiple times with that ID.
93 public bool request(string id)
95 bool res = (requests.size == 0);
97 requests[id] = requests[id] + 1;
105 * Release a resource using the given ID.
107 * If after the call nothing is requesting the resource, stop it and
108 * return true. Else, take note of the release and return false.
110 * If a resource is requested multiple times with the same ID, it will
111 * need to be released multiple times with that ID.
113 public bool release(string id)
117 if (requests[id] > 1)
118 requests[id] = requests[id] - 1;
124 if (requests.size > 0)
131 // class Service(Resource):
132 // "Service that is activated only when someone is listening"
133 // def __init__(self, types = []):
135 // Initialise a service that can emit signals for the given event types
137 // super(Service, self).__init__()
138 // self.callbacks = dict()
140 // self.callbacks[t] = set()
141 // self.started = False
143 // def notify(self, type, *args, **kw):
144 // "Call all callbacks with the given parameters"
145 // for cb in self.callbacks[type]:
148 // def has_callbacks(self):
149 // for i in self.callbacks.values():
153 // def connect(self, type, callback):
154 // "Connect a callback to this resource, activating it if needed"
155 // do_start = not self.has_callbacks()
156 // self.callbacks[type].add(callback)
159 // self.started = True
161 // def disconnect(self, type, callback):
162 // "Disconnect a callback to this resource, activating it if needed"
163 // if not self.has_callbacks(): return
164 // self.callbacks[type].discard(callback)
165 // if not self.has_callbacks():
167 // self.started = False
173 // def get_parent(s):
174 // "Get the parent name for s"
175 // pos = s.rfind(".")
176 // if pos == -1: return None
178 // if res == "menu": return None
181 // def default_label(s):
182 // "Compute a default label given the last element of a path"
183 // pos = s.rfind(".")
184 // if pos == -1: return s.capitalize()
185 // return s[pos+1:].capitalize()
187 public class Registry : Object, Resource
189 HashMap<string, Resource> memb_resources;
190 HashMap<string, Service> memb_services;
191 HashMap<string, Applet> memb_applets;
192 HashMap<string, Menu> memb_menus;
193 protected ArrayList<Resource> registration_order;
194 public DBus.Connection sbus;
198 memb_resources = new HashMap<string, Resource>(str_hash, str_equal);
199 memb_services = new HashMap<string, Service>(str_hash, str_equal);
200 memb_applets = new HashMap<string, Applet>(str_hash, str_equal);
201 memb_menus = new HashMap<string, Menu>(str_hash, str_equal);
202 registration_order = new ArrayList<Resource>();
203 sbus = DBus.Bus.get(DBus.BusType.SYSTEM);
206 public void shutdown()
208 // Shutdown in reverse registration order
209 for (int i = registration_order.size - 1; i >= 0; --i)
210 registration_order[i].shutdown();
213 public void register_resource(string name, Resource obj)
215 memb_resources[name] = obj;
216 registration_order.add(obj);
219 public void register_service(Service obj)
221 memb_services[obj.name] = obj;
222 registration_order.add(obj);
225 public void register_applet(string name, Applet obj)
227 memb_applets[name] = obj;
228 registration_order.add(obj);
231 public void register_menu(string name, Menu obj)
233 memb_applets[name] = obj;
234 memb_menus[name] = obj;
235 registration_order.add(obj);
238 public Resource? getr(string name)
240 if (name in memb_resources)
241 return memb_resources[name];
244 log.error("getr: no resource found: " + name);
249 public Service? gets(string name)
251 if (name in memb_services)
252 return memb_services[name];
255 log.error("gets: no service found: " + name);
260 public Applet? geta(string name)
262 if (name in memb_applets)
263 return memb_applets[name];
266 log.error("geta: no applet found: " + name);
271 public Menu? getmenu(string name)
273 if (name in memb_menus)
274 return memb_menus[name];
277 log.error("getmenu: no menu found: " + name);
283 // class Registry(object):
284 // """Collection of resources.
286 // Various factories can be registered by name on the registry. Then when an
287 // object is requested for the first time, it is created using the factory.
288 // When it is requested again, the existing object is reused.
291 // def __init__(self):
292 // self.factories = dict()
293 // self.objects = dict()
294 // self.labels = dict()
296 // def register(self, obj, name=None):
297 // """Register an object at the given path.
299 // Name the path to this object, like "menu.gps.monitor".
302 // name = obj.props.name
304 // if name in self.objects:
305 // return KeyError("%s is already registered", name)
306 // zavai.info("Registering", name)
307 // self.objects[name] = obj
309 // if name.startswith("menu."):
310 // self.add_to_menu(name)
312 // def register_factory(self, fac, name, label = None):
313 // """Register an object factory at the given path.
315 // Name the path to this object, like "menu.gps.monitor".
317 // if name in self.factories:
318 // return KeyError("Factory %s is already registered", name)
319 // zavai.info("Registering factory", name)
320 // self.factories[name] = fac
321 // if label is not None: self.labels[name] = label
323 // def add_to_menu(self, name):
324 // "Add the applet with the given name to the menu structure"
325 // parent = get_parent(name)
326 // if parent is not None:
327 // zavai.info("Add to menu", name, parent)
328 // menu = self.menu(parent)
330 // obj = self.resource(name)
331 // if isinstance(obj, gtk.ToggleAction):
332 // menu.add_child(zavai.ToggleButton(self, name, action=obj))
333 // elif isinstance(obj, gtk.Action):
334 // menu.add_child(zavai.LinkButton(self, name, action=obj))
336 // menu.add_child(zavai.LinkButton(self, name, self.label(name)))
338 // def label(self, name):
339 // "Return the label for the object with the given name"
340 // res = self.labels.get(name)
341 // if res is not None:
344 // obj = self.resource(name)
345 // return obj.props.label
347 // return default_label(name)
349 // def resource(self, name):
350 // """Get a resource from the registry.
352 // If no resource exists at `name` but there is a factory, instantiate the
353 // object using the factory.
355 // If not even a factory exists at `name`, returns None.
357 // res = self.objects.get(name, None)
359 // fac = self.factories.get(name, None)
360 // if fac is not None:
361 // res = self.objects[name] = fac(self, name)
364 // def menu(self, name):
365 // """Get a menu resource, automatically creating it if it is missing.
367 // Menus are created automatically linked to a parent menu, according to
368 // the hierarchy in `name`.
370 // res = self.resource(name)
372 // # Check if it is a toplevel menu
373 // if name.startswith("menu."):
374 // parent = get_parent(name[5:])
375 // if parent is not None:
376 // parent = "menu." + parent
378 // parent = get_parent(name)
380 // res = zavai.Menu(self, name, parent)
381 // self.register(res, name)
384 // def shutdown(self):
385 // """Shut down all objects in this Registry.
387 // After shutting down, all objects cannot be used anymore"""
388 // for o in self.objects.itervalues():
389 // if isinstance(o, Resource):
391 // self.objects.clear()
394 zavai.Registry registry;