protected static bool CanExtract(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData, out IResourceAccessor metaFileAccessor)
        {
            metaFileAccessor = null;
            IFileSystemResourceAccessor fsra = mediaItemAccessor as IFileSystemResourceAccessor;

            if (fsra == null || !fsra.IsFile)
            {
                return(false);
            }

            string title;

            if (!MediaItemAspect.TryGetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, out title) || string.IsNullOrEmpty(title))
            {
                return(false);
            }

            string filePath       = mediaItemAccessor.CanonicalLocalResourcePath.ToString();
            string lowerExtension = StringUtils.TrimToEmpty(ProviderPathHelper.GetExtension(filePath)).ToLowerInvariant();

            if (lowerExtension != ".ts")
            {
                return(false);
            }
            string metaFilePath = ProviderPathHelper.ChangeExtension(filePath, ".arg");

            if (!ResourcePath.Deserialize(metaFilePath).TryCreateLocalResourceAccessor(out metaFileAccessor))
            {
                return(false);
            }
            return(true);
        }
Exemplo n.º 2
0
        public override void Update(MediaItem mediaItem)
        {
            base.Update(mediaItem);
            SingleMediaItemAspect imageAspect;

            if (MediaItemAspect.TryGetAspect(mediaItem.Aspects, ImageAspect.Metadata, out imageAspect))
            {
                SimpleTitle = Title;
                int?width  = (int?)imageAspect[ImageAspect.ATTR_WIDTH];
                int?height = (int?)imageAspect[ImageAspect.ATTR_HEIGHT];
                if (width.HasValue && width.Value > 0 && height.HasValue && height.Value > 0)
                {
                    Width  = width;
                    Height = height;
                    Size   = width + " x " + height;
                }
            }
            IList <MultipleMediaItemAspect> resourceAspects;

            if (MediaItemAspect.TryGetAspects(mediaItem.Aspects, ProviderResourceAspect.Metadata, out resourceAspects))
            {
                ResourcePath rp  = ResourcePath.Deserialize((string)resourceAspects[0][ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH]);
                string       ext = ProviderPathHelper.GetExtension(rp.FileName);
                if (ext.Length > 1)
                {
                    // remove leading '.'
                    ext = ext.Substring(1);
                }
                Extension = ext;
                MimeType  = (string)resourceAspects[0][ProviderResourceAspect.ATTR_MIME_TYPE];
            }
            FireChange();
        }
Exemplo n.º 3
0
        protected bool TryGetConfiguration(MediaItem mediaItem, out EmulatorConfiguration configuration)
        {
            configuration = null;
            List <string> mimeTypes;
            string        mimeType;

            if (mediaItem == null ||
                !MediaItemAspect.TryGetAttribute(mediaItem.Aspects, ProviderResourceAspect.ATTR_MIME_TYPE, out mimeTypes) ||
                string.IsNullOrEmpty(mimeType = mimeTypes.First()))
            {
                return(false);
            }

            List <string> paths;
            string        path;

            if (!MediaItemAspect.TryGetAttribute(mediaItem.Aspects, ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, out paths) ||
                string.IsNullOrEmpty(path = paths.First()))
            {
                return(false);
            }

            ResourcePath rp  = ResourcePath.Deserialize(path);
            string       ext = ProviderPathHelper.GetExtension(rp.FileName);

            return(ServiceRegistration.Get <IEmulatorManager>().TryGetConfiguration(mimeType, ext, out configuration));
        }
 public bool ResourceExists(string path)
 {
     if (string.IsNullOrEmpty(path))
     {
         return(false);
     }
     path = ProviderPathHelper.Combine(_path, path);
     return(_provider.IsResource(path));
 }
        public IFileSystemResourceAccessor GetResource(string path)
        {
            IResourceAccessor result;

            if (_provider.TryCreateResourceAccessor(ProviderPathHelper.Combine(_path, path), out result))
            {
                return((IFileSystemResourceAccessor)result);
            }
            return(null);
        }
        public IFileSystemResourceAccessor GetResource(string path)
        {
            IFileSystemResourceAccessor ra = (IFileSystemResourceAccessor)_mountingDataProxy.ResourceAccessor.Clone();

            try
            {
                return(GetLocalFsResourceAccessor(ra, ProviderPathHelper.Combine(_path, path)));
            }
            catch
            {
                ra.Dispose();
                throw;
            }
        }
        public static Type GetPlayerTypeForMediaItem(IResourceLocator locator, string mimeType)
        {
            Type playerType;

            // When a mimetype is set, try to get the player type for it
            if (mimeType != null && MIMETYPES2PLAYER.TryGetValue(mimeType.ToLowerInvariant(), out playerType))
            {
                return(playerType);
            }

            // 2nd chance: If no mimetype matches, try extension
            string path      = locator.NativeResourcePath.LastPathSegment.Path;
            string extension = StringUtils.TrimToEmpty(ProviderPathHelper.GetExtension(path)).ToLowerInvariant();

            if (EXTENSIONS2PLAYER.TryGetValue(extension, out playerType))
            {
                return(playerType);
            }
            return(null);
        }
Exemplo n.º 8
0
        protected static bool CanExtract(ILocalFsResourceAccessor lfsra, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData)
        {
            if (lfsra == null || !lfsra.IsFile)
            {
                return(false);
            }

            string title;

            if (!MediaItemAspect.TryGetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, out title) || string.IsNullOrEmpty(title))
            {
                return(false);
            }

            string filePath       = lfsra.CanonicalLocalResourcePath.ToString();
            string lowerExtension = StringUtils.TrimToEmpty(ProviderPathHelper.GetExtension(filePath)).ToLowerInvariant();

            if (lowerExtension != ".wtv" && lowerExtension != ".dvr-ms")
            {
                return(false);
            }
            return(true);
        }
Exemplo n.º 9
0
        public ImageItem(MediaItem mediaItem) : base(mediaItem)
        {
            MediaItemAspect imageAspect;

            if (mediaItem.Aspects.TryGetValue(ImageAspect.ASPECT_ID, out imageAspect))
            {
                SimpleTitle = Title;
                int?width  = (int?)imageAspect[ImageAspect.ATTR_WIDTH];
                int?height = (int?)imageAspect[ImageAspect.ATTR_HEIGHT];
                if (width.HasValue && width.Value > 0 && height.HasValue && height.Value > 0)
                {
                    Width  = width;
                    Height = height;
                    Size   = width + " x " + height;
                }
            }
            MediaItemAspect resourceAspect;

            if (mediaItem.Aspects.TryGetValue(ProviderResourceAspect.ASPECT_ID, out resourceAspect))
            {
                ResourcePath rp  = ResourcePath.Deserialize((string)resourceAspect[ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH]);
                string       ext = ProviderPathHelper.GetExtension(rp.FileName);
                if (ext.Length > 1)
                {
                    // remove leading '.'
                    ext = ext.Substring(1);
                }
                Extension = ext;
            }
            MediaItemAspect mediaAspect;

            if (mediaItem.Aspects.TryGetValue(MediaAspect.ASPECT_ID, out mediaAspect))
            {
                MimeType = (string)mediaAspect[MediaAspect.ATTR_MIME_TYPE];
            }
        }
Exemplo n.º 10
0
        protected static bool CanExtract(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData)
        {
            IFileSystemResourceAccessor fsra = mediaItemAccessor as IFileSystemResourceAccessor;

            if (fsra == null || !fsra.IsFile)
            {
                return(false);
            }

            string filePath       = mediaItemAccessor.CanonicalLocalResourcePath.ToString();
            string lowerExtension = StringUtils.TrimToEmpty(ProviderPathHelper.GetExtension(filePath)).ToLowerInvariant();

            if (lowerExtension != ".ts")
            {
                return(false);
            }
            string metaFilePath = ProviderPathHelper.ChangeExtension(filePath, ".xml");

            if (!ResourcePath.Deserialize(metaFilePath).TryCreateLocalResourceAccessor(out _))
            {
                return(false);
            }
            return(true);
        }
