Modified Song model, added more functionality to the Album context and store, and need to work on how album records are handled when uploading songs. I left TODO's on where to pick up. #22, #25, #29
This commit is contained in:
+447
-428
@@ -12,468 +12,487 @@ using Id3;
|
||||
using Id3.Frames;
|
||||
using MySql.Data;
|
||||
using MySql.Data.MySqlClient;
|
||||
using NLog;
|
||||
using TagLib;
|
||||
|
||||
using Icarus.Models;
|
||||
using Icarus.Controllers.Utilities;
|
||||
using Icarus.Models;
|
||||
using Icarus.Models.Context;
|
||||
|
||||
namespace Icarus.Controllers.Managers
|
||||
{
|
||||
public class SongManager
|
||||
{
|
||||
#region Fields
|
||||
private MySqlConnection _conn;
|
||||
private MySqlCommand _cmd;
|
||||
private MySqlDataAdapter _dataDump;
|
||||
private DataTable _results;
|
||||
private List<Song> _songs;
|
||||
private Song _song;
|
||||
private IConfiguration _config;
|
||||
private string _connectionString;
|
||||
private string _tempDirectoryRoot;
|
||||
private string _archiveDirectoryRoot;
|
||||
private string _compressedSongFilename;
|
||||
#endregion
|
||||
public class SongManager
|
||||
{
|
||||
#region Fields
|
||||
private static Logger _logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
|
||||
private MySqlConnection _conn;
|
||||
private MySqlCommand _cmd;
|
||||
private MySqlDataAdapter _dataDump;
|
||||
private DataTable _results;
|
||||
private List<Song> _songs;
|
||||
private Song _song;
|
||||
private IConfiguration _config;
|
||||
private string _connectionString;
|
||||
private string _tempDirectoryRoot;
|
||||
private string _archiveDirectoryRoot;
|
||||
private string _compressedSongFilename;
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
public Song SongDetails
|
||||
{
|
||||
get => _song;
|
||||
set => _song = value;
|
||||
}
|
||||
|
||||
public string ArchiveDirectoryRoot
|
||||
{
|
||||
get => _archiveDirectoryRoot;
|
||||
set => _archiveDirectoryRoot = value;
|
||||
}
|
||||
public string CompressedSongFilename
|
||||
{
|
||||
get => _compressedSongFilename;
|
||||
set => _compressedSongFilename = value;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructors
|
||||
public SongManager()
|
||||
{
|
||||
Initialize();
|
||||
InitializeConnection();
|
||||
}
|
||||
|
||||
public SongManager(Song song)
|
||||
{
|
||||
Initialize();
|
||||
InitializeConnection();
|
||||
_song = song;
|
||||
}
|
||||
public SongManager(IConfiguration config)
|
||||
{
|
||||
_config = config;
|
||||
Initialize();
|
||||
InitializeConnection();
|
||||
}
|
||||
public SongManager(IConfiguration config, string tempDirectoryRoot)
|
||||
{
|
||||
_config = config;
|
||||
_tempDirectoryRoot = tempDirectoryRoot;
|
||||
Initialize();
|
||||
InitializeConnection();
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
public bool DeleteSongFromFileSystem(Song songMetaData)
|
||||
{
|
||||
bool successful = false;
|
||||
try
|
||||
{
|
||||
var songPath = songMetaData.SongPath;
|
||||
System.IO.File.Delete(songPath);
|
||||
successful = true;
|
||||
DirectoryManager dirMgr = new DirectoryManager(_config, songMetaData);
|
||||
dirMgr.DeleteEmptyDirectories();
|
||||
Console.WriteLine("Song successfully deleted");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
}
|
||||
|
||||
return successful;
|
||||
}
|
||||
|
||||
public void SaveSongDetails()
|
||||
{
|
||||
try
|
||||
{
|
||||
using (MySqlConnection conn = new MySqlConnection(_connectionString))
|
||||
#region Properties
|
||||
public Song SongDetails
|
||||
{
|
||||
conn.Open();
|
||||
string query = "INSERT INTO Songs(Title, Album, Artist, Year, Genre, Duration, " +
|
||||
"Filename, SongPath) VALUES(@Title, @Album, @Artist, @Year, @Genre, " +
|
||||
"@Duration, @Filename, @SongPath)";
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@Title", _song.Title);
|
||||
cmd.Parameters.AddWithValue("@Album", _song.Album);
|
||||
cmd.Parameters.AddWithValue("@Artist", _song.Artist);
|
||||
cmd.Parameters.AddWithValue("@Year", _song.Year);
|
||||
cmd.Parameters.AddWithValue("@Genre", _song.Genre);
|
||||
cmd.Parameters.AddWithValue("@Duration", _song.Duration);
|
||||
cmd.Parameters.AddWithValue("@Filename", _song.Filename);
|
||||
cmd.Parameters.AddWithValue("@SongPath", _song.SongPath);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
get => _song;
|
||||
set => _song = value;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
Console.WriteLine($"An Error Occurred: {exMsg}");
|
||||
}
|
||||
}
|
||||
public void SaveSongDetails(Song song)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (MySqlConnection conn = new MySqlConnection(_connectionString))
|
||||
{
|
||||
conn.Open();
|
||||
string query = "INSERT INTO Songs(Title, Album, Artist, Year, Genre, Duration, " +
|
||||
", Filename, SongPath) VALUES(@Title, @Album, @Artist, @Year, @Genre, " +
|
||||
"@Duration, @Filename, @SongPath)";
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@Title", song.Title);
|
||||
cmd.Parameters.AddWithValue("@Album", song.Album);
|
||||
cmd.Parameters.AddWithValue("@Artist", song.Artist);
|
||||
cmd.Parameters.AddWithValue("@Year", song.Year);
|
||||
cmd.Parameters.AddWithValue("@Genre", song.Genre);
|
||||
cmd.Parameters.AddWithValue("@Duration", song.Duration);
|
||||
cmd.Parameters.AddWithValue("@Filename", song.Filename);
|
||||
cmd.Parameters.AddWithValue("@SongPath", song.SongPath);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
public string ArchiveDirectoryRoot
|
||||
{
|
||||
get => _archiveDirectoryRoot;
|
||||
set => _archiveDirectoryRoot = value;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
Console.WriteLine($"An Error Occurred: {exMsg}");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SaveSong(SongData songData)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (MySqlConnection conn = new MySqlConnection(_connectionString))
|
||||
public string CompressedSongFilename
|
||||
{
|
||||
conn.Open();
|
||||
string query = "INSERT INTO SongData(Data) VALUES(@Data)";
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@Data", songData.Data);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
get => _compressedSongFilename;
|
||||
set => _compressedSongFilename = value;
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
Console.WriteLine($"An error occurred: {exMsg}");
|
||||
}
|
||||
}
|
||||
public async Task SaveSongToFileSystem(IFormFile song)
|
||||
{
|
||||
try
|
||||
{
|
||||
Console.WriteLine("Saving song to the filesystem");
|
||||
var filePath = Path.Combine(_tempDirectoryRoot, song.FileName);
|
||||
Console.WriteLine("Saving song to the filePath");
|
||||
await SaveSongToFileSystemTemp(song, filePath);
|
||||
System.IO.File.Delete(filePath);
|
||||
#endregion
|
||||
|
||||
|
||||
DirectoryManager dirMgr = new DirectoryManager(_config, _song);
|
||||
dirMgr.CreateDirectory();
|
||||
filePath = dirMgr.SongDirectory;
|
||||
if (!song.FileName.EndsWith(".mp3"))
|
||||
filePath += $"{song.FileName}.mp3";
|
||||
else
|
||||
filePath += $"{song.FileName}";
|
||||
|
||||
Console.WriteLine($"Full path {filePath}");
|
||||
|
||||
using (var fileStream = new FileStream(filePath, FileMode.Create))
|
||||
#region Constructors
|
||||
public SongManager()
|
||||
{
|
||||
await song.CopyToAsync(fileStream);
|
||||
_song.SongPath = filePath;
|
||||
|
||||
Console.WriteLine($"Writing song to the directory: {filePath}");
|
||||
Initialize();
|
||||
InitializeConnection();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
Console.WriteLine($"An error occurred: {exMsg}");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<List<Song>> RetrieveAllSongDetails()
|
||||
{
|
||||
try
|
||||
{
|
||||
InitializeResults();
|
||||
_songs = new List<Song>();
|
||||
_conn.Open();
|
||||
string query = "SELECT * FROM Songs";
|
||||
|
||||
_cmd = new MySqlCommand(query, _conn);
|
||||
_cmd.ExecuteNonQuery();
|
||||
|
||||
_dataDump = new MySqlDataAdapter(_cmd);
|
||||
_dataDump.Fill(_results);
|
||||
_dataDump.Dispose();
|
||||
|
||||
await PopulateSongDetails();
|
||||
|
||||
|
||||
_conn.Close();
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
Console.WriteLine($"An error ocurred: {exMsg}");
|
||||
}
|
||||
|
||||
return _songs;
|
||||
}
|
||||
public async Task<Song> RetrieveSongDetails(int id)
|
||||
{
|
||||
DataTable results = new DataTable();
|
||||
|
||||
try
|
||||
{
|
||||
using (MySqlConnection conn = new MySqlConnection(_connectionString))
|
||||
public SongManager(Song song)
|
||||
{
|
||||
conn.Open();
|
||||
string query = "SELECT * FROM Songs WHERE Id=@Id";
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@Id", id);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
Initialize();
|
||||
InitializeConnection();
|
||||
_song = song;
|
||||
}
|
||||
public SongManager(IConfiguration config)
|
||||
{
|
||||
_config = config;
|
||||
Initialize();
|
||||
InitializeConnection();
|
||||
}
|
||||
public SongManager(IConfiguration config, string tempDirectoryRoot)
|
||||
{
|
||||
_config = config;
|
||||
_tempDirectoryRoot = tempDirectoryRoot;
|
||||
Initialize();
|
||||
InitializeConnection();
|
||||
}
|
||||
#endregion
|
||||
|
||||
using (MySqlDataAdapter dataDump = new MySqlDataAdapter(cmd))
|
||||
|
||||
#region Methods
|
||||
public bool DeleteSongFromFileSystem(Song songMetaData)
|
||||
{
|
||||
bool successful = false;
|
||||
try
|
||||
{
|
||||
var songPath = songMetaData.SongPath;
|
||||
System.IO.File.Delete(songPath);
|
||||
successful = true;
|
||||
DirectoryManager dirMgr = new DirectoryManager(_config, songMetaData);
|
||||
dirMgr.DeleteEmptyDirectories();
|
||||
Console.WriteLine("Song successfully deleted");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
}
|
||||
|
||||
return successful;
|
||||
}
|
||||
|
||||
public void SaveSongDetails()
|
||||
{
|
||||
try
|
||||
{
|
||||
using (MySqlConnection conn = new MySqlConnection(_connectionString))
|
||||
{
|
||||
conn.Open();
|
||||
string query = "INSERT INTO Songs(Title, Album, Artist, Year, Genre, Duration, " +
|
||||
"Filename, SongPath) VALUES(@Title, @Album, @Artist, @Year, @Genre, " +
|
||||
"@Duration, @Filename, @SongPath)";
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@Title", _song.Title);
|
||||
cmd.Parameters.AddWithValue("@Album", _song.Album);
|
||||
cmd.Parameters.AddWithValue("@Artist", _song.Artist);
|
||||
cmd.Parameters.AddWithValue("@Year", _song.Year);
|
||||
cmd.Parameters.AddWithValue("@Genre", _song.Genre);
|
||||
cmd.Parameters.AddWithValue("@Duration", _song.Duration);
|
||||
cmd.Parameters.AddWithValue("@Filename", _song.Filename);
|
||||
cmd.Parameters.AddWithValue("@SongPath", _song.SongPath);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
Console.WriteLine($"An Error Occurred: {exMsg}");
|
||||
}
|
||||
}
|
||||
public void SaveSongDetails(Song song)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (MySqlConnection conn = new MySqlConnection(_connectionString))
|
||||
{
|
||||
conn.Open();
|
||||
string query = "INSERT INTO Songs(Title, Album, Artist, Year, Genre, Duration, " +
|
||||
", Filename, SongPath) VALUES(@Title, @Album, @Artist, @Year, @Genre, " +
|
||||
"@Duration, @Filename, @SongPath)";
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@Title", song.Title);
|
||||
cmd.Parameters.AddWithValue("@Album", song.Album);
|
||||
cmd.Parameters.AddWithValue("@Artist", song.Artist);
|
||||
cmd.Parameters.AddWithValue("@Year", song.Year);
|
||||
cmd.Parameters.AddWithValue("@Genre", song.Genre);
|
||||
cmd.Parameters.AddWithValue("@Duration", song.Duration);
|
||||
cmd.Parameters.AddWithValue("@Filename", song.Filename);
|
||||
cmd.Parameters.AddWithValue("@SongPath", song.SongPath);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
Console.WriteLine($"An Error Occurred: {exMsg}");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SaveSong(SongData songData)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (MySqlConnection conn = new MySqlConnection(_connectionString))
|
||||
{
|
||||
conn.Open();
|
||||
string query = "INSERT INTO SongData(Data) VALUES(@Data)";
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@Data", songData.Data);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
Console.WriteLine($"An error occurred: {exMsg}");
|
||||
}
|
||||
}
|
||||
public async Task SaveSongToFileSystem(IFormFile song)
|
||||
{
|
||||
try
|
||||
{
|
||||
Console.WriteLine("Saving song to the filesystem");
|
||||
var filePath = Path.Combine(_tempDirectoryRoot, song.FileName);
|
||||
Console.WriteLine("Saving song to the filePath");
|
||||
await SaveSongToFileSystemTemp(song, filePath);
|
||||
System.IO.File.Delete(filePath);
|
||||
|
||||
|
||||
DirectoryManager dirMgr = new DirectoryManager(_config, _song);
|
||||
dirMgr.CreateDirectory();
|
||||
filePath = dirMgr.SongDirectory;
|
||||
if (!song.FileName.EndsWith(".mp3"))
|
||||
filePath += $"{song.FileName}.mp3";
|
||||
else
|
||||
filePath += $"{song.FileName}";
|
||||
|
||||
Console.WriteLine($"Full path {filePath}");
|
||||
|
||||
using (var fileStream = new FileStream(filePath, FileMode.Create))
|
||||
{
|
||||
await song.CopyToAsync(fileStream);
|
||||
_song.SongPath = filePath;
|
||||
|
||||
Console.WriteLine($"Writing song to the directory: {filePath}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
Console.WriteLine($"An error occurred: {exMsg}");
|
||||
}
|
||||
}
|
||||
public async Task SaveSongToFileSystem(IFormFile song, MusicStoreContext sStoreContext,
|
||||
AlbumStoreContext alStoreContext,
|
||||
ArtistStoreContext arStoreContext)
|
||||
{
|
||||
try
|
||||
{
|
||||
dataDump.Fill(results);
|
||||
// TODO: Define and implement method that will take care of the
|
||||
// song and album records, eventually will address the artist
|
||||
// records. Make use of helper functions
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
Console.WriteLine($"An error occurred");
|
||||
}
|
||||
|
||||
public async Task<List<Song>> RetrieveAllSongDetails()
|
||||
{
|
||||
try
|
||||
{
|
||||
InitializeResults();
|
||||
_songs = new List<Song>();
|
||||
_conn.Open();
|
||||
string query = "SELECT * FROM Songs";
|
||||
|
||||
_cmd = new MySqlCommand(query, _conn);
|
||||
_cmd.ExecuteNonQuery();
|
||||
|
||||
_dataDump = new MySqlDataAdapter(_cmd);
|
||||
_dataDump.Fill(_results);
|
||||
_dataDump.Dispose();
|
||||
|
||||
await PopulateSongDetails();
|
||||
|
||||
|
||||
_conn.Close();
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
Console.WriteLine($"An error ocurred: {exMsg}");
|
||||
}
|
||||
|
||||
return _songs;
|
||||
}
|
||||
public async Task<Song> RetrieveSongDetails(int id)
|
||||
{
|
||||
DataTable results = new DataTable();
|
||||
|
||||
try
|
||||
{
|
||||
using (MySqlConnection conn = new MySqlConnection(_connectionString))
|
||||
{
|
||||
conn.Open();
|
||||
string query = "SELECT * FROM Songs WHERE Id=@Id";
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@Id", id);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
|
||||
using (MySqlDataAdapter dataDump = new MySqlDataAdapter(cmd))
|
||||
{
|
||||
dataDump.Fill(results);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
Console.WriteLine($"An error occurred");
|
||||
}
|
||||
|
||||
DataRow row = results.Rows[0];
|
||||
DataRow row = results.Rows[0];
|
||||
|
||||
return new Song
|
||||
{
|
||||
Id = Int32.Parse(row["Id"].ToString()),
|
||||
Filename = row["Filename"].ToString(),
|
||||
SongPath = row["SongPath"].ToString()
|
||||
};
|
||||
}
|
||||
public async Task<SongData> RetrieveSong(int id)
|
||||
{
|
||||
SongData song = new SongData();
|
||||
try
|
||||
{
|
||||
_song = await RetrieveSongDetails(id);
|
||||
song = await RetrieveSongFromFileSystem(_song);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
Console.WriteLine($"An error occurred: {exMsg}");
|
||||
}
|
||||
|
||||
return song;
|
||||
}
|
||||
public async Task<SongData> RetrieveSong(Song songMetaData)
|
||||
{
|
||||
SongData song = new SongData();
|
||||
try
|
||||
{
|
||||
Console.WriteLine("Fetching song from filesystem");
|
||||
song = await RetrieveSongFromFileSystem(songMetaData);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
Console.WriteLine($"An error occurred: {exMsg}");
|
||||
}
|
||||
|
||||
return song;
|
||||
}
|
||||
|
||||
|
||||
Song RetrieveMetaData(string filePath)
|
||||
{
|
||||
Song newSong = new Song
|
||||
{
|
||||
Title = "Untitled",
|
||||
Artist = "Untitled",
|
||||
Album = "Untitled",
|
||||
Year = 0,
|
||||
Genre = "Untitled",
|
||||
Duration = 0,
|
||||
SongPath = ""
|
||||
};
|
||||
string title, artist, album, genre;
|
||||
int year, duration;
|
||||
|
||||
Console.WriteLine("Stripping song metadata");
|
||||
try
|
||||
{
|
||||
TagLib.File tfile = TagLib.File.Create(filePath);
|
||||
|
||||
|
||||
using (var mp3 = new Mp3(filePath))
|
||||
{
|
||||
Id3Tag tag = mp3.GetTag(Id3TagFamily.Version2X);
|
||||
title = tag.Title;
|
||||
Console.WriteLine("Title: {0}", title);
|
||||
newSong.Title = title;
|
||||
artist = tag.Artists;
|
||||
Console.WriteLine("Artist: {0}", artist);
|
||||
newSong.Artist = artist;
|
||||
album = tag.Album;
|
||||
Console.WriteLine("Album: {0}", album);
|
||||
newSong.Album = album;
|
||||
genre = "Not Implemented";
|
||||
Console.WriteLine("Genre: {0}", genre);
|
||||
newSong.Genre = genre;
|
||||
year = (int)tag.Year;
|
||||
Console.WriteLine("Year: {0}", year);
|
||||
newSong.Year = year;
|
||||
duration = (int)tfile.Properties.Duration.TotalSeconds;
|
||||
Console.WriteLine("Duration: {0}", duration);
|
||||
newSong.Duration = duration;
|
||||
}
|
||||
|
||||
_song = newSong;
|
||||
return new Song
|
||||
{
|
||||
Id = Int32.Parse(row["Id"].ToString()),
|
||||
Filename = row["Filename"].ToString(),
|
||||
SongPath = row["SongPath"].ToString()
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
public async Task<SongData> RetrieveSong(int id)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
Console.WriteLine($"An error occurred when stripping metadata\n{msg}");
|
||||
_song = newSong;
|
||||
SongData song = new SongData();
|
||||
try
|
||||
{
|
||||
_song = await RetrieveSongDetails(id);
|
||||
song = await RetrieveSongFromFileSystem(_song);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
Console.WriteLine($"An error occurred: {exMsg}");
|
||||
}
|
||||
|
||||
return song;
|
||||
}
|
||||
public async Task<SongData> RetrieveSong(Song songMetaData)
|
||||
{
|
||||
SongData song = new SongData();
|
||||
try
|
||||
{
|
||||
Console.WriteLine("Fetching song from filesystem");
|
||||
song = await RetrieveSongFromFileSystem(songMetaData);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var exMsg = ex.Message;
|
||||
Console.WriteLine($"An error occurred: {exMsg}");
|
||||
}
|
||||
|
||||
return song;
|
||||
}
|
||||
|
||||
return newSong;
|
||||
}
|
||||
|
||||
async Task<SongData> RetrieveSongFromFileSystem(Song details)
|
||||
{
|
||||
byte[] uncompressedSong = System.IO.File.ReadAllBytes(details.SongPath);
|
||||
Song RetrieveMetaData(string filePath)
|
||||
{
|
||||
Song newSong = new Song
|
||||
{
|
||||
Title = "Untitled",
|
||||
Artist = "Untitled",
|
||||
Album = "Untitled",
|
||||
Year = 0,
|
||||
Genre = "Untitled",
|
||||
Duration = 0,
|
||||
SongPath = ""
|
||||
};
|
||||
string title, artist, album, genre;
|
||||
int year, duration;
|
||||
|
||||
return new SongData
|
||||
{
|
||||
Data = uncompressedSong
|
||||
};
|
||||
}
|
||||
Console.WriteLine("Stripping song metadata");
|
||||
try
|
||||
{
|
||||
TagLib.File tfile = TagLib.File.Create(filePath);
|
||||
|
||||
|
||||
async Task SaveSongToFileSystemTemp(IFormFile song, string filePath)
|
||||
{
|
||||
using (var fileStream = new FileStream(filePath, FileMode.Create))
|
||||
{
|
||||
Console.WriteLine("Retrieving song and storing it in memory");
|
||||
await song.CopyToAsync(fileStream);
|
||||
Console.WriteLine($"Retrieving metadata of song from filepath {filePath}");
|
||||
MetadataRetriever meta = new MetadataRetriever();
|
||||
_song = meta.RetrieveMetaData(filePath);
|
||||
//_song = RetrieveMetaData(filePath);
|
||||
Console.WriteLine("Assigning song filename");
|
||||
_song.Filename = song.FileName;
|
||||
Console.WriteLine($"Song filename retrieved: {song.FileName}");
|
||||
}
|
||||
}
|
||||
using (var mp3 = new Mp3(filePath))
|
||||
{
|
||||
Id3Tag tag = mp3.GetTag(Id3TagFamily.Version2X);
|
||||
title = tag.Title;
|
||||
Console.WriteLine("Title: {0}", title);
|
||||
newSong.Title = title;
|
||||
artist = tag.Artists;
|
||||
Console.WriteLine("Artist: {0}", artist);
|
||||
newSong.Artist = artist;
|
||||
album = tag.Album;
|
||||
Console.WriteLine("Album: {0}", album);
|
||||
newSong.Album = album;
|
||||
genre = "Not Implemented";
|
||||
Console.WriteLine("Genre: {0}", genre);
|
||||
newSong.Genre = genre;
|
||||
year = (int)tag.Year;
|
||||
Console.WriteLine("Year: {0}", year);
|
||||
newSong.Year = year;
|
||||
duration = (int)tfile.Properties.Duration.TotalSeconds;
|
||||
Console.WriteLine("Duration: {0}", duration);
|
||||
newSong.Duration = duration;
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
try
|
||||
{
|
||||
_connectionString = _config.GetConnectionString("IcarusDev");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Error Occurred: {ex.Message}");
|
||||
}
|
||||
_song = newSong;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
Console.WriteLine($"An error occurred when stripping metadata\n{msg}");
|
||||
_song = newSong;
|
||||
}
|
||||
|
||||
return newSong;
|
||||
}
|
||||
|
||||
async Task<SongData> RetrieveSongFromFileSystem(Song details)
|
||||
{
|
||||
byte[] uncompressedSong = System.IO.File.ReadAllBytes(details.SongPath);
|
||||
|
||||
}
|
||||
void InitializeConnection()
|
||||
{
|
||||
_conn = new MySqlConnection(_connectionString);
|
||||
}
|
||||
void InitializeResults()
|
||||
{
|
||||
_results = new DataTable();
|
||||
}
|
||||
async Task PopulateSongDetails()
|
||||
{
|
||||
foreach (DataRow row in _results.Rows)
|
||||
{
|
||||
Song song = new Song();
|
||||
foreach (DataColumn col in _results.Columns)
|
||||
{
|
||||
string colStr = col.ToString().ToUpper();
|
||||
switch (colStr)
|
||||
{
|
||||
case "ID":
|
||||
song.Id = Int32.Parse(row[col].ToString());
|
||||
break;
|
||||
case "TITLE":
|
||||
song.Title = row[col].ToString();
|
||||
break;
|
||||
case "ALBUM":
|
||||
song.Album = row[col].ToString();
|
||||
break;
|
||||
case "ARTIST":
|
||||
song.Artist = row[col].ToString();
|
||||
break;
|
||||
case "YEAR":
|
||||
song.Year = Int32.Parse(row[col].ToString());
|
||||
break;
|
||||
case "GENRE":
|
||||
song.Genre = row[col].ToString();
|
||||
break;
|
||||
case "DURATION":
|
||||
song.Duration = Int32.Parse(row[col].ToString());
|
||||
break;
|
||||
case "FILENAME":
|
||||
song.Filename = row[col].ToString();
|
||||
break;
|
||||
case "SONGPATH":
|
||||
song.SongPath = row[col].ToString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
_songs.Add(song);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
return new SongData
|
||||
{
|
||||
Data = uncompressedSong
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
async Task SaveSongToFileSystemTemp(IFormFile song, string filePath)
|
||||
{
|
||||
using (var fileStream = new FileStream(filePath, FileMode.Create))
|
||||
{
|
||||
Console.WriteLine("Retrieving song and storing it in memory");
|
||||
await song.CopyToAsync(fileStream);
|
||||
Console.WriteLine($"Retrieving metadata of song from filepath {filePath}");
|
||||
MetadataRetriever meta = new MetadataRetriever();
|
||||
_song = meta.RetrieveMetaData(filePath);
|
||||
|
||||
Console.WriteLine("Assigning song filename");
|
||||
_song.Filename = song.FileName;
|
||||
Console.WriteLine($"Song filename retrieved: {song.FileName}");
|
||||
}
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
try
|
||||
{
|
||||
_connectionString = _config.GetConnectionString("IcarusDev");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Error Occurred: {ex.Message}");
|
||||
}
|
||||
|
||||
}
|
||||
void InitializeConnection()
|
||||
{
|
||||
_conn = new MySqlConnection(_connectionString);
|
||||
}
|
||||
void InitializeResults()
|
||||
{
|
||||
_results = new DataTable();
|
||||
}
|
||||
async Task PopulateSongDetails()
|
||||
{
|
||||
foreach (DataRow row in _results.Rows)
|
||||
{
|
||||
Song song = new Song();
|
||||
foreach (DataColumn col in _results.Columns)
|
||||
{
|
||||
string colStr = col.ToString().ToUpper();
|
||||
switch (colStr)
|
||||
{
|
||||
case "ID":
|
||||
song.Id = Int32.Parse(row[col].ToString());
|
||||
break;
|
||||
case "TITLE":
|
||||
song.Title = row[col].ToString();
|
||||
break;
|
||||
case "ALBUM":
|
||||
song.Album = row[col].ToString();
|
||||
break;
|
||||
case "ARTIST":
|
||||
song.Artist = row[col].ToString();
|
||||
break;
|
||||
case "YEAR":
|
||||
song.Year = Int32.Parse(row[col].ToString());
|
||||
break;
|
||||
case "GENRE":
|
||||
song.Genre = row[col].ToString();
|
||||
break;
|
||||
case "DURATION":
|
||||
song.Duration = Int32.Parse(row[col].ToString());
|
||||
break;
|
||||
case "FILENAME":
|
||||
song.Filename = row[col].ToString();
|
||||
break;
|
||||
case "SONGPATH":
|
||||
song.SongPath = row[col].ToString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
_songs.Add(song);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using Icarus.Controllers.Managers;
|
||||
using Icarus.Models;
|
||||
@@ -16,12 +17,13 @@ using Icarus.Models.Context;
|
||||
|
||||
namespace Icarus.Controllers
|
||||
{
|
||||
[Route("api/song/data")]
|
||||
[ApiController]
|
||||
public class SongDataController : ControllerBase
|
||||
{
|
||||
#region Fields
|
||||
private IConfiguration _config;
|
||||
[Route("api/song/data")]
|
||||
[ApiController]
|
||||
public class SongDataController : ControllerBase
|
||||
{
|
||||
#region Fields
|
||||
private IConfiguration _config;
|
||||
private ILogger<SongDataController> _logger;
|
||||
private SongManager _songMgr;
|
||||
private string _songTempDir;
|
||||
#endregion
|
||||
@@ -32,24 +34,24 @@ namespace Icarus.Controllers
|
||||
|
||||
|
||||
#region Constructor
|
||||
public SongDataController(IConfiguration config)
|
||||
public SongDataController(IConfiguration config, ILogger<SongDataController> logger)
|
||||
{
|
||||
_config = config;
|
||||
_logger = logger;
|
||||
_songTempDir = _config.GetValue<string>("TemporaryMusicPath");
|
||||
_songMgr = new SongManager(config, _songTempDir);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
[HttpGet("{id}")]
|
||||
[HttpGet("{id}")]
|
||||
[Route("private-scoped")]
|
||||
[Authorize("download:songs")]
|
||||
public async Task<IActionResult> Get(int id)
|
||||
{
|
||||
public async Task<IActionResult> Get(int id)
|
||||
{
|
||||
MusicStoreContext context = HttpContext
|
||||
.RequestServices
|
||||
.GetService(typeof(MusicStoreContext))
|
||||
as MusicStoreContext;
|
||||
.RequestServices
|
||||
.GetService(typeof(MusicStoreContext)) as MusicStoreContext;
|
||||
var songMetaData = context.GetSong(id);
|
||||
|
||||
SongData song = await _songMgr.RetrieveSong(songMetaData);
|
||||
@@ -57,46 +59,55 @@ namespace Icarus.Controllers
|
||||
return File(song.Data, "application/x-msdownload", songMetaData.Filename);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[HttpPost]
|
||||
[Authorize("upload:songs")]
|
||||
public async Task Post([FromForm(Name = "file")] List<IFormFile> songData)
|
||||
{
|
||||
public async Task Post([FromForm(Name = "file")] List<IFormFile> songData)
|
||||
{
|
||||
try
|
||||
{
|
||||
MusicStoreContext context = HttpContext
|
||||
.RequestServices
|
||||
.GetService(typeof(MusicStoreContext))
|
||||
as MusicStoreContext;
|
||||
MusicStoreContext songStoreContext = HttpContext
|
||||
.RequestServices
|
||||
.GetService(typeof(MusicStoreContext)) as MusicStoreContext;
|
||||
AlbumStoreContext albumStoreContext = HttpContext
|
||||
.RequestServices
|
||||
.GetService(typeof(AlbumStoreContext)) as AlbumStoreContext;
|
||||
ArtistStoreContext artistStoreContext = HttpContext
|
||||
.RequestServices
|
||||
.GetService(typeof(ArtistStoreContext)) as ArtistStoreContext;
|
||||
|
||||
Console.WriteLine("Uploading song...");
|
||||
_logger.LogInformation("Uploading song...");
|
||||
|
||||
var uploads = _songTempDir;
|
||||
Console.WriteLine($"Song Root Path {uploads}");
|
||||
_logger.LogInformation($"Song root path {uploads}");
|
||||
foreach (var sng in songData)
|
||||
{
|
||||
if (sng.Length > 0) {
|
||||
Console.WriteLine($"Song filename {sng.FileName}");
|
||||
await _songMgr.SaveSongToFileSystem(sng);
|
||||
_logger.LogInformation($"Song filename {sng.FileName}");
|
||||
// TODO: Add functionality for overloaded method
|
||||
await _songMgr.SaveSongToFileSystem(sng, songStoreContext,
|
||||
albumStoreContext, artistStoreContext);
|
||||
var song = _songMgr.SongDetails;
|
||||
context.SaveSong(song);
|
||||
Console.WriteLine("Song successfully saved");
|
||||
songStoreContext.SaveSong(song);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"An error occurred: {ex.Message}");
|
||||
var msg = ex.Message;
|
||||
_logger.LogError(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
|
||||
[HttpDelete("{id}")]
|
||||
[HttpDelete("{id}")]
|
||||
[Authorize("delete:songs")]
|
||||
public void Delete(int id)
|
||||
{
|
||||
public void Delete(int id)
|
||||
{
|
||||
MusicStoreContext context = HttpContext
|
||||
.RequestServices
|
||||
.GetService(typeof(MusicStoreContext))
|
||||
as MusicStoreContext;
|
||||
.RequestServices
|
||||
.GetService(typeof(MusicStoreContext)) as MusicStoreContext;
|
||||
|
||||
var songMetaData = context.GetSong(id);
|
||||
|
||||
@@ -107,5 +118,5 @@ namespace Icarus.Controllers
|
||||
context.DeleteSong(songMetaData.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
@@ -14,5 +16,7 @@ namespace Icarus.Models
|
||||
public string AlbumArtist { get; set; }
|
||||
[JsonProperty("song_count")]
|
||||
public int SongCount { get; set; }
|
||||
[JsonIgnore]
|
||||
public List<Song> Songs { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,87 @@ namespace Icarus.Models.Context
|
||||
|
||||
return albums;
|
||||
}
|
||||
|
||||
public bool DoesAlbumExist(Album album)
|
||||
{
|
||||
try
|
||||
{
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void SaveAlbum(Album album)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (MySqlConnection conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
var query = "INSERT INTO Album(Title, AlbumArtist, " +
|
||||
"SongCount) VALUES (@Title, @AlbumArtist, " +
|
||||
"SongCount)";
|
||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@Title", album.Title);
|
||||
cmd.Parameters.AddWithValue("@AlbumArtist", album.AlbumArtist);
|
||||
cmd.Parameters.AddWithValue("@SongCount", album.SongCount);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
|
||||
private List<Album> ParseData(MySqlDataReader reader)
|
||||
{
|
||||
List<Album> albums = new List<Album>();
|
||||
while (reader.Read())
|
||||
{
|
||||
var id = Convert.ToInt32(reader["Id"]);
|
||||
var title = reader["Title"].ToString();
|
||||
var albumArtist = reader["AlbumArtist"].ToString();
|
||||
var songCount = Convert.ToInt32(reader["SongCount"]);
|
||||
albums.Add(new Album
|
||||
{
|
||||
Id = id,
|
||||
Title = title,
|
||||
AlbumArtist = albumArtist,
|
||||
SongCount = songCount
|
||||
});
|
||||
}
|
||||
|
||||
return albums;
|
||||
}
|
||||
private Album ParseSingleData(MySqlDataReader reader)
|
||||
{
|
||||
Album album = new Album();
|
||||
while (reader.Read())
|
||||
{
|
||||
var id = Convert.ToInt32(reader["Id"]);
|
||||
var title = reader["Title"].ToString();
|
||||
var albumArtist = reader["AlbumArtist"].ToString();
|
||||
var songCount = Convert.ToInt32(reader["SongCount"]);
|
||||
album = new Album
|
||||
{
|
||||
Id = id,
|
||||
Title = title,
|
||||
AlbumArtist = albumArtist,
|
||||
SongCount = songCount
|
||||
};
|
||||
}
|
||||
|
||||
return album;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ using NLog;
|
||||
|
||||
namespace Icarus.Models.Context
|
||||
{
|
||||
public class MusicStoreContext
|
||||
public class MusicStoreContext : BaseStoreContext
|
||||
{
|
||||
#region Fields
|
||||
private static Logger _logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
@@ -14,14 +14,13 @@ namespace Icarus.Models.Context
|
||||
|
||||
|
||||
#region Properties
|
||||
public string ConnectionString { get; set; }
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructors
|
||||
public MusicStoreContext(string connectionString)
|
||||
{
|
||||
this.ConnectionString = connectionString;
|
||||
_connectionString = connectionString;
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -202,10 +201,53 @@ namespace Icarus.Models.Context
|
||||
return song;
|
||||
}
|
||||
|
||||
private MySqlConnection GetConnection()
|
||||
{
|
||||
return new MySqlConnection(ConnectionString);
|
||||
}
|
||||
private List<Song> ParseData(MySqlDataReader reader)
|
||||
{
|
||||
|
||||
List<Song> songs = new List<Song>();
|
||||
while (reader.Read())
|
||||
{
|
||||
songs.Add(new Song
|
||||
{
|
||||
Id = Convert.ToInt32(reader["Id"]),
|
||||
Title = reader["Title"].ToString(),
|
||||
Album = reader["Album"].ToString(),
|
||||
Artist = reader["Artist"].ToString(),
|
||||
Year = Convert.ToInt32(reader["Year"]),
|
||||
Genre = reader["Genre"].ToString(),
|
||||
Duration = Convert.ToInt32(reader["Duration"]),
|
||||
Filename = reader["Filename"].ToString(),
|
||||
SongPath = reader["SongPath"].ToString()
|
||||
});
|
||||
}
|
||||
|
||||
return songs;
|
||||
}
|
||||
|
||||
private Song ParseSingleData(MySqlDataReader reader)
|
||||
{
|
||||
Song song = new Song();
|
||||
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
song = new Song
|
||||
{
|
||||
Id = Convert.ToInt32(reader["Id"]),
|
||||
Title = reader["Title"].ToString(),
|
||||
Album = reader["Album"].ToString(),
|
||||
Artist = reader["Artist"].ToString(),
|
||||
Year = Convert.ToInt32(reader["Year"]),
|
||||
Genre = reader["Genre"].ToString(),
|
||||
Duration = Convert.ToInt32(reader["Duration"]),
|
||||
Filename = reader["Filename"].ToString(),
|
||||
SongPath = reader["SongPath"].ToString()
|
||||
};
|
||||
}
|
||||
|
||||
return song;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,11 @@ namespace Icarus.Models.Context
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<Song>();
|
||||
modelBuilder.Entity<Song>()
|
||||
.HasOne(s => s.AlbumObject)
|
||||
.WithMany(a => a.Songs)
|
||||
.HasForeignKey(s => s.AlbumId)
|
||||
.HasConstraintName("ForeignKey_Song_Album");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
@@ -29,5 +30,9 @@ namespace Icarus.Models
|
||||
public string Filename { get; set; }
|
||||
[JsonProperty("song_path")]
|
||||
public string SongPath { get; set; }
|
||||
[JsonIgnore]
|
||||
public Album AlbumObject { get; set; }
|
||||
[JsonIgnore]
|
||||
public int AlbumId { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,6 +100,8 @@ namespace Icarus
|
||||
.GetConnectionString("DefaultConnection"))));
|
||||
|
||||
services.AddDbContext<SongContext>(options => options.UseMySQL(connString));
|
||||
services.AddDbContext<AlbumContext>(options => options.UseMySQL(connString));
|
||||
services.AddDbContext<ArtistContext>(options => options.UseMySQL(connString));
|
||||
services.AddDbContext<UserContext>(options => options.UseMySQL(connString));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user