Restructuring. Added services.
This commit is contained in:
56
Aurora/Backend/Models/BaseSong.cs
Normal file
56
Aurora/Backend/Models/BaseSong.cs
Normal file
@ -0,0 +1,56 @@
|
||||
using System;
|
||||
namespace Aurora.Backend.Models
|
||||
{
|
||||
public abstract class BaseSong
|
||||
{
|
||||
public BaseSong()
|
||||
{
|
||||
Id = Guid.NewGuid().ToString();
|
||||
}
|
||||
|
||||
#region Properties
|
||||
public string Id { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The title of the song.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The artist of the song.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public string Artist { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The album from which the song belongs.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public string Album { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The duration of the song.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public string Duration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Extra data associated with a song.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public object Metadata { get; set; }
|
||||
|
||||
|
||||
#endregion Properties
|
||||
|
||||
#region Methods
|
||||
/// <summary>
|
||||
/// Play this instance.
|
||||
/// </summary>
|
||||
public abstract void Play();
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
}
|
26
Aurora/Backend/Models/LocalSong.cs
Normal file
26
Aurora/Backend/Models/LocalSong.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Aurora.Backend.Models
|
||||
{
|
||||
public class LocalSong : BaseSong
|
||||
{
|
||||
public LocalSong(FileInfo fileInfo)
|
||||
{
|
||||
File = fileInfo;
|
||||
}
|
||||
|
||||
#region Properties
|
||||
public FileInfo File { get; private set; }
|
||||
|
||||
#endregion Properties
|
||||
|
||||
#region Methods
|
||||
public override void Play()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion Methods
|
||||
}
|
||||
}
|
22
Aurora/Backend/Services/BaseService.cs
Normal file
22
Aurora/Backend/Services/BaseService.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
|
||||
namespace Aurora.Backend.Services
|
||||
{
|
||||
public abstract class BaseService<T> where T : class
|
||||
{
|
||||
private static volatile Lazy<T> _instance = new Lazy<T>(() => CreateInstanceOfT());
|
||||
|
||||
public static T Instance
|
||||
{
|
||||
get { return _instance.Value; }
|
||||
}
|
||||
|
||||
private static T CreateInstanceOfT()
|
||||
{
|
||||
|
||||
return Activator.CreateInstance(typeof(T), true) as T;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
65
Aurora/Backend/Services/LibraryService.cs
Normal file
65
Aurora/Backend/Services/LibraryService.cs
Normal file
@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using Aurora.Backend.Models;
|
||||
using Aurora.Backend.Utils;
|
||||
using NAudio.Wave;
|
||||
|
||||
namespace Aurora.Backend.Services
|
||||
{
|
||||
public class LibraryService : BaseService<LibraryService>
|
||||
{
|
||||
#region Fields
|
||||
private string _pathName = "/Users/brandonwatson/Music/iTunes/iTunes Media/Music";
|
||||
private string _extensions = ".wav,.mp3,.aiff,.flac,.m4a,.m4b,.wma";
|
||||
private Dictionary<string, Song> _library;
|
||||
|
||||
|
||||
#endregion Fields
|
||||
|
||||
public LibraryService()
|
||||
{
|
||||
_library = new Dictionary<string, Song>();
|
||||
LoadLibrary();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the songs.
|
||||
/// </summary>
|
||||
/// <returns>The songs.</returns>
|
||||
public ObservableCollection<Song> GetLibrary()
|
||||
{
|
||||
ObservableCollection<Song> collection = new ObservableCollection<Song>();
|
||||
foreach (KeyValuePair<string, Song> pair in _library)
|
||||
{
|
||||
collection.Add(pair.Value);
|
||||
}
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads library from files.
|
||||
/// </summary>
|
||||
private void LoadLibrary()
|
||||
{
|
||||
//Get songs
|
||||
List<FileInfo> musicFiles = FileSystemUtils.TraverseFoldersAsync(_pathName, _extensions);
|
||||
|
||||
foreach (FileInfo file in musicFiles)
|
||||
{
|
||||
TagLib.File tagFile = TagLib.File.Create(file.FullName);
|
||||
|
||||
Song song = new Song(file)
|
||||
{
|
||||
Title = tagFile.Tag.Title,
|
||||
Album = tagFile.Tag.Album,
|
||||
Artist = tagFile.Tag.FirstAlbumArtist
|
||||
};
|
||||
|
||||
_library.Add(song.Id, song);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
82
Aurora/Backend/Utils/FileSystemUtils.cs
Normal file
82
Aurora/Backend/Utils/FileSystemUtils.cs
Normal file
@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Aurora.Backend.Utils
|
||||
{
|
||||
public class FileSystemUtils
|
||||
{
|
||||
|
||||
public FileSystemUtils()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronousely recursively traverse a directory path.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the directory to traverse</param>
|
||||
/// <param name="extensions">Comma separated list of file extensions to accept</param>
|
||||
public static List<FileInfo> TraverseFoldersAsync(string path, string extensions)
|
||||
{
|
||||
string[] extensionList = extensions.Split(',');
|
||||
|
||||
ConcurrentBag<Task> tasks = new ConcurrentBag<Task>();
|
||||
List<FileInfo> outFiles = new List<FileInfo>();
|
||||
DirectoryInfo directoryInfo = new DirectoryInfo(path);
|
||||
|
||||
tasks.Add(Task.Run(() => Traverse(directoryInfo, tasks, outFiles, extensionList)));
|
||||
|
||||
Task waitingTask;
|
||||
while (tasks.TryTake(out waitingTask))
|
||||
{
|
||||
waitingTask.Wait();
|
||||
}
|
||||
|
||||
return outFiles;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Recursive method to capture children of a directory.
|
||||
/// </summary>
|
||||
/// <param name="dir">The directory to traverse</param>
|
||||
/// <param name="tasks">The list of currently running tasks</param>
|
||||
private static void Traverse(DirectoryInfo dir, ConcurrentBag<Task> tasks, List<FileInfo> outFiles, string[] extensions)
|
||||
{
|
||||
try
|
||||
{
|
||||
DirectoryInfo[] directoryInfos = dir.GetDirectories();
|
||||
//Enque children
|
||||
foreach (DirectoryInfo childInfo in directoryInfos)
|
||||
{
|
||||
tasks.Add(Task.Run(() => Traverse(childInfo, tasks, outFiles, extensions)));
|
||||
}
|
||||
|
||||
//Collect files
|
||||
foreach (FileInfo fileInfo in dir.GetFiles())
|
||||
{
|
||||
if (extensions.Any(e => e == fileInfo.Extension))
|
||||
{
|
||||
//Don't know if this lock is necessary
|
||||
lock (outFiles)
|
||||
{
|
||||
outFiles.Add(fileInfo);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"{ex.GetType()} {ex.Message}\n{ex.StackTrace}");
|
||||
ex = ex.InnerException;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user