Exemplo n.º 11
0
        public bool TryExtractMetadata(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData, bool importOnly, bool forceQuickMode)
        {
            IFileSystemResourceAccessor fsra = mediaItemAccessor as IFileSystemResourceAccessor;

            if (fsra == null || !fsra.IsFile)
            {
                return(false);
            }
            if (extractedAspectData.ContainsKey(AudioAspect.ASPECT_ID))
            {
                return(false);
            }

            try
            {
                var extension = DosPathHelper.GetExtension(fsra.ResourceName).ToLowerInvariant();
                if (extension != ".ts")
                {
                    return(false);
                }

                using (MediaInfoWrapper mediaInfo = ReadMediaInfo(fsra))
                {
                    // Before we start evaluating the file, check if it is not a video file (
                    if (mediaInfo.IsValid && (mediaInfo.GetVideoCount() != 0 || mediaInfo.GetAudioCount() == 0))
                    {
                        return(false);
                    }
                    string fileName = ProviderPathHelper.GetFileNameWithoutExtension(fsra.Path) ?? string.Empty;
                    MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, fileName);
                    MultipleMediaItemAspect providerResourceAspect = MediaItemAspect.CreateAspect(extractedAspectData, ProviderResourceAspect.Metadata);
                    providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_SIZE, fsra.Size);
                    providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, "slimtv/radio");

                    var audioBitrate = mediaInfo.GetAudioBitrate(0);
                    if (audioBitrate.HasValue)
                    {
                        MediaItemAspect.SetAttribute(extractedAspectData, AudioAspect.ATTR_BITRATE, (int)(audioBitrate.Value / 1000)); // We store kbit/s;
                    }
                    var audioChannels = mediaInfo.GetAudioChannels(0);
                    if (audioChannels.HasValue)
                    {
                        MediaItemAspect.SetAttribute(extractedAspectData, AudioAspect.ATTR_CHANNELS, audioChannels.Value);
                    }
                    var audioSampleRate = mediaInfo.GetAudioSampleRate(0);
                    if (audioSampleRate.HasValue)
                    {
                        MediaItemAspect.SetAttribute(extractedAspectData, AudioAspect.ATTR_SAMPLERATE, audioSampleRate.Value);
                    }

                    MediaItemAspect.SetAttribute(extractedAspectData, AudioAspect.ATTR_ENCODING, mediaInfo.GetAudioCodec(0));
                    // MediaInfo returns milliseconds, we need seconds
                    long?time = mediaInfo.GetPlaytime(0);
                    if (time.HasValue && time > 1000)
                    {
                        MediaItemAspect.SetAttribute(extractedAspectData, AudioAspect.ATTR_DURATION, time.Value / 1000);
                    }
                }
                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("RadioRecordingMetadataExtractor: Exception reading resource '{0}' (Text: '{1}')", fsra.CanonicalLocalResourcePath, e.Message);
                return(false);
            }
        }
Exemplo n.º 12
0
        public bool TryExtractMetadata(IResourceAccessor mediaItemAccessor, IDictionary <Guid, MediaItemAspect> extractedAspectData, bool forceQuickMode)
        {
            IFileSystemResourceAccessor fsra = mediaItemAccessor as IFileSystemResourceAccessor;

            if (fsra == null)
            {
                return(false);
            }
            if (!fsra.IsFile)
            {
                return(false);
            }
            string fileName = fsra.ResourceName;

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

            try
            {
                File tag;
                try
                {
                    ByteVector.UseBrokenLatin1Behavior = true; // Otherwise we have problems retrieving non-latin1 chars
                    tag = File.Create(new ResourceProviderFileAbstraction(fsra));
                }
                catch (CorruptFileException)
                {
                    // 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("AudioMetadataExtractor: Audio file '{0}' seems to be broken", fsra.CanonicalLocalResourcePath);
                    return(false);
                }

                // Some file extensions like .mp4 can contain audio and video. Do not handle files with video content here.
                if (tag.Properties.VideoHeight > 0 && tag.Properties.VideoWidth > 0)
                {
                    return(false);
                }

                fileName = ProviderPathHelper.GetFileNameWithoutExtension(fileName) ?? string.Empty;
                string title;
                string artist;
                uint?  trackNo;
                GuessMetadataFromFileName(fileName, out title, out artist, out trackNo);
                if (!string.IsNullOrEmpty(tag.Tag.Title))
                {
                    title = tag.Tag.Title;
                }
                IEnumerable <string> artists;
                if (tag.Tag.Performers.Length > 0)
                {
                    artists = tag.Tag.Performers;
                    if ((tag.TagTypes & TagTypes.Id3v2) != 0)
                    {
                        artists = PatchID3v23Enumeration(artists);
                    }
                }
                else
                {
                    artists = artist == null ? null : new string[] { artist }
                };
                if (tag.Tag.Track != 0)
                {
                    trackNo = tag.Tag.Track;
                }
                MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, title);
                MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_SIZE, fsra.Size);
                // FIXME Albert: tag.MimeType returns taglib/mp3 for an MP3 file. This is not what we want and collides with the
                // mimetype handling in the BASS player, which expects audio/xxx.
                if (!string.IsNullOrWhiteSpace(tag.MimeType))
                {
                    MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_MIME_TYPE, tag.MimeType.Replace("taglib/", "audio/"));
                }

                MediaItemAspect.SetCollectionAttribute(extractedAspectData, AudioAspect.ATTR_ARTISTS, ApplyAdditionalSeparator(artists));
                MediaItemAspect.SetAttribute(extractedAspectData, AudioAspect.ATTR_ALBUM, StringUtils.TrimToNull(tag.Tag.Album));
                IEnumerable <string> albumArtists = tag.Tag.AlbumArtists;
                if ((tag.TagTypes & TagTypes.Id3v2) != 0)
                {
                    albumArtists = PatchID3v23Enumeration(albumArtists);
                }
                MediaItemAspect.SetCollectionAttribute(extractedAspectData, AudioAspect.ATTR_ALBUMARTISTS, ApplyAdditionalSeparator(albumArtists));
                MediaItemAspect.SetAttribute(extractedAspectData, AudioAspect.ATTR_BITRATE, tag.Properties.AudioBitrate);
                MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_COMMENT, StringUtils.TrimToNull(tag.Tag.Comment));
                IEnumerable <string> composers = tag.Tag.Composers;
                if ((tag.TagTypes & TagTypes.Id3v2) != 0)
                {
                    composers = PatchID3v23Enumeration(composers);
                }
                MediaItemAspect.SetCollectionAttribute(extractedAspectData, AudioAspect.ATTR_COMPOSERS, ApplyAdditionalSeparator(composers));

                MediaItemAspect.SetAttribute(extractedAspectData, AudioAspect.ATTR_DURATION, (long)tag.Properties.Duration.TotalSeconds);
                if (tag.Tag.Genres.Length > 0)
                {
                    IEnumerable <string> genres = tag.Tag.Genres;
                    if ((tag.TagTypes & TagTypes.Id3v2) != 0)
                    {
                        genres = PatchID3v23Enumeration(genres);
                    }
                    MediaItemAspect.SetCollectionAttribute(extractedAspectData, AudioAspect.ATTR_GENRES, ApplyAdditionalSeparator(genres));
                }
                if (trackNo.HasValue)
                {
                    MediaItemAspect.SetAttribute(extractedAspectData, AudioAspect.ATTR_TRACK, (int)trackNo.Value);
                }
                if (tag.Tag.TrackCount != 0)
                {
                    MediaItemAspect.SetAttribute(extractedAspectData, AudioAspect.ATTR_NUMTRACKS, (int)tag.Tag.TrackCount);
                }
                int year = (int)tag.Tag.Year;
                if (year >= 30 && year <= 99)
                {
                    year += 1900;
                }
                if (year >= 1930 && year <= 2030)
                {
                    MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_RECORDINGTIME, new DateTime(year, 1, 1));
                }


                // The following code gets cover art images from file (embedded) or from windows explorer cache (supports folder.jpg).
                IPicture[] pics = tag.Tag.Pictures;
                if (pics.Length > 0)
                {
                    try
                    {
                        using (MemoryStream stream = new MemoryStream(pics[0].Data.Data))
                            using (MemoryStream resized = (MemoryStream)ImageUtilities.ResizeImage(stream, ImageFormat.Jpeg, MAX_COVER_WIDTH, MAX_COVER_HEIGHT))
                            {
                                MediaItemAspect.SetAttribute(extractedAspectData, ThumbnailLargeAspect.ATTR_THUMBNAIL, resized.ToArray());
                            }
                    }
                    // Decoding of invalid image data can fail, but main MediaItem is correct.
                    catch { }
                }
                else
                {
                    // In quick mode only allow thumbs taken from cache.
                    bool cachedOnly = forceQuickMode;

                    // Thumbnail extraction
                    fileName = mediaItemAccessor.ResourcePathName;
                    IThumbnailGenerator generator = ServiceRegistration.Get <IThumbnailGenerator>();
                    byte[]    thumbData;
                    ImageType imageType;
                    if (generator.GetThumbnail(fileName, 256, 256, cachedOnly, out thumbData, out imageType))
                    {
                        MediaItemAspect.SetAttribute(extractedAspectData, ThumbnailLargeAspect.ATTR_THUMBNAIL, thumbData);
                    }
                }
                return(true);
            }
            catch (UnsupportedFormatException)
            {
                ServiceRegistration.Get <ILogger>().Info("AudioMetadataExtractor: Unsupported audio file '{0}'", fsra.CanonicalLocalResourcePath);
                return(false);
            }
            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("AudioMetadataExtractor: Exception reading resource '{0}' (Text: '{1}')", fsra.CanonicalLocalResourcePath, e.Message);
            }
            return(false);
        }
        protected ICollection <IFileSystemResourceAccessor> CreateChildResourceAccessors(IEnumerable <string> namesWithPathPrefix, bool isDirectory)
        {
            string rootPath = StringUtils.CheckSuffix(_path, "/");

            return(namesWithPathPrefix.Select(filePath => new StreamedResourceToLocalFsAccessBridge(_mountingDataProxy,
                                                                                                    rootPath + ProviderPathHelper.GetFileName(filePath) + (isDirectory ? "/" : string.Empty))).Cast <IFileSystemResourceAccessor>().ToList());
        }
Exemplo n.º 14
0
 protected string ExpandPath(string relativeOrAbsoluteProviderPath)
 {
     return(ProviderPathHelper.Combine(_pathToDirOrFile, relativeOrAbsoluteProviderPath));
 }
