Exemplo n.º 1
0
 public ImporterWorkerAction(ActionType actionType, IMediaBrowsing mediaBrowsingCallback, IImportResultHandler importResultHandler)
 {
     if (actionType == ActionType.Startup)
     {
         throw new ArgumentException("ActionType.Startup must not relate to an IMediaBrowsing and an IImportResultHandler");
     }
     if (actionType == ActionType.ScheduleImport)
     {
         throw new ArgumentException("ActionType.ScheduleImport must not relate to an IMediaBrowsing and an IImportResultHandler and requires an ImportJobInformation");
     }
     if (actionType == ActionType.CancelImport)
     {
         throw new ArgumentException("ActionType.CancelImport must not relate to an IMediaBrowsing and an IImportResultHandler");
     }
     if (actionType == ActionType.Suspend)
     {
         throw new ArgumentException("ActionType.Suspend must not relate to an IMediaBrowsing and an IImportResultHandler");
     }
     if (actionType == ActionType.Shutdown)
     {
         throw new ArgumentException("ActionType.Shutdown must not relate to an IMediaBrowsing and an IImportResultHandler");
     }
     _actionType            = actionType;
     _importJobInformation  = null;
     _mediaBrowsingCallback = mediaBrowsingCallback;
     _importResultHandler   = importResultHandler;
     _tcs = new TaskCompletionSource <object>();
 }
Exemplo n.º 2
0
        /// <summary>
        /// Imports the resource with the given <paramref name="mediaItemAccessor"/>.
        /// </summary>
        /// <remarks>
        /// This method will be called for file resources as well as for directory resources because some metadata extractors
        /// extract their metadata from directories.
        /// </remarks>
        /// <param name="mediaItemAccessor">File or directory resource to be imported.</param>
        /// <param name="parentDirectoryId">Media item id of the parent directory, if present, else <see cref="Guid.Empty"/>.</param>
        /// <param name="metadataExtractors">Collection of metadata extractors to apply to the given resoure.</param>
        /// <param name="resultHandler">Callback to notify the import results.</param>
        /// <param name="mediaAccessor">Convenience reference to the media accessor.</param>
        /// <returns><c>true</c>, if metadata could be extracted from the given <paramref name="mediaItemAccessor"/>, else
        /// <c>false</c>.</returns>
        protected bool ImportResource(ImportJob importJob, IResourceAccessor mediaItemAccessor, Guid parentDirectoryId, ICollection <IMetadataExtractor> metadataExtractors,
                                      IImportResultHandler resultHandler, IMediaAccessor mediaAccessor)
        {
            const bool   forceQuickMode = false; // Allow extractions with probably longer runtime.
            ResourcePath path           = mediaItemAccessor.CanonicalLocalResourcePath;

            ImporterWorkerMessaging.SendImportMessage(ImporterWorkerMessaging.MessageType.ImportStatus, path);
            IDictionary <Guid, IList <MediaItemAspect> > aspects = mediaAccessor.ExtractMetadataAsync(mediaItemAccessor, metadataExtractors, forceQuickMode).Result;

            if (aspects == null)
            {
                // No metadata could be extracted
                return(false);
            }
            using (CancellationTokenSource cancelToken = new CancellationTokenSource())
            {
                try
                {
                    resultHandler.UpdateMediaItemAsync(parentDirectoryId, path, MediaItemAspect.GetAspects(aspects), importJob.JobType == ImportJobType.Refresh, importJob.BasePath);
                    resultHandler.DeleteUnderPathAsync(path);
                }
                catch
                {
                    cancelToken.Cancel();
                    throw;
                }
            }
            return(true);
        }
Exemplo n.º 3
0
        private void DoActivate(IMediaBrowsing mediaBrowsingCallback, IImportResultHandler importResultHandler)
        {
            if (_status != Status.Suspended)
            {
                ServiceRegistration.Get <ILogger>().Error("ImporterWorker: Activation was requested although status was not 'Suspended' but '{0}'", _status);
                return;
            }

            _mediaBrowsing       = mediaBrowsingCallback;
            _importResultHandler = importResultHandler;

            foreach (var kvp in _importJobControllers)
            {
                // To avoid peaks on system startup when multiple ImportJobs were saved to disk and are now
                // reactivated, we start one ImportJob every 500ms.
                // Currently we also need this because the MediaAccessor is not threadsafe on startup
                // see here: http://forum.team-mediaportal.com/threads/mediaaccessor-not-thread-safe.125132/
                // ToDo: Make MediaAccessor threadsafe on startup
                Task.Delay(500).Wait();
                kvp.Value.Activate(_mediaBrowsing, _importResultHandler);
            }

            _status = Status.Activated;
            ServiceRegistration.Get <ILogger>().Info("ImporterWorker: Activated ({0} ImportJobs pending)", _importJobControllers.Count);
        }
