Beispiel #1
0
        public void GetContentMetadata(Book.Part part, EFlags flags = default)
        {
            var filename = part.AaxFileItem.FileName;

            Log(3, this, () => $"\"{filename.SubstitUser ()}\", flags={flags}");

            try {
                var contentMetadataFile = findContentMetadataFile(filename);
                if (contentMetadataFile is null || contentMetadataFile.Filename is null)
                {
                    part.AaxFileItem.ContentMetadataFile = new AsinJsonFile(null, null);
                    return;
                }

                part.AaxFileItem.ContentMetadataFile = contentMetadataFile;
                string metafile = contentMetadataFile.Filename;
                Log(3, this, () => $"\"{metafile.SubstitUser ()}\"");

                if (flags.HasFlag(EFlags.fileOnly))
                {
                    return;
                }

                getContentMetaChapters(part, metafile, flags.HasFlag(EFlags.skuOnly));
            } catch (Exception exc) {
                Log(1, this, () => exc.ToShortString());
            }
        }
Beispiel #2
0
        private void setContext(Book.Part part = null)
        {
            if (part is null && Book.PartsType != Book.EParts.some)
            {
                part = Book?.Parts?.FirstOrDefault();
            }
            if (part is null || !part.AaxFileItem.Converted)
            {
                return;
            }

            AaxFileItem = part.AaxFileItem;
            double duration = 0;

            if (Book.PartsType != Book.EParts.some)
            {
                duration = Book.Parts.SelectMany(p => p.Tracks).Select(t => t.Time.Duration.TotalSeconds).Sum();
            }
            else
            {
                duration = part.Tracks.Select(t => t.Time.Duration.TotalSeconds).Sum();
            }

            Duration = TimeSpan.FromSeconds(duration);
        }
Beispiel #3
0
        public void GetContentMetadata(Book.Part part, bool fileOnly = false)
        {
            var filename = part.AaxFileItem.FileName;

            Log(3, this, () => $"\"{filename.SubstitUser ()}\", file only={fileOnly}");

            var contentMetadataFile = findContentMetadataFile(filename);

            if (contentMetadataFile is null || contentMetadataFile.Filename is null)
            {
                part.AaxFileItem.ContentMetadataFile = new ContentMetadataFile(null, null);
                return;
            }

            part.AaxFileItem.ContentMetadataFile = contentMetadataFile;
            string metafile = contentMetadataFile.Filename;

            Log(3, this, () => $"\"{metafile.SubstitUser ()}\"");

            if (fileOnly)
            {
                return;
            }

            getContentMetaChapters(part, metafile);
        }
Beispiel #4
0
        private string chapterList(Book.Part part)
        {
            var sb = new StringBuilder($"content meta chapters:");

            sb.AppendLine();
            if (!(part.Chapters2 is null))
            {
                foreach (var ch in part.Chapters2)
                {
                    sb.AppendLine($"  {ch}");
                }
            }
            sb.Append($"  intro={part.BrandIntro.ToStringHMSm ()}, outro={part.BrandOutro.ToStringHMSm ()}, duration={part.Duration.ToStringHMSm ()}");
            return(sb.ToString());
        }
