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(); }
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!!!!!!!!!!!!!!!!!!!!!"); }
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()); }
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); }
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 }; } }
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())); }
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(); }
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); }
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); } }
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); }
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"); } }
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(); } }
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 }