Exemplo n.º 4
0
        protected Guid GetOrAddDirectory(ImportJob importJob, IFileSystemResourceAccessor directoryAccessor, Guid parentDirectoryId,
                                         IMediaBrowsing mediaBrowsing, IImportResultHandler resultHandler)
        {
            ResourcePath directoryPath = directoryAccessor.CanonicalLocalResourcePath;
            MediaItem    directoryItem = mediaBrowsing.LoadLocalItemAsync(directoryPath, EMPTY_MIA_ID_ENUMERATION, DIRECTORY_MIA_ID_ENUMERATION).Result;

            if (directoryItem != null)
            {
                SingleMediaItemAspect da;
                if (!MediaItemAspect.TryGetAspect(directoryItem.Aspects, DirectoryAspect.Metadata, out da))
                { // This is the case if the path was formerly imported as a non-directory media item; we cannot reuse it
                    resultHandler.DeleteMediaItemAsync(directoryPath);
                    directoryItem = null;
                }
            }
            if (directoryItem == null)
            { // Add directory item to ML
                MediaItemAspect mia = new SingleMediaItemAspect(MediaAspect.Metadata);
                mia.SetAttribute(MediaAspect.ATTR_TITLE, directoryAccessor.ResourceName);
                mia.SetAttribute(MediaAspect.ATTR_SORT_TITLE, directoryAccessor.ResourceName);
                mia.SetAttribute(MediaAspect.ATTR_ISVIRTUAL, false);
                mia.SetAttribute(MediaAspect.ATTR_RECORDINGTIME, DateTime.MinValue);
                mia.SetAttribute(MediaAspect.ATTR_RATING, 0);
                mia.SetAttribute(MediaAspect.ATTR_COMMENT, null);
                mia.SetAttribute(MediaAspect.ATTR_LASTPLAYED, DateTime.MinValue);
                MediaItemAspect         da      = new SingleMediaItemAspect(DirectoryAspect.Metadata);
                IList <MediaItemAspect> aspects = new List <MediaItemAspect>(new[]
                {
                    mia,
                    da,
                });
                return(resultHandler.UpdateMediaItemAsync(parentDirectoryId, directoryPath, aspects, importJob.JobType == ImportJobType.Refresh, importJob.BasePath).Result);
            }
            return(directoryItem.MediaItemId);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Imports or refreshes a single file without a parent directory with the specified <paramref name="fileAccessor"/>.
        /// </summary>
        /// <param name="importJob">The import job being processed.</param>
        /// <param name="fileAccessor">Resource accessor for the file to import.</param>
        /// <param name="metadataExtractors">Metadata extractors to apply on the resource.</param>
        /// <param name="mediaBrowsing">Callback interface to the media library for the refresh import type.</param>
        /// <param name="resultHandler">Callback to notify the import result.</param>
        /// <param name="mediaAccessor">Convenience reference to the media accessor.</param>
        protected void ImportSingleFile(ImportJob importJob, IResourceAccessor fileAccessor,
                                        ICollection <IMetadataExtractor> metadataExtractors, IMediaBrowsing mediaBrowsing,
                                        IImportResultHandler resultHandler, IMediaAccessor mediaAccessor)
        {
            ResourcePath currentFilePath = fileAccessor.CanonicalLocalResourcePath;

            try
            {
                if (importJob.JobType == ImportJobType.Refresh)
                {
                    MediaItem mediaItem = mediaBrowsing.LoadLocalItem(currentFilePath,
                                                                      IMPORTER_MIA_ID_ENUMERATION, EMPTY_MIA_ID_ENUMERATION);
                    MediaItemAspect importerAspect;
                    if (mediaItem != null && mediaItem.Aspects.TryGetValue(ImporterAspect.ASPECT_ID, out importerAspect) &&
                        (DateTime)importerAspect[ImporterAspect.ATTR_LAST_IMPORT_DATE] > fileAccessor.LastChanged)
                    {
                        return;
                    }
                }
                ImportResource(fileAccessor, Guid.Empty, metadataExtractors, resultHandler, mediaAccessor);
            }
            catch (Exception e)
            {
                CheckSuspended(e); // Throw ImportAbortException if suspended - will skip warning and tagging job as erroneous
                ServiceRegistration.Get <ILogger>().Warn("ImporterWorker: Problem while importing resource '{0}'", e, currentFilePath);
                importJob.State = ImportJobState.Erroneous;
            }
        }
Exemplo n.º 6
0
 public void Activate(IMediaBrowsing mediaBrowsingCallback, IImportResultHandler importResultHandler)
 {
     lock (_syncObj)
     {
         _mediaBrowsingCallback = mediaBrowsingCallback;
         _importResultHandler   = importResultHandler;
     }
     StartImporterLoop_NoLock();
 }
Exemplo n.º 7
0
 public void Activate(IMediaBrowsing mediaBrowsingCallback, IImportResultHandler importResultHandler)
 {
     _mediaBrowsingCallback = mediaBrowsingCallback;
     _importResultHandler   = importResultHandler;
     _suspensionLink        = InputBlock.LinkTo(InnerBlock, new DataflowLinkOptions {
         PropagateCompletion = true
     });
     _stopWatch.Start();
     Activated.Set();
 }
Exemplo n.º 8
0
 public ImporterWorkerAction(ActionType actionType)
 {
   if (actionType == ActionType.Activate)
     throw new ArgumentException("ActionType.Activate requires an IMediaBrowsing and an IImportResultHandler");
   if (actionType == ActionType.ScheduleImport)
     throw new ArgumentException("ActionType.ScheduleImport requires an ImportJobInformation");
   _actionType = actionType;
   _importJobInformation = null;
   _mediaBrowsingCallback = null;
   _importResultHandler = null;
   _tcs = new TaskCompletionSource<object>();
 }
Exemplo n.º 9
0
 /// <summary>
 /// Activates the ImportJob
 /// </summary>
 /// <param name="mediaBrowsingCallback"></param>
 /// <param name="importResultHandler"></param>
 public void Activate(IMediaBrowsing mediaBrowsingCallback, IImportResultHandler importResultHandler)
 {
     // To avoid peaks on system startup we start one Block every 100ms.
     // Currently we also need this because the MediaAccessor is not threadsafe on startup
     // see here: http://forum.team-mediaportal.com/threads/mediaaccessor-not-thread-safe.125132/
     // ToDo: Make MediaAccessor threadsafe on startup
     foreach (var block in _dataflowBlocks)
     {
         block.Activate(mediaBrowsingCallback, importResultHandler);
         Task.Delay(100).Wait();
     }
     ServiceRegistration.Get <ILogger>().Info("ImporterWorker.{0}: Activated", this);
     ImporterWorkerMessaging.SendImportMessage(ImporterWorkerMessaging.MessageType.ImportStarted, _importJobInformation.BasePath);
 }
Exemplo n.º 10
0
        public void Activate(IMediaBrowsing mediaBrowsingCallback, IImportResultHandler importResultHandler)
        {
            if (mediaBrowsingCallback == null)
            {
                throw new ArgumentNullException("mediaBrowsingCallback");
            }
            if (importResultHandler == null)
            {
                throw new ArgumentNullException("importResultHandler");
            }

            ServiceRegistration.Get <ILogger>().Info("ImporterWorker: Activation requested...");
            RequestAction(new ImporterWorkerAction(ImporterWorkerAction.ActionType.Activate, mediaBrowsingCallback, importResultHandler));
        }
Exemplo n.º 11
0
 public ImporterWorkerAction(ActionType actionType)
 {
     if (actionType == ActionType.Activate)
     {
         throw new ArgumentException("ActionType.Activate requires an IMediaBrowsing and an IImportResultHandler");
     }
     if (actionType == ActionType.ScheduleImport)
     {
         throw new ArgumentException("ActionType.ScheduleImport requires an ImportJobInformation");
     }
     _actionType            = actionType;
     _importJobInformation  = null;
     _mediaBrowsingCallback = null;
     _importResultHandler   = null;
     _tcs = new TaskCompletionSource <object>();
 }
Exemplo n.º 12
0
 public ImporterWorkerAction(ActionType actionType, ImportJobInformation importJobInformation)
 {
   if (actionType == ActionType.Startup)
     throw new ArgumentException("ActionType.Startup must not relate to an ImportJobInformation");
   if (actionType == ActionType.Activate)
     throw new ArgumentException("ActionType.Activate must not relate to an ImportJobInformation and requires an IMediaBrowsing and an IImportResultHandler");
   if (actionType == ActionType.Suspend)
     throw new ArgumentException("ActionType.Suspend must not relate to an ImportJobInformation");
   if (actionType == ActionType.Shutdown)
     throw new ArgumentException("ActionType.Shutdown must not relate to an ImportJobInformation");
   _actionType = actionType;
   _importJobInformation = importJobInformation;
   _mediaBrowsingCallback = null;
   _importResultHandler = null;
   _tcs = new TaskCompletionSource<object>();
 }
Exemplo n.º 13
0
        /// <summary>
        /// Imports or refreshes a single file without a parent directory with the specified <paramref name="resourceAccessor"/>.
        /// </summary>
        /// <param name="importJob">The import job being processed.</param>
        /// <param name="resourceAccessor">Resource accessor for the file to import.</param>
        /// <param name="metadataExtractors">Metadata extractors to apply on the resource.</param>
        /// <param name="mediaBrowsing">Callback interface to the media library for the refresh import type.</param>
        /// <param name="resultHandler">Callback to notify the import result.</param>
        /// <param name="mediaAccessor">Convenience reference to the media accessor.</param>
        protected void ImportSingleFile(ImportJob importJob, IResourceAccessor resourceAccessor,
                                        ICollection <IMetadataExtractor> metadataExtractors, IMediaBrowsing mediaBrowsing,
                                        IImportResultHandler resultHandler, IMediaAccessor mediaAccessor)
        {
            ResourcePath currentFilePath = resourceAccessor.CanonicalLocalResourcePath;

            try
            {
                ImportResource(importJob, resourceAccessor, Guid.Empty, metadataExtractors, resultHandler, mediaAccessor);
            }
            catch (Exception e)
            {
                CheckSuspended(e); // Throw ImportAbortException if suspended - will skip warning and tagging job as erroneous
                ServiceRegistration.Get <ILogger>().Warn("ImporterWorker: Problem while importing resource '{0}'", e, currentFilePath);
                importJob.State = ImportJobState.Erroneous;
            }
        }
Exemplo n.º 14
0
 public ImporterWorkerAction(ActionType actionType, IMediaBrowsing mediaBrowsingCallback, IImportResultHandler importResultHandler)
 {
   if (actionType == ActionType.Startup)
     throw new ArgumentException("ActionType.Startup must not relate to an IMediaBrowsing and an IImportResultHandler");
   if (actionType == ActionType.ScheduleImport)
     throw new ArgumentException("ActionType.ScheduleImport must not relate to an IMediaBrowsing and an IImportResultHandler and requires an ImportJobInformation");
   if (actionType == ActionType.CancelImport)
     throw new ArgumentException("ActionType.CancelImport must not relate to an IMediaBrowsing and an IImportResultHandler");
   if (actionType == ActionType.Suspend)
     throw new ArgumentException("ActionType.Suspend must not relate to an IMediaBrowsing and an IImportResultHandler");
   if (actionType == ActionType.Shutdown)
     throw new ArgumentException("ActionType.Shutdown must not relate to an IMediaBrowsing and an IImportResultHandler");
   _actionType = actionType;
   _importJobInformation = null;
   _mediaBrowsingCallback = mediaBrowsingCallback;
   _importResultHandler = importResultHandler;
   _tcs = new TaskCompletionSource<object>();
 }
Exemplo n.º 15
0
    public void Activate(IMediaBrowsing mediaBrowsingCallback, IImportResultHandler importResultHandler)
    {
      if (mediaBrowsingCallback == null)
        throw new ArgumentNullException("mediaBrowsingCallback");
      if (importResultHandler == null)
        throw new ArgumentNullException("importResultHandler");

      ServiceRegistration.Get<ILogger>().Info("ImporterWorker: Activation requested...");
      RequestAction(new ImporterWorkerAction(ImporterWorkerAction.ActionType.Activate, mediaBrowsingCallback, importResultHandler));
    }
Exemplo n.º 16
0
        /// <summary>
        /// Imports or refreshes the directory with the specified <paramref name="directoryAccessor"/>. Sub directories will not
        /// be processed in this method.
        /// </summary>
        /// <param name="importJob">The import job being processed.</param>
        /// <param name="parentDirectoryId">Media item id of the parent directory, if present, else <see cref="Guid.Empty"/>.</param>
        /// <param name="directoryAccessor">Resource accessor for the directory to import.</param>
        /// <param name="metadataExtractors">Metadata extractors to apply on the resources.</param>
        /// <param name="mediaBrowsing">Callback interface to the media library for the refresh import type.</param>
        /// <param name="resultHandler">Callback to notify the import result.</param>
        /// <param name="mediaAccessor">Convenience reference to the media accessor.</param>
        /// <returns>Id of the directory's media item or <c>null</c>, if the given <paramref name="directoryAccessor"/>
        /// was imported as a media item or if an error occured. If <c>null</c> is returned, the directory import should be
        /// considered to be finished.</returns>
        protected Guid?ImportDirectory(ImportJob importJob, Guid parentDirectoryId, IFileSystemResourceAccessor directoryAccessor,
                                       ICollection <IMetadataExtractor> metadataExtractors, IMediaBrowsing mediaBrowsing,
                                       IImportResultHandler resultHandler, IMediaAccessor mediaAccessor)
        {
            ResourcePath currentDirectoryPath = directoryAccessor.CanonicalLocalResourcePath;

            try
            {
                ImporterWorkerMessaging.SendImportMessage(ImporterWorkerMessaging.MessageType.ImportStatus, currentDirectoryPath);
                if (ImportResource(importJob, directoryAccessor, parentDirectoryId, metadataExtractors, resultHandler, mediaAccessor))
                {
                    // The directory could be imported as a media item.
                    // If the directory itself was identified as a normal media item, don't import its children.
                    // Necessary for DVD directories, for example.
                    return(null);
                }
                Guid directoryId = GetOrAddDirectory(importJob, directoryAccessor, parentDirectoryId, mediaBrowsing, resultHandler);
                IDictionary <string, MediaItem> path2Item = new Dictionary <string, MediaItem>();
                if (importJob.JobType == ImportJobType.Refresh)
                {
                    foreach (MediaItem mediaItem in mediaBrowsing.BrowseAsync(directoryId,
                                                                              IMPORTER_PROVIDER_MIA_ID_ENUMERATION, EMPTY_MIA_ID_ENUMERATION, null, false).Result)
                    {
                        IList <MultipleMediaItemAspect> providerResourceAspects;
                        if (MediaItemAspect.TryGetAspects(mediaItem.Aspects, ProviderResourceAspect.Metadata, out providerResourceAspects))
                        {
                            path2Item[providerResourceAspects[0].GetAttributeValue <string>(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH)] = mediaItem;
                        }
                    }
                }
                CheckImportStillRunning(importJob.State);
                ICollection <IFileSystemResourceAccessor> files = FileSystemResourceNavigator.GetFiles(directoryAccessor, false);
                if (files != null)
                {
                    foreach (IFileSystemResourceAccessor fileAccessor in files)
                    {
                        using (fileAccessor)
                        { // Add & update files
                            ResourcePath currentFilePath    = fileAccessor.CanonicalLocalResourcePath;
                            string       serializedFilePath = currentFilePath.Serialize();
                            try
                            {
                                SingleMediaItemAspect importerAspect;
                                MediaItem             mediaItem;
                                if (importJob.JobType == ImportJobType.Refresh &&
                                    path2Item.TryGetValue(serializedFilePath, out mediaItem) &&
                                    MediaItemAspect.TryGetAspect(mediaItem.Aspects, ImporterAspect.Metadata, out importerAspect) &&
                                    importerAspect.GetAttributeValue <DateTime>(ImporterAspect.ATTR_LAST_IMPORT_DATE) > fileAccessor.LastChanged)
                                { // We can skip this file; it was imported after the last change time of the item
                                    path2Item.Remove(serializedFilePath);
                                    continue;
                                }
                                if (ImportResource(importJob, fileAccessor, directoryId, metadataExtractors, resultHandler, mediaAccessor))
                                {
                                    path2Item.Remove(serializedFilePath);
                                }
                            }
                            catch (Exception e)
                            {
                                CheckSuspended(e); // Throw ImportAbortException if suspended - will skip warning and tagging job as erroneous
                                ServiceRegistration.Get <ILogger>().Warn("ImporterWorker: Problem while importing resource '{0}'", e, serializedFilePath);
                                importJob.State = ImportJobState.Erroneous;
                            }
                            CheckImportStillRunning(importJob.State);
                        }
                    }
                }
                if (importJob.JobType == ImportJobType.Refresh)
                { // Remove remaining (= non-present) files
                    foreach (string pathStr in path2Item.Keys)
                    {
                        ResourcePath path = ResourcePath.Deserialize(pathStr);
                        try
                        {
                            IResourceAccessor ra;
                            if (!path.TryCreateLocalResourceAccessor(out ra))
                            {
                                throw new IllegalCallException("Unable to access resource path '{0}'", importJob.BasePath);
                            }
                            using (ra)
                            {
                                IFileSystemResourceAccessor fsra = ra as IFileSystemResourceAccessor;
                                if (fsra == null || !fsra.IsFile)
                                {
                                    // Don't touch directories because they will be imported in a different call of ImportDirectory
                                    continue;
                                }
                            }
                        }
                        catch (IllegalCallException)
                        {
                            // This happens if the resource doesn't exist any more - we also catch missing directories here
                        }
                        // Delete all remaining items
                        resultHandler.DeleteMediaItemAsync(path);
                        CheckImportStillRunning(importJob.State);
                    }
                }
                return(directoryId);
            }
            catch (ImportSuspendedException)
            {
                throw;
            }
            catch (ImportAbortException)
            {
                throw;
            }
            catch (UnauthorizedAccessException e)
            {
                // If the access to the file or folder was denied, simply continue with the others
                ServiceRegistration.Get <ILogger>().Warn("ImporterWorker: Problem accessing resource '{0}', continueing with one", e, currentDirectoryPath);
            }
            catch (Exception e)
            {
                CheckSuspended(e); // Throw ImportAbortException if suspended - will skip warning and tagging job as erroneous
                ServiceRegistration.Get <ILogger>().Warn("ImporterWorker: Problem while importing directory '{0}'", e, currentDirectoryPath);
                importJob.State = ImportJobState.Erroneous;
            }
            return(null);
        }
Exemplo n.º 17
0
    public MediaLibrary()
    {
      ISystemResolver systemResolver = ServiceRegistration.Get<ISystemResolver>();
      _localSystemId = systemResolver.LocalSystemId;

      _mediaBrowsingCallback = new MediaBrowsingCallback(this);
      _importResultHandler = new ImportResultHandler(this);
      _messageQueue = new AsynchronousMessageQueue(this, new string[]
        {
            ImporterWorkerMessaging.CHANNEL
        });
      _messageQueue.MessageReceived += OnMessageReceived;
      _messageQueue.Start();
    }
Exemplo n.º 18
0
 /// <summary>
 /// Imports the resource with the given <paramref name="mediaItemAccessor"/>.
 /// </summary>
 /// <remarks>
 /// This method will be called for file resources as well as for directory resources because some metadata extractors
 /// extract their metadata from directories.
 /// </remarks>
 /// <param name="mediaItemAccessor">File or directory resource to be imported.</param>
 /// <param name="parentDirectoryId">Media item id of the parent directory, if present, else <see cref="Guid.Empty"/>.</param>
 /// <param name="metadataExtractors">Collection of metadata extractors to apply to the given resoure.</param>
 /// <param name="resultHandler">Callback to notify the import results.</param>
 /// <param name="mediaAccessor">Convenience reference to the media accessor.</param>
 /// <returns><c>true</c>, if metadata could be extracted from the given <paramref name="mediaItemAccessor"/>, else
 /// <c>false</c>.</returns>
 protected bool ImportResource(IResourceAccessor mediaItemAccessor, Guid parentDirectoryId,
     ICollection<IMetadataExtractor> metadataExtractors, IImportResultHandler resultHandler, IMediaAccessor mediaAccessor)
 {
   const bool forceQuickMode = false; // Allow extractions with probably longer runtime.
   ResourcePath path = mediaItemAccessor.CanonicalLocalResourcePath;
   ImporterWorkerMessaging.SendImportMessage(ImporterWorkerMessaging.MessageType.ImportStatus, path);
   IDictionary<Guid, MediaItemAspect> aspects = mediaAccessor.ExtractMetadata(mediaItemAccessor, metadataExtractors, forceQuickMode);
   if (aspects == null)
     // No metadata could be extracted
     return false;
   resultHandler.UpdateMediaItem(parentDirectoryId, path, aspects.Values);
   resultHandler.DeleteUnderPath(path);
   return true;
 }
Exemplo n.º 19
0
        /// <summary>
        /// Imports the resource with the given <paramref name="mediaItemAccessor"/>.
        /// </summary>
        /// <remarks>
        /// This method will be called for file resources as well as for directory resources because some metadata extractors
        /// extract their metadata from directories.
        /// </remarks>
        /// <param name="mediaItemAccessor">File or directory resource to be imported.</param>
        /// <param name="parentDirectoryId">Media item id of the parent directory, if present, else <see cref="Guid.Empty"/>.</param>
        /// <param name="metadataExtractors">Collection of metadata extractors to apply to the given resoure.</param>
        /// <param name="resultHandler">Callback to notify the import results.</param>
        /// <param name="mediaAccessor">Convenience reference to the media accessor.</param>
        /// <returns><c>true</c>, if metadata could be extracted from the given <paramref name="mediaItemAccessor"/>, else
        /// <c>false</c>.</returns>
        protected bool ImportResource(IResourceAccessor mediaItemAccessor, Guid parentDirectoryId,
                                      ICollection <IMetadataExtractor> metadataExtractors, IImportResultHandler resultHandler, IMediaAccessor mediaAccessor)
        {
            const bool   forceQuickMode = false; // Allow extractions with probably longer runtime.
            ResourcePath path           = mediaItemAccessor.CanonicalLocalResourcePath;

            ImporterWorkerMessaging.SendImportMessage(ImporterWorkerMessaging.MessageType.ImportStatus, path);
            IDictionary <Guid, MediaItemAspect> aspects = mediaAccessor.ExtractMetadata(mediaItemAccessor, metadataExtractors, forceQuickMode);

            if (aspects == null)
            {
                // No metadata could be extracted
                return(false);
            }
            resultHandler.UpdateMediaItem(parentDirectoryId, path, aspects.Values);
            resultHandler.DeleteUnderPath(path);
            return(true);
        }
Exemplo n.º 20
0
 /// <summary>
 /// Imports or refreshes a single file without a parent directory with the specified <paramref name="resourceAccessor"/>.
 /// </summary>
 /// <param name="importJob">The import job being processed.</param>
 /// <param name="resourceAccessor">Resource accessor for the file to import.</param>
 /// <param name="metadataExtractors">Metadata extractors to apply on the resource.</param>
 /// <param name="mediaBrowsing">Callback interface to the media library for the refresh import type.</param>
 /// <param name="resultHandler">Callback to notify the import result.</param>
 /// <param name="mediaAccessor">Convenience reference to the media accessor.</param>
 protected void ImportSingleFile(ImportJob importJob, IResourceAccessor resourceAccessor,
     ICollection<IMetadataExtractor> metadataExtractors, IMediaBrowsing mediaBrowsing,
     IImportResultHandler resultHandler, IMediaAccessor mediaAccessor)
 {
   ResourcePath currentFilePath = resourceAccessor.CanonicalLocalResourcePath;
   try
   {
     ImportResource(resourceAccessor, Guid.Empty, metadataExtractors, resultHandler, mediaAccessor);
   }
   catch (Exception e)
   {
     CheckSuspended(e); // Throw ImportAbortException if suspended - will skip warning and tagging job as erroneous
     ServiceRegistration.Get<ILogger>().Warn("ImporterWorker: Problem while importing resource '{0}'", e, currentFilePath);
     importJob.State = ImportJobState.Erroneous;
   }
 }
Exemplo n.º 21
0
 protected Guid GetOrAddDirectory(IFileSystemResourceAccessor directoryAccessor, Guid parentDirectoryId,
     IMediaBrowsing mediaBrowsing, IImportResultHandler resultHandler)
 {
   ResourcePath directoryPath = directoryAccessor.CanonicalLocalResourcePath;
   MediaItem directoryItem = mediaBrowsing.LoadLocalItem(directoryPath, EMPTY_MIA_ID_ENUMERATION, DIRECTORY_MIA_ID_ENUMERATION);
   if (directoryItem != null)
   {
     MediaItemAspect da;
     if (!directoryItem.Aspects.TryGetValue(DirectoryAspect.ASPECT_ID, out da))
     { // This is the case if the path was formerly imported as a non-directory media item; we cannot reuse it
       resultHandler.DeleteMediaItem(directoryPath);
       directoryItem = null;
     }
   }
   if (directoryItem == null)
   { // Add directory item to ML
     MediaItemAspect mia = new MediaItemAspect(MediaAspect.Metadata);
     mia.SetAttribute(MediaAspect.ATTR_TITLE, directoryAccessor.ResourceName);
     mia.SetAttribute(MediaAspect.ATTR_MIME_TYPE, null);
     mia.SetAttribute(MediaAspect.ATTR_RECORDINGTIME, DateTime.MinValue);
     mia.SetAttribute(MediaAspect.ATTR_RATING, 0);
     mia.SetAttribute(MediaAspect.ATTR_COMMENT, null);
     mia.SetAttribute(MediaAspect.ATTR_LASTPLAYED, DateTime.MinValue);
     MediaItemAspect da = new MediaItemAspect(DirectoryAspect.Metadata);
     IList<MediaItemAspect> aspects = new List<MediaItemAspect>(new[]
       {
           mia,
           da,
       });
     return resultHandler.UpdateMediaItem(parentDirectoryId, directoryPath, aspects);
   }
   return directoryItem.MediaItemId;
 }
Exemplo n.º 22
0
    private void DoActivate(IMediaBrowsing mediaBrowsingCallback, IImportResultHandler importResultHandler)
    {
      if (_status != Status.Suspended)
      {
        ServiceRegistration.Get<ILogger>().Error("ImporterWorker: Activation was requested although status was not 'Suspended' but '{0}'", _status);
        return;
      }

      _mediaBrowsing = mediaBrowsingCallback;
      _importResultHandler = importResultHandler;

      foreach (var kvp in _importJobControllers)
      {
        // To avoid peaks on system startup when multiple ImportJobs were saved to disk and are now
        // reactivated, we start one ImportJob every 500ms.
        // Currently we also need this because the MediaAccessor is not threadsafe on startup
        // see here: http://forum.team-mediaportal.com/threads/mediaaccessor-not-thread-safe.125132/
        // ToDo: Make MediaAccessor threadsafe on startup
        Task.Delay(500).Wait();
        kvp.Value.Activate(_mediaBrowsing, _importResultHandler);
      }

      _status = Status.Activated;
      ServiceRegistration.Get<ILogger>().Info("ImporterWorker: Activated ({0} ImportJobs pending)", _importJobControllers.Count);
    }
Exemplo n.º 23
0
 /// <summary>
 /// Imports or refreshes the directory with the specified <paramref name="directoryAccessor"/>. Sub directories will not
 /// be processed in this method.
 /// </summary>
 /// <param name="importJob">The import job being processed.</param>
 /// <param name="parentDirectoryId">Media item id of the parent directory, if present, else <see cref="Guid.Empty"/>.</param>
 /// <param name="directoryAccessor">Resource accessor for the directory to import.</param>
 /// <param name="metadataExtractors">Metadata extractors to apply on the resources.</param>
 /// <param name="mediaBrowsing">Callback interface to the media library for the refresh import type.</param>
 /// <param name="resultHandler">Callback to notify the import result.</param>
 /// <param name="mediaAccessor">Convenience reference to the media accessor.</param>
 /// <returns>Id of the directory's media item or <c>null</c>, if the given <paramref name="directoryAccessor"/>
 /// was imported as a media item or if an error occured. If <c>null</c> is returned, the directory import should be
 /// considered to be finished.</returns>
 protected Guid? ImportDirectory(ImportJob importJob, Guid parentDirectoryId, IFileSystemResourceAccessor directoryAccessor,
     ICollection<IMetadataExtractor> metadataExtractors, IMediaBrowsing mediaBrowsing,
     IImportResultHandler resultHandler, IMediaAccessor mediaAccessor)
 {
   ResourcePath currentDirectoryPath = directoryAccessor.CanonicalLocalResourcePath;
   try
   {
     ImporterWorkerMessaging.SendImportMessage(ImporterWorkerMessaging.MessageType.ImportStatus, currentDirectoryPath);
     if (ImportResource(directoryAccessor, parentDirectoryId, metadataExtractors, resultHandler, mediaAccessor))
       // The directory could be imported as a media item.
       // If the directory itself was identified as a normal media item, don't import its children.
       // Necessary for DVD directories, for example.
       return null;
     Guid directoryId = GetOrAddDirectory(directoryAccessor, parentDirectoryId, mediaBrowsing, resultHandler);
     IDictionary<string, MediaItem> path2Item = new Dictionary<string, MediaItem>();
     if (importJob.JobType == ImportJobType.Refresh)
     {
       foreach (MediaItem mediaItem in mediaBrowsing.Browse(directoryId,
           IMPORTER_PROVIDER_MIA_ID_ENUMERATION, EMPTY_MIA_ID_ENUMERATION))
       {
         MediaItemAspect providerResourceAspect;
         if (mediaItem.Aspects.TryGetValue(ProviderResourceAspect.ASPECT_ID, out providerResourceAspect))
           path2Item[providerResourceAspect.GetAttributeValue<string>(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH)] = mediaItem;
       }
     }
     CheckImportStillRunning(importJob.State);
     ICollection<IFileSystemResourceAccessor> files = FileSystemResourceNavigator.GetFiles(directoryAccessor, false);
     if (files != null)
       foreach (IFileSystemResourceAccessor fileAccessor in files)
         using (fileAccessor)
         { // Add & update files
           ResourcePath currentFilePath = fileAccessor.CanonicalLocalResourcePath;
           string serializedFilePath = currentFilePath.Serialize();
           try
           {
             MediaItemAspect importerAspect;
             MediaItem mediaItem;
             if (importJob.JobType == ImportJobType.Refresh &&
                 path2Item.TryGetValue(serializedFilePath, out mediaItem) &&
                 mediaItem.Aspects.TryGetValue(ImporterAspect.ASPECT_ID, out importerAspect) &&
                 importerAspect.GetAttributeValue<DateTime>(ImporterAspect.ATTR_LAST_IMPORT_DATE) > fileAccessor.LastChanged)
             { // We can skip this file; it was imported after the last change time of the item
               path2Item.Remove(serializedFilePath);
               continue;
             }
             if (ImportResource(fileAccessor, directoryId, metadataExtractors, resultHandler, mediaAccessor))
               path2Item.Remove(serializedFilePath);
           }
           catch (Exception e)
           {
             CheckSuspended(e); // Throw ImportAbortException if suspended - will skip warning and tagging job as erroneous
             ServiceRegistration.Get<ILogger>().Warn("ImporterWorker: Problem while importing resource '{0}'", e, serializedFilePath);
             importJob.State = ImportJobState.Erroneous;
           }
           CheckImportStillRunning(importJob.State);
         }
     if (importJob.JobType == ImportJobType.Refresh)
     { // Remove remaining (= non-present) files
       foreach (string pathStr in path2Item.Keys)
       {
         ResourcePath path = ResourcePath.Deserialize(pathStr);
         try
         {
           IResourceAccessor ra;
           if (!path.TryCreateLocalResourceAccessor(out ra))
             throw new IllegalCallException("Unable to access resource path '{0}'", importJob.BasePath);
           using (ra)
           {
             IFileSystemResourceAccessor fsra = ra as IFileSystemResourceAccessor;
             if (fsra == null || !fsra.IsFile)
               // Don't touch directories because they will be imported in a different call of ImportDirectory
               continue;
           }
         }
         catch (IllegalCallException)
         {
           // This happens if the resource doesn't exist any more - we also catch missing directories here
         }
         // Delete all remaining items
         resultHandler.DeleteMediaItem(path);
         CheckImportStillRunning(importJob.State);
       }
     }
     return directoryId;
   }
   catch (ImportSuspendedException)
   {
     throw;
   }
   catch (ImportAbortException)
   {
     throw;
   }
   catch (UnauthorizedAccessException e)
   {
     // If the access to the file or folder was denied, simply continue with the others
     ServiceRegistration.Get<ILogger>().Warn("ImporterWorker: Problem accessing resource '{0}', continueing with one", e, currentDirectoryPath);
   }
   catch (Exception e)
   {
     CheckSuspended(e); // Throw ImportAbortException if suspended - will skip warning and tagging job as erroneous
     ServiceRegistration.Get<ILogger>().Warn("ImporterWorker: Problem while importing directory '{0}'", e, currentDirectoryPath);
     importJob.State = ImportJobState.Erroneous;
   }
   return null;
 }
Exemplo n.º 24
0
 public void Activate(IMediaBrowsing mediaBrowsingCallback, IImportResultHandler importResultHandler)
 {
   lock (_syncObj)
   {
     _mediaBrowsingCallback = mediaBrowsingCallback;
     _importResultHandler = importResultHandler;
   }
   StartImporterLoop_NoLock();
 }
Exemplo n.º 25
0
 /// <summary>
 /// Activates the ImportJob
 /// </summary>
 /// <param name="mediaBrowsingCallback"></param>
 /// <param name="importResultHandler"></param>
 public void Activate(IMediaBrowsing mediaBrowsingCallback, IImportResultHandler importResultHandler)
 {
   // To avoid peaks on system startup we start one Block every 100ms.
   // Currently we also need this because the MediaAccessor is not threadsafe on startup
   // see here: http://forum.team-mediaportal.com/threads/mediaaccessor-not-thread-safe.125132/
   // ToDo: Make MediaAccessor threadsafe on startup
   foreach (var block in _dataflowBlocks)
   {
     block.Activate(mediaBrowsingCallback, importResultHandler);
     Task.Delay(100).Wait();
   }
   ServiceRegistration.Get<ILogger>().Info("ImporterWorker.{0}: Activated", this);
   ImporterWorkerMessaging.SendImportMessage(ImporterWorkerMessaging.MessageType.ImportStarted, _importJobInformation.BasePath);
 }
Exemplo n.º 26
0
 /// <summary>
 /// Imports or refreshes a single file without a parent directory with the specified <paramref name="fileAccessor"/>.
 /// </summary>
 /// <param name="importJob">The import job being processed.</param>
 /// <param name="fileAccessor">Resource accessor for the file to import.</param>
 /// <param name="metadataExtractors">Metadata extractors to apply on the resource.</param>
 /// <param name="mediaBrowsing">Callback interface to the media library for the refresh import type.</param>
 /// <param name="resultHandler">Callback to notify the import result.</param>
 /// <param name="mediaAccessor">Convenience reference to the media accessor.</param>
 protected void ImportSingleFile(ImportJob importJob, IResourceAccessor fileAccessor,
     ICollection<IMetadataExtractor> metadataExtractors, IMediaBrowsing mediaBrowsing,
     IImportResultHandler resultHandler, IMediaAccessor mediaAccessor)
 {
   ResourcePath currentFilePath = fileAccessor.CanonicalLocalResourcePath;
   try
   {
     if (importJob.JobType == ImportJobType.Refresh)
     {
       MediaItem mediaItem = mediaBrowsing.LoadLocalItem(currentFilePath,
           IMPORTER_MIA_ID_ENUMERATION, EMPTY_MIA_ID_ENUMERATION);
       MediaItemAspect importerAspect;
       if (mediaItem != null && mediaItem.Aspects.TryGetValue(ImporterAspect.ASPECT_ID, out importerAspect) &&
           (DateTime) importerAspect[ImporterAspect.ATTR_LAST_IMPORT_DATE] > fileAccessor.LastChanged)
         return;
     }
     ImportResource(fileAccessor, Guid.Empty, metadataExtractors, resultHandler, mediaAccessor);
   }
   catch (Exception e)
   {
     CheckSuspended(e); // Throw ImportAbortException if suspended - will skip warning and tagging job as erroneous
     ServiceRegistration.Get<ILogger>().Warn("ImporterWorker: Problem while importing resource '{0}'", e, currentFilePath);
     importJob.State = ImportJobState.Erroneous;
   }
 }