Beispiel #5
0
        private AA.AsinJsonFile findSeriesFileDirectOrSku(Book.Part part, bool fileOnly, string filePrefix, GetProductsDelegate getProducts)
        {
            // try to find sims by series file, either locally, relative or absolute
            // precondition content meta file is available
            // either by ASIN (single-part book) or by SKU (multipart book)


            // get asin
            var    afi  = part.AaxFileItem;
            string asin = afi.ContentMetadataFile?.ASIN;

            if (asin is null)
            {
                Log(3, this, () => $"ASIN not found.");
                return(null);
            }
            Log(3, this, () => $"ASIN={asin}{(filePrefix.IsNullOrWhiteSpace() ? string.Empty : $", prefix={filePrefix}")}");
Beispiel #6
0
        private bool findSeriesFile(Book.Part part, bool fileOnly, string filePrefix, GetProductsDelegate getProducts)
        {
            try {
                var simsBySeriesFile = findSeriesFileDirectOrSku(part, fileOnly, filePrefix, getProducts);
                if (simsBySeriesFile is null || simsBySeriesFile.Filename is null)
                {
                    part.AaxFileItem.SimsBySeriesFile = new AA.AsinJsonFile(null, null);
                    return(false);
                }

                part.AaxFileItem.SimsBySeriesFile = simsBySeriesFile;
                string metafile = simsBySeriesFile.Filename;
                Log(3, this, () => $"\"{metafile.SubstitUser ()}\"");
                return(true);
            } catch (Exception exc) {
                Log(1, this, () => exc.ToShortString());
                return(false);
            }
        }
Beispiel #7
0
        public void GetSimsBySeries(Book.Part part, bool fileOnly = false)
        {
            if (part.Book.ExternalMeta != null)
            {
                return;
            }

            var filename = part.AaxFileItem.FileName;

            Log(3, this, () => $"\"{filename.SubstitUser ()}\", file only={fileOnly}");

            // either ASIN.json or series_titles_ASIN.json
            bool succ = findSeriesFile(part, fileOnly, string.Empty, getProductsSingle);

            if (!succ)
            {
                findSeriesFile(part, fileOnly, SERIES_TITLES, getProductsMulti);
            }
        }
            public readonly int nnPrt = -1;   // part digits

            public Numbers(Track track, Book.Part part)
            {
                Book book = part.Book;

                this.nPrt  = part.PartNumber;
                this.nnPrt = book.Parts.Select(p => p.PartNumber).Max().Digits();

                if (!(track is null))
                {
                    var chapterTracks = part.Tracks?.Where(t => !(track.Chapter is null) && object.ReferenceEquals(t.Chapter, track.Chapter)).ToList();
                    this.nChTrk  = (chapterTracks?.IndexOf(track) ?? -1) + 1;
                    this.nChTrks = chapterTracks?.Count ?? 0;
                    this.nnChTrk = this.nChTrks.Digits();
                }

                if (book.PartsType == Book.EParts.some)
                {
                    this.nTrk  = (part.Tracks?.IndexOf(track) ?? -1) + 1;
                    this.nTrks = part.Tracks?.Count ?? 0;

                    this.nDsk  = part.PartNumber;
                    this.nDsks = 0;

                    this.nChp  = (part.Chapters?.IndexOf(track?.Chapter) ?? -1) + 1;
                    this.nnChp = part.Chapters?.Count.Digits() ?? 0;
                }
                else
                {
                    this.nTrk = book.Parts.Select(pt =>
                    {
                        if (pt != part)
                        {
                            if (pt.PartNumber < part.PartNumber)
                            {
                                return(pt.Tracks?.Count ?? 0);
                            }
                            else
                            {
                                return(0);
                            }
                        }
                        else
                        {
                            return((part.Tracks?.IndexOf(track) ?? -1) + 1);
                        }
                    }).Sum();

                    this.nTrks = book.Parts.Select(p => p.Tracks?.Count() ?? 0).Sum();

                    this.nDsks = book.Parts.Count;


                    this.nChp = book.Parts.Select(pt =>
                    {
                        if (pt != part)
                        {
                            if (pt.PartNumber < part.PartNumber)
                            {
                                return(pt.Chapters?.Count ?? 0);
                            }
                            else
                            {
                                return(0);
                            }
                        }
                        else
                        {
                            if (track?.Chapter is null)
                            {
                                return(0);
                            }
                            else
                            {
                                return((pt.Chapters?.IndexOf(track?.Chapter) ?? -1) + 1);
                            }
                        }
                    }).Sum();

                    this.nnChp = book.Parts.Select(p => p.Chapters?.Count ?? 0).Sum().Digits();
                    this.nDsk  = book.PartsType == Book.EParts.none ? 1 : part.PartNumber;
                }

                this.nnTrk = this.nTrks.Digits();
            }
Beispiel #9
0
        public void CreateCueSheet(Book.Part part, int trackDurMins, bool splitTimeMode)
        {
            Log(3, this, () => this.ToString());

            // chapter duration in sec
            double chLenSec = this.Time.Duration.TotalSeconds;

            // rounded number of tracks in chapter, observing desired track duration
            int numTracks = Math.Max((int)(chLenSec / (trackDurMins * 60) + 0.5), 1);

            // average track length in sec
            double aveTrackLen = chLenSec / numTracks;

            // average track length as TimeSpan
            var tsAveTrackLen = TimeSpan.FromSeconds(aveTrackLen);

            // search range for silence at desired end of track is +/- 1/3 ave track length
            var tsSearchRange = TimeSpan.FromSeconds(aveTrackLen / 3);

            // start 1st track at zero
            // unless in time split mode where we start at the actual beginning of the chapter
            var tsStart = TimeSpan.Zero;

            if (splitTimeMode)
            {
                tsStart = this.Time.Begin;
            }

            // desired end of 1st track
            var tsEnd = tsStart + tsAveTrackLen;

            // max end is chapter duration unless in time split mode
            var tsChEnd = this.Time.Duration - TS_EPS_SILENCE;

            if (splitTimeMode)
            {
                tsChEnd = this.Time.End;
            }

            // filter silences
            var silences = this.Silences.Where(s => s.Duration >= TS_SHORT_SILENCE).ToList();

            // while chapter length has not been reached, will be checked in loop
            while (true)
            {
                if (tsEnd < tsChEnd)
                {
                    // upper search limit for silence
                    var tsUpper = tsEnd + tsSearchRange;
                    // lower search limit for silence
                    var tsLower = tsEnd - tsSearchRange;

                    // take the easy road using LINQ, find nearest silence or none, above and below
                    var silUp = silences.Where(t => t.Begin >= tsEnd && t.Begin < tsUpper).FirstOrDefault();
                    var silDn = silences.Where(t => t.End > tsLower && t.End <= tsEnd).LastOrDefault();

                    // which silence shall it be
                    TimeInterval sil = null;
                    if (!(silUp is null || silDn is null))
                    {
                        // up and down found, use nearest
                        var deltaUp = silUp.Begin - tsEnd;
                        var deltaDn = tsEnd - silDn.End;
                        if (deltaUp < deltaDn)
                        {
                            sil = silUp;
                        }
                        else
                        {
                            sil = silDn;
                        }
                    }
                    else
                    {
                        // not both found, use any present
                        if (!(silUp is null))
                        {
                            sil = silUp;
                        }
 public PartChapters(Book.Part part)
 {
     Part = part;
 }
Beispiel #11
0
        private void getContentMetaChapters(Book.Part part, string metafile, bool skuOnly)
        {
            string json     = File.ReadAllText(metafile);
            var    metadata = JsonConvert.DeserializeObject <json.AppContentMetadata> (json);

            // get the SKU
            part.SKU = metadata.content_metadata.content_reference.sku;
            Log(3, this, () => $"SKU={part.SKU}");

            if (skuOnly)
            {
                return;
            }

            // set the chapters
            var chapters     = new List <Chapter> ();
            var metaChapters = metadata.content_metadata.chapter_info.chapters;

            if (metaChapters.Count == 0)
            {
                return;
            }

            // handle chapters with no name. Set '.' as a placeholder
            var whites = metaChapters.Where(c => string.IsNullOrWhiteSpace(c.title)).ToList();

            whites.ForEach(c => c.title = ".");

            // handle chapters of zero length. Min length must be 1 ms.
            var zeros = metaChapters.Where(c => c.length_ms == 0).ToList();

            Log(3, this, () => $"chapters: #zero={zeros.Count}, #white={whites.Count}");
            if (zeros.Count > 0)
            {
                zeros.ForEach(c => c.length_ms = Chapter.MS_MIN_CHAPTER_LENGTH);
                for (int i = 1; i < metaChapters.Count; i++)
                {
                    var ch0       = metaChapters[i - 1];
                    var ch        = metaChapters[i];
                    int chOffsNew = ch0.start_offset_ms + ch0.length_ms;
                    if (ch.start_offset_ms >= chOffsNew)
                    {
                        continue;
                    }
                    Log(3, this, () => $"duration fix for: {ch}");
                    int chLenNew = ch.length_ms + ch.start_offset_ms - chOffsNew;
                    if (chLenNew <= 0)
                    {
                        chLenNew = Chapter.MS_MIN_CHAPTER_LENGTH;
                    }
                    ch.start_offset_ms = chOffsNew;
                    ch.length_ms       = chLenNew;
                }
            }

            foreach (var ch in metaChapters)
            {
                var chapter = new Chapter();
                chapter.Name       = ch.title.Trim();
                chapter.Time.Begin = TimeSpan.FromMilliseconds(ch.start_offset_ms);
                chapter.Time.End   = TimeSpan.FromMilliseconds(ch.start_offset_ms + ch.length_ms);
                chapters.Add(chapter);
            }
            part.Chapters2 = chapters;

            // set brandintro and brandoutro times
            part.BrandIntro = TimeSpan.FromMilliseconds(metadata.content_metadata.chapter_info.brandIntroDurationMs);
            part.BrandOutro = TimeSpan.FromMilliseconds(metadata.content_metadata.chapter_info.brandOutroDurationMs);
            part.Duration   = TimeSpan.FromMilliseconds(metadata.content_metadata.chapter_info.runtime_length_ms);

            Log(3, this, () => chapterList(part));
        }
Beispiel #12
0
 public void GetContentMetadata(Book.Part part, bool fileOnly) =>
 GetContentMetadata(part, fileOnly ? EFlags.fileOnly : default);