示例#1
0
        /// <summary>
        /// Returns a resource accessor instance of interface <see cref="ILocalFsResourceAccessor"/>. This instance will return the
        /// given <paramref name="baseResourceAccessor"/>, casted to <see cref="ILocalFsResourceAccessor"/> if possible, or
        /// a new instance of <see cref="StreamedResourceToLocalFsAccessBridge"/> to provide the <see cref="ILocalFsResourceAccessor"/>
        /// instance.
        /// </summary>
        /// <remarks>
        /// The ownership of the given <paramref name="baseResourceAccessor"/> is transferred from the caller to the returned
        /// result value. That means, if this method succeeds, the caller must dispose the result value, it must not dispose
        /// the given <paramref name="baseResourceAccessor"/> any more.
        /// </remarks>
        /// <param name="baseResourceAccessor">Resource accessor which is used to provide the resource contents.</param>
        /// <param name="path">Relative path based on the given baseResourceAccessor.</param>
        /// <returns>Resource accessor which implements <see cref="ILocalFsResourceAccessor"/>.</returns>
        public static ILocalFsResourceAccessor GetLocalFsResourceAccessor(IResourceAccessor baseResourceAccessor, string path)
        {
            // Try to get an ILocalFsResourceAccessor
            ILocalFsResourceAccessor result = baseResourceAccessor as ILocalFsResourceAccessor;

            if (result != null)
            {
                // Simple case: The media item is located in the local file system or the resource provider returns
                // an ILocalFsResourceAccessor from elsewhere - simply return it
                return(result);
            }

            // Set up a resource bridge mapping the remote or complex resource to a local file or directory
            string            key = baseResourceAccessor.CanonicalLocalResourcePath.Serialize();
            MountingDataProxy md;
            bool dispose = false;

            lock (_syncObj)
            {
                if (_activeMounts.TryGetValue(key, out md))
                {
                    // Base accessor not needed - we use our cached accessor
                    dispose = true;
                }
                else
                {
                    _activeMounts.Add(key, md = CreateMountingDataProxy(key, baseResourceAccessor));
                }
            }
            if (dispose)
            {
                baseResourceAccessor.Dispose();
            }
            return(new StreamedResourceToLocalFsAccessBridge(md, path));
        }
 public void Dispose()
 {
     if (_accessor != null)
     {
         _accessor.Dispose();
     }
 }
示例#3
0
 protected override void FreeData()
 {
     _texture = null;
     _stream.Close();
     _resourceAccessor.Dispose();
     base.FreeData();
 }
        public bool TryExtractMetadata(IResourceAccessor mediaItemAccessor, IDictionary <Guid, MediaItemAspect> extractedAspectData, bool forceQuickMode)
        {
            try
            {
                IResourceAccessor ra = mediaItemAccessor.Clone();
                try
                {
                    using (ILocalFsResourceAccessor fsra = StreamedResourceToLocalFsAccessBridge.GetLocalFsResourceAccessor(ra))
                        if (fsra != null && fsra.IsDirectory && fsra.ResourceExists("BDMV"))
                        {
                            IFileSystemResourceAccessor fsraBDMV = fsra.GetResource("BDMV");
                            if (fsraBDMV != null && fsraBDMV.ResourceExists("index.bdmv"))
                            {
                                // This line is important to keep in, if no VideoAspect is created here, the MediaItems is not detected as Video!
                                MediaItemAspect.GetOrCreateAspect(extractedAspectData, VideoAspect.Metadata);
                                MediaItemAspect mediaAspect = MediaItemAspect.GetOrCreateAspect(extractedAspectData, MediaAspect.Metadata);

                                mediaAspect.SetAttribute(MediaAspect.ATTR_MIME_TYPE, "video/bluray"); // BluRay disc

                                string    bdmvDirectory = fsra.LocalFileSystemPath;
                                BDInfoExt bdinfo        = new BDInfoExt(bdmvDirectory);
                                string    title         = bdinfo.GetTitle();
                                mediaAspect.SetAttribute(MediaAspect.ATTR_TITLE, title ?? mediaItemAccessor.ResourceName);

                                // Check for BD disc thumbs
                                FileInfo thumbnail = bdinfo.GetBiggestThumb();
                                if (thumbnail != null)
                                {
                                    byte[] binary = new byte[thumbnail.Length];
                                    using (FileStream fileStream = new FileStream(thumbnail.FullName, FileMode.Open, FileAccess.Read))
                                        using (BinaryReader binaryReader = new BinaryReader(fileStream))
                                            binaryReader.Read(binary, 0, binary.Length);

                                    MediaItemAspect.SetAttribute(extractedAspectData, ThumbnailLargeAspect.ATTR_THUMBNAIL, binary);
                                }
                                return(true);
                            }
                        }
                }
                catch
                {
                    ra.Dispose();
                    throw;
                }
                return(false);
            }
            catch
            {
                // Only log at the info level here - And simply return false. This makes the importer know that we
                // couldn't perform our task here
                if (mediaItemAccessor != null)
                {
                    ServiceRegistration.Get <ILogger>().Info("BluRayMetadataExtractor: Exception reading source '{0}'", mediaItemAccessor.ResourcePathName);
                }
                return(false);
            }
        }
示例#5
0
        public bool TryCreateLocalFsAccessor(out ILocalFsResourceAccessor localFsResourceAccessor)
        {
            IResourceAccessor           accessor = CreateAccessor();
            IFileSystemResourceAccessor fsra     = accessor as IFileSystemResourceAccessor;

            if (fsra == null)
            {
                accessor.Dispose();
                localFsResourceAccessor = null;
                return(false);
            }
            try
            {
                localFsResourceAccessor = StreamedResourceToLocalFsAccessBridge.StreamedResourceToLocalFsAccessBridge.GetLocalFsResourceAccessor(fsra);
                return(true);
            }
            catch
            {
                accessor.Dispose();
                throw;
            }
        }
