示例#1
0
        private async Task UpdateAsync(MusicDb db /*, IEnumerable<string> paths*/)
        {
            var ti = await db.TaskItems.FindAsync(taskId);

            var artists = await db.ArtistStyles.Where(x => x.StyleId == musicStyle && x.Artist.Type != ArtistType.Various)
                          .Select(x => x.Artist)
                          .ToArrayAsync();

            foreach (var artist in artists)
            {
                var portraitFile = artist.GetPortraitFile(musicOptions);
                if (portraitFile == null)
                {
                    if (artist.Portrait != null)
                    {
                        artist.Portrait = null;
                        log.Information($"{ti} artist {artist.Name} portrait removed");
                    }
                }
                else if (artist.Portrait.HasChanged(portraitFile))
                {
                    artist.Portrait = await portraitFile.GetImage();

                    log.Information($"{ti} artist {artist.Name} portrait updated");
                }
            }
            ti.Status     = Music.Core.TaskStatus.Finished;
            ti.FinishedAt = DateTimeOffset.Now;
            await db.SaveChangesAsync();
        }
示例#2
0
        private async Task Start()
        {
            log.Information($"started");
            while (!cancellationToken.IsCancellationRequested)
            {
                await Task.Delay(2000);

                try
                {
                    TaskItem taskItem = null;
                    using (var db = new MusicDb(connectionString))
                    {
                        taskItem = db.TaskItems
                                   .Where(x => x.Type == TaskType.ResampleWork && x.Status == Music.Core.TaskStatus.Pending)
                                   .OrderBy(x => x.ScheduledAt)
                                   .FirstOrDefault();
                        if (taskItem != null)
                        {
                            taskItem.Status = Music.Core.TaskStatus.InProgress;
                            await db.SaveChangesAsync();
                        }
                    }
                    if (taskItem != null)
                    {
                        await ResampleAsync(taskItem.Id);
                    }
                }
                catch (Exception xe)
                {
                    log.Error(xe);
                }
            }
            log.Error($"finished!!!!!!!!!!!!!!!!!!!!!");
        }
示例#3
0
        public async Task <IActionResult> UpdateWork(MusicStyles style)
        {
            ITEOBase teo = null;

            switch (style)
            {
            case MusicStyles.Popular:
                teo = await this.Request.FromBody <PopularAlbumTEO>();

                break;

            case MusicStyles.WesternClassical:
                teo = await this.Request.FromBody <WesternClassicalAlbumTEO>();

                break;
            }
            var id   = teo.Id;
            var work = await musicDb.Works.FindAsync(id);

            teo.AfterDeserialisation(work);
            teo.SaveChanges(work);
            await teo.SaveMusicTags();

            work.LastModified = DateTimeOffset.Now;
            await musicDb.SaveChangesAsync();

            return(SuccessResult());
        }
示例#4
0
        private async Task <TaskItem> AddTask(MusicDb db, MusicStyles style, TaskType type, string taskString, /* bool queueTask = true,*/ bool force = false)
        {
            var existing = db.TaskItems
                           .Where(t => t.Type == type && t.MusicStyle == style &&
                                  t.TaskString.ToLower() == taskString.ToLower() &&
                                  (t.Status == Music.Core.TaskStatus.Pending || t.Status == Music.Core.TaskStatus.InProgress) &&
                                  t.Force == force);

            if (existing.Count() == 0)
            {
                var now = DateTimeOffset.Now;
                var ti  = new TaskItem
                {
                    Type        = type,
                    CreatedAt   = now,
                    ScheduledAt = now,
                    Status      = Music.Core.TaskStatus.Pending,
                    MusicStyle  = style,
                    TaskString  = taskString,
                    Force       = force
                };
                await db.TaskItems.AddAsync(ti);

                await db.SaveChangesAsync();

                taskRunner.QueueTask(ti);
                return(ti);
            }
            else
            {
                log.Debug($"Task type {type} for target {taskString} skipped as alrerady present");
            }
            return(null);
        }
