/* * registry - zavai resource registry * * Copyright (C) 2009 Enrico Zini * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ using GLib; using Gee; namespace zavai { public interface Resource : Object { /** * Shut down this resource. * * Normally one does nothing here, but it is important to give resources a * chance to do cleanup when the program quits. * * This can be used for tasks like closing the tags on a GPX track, * releasing a FSO resource, restoring mixer settings and so on. */ public abstract void shutdown(); } public abstract class Service : Object, Resource { public string name { get; construct; } bool _started; public bool started { get { return _started; } set { _started = value; } default = false; } public signal void toggled(bool new_state); protected HashMap requests; construct { requests = new HashMap(str_hash, str_equal); } public void shutdown() { stop(); } /// Activate the service protected virtual void start() { if (!started) { stderr.printf("SERVICE %s started\n", name); started = true; toggled(started); } } /// Deactivate the service protected virtual void stop() { if (started) { stderr.printf("SERVICE %s stopped\n", name); started = false; toggled(started); } } /** Request a resource using the given ID. * * If it is the first time the resource is requested, start it and * return true. Else, take note of the request and return false. * * If a resource is requested multiple times with the same ID, it will * need to be released multiple times with that ID. */ public bool request(string id) { bool res = (requests.size == 0); if (id in requests) requests[id] = requests[id] + 1; else requests.set(id, 1); if (res) start(); return res; } /** * Release a resource using the given ID. * * If after the call nothing is requesting the resource, stop it and * return true. Else, take note of the release and return false. * * If a resource is requested multiple times with the same ID, it will * need to be released multiple times with that ID. */ public bool release(string id) { if (id in requests) { if (requests[id] > 1) requests[id] = requests[id] - 1; else requests.remove(id); } else { return false; } if (requests.size > 0) return false; stop(); return true; } } public class Registry : Object, Resource { HashMap memb_resources; HashMap memb_services; HashMap memb_applets; HashMap memb_menus; protected ArrayList registration_order; public DBus.Connection sbus; public string bus_name; public Registry() { memb_resources = new HashMap(str_hash, str_equal); memb_services = new HashMap(str_hash, str_equal); memb_applets = new HashMap(str_hash, str_equal); memb_menus = new HashMap(str_hash, str_equal); registration_order = new ArrayList(); sbus = DBus.Bus.get(DBus.BusType.SYSTEM); bus_name = DBus.bus_get_unique_name(sbus.get_connection()); zavai.log.info("My bus name: " + bus_name); dynamic DBus.Object tmp_dbus = sbus.get_object( "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus"); bus_name = "org.enricozini.zavai"; uint res = tmp_dbus.RequestName(bus_name, (uint)DBus.NameFlag.DO_NOT_QUEUE); switch (res) { case DBus.RequestNameReply.PRIMARY_OWNER: zavai.log.info("Registered to dbus as " + bus_name); break; case DBus.RequestNameReply.IN_QUEUE: zavai.log.info("In queue, but I asked not to"); break; case DBus.RequestNameReply.EXISTS: zavai.log.info(bus_name + " already exists"); break; case DBus.RequestNameReply.ALREADY_OWNER: zavai.log.info("I already own the name " + bus_name + " but I do not remember asking for it"); break; } } public void shutdown() { // Shutdown in reverse registration order for (int i = registration_order.size - 1; i >= 0; --i) registration_order[i].shutdown(); } public void register_resource(string name, Resource obj) { memb_resources[name] = obj; registration_order.add(obj); } public void register_service(Service obj) { memb_services[obj.name] = obj; registration_order.add(obj); } public void register_applet(string name, Applet obj) { memb_applets[name] = obj; registration_order.add(obj); } public void register_menu(string name, Menu obj) { memb_applets[name] = obj; memb_menus[name] = obj; registration_order.add(obj); } public Resource? getr(string name) { if (name in memb_resources) return memb_resources[name]; else { log.error("getr: no resource found: " + name); return null; } } public Service? gets(string name) { if (name in memb_services) return memb_services[name]; else { log.error("gets: no service found: " + name); return null; } } public Applet? geta(string name) { if (name in memb_applets) return memb_applets[name]; else { log.error("geta: no applet found: " + name); return null; } } public Menu? getmenu(string name) { if (name in memb_menus) return memb_menus[name]; else { log.error("getmenu: no menu found: " + name); return null; } } } zavai.Registry registry; }