示例#6
0
        public IFileSystemResourceAccessor GetResource(string path)
        {
            IResourceAccessor ra = _mountingDataProxy.ResourceAccessor.Clone();

            try
            {
                return(GetLocalFsResourceAccessor(ra, ProviderPathHelper.Combine(_path, path)));
            }
            catch
            {
                ra.Dispose();
                throw;
            }
        }
 public void Dispose()
 {
     if (_baseAccessor == null)
     {
         // Already disposed
         return;
     }
     if (!UnmountResource())
     {
         // The ownership was transferred to the resource mounting service, so if unmounting was succesful, we must not dispose our base accessor
         _baseAccessor.Dispose();
     }
     _baseAccessor = null;
 }
示例#8
0
        public ILocalFsResourceAccessor CreateLocalFsAccessor()
        {
            IResourceAccessor accessor = CreateAccessor();

            try
            {
                return(StreamedResourceToLocalFsAccessBridge.StreamedResourceToLocalFsAccessBridge.GetLocalFsResourceAccessor(accessor));
            }
            catch
            {
                accessor.Dispose();
                throw;
            }
        }
示例#9
0
        /// <summary>
        /// This method handles two cases:
        /// <list type="bullet">
        /// <item>No player available to play the resource</item>
        /// <item>The resouce to play is broken</item>
        /// </list>
        /// </summary>
        /// <param name="item"></param>
        /// <param name="exceptions"></param>
        protected void HandleUnableToPlay(MediaItem item, ICollection <Exception> exceptions)
        {
            INotificationService notificationService = ServiceRegistration.Get <INotificationService>();
            // Start a heuristics to find a proper error message for the user
            IResourceLocator locator = item.GetResourceLocator();

            if (locator == null)
            {
                ServiceRegistration.Get <ILogger>().Warn("PlayerSlotController: Could not play media item '{0}', resource locator could not be built", item);
                return;
            }
            if (exceptions.Count != 0) // This is the indicator that at least one player builder tried to open the resource but threw an exception
            {
                // 1) Check if resource is present
                IResourceAccessor ra = null;
                try
                {
                    bool exists;
                    try
                    {
                        ra = locator.CreateAccessor();
                        IFileSystemResourceAccessor fsra = ra as IFileSystemResourceAccessor;
                        exists = fsra != null && fsra.Exists;
                    }
                    catch (Exception)
                    {
                        exists = false;
                    }
                    notificationService.EnqueueNotification(
                        NotificationType.UserInteractionRequired, RES_ERROR_PLAYING_MEDIA_ITEM_TITLE, exists ?
                        LocalizationHelper.Translate(RES_UNABLE_TO_PLAY_MEDIA_ITEM_TEXT, ra.ResourceName) :
                        LocalizationHelper.Translate(RES_RESOURCE_NOT_FOUND_TEXT, locator.NativeResourcePath.FileName), true);
                }
                finally
                {
                    if (ra != null)
                    {
                        ra.Dispose();
                    }
                }
            }
            else
            {
                using (IResourceAccessor ra = locator.CreateAccessor())
                    notificationService.EnqueueNotification(NotificationType.UserInteractionRequired, RES_NO_PLAYER_AVAILABLE_NOTIFICATION_TITLE,
                                                            LocalizationHelper.Translate(RES_NO_PLAYER_AVAILABLE_NOTIFICATION_TEXT, ra.ResourceName), true);
            }
        }
示例#10
0
        public async Task <bool> TryExtractMetadataAsync(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData, bool forceQuickMode)
        {
            IResourceAccessor disposeAccessor = null;

            try
            {
                IFileSystemResourceAccessor fsra = mediaItemAccessor as IFileSystemResourceAccessor;

                if (fsra == null)
                {
                    return(false);
                }

                if (!fsra.IsFile)
                {
                    if (!IsChainedResourceProvider(mediaItemAccessor))
                    {
                        return(false);
                    }
                    // The importer mounts iso and zip files as virtual directories but we need the accessor
                    // to the original file so we have to create one here and remember to dispose it later.
                    ResourcePath path = new ResourcePath(new[] { mediaItemAccessor.CanonicalLocalResourcePath.BasePathSegment });
                    if (!path.TryCreateLocalResourceAccessor(out disposeAccessor))
                    {
                        return(false);
                    }
                }

                using (LocalFsResourceAccessorHelper rah = new LocalFsResourceAccessorHelper(disposeAccessor ?? mediaItemAccessor))
                    return(await ExtractGameData(rah.LocalFsResourceAccessor, extractedAspectData, forceQuickMode).ConfigureAwait(false));
            }
            catch (Exception e)
            {
                // Only log at the info level here - And simply return false. This lets the caller know that we
                // couldn't perform our task here.
                Logger.Info("GamesMetadataExtractor: Exception reading resource '{0}' (Text: '{1}')", mediaItemAccessor.CanonicalLocalResourcePath, e.Message);
            }
            finally
            {
                if (disposeAccessor != null)
                {
                    disposeAccessor.Dispose();
                }
            }
            return(false);
        }
 public virtual void Dispose()
 {
     foreach (FileHandle handle in _fileHandles)
     {
         handle.Cleanup();
     }
     if (_resourceAccessor != null)
     {
         try
         {
             _resourceAccessor.Dispose();
         }
         catch (Exception e)
         {
             ServiceRegistration.Get <ILogger>().Warn("Dokan virtual filesystem resource: Error disposing resource accessor '{0}'", e, _resourceAccessor);
         }
     }
     _resourceAccessor = null;
 }
示例#12
0
 public void Dispose()
 {
     foreach (string tempFilePath in _tempFilePaths.Values)
     {
         try
         {
             File.Delete(tempFilePath);
         }
         catch (Exception e)
         {
             ServiceRegistration.Get <ILogger>().Warn("ZipResourceProxy: Unable to delete temp file '{0}'", e, tempFilePath);
         }
     }
     _tempFilePaths.Clear();
     CloseZipFile();
     if (_zipFileResourceAccessor != null)
     {
         _zipFileResourceAccessor.Dispose();
         _zipFileResourceAccessor = null;
     }
 }
        public bool Init(MediaItem mediaItem)
        {
            // Prepare process information
            Prepare(mediaItem);

            IResourceAccessor ra = null;

            try
            {
                ra = mediaItem.GetResourceLocator().CreateAccessor();
                RawUrlResourceAccessor rua = ra as RawUrlResourceAccessor;
                if (rua != null)
                {
                    _fileOrUrl = rua.URL;
                }
                else
                {
                    RawTokenResourceAccessor rra = ra as RawTokenResourceAccessor;
                    if (rra == null)
                    {
                        return(false);
                    }
                    _fileOrUrl = rra.Token;
                }
                Play();
                return(true);
            }
            catch (Exception)
            {
                // Log
            }
            finally
            {
                if (ra != null)
                {
                    ra.Dispose();
                }
            }
            return(false);
        }
