2 * Copyright (C) 2008 Nokia Corporation.
3 * Copyright (C) 2008 Zeeshan Ali (Khattak) <zeeshanak@gnome.org>.
5 * Author: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
7 * This file is part of Rygel.
9 * Rygel is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * Rygel is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27 public class Rygel.Main : Object {
28 private static int PLUGIN_TIMEOUT = 5;
30 private PluginLoader plugin_loader;
31 private ContextManager context_manager;
32 private ArrayList <RootDeviceFactory> factories;
33 private ArrayList <RootDevice> root_devices;
35 private Configuration config;
36 private LogHandler log_handler;
38 private MainLoop main_loop;
40 private int exit_code;
41 public bool need_restart;
43 private Main () throws GLib.Error {
44 Environment.set_application_name (_(BuildConfig.PACKAGE_NAME));
46 this.log_handler = LogHandler.get_default ();
47 this.config = MetaConfig.get_default ();
48 this.plugin_loader = new PluginLoader ();
49 this.root_devices = new ArrayList <RootDevice> ();
50 this.factories = new ArrayList <RootDeviceFactory> ();
51 this.context_manager = this.create_context_manager ();
52 this.main_loop = new GLib.MainLoop (null, false);
56 this.plugin_loader.plugin_available.connect (this.on_plugin_loaded);
58 SignalHandler.setup (this);
61 public void exit (int exit_code) {
62 this.exit_code = exit_code;
64 this.main_loop.quit ();
66 SignalHandler.cleanup ();
69 public void restart () {
70 this.need_restart = true;
76 this.plugin_loader.load_plugins ();
78 Timeout.add_seconds (PLUGIN_TIMEOUT, () => {
79 if (this.plugin_loader.list_plugins ().size == 0) {
80 warning (ngettext ("No plugins found in %d second; giving up..",
81 "No plugins found in %d seconds; giving up..",
91 this.main_loop.run ();
93 return this.exit_code;
96 private void on_plugin_loaded (PluginLoader plugin_loader,
98 var iterator = this.factories.iterator ();
99 while (iterator.next ()) {
100 this.create_device.begin (plugin, iterator.get ());
104 private ContextManager create_context_manager () {
108 port = this.config.get_port ();
109 } catch (GLib.Error err) {}
111 var manager = new ContextManager (null, port);
113 manager.context_available.connect (this.on_context_available);
114 manager.context_unavailable.connect (this.on_context_unavailable);
119 private void on_context_available (GUPnP.ContextManager manager,
120 GUPnP.Context context) {
123 debug ("new network context %s (%s) available.",
128 iface = this.config.get_interface ();
129 } catch (GLib.Error err) {}
131 if (iface == null || iface == context.interface) {
133 var factory = new RootDeviceFactory (context);
134 this.factories.add (factory);
136 var iterator = this.plugin_loader.list_plugins ().iterator ();
137 while (iterator.next ()) {
138 this.create_device.begin (iterator.get (), factory);
140 } catch (GLib.Error err) {
141 warning (_("Failed to create root device factory: %s"),
145 debug ("Ignoring network context %s (%s).",
151 private void on_context_unavailable (GUPnP.ContextManager manager,
152 GUPnP.Context context) {
153 debug ("Network context %s (%s) now unavailable.",
157 var factory_iter = this.factories.iterator ();
158 while (factory_iter.next ()) {
159 if (context == factory_iter.get ().context) {
160 factory_iter.remove ();
164 var device_iter = this.root_devices.iterator ();
165 while (device_iter.next ()) {
166 if (context == device_iter.get ().context) {
167 device_iter.remove ();
172 private async void create_device (Plugin plugin,
173 RootDeviceFactory factory) {
174 // The call to factory.create(), although synchronous spins the
175 // the mainloop and therefore might in turn triger some of the signal
176 // handlers here that modify one of the lists that we might be iterating
177 // while this function is called. Modification of an ArrayList while
178 // iterating it is currently unsuppored and leads to a crash and that is
179 // why defer to mainloop here.
180 Idle.add (create_device.callback);
184 var device = factory.create (plugin);
186 device.available = plugin.available;
188 this.root_devices.add (device);
190 plugin.notify["available"].connect (this.on_plugin_notify);
191 } catch (GLib.Error error) {
192 warning (_("Failed to create RootDevice for %s. Reason: %s"),
198 private void on_plugin_notify (Object obj,
200 var plugin = obj as Plugin;
202 foreach (var device in this.root_devices) {
203 if (device.resource_factory == plugin) {
204 device.available = plugin.available;
209 private static int main (string[] args) {
213 var original_args = args;
215 Intl.setlocale (LocaleCategory.ALL, "");
216 Intl.bindtextdomain (BuildConfig.GETTEXT_PACKAGE,
217 BuildConfig.LOCALEDIR);
218 Intl.bind_textdomain_codeset (BuildConfig.GETTEXT_PACKAGE, "UTF-8");
219 Intl.textdomain (BuildConfig.GETTEXT_PACKAGE);
222 // Parse commandline options
223 CmdlineConfig.parse_args (ref args);
225 // initialize gstreamer
226 var dummy_args = new string[0];
227 Gst.init (ref dummy_args);
230 service = new DBusService (main);
231 } catch (IOError err) {
232 warning (_("Failed to start D-Bus service: %s"), err.message);
233 } catch (CmdlineConfigError.VERSION_ONLY err) {
235 } catch (GLib.Error err) {
236 error ("%s", err.message);
239 int exit_code = main.run ();
241 if (main.need_restart) {
242 Misc.Posix.execvp (original_args[0], original_args);