示例#5
0
        private async Task <List <CatalogueResult> > CatalogueAsync(MusicDb db, PathData pd)
        {
            db.ChangeTracker.AutoDetectChangesEnabled = false;
            taskItem = await db.TaskItems.FindAsync(taskId);

            try
            {
                bool changesPresent(OpusFolder folder)
                {
                    var(result, changes) = folder.CheckForChanges(db);
                    if (result)
                    {
                        log.Information($"{folder}, change {changes}");
                    }
                    return(result);
                };
                var results = new List <CatalogueResult>();
                var folder  = new OpusFolder(musicOptions, pd);
                //if (forceChanges == true || folder.CheckForChanges(db))
                if (forceChanges == true || changesPresent(folder))
                {
                    var delay = GetRandomDelay();
                    log.Debug($"{taskItem} starting {folder.ToString()} after delay of {delay}ms");
                    await Task.Delay(TimeSpan.FromMilliseconds(delay));

                    results = await ProcessFolderAsync(db, folder);

                    var success = results.All(x => x.Status == CatalogueStatus.Success || x.Status == CatalogueStatus.GeneratedFilesOutOfDate);
                    taskItem.Status = success ? Music.Core.TaskStatus.Finished : Music.Core.TaskStatus.Failed;
                }
                else
                {
                    taskItem.Status = Music.Core.TaskStatus.Finished;
                    results.Add(new CatalogueResult {
                        Status = CatalogueStatus.Success
                    });
                    log.Information($"{taskItem} starting {folder.ToString()} no update required");
                }
                taskItem.FinishedAt = DateTimeOffset.Now;
                await db.SaveChangesAsync();

                return(results);
            }
            catch (Exception xe)
            {
                log.Error(xe, $"task {taskItem}");
                throw new CatalogueFailed {
                          TaskId = taskId
                };
            }
        }
示例#6
0
        public async Task <IActionResult> ConfirmDevice()
        {
            Device device          = null;
            var    deviceToConfirm = await this.Request.FromBody <AudioDevice>();

            if (deviceToConfirm.Type != AudioDeviceType.Browser)
            {
                device = await musicDb.Devices.SingleOrDefaultAsync(x => x.HostMachine.ToLower() == deviceToConfirm.HostMachine.ToLower() &&
                                                                    x.MACAddress.ToLower() == deviceToConfirm.MACAddress.ToLower());

                //&& x.Name.ToLower() == deviceToConfirm.Name.ToLower()); ;
                if (device == null)
                {
                    device = AddNewDeviceToDB(deviceToConfirm);
                }
                if (device.CanReposition != deviceToConfirm.CanReposition || device.MaxSampleRate != (deviceToConfirm.Capability?.MaxSampleRate ?? 0))
                {
                    device.CanReposition = deviceToConfirm.CanReposition;
                    device.MaxSampleRate = deviceToConfirm.Capability?.MaxSampleRate ?? 0;
                }
                device.LastSeenDateTime = DateTimeOffset.Now;
                device.PlayerUrl        = deviceToConfirm.Url;
                await musicDb.SaveChangesAsync();
            }
            else
            {
                // all browser devices must have a key already (due to prior web audio registration)
                device = await musicDb.Devices.SingleOrDefaultAsync(x => x.KeyName == deviceToConfirm.Key);

                // Note: device.LastSeenDateTime is set during web audio start
                await musicDb.SaveChangesAsync();
            }
            if (!ValidatePlaylist(device))
            {
                await musicDb.SaveChangesAsync();
            }
            log.Debug($"Confirming device {device.KeyName}, {device.DisplayName}, {device.HostMachine}, disabled =  {device.IsDisabled} ");
            await SyncDeviceWithPlayManager(device);

            return(SuccessResult(device.ToDTO()));
        }
示例#7
0
        private async Task ResampleAsync(MusicDb db)
        {
            db.ChangeTracker.AutoDetectChangesEnabled = false;
            taskItem = await db.TaskItems.FindAsync(taskId);

            var sources        = new MusicSources(musicOptions, true);
            var vbrDestination = sources.FirstOrDefault(x => x.IsGenerated);

            if (vbrDestination != null)
            {
                var work = await db.Works.SingleAsync(x => x.UID.ToString() == taskItem.TaskString);

                foreach (var track in work.Tracks)
                {
                    var mf = track.MusicFiles.First(f => f.Encoding == EncodingType.flac);
                    var destinationFile = mf.File.Replace(mf.DiskRoot, vbrDestination.DiskRoot, StringComparison.CurrentCultureIgnoreCase);
                    destinationFile = destinationFile.Replace(".flac", ".mp3", StringComparison.CurrentCultureIgnoreCase);
                    var srcFi = new FileInfo(mf.File);
                    var vbrFi = new FileInfo(destinationFile);
                    if (!vbrFi.Exists || srcFi.LastWriteTimeUtc > vbrFi.LastWriteTimeUtc)
                    {
                        var existingVbr = track.MusicFiles.FirstOrDefault(f => f.IsGenerated);
                        if (existingVbr != null)
                        {
                            track.MusicFiles.Remove(existingVbr);
                            db.MusicFiles.Remove(existingVbr);
                        }
                        await Resample(srcFi.FullName, vbrFi.FullName);

                        vbrFi.Refresh();
                        AddToTrack(vbrDestination, track, mf, vbrFi);
                    }
                }
            }
            else
            {
                log.Warning($"{taskItem} Resampling failed as no source for generated files is available");
            }
            taskItem.FinishedAt = DateTimeOffset.Now;
            taskItem.Status     = Music.Core.TaskStatus.Finished;
            await db.SaveChangesAsync();
        }
