/// <summary> /// Synchronously synchronizes all local shares and media item aspect types with the MediaPortal server. /// </summary> protected async Task CompleteServerConnectionAsync() { UPnPServerControllerServiceProxy sc = ServerControllerServiceProxy; ISystemResolver systemResolver = ServiceRegistration.Get <ISystemResolver>(); if (sc != null) { try { // Check if we're attached to the server. If the server lost its state, it might have forgotten us. if (!sc.GetAttachedClients().Select(clientMetadata => clientMetadata.SystemId).Contains(systemResolver.LocalSystemId)) { sc.AttachClient(systemResolver.LocalSystemId); } } catch (Exception e) { ServiceRegistration.Get <ILogger>().Warn("ServerConnectionManager: Error checking attachment state at home server '{0}'", e, HomeServerSystemId); return; // This is a real error case, we don't need to try any other service calls } // Register state variables change events sc.AttachedClientsChanged += OnAttachedClientsChanged; sc.ConnectedClientsChanged += OnConnectedClientsChanged; } IImporterWorker importerWorker = ServiceRegistration.Get <IImporterWorker>(); ICollection <Share> newShares = new List <Share>(); UPnPContentDirectoryServiceProxy cd = ContentDirectoryServiceProxy; if (cd != null) { // Update shares registration try { ISettingsManager settingsManager = ServiceRegistration.Get <ISettingsManager>(); ServerConnectionSettings settings = settingsManager.Load <ServerConnectionSettings>(); ServiceRegistration.Get <ILogger>().Info("ServerConnectionManager: Synchronizing shares with home server"); IDictionary <Guid, Share> serverShares = new Dictionary <Guid, Share>(); foreach (Share share in await cd.GetSharesAsync(systemResolver.LocalSystemId, SharesFilter.All)) { serverShares.Add(share.ShareId, share); } IDictionary <Guid, Share> localShares = ServiceRegistration.Get <ILocalSharesManagement>().Shares; // First remove shares - if the client lost its configuration and re-registers an already present share, the server's method will throw an exception foreach (Guid serverShareId in serverShares.Keys) { if (!localShares.ContainsKey(serverShareId)) { await cd.RemoveShareAsync(serverShareId); } } foreach (Share localShare in localShares.Values) { RelocationMode relocationMode; if (!serverShares.ContainsKey(localShare.ShareId)) { await cd.RegisterShareAsync(localShare); newShares.Add(localShare); } else if (settings.CachedSharesUpdates.TryGetValue(localShare.ShareId, out relocationMode)) { await cd.UpdateShareAsync(localShare.ShareId, localShare.BaseResourcePath, localShare.Name, localShare.UseShareWatcher, localShare.MediaCategories, relocationMode); switch (relocationMode) { case RelocationMode.ClearAndReImport: importerWorker.ScheduleImport(localShare.BaseResourcePath, localShare.MediaCategories, true); break; case RelocationMode.Relocate: importerWorker.ScheduleRefresh(localShare.BaseResourcePath, localShare.MediaCategories, true); break; } } } settings.CachedSharesUpdates.Clear(); settingsManager.Save(settings); } catch (Exception e) { ServiceRegistration.Get <ILogger>().Warn("ServerConnectionManager: Could not synchronize local shares with server", e); } // Update media item aspect type registration try { IMediaItemAspectTypeRegistration miatr = ServiceRegistration.Get <IMediaItemAspectTypeRegistration>(); ServiceRegistration.Get <ILogger>().Info("ServerConnectionManager: Checking for unregistered media item aspect types at home server"); ICollection <Guid> serverMIATypes = await cd.GetAllManagedMediaItemAspectTypesAsync(); foreach (KeyValuePair <Guid, MediaItemAspectMetadata> localMiaType in miatr.LocallyKnownMediaItemAspectTypes) { if (!serverMIATypes.Contains(localMiaType.Key)) { ServiceRegistration.Get <ILogger>().Info("ServerConnectionManager: Adding unregistered media item aspect type '{0}' (ID '{1}') at home server", localMiaType.Value.Name, localMiaType.Key); await cd.AddMediaItemAspectStorageAsync(localMiaType.Value); } } } catch (Exception e) { ServiceRegistration.Get <ILogger>().Warn("ServerConnectionManager: Could not synchronize local media item aspect types with server", e); } // Register state variables change events cd.PlaylistsChanged += OnContentDirectoryPlaylistsChanged; cd.MIATypeRegistrationsChanged += OnContentDirectoryMIATypeRegistrationsChanged; cd.RegisteredSharesChangeCounterChanged += OnRegisteredSharesChangeCounterChanged; // Activate importer worker ServiceRegistration.Get <ILogger>().Debug("ServerConnectionManager: Activating importer worker"); ImporterCallback ic = new ImporterCallback(cd); importerWorker.Activate(ic, ic); foreach (Share share in newShares) { importerWorker.ScheduleImport(share.BaseResourcePath, share.MediaCategories, true); } } }
void OnMessageReceived(AsynchronousMessageQueue queue, SystemMessage message) { if (message.ChannelName == SharesMessaging.CHANNEL) { IContentDirectory cd = ContentDirectory; SharesMessaging.MessageType messageType = (SharesMessaging.MessageType)message.MessageType; IImporterWorker importerWorker = ServiceRegistration.Get <IImporterWorker>(); Share share; switch (messageType) { case SharesMessaging.MessageType.ShareAdded: share = (Share)message.MessageData[SharesMessaging.SHARE]; if (cd != null) { cd.RegisterShare(share); } importerWorker.ScheduleImport(share.BaseResourcePath, share.MediaCategories, true); break; case SharesMessaging.MessageType.ShareRemoved: share = (Share)message.MessageData[SharesMessaging.SHARE]; importerWorker.CancelJobsForPath(share.BaseResourcePath); if (cd != null) { cd.RemoveShare(share.ShareId); } break; case SharesMessaging.MessageType.ShareChanged: RelocationMode relocationMode = (RelocationMode)message.MessageData[SharesMessaging.RELOCATION_MODE]; share = (Share)message.MessageData[SharesMessaging.SHARE]; importerWorker.CancelJobsForPath(share.BaseResourcePath); if (cd == null) { ISettingsManager settingsManager = ServiceRegistration.Get <ISettingsManager>(); ServerConnectionSettings settings = settingsManager.Load <ServerConnectionSettings>(); RelocationMode oldMode; if (settings.CachedSharesUpdates.TryGetValue(share.ShareId, out oldMode) && oldMode == RelocationMode.ClearAndReImport) { // ClearAndReimport is stronger than Relocate, use ClearAndReImport relocationMode = oldMode; } settings.CachedSharesUpdates[share.ShareId] = relocationMode; settingsManager.Save(settings); } else { cd.UpdateShare(share.ShareId, share.BaseResourcePath, share.Name, share.MediaCategories, relocationMode); switch (relocationMode) { case RelocationMode.ClearAndReImport: importerWorker.ScheduleImport(share.BaseResourcePath, share.MediaCategories, true); break; case RelocationMode.Relocate: importerWorker.ScheduleRefresh(share.BaseResourcePath, share.MediaCategories, true); break; } } break; case SharesMessaging.MessageType.ReImportShare: share = (Share)message.MessageData[SharesMessaging.SHARE]; importerWorker.ScheduleRefresh(share.BaseResourcePath, share.MediaCategories, true); break; } } else if (message.ChannelName == ImporterWorkerMessaging.CHANNEL) { IContentDirectory cd = ContentDirectory; ImporterWorkerMessaging.MessageType messageType = (ImporterWorkerMessaging.MessageType)message.MessageType; switch (messageType) { case ImporterWorkerMessaging.MessageType.ImportStarted: case ImporterWorkerMessaging.MessageType.ImportCompleted: if (cd == null) { break; } ResourcePath path = (ResourcePath)message.MessageData[ImporterWorkerMessaging.RESOURCE_PATH]; ILocalSharesManagement lsm = ServiceRegistration.Get <ILocalSharesManagement>(); ICollection <Share> shares = lsm.Shares.Values; Share share = shares.BestContainingPath(path); if (share == null) { break; } if (messageType == ImporterWorkerMessaging.MessageType.ImportStarted) { cd.ClientStartedShareImport(share.ShareId); } else { cd.ClientCompletedShareImport(share.ShareId); } break; } } }
void OnMessageReceived(AsynchronousMessageQueue queue, SystemMessage message) { if (message.ChannelName == SharesMessaging.CHANNEL) { IContentDirectory cd = ContentDirectory; SharesMessaging.MessageType messageType = (SharesMessaging.MessageType)message.MessageType; IImporterWorker importerWorker = ServiceRegistration.Get <IImporterWorker>(); Share share; switch (messageType) { case SharesMessaging.MessageType.ShareAdded: share = (Share)message.MessageData[SharesMessaging.SHARE]; if (cd != null) { cd.RegisterShareAsync(share); } importerWorker.ScheduleImport(share.BaseResourcePath, share.MediaCategories, true); break; case SharesMessaging.MessageType.ShareRemoved: share = (Share)message.MessageData[SharesMessaging.SHARE]; importerWorker.CancelJobsForPath(share.BaseResourcePath); if (cd != null) { cd.RemoveShareAsync(share.ShareId); } break; case SharesMessaging.MessageType.ShareChanged: RelocationMode relocationMode = (RelocationMode)message.MessageData[SharesMessaging.RELOCATION_MODE]; share = (Share)message.MessageData[SharesMessaging.SHARE]; importerWorker.CancelJobsForPath(share.BaseResourcePath); if (cd == null) { ISettingsManager settingsManager = ServiceRegistration.Get <ISettingsManager>(); ServerConnectionSettings settings = settingsManager.Load <ServerConnectionSettings>(); RelocationMode oldMode; if (settings.CachedSharesUpdates.TryGetValue(share.ShareId, out oldMode) && oldMode == RelocationMode.ClearAndReImport) { // ClearAndReimport is stronger than Relocate, use ClearAndReImport relocationMode = oldMode; } settings.CachedSharesUpdates[share.ShareId] = relocationMode; settingsManager.Save(settings); } else { cd.UpdateShareAsync(share.ShareId, share.BaseResourcePath, share.Name, share.UseShareWatcher, share.MediaCategories, relocationMode); switch (relocationMode) { case RelocationMode.ClearAndReImport: importerWorker.ScheduleImport(share.BaseResourcePath, share.MediaCategories, true); break; case RelocationMode.Relocate: importerWorker.ScheduleRefresh(share.BaseResourcePath, share.MediaCategories, true); break; } } break; case SharesMessaging.MessageType.ReImportShare: share = (Share)message.MessageData[SharesMessaging.SHARE]; importerWorker.ScheduleRefresh(share.BaseResourcePath, share.MediaCategories, true); break; } } else if (message.ChannelName == ImporterWorkerMessaging.CHANNEL) { IContentDirectory cd = ContentDirectory; ImporterWorkerMessaging.MessageType messageType = (ImporterWorkerMessaging.MessageType)message.MessageType; switch (messageType) { case ImporterWorkerMessaging.MessageType.ImportStarted: case ImporterWorkerMessaging.MessageType.ImportCompleted: if (cd == null) { break; } ResourcePath path = (ResourcePath)message.MessageData[ImporterWorkerMessaging.RESOURCE_PATH]; ILocalSharesManagement lsm = ServiceRegistration.Get <ILocalSharesManagement>(); ICollection <Share> shares = lsm.Shares.Values; Share share = shares.BestContainingPath(path); if (share == null) { break; } if (messageType == ImporterWorkerMessaging.MessageType.ImportStarted) { cd.ClientStartedShareImportAsync(share.ShareId); } else { cd.ClientCompletedShareImportAsync(share.ShareId); } break; } } else if (message.ChannelName == ServerStateMessaging.CHANNEL) { //Check if Tv Server state has changed and update if necessary ServerStateMessaging.MessageType messageType = (ServerStateMessaging.MessageType)message.MessageType; if (messageType == ServerStateMessaging.MessageType.StatesChanged) { var states = message.MessageData[ServerStateMessaging.STATES] as IDictionary <Guid, object>; if (states != null && states.ContainsKey(ShareImportServerState.STATE_ID)) { ShareImportServerState importState = states[ShareImportServerState.STATE_ID] as ShareImportServerState; if (importState != null) { List <ShareImportState> shareStates = new List <ShareImportState>(importState.Shares); lock (_syncObj) { UpdateCurrentlyImportingShares(shareStates.Where(s => s.IsImporting).Select(s => s.ShareId).ToList()); UpdateCurrentlyImportingSharesProgresses(shareStates.Where(s => s.IsImporting).ToDictionary(s => s.ShareId, s => s.Progress)); } } } else if (states != null && states.ContainsKey(DatabaseUpgradeServerState.STATE_ID)) { DatabaseUpgradeServerState upgradeState = states[DatabaseUpgradeServerState.STATE_ID] as DatabaseUpgradeServerState; if (upgradeState != null && !upgradeState.IsUpgrading && upgradeState.Progress == 100) { ServerConnectionMessaging.SendServerConnectionStateChangedMessage(ServerConnectionMessaging.MessageType.HomeServerDisconnected); ServerConnectionMessaging.SendServerConnectionStateChangedMessage(ServerConnectionMessaging.MessageType.HomeServerConnected); } } } } }
static UPnPError OnScheduleImports(DvAction action, IList <object> inParams, out IList <object> outParams, CallContext context) { outParams = null; ICollection <Guid> shareIds = MarshallingHelper.ParseCsvGuidCollection((string)inParams[0]); string importJobTypeStr = (string)inParams[1]; ImportJobType importJobType; UPnPError error = ParseImportJobType("ImportJobType", importJobTypeStr, out importJobType); if (error != null) { return(error); } IMediaLibrary mediaLibrary = ServiceRegistration.Get <IMediaLibrary>(); IDictionary <Guid, Share> allShares = mediaLibrary.GetShares(null); IDictionary <string, ICollection <Share> > importRequests = new Dictionary <string, ICollection <Share> >(); foreach (Guid shareId in shareIds) { Share importShare; if (!allShares.TryGetValue(shareId, out importShare)) { // Share not found continue; } ICollection <Share> systemShares; if (!importRequests.TryGetValue(importShare.SystemId, out systemShares)) { importRequests[importShare.SystemId] = new List <Share> { importShare } } ; else { systemShares.Add(importShare); } } // Local imports at the server ISystemResolver systemResolver = ServiceRegistration.Get <ISystemResolver>(); ICollection <Share> shares; if (importRequests.TryGetValue(systemResolver.LocalSystemId, out shares)) { IImporterWorker importerWorker = ServiceRegistration.Get <IImporterWorker>(); foreach (Share share in shares) { if (importJobType == ImportJobType.Import) { importerWorker.ScheduleImport(share.BaseResourcePath, share.MediaCategories, true); } else { importerWorker.ScheduleRefresh(share.BaseResourcePath, share.MediaCategories, true); } } } ServiceRegistration.Get <IThreadPool>().Add(() => ScheduleClientImports(importRequests, importJobType)); return(null); }