Exemplo n.º 15
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
            {
                if (!(mediaItemAccessor is IFileSystemResourceAccessor))
                {
                    return(false);
                }
                IFileSystemResourceAccessor fsra = mediaItemAccessor as IFileSystemResourceAccessor;
                // Open a stream for media item to detect mimeType.
                using (Stream mediaStream = fsra.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(fsra))
                {
                    mediaAspect.SetAttribute(MediaAspect.ATTR_TITLE, ProviderPathHelper.GetFileNameWithoutExtension(fileName));
                    mediaAspect.SetAttribute(MediaAspect.ATTR_RECORDINGTIME, exif.OriginalDate != DateTime.MinValue ? exif.OriginalDate : fsra.LastChanged);
                    mediaAspect.SetAttribute(MediaAspect.ATTR_COMMENT, StringUtils.TrimToNull(exif.ImageDescription));

                    if (exif.PixXDim.HasValue)
                    {
                        imageAspect.SetAttribute(ImageAspect.ATTR_WIDTH, (int)exif.PixXDim);
                    }
                    if (exif.PixYDim.HasValue)
                    {
                        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));
                    if (exif.ExposureBias.HasValue)
                    {
                        imageAspect.SetAttribute(ImageAspect.ATTR_EXPOSURE_BIAS, ((double)exif.ExposureBias).ToString());
                    }
                    imageAspect.SetAttribute(ImageAspect.ATTR_EXPOSURE_TIME, exif.ExposureTime);
                    imageAspect.SetAttribute(ImageAspect.ATTR_FLASH_MODE, StringUtils.TrimToNull(exif.FlashMode));
                    if (exif.FNumber.HasValue)
                    {
                        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.OrientationType ?? 0));
                    imageAspect.SetAttribute(ImageAspect.ATTR_METERING_MODE, exif.MeteringMode.ToString());

                    if (exif.Latitude.HasValue && exif.Longitude.HasValue)
                    {
                        imageAspect.SetAttribute(ImageAspect.ATTR_LATITUDE, exif.Latitude);
                        imageAspect.SetAttribute(ImageAspect.ATTR_LONGITUDE, exif.Longitude);

                        LocationInfo locationInfo;
                        if (!forceQuickMode && GeoLocationMatcher.Instance.TryLookup(exif.Latitude.Value, exif.Longitude.Value, out locationInfo))
                        {
                            imageAspect.SetAttribute(ImageAspect.ATTR_CITY, locationInfo.City);
                            imageAspect.SetAttribute(ImageAspect.ATTR_STATE, locationInfo.State);
                            imageAspect.SetAttribute(ImageAspect.ATTR_COUNTRY, locationInfo.Country);
                        }
                    }

                    using (ILocalFsResourceAccessor lfsra = StreamedResourceToLocalFsAccessBridge.GetLocalFsResourceAccessor((IFileSystemResourceAccessor)fsra.Clone()))
                    {
                        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);
        }
Exemplo n.º 16
0
        public override bool TryExtractMetadata(IResourceAccessor mediaItemAccessor, IDictionary <Guid, MediaItemAspect> extractedAspectData, bool forceQuickMode)
        {
            // If the base AudioMDE already extracted metadata, don't try here again to avoid conflicts.
            if (extractedAspectData.ContainsKey(AudioAspect.ASPECT_ID))
            {
                return(false);
            }

            ILocalFsResourceAccessor fsra = mediaItemAccessor as ILocalFsResourceAccessor;

            if (fsra == null)
            {
                return(false);
            }
            if (!fsra.IsFile)
            {
                return(false);
            }
            string fileName = fsra.ResourceName;

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

            try
            {
                TAG_INFO tags;
                using (fsra.EnsureLocalFileSystemAccess())
                    tags = BassTags.BASS_TAG_GetFromFile(fsra.LocalFileSystemPath);
                if (tags == null)
                {
                    return(false);
                }

                fileName = ProviderPathHelper.GetFileNameWithoutExtension(fileName) ?? string.Empty;
                string title;
                string artist;
                uint?  trackNo;
                GuessMetadataFromFileName(fileName, out title, out artist, out trackNo);
                if (!string.IsNullOrWhiteSpace(tags.title))
                {
                    title = tags.title;
                }
                IEnumerable <string> artists;
                if (!string.IsNullOrWhiteSpace(tags.artist))
                {
                    artists = SplitTagEnum(tags.artist);
                    artists = PatchID3v23Enumeration(artists);
                }
                else
                {
                    artists = artist == null ? null : new string[] { artist }
                };
                if (!string.IsNullOrWhiteSpace(tags.track) && tags.track != "0")
                {
                    int iTrackNo;
                    if (int.TryParse(tags.track, out iTrackNo))
                    {
                        trackNo = (uint?)iTrackNo;
                    }
                    else
                    {
                        trackNo = null;
                    }
                }

                MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, title);
                MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_SIZE, fsra.Size);
                // Calling EnsureLocalFileSystemAccess not necessary; only string operation
                MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_MIME_TYPE, "audio/" + Path.GetExtension(fsra.LocalFileSystemPath).Substring(1));
                MediaItemAspect.SetCollectionAttribute(extractedAspectData, AudioAspect.ATTR_ARTISTS, ApplyAdditionalSeparator(artists));
                MediaItemAspect.SetAttribute(extractedAspectData, AudioAspect.ATTR_ALBUM, StringUtils.TrimToNull(tags.album));
                IEnumerable <string> albumArtists = SplitTagEnum(tags.albumartist);
                albumArtists = PatchID3v23Enumeration(albumArtists);

                MediaItemAspect.SetCollectionAttribute(extractedAspectData, AudioAspect.ATTR_ALBUMARTISTS, ApplyAdditionalSeparator(albumArtists));
                MediaItemAspect.SetAttribute(extractedAspectData, AudioAspect.ATTR_BITRATE, tags.bitrate);
                MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_COMMENT, StringUtils.TrimToNull(tags.comment));
                IEnumerable <string> composers = SplitTagEnum(tags.composer);
                composers = PatchID3v23Enumeration(composers);
                MediaItemAspect.SetCollectionAttribute(extractedAspectData, AudioAspect.ATTR_COMPOSERS, ApplyAdditionalSeparator(composers));

                MediaItemAspect.SetAttribute(extractedAspectData, AudioAspect.ATTR_DURATION, (long)tags.duration);

                IEnumerable <string> genres = SplitTagEnum(tags.genre);
                genres = PatchID3v23Enumeration(genres);
                MediaItemAspect.SetCollectionAttribute(extractedAspectData, AudioAspect.ATTR_GENRES, ApplyAdditionalSeparator(genres));

                if (trackNo.HasValue)
                {
                    MediaItemAspect.SetAttribute(extractedAspectData, AudioAspect.ATTR_TRACK, (int)trackNo.Value);
                }

                int year;
                if (int.TryParse(tags.year, out year))
                {
                    if (year >= 30 && year <= 99)
                    {
                        year += 1900;
                    }
                    if (year >= 1930 && year <= 2030)
                    {
                        MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_RECORDINGTIME, new DateTime(year, 1, 1));
                    }
                }

                // The following code gets cover art images from file (embedded) or from windows explorer cache (supports folder.jpg).
                if (tags.PictureCount > 0)
                {
                    try
                    {
                        using (Image cover = tags.PictureGetImage(0))
                            using (Image resized = ImageUtilities.ResizeImage(cover, MAX_COVER_WIDTH, MAX_COVER_HEIGHT))
                                using (MemoryStream result = new MemoryStream())
                                {
                                    resized.Save(result, ImageFormat.Jpeg);
                                    MediaItemAspect.SetAttribute(extractedAspectData, ThumbnailLargeAspect.ATTR_THUMBNAIL, result.ToArray());
                                }
                    }
                    // Decoding of invalid image data can fail, but main MediaItem is correct.
                    catch { }
                }
                else
                {
                    // In quick mode only allow thumbs taken from cache.
                    bool cachedOnly = forceQuickMode;

                    // Thumbnail extraction
                    fileName = mediaItemAccessor.ResourcePathName;
                    IThumbnailGenerator generator = ServiceRegistration.Get <IThumbnailGenerator>();
                    byte[]    thumbData;
                    ImageType imageType;
                    if (generator.GetThumbnail(fileName, cachedOnly, out thumbData, out imageType))
                    {
                        MediaItemAspect.SetAttribute(extractedAspectData, 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("BassAudioMetadataExtractor: Exception reading resource '{0}' (Text: '{1}')", fsra.CanonicalLocalResourcePath, e.Message);
            }
            return(false);
        }
Exemplo n.º 17
0
        public bool TryExtractMetadata(IResourceAccessor mediaItemAccessor, IDictionary <Guid, MediaItemAspect> extractedAspectData, bool forceQuickMode)
        {
            try
            {
                IFileSystemResourceAccessor fsra = mediaItemAccessor as IFileSystemResourceAccessor;
                if (fsra == null || !mediaItemAccessor.IsFile)
                {
                    return(false);
                }

                string filePath       = mediaItemAccessor.CanonicalLocalResourcePath.ToString();
                string lowerExtension = StringUtils.TrimToEmpty(ProviderPathHelper.GetExtension(filePath)).ToLowerInvariant();
                if (lowerExtension != ".ts")
                {
                    return(false);
                }
                string            metaFilePath = ProviderPathHelper.ChangeExtension(filePath, ".xml");
                IResourceAccessor metaFileAccessor;
                if (!ResourcePath.Deserialize(metaFilePath).TryCreateLocalResourceAccessor(out metaFileAccessor))
                {
                    return(false);
                }

                Tags tags;
                using (metaFileAccessor)
                {
                    using (Stream metaStream = metaFileAccessor.OpenRead())
                        tags = (Tags)GetTagsXmlSerializer().Deserialize(metaStream);
                }

                MediaItemAspect mediaAspect     = MediaItemAspect.GetOrCreateAspect(extractedAspectData, MediaAspect.Metadata);
                MediaItemAspect videoAspect     = MediaItemAspect.GetOrCreateAspect(extractedAspectData, VideoAspect.Metadata);
                MediaItemAspect recordingAspect = MediaItemAspect.GetOrCreateAspect(extractedAspectData, RecordingAspect.Metadata);

                // Handle series information
                SeriesInfo seriesInfo = GetSeriesFromTags(tags);
                if (seriesInfo.IsCompleteMatch)
                {
                    if (!forceQuickMode)
                    {
                        SeriesTvDbMatcher.Instance.FindAndUpdateSeries(seriesInfo);
                    }

                    seriesInfo.SetMetadata(extractedAspectData);
                }

                string value;
                if (TryGet(tags, TAG_TITLE, out value) && !string.IsNullOrEmpty(value))
                {
                    mediaAspect.SetAttribute(MediaAspect.ATTR_TITLE, value);
                }

                if (TryGet(tags, TAG_GENRE, out value))
                {
                    videoAspect.SetCollectionAttribute(VideoAspect.ATTR_GENRES, new List <String> {
                        value
                    });
                }

                if (TryGet(tags, TAG_PLOT, out value))
                {
                    videoAspect.SetAttribute(VideoAspect.ATTR_STORYPLOT, value);
                    Match yearMatch = _yearMatcher.Match(value);
                    int   guessedYear;
                    if (int.TryParse(yearMatch.Value, out guessedYear))
                    {
                        MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_RECORDINGTIME, new DateTime(guessedYear, 1, 1));
                    }
                }

                if (TryGet(tags, TAG_CHANNEL, out value))
                {
                    recordingAspect.SetAttribute(RecordingAspect.ATTR_CHANNEL, value);
                }

                // Recording date formatted: 2011-11-04 20:55
                DateTime recordingStart;
                DateTime recordingEnd;
                if (TryGet(tags, TAG_STARTTIME, out value) && DateTime.TryParse(value, out recordingStart))
                {
                    recordingAspect.SetAttribute(RecordingAspect.ATTR_STARTTIME, recordingStart);
                }

                if (TryGet(tags, TAG_ENDTIME, out value) && DateTime.TryParse(value, out recordingEnd))
                {
                    recordingAspect.SetAttribute(RecordingAspect.ATTR_ENDTIME, recordingEnd);
                }

                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("Tve3RecordingMetadataExtractor: Exception reading resource '{0}' (Text: '{1}')", mediaItemAccessor.CanonicalLocalResourcePath, e.Message);
            }
            return(false);
        }
        private bool ExtractMetadata(ILocalFsResourceAccessor lfsra, IDictionary <Guid, MediaItemAspect> extractedAspectData, bool forceQuickMode)
        {
            if (lfsra == null || !lfsra.IsFile)
            {
                return(false);
            }

            string title;

            if (!MediaItemAspect.TryGetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, out title) || string.IsNullOrEmpty(title))
            {
                return(false);
            }

            string filePath       = lfsra.CanonicalLocalResourcePath.ToString();
            string lowerExtension = StringUtils.TrimToEmpty(ProviderPathHelper.GetExtension(filePath)).ToLowerInvariant();

            if (lowerExtension != ".wtv" && lowerExtension != ".dvr-ms")
            {
                return(false);
            }

            using (var rec = new MCRecMetadataEditor(lfsra.LocalFileSystemPath))
            {
                // Handle series information
                IDictionary tags       = rec.GetAttributes();
                SeriesInfo  seriesInfo = GetSeriesFromTags(tags);

                if (!forceQuickMode)
                {
                    if (SeriesTvDbMatcher.Instance.FindAndUpdateSeries(seriesInfo))
                    {
                        seriesInfo.SetMetadata(extractedAspectData);
                    }
                }

                // Force MimeType
                MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_MIME_TYPE, "slimtv/wtv");

                string value;
                if (TryGet(tags, TAG_TITLE, out value) && !string.IsNullOrEmpty(value))
                {
                    MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, value);
                }

                if (TryGet(tags, TAG_GENRE, out value))
                {
                    MediaItemAspect.SetCollectionAttribute(extractedAspectData, VideoAspect.ATTR_GENRES, new List <String>(value.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries)));
                }

                if (TryGet(tags, TAG_PLOT, out value))
                {
                    MediaItemAspect.SetAttribute(extractedAspectData, VideoAspect.ATTR_STORYPLOT, value);
                }

                if (TryGet(tags, TAG_ORIGINAL_TIME, out value))
                {
                    DateTime origTime;
                    if (DateTime.TryParse(value, out origTime))
                    {
                        MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_RECORDINGTIME, origTime);
                    }
                }

                if (TryGet(tags, TAG_CHANNEL, out value))
                {
                    MediaItemAspect.SetAttribute(extractedAspectData, RecordingAspect.ATTR_CHANNEL, value);
                }

                long lValue;
                if (TryGet(tags, TAG_STARTTIME, out lValue))
                {
                    MediaItemAspect.SetAttribute(extractedAspectData, RecordingAspect.ATTR_STARTTIME, FromMCEFileTime(lValue));
                }
                if (TryGet(tags, TAG_ENDTIME, out lValue))
                {
                    MediaItemAspect.SetAttribute(extractedAspectData, RecordingAspect.ATTR_ENDTIME, FromMCEFileTime(lValue));
                }
            }
            return(true);
        }