示例#14
0
        public static ImageSource ResourceLocatorSource(object source, int width, int height)
        {
            IResourceLocator locator = source as IResourceLocator;

            if (locator == null)
            {
                return(null);
            }
            IResourceLocator            resourceLocator = locator;
            IResourceAccessor           ra   = resourceLocator.CreateAccessor();
            IFileSystemResourceAccessor fsra = ra as IFileSystemResourceAccessor;

            if (fsra == null)
            {
                ra.Dispose();
            }
            else
            {
                return(new ResourceAccessorTextureImageSource(fsra, RightAngledRotation.Zero));
            }
            return(null);
        }
示例#15
0
 public void Dispose()
 {
     if (_diskFileSystem != null)
     {
         IDisposable d = _diskFileSystem as IDisposable;
         if (d != null)
         {
             d.Dispose();
         }
         _diskFileSystem = null;
     }
     if (_underlayingStream != null)
     {
         _underlayingStream.Dispose();
         _underlayingStream = null;
     }
     if (_isoFileResourceAccessor != null)
     {
         _isoFileResourceAccessor.Dispose();
         _isoFileResourceAccessor = null;
     }
 }
示例#16
0
 static void OnResourcePathObjectsPruned(ILRUCache <ResourcePath, IResourceAccessor> sender, ResourcePath key, IResourceAccessor value)
 {
     value.Dispose();
 }