示例#8
0
        protected async Task <Artist> GetArtistAsync(string name)
        {
            Debug.Assert(MusicDb != null);
            name = MusicOptions.ReplaceAlias(name);
            Artist artist = FindArtist(name);

            if (artist == null)
            {
                artist = new Artist
                {
                    UID          = Guid.NewGuid(),
                    Name         = name,
                    Type         = ArtistType.Artist,
                    OriginalName = name,
                };
                artist.ArtistStyles.Add(new ArtistStyle {
                    Artist = artist, StyleId = MusicStyle
                });
                log.Debug($"{taskItem} new artist instance for {name}, {artist.Id}");
                if (this is PopularMusicAlbumSet && OpusType == OpusType.Collection)
                {
                    artist.Type = ArtistType.Various;
                }
                await MusicDb.Artists.AddAsync(artist);

                await MusicDb.SaveChangesAsync();
            }
            if (artist.Type != ArtistType.Various)
            {
                // var artistFoldername = OpusType == OpusType.Collection ? null : FirstFile.OpusPath.Split('\\')[0];// Path.GetFileName(Path.GetDirectoryName(FirstFile.File));
                var portrait = artist.GetPortraitFile(MusicOptions);
                if (portrait != null)
                {
                    artist.Portrait = await portrait.GetImage();
                }
            }
            artist.LastModified = DateTimeOffset.Now;
            return(artist);
        }
示例#9
0
        private async Task LoadOutstandingTasks()
        {
            var now  = DateTimeOffset.Now;
            var list = new List <TaskItem>();

            using (var db = new MusicDb(connectionString))
            {
                foreach (var ti in db.TaskItems.Where(x =>
                                                      x.Type != TaskType.ResampleWork && x.Status != Music.Core.TaskStatus.Finished && x.Status != Music.Core.TaskStatus.Failed))
                {
                    ti.Status      = Music.Core.TaskStatus.Pending;
                    ti.ScheduledAt = now;
                    ti.FinishedAt  = default;
                    list.Add(ti);
                }
                await db.SaveChangesAsync();
            }
            foreach (var item in list)
            {
                //taskRunner.TaskAdded(item.Id, item.Type);
                taskRunner.QueueTask(item);
            }
        }
示例#10
0
        private async Task <List <CatalogueResult> > ProcessFolderAsync(MusicDb db, OpusFolder folder)
        {
            var results = new List <CatalogueResult>();

            db.Database.SetCommandTimeout(TimeSpan.FromMinutes(10));
            StepTimer st = null;

            if (musicOptions.TimeCatalogueSteps)
            {
                st = new StepTimer();
                st.Start();
            }
            if (/*true ||*/ taskItem.Force)
            {
                var deletedFilesCount = folder.RemoveCurrentMusicFiles(db); st?.Time("Removal");
                if (deletedFilesCount > 0)
                {
                    await db.SaveChangesAsync();
                }
            }
            var musicFiles = await WriteAudioFilesAsync(db, folder); st?.Time("MusicFiles to DB");

            if (musicFiles.Count() > 0) // count is 0 most often when trying to find singles for an artist
            {
                await UpdateTagsAsync(db, musicFiles); st?.Time("Extract tags");
                var musicSets = GetMusicSets(db, folder, musicFiles); st?.Time("Split into sets");
                int i         = 0;
                foreach (var set in musicSets)
                {
                    var cr = await set.CatalogueAsync(); st?.Time($"Set {i++ + 1}");
                    results.Add(cr);
                    if (cr.Status == CatalogueStatus.Success)
                    {
                        if (cr.Artist == null)
                        {
                            log.Trace($"Artist missing");
                        }
                        switch (cr.MusicSetType)
                        {
                        case Type T when T == typeof(PopularMusicAlbumSet) || T == typeof(WesternClassicalAlbumSet):
                            if (cr.Work == null)
                            {
                                log.Trace($"Album missing");
                            }
                            else if (cr.Work.Tracks == null || cr.Work.Tracks.Count() == 0)
                            {
                                log.Trace($"Work has no tracks");
                            }
                            if (cr.Tracks == null)
                            {
                                log.Trace($"Tracks missing");
                            }
                            else if (cr.Tracks.Count() == 0)
                            {
                                log.Trace($"Track count is 0");
                            }
                            //if(cr.TaskItem != null)
                            //{
                            //    QueueTask(cr.TaskItem);
                            //}
                            break;

                        case Type T when T == typeof(WesternClassicalCompositionSet):
                            if (cr.Composition == null)
                            {
                                log.Trace($"Composition missing");
                            }
                            if (cr.Performance == null)
                            {
                                log.Trace($"Performance missing");
                            }
                            else if (cr.Performance.Movements == null || cr.Performance.Movements.Count() == 0)
                            {
                                log.Trace($"Performance has no movements");
                            }

                            break;
                        }
                    }
                }
            }
            else
            {
                results.Add(new CatalogueResult {
                    Status = CatalogueStatus.Success
                });
            }
            return(results);
        }