Exemplo n.º 19
0
        public override async Task <AsyncResult <ContentDirectoryMessaging.MediaItemChangeType> > ProcessAsync(MediaItem mediaItem)
        {
            IContentDirectory cd = ServiceRegistration.Get <IServerConnectionManager>().ContentDirectory;
            bool removeFromML    = IsManagedByMediaLibrary(mediaItem) && cd != null;

            var falseResult = new AsyncResult <ContentDirectoryMessaging.MediaItemChangeType>(false, ContentDirectoryMessaging.MediaItemChangeType.None);

            // Support multi-resource media items and secondary resources
            IList <MultipleMediaItemAspect> providerAspects;

            if (!MediaItemAspect.TryGetAspects(mediaItem.Aspects, ProviderResourceAspect.Metadata, out providerAspects))
            {
                return(falseResult);
            }

            foreach (MultipleMediaItemAspect providerAspect in providerAspects)
            {
                string systemId             = (string)providerAspect[ProviderResourceAspect.ATTR_SYSTEM_ID];
                string resourceAccessorPath = (string)providerAspect[ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH];
                var    rl = new ResourceLocator(systemId, ResourcePath.Deserialize(resourceAccessorPath));
                using (var ra = rl.CreateAccessor())
                {
                    var rad = ra as IResourceDeletor;
                    if (rad == null)
                    {
                        return(falseResult);
                    }

                    // First try to delete the file from storage.
                    if (!rad.Delete())
                    {
                        return(falseResult);
                    }

                    // If the MediaItem was loaded from ML, remove it there as well.
                    if (removeFromML)
                    {
                        await cd.DeleteMediaItemOrPathAsync(rl.NativeSystemId, rl.NativeResourcePath, true);
                    }
                }
            }

            // Check for special cases here:
            // 1) Recordings have an additional .xml attached
            // 2) Deleting files could lead to empty folders that should be also removed
            foreach (DeleteRule rule in _defaultRules.Where(r => r.IsEnabled))
            {
                if (mediaItem.Aspects.ContainsKey(rule.HasAspectGuid))
                {
                    var tsPath = mediaItem.GetResourceLocator().NativeResourcePath.ToString();
                    foreach (string otherExtension in rule.DeleteOtherExtensions)
                    {
                        string            otherFilePath = ProviderPathHelper.ChangeExtension(tsPath, otherExtension);
                        IResourceAccessor ra;
                        if (!ResourcePath.Deserialize(otherFilePath).TryCreateLocalResourceAccessor(out ra))
                        {
                            continue;
                        }

                        // Delete other file. We do not check here for existance of file, the Delete needs to handle this.
                        using (ra)
                        {
                            var rad = ra as IResourceDeletor;
                            rad?.Delete();
                        }
                    }

                    if (rule.DeleteEmptyFolders)
                    {
                        var folderPath = ProviderPathHelper.GetDirectoryName(tsPath);
                        IResourceAccessor ra;
                        if (!ResourcePath.Deserialize(folderPath).TryCreateLocalResourceAccessor(out ra))
                        {
                            continue;
                        }

                        // Delete folder if empty
                        using (ra)
                        {
                            IFileSystemResourceAccessor fsra = ra as IFileSystemResourceAccessor;
                            if (fsra != null)
                            {
                                var isEmpty = fsra.GetFiles().Count == 0 && fsra.GetChildDirectories().Count == 0;
                                if (isEmpty)
                                {
                                    var rad = ra as IResourceDeletor;
                                    rad?.Delete();
                                }
                            }
                        }
                    }
                }
            }

            return(new AsyncResult <ContentDirectoryMessaging.MediaItemChangeType>(true, ContentDirectoryMessaging.MediaItemChangeType.Deleted));
        }
        public override async Task <bool> TryExtractMetadataAsync(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData, bool forceQuickMode)
        {
            // If the base AudioMDE already extracted metadata, don't try here again to avoid conflicts.
            if (extractedAspectData.ContainsKey(AudioAspect.ASPECT_ID))
            {
                return(false);
            }

            ILocalFsResourceAccessor fsra = mediaItemAccessor as ILocalFsResourceAccessor;

            if (fsra == null)
            {
                return(false);
            }
            if (!fsra.IsFile)
            {
                return(false);
            }
            string fileName = fsra.ResourceName;

            if (!HasAudioExtension(fileName))
            {
                return(false);
            }
            if (extractedAspectData.ContainsKey(ReimportAspect.ASPECT_ID)) //Ignore for reimports because the tags might be the cause of the wrong match
            {
                return(false);
            }

            try
            {
                TAG_INFO tags;
                using (fsra.EnsureLocalFileSystemAccess())
                    tags = BassTags.BASS_TAG_GetFromFile(fsra.LocalFileSystemPath);
                if (tags == null)
                {
                    return(false);
                }

                fileName = ProviderPathHelper.GetFileNameWithoutExtension(fileName) ?? string.Empty;
                string title;
                string artist;
                uint?  trackNo;
                GuessMetadataFromFileName(fileName, out title, out artist, out trackNo);
                if (!string.IsNullOrWhiteSpace(tags.title))
                {
                    title = tags.title;
                }
                IEnumerable <string> artists;
                if (!string.IsNullOrWhiteSpace(tags.artist))
                {
                    artists = SplitTagEnum(tags.artist);
                    artists = PatchID3v23Enumeration(artists);
                }
                else
                {
                    artists = artist == null ? null : new string[] { artist }
                };
                if (!string.IsNullOrWhiteSpace(tags.track) && tags.track != "0")
                {
                    int iTrackNo;
                    if (int.TryParse(tags.track, out iTrackNo))
                    {
                        trackNo = (uint?)iTrackNo;
                    }
                    else
                    {
                        trackNo = null;
                    }
                }

                TrackInfo trackInfo = new TrackInfo();
                if (extractedAspectData.ContainsKey(AudioAspect.ASPECT_ID))
                {
                    trackInfo.FromMetadata(extractedAspectData);
                }
                else
                {
                    MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, title);
                    IList <MultipleMediaItemAspect> providerResourceAspect;
                    if (MediaItemAspect.TryGetAspects(extractedAspectData, ProviderResourceAspect.Metadata, out providerResourceAspect))
                    {
                        providerResourceAspect[0].SetAttribute(ProviderResourceAspect.ATTR_SIZE, fsra.Size);
                        // Calling EnsureLocalFileSystemAccess not necessary; only string operation
                        providerResourceAspect[0].SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, "audio/" + Path.GetExtension(fsra.LocalFileSystemPath).Substring(1));
                    }
                    MediaItemAspect.SetAttribute(extractedAspectData, AudioAspect.ATTR_BITRATE, tags.bitrate);
                    MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_COMMENT, StringUtils.TrimToNull(tags.comment));
                    MediaItemAspect.SetAttribute(extractedAspectData, AudioAspect.ATTR_DURATION, (long)tags.duration);
                }

                if (!trackInfo.IsBaseInfoPresent)
                {
                    trackInfo.TrackName = title;
                    trackInfo.Album     = StringUtils.TrimToNull(tags.album);
                    if (trackNo.HasValue)
                    {
                        trackInfo.TrackNum = (int)trackNo.Value;
                    }

                    trackInfo.Artists = new List <PersonInfo>();
                    foreach (string artistName in ApplyAdditionalSeparator(artists))
                    {
                        trackInfo.Artists.Add(new PersonInfo()
                        {
                            Name            = artistName,
                            Occupation      = PersonAspect.OCCUPATION_ARTIST,
                            ParentMediaName = trackInfo.Album,
                            MediaName       = trackInfo.TrackName
                        });
                    }

                    IEnumerable <string> albumArtists = SplitTagEnum(tags.albumartist);
                    albumArtists           = PatchID3v23Enumeration(albumArtists);
                    trackInfo.AlbumArtists = new List <PersonInfo>();
                    foreach (string artistName in ApplyAdditionalSeparator(albumArtists))
                    {
                        trackInfo.AlbumArtists.Add(new PersonInfo()
                        {
                            Name            = artistName,
                            Occupation      = PersonAspect.OCCUPATION_ARTIST,
                            ParentMediaName = trackInfo.Album,
                            MediaName       = trackInfo.TrackName
                        });
                    }

                    IEnumerable <string> composers = SplitTagEnum(tags.composer);
                    composers           = PatchID3v23Enumeration(composers);
                    trackInfo.Composers = new List <PersonInfo>();
                    foreach (string composerName in ApplyAdditionalSeparator(composers))
                    {
                        trackInfo.Composers.Add(new PersonInfo()
                        {
                            Name            = composerName,
                            Occupation      = PersonAspect.OCCUPATION_COMPOSER,
                            ParentMediaName = trackInfo.Album,
                            MediaName       = trackInfo.TrackName
                        });
                    }

                    IEnumerable <string> genres = SplitTagEnum(tags.genre);
                    genres           = PatchID3v23Enumeration(genres);
                    trackInfo.Genres = ApplyAdditionalSeparator(genres).Where(s => !string.IsNullOrEmpty(s?.Trim())).Select(s => new GenreInfo {
                        Name = s.Trim()
                    }).ToList();
                    IGenreConverter converter = ServiceRegistration.Get <IGenreConverter>();
                    foreach (var genre in trackInfo.Genres)
                    {
                        if (!genre.Id.HasValue && converter.GetGenreId(genre.Name, GenreCategory.Music, null, out int genreId))
                        {
                            genre.Id = genreId;
                        }
                    }

                    int year;
                    if (int.TryParse(tags.year, out year))
                    {
                        if (year >= 30 && year <= 99)
                        {
                            year += 1900;
                        }
                        if (year >= 1930 && year <= 2030)
                        {
                            trackInfo.ReleaseDate = new DateTime(year, 1, 1);
                        }
                    }

                    if (!trackInfo.HasThumbnail)
                    {
                        // The following code gets cover art images from file (embedded) or from windows explorer cache (supports folder.jpg).
                        if (tags.PictureCount > 0)
                        {
                            try
                            {
                                using (Image cover = tags.PictureGetImage(0))
                                    using (MemoryStream result = new MemoryStream())
                                    {
                                        cover.Save(result, ImageFormat.Jpeg);
                                        trackInfo.Thumbnail  = result.ToArray();
                                        trackInfo.HasChanged = true;
                                    }
                            }
                            // Decoding of invalid image data can fail, but main MediaItem is correct.
                            catch { }
                        }
                    }
                }

                if (!SkipOnlineSearches && !forceQuickMode)
                {
                    await OnlineMatcherService.Instance.FindAndUpdateTrackAsync(trackInfo).ConfigureAwait(false);
                }

                if (!trackInfo.HasChanged)
                {
                    return(false);
                }

                trackInfo.SetMetadata(extractedAspectData);

                return(trackInfo.IsBaseInfoPresent);
            }
            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("BassAudioMetadataExtractor: Exception reading resource '{0}' (Text: '{1}')", fsra.CanonicalLocalResourcePath, e.Message);
            }
            return(false);
        }
