diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..ced5401
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,15 @@
+{
+ // Use IntelliSense to learn about possible attributes.
+ // Hover to view descriptions of existing attributes.
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Launch",
+ "type": "xamarin",
+ "request": "launch",
+ "package": "com.your.app.package",
+ "intent": ""
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Aurora.gtk/Aurora.gtk.csproj b/Aurora.gtk/Aurora.gtk.csproj
index ae9fc38..dfeca64 100644
--- a/Aurora.gtk/Aurora.gtk.csproj
+++ b/Aurora.gtk/Aurora.gtk.csproj
@@ -64,6 +64,23 @@
..\packages\Xamarin.Forms.Platform.GTK.3.6.0.344457\lib\net45\Xamarin.Forms.Platform.GTK.dll
+
+ ..\packages\System.Reflection.4.3.0\lib\net462\System.Reflection.dll
+
+
+
+ ..\packages\System.Reflection.TypeExtensions.4.4.0\lib\net461\System.Reflection.TypeExtensions.dll
+
+
+ ..\packages\System.Runtime.Serialization.Primitives.4.3.0\lib\net46\System.Runtime.Serialization.Primitives.dll
+
+
+
+ ..\packages\taglib-sharp-netstandard2.0.2.1.0\lib\netstandard2.0\taglib-sharp.dll
+
+
+ ..\packages\Xamarin.Forms.DataGrid.3.1.0\lib\netstandard2.0\Xamarin.Forms.DataGrid.dll
+
diff --git a/Aurora.gtk/packages.config b/Aurora.gtk/packages.config
index 8a64bff..e160d7a 100644
--- a/Aurora.gtk/packages.config
+++ b/Aurora.gtk/packages.config
@@ -1,5 +1,10 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Aurora/Aurora.csproj b/Aurora/Aurora.csproj
index 03abbe3..0825bec 100644
--- a/Aurora/Aurora.csproj
+++ b/Aurora/Aurora.csproj
@@ -13,6 +13,8 @@
+
+
diff --git a/Aurora/Frontend/Models/Song.cs b/Aurora/Frontend/Models/Song.cs
new file mode 100644
index 0000000..bf17f18
--- /dev/null
+++ b/Aurora/Frontend/Models/Song.cs
@@ -0,0 +1,41 @@
+using System;
+
+namespace Aurora.Frontend.Views.Songs
+{
+ public class Song
+ {
+ public Song()
+ {
+ }
+
+ ///
+ /// The title of the song.
+ ///
+ ///
+ public string Title { get; set; }
+
+ ///
+ /// The artist of the song.
+ ///
+ ///
+ public string Artist { get; set; }
+
+ ///
+ /// The album from which the song belongs.
+ ///
+ ///
+ public string Album { get; set; }
+
+ ///
+ /// The duration of the song.
+ ///
+ ///
+ public string Duration { get; set; }
+
+ ///
+ /// Extra data associated with a song.
+ ///
+ ///
+ public object Metadata { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Aurora/Frontend/Utils/FileSystemUtils.cs b/Aurora/Frontend/Utils/FileSystemUtils.cs
new file mode 100644
index 0000000..b951088
--- /dev/null
+++ b/Aurora/Frontend/Utils/FileSystemUtils.cs
@@ -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.Frontend.Utils
+{
+ public class FileSystemUtils
+ {
+
+ public FileSystemUtils()
+ {
+ }
+
+
+ ///
+ /// Asynchronousely recursively traverse a directory path.
+ ///
+ /// The path to the directory to traverse
+ /// Comma separated list of file extensions to accept
+ public static List TraverseFoldersAsync(string path, string extensions)
+ {
+ string[] extensionList = extensions.Split(',');
+
+ ConcurrentBag tasks = new ConcurrentBag();
+ List outFiles = new List();
+ 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;
+ }
+
+
+
+ ///
+ /// Recursive method to capture children of a directory.
+ ///
+ /// The directory to traverse
+ /// The list of currently running tasks
+ private static void Traverse(DirectoryInfo dir, ConcurrentBag tasks, List 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;
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Aurora/Frontend/Views/Songs/SongsView.xaml b/Aurora/Frontend/Views/Songs/SongsView.xaml
index f6276ef..5a48407 100644
--- a/Aurora/Frontend/Views/Songs/SongsView.xaml
+++ b/Aurora/Frontend/Views/Songs/SongsView.xaml
@@ -1,6 +1,38 @@
-
+
-
+
+
+
+
+
+ 15
+ 13
+ 20
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ #F2F2F2
+ #FFFFFF
+
+
+
+
+
diff --git a/Aurora/Frontend/Views/Songs/SongsView.xaml.cs b/Aurora/Frontend/Views/Songs/SongsView.xaml.cs
index 24e46e8..859ee32 100644
--- a/Aurora/Frontend/Views/Songs/SongsView.xaml.cs
+++ b/Aurora/Frontend/Views/Songs/SongsView.xaml.cs
@@ -10,6 +10,7 @@ namespace Aurora.Frontend.Views.Songs
public SongsView()
{
InitializeComponent();
+ BindingContext = new SongsViewModel();
}
}
}
diff --git a/Aurora/Frontend/Views/Songs/SongsViewModel.cs b/Aurora/Frontend/Views/Songs/SongsViewModel.cs
index ac83454..532d241 100644
--- a/Aurora/Frontend/Views/Songs/SongsViewModel.cs
+++ b/Aurora/Frontend/Views/Songs/SongsViewModel.cs
@@ -1,10 +1,77 @@
using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.IO;
+using Aurora.Frontend.Utils;
+
namespace Aurora.Frontend.Views.Songs
{
- public class SongsViewModel
+ public class SongsViewModel : BaseViewModel
{
+ #region Fields
+ private string _pathName = "/Users/brandonwatson/Music/iTunes/iTunes Media/Music";
+ private string _extensions = ".wav,.mp3,.aiff,.flac,.m4a,.m4b,.wma";
+ private ObservableCollection _songsList;
+ private Song _selectedSong;
+
+ #endregion Fields
+
+ #region Constructor
public SongsViewModel()
{
+ _songsList = new ObservableCollection();
+ Initialize();
}
+
+ #endregion Constructor
+
+ #region Properties
+ public ObservableCollection SongsList
+ {
+ get { return _songsList; }
+ set
+ {
+ if (value != _songsList)
+ {
+ _songsList = value;
+ OnPropertyChanged("SongList");
+ }
+ }
+ }
+
+ public Song SelectedSong
+ {
+ get { return _selectedSong; }
+ set
+ {
+ if (value != _selectedSong)
+ {
+ _selectedSong = value;
+ OnPropertyChanged("SelectedSong");
+ }
+ }
+ }
+
+ #endregion Properties
+
+ #region Methods
+ public void Initialize()
+ {
+ List musicFiles = FileSystemUtils.TraverseFoldersAsync(_pathName, _extensions);
+
+ foreach (FileInfo file in musicFiles)
+ {
+ TagLib.File tagFile = TagLib.File.Create(file.FullName);
+ _songsList.Add(new Song()
+ {
+ Title = tagFile.Tag.Title,
+ Album = tagFile.Tag.Album,
+ Artist = tagFile.Tag.FirstAlbumArtist
+ });
+ }
+ }
+
+ #endregion Methods
+
}
}
diff --git a/aurora.code-workspace b/aurora.code-workspace
new file mode 100644
index 0000000..362d7c2
--- /dev/null
+++ b/aurora.code-workspace
@@ -0,0 +1,7 @@
+{
+ "folders": [
+ {
+ "path": "."
+ }
+ ]
+}
\ No newline at end of file