示例#11
0
        private async Task ExpandAsync(MusicDb db)
        {
            this.db = db;
            List <TaskItem> taskList = null;// new List<TaskItem>();
            var             ti       = await db.TaskItems.FindAsync(taskId);

            switch (ti.Type)
            {
            case TaskType.ArtistFolder:
                taskList = ExpandArtistFolder(taskData);
                break;

            case TaskType.ArtistName:
                taskList = ExpandArtistName(taskData);
                break;

            case TaskType.MusicStyle:
                taskList = ExpandMusicStyle(musicStyle);
                break;

            default:
                log.Warning($"Task id {taskId} unexpected task type {ti.Type}");
                break;
            }
            ti.Status     = Music.Core.TaskStatus.Finished;
            ti.FinishedAt = DateTimeOffset.Now;
            if (taskList.Count() > 0)
            {
                foreach (var item in taskList)
                {
                    item.Force = ti.Force;
                }
                var generatedRoots = new List <string>();
                foreach (var source in new MusicSources(musicOptions))
                {
                    if (source.IsGenerated)
                    {
                        generatedRoots.Add(source.DiskRoot);
                    }
                }
                var generatedItems = taskList.Where(x => generatedRoots.Any(z => x.TaskString.StartsWith(z, System.Globalization.CompareOptions.IgnoreCase))).ToList();
                var originalItems  = taskList.Except(generatedItems).ToList();
                originalItems.Shuffle();
                generatedItems.Shuffle();
                db.TaskItems.AddRange(originalItems);
                await db.SaveChangesAsync();

                db.TaskItems.AddRange(generatedItems);
            }
            await db.SaveChangesAsync();

            if (taskList.Count() > 0)
            {
                foreach (var item in taskList.OrderBy(t => t.Id))
                {
                    QueueTask(item);
                }
                var taskIdList = taskList.Select(t => t.Id).OrderBy(x => x);
                log.Information($"{ti} expanded to {taskIdList.Count()} items from [TI-{taskIdList.First()}] to [TI-{taskIdList.Last()}]");
            }
            else
            {
                log.Information($"{ti} expanded to 0 items");
            }
        }
示例#12
0
        private async Task ResampleAsync(long taskId)
        {
            using (var db = new MusicDb(connectionString))
            {
                TaskItem taskItem = null;
                db.ChangeTracker.AutoDetectChangesEnabled = false;
                taskItem = await db.TaskItems.FindAsync(taskId);

                var sources        = new MusicSources(musicOptions, true);
                var vbrDestination = sources.FirstOrDefault(x => x.IsGenerated);
                if (vbrDestination != null)
                {
                    var work = await db.Works.SingleOrDefaultAsync(x => x.UID.ToString() == taskItem.TaskString);

                    if (work != null)
                    {
                        //log.Information($"Resampling {work.Artist.Name}, {work.Name}");
                        int resampledCount = 0;
                        foreach (var track in work.Tracks)
                        {
                            var mf = track.MusicFiles.First(f => f.Encoding == EncodingType.flac);
                            var destinationFile = mf.File.Replace(mf.DiskRoot, vbrDestination.DiskRoot, StringComparison.CurrentCultureIgnoreCase);
                            destinationFile = destinationFile.Replace(".flac", ".mp3", StringComparison.CurrentCultureIgnoreCase);
                            var srcFi = new FileInfo(mf.File);
                            var vbrFi = new FileInfo(destinationFile);
                            if (!vbrFi.Exists || srcFi.LastWriteTimeUtc > vbrFi.LastWriteTimeUtc)
                            {
                                await Resample(taskItem, srcFi.FullName, vbrFi.FullName);

                                vbrFi.Refresh();
                                resampledCount++;
                            }
                            else
                            {
                                log.Debug($"{taskItem} {vbrFi.Name} is up to date");
                            }
                            var existingVbr = track.MusicFiles.FirstOrDefault(f => f.IsGenerated);
                            if (existingVbr != null)
                            {
                                track.MusicFiles.Remove(existingVbr);
                                db.MusicFiles.Remove(existingVbr);
                            }
                            AddToTrack(vbrDestination, track, mf, vbrFi);
                            await db.SaveChangesAsync();
                        }
                        log.Information($"{taskItem} resampling completed {work.Artist.Name}, {work.Name}, {resampledCount}/{work.Tracks.Count()} files");
                    }
                    else
                    {
                        log.Warning($"{taskItem} work with uid {taskItem.TaskString} not found");
                        taskItem.FinishedAt = DateTimeOffset.Now;
                        taskItem.Status     = Music.Core.TaskStatus.Failed;
                        await db.SaveChangesAsync();

                        return;
                    }
                }
                else
                {
                    log.Warning($"{taskItem} Resampling failed as no source for generated files is available");
                }
                taskItem.FinishedAt = DateTimeOffset.Now;
                taskItem.Status     = Music.Core.TaskStatus.Finished;
                await db.SaveChangesAsync();
            }
        }