示例#17
0
        /// <summary>
        /// Loads an ImageSource and allows control of thumbnail use.
        /// Morpheus_xx, 2011-12-13: For fallback sources no thumbnails should be used, because ALL thumbs are created as JPG. This currenly causes an issue:
        /// Source -> no thumbnail created -> FallbackSource (PNG) -> creates a JPG thumbnail, so Alpha-Channel of FallbackSource is lost.
        /// TODO: Image class and thumbnail handling should be refactored to allow more control about image formats and thumbs usage.
        /// </summary>
        /// <param name="source">Source</param>
        /// <param name="allowThumbs">True to allow building a thumbnail of given source</param>
        /// <returns>ImageSource or null</returns>
        protected ImageSource LoadImageSource(object source, bool allowThumbs)
        {
            if (source == null)
            {
                return(null);
            }
            bool thumbnail = allowThumbs && Thumbnail;

            _invalidateImageSourceOnResize = false;
            if (source is MediaItem)
            {
                _invalidateImageSourceOnResize = true;
                return(MediaItemsHelper.CreateThumbnailImageSource((MediaItem)source, (int)Math.Max(Width, Height)));
            }
            if (source is IResourceLocator)
            {
                IResourceLocator            resourceLocator = (IResourceLocator)source;
                IResourceAccessor           ra   = resourceLocator.CreateAccessor();
                IFileSystemResourceAccessor fsra = ra as IFileSystemResourceAccessor;
                if (fsra == null)
                {
                    ra.Dispose();
                }
                else
                {
                    return(new ResourceAccessorTextureImageSource(fsra, RightAngledRotation.Zero));
                }
            }
            ImageSource result = source as ImageSource;

            if (result != null)
            {
                return(result);
            }
            string uriSource = source as string;

            if (!string.IsNullOrEmpty(uriSource))
            {
                // Remember to adapt list of supported extensions for image player plugin...
                if (IsValidSource(uriSource))
                {
                    BitmapImageSource bmi = new BitmapImageSource {
                        UriSource = uriSource, Thumbnail = thumbnail
                    };
                    if (thumbnail)
                    {
                        // Set the requested thumbnail dimension, to use the best matching format.
                        bmi.ThumbnailDimension = (int)Math.Max(Width, Height);
                    }
                    return(bmi);
                }
                // TODO: More image types
            }
            string warnSource = source.ToString();

            if (_formerWarnURI != warnSource)
            {
                ServiceRegistration.Get <ILogger>().Warn("Image: Image source '{0}' is not supported", warnSource);
                // Remember if we already wrote a warning to the log to avoid log flooding
                _formerWarnURI = uriSource;
            }
            return(null);
        }
 public void Dispose()
 {
     _resourceAccessor.Dispose();
     _resourceAccessor = null;
 }
        /// <summary>
        /// Returns all child directories of the given directory.
        /// </summary>
        /// <remarks>
        /// This will return all native child directories of the given directory together with all virtual child
        /// directories. The native child directories are taken directly from the given <paramref name="directoryAccessor"/>,
        /// the virtual child directories are obtained by taking the root directories of each chained resource provider applied
        /// to the child files of the given directory.
        /// If, for example, the given <paramref name="directoryAccessor"/> contains a child directory "A" and a child
        /// archive file "B" which can work as input for an installed archive provider, providing the root directory "C"
        /// of that archive, this method will return the resource accessors for directories "A" and "C".
        /// </remarks>
        /// <param name="directoryAccessor">Directory resource accessor to get all child directories for.</param>
        /// <param name="showSystemResources">If set to <c>true</c>, system resources like the virtual drives and directories of the
        /// <see cref="IResourceMountingService"/> will also be returned, else removed from the result value.</param>
        /// <returns>Collection of directory accessors for all native and virtual child directories or <c>null</c>,
        /// if the given <paramref name="directoryAccessor"/> is not a <see cref="IFileSystemResourceAccessor"/> and
        /// if there is no chained resource provider to unfold the given directory.</returns>
        public static ICollection <IFileSystemResourceAccessor> GetChildDirectories(IResourceAccessor directoryAccessor, bool showSystemResources)
        {
            IResourceMountingService resourceMountingService = ServiceRegistration.Get <IResourceMountingService>();
            IResourceAccessor        chainedResourceAccesor; // Needed in multiple source locations, that's why we declare it here

            if (directoryAccessor is IFileSystemResourceAccessor)
            {
                IFileSystemResourceAccessor dirFsra = (IFileSystemResourceAccessor)directoryAccessor;
                ICollection <IFileSystemResourceAccessor> childDirectories = dirFsra.GetChildDirectories();
                ICollection <IFileSystemResourceAccessor> result           = new List <IFileSystemResourceAccessor>();
                if (childDirectories != null)
                {
                    // Directories are maybe filtered and then just added
                    foreach (IFileSystemResourceAccessor childDirectoryAccessor in childDirectories)
                    {
                        if (!showSystemResources && resourceMountingService.IsVirtualResource(childDirectoryAccessor.CanonicalLocalResourcePath))
                        {
                            childDirectoryAccessor.Dispose();
                            continue;
                        }
                        result.Add(childDirectoryAccessor);
                    }
                }
                ICollection <IFileSystemResourceAccessor> files = dirFsra.GetFiles();
                if (files != null)
                {
                    // For files, we try to chain up chained resource providers
                    foreach (IFileSystemResourceAccessor fileAccessor in files)
                    {
                        if (!showSystemResources && resourceMountingService.IsVirtualResource(fileAccessor.CanonicalLocalResourcePath))
                        {
                            fileAccessor.Dispose();
                            continue;
                        }
                        if (TryUnfold(fileAccessor, out chainedResourceAccesor))
                        {
                            IFileSystemResourceAccessor chainedFsra = chainedResourceAccesor as IFileSystemResourceAccessor;
                            if (chainedFsra != null)
                            {
                                result.Add(chainedFsra);
                            }
                            else
                            {
                                chainedResourceAccesor.Dispose();
                            }
                        }
                        else
                        {
                            fileAccessor.Dispose();
                        }
                    }
                }
                return(result);
            }
            // Try to unfold simple resource
            IResourceAccessor dra = directoryAccessor.Clone();

            try
            {
                if (TryUnfold(dra, out chainedResourceAccesor))
                {
                    IFileSystemResourceAccessor chainedFsra = chainedResourceAccesor as IFileSystemResourceAccessor;
                    if (chainedFsra != null)
                    {
                        return(new List <IFileSystemResourceAccessor>(new IFileSystemResourceAccessor[] { chainedFsra }));
                    }
                    chainedResourceAccesor.Dispose();
                }
                else
                {
                    dra.Dispose();
                }
            }
            catch
            {
                dra.Dispose();
                throw;
            }
            return(null);
        }
        public bool TryExtractMetadata(IResourceAccessor mediaItemAccessor, IDictionary <Guid, MediaItemAspect> extractedAspectData, bool forceQuickMode)
        {
            try
            {
                VideoResult result = null;
                IFileSystemResourceAccessor fsra = mediaItemAccessor as IFileSystemResourceAccessor;
                if (fsra != null && fsra.IsDirectory && fsra.ResourceExists("VIDEO_TS"))
                {
                    IFileSystemResourceAccessor fsraVideoTs = fsra.GetResource("VIDEO_TS");
                    if (fsraVideoTs != null && fsraVideoTs.ResourceExists("VIDEO_TS.IFO"))
                    {
                        // Video DVD
                        using (MediaInfoWrapper videoTsInfo = ReadMediaInfo(fsraVideoTs.GetResource("VIDEO_TS.IFO")))
                        {
                            if (!videoTsInfo.IsValid || videoTsInfo.GetVideoCount() == 0)
                            {
                                return(false); // Invalid video_ts.ifo file
                            }
                            result = VideoResult.CreateDVDInfo(fsra.ResourceName, videoTsInfo);
                        }
                        // Iterate over all video files; MediaInfo finds different audio/video metadata for each .ifo file
                        ICollection <IFileSystemResourceAccessor> files = fsraVideoTs.GetFiles();
                        if (files != null)
                        {
                            foreach (IFileSystemResourceAccessor file in files)
                            {
                                string lowerPath = (file.ResourcePathName ?? string.Empty).ToLowerInvariant();
                                if (!lowerPath.EndsWith(".ifo") || lowerPath.EndsWith("video_ts.ifo"))
                                {
                                    continue;
                                }
                                using (MediaInfoWrapper mediaInfo = ReadMediaInfo(file))
                                {
                                    // Before we start evaluating the file, check if it is a video at all
                                    if (mediaInfo.IsValid && mediaInfo.GetVideoCount() == 0)
                                    {
                                        continue;
                                    }
                                    result.AddMediaInfo(mediaInfo);
                                }
                            }
                        }
                    }
                }
                else if (mediaItemAccessor.IsFile)
                {
                    string filePath = mediaItemAccessor.ResourcePathName;
                    if (!HasVideoExtension(filePath))
                    {
                        return(false);
                    }
                    using (MediaInfoWrapper fileInfo = ReadMediaInfo(mediaItemAccessor))
                    {
                        // Before we start evaluating the file, check if it is a video at all
                        if (!fileInfo.IsValid || (fileInfo.GetVideoCount() == 0 && !IsWorkaroundRequired(filePath)))
                        {
                            return(false);
                        }

                        string mediaTitle = DosPathHelper.GetFileNameWithoutExtension(mediaItemAccessor.ResourceName);
                        result = VideoResult.CreateFileInfo(mediaTitle, fileInfo);
                    }
                    using (Stream stream = mediaItemAccessor.OpenRead())
                        result.MimeType = MimeTypeDetector.GetMimeType(stream);
                }
                if (result != null)
                {
                    result.UpdateMetadata(extractedAspectData);

                    ILocalFsResourceAccessor disposeLfsra = null;
                    try
                    {
                        ILocalFsResourceAccessor lfsra = mediaItemAccessor as ILocalFsResourceAccessor;
                        if (lfsra == null && !forceQuickMode)
                        { // In case forceQuickMode, we only want local browsing
                            IResourceAccessor ra = mediaItemAccessor.Clone();
                            try
                            {
                                lfsra        = StreamedResourceToLocalFsAccessBridge.GetLocalFsResourceAccessor(ra);
                                disposeLfsra = lfsra; // Remember to dispose the extra resource accessor instance
                            }
                            catch (Exception)
                            {
                                ra.Dispose();
                            }
                        }
                        if (lfsra != null)
                        {
                            string localFsPath = lfsra.LocalFileSystemPath;
                            ExtractMatroskaTags(localFsPath, extractedAspectData, forceQuickMode);
                            ExtractThumbnailData(localFsPath, extractedAspectData, forceQuickMode);
                        }
                    }
                    finally
                    {
                        if (disposeLfsra != null)
                        {
                            disposeLfsra.Dispose();
                        }
                    }
                    return(true);
                }
            }
            catch (Exception e)
            {
                // Only log at the info level here - And simply return false. This lets the caller know that we
                // couldn't perform our task here.
                ServiceRegistration.Get <ILogger>().Info("VideoMetadataExtractor: Exception reading resource '{0}' (Text: '{1}')", mediaItemAccessor.CanonicalLocalResourcePath, e.Message);
            }
            return(false);
        }
    /// <summary>
    /// Returns a resource accessor instance of interface <see cref="ILocalFsResourceAccessor"/>. This instance will return the
    /// given <paramref name="baseResourceAccessor"/>, casted to <see cref="ILocalFsResourceAccessor"/> if possible, or
    /// a new instance of <see cref="StreamedResourceToLocalFsAccessBridge"/> to provide the <see cref="ILocalFsResourceAccessor"/>
    /// instance.
    /// </summary>
    /// <remarks>
    /// The ownership of the given <paramref name="baseResourceAccessor"/> is transferred from the caller to the returned
    /// result value. That means, if this method succeeds, the caller must dispose the result value, it must not dispose
    /// the given <paramref name="baseResourceAccessor"/> any more.
    /// </remarks>
    /// <param name="baseResourceAccessor">Resource accessor which is used to provide the resource contents.</param>
    /// <param name="path">Relative path based on the given baseResourceAccessor.</param>
    /// <returns>Resource accessor which implements <see cref="ILocalFsResourceAccessor"/>.</returns>
    public static ILocalFsResourceAccessor GetLocalFsResourceAccessor(IResourceAccessor baseResourceAccessor, string path)
    {
      // Try to get an ILocalFsResourceAccessor
      ILocalFsResourceAccessor result = baseResourceAccessor as ILocalFsResourceAccessor;
      if (result != null)
          // Simple case: The media item is located in the local file system or the resource provider returns
          // an ILocalFsResourceAccessor from elsewhere - simply return it
        return result;

      // Set up a resource bridge mapping the remote or complex resource to a local file or directory
      string key = baseResourceAccessor.CanonicalLocalResourcePath.Serialize();
      MountingDataProxy md;
      bool dispose = false;
      lock (_syncObj)
      {
        if (_activeMounts.TryGetValue(key, out md))
            // Base accessor not needed - we use our cached accessor
          dispose = true;
        else
          _activeMounts.Add(key, md = CreateMountingDataProxy(key, baseResourceAccessor));
      }
      if (dispose)
        baseResourceAccessor.Dispose();
      return new StreamedResourceToLocalFsAccessBridge(md, path);
    }
        public async Task <MetadataContainer> ParseMediaItemAsync(MediaItem media, int?editionId = null, bool cache = true)
        {
            try
            {
                if (media.IsStub)
                {
                    return(null);
                }

                string            category = null;
                MetadataContainer info     = null;

                //Check for live items
                if (media.Aspects.ContainsKey(AudioAspect.ASPECT_ID))
                {
                    category = AUDIO_CATEGORY;
                    if (media.IsLiveRadioItem() && media is LiveTvMediaItem ltmi)
                    {
                        info = await ParseSlimTvItemAsync(ltmi).ConfigureAwait(false);

                        if (info != null)
                        {
                            info.Metadata[Editions.DEFAULT_EDITION].Live = true;
                            info.Metadata[Editions.DEFAULT_EDITION].Size = 0;
                        }
                        return(info);
                    }
                }
                else if (media.Aspects.ContainsKey(VideoAspect.ASPECT_ID))
                {
                    category = VIDEO_CATEGORY;
                    if (media.IsLiveTvItem() && media is LiveTvMediaItem ltmi)
                    {
                        info = await ParseSlimTvItemAsync(ltmi).ConfigureAwait(false);

                        if (info != null)
                        {
                            info.Metadata[Editions.DEFAULT_EDITION].Live = true;
                            info.Metadata[Editions.DEFAULT_EDITION].Size = 0;
                        }
                        return(info);
                    }
                }
                else if (media.Aspects.ContainsKey(ImageAspect.ASPECT_ID))
                {
                    category = IMAGE_CATEGORY;
                }

                info = await LoadAnalysisAsync(media, category, media.MediaItemId);

                if (info != null)
                {
                    return(info);
                }

                IList <MultipleMediaItemAspect> providerAspects;
                if (!MediaItemAspect.TryGetAspects(media.Aspects, ProviderResourceAspect.Metadata, out providerAspects))
                {
                    return(null);
                }

                IDictionary <int, ResourceLocator> resources = null;
                if (media.HasEditions)
                {
                    IEnumerable <int> praIdxs = null;
                    if (editionId.HasValue)
                    {
                        praIdxs = media.Editions.First(e => e.Key == editionId.Value).Value.PrimaryResourceIndexes;
                    }
                    else
                    {
                        praIdxs = media.Editions.SelectMany(e => e.Value.PrimaryResourceIndexes).Distinct();
                    }

                    resources = providerAspects.Where(pra => praIdxs.Contains(pra.GetAttributeValue <int>(ProviderResourceAspect.ATTR_RESOURCE_INDEX))).
                                ToDictionary(pra => pra.GetAttributeValue <int>(ProviderResourceAspect.ATTR_RESOURCE_INDEX), pra => new ResourceLocator(pra.GetAttributeValue <string>(ProviderResourceAspect.ATTR_SYSTEM_ID), ResourcePath.Deserialize(pra.GetAttributeValue <string>(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH))));
                }
                else
                {
                    resources = providerAspects.Where(pra => pra.GetAttributeValue <int>(ProviderResourceAspect.ATTR_TYPE) == ProviderResourceAspect.TYPE_PRIMARY).
                                ToDictionary(pra => pra.GetAttributeValue <int>(ProviderResourceAspect.ATTR_RESOURCE_INDEX), pra => new ResourceLocator(pra.GetAttributeValue <string>(ProviderResourceAspect.ATTR_SYSTEM_ID), ResourcePath.Deserialize(pra.GetAttributeValue <string>(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH))));
                }

                //Process media resources
                Dictionary <int, Dictionary <int, IResourceAccessor> > editions = new Dictionary <int, Dictionary <int, IResourceAccessor> >();
                foreach (var res in resources)
                {
                    int edition = Editions.DEFAULT_EDITION;
                    if (media.HasEditions)
                    {
                        edition = media.Editions.FirstOrDefault(e => e.Value.PrimaryResourceIndexes.Contains(res.Key)).Value.SetNo;
                    }

                    if (!editions.ContainsKey(edition))
                    {
                        editions.Add(edition, new Dictionary <int, IResourceAccessor>());
                    }
                    IResourceAccessor mia = res.Value.CreateAccessor();

                    if (mia is IFileSystemResourceAccessor fileRes && !fileRes.IsFile)
                    {
                        if (fileRes.ResourceExists("VIDEO_TS"))
                        {
                            using (IFileSystemResourceAccessor fsraVideoTs = fileRes.GetResource("VIDEO_TS"))
                            {
                                if (fsraVideoTs != null && fsraVideoTs.ResourceExists("VIDEO_TS.IFO"))
                                {
                                    //Find all titles and add each of them
                                    var titles = GetDvdTitleFiles(fsraVideoTs);
                                    foreach (var title in titles)
                                    {
                                        int fileNo = 0;
                                        foreach (var file in title.Value)
                                        {
                                            fileNo++;
                                            int titleKey = MetadataContainer.GetDvdResource(res.Key, title.Key, fileNo);
                                            editions[edition].Add(titleKey, file);
                                        }
                                    }
                                }
                            }
                        }
                        else if (fileRes.ResourceExists("BDMV"))
                        {
                            using (IFileSystemResourceAccessor fsraBDMV = fileRes.GetResource("BDMV"))
                            {
                                if (fsraBDMV != null && fsraBDMV.ResourceExists("index.bdmv") && fsraBDMV.ResourceExists("STREAM"))
                                {
                                    using (IFileSystemResourceAccessor fsraStream = fsraBDMV.GetResource("STREAM"))
                                    {
                                        var orderedFileList = fsraStream.GetFiles().Where(f => f.ResourceName.EndsWith(".m2ts", StringComparison.InvariantCultureIgnoreCase)).OrderByDescending(f => f.Size);
                                        //Use the largest file which is probably the main stream
                                        var mainStream = orderedFileList.First();
                                        editions[edition].Add(res.Key, mainStream);
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        editions[edition].Add(res.Key, mia);
                    }
                    mia.Dispose();
                }
示例#23
0
        /// <summary>
        /// Creates a local resource provider chain for this resource path, if it is a local path
        /// (see <see cref="CheckValidLocalPath"/>), and returns its result in a <see cref="IResourceAccessor"/> instance.
        /// </summary>
        /// <param name="result">Returns the resource accessor to access the resource represented by this path, if the
        /// return value is <c>true</c>. Else, this parameter doesn't return a meaningful value.</param>
        /// <returns><c>true</c>, if a resource accessor could successfully be built for this path.</returns>
        /// <exception cref="IllegalCallException">If one of the referenced resource providers is not available in the system or
        /// has the wrong type.</exception>
        /// <exception cref="UnexpectedStateException">If this path is empty.</exception>
        public bool TryCreateLocalResourceAccessor(out IResourceAccessor result)
        {
            IResourceAccessor resourceAccessor = null;

            if (USE_RA_CACHE)
            {
                if (TryGetCloneFromCache(this, out resourceAccessor))
                {
                    result = resourceAccessor;
                    return(true);
                }
            }
            IMediaAccessor mediaAccessor             = ServiceRegistration.Get <IMediaAccessor>();
            IEnumerator <ProviderPathSegment> enumer = _pathSegments.GetEnumerator();

            if (!enumer.MoveNext())
            {
                throw new UnexpectedStateException("Cannot build resource accessor for an empty resource path");
            }
            try
            {
                do
                {
                    ProviderPathSegment pathSegment = enumer.Current;
                    IResourceProvider   resourceProvider;
                    if (!mediaAccessor.LocalResourceProviders.TryGetValue(pathSegment.ProviderId, out resourceProvider))
                    {
                        throw new IllegalCallException("The resource provider with id '{0}' is not accessible in the current system", pathSegment.ProviderId);
                    }
                    if (resourceAccessor == null)
                    {
                        IBaseResourceProvider baseProvider = resourceProvider as IBaseResourceProvider;
                        if (baseProvider == null)
                        {
                            throw new IllegalCallException("The resource provider with id '{0}' does not implement the {1} interface", pathSegment.ProviderId, typeof(IBaseResourceProvider).Name);
                        }
                        if (!baseProvider.TryCreateResourceAccessor(pathSegment.Path, out resourceAccessor))
                        {
                            result = null;
                            return(false);
                        }
                    }
                    else
                    {
                        IChainedResourceProvider chainedProvider = resourceProvider as IChainedResourceProvider;
                        if (chainedProvider == null)
                        {
                            throw new IllegalCallException("The resource provider with id '{0}' does not implement the {1} interface", pathSegment.ProviderId, typeof(IChainedResourceProvider).Name);
                        }
                        IResourceAccessor chainedRa;
                        if (!chainedProvider.TryChainUp(resourceAccessor, pathSegment.Path, out chainedRa))
                        {
                            resourceAccessor.Dispose();
                            result = null;
                            return(false);
                        }
                        resourceAccessor = chainedRa;
                    }
                } while (enumer.MoveNext());
            }
            catch (Exception)
            {
                if (resourceAccessor != null)
                {
                    resourceAccessor.Dispose();
                }
                throw;
            }
            if (USE_RA_CACHE)
            {
                AddToCache(this, resourceAccessor);
            }
            result = resourceAccessor;
            return(true);
        }
示例#24
0
        /// <summary>
        /// Instantiates all the necessary DataflowBlocks for the given ImportJob
        /// </summary>
        /// <remarks>
        /// We first have to distinguish between two cases here:
        ///  - BasePath points to a resource for which we can only create an IResourceAccessor - not an IFilesystemResourceAccessor
        ///    For this case we only import that single resource and don't have to take care of directories and subdirectories
        ///    ToDo: This still needs to be implemented
        /// - BasePath points to a resource for which we can create an IFilesystemResourceAccessor
        ///   Here we first check whether the resource on the given BasePath exists. If not, we do nothing.
        ///   If it does exist, we distinguish two cases:
        ///   - The ImportJob was restored from disk, in which case we push the existing PendingImportResources to the respective DataflowBlocks.
        ///   - The ImportJob was freshly created, in which case we push the BasePath to the first DataFlowBlock.
        ///     In this case there are three subcases:
        ///     - BasePath points to a single resource
        ///     - BasePath points to a directory which is not a single resource and the ImportJob does not include subdirectories
        ///     - BasePath points to a directory which is not a single resource and the ImportJob does include subdirectories
        ///     These subcases, however, are taken care of by the DataflowBlocks - not by the ImportJobController
        /// </remarks>
        private void SetupDataflowBlocks(IEnumerable <PendingImportResourceNewGen> pendingImportResources)
        {
            // If we cannot access the BasePath at all, we just log and return
            IResourceAccessor ra = null;

            try
            {
                if (!_importJobInformation.BasePath.TryCreateLocalResourceAccessor(out ra))
                {
                    ServiceRegistration.Get <ILogger>().Warn("ImporterWorker.{0}: Unable to access resource path '{1}'.", this, _importJobInformation.BasePath);
                    return;
                }
            }
            catch (Exception e)
            {
                ServiceRegistration.Get <ILogger>().Error("ImporterWorker.{0}: Error while creating ResourceAccessor for resource path '{1}'.", e, this, _importJobInformation.BasePath);
                if (ra != null)
                {
                    ra.Dispose();
                }
                return;
            }

            try
            {
                // As of now we have a ResourceAccessor that needs to be disposed
                using (ra)
                {
                    // If we have a ResourceAccessor which is not an IFileSystemResourceAccessor, just import that single resource
                    if (!(ra is IFileSystemResourceAccessor))
                    {
                        // ToDo: Implement import of Non-IFilesSystemResourceAccessors
                        return;
                    }

                    // Now we are sure it is an IFileSystemResourceAccessor
                    var fsra = ra as IFileSystemResourceAccessor;

                    // If the BasePath does not exist, we do nothing. This is necessary to avoid whole shares being removed from
                    // the MediaLibrary when a RefreshImport is scheduled while e.g. network resources are unavailable.
                    // If fsra is a NetworkNeighborhoddResourceAccessor and its IsServerPath() method returns true, fsra.Exists()
                    // will always return true. If therefore the BasePath of this Import points to a whole server and this server
                    // is not available during a RefreshImport, the whole share will be deleted from the MediaLibrary.
                    // ToDo: Rework this in NetworkNeighborhoodResourceAccessor
                    if (!fsra.Exists)
                    {
                        ServiceRegistration.Get <ILogger>().Warn("ImporterWorker.{0}: Resource '{1}' does not exists or is not available.", this, _importJobInformation.BasePath);
                        return;
                    }

                    // Now we are sure that we need a DataflowBlock network

                    // Create the blocks
                    _dataflowBlocks.Add(new DirectoryUnfoldBlock(_cts.Token, _importJobInformation, this));
                    _dataflowBlocks.Add(new DirectorySaveBlock(_cts.Token, _importJobInformation, this));
                    _dataflowBlocks.Add(new FileUnfoldBlock(_cts.Token, _importJobInformation, this));
                    _dataflowBlocks.Add(new MetadataExtractorBlock(_cts.Token, _importJobInformation, this, false));
                    _dataflowBlocks.Add(new MediaItemSaveBlock(_cts.Token, _importJobInformation, this));

                    // Link the blocks
                    for (int i = 0; i < _dataflowBlocks.Count - 1; i++)
                    {
                        _dataflowBlocks[i].LinkTo(_dataflowBlocks[i + 1], new DataflowLinkOptions {
                            PropagateCompletion = true
                        });
                    }
                    _dataflowBlocks[_dataflowBlocks.Count - 1].LinkTo(DataflowBlock.NullTarget <PendingImportResourceNewGen>());

                    // Fill the blocks
                    var  completeFirstBlockAfterTheseTasks = new HashSet <Task>();
                    bool firstBlockNeedsCompletion         = true;
                    if (pendingImportResources == null)
                    {
                        // This ImportJob was freshly created and not persisted to disk before
                        // Just post the BasePath as new PendingImportResource
                        var rootImportResource = new PendingImportResourceNewGen(null, fsra.Clone() as IFileSystemResourceAccessor, DirectoryUnfoldBlock.BLOCK_NAME, this);
                        _dataflowBlocks[0].Post(rootImportResource);
                        firstBlockNeedsCompletion = false;
                    }
                    else
                    {
                        // This ImportJob was persisted to disk before
                        int numberOfRestoredPendingResources = 0;
                        foreach (var pendingImportResource in pendingImportResources)
                        {
                            pendingImportResource.InitializeAfterDeserialization(this);
                            ImporterWorkerDataflowBlockBase block = _dataflowBlocks.Find(b => b.ToString() == pendingImportResource.CurrentBlock);
                            if (block != null)
                            {
                                completeFirstBlockAfterTheseTasks.Add(block.SendAsync(pendingImportResource, _cts.Token));
                                numberOfRestoredPendingResources++;
                                if (block == _dataflowBlocks[0])
                                {
                                    firstBlockNeedsCompletion = false;
                                }
                            }
                            else
                            {
                                ServiceRegistration.Get <ILogger>().Error("ImporterWorker.{0}: Could not add {1} after deserialization. DataflowBlock with name {2} does not exist.", this, pendingImportResource, pendingImportResource.CurrentBlock);
                                pendingImportResource.Dispose();
                            }
                        }
                        ServiceRegistration.Get <ILogger>().Debug("ImporterWorker.{0}: {1} PendingImportResources restored.", this, numberOfRestoredPendingResources);
                    }
                    completeFirstBlockAfterTheseTasks.Add(_firstBlockHasFinished.Task);
                    if (firstBlockNeedsCompletion)
                    {
                        FirstBlockHasFinished();
                    }

                    // The first DataflowBlock in the network (DirectoryUnfoldBlock) must be set to completed when
                    // (a) The DirectoryUnfoldBlock has signaled that it is finished (by calling FirstBlockHasFinished()) and
                    // (b) in case of an ImportJob that has been restored from disk, all restored PendingImportResources
                    //     have been put into the Dataflow network
                    Task.WhenAll(completeFirstBlockAfterTheseTasks).ContinueWith(previousTask => _dataflowBlocks[0].Complete());
                }
            }
            catch (Exception e)
            {
                ServiceRegistration.Get <ILogger>().Error("ImporterWorker.{0}: Error while setting up DataflowBlocks for resource path '{1}.", e, this, _importJobInformation.BasePath);
            }
        }
示例#25
0
        public bool TryExtractMetadata(IResourceAccessor mediaItemAccessor, IDictionary <Guid, MediaItemAspect> extractedAspectData, bool forceQuickMode)
        {
            string fileName = mediaItemAccessor.ResourceName;

            if (!HasImageExtension(fileName))
            {
                return(false);
            }

            MediaItemAspect mediaAspect          = MediaItemAspect.GetOrCreateAspect(extractedAspectData, MediaAspect.Metadata);
            MediaItemAspect imageAspect          = MediaItemAspect.GetOrCreateAspect(extractedAspectData, ImageAspect.Metadata);
            MediaItemAspect thumbnailSmallAspect = MediaItemAspect.GetOrCreateAspect(extractedAspectData, ThumbnailSmallAspect.Metadata);
            MediaItemAspect thumbnailLargeAspect = MediaItemAspect.GetOrCreateAspect(extractedAspectData, ThumbnailLargeAspect.Metadata);

            try
            {
                // Open a stream for media item to detect mimeType.
                using (Stream mediaStream = mediaItemAccessor.OpenRead())
                {
                    string mimeType = MimeTypeDetector.GetMimeType(mediaStream);
                    if (mimeType != null)
                    {
                        mediaAspect.SetAttribute(MediaAspect.ATTR_MIME_TYPE, mimeType);
                    }
                }
                // Extract EXIF information from media item.
                using (ExifMetaInfo.ExifMetaInfo exif = new ExifMetaInfo.ExifMetaInfo(mediaItemAccessor))
                {
                    mediaAspect.SetAttribute(MediaAspect.ATTR_TITLE, ProviderPathHelper.GetFileNameWithoutExtension(fileName));
                    mediaAspect.SetAttribute(MediaAspect.ATTR_RECORDINGTIME, exif.OriginalDate != DateTime.MinValue ? exif.OriginalDate : mediaItemAccessor.LastChanged);
                    mediaAspect.SetAttribute(MediaAspect.ATTR_COMMENT, StringUtils.TrimToNull(exif.ImageDescription));

                    imageAspect.SetAttribute(ImageAspect.ATTR_WIDTH, (int)exif.PixXDim);
                    imageAspect.SetAttribute(ImageAspect.ATTR_HEIGHT, (int)exif.PixYDim);
                    imageAspect.SetAttribute(ImageAspect.ATTR_MAKE, StringUtils.TrimToNull(exif.EquipMake));
                    imageAspect.SetAttribute(ImageAspect.ATTR_MODEL, StringUtils.TrimToNull(exif.EquipModel));
                    imageAspect.SetAttribute(ImageAspect.ATTR_EXPOSURE_BIAS, ((double)exif.ExposureBias).ToString());
                    imageAspect.SetAttribute(ImageAspect.ATTR_EXPOSURE_TIME, exif.ExposureTime.ToString());
                    imageAspect.SetAttribute(ImageAspect.ATTR_FLASH_MODE, StringUtils.TrimToNull(exif.FlashMode));
                    imageAspect.SetAttribute(ImageAspect.ATTR_FNUMBER, string.Format("F {0}", (double)exif.FNumber));
                    imageAspect.SetAttribute(ImageAspect.ATTR_ISO_SPEED, StringUtils.TrimToNull(exif.ISOSpeed));
                    imageAspect.SetAttribute(ImageAspect.ATTR_ORIENTATION, (Int32)exif.Orientation);
                    imageAspect.SetAttribute(ImageAspect.ATTR_METERING_MODE, exif.MeteringMode.ToString());

                    IResourceAccessor        ra = mediaItemAccessor.Clone();
                    ILocalFsResourceAccessor lfsra;
                    try
                    {
                        lfsra = StreamedResourceToLocalFsAccessBridge.GetLocalFsResourceAccessor(ra);
                    }
                    catch
                    {
                        ra.Dispose();
                        throw;
                    }
                    using (lfsra)
                    {
                        string localFsResourcePath = lfsra.LocalFileSystemPath;
                        if (localFsResourcePath != null)
                        {
                            // In quick mode only allow thumbs taken from cache.
                            bool cachedOnly = forceQuickMode;

                            // Thumbnail extraction
                            IThumbnailGenerator generator = ServiceRegistration.Get <IThumbnailGenerator>();
                            byte[]    thumbData;
                            ImageType imageType;
                            if (generator.GetThumbnail(localFsResourcePath, 96, 96, cachedOnly, out thumbData, out imageType))
                            {
                                thumbnailSmallAspect.SetAttribute(ThumbnailSmallAspect.ATTR_THUMBNAIL, thumbData);
                            }
                            if (generator.GetThumbnail(localFsResourcePath, 256, 256, cachedOnly, out thumbData, out imageType))
                            {
                                thumbnailLargeAspect.SetAttribute(ThumbnailLargeAspect.ATTR_THUMBNAIL, thumbData);
                            }
                        }
                    }
                }
                return(true);
            }
            catch (Exception e)
            {
                // Only log at the info level here - And simply return false. This makes the importer know that we
                // couldn't perform our task here.
                ServiceRegistration.Get <ILogger>().Info("ImageMetadataExtractor: Exception reading resource '{0}' (Text: '{1}')", mediaItemAccessor.CanonicalLocalResourcePath, e.Message);
            }
            return(false);
        }