public TorshifySongPlayerTest()
        {
            _session = Substitute.For<ISession>();
            _link = Substitute.For<ILink<ITrackAndOffset>>();

            var linkFactory = Substitute.For<ILinkFactory>();
            linkFactory.GetLink(Arg.Any<string>()).Returns(_link);

            _songPlayer = new TorshifySongPlayer(_session, linkFactory);
        }
        public void Run(string[] args)
        {
            InitializeLogging();

            var log = LogManager.GetLogger("Main");

            AppDomain.CurrentDomain.UnhandledException += (sender, eventArgs) =>
            {
                var exception = (Exception) eventArgs.ExceptionObject;
                log.Fatal(exception);
            };

            string username = string.Empty;
            string password = string.Empty;
            string cacheFolder = Constants.CacheFolder;
            string settingsFolder = Constants.SettingsFolder;
            string userAgent = Constants.UserAgent;
            bool hidden = false;
            int port = 8081;
            int loginTimeout = 50000;

            new OptionSet
            {
                { "u|username="******"p|password="******"cf|cachefolder=", v => cacheFolder = v },
                { "sf|settingsfolder=", v => settingsFolder = v },
                { "ua|useragent=", v => userAgent = v },
                { "hidden", v => hidden = v != null },
                { "port=", v =>
                {
                    if(v != null)
                        int.TryParse(v, out port);
                }},
                { "logintimeout=", v =>
                {
                    if(v != null)
                        int.TryParse(v, out loginTimeout);
                }}
            }.Parse(args);

            if (hidden)
            {
                var hwnd = GetConsoleWindow();
                ShowWindow(hwnd, SW_HIDE);
            }

            var session =
               SessionFactory
                   .CreateSession(
                       Constants.ApplicationKey,
                       cacheFolder,
                       settingsFolder,
                       userAgent)
                   .SetPreferredBitrate(Bitrate.Bitrate320k);

            var wait = new ManualResetEvent(false);
            session.LoginComplete += (sender, eventArgs) =>
            {
                log.Info(eventArgs.Status == Error.OK ? "Logged in" : eventArgs.Message);
                wait.Set();
            };

            if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
            {
                log.Info("Please specify both username and password. -u=userName -p=password");
                Console.ReadLine();
                Environment.Exit(-1);
            }

            session.Login(username, password);

            if (!wait.WaitOne(loginTimeout))
            {
                log.Error("Timed out [After " + loginTimeout + " ms]");
                Environment.Exit(-1);
            }

            var player = new TorshifySongPlayer(session, new SessionLinkFactory(session));

            GlobalHost.DependencyResolver.Register(typeof(ISongPlayer), () => player);

            var signalRUrl = "http://localhost:" + port + "/";
            var nancyFxUrl = "http://localhost:" + (port + 1) + "/torshify/";
            try
            {
                log.Info("SignalR URL: " + signalRUrl);
                log.Info("NancyFX URL: " + nancyFxUrl);

                var server = new SignalR.Hosting.Self.Server(signalRUrl);
                server.MapHubs();
                server.Start();

                var hub = GlobalHost.ConnectionManager.GetHubContext<TorshifyHub>();

                player.IsPlayingChanged += (sender, eventArgs) => hub.Clients.IsPlayingChanged(eventArgs);
                player.IsMutedChanged += (sender, eventArgs) => hub.Clients.IsMutedChanged(eventArgs);
                player.Buffering += (sender, eventArgs) => hub.Clients.Buffering(eventArgs);
                player.Progress += (sender, eventArgs) => hub.Clients.Progress(eventArgs);
                player.CurrentSongChanged += (sender, eventArgs) => hub.Clients.CurrentSongChanged(eventArgs);
                player.CurrentSongCompleted += (sender, eventArgs) => hub.Clients.CurrentSongCompleted(eventArgs);
                player.VolumeChanged += (sender, eventArgs) => hub.Clients.VolumeChanged(eventArgs);

                var bootstrapper = new NancyBootstrapper(session);

                var nancyHost = new NancyHost(new Uri(nancyFxUrl), bootstrapper);
                nancyHost.Start();
            }
            catch (Exception e)
            {
                log.Fatal(e);
            }

            Console.ReadLine();
            log.Info("Exiting");
        }