Exemplo n.º 21
0
        /// <summary>
        /// Tries to load chapter information from external file. This method checks for ComSkip files (.txt).
        /// </summary>
        /// <returns></returns>
        protected virtual bool EnumerateExternalChapters()
        {
            var fsra = _resourceAccessor as IFileSystemResourceAccessor;

            if (fsra == null || !fsra.IsFile)
            {
                return(false);
            }

            try
            {
                string            filePath     = _resourceAccessor.CanonicalLocalResourcePath.ToString();
                string            metaFilePath = ProviderPathHelper.ChangeExtension(filePath, ".txt");
                IResourceAccessor raTextFile;
                if (!ResourcePath.Deserialize(metaFilePath).TryCreateLocalResourceAccessor(out raTextFile))
                {
                    return(false);
                }

                List <double> positions = new List <double>();
                using (LocalFsResourceAccessorHelper lfsra = new LocalFsResourceAccessorHelper(raTextFile))
                {
                    if (lfsra.LocalFsResourceAccessor == null)
                    {
                        return(false);
                    }
                    using (var stream = lfsra.LocalFsResourceAccessor.OpenRead())
                        using (var chaptersReader = new StreamReader(stream))
                        {
                            string line = chaptersReader.ReadLine();

                            int fps;
                            if (string.IsNullOrWhiteSpace(line) || !int.TryParse(line.Substring(line.LastIndexOf(' ') + 1), out fps))
                            {
                                ServiceRegistration.Get <ILogger>().Warn("VideoPlayer: EnumerateExternalChapters() - Invalid ComSkip chapter file");
                                return(false);
                            }

                            double framesPerSecond = fps / 100.0;

                            while ((line = chaptersReader.ReadLine()) != null)
                            {
                                if (String.IsNullOrEmpty(line))
                                {
                                    continue;
                                }

                                string[] tokens = line.Split('\t');
                                if (tokens.Length != 2)
                                {
                                    continue;
                                }

                                foreach (var token in tokens)
                                {
                                    int time;
                                    if (int.TryParse(token, NumberStyles.Float, NumberFormatInfo.InvariantInfo, out time))
                                    {
                                        positions.Add(time / framesPerSecond);
                                    }
                                }
                            }
                        }
                }

                // Insert start of video as position
                if (!positions.Contains(0d))
                {
                    positions.Insert(0, 0d);
                }

                var chapterNames = new List <string>();
                var chapterTimes = new List <double>();

                for (int index = 0; index < positions.Count - 1; index++)
                {
                    var timeFrom = positions[index];
                    var timeTo   = positions[index + 1];
                    // Filter out segments with less than 2 seconds duration
                    if (timeTo - timeFrom <= 2)
                    {
                        continue;
                    }
                    var chapterName = string.Format("ComSkip {0} [{1} - {2}]", chapterNames.Count + 1,
                                                    FormatDuration(timeFrom),
                                                    FormatDuration(timeTo));
                    chapterNames.Add(chapterName);
                    chapterTimes.Add(timeFrom);
                }
                _chapterNames      = chapterNames.ToArray();
                _chapterTimestamps = chapterTimes.ToArray();
                return(_chapterNames.Length > 0);
            }
            catch (Exception ex)
            {
                ServiceRegistration.Get <ILogger>().Error("VideoPlayer: EnumerateExternalChapters() - Exception while reading ComSkip chapter file", ex);
                return(false);
            }
        }
        public virtual bool TryExtractMetadata(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData, bool importOnly, bool forceQuickMode)
        {
            IFileSystemResourceAccessor fsra = mediaItemAccessor as IFileSystemResourceAccessor;

            if (fsra == null)
            {
                return(false);
            }
            if (!fsra.IsFile)
            {
                return(false);
            }
            string fileName = fsra.ResourceName;

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

            bool refresh = false;

            if (extractedAspectData.ContainsKey(AudioAspect.ASPECT_ID))
            {
                refresh = true;
            }

            try
            {
                TrackInfo trackInfo = new TrackInfo();
                if (refresh)
                {
                    trackInfo.FromMetadata(extractedAspectData);
                }
                if (!trackInfo.IsBaseInfoPresent)
                {
                    File tag = null;
                    try
                    {
                        ByteVector.UseBrokenLatin1Behavior = true; // Otherwise we have problems retrieving non-latin1 chars
                        tag = File.Create(new ResourceProviderFileAbstraction(fsra));
                    }
                    catch (CorruptFileException)
                    {
                        // 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("AudioMetadataExtractor: Audio file '{0}' seems to be broken", fsra.CanonicalLocalResourcePath);
                        return(false);
                    }

                    using (tag)
                    {
                        // Some file extensions like .mp4 can contain audio and video. Do not handle files with video content here.
                        if (tag.Properties.VideoHeight > 0 && tag.Properties.VideoWidth > 0)
                        {
                            return(false);
                        }

                        fileName = ProviderPathHelper.GetFileNameWithoutExtension(fileName) ?? string.Empty;
                        string title;
                        string sortTitle;
                        string artist;
                        uint?  trackNo;
                        GuessMetadataFromFileName(fileName, out title, out artist, out trackNo);
                        if (!string.IsNullOrEmpty(title))
                        {
                            title = CultureInfo.InvariantCulture.TextInfo.ToTitleCase(title.ToLowerInvariant());
                        }
                        if (!string.IsNullOrEmpty(artist))
                        {
                            artist = CultureInfo.InvariantCulture.TextInfo.ToTitleCase(artist.ToLowerInvariant());
                        }

                        if (!string.IsNullOrEmpty(tag.Tag.Title))
                        {
                            title = tag.Tag.Title.Trim();
                        }

                        sortTitle = BaseInfo.GetSortTitle(title);
                        if (!string.IsNullOrEmpty(tag.Tag.TitleSort))
                        {
                            sortTitle = tag.Tag.TitleSort.Trim();
                        }

                        IEnumerable <string> artists;
                        if (tag.Tag.Performers.Length > 0)
                        {
                            artists = tag.Tag.Performers;
                            if ((tag.TagTypes & TagTypes.Id3v2) != 0)
                            {
                                artists = PatchID3v23Enumeration(artists);
                            }
                        }
                        else
                        {
                            artists = artist == null ? null : new string[] { artist.Trim() }
                        };
                        if (tag.Tag.Track != 0)
                        {
                            trackNo = tag.Tag.Track;
                        }

                        if (importOnly)
                        {
                            MultipleMediaItemAspect providerResourceAspect = MediaItemAspect.CreateAspect(extractedAspectData, ProviderResourceAspect.Metadata);
                            providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_INDEX, 0);
                            providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_PRIMARY, true);
                            providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_SIZE, fsra.Size);
                            providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, fsra.CanonicalLocalResourcePath.Serialize());
                            // FIXME Albert: tag.MimeType returns taglib/mp3 for an MP3 file. This is not what we want and collides with the
                            // mimetype handling in the BASS player, which expects audio/xxx.
                            if (!string.IsNullOrWhiteSpace(tag.MimeType))
                            {
                                providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, tag.MimeType.Replace("taglib/", "audio/"));
                            }

                            MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, title);
                            MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_SORT_TITLE, sortTitle);
                            MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_ISVIRTUAL, false);
                            MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_COMMENT, StringUtils.TrimToNull(tag.Tag.Comment));
                            MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_RECORDINGTIME, fsra.LastChanged);
                        }

                        trackInfo.TrackName     = title;
                        trackInfo.TrackNameSort = sortTitle;
                        if (tag.Properties.Codecs.Count() > 0)
                        {
                            trackInfo.Encoding = tag.Properties.Codecs.First().Description;
                        }
                        if (tag.Properties.Duration.TotalSeconds != 0)
                        {
                            trackInfo.Duration = (long)tag.Properties.Duration.TotalSeconds;
                        }
                        if (tag.Properties.AudioBitrate != 0)
                        {
                            trackInfo.BitRate = (int)tag.Properties.AudioBitrate;
                        }
                        if (tag.Properties.AudioChannels != 0)
                        {
                            trackInfo.Channels = (int)tag.Properties.AudioChannels;
                        }
                        if (tag.Properties.AudioSampleRate != 0)
                        {
                            trackInfo.SampleRate = (int)tag.Properties.AudioSampleRate;
                        }

                        TagLib.Id3v2.Tag id3Tag = (TagLib.Id3v2.Tag)tag.GetTag(TagTypes.Id3v2, false);
                        if (id3Tag != null && !id3Tag.IsEmpty)
                        {
                            trackInfo.Compilation = id3Tag.IsCompilation;
                        }

                        trackInfo.Album = !string.IsNullOrEmpty(tag.Tag.Album) ? tag.Tag.Album.Trim() : null;
                        if (!string.IsNullOrEmpty(tag.Tag.AlbumSort))
                        {
                            IAudioRelationshipExtractor.StoreAlbum(extractedAspectData, tag.Tag.Album, tag.Tag.AlbumSort.Trim());
                        }

                        if (trackNo.HasValue)
                        {
                            trackInfo.TrackNum = (int)trackNo.Value;
                        }
                        if (tag.Tag.TrackCount != 0)
                        {
                            trackInfo.TotalTracks = (int)tag.Tag.TrackCount;
                        }
                        if (tag.Tag.Disc != 0)
                        {
                            trackInfo.DiscNum = (int)tag.Tag.Disc;
                        }
                        if (tag.Tag.DiscCount != 0)
                        {
                            trackInfo.TotalDiscs = (int)tag.Tag.DiscCount;
                        }
                        if (!string.IsNullOrEmpty(tag.Tag.Lyrics))
                        {
                            trackInfo.TrackLyrics = tag.Tag.Lyrics;
                        }

                        if (tag.Tag.TrackCount != 0)
                        {
                            trackInfo.TotalTracks = (int)tag.Tag.TrackCount;
                        }

                        if (!string.IsNullOrEmpty(tag.Tag.MusicBrainzTrackId))
                        {
                            trackInfo.MusicBrainzId = tag.Tag.MusicBrainzTrackId;
                        }
                        if (!string.IsNullOrEmpty(tag.Tag.MusicBrainzReleaseId))
                        {
                            trackInfo.AlbumMusicBrainzId = tag.Tag.MusicBrainzReleaseId;
                        }
                        if (!string.IsNullOrEmpty(tag.Tag.MusicBrainzDiscId))
                        {
                            trackInfo.AlbumMusicBrainzDiscId = tag.Tag.MusicBrainzDiscId;
                        }
                        if (!string.IsNullOrEmpty(tag.Tag.AmazonId))
                        {
                            trackInfo.AlbumAmazonId = tag.Tag.AmazonId;
                        }
                        if (!string.IsNullOrEmpty(tag.Tag.MusicIpId))
                        {
                            trackInfo.MusicIpId = tag.Tag.MusicIpId;
                        }

                        trackInfo.Artists = new List <PersonInfo>();
                        if (artists != null)
                        {
                            foreach (string artistName in ApplyAdditionalSeparator(artists))
                            {
                                trackInfo.Artists.Add(new PersonInfo()
                                {
                                    Name            = artistName.Trim(),
                                    Occupation      = PersonAspect.OCCUPATION_ARTIST,
                                    ParentMediaName = trackInfo.Album,
                                    MediaName       = trackInfo.TrackName
                                });
                            }
                        }

                        //Save id if possible
                        if (trackInfo.Artists.Count == 1 && !string.IsNullOrEmpty(tag.Tag.MusicBrainzArtistId))
                        {
                            trackInfo.Artists[0].MusicBrainzId = tag.Tag.MusicBrainzArtistId;
                        }

                        IEnumerable <string> albumArtists = tag.Tag.AlbumArtists;
                        if ((tag.TagTypes & TagTypes.Id3v2) != 0)
                        {
                            albumArtists = PatchID3v23Enumeration(albumArtists);
                        }
                        trackInfo.AlbumArtists = new List <PersonInfo>();
                        if (albumArtists != null)
                        {
                            foreach (string artistName in ApplyAdditionalSeparator(albumArtists))
                            {
                                trackInfo.AlbumArtists.Add(new PersonInfo()
                                {
                                    Name            = artistName.Trim(),
                                    Occupation      = PersonAspect.OCCUPATION_ARTIST,
                                    ParentMediaName = trackInfo.Album,
                                    MediaName       = trackInfo.TrackName
                                });
                            }
                        }

                        //Save id if possible
                        if (trackInfo.AlbumArtists.Count == 1 && !string.IsNullOrEmpty(tag.Tag.MusicBrainzReleaseArtistId))
                        {
                            trackInfo.AlbumArtists[0].MusicBrainzId = tag.Tag.MusicBrainzReleaseArtistId;
                        }

                        IEnumerable <string> composers = tag.Tag.Composers;
                        if ((tag.TagTypes & TagTypes.Id3v2) != 0)
                        {
                            composers = PatchID3v23Enumeration(composers);
                        }
                        trackInfo.Composers = new List <PersonInfo>();
                        if (composers != null)
                        {
                            foreach (string composerName in ApplyAdditionalSeparator(composers))
                            {
                                trackInfo.Composers.Add(new PersonInfo()
                                {
                                    Name            = composerName.Trim(),
                                    Occupation      = PersonAspect.OCCUPATION_COMPOSER,
                                    ParentMediaName = trackInfo.Album,
                                    MediaName       = trackInfo.TrackName
                                });
                            }
                        }

                        if (tag.Tag.Genres.Length > 0)
                        {
                            IEnumerable <string> genres = tag.Tag.Genres;
                            if ((tag.TagTypes & TagTypes.Id3v2) != 0)
                            {
                                genres = PatchID3v23Enumeration(genres);
                            }
                            trackInfo.Genres = ApplyAdditionalSeparator(genres).Select(s => new GenreInfo {
                                Name = s.Trim()
                            }).ToList();
                            OnlineMatcherService.Instance.AssignMissingMusicGenreIds(trackInfo.Genres);
                        }

                        int year = (int)tag.Tag.Year;
                        if (year >= 30 && year <= 99)
                        {
                            year += 1900;
                        }
                        if (year >= 1930 && year <= 2030)
                        {
                            trackInfo.ReleaseDate = new DateTime(year, 1, 1);
                        }

                        if (!trackInfo.HasThumbnail)
                        {
                            // The following code gets cover art images from file (embedded) or from windows explorer cache (supports folder.jpg).
                            IPicture[] pics = tag.Tag.Pictures;
                            if (pics.Length > 0)
                            {
                                try
                                {
                                    using (MemoryStream stream = new MemoryStream(pics[0].Data.Data))
                                    {
                                        trackInfo.Thumbnail  = stream.ToArray();
                                        trackInfo.HasChanged = true;
                                    }
                                }
                                // Decoding of invalid image data can fail, but main MediaItem is correct.
                                catch { }
                            }
                            else
                            {
                                // In quick mode only allow thumbs taken from cache.
                                bool cachedOnly = importOnly || forceQuickMode;

                                // Thumbnail extraction
                                fileName = mediaItemAccessor.ResourcePathName;
                                IThumbnailGenerator generator = ServiceRegistration.Get <IThumbnailGenerator>();
                                byte[]    thumbData;
                                ImageType imageType;
                                if (generator.GetThumbnail(fileName, cachedOnly, out thumbData, out imageType))
                                {
                                    trackInfo.Thumbnail  = thumbData;
                                    trackInfo.HasChanged = true;
                                }
                            }
                        }
                    }

                    if (string.IsNullOrEmpty(trackInfo.Album) || trackInfo.Artists.Count == 0)
                    {
                        MusicNameMatcher.MatchTrack(fileName, trackInfo);
                    }
                }

                //Determine compilation
                if (importOnly && !trackInfo.Compilation)
                {
                    if (trackInfo.AlbumArtists.Count > 0 &&
                        (trackInfo.AlbumArtists[0].Name.IndexOf("Various", StringComparison.InvariantCultureIgnoreCase) >= 0 ||
                         trackInfo.AlbumArtists[0].Name.Equals("VA", StringComparison.InvariantCultureIgnoreCase)))
                    {
                        trackInfo.Compilation = true;
                    }
                    else
                    {
                        //Look for itunes compilation folder
                        var mediaItemPath = mediaItemAccessor.CanonicalLocalResourcePath;
                        var albumMediaItemDirectoryPath  = ResourcePathHelper.Combine(mediaItemPath, "../");
                        var artistMediaItemDirectoryPath = ResourcePathHelper.Combine(mediaItemPath, "../../");

                        if (IsDiscFolder(trackInfo.Album, albumMediaItemDirectoryPath.FileName))
                        {
                            //Probably a CD folder so try next parent
                            artistMediaItemDirectoryPath = ResourcePathHelper.Combine(mediaItemPath, "../../../");
                        }
                        if (artistMediaItemDirectoryPath.FileName.IndexOf("Compilation", StringComparison.InvariantCultureIgnoreCase) >= 0)
                        {
                            trackInfo.Compilation = true;
                        }
                    }
                }

                if (!refresh)
                {
                    //Check artists
                    trackInfo.Artists      = GetCorrectedArtistsList(trackInfo, trackInfo.Artists);
                    trackInfo.AlbumArtists = GetCorrectedArtistsList(trackInfo, trackInfo.AlbumArtists);
                }

                trackInfo.AssignNameId();

                if (!forceQuickMode)
                {
                    AudioCDMatcher.GetDiscMatchAndUpdate(mediaItemAccessor.ResourcePathName, trackInfo);

                    if (SkipOnlineSearches && !SkipFanArtDownload)
                    {
                        TrackInfo tempInfo = trackInfo.Clone();
                        OnlineMatcherService.Instance.FindAndUpdateTrack(tempInfo, importOnly);
                        trackInfo.CopyIdsFrom(tempInfo);
                        trackInfo.HasChanged = tempInfo.HasChanged;
                    }
                    else if (!SkipOnlineSearches)
                    {
                        OnlineMatcherService.Instance.FindAndUpdateTrack(trackInfo, importOnly);
                    }
                }

                if (refresh)
                {
                    if ((IncludeArtistDetails && !BaseInfo.HasRelationship(extractedAspectData, PersonAspect.ROLE_ARTIST) && trackInfo.Artists.Count > 0) ||
                        (IncludeArtistDetails && !BaseInfo.HasRelationship(extractedAspectData, PersonAspect.ROLE_ALBUMARTIST) && trackInfo.AlbumArtists.Count > 0) ||
                        (IncludeComposerDetails && !BaseInfo.HasRelationship(extractedAspectData, PersonAspect.ROLE_COMPOSER) && trackInfo.Composers.Count > 0))
                    {
                        trackInfo.HasChanged = true;
                    }
                }

                if (!trackInfo.HasChanged && !importOnly)
                {
                    return(false);
                }

                trackInfo.SetMetadata(extractedAspectData);

                if (importOnly)
                {
                    //Store metadata for the Relationship Extractors
                    if (IncludeArtistDetails)
                    {
                        IAudioRelationshipExtractor.StorePersons(extractedAspectData, trackInfo.Artists, false);
                        IAudioRelationshipExtractor.StorePersons(extractedAspectData, trackInfo.AlbumArtists, true);
                    }
                    if (IncludeComposerDetails)
                    {
                        IAudioRelationshipExtractor.StorePersons(extractedAspectData, trackInfo.Composers, false);
                    }
                }

                return(trackInfo.IsBaseInfoPresent);
            }
            catch (UnsupportedFormatException)
            {
                ServiceRegistration.Get <ILogger>().Info("AudioMetadataExtractor: Unsupported audio file '{0}'", fsra.CanonicalLocalResourcePath);
                return(false);
            }
            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("AudioMetadataExtractor: Exception reading resource '{0}' (Text: '{1}')", fsra.CanonicalLocalResourcePath, e.Message);
            }
            return(false);
        }
