using System; using System.Linq; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Web.Hosting; using Ninject; using NLog; using NzbDrone.Core.Instrumentation; using NzbDrone.Core.Providers; using NzbDrone.Core.Providers.Core; using NzbDrone.Core.Providers.ExternalNotification; using NzbDrone.Core.Providers.Indexer; using NzbDrone.Core.Providers.Jobs; using NzbDrone.Core.Repository; using NzbDrone.Core.Repository.Quality; using SubSonic.DataProviders; using SubSonic.Repository; namespace NzbDrone.Core { public static class CentralDispatch { private static StandardKernel _kernel; private static readonly Object KernelLock = new object(); private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); public static String AppPath { get { if (!String.IsNullOrWhiteSpace(HostingEnvironment.ApplicationPhysicalPath)) { return HostingEnvironment.ApplicationPhysicalPath; } return Directory.GetCurrentDirectory(); } } public static StandardKernel NinjectKernel { get { if (_kernel == null) { BindKernel(); } return _kernel; } } public static void BindKernel() { lock (KernelLock) { Logger.Debug("Binding Ninject's Kernel"); _kernel = new StandardKernel(); //Sqlite var appDataPath = new DirectoryInfo(Path.Combine(AppPath, "App_Data")); if (!appDataPath.Exists) appDataPath.Create(); string connectionString = String.Format("Data Source={0};Version=3;", Path.Combine(appDataPath.FullName, "nzbdrone.db")); var dbProvider = ProviderFactory.GetProvider(connectionString, "System.Data.SQLite"); string logConnectionString = String.Format("Data Source={0};Version=3;", Path.Combine(appDataPath.FullName, "log.db")); var logDbProvider = ProviderFactory.GetProvider(logConnectionString, "System.Data.SQLite"); //SQLExpress //string logConnectionString = String.Format(@"server=.\SQLExpress; database=NzbDroneLogs; Trusted_Connection=True;"); //var logDbProvider = ProviderFactory.GetProvider(logConnectionString, "System.Data.SqlClient"); var logRepository = new SimpleRepository(logDbProvider, SimpleRepositoryOptions.RunMigrations); //dbProvider.ExecuteQuery(new QueryCommand("VACUUM", dbProvider)); dbProvider.Log = new NlogWriter(); _kernel.Bind<QualityProvider>().ToSelf().InSingletonScope(); _kernel.Bind<TvDbProvider>().ToSelf().InTransientScope(); _kernel.Bind<HttpProvider>().ToSelf().InSingletonScope(); _kernel.Bind<SeriesProvider>().ToSelf().InSingletonScope(); _kernel.Bind<SeasonProvider>().ToSelf().InSingletonScope(); _kernel.Bind<EpisodeProvider>().ToSelf().InSingletonScope(); _kernel.Bind<UpcomingEpisodesProvider>().ToSelf().InSingletonScope(); _kernel.Bind<DiskProvider>().ToSelf().InSingletonScope(); _kernel.Bind<SabProvider>().ToSelf().InSingletonScope(); _kernel.Bind<HistoryProvider>().ToSelf().InSingletonScope(); _kernel.Bind<RootDirProvider>().ToSelf().InSingletonScope(); _kernel.Bind<ExternalNotificationProvider>().ToSelf().InSingletonScope(); _kernel.Bind<XbmcProvider>().ToSelf().InSingletonScope(); _kernel.Bind<PostProcessingProvider>().ToSelf().InSingletonScope(); _kernel.Bind<ConfigProvider>().To<ConfigProvider>().InSingletonScope(); _kernel.Bind<SyncProvider>().ToSelf().InSingletonScope(); _kernel.Bind<RenameProvider>().ToSelf().InSingletonScope(); _kernel.Bind<NotificationProvider>().ToSelf().InSingletonScope(); _kernel.Bind<LogProvider>().ToSelf().InSingletonScope(); _kernel.Bind<MediaFileProvider>().ToSelf().InSingletonScope(); _kernel.Bind<JobProvider>().ToSelf().InSingletonScope(); _kernel.Bind<IndexerProvider>().ToSelf().InSingletonScope(); _kernel.Bind<WebTimer>().ToSelf().InSingletonScope(); _kernel.Bind<AutoConfigureProvider>().ToSelf().InSingletonScope(); _kernel.Bind<IRepository>().ToMethod( c => new SimpleRepository(dbProvider, SimpleRepositoryOptions.RunMigrations)).InSingletonScope(); _kernel.Bind<IRepository>().ToConstant(logRepository).WhenInjectedInto<SubsonicTarget>(). InSingletonScope(); _kernel.Bind<IRepository>().ToConstant(logRepository).WhenInjectedInto<LogProvider>().InSingletonScope(); ForceMigration(_kernel.Get<IRepository>()); SetupDefaultQualityProfiles(_kernel.Get<IRepository>()); //Setup the default QualityProfiles on start-up BindIndexers(); BindJobs(); BindExternalNotifications(); } } private static void BindIndexers() { _kernel.Bind<IndexerProviderBase>().To<NzbsOrgProvider>().InSingletonScope(); _kernel.Bind<IndexerProviderBase>().To<NzbMatrixProvider>().InSingletonScope(); _kernel.Bind<IndexerProviderBase>().To<NzbsRUsProvider>().InSingletonScope(); _kernel.Bind<IndexerProviderBase>().To<NewzbinProvider>().InSingletonScope(); var indexers = _kernel.GetAll<IndexerProviderBase>(); _kernel.Get<IndexerProvider>().InitializeIndexers(indexers.ToList()); } private static void BindJobs() { _kernel.Bind<IJob>().To<RssSyncJob>().InTransientScope(); _kernel.Bind<IJob>().To<NewSeriesUpdate>().InTransientScope(); _kernel.Bind<IJob>().To<UpdateInfoJob>().InTransientScope(); _kernel.Bind<IJob>().To<MediaFileScanJob>().InTransientScope(); _kernel.Bind<IJob>().To<DeleteSeriesJob>().InTransientScope(); _kernel.Get<JobProvider>().Initialize(); _kernel.Get<WebTimer>().StartTimer(30); } private static void BindExternalNotifications() { _kernel.Bind<ExternalNotificationProviderBase>().To<XbmcNotificationProvider>().InSingletonScope(); var notifiers = _kernel.GetAll<ExternalNotificationProviderBase>(); _kernel.Get<ExternalNotificationProvider>().InitializeNotifiers(notifiers.ToList()); } private static void ForceMigration(IRepository repository) { repository.All<Series>().Count(); repository.All<Season>().Count(); repository.All<Episode>().Count(); repository.All<EpisodeFile>().Count(); repository.All<QualityProfile>().Count(); repository.All<History>().Count(); } /// <summary> /// Forces IISExpress process to exit with the host application /// </summary> public static void DedicateToHost() { try { Logger.Debug("Attaching to parent process for automatic termination."); var pc = new PerformanceCounter("Process", "Creating Process ID", Process.GetCurrentProcess().ProcessName); var pid = (int)pc.NextValue(); var hostProcess = Process.GetProcessById(pid); hostProcess.EnableRaisingEvents = true; hostProcess.Exited += (delegate { Logger.Info("Host has been terminated. Shutting down web server."); ShutDown(); }); Logger.Debug("Successfully Attached to host. Process ID: {0}", pid); } catch (Exception e) { Logger.Fatal(e); } } private static void ShutDown() { Logger.Info("Shutting down application."); Process.GetCurrentProcess().Kill(); } private static void SetupDefaultQualityProfiles(IRepository repository) { var sd = new QualityProfile { Name = "SD", Allowed = new List<QualityTypes> { QualityTypes.TV, QualityTypes.DVD }, Cutoff = QualityTypes.TV }; var hd = new QualityProfile { Name = "HD", Allowed = new List<QualityTypes> { QualityTypes.HDTV, QualityTypes.WEBDL, QualityTypes.BDRip, QualityTypes.Bluray720 }, Cutoff = QualityTypes.HDTV }; //Add or Update SD Logger.Debug(String.Format("Checking for default QualityProfile: {0}", sd.Name)); var sdDb = repository.Single<QualityProfile>(i => i.Name == sd.Name); if (sdDb == null) { Logger.Debug(String.Format("Adding new default QualityProfile: {0}", sd.Name)); repository.Add(sd); } else { Logger.Debug(String.Format("Updating default QualityProfile: {0}", sd.Name)); sd.QualityProfileId = sdDb.QualityProfileId; repository.Update(sd); } //Add or Update HD Logger.Debug(String.Format("Checking for default QualityProfile: {0}", hd.Name)); var hdDb = repository.Single<QualityProfile>(i => i.Name == hd.Name); if (hdDb == null) { Logger.Debug(String.Format("Adding new default QualityProfile: {0}", hd.Name)); repository.Add(hd); } else { Logger.Debug(String.Format("Updating default QualityProfile: {0}", hd.Name)); hd.QualityProfileId = hdDb.QualityProfileId; repository.Update(hd); } } } }