예제 #1
0
        public async Task SetMetaData(string fileName, IEnumerable <MetaDataItem> metaData, Func <MetaDataItem, bool> predicate)
        {
            if (MetaDataBehaviourConfiguration.GetWriteBehaviour(this.Write.Value) == WriteBehaviour.None)
            {
                Logger.Write(this, LogLevel.Warn, "Writing is disabled: {0}", fileName);
                return;
            }
            if (!this.IsSupported(fileName))
            {
                Logger.Write(this, LogLevel.Warn, "Unsupported file format: {0}", fileName);
                return;
            }
            var metaDataItems = default(IEnumerable <MetaDataItem>);

            lock (metaData)
            {
                if (predicate != null)
                {
                    metaDataItems = metaData.Where(predicate).ToArray();
                }
                else
                {
                    metaDataItems = metaData.ToArray();
                }
                if (!metaDataItems.Any())
                {
                    //Nothing to update.
                    return;
                }
            }
            var collect = default(bool);

            using (var file = this.FileFactory.Create(fileName))
            {
                if (file.PossiblyCorrupt)
                {
                    this.AddWarnings(fileName, file.CorruptionReasons);
                }
                foreach (var metaDataItem in metaDataItems)
                {
                    switch (metaDataItem.Type)
                    {
                    case MetaDataItemType.Tag:
                        this.SetTag(metaDataItem, file);
                        break;

                    case MetaDataItemType.Image:
                        if (file.InvariantStartPosition > MAX_TAG_SIZE)
                        {
                            collect = true;
                        }
                        await ImageManager.Write(this, metaDataItem, file).ConfigureAwait(false);

                        break;

                    case MetaDataItemType.Document:
                        if (this.Documents.Value)
                        {
                            DocumentManager.Write(this, metaDataItem, file);
                        }
                        break;
                    }
                }
                if (file is IMetaDataSource metaDataSource)
                {
                    await this.SetAdditional(metaData, file, metaDataSource).ConfigureAwait(false);
                }
                file.Save();
            }
            if (collect)
            {
                //If we encountered a large meta data section (>10MB) then we need to try to reclaim the memory.
                GC.Collect();
            }
        }
예제 #2
0
        public async Task <IEnumerable <MetaDataItem> > GetMetaData(string fileName, Func <File> factory)
        {
            if (!this.IsSupported(fileName))
            {
                Logger.Write(this, LogLevel.Warn, "Unsupported file format: {0}", fileName);
                this.AddWarning(fileName, "Unsupported file format.");
                return(Enumerable.Empty <MetaDataItem>());
            }
            var collect  = default(bool);
            var metaData = new List <MetaDataItem>();

            Logger.Write(this, LogLevel.Trace, "Reading meta data for file: {0}", fileName);
            try
            {
                using (var file = factory())
                {
                    if (file.PossiblyCorrupt)
                    {
                        this.AddWarnings(fileName, file.CorruptionReasons);
                    }
                    if (file.InvariantStartPosition > MAX_TAG_SIZE)
                    {
                        collect = true;
                    }
                    if (file.Tag != null)
                    {
                        this.AddTags(metaData, file.Tag);
                    }
                    if (file.Properties != null)
                    {
                        this.AddProperties(metaData, file.Properties);
                    }
                    if (this.Popularimeter.Value)
                    {
                        this.Try(() => PopularimeterManager.Read(this, metaData, file), this.ErrorHandler);
                    }
                    if (this.ReplayGain.Value)
                    {
                        this.Try(() => ReplayGainManager.Read(this, metaData, file), this.ErrorHandler);
                    }
                    if (this.Documents.Value)
                    {
                        this.Try(() => DocumentManager.Read(this, metaData, file), this.ErrorHandler);
                    }
                    this.Try(() => CompilationManager.Read(this, metaData, file), this.ErrorHandler);
                    if (file is IMetaDataSource metaDataSource)
                    {
                        await this.AddAdditional(metaData, file, metaDataSource).ConfigureAwait(false);
                    }
                    await ImageManager.Read(this, metaData, file).ConfigureAwait(false);
                }
            }
            catch (UnsupportedFormatException)
            {
                Logger.Write(this, LogLevel.Warn, "Unsupported file format: {0}", fileName);
                this.AddWarning(fileName, "Unsupported file format.");
            }
            catch (OutOfMemoryException)
            {
                //This can happen with really big embedded images.
                //It's tricky to avoid because we can't check InvariantStartPosition without parsing.
                Logger.Write(this, LogLevel.Warn, "Out of memory: {0}", fileName);
                this.AddWarning(fileName, "Out of memory.");
                collect = true;
            }
            catch (Exception e)
            {
                Logger.Write(this, LogLevel.Warn, "Failed to read meta data: {0} => {1}", fileName, e.Message);
                this.AddWarning(fileName, string.Format("Failed to read meta data: {0}", e.Message));
            }
            finally
            {
                if (collect)
                {
                    //If we encountered a large meta data section (>10MB) then we need to try to reclaim the memory.
                    GC.Collect();
                }
            }
            return(metaData);
        }