Exemplo n.º 23
0
        public bool TryExtractMetadata(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData, bool importOnly, bool forceQuickMode)
        {
            string fileName = mediaItemAccessor.ResourceName;

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

            bool refresh = false;

            if (extractedAspectData.ContainsKey(ImageAspect.ASPECT_ID))
            {
                refresh = true;
            }

            try
            {
                IFileSystemResourceAccessor fsra = mediaItemAccessor as IFileSystemResourceAccessor;
                if (!refresh)
                {
                    MultipleMediaItemAspect providerResourceAspect = MediaItemAspect.CreateAspect(extractedAspectData, ProviderResourceAspect.Metadata);
                    providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_INDEX, 0);
                    providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_PRIMARY, true);

                    if (!(mediaItemAccessor is IFileSystemResourceAccessor))
                    {
                        return(false);
                    }

                    // Open a stream for media item to detect mimeType.
                    using (Stream mediaStream = fsra.OpenRead())
                    {
                        string mimeType = MimeTypeDetector.GetMimeType(mediaStream) ?? DEFAULT_MIMETYPE;
                        providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, mimeType);
                        providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_SIZE, fsra.Size);
                    }
                }

                MediaItemAspect mediaAspect = MediaItemAspect.GetOrCreateAspect(extractedAspectData, MediaAspect.Metadata);
                mediaAspect.SetAttribute(MediaAspect.ATTR_ISVIRTUAL, false);
                MediaItemAspect imageAspect = MediaItemAspect.GetOrCreateAspect(extractedAspectData, ImageAspect.Metadata);

                if (!refresh)
                {
                    // Extract EXIF information from media item.
                    using (ExifMetaInfo.ExifMetaInfo exif = new ExifMetaInfo.ExifMetaInfo(fsra))
                    {
                        mediaAspect.SetAttribute(MediaAspect.ATTR_TITLE, ProviderPathHelper.GetFileNameWithoutExtension(fileName));
                        mediaAspect.SetAttribute(MediaAspect.ATTR_RECORDINGTIME, exif.OriginalDate != DateTime.MinValue ? exif.OriginalDate : fsra.LastChanged);
                        mediaAspect.SetAttribute(MediaAspect.ATTR_COMMENT, StringUtils.TrimToNull(exif.ImageDescription));

                        if (exif.PixXDim.HasValue)
                        {
                            imageAspect.SetAttribute(ImageAspect.ATTR_WIDTH, (int)exif.PixXDim);
                        }
                        if (exif.PixYDim.HasValue)
                        {
                            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));
                        if (exif.ExposureBias.HasValue)
                        {
                            imageAspect.SetAttribute(ImageAspect.ATTR_EXPOSURE_BIAS, ((double)exif.ExposureBias).ToString());
                        }
                        imageAspect.SetAttribute(ImageAspect.ATTR_EXPOSURE_TIME, exif.ExposureTime);
                        imageAspect.SetAttribute(ImageAspect.ATTR_FLASH_MODE, StringUtils.TrimToNull(exif.FlashMode));
                        if (exif.FNumber.HasValue)
                        {
                            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.OrientationType ?? 0));
                        imageAspect.SetAttribute(ImageAspect.ATTR_METERING_MODE, exif.MeteringMode.ToString());

                        if (exif.Latitude.HasValue && exif.Longitude.HasValue)
                        {
                            imageAspect.SetAttribute(ImageAspect.ATTR_LATITUDE, exif.Latitude);
                            imageAspect.SetAttribute(ImageAspect.ATTR_LONGITUDE, exif.Longitude);
                        }
                    }

                    byte[] thumbData;
                    // We only want to create missing thumbnails here, so check for existing ones first
                    if (MediaItemAspect.TryGetAttribute(extractedAspectData, ThumbnailLargeAspect.ATTR_THUMBNAIL, out thumbData) && thumbData != null)
                    {
                        return(true);
                    }

                    using (LocalFsResourceAccessorHelper rah = new LocalFsResourceAccessorHelper(mediaItemAccessor))
                        using (rah.LocalFsResourceAccessor.EnsureLocalFileSystemAccess())
                        {
                            string localFsResourcePath = rah.LocalFsResourceAccessor.LocalFileSystemPath;
                            if (localFsResourcePath != null)
                            {
                                // Thumbnail extraction
                                IThumbnailGenerator generator = ServiceRegistration.Get <IThumbnailGenerator>();
                                ImageType           imageType;
                                if (generator.GetThumbnail(localFsResourcePath, true, out thumbData, out imageType))
                                {
                                    MediaItemAspect.SetAttribute(extractedAspectData, ThumbnailLargeAspect.ATTR_THUMBNAIL, thumbData);
                                }
                            }
                        }
                    return(true);
                }
                else
                {
                    bool   updated   = false;
                    double?latitude  = imageAspect.GetAttributeValue <double?>(ImageAspect.ATTR_LATITUDE);
                    double?longitude = imageAspect.GetAttributeValue <double?>(ImageAspect.ATTR_LONGITUDE);
                    if (IncludeGeoLocationDetails && !importOnly && latitude.HasValue && longitude.HasValue &&
                        string.IsNullOrEmpty(imageAspect.GetAttributeValue <string>(ImageAspect.ATTR_COUNTRY)))
                    {
                        CivicAddress locationInfo;
                        if (!forceQuickMode && GeoLocationService.Instance.TryLookup(new GeoCoordinate(latitude.Value, longitude.Value), out locationInfo))
                        {
                            imageAspect.SetAttribute(ImageAspect.ATTR_CITY, locationInfo.City);
                            imageAspect.SetAttribute(ImageAspect.ATTR_STATE, locationInfo.StateProvince);
                            imageAspect.SetAttribute(ImageAspect.ATTR_COUNTRY, locationInfo.CountryRegion);
                            updated = true;
                        }
                    }

                    byte[] thumbData;
                    // We only want to create missing thumbnails here, so check for existing ones first
                    if (MediaItemAspect.TryGetAttribute(extractedAspectData, ThumbnailLargeAspect.ATTR_THUMBNAIL, out thumbData) && thumbData != null)
                    {
                        return(updated);
                    }

                    using (LocalFsResourceAccessorHelper rah = new LocalFsResourceAccessorHelper(mediaItemAccessor))
                        using (rah.LocalFsResourceAccessor.EnsureLocalFileSystemAccess())
                        {
                            string localFsResourcePath = rah.LocalFsResourceAccessor.LocalFileSystemPath;
                            if (localFsResourcePath != null)
                            {
                                // In quick mode only allow thumbs taken from cache.
                                bool cachedOnly = forceQuickMode;
                                // Thumbnail extraction
                                IThumbnailGenerator generator = ServiceRegistration.Get <IThumbnailGenerator>();
                                ImageType           imageType;
                                if (generator.GetThumbnail(localFsResourcePath, cachedOnly, out thumbData, out imageType))
                                {
                                    MediaItemAspect.SetAttribute(extractedAspectData, ThumbnailLargeAspect.ATTR_THUMBNAIL, thumbData);
                                    updated = true;
                                }
                            }
                        }
                    return(updated);
                }
            }
            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);
        }