示例#13
0
        private async Task DeleteAsync(MusicDb db, PathData pd)
        {
            db.ChangeTracker.AutoDetectChangesEnabled = false;
            taskItem = await db.TaskItems.FindAsync(taskId);

            IEnumerable <MusicFile> musicFileList = null;
            string path = "";

            if (pd.GetFullOpusPath() != null)
            {
                path          = pd.IsCollections ? pd.OpusPath : $"{pd.ArtistPath}\\{pd.OpusPath}";
                musicFileList = db.MusicFiles
                                .Where(f => (f.DiskRoot.ToLower() == pd.DiskRoot.ToLower()) &&
                                       (f.StylePath.ToLower() == pd.StylePath.ToLower()) &&
                                       (f.OpusPath.ToLower() == path.ToLower()))
                                .OrderBy(f => f.File)
                ;
            }
            else
            {
                if (pd.IsCollections)
                {
                    musicFileList = db.MusicFiles
                                    .Where(f => (f.DiskRoot.ToLower() == pd.DiskRoot.ToLower()) &&
                                           (f.StylePath.ToLower() == pd.StylePath.ToLower()) &&
                                           f.Musician.ToLower() == "collections")
                                    .OrderBy(f => f.File)
                    ;
                }
                else
                {
                    musicFileList = db.MusicFiles
                                    .Where(f => (f.DiskRoot.ToLower() == pd.DiskRoot.ToLower()) &&
                                           (f.StylePath.ToLower() == pd.StylePath.ToLower()) &&
                                           f.OpusPath.StartsWith(pd.ArtistPath))
                                    .OrderBy(f => f.File)
                    ;
                }
            }

            log.Information($"Deleting {musicFileList.Count()} music files");
            var dc = new DeleteContext(taskItem);

            foreach (var mf in musicFileList)
            {
                db.Delete(mf, dc);
            }
            taskItem.Status     = Music.Core.TaskStatus.Finished;
            taskItem.FinishedAt = DateTimeOffset.Now;
            await db.SaveChangesAsync();

            if (dc.DeletedArtistId.HasValue)
            {
                await this.playManager.SendArtistDeleted(dc.DeletedArtistId.Value);
            }
            else if (dc.ModifiedArtistId.HasValue)
            {
                var shouldSend = true;
                var artist     = await db.Artists.FindAsync(dc.ModifiedArtistId.Value);

                if (artist != null)
                {
                    shouldSend = artist.Type != ArtistType.Various;
                }
                if (shouldSend)
                {
                    await this.playManager.SendArtistNewOrModified(dc.ModifiedArtistId.Value);
                }
            }
            //if (dc.DeletedArtistId.HasValue || dc.ModifiedArtistId.HasValue)
            //{
            //    var shouldSend = true;
            //    var id = dc.ModifiedArtistId ?? 0;
            //    if (id > 0)
            //    {
            //        var artist = await db.Artists.FindAsync(id);
            //        shouldSend = artist.Type != ArtistType.Various;
            //    }
            //    if (shouldSend)
            //    {
            //        if (dc.DeletedArtistId.HasValue)
            //        {
            //            await this.playManager.SendArtistDeleted(dc.DeletedArtistId.Value);
            //        }
            //        else if (dc.ModifiedArtistId.HasValue)
            //        {
            //            await this.playManager.SendArtistNewOrModified(dc.ModifiedArtistId.Value);
            //        }
            //    }
            //}
            // send artist modified/deleted - info is in dc
        }