core: Hide internal API
[profile/ivi/rygel.git] / src / rygel / rygel-main.vala
1 /*
2  * Copyright (C) 2008 Nokia Corporation.
3  * Copyright (C) 2008 Zeeshan Ali (Khattak) <zeeshanak@gnome.org>.
4  *
5  * Author: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
6  *
7  * This file is part of Rygel.
8  *
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.
13  *
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.
18  *
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.
22  */
23
24 using CStuff;
25 using Gee;
26 using GUPnP;
27
28 public class Rygel.Main : Object {
29     private PluginLoader plugin_loader;
30     private ContextManager context_manager;
31     private ArrayList <RootDeviceFactory> factories;
32     private ArrayList <RootDevice> root_devices;
33
34     private Configuration config;
35
36     private MainLoop main_loop;
37
38     private int exit_code;
39
40     private Main () throws GLib.Error {
41         Environment.set_application_name (_(BuildConfig.PACKAGE_NAME));
42
43         this.config = MetaConfig.get_default ();
44         this.plugin_loader = new PluginLoader ();
45         this.root_devices = new ArrayList <RootDevice> ();
46         this.factories = new ArrayList <RootDeviceFactory> ();
47         this.context_manager = this.create_context_manager ();
48         this.main_loop = new GLib.MainLoop (null, false);
49
50         this.exit_code = 0;
51
52         this.plugin_loader.plugin_available += this.on_plugin_loaded;
53
54         Utils.on_application_exit (this.application_exit_cb);
55     }
56
57     public void exit (int exit_code) {
58         this.exit_code = exit_code;
59         this.main_loop.quit ();
60     }
61
62     private int run () {
63         this.plugin_loader.load_plugins ();
64
65         this.main_loop.run ();
66
67         return this.exit_code;
68     }
69
70     private void application_exit_cb () {
71         this.exit (0);
72     }
73
74     private void on_plugin_loaded (PluginLoader plugin_loader,
75                                    Plugin       plugin) {
76         // We iterate over the copy of the list rather than list itself because
77         // there is high chances of the original list being modified during the
78         // iteration, which is not allowed by libgee.
79         var factories = new ArrayList <RootDeviceFactory> ();
80         foreach (var factory in this.factories) {
81             factories.add (factory);
82         }
83
84         foreach (var factory in factories) {
85             this.create_device (plugin, factory);
86         }
87     }
88
89     private ContextManager create_context_manager () {
90         int port = 0;
91
92         try {
93             port = this.config.get_port ();
94         } catch (GLib.Error err) {}
95
96         var manager = new ContextManager (null, port);
97
98         manager.context_available.connect (this.on_context_available);
99         manager.context_unavailable.connect (this.on_context_unavailable);
100
101         return manager;
102     }
103
104     private void on_context_available (GUPnP.ContextManager manager,
105                                        GUPnP.Context        context) {
106         string host_ip = null;
107
108         debug ("new network context %s (%s) available.",
109                context.interface,
110                context.host_ip);
111
112         try {
113             host_ip = this.config.get_host_ip ();
114         } catch (GLib.Error err) {}
115
116         if (host_ip == null || host_ip == context.host_ip) {
117             var factory = new RootDeviceFactory (context);
118             this.factories.add (factory);
119
120             // See the comment in on_plugin_loaded method
121             var plugins = new ArrayList <Plugin> ();
122             foreach (var plugin in this.plugin_loader.list_plugins ()) {
123                 plugins.add (plugin);
124             }
125
126             foreach (var plugin in plugins) {
127                 this.create_device (plugin, factory);
128             }
129         } else {
130             debug ("Ignoring network context %s (%s).",
131                    context.interface,
132                    context.host_ip);
133         }
134     }
135
136     private void on_context_unavailable (GUPnP.ContextManager manager,
137                                          GUPnP.Context        context) {
138         debug ("Network context %s (%s) now unavailable.",
139                context.interface,
140                context.host_ip);
141
142         var factory_list = new ArrayList <RootDeviceFactory> ();
143         foreach (var factory in this.factories) {
144             if (context == factory.context) {
145                 factory_list.add (factory);
146             }
147         }
148
149         foreach (var factory in factory_list) {
150             this.factories.remove (factory);
151         }
152
153         var device_list = new ArrayList <RootDevice> ();
154         foreach (var device in this.root_devices) {
155             if (context == device.context) {
156                 device_list.add (device);
157             }
158         }
159
160         foreach (var device in device_list) {
161             this.root_devices.remove (device);
162         }
163     }
164
165     private void create_device (Plugin            plugin,
166                                 RootDeviceFactory factory) {
167         try {
168             var device = factory.create (plugin);
169
170             device.available = plugin.available;
171
172             this.root_devices.add (device);
173
174             plugin.notify["available"] += this.on_plugin_notify;
175         } catch (GLib.Error error) {
176             warning ("Failed to create RootDevice for %s. Reason: %s\n",
177                     plugin.name,
178                     error.message);
179         }
180     }
181
182     private void on_plugin_notify (Plugin    plugin,
183                                    ParamSpec spec) {
184         foreach (var device in this.root_devices) {
185             if (device.resource_factory == plugin) {
186                 device.available = plugin.available;
187             }
188         }
189     }
190
191     private static int main (string[] args) {
192         Main main;
193         DBusService service;
194
195         try {
196             // Parse commandline options
197             CmdlineConfig.parse_args (ref args);
198
199             // initialize gstreamer
200             var dummy_args = new string[0];
201             Gst.init (ref dummy_args);
202
203             main = new Main ();
204             service = new DBusService (main);
205         } catch (CmdlineConfigError.VERSION_ONLY err) {
206             return 0;
207         } catch (GLib.Error err) {
208             error ("%s", err.message);
209
210             return -1;
211         }
212
213         int exit_code = main.run ();
214
215         return exit_code;
216     }
217 }
218