/// <summary>
        /// Checks and initialises all the components for the application.
        /// </summary>
        static bool Init()
        {
            bool ok;

            // Set the error level
            Logger.Level = Logger.LogLevel.Info;

            // Loads all settings
            Config = LoadConfig();
            if (Config == null) return false;

            // Loads all plugins
            if (!LoadPlugins()) return false;

            // Get port for the http server
            int httpPort;
            ok = Config.TryGetInt("httpPort", out httpPort, 80);
            if (!ok || httpPort <= 0)
                Logger.Log("Could not parse a valid value for httpPort setting. Using default: " + httpPort.ToString(), Logger.LogLevel.Warn);

            // Get port for the websocket server
            int websocketPort;
            ok = Config.TryGetInt("websocketPort", out websocketPort, 81);
            if (!ok || websocketPort <= 0)
                Logger.Log("Could not parse a valid value for websocketPort setting. Using default: " + websocketPort.ToString(), Logger.LogLevel.Warn);

            // Get the media detector polling interval
            int mediaPollingInterval;
            ok = Config.TryGetInt("mediaPollingInterval", out mediaPollingInterval, 3000);
            if (!ok || mediaPollingInterval <= 0)
                Logger.Log("Could not parse a valid value for mediaPollingInterval setting. Using default: " + mediaPollingInterval.ToString(), Logger.LogLevel.Warn);

            // Init the server
            var server = new Server(Program.WebServerPath, httpPort, websocketPort);

            // Init the library
            var library = Library.Instance;
            library.Init(server, mediaPollingInterval);

            // Start server
            if (!server.Start()) {
                Shutdown("Could not start server");
                return false;
            }

            // Show the form
            Logger.Log("Loading complete!", Logger.LogLevel.Info);
            var mainForm = new Forms.Main();
            Application.Run(mainForm);

            // Done
            return true;
        }
        /// <summary>
        /// Initialises the library
        /// </summary>
        /// <param name="mediaWatcherPollingInterval">The interval at which to look for modified media</param>
        public void Init(Server server, int mediaWatcherPollingInterval)
        {
            _server = server;

            // Set retry period from config
            int period;
            Program.Config.TryGetInt("artwork.retryPeriod", out period);
            _artworkRetryPeriod = new TimeSpan(0, 0, period);

            // Instantiate all available MediumWatchers
            // These watch the Medium instances and generate Containers
            _mediumWatchers = Util.InstantiateAllImplementations<IMediumWatcher>();
            Medium.AfterCreate += new Collectable<Medium>.ItemEventHandler(Medium_AfterCreate);
            Medium.AfterDispose += new Collectable<Medium>.ItemEventHandler(Medium_AfterDispose);

            // Watch for container changes
            Container.AfterCreate += new Collectable<Container>.ItemEventHandler(Container_AfterCreate);
            Container.AfterUpdate += new Collectable<Container>.ItemEventHandler(Container_AfterUpdate);
            Container.AfterDispose += new Collectable<Container>.ItemEventHandler(Container_AfterDispose);

            // Build local medium
            string name = Program.Config.GetString("name", "Touchee");
            new Medium(name, MediumType.Local).Save();
            new Medium("Webcasts", MediumType.Web).Save();

            // Instantiate all available MediaWatchers
            // These generate Medium instances
            _mediaWatchers = Util.InstantiateAllImplementations<IMediaWatcher>();

            // Start media detection
            _mediaWatchers.ForEach(w => w.Watch(mediaWatcherPollingInterval));
        }