Exemplo n.º 24
0
        private static void TestRecording(string filename)
        {
            if (Directory.Exists("_Test"))
            {
                Directory.Delete("_Test", true);
            }

            ServiceRegistration.Set <IPathManager>(new PathManager());
            ServiceRegistration.Get <IPathManager>().SetPath("DATA", "_Test/Data");

            ServiceRegistration.Set <ILocalization>(new NoLocalization());
            ServiceRegistration.Set <ILogger>(new ConsoleLogger(LogLevel.All, true));

            ServiceRegistration.Set <IMediaAccessor>(new TestMediaAccessor());
            ServiceRegistration.Set <IMediaItemAspectTypeRegistration>(new MockMediaItemAspectTypeRegistration());

            ApplicationCore.RegisterDefaultMediaItemAspectTypes().Wait();

            ServiceRegistration.Set <SeriesTvDbMatcher>(new SeriesTvDbMatcher());

            IDictionary <Guid, IList <MediaItemAspect> > aspects = new Dictionary <Guid, IList <MediaItemAspect> >();

            string ext = StringUtils.TrimToEmpty(ProviderPathHelper.GetExtension(filename)).ToLowerInvariant();

            if (ext != ".xml")
            {
                Console.WriteLine("Filetype must be XML");
                return;
            }
            XmlSerializer serializer = new XmlSerializer(typeof(Tve3RecordingMetadataExtractor.Tags));

            using (Stream stream = new FileStream(filename, FileMode.Open, FileAccess.Read))
            {
                Tve3RecordingMetadataExtractor.Tags      tags = (Tve3RecordingMetadataExtractor.Tags)serializer.Deserialize(stream);
                Tve3RecordingMetadataExtractor.SimpleTag tag  = tags.Tag.Find(t => t.Name == "TITLE");
                MediaItemAspect.SetAttribute(aspects, MediaAspect.ATTR_TITLE, tag.Value);
            }

            IMediaItemAspectTypeRegistration registration = ServiceRegistration.Get <IMediaItemAspectTypeRegistration>();

            Console.WriteLine("Before extract:");
            ShowMIAs(aspects, registration);

            IMetadataExtractor extractor = new Tve3RecordingMetadataExtractor();
            IResourceAccessor  accessor  = new MockLocalFsResourceAccessor(ProviderPathHelper.ChangeExtension(filename, ".ts"));

            extractor.TryExtractMetadataAsync(accessor, aspects, false);

            Console.WriteLine("After extract:");
            ShowMIAs(aspects, registration);

            string value;

            if (MediaItemAspect.TryGetExternalAttribute(aspects, ExternalIdentifierAspect.SOURCE_TVDB, ExternalIdentifierAspect.TYPE_SERIES, out value))
            {
                SeriesInfo seriesInfo = new SeriesInfo()
                {
                    TvdbId = Int32.Parse(value)
                };
                SeriesTvDbMatcher.Instance.UpdateSeriesAsync(seriesInfo, false).Wait();
                Console.WriteLine("{0}: {1}", seriesInfo.SeriesName, seriesInfo.Description);
            }
        }