From 51d40f270d45853117a7ec76af47d0f8b6e81e5f Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 11 Aug 2019 17:51:42 -0400 Subject: [PATCH] Tricky implementing taglib's APIC extracting/saving feature, but I got it. Left some TODO's on where to pick up #56 --- Controllers/Managers/CoverArtManager.cs | 31 +++++++- Controllers/Managers/DirectoryManager.cs | 6 +- Controllers/Managers/SongManager.cs | 21 ----- Controllers/Utilities/MetadataRetriever.cs | 12 ++- Libs/CMakeLists.txt | 2 + Libs/include/imageFile.h | 38 +++++++++ Libs/include/models.h | 7 ++ Libs/src/imageFile.cpp | 10 +++ Libs/src/metadata_retriever.cpp | 21 ++++- Models/CoverArt.cs | 10 +++ Models/Song.cs | 93 +++++++++++++--------- 11 files changed, 183 insertions(+), 68 deletions(-) create mode 100644 Libs/include/imageFile.h create mode 100644 Libs/src/imageFile.cpp diff --git a/Controllers/Managers/CoverArtManager.cs b/Controllers/Managers/CoverArtManager.cs index 5476832..482e8ba 100644 --- a/Controllers/Managers/CoverArtManager.cs +++ b/Controllers/Managers/CoverArtManager.cs @@ -67,15 +67,22 @@ namespace Icarus.Controllers.Managers DirectoryManager.create_directory(SongManager.ConvertSongToSng(song), _rootCoverArtPath, imgPath); - var imagePath = imgPath.ToString().Substring(0, strCount); - imagePath += song.Title + ".png"; + var imagePath = imgPath.ToString().Substring(0, strCount) + + song.Title + ".png"; var coverArt = new CoverArt { SongTitle = song.Title, ImagePath = imagePath }; - var metaData = new MetadataRetriever(); + var cov = ConvertCoverArtToCovArt(coverArt); + var stock_path = _rootCoverArtPath + "CoverArt.png"; + + //var metaData = new MetadataRetriever(); + // TODO: Work on the function on the c++ side + // I left some TODO's + MetadataRetriever.update_cover_art(ref cov, stock_path, song.SongPath); + /** var imgBytes = metaData.RetrieveCoverArtBytes(song); if (imgBytes != null) @@ -89,6 +96,7 @@ namespace Icarus.Controllers.Managers coverArt.ImagePath = _rootCoverArtPath + "CoverArt.png"; metaData.UpdateCoverArt(song, coverArt); } + */ return coverArt; } @@ -101,6 +109,23 @@ namespace Icarus.Controllers.Managers return null; } + public static CovArt ConvertCoverArtToCovArt(CoverArt cover) + { + return new CovArt + { + SongTitle = cover.SongTitle, + ImagePath = cover.ImagePath + }; + } + public static CoverArt ConvertCovArtToCoverArt(CovArt cov) + { + return new CoverArt + { + SongTitle = cov.SongTitle, + ImagePath = cov.ImagePath + }; + } + private void Initialize() { var stockCover = _rootCoverArtPath + "CoverArt.png"; diff --git a/Controllers/Managers/DirectoryManager.cs b/Controllers/Managers/DirectoryManager.cs index 33ea555..5a512f9 100644 --- a/Controllers/Managers/DirectoryManager.cs +++ b/Controllers/Managers/DirectoryManager.cs @@ -16,7 +16,7 @@ namespace Icarus.Controllers.Managers #region Methods #region C++ libs [DllImport("libicarus.so")] - public static extern void create_directory(SongManager.Sng song, string root_path, StringBuilder created_dir); + public static extern void create_directory(Sng song, string root_path, StringBuilder created_dir); [DllImport("libicarus.so")] public static extern void copy_stock_cover_art(string target_path, string source_path); @@ -28,10 +28,10 @@ namespace Icarus.Controllers.Managers public static extern void delete_cover_art(string cover_art_path, string stock_path); [DllImport("libicarus.so")] - public static extern void delete_empty_directories(SongManager.Sng song, string root_path); + public static extern void delete_empty_directories(Sng song, string root_path); [DllImport("libicarus.so")] - public static extern void delete_song_empty_directories(SongManager.Sng song, string root_path); + public static extern void delete_song_empty_directories(Sng song, string root_path); #endregion #endregion } diff --git a/Controllers/Managers/SongManager.cs b/Controllers/Managers/SongManager.cs index b102f44..d799ba4 100644 --- a/Controllers/Managers/SongManager.cs +++ b/Controllers/Managers/SongManager.cs @@ -760,26 +760,5 @@ namespace Icarus.Controllers.Managers yearStore.DeleteYear(year); } #endregion - - - #region Structs - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - public struct Sng - { - public int Id; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] - public string Title; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] - public string Artist; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] - public string Album; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] - public string Genre; - public int Year; - public int Duration; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] - public string SongPath; - }; - #endregion } } diff --git a/Controllers/Utilities/MetadataRetriever.cs b/Controllers/Utilities/MetadataRetriever.cs index b25b1a0..46f89e1 100644 --- a/Controllers/Utilities/MetadataRetriever.cs +++ b/Controllers/Utilities/MetadataRetriever.cs @@ -58,11 +58,17 @@ namespace Icarus.Controllers.Utilities #region C++ Libs [DllImport("libicarus.so")] - public static extern void retrieve_metadata(ref SongManager.Sng sng, string file_path); + public static extern void retrieve_metadata(ref Sng sng, string file_path); + [DllImport("libicarus.so")] - public static extern void update_metadata(ref SongManager.Sng sng_updated, ref SongManager.Sng sng_old); + public static extern void update_metadata(ref Sng sng_updated, ref Sng sng_old); + + [DllImport("libicarus.so")] + public static extern void update_cover_art(ref CovArt cov, string stock_cover_path, string song_path); #endregion + // TODO: Remove this when the update_cover_art(..) has been implemented + /** public byte[] RetrieveCoverArtBytes(Song song) { try @@ -81,7 +87,9 @@ namespace Icarus.Controllers.Utilities return null; } + */ + // TODO: Remove this when the update_cover_art(..) has been implemented public void UpdateCoverArt(Song song, CoverArt coverArt) { Console.WriteLine("Updating song's cover art"); diff --git a/Libs/CMakeLists.txt b/Libs/CMakeLists.txt index ff2d651..b93884e 100644 --- a/Libs/CMakeLists.txt +++ b/Libs/CMakeLists.txt @@ -7,11 +7,13 @@ set(CMAKE_CXX_STANDARD 17) set(SOURCES src/directory_manager.cpp + src/imageFile.cpp src/metadata_retriever.cpp ) set(HEADERS include/models.h include/directory_manager.h + include/imageFile.h include/metadata_retriever.h ) diff --git a/Libs/include/imageFile.h b/Libs/include/imageFile.h new file mode 100644 index 0000000..18322a8 --- /dev/null +++ b/Libs/include/imageFile.h @@ -0,0 +1,38 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class imageFile : public TagLib::File +{ +public: + imageFile(const char *file); + /** + imageFile(const char *file) : TagLib::File(file) + { + + } + */ + + TagLib::ByteVector data(); + /** + TagLib::ByteVector data() + { + return readBlock(length()); + } + */ + + +private: + virtual TagLib::Tag *tag() const { return 0; } + virtual TagLib::AudioProperties *audioProperties() const { return 0; } + virtual bool save() { return false; } +}; diff --git a/Libs/include/models.h b/Libs/include/models.h index e5e5ebc..78af2b9 100644 --- a/Libs/include/models.h +++ b/Libs/include/models.h @@ -10,3 +10,10 @@ struct Song int Duration; char SongPath[1024]; }; + +struct Cover +{ + int Id; + char SongTitle[1024]; + char ImagePath[1024]; +}; diff --git a/Libs/src/imageFile.cpp b/Libs/src/imageFile.cpp new file mode 100644 index 0000000..9cab142 --- /dev/null +++ b/Libs/src/imageFile.cpp @@ -0,0 +1,10 @@ +#include "imageFile.h" + +imageFile::imageFile(const char *file) : TagLib::File(file) +{ +} + +TagLib::ByteVector imageFile::data() +{ + return readBlock(length()); +} diff --git a/Libs/src/metadata_retriever.cpp b/Libs/src/metadata_retriever.cpp index 679ef0b..97d37b1 100644 --- a/Libs/src/metadata_retriever.cpp +++ b/Libs/src/metadata_retriever.cpp @@ -1,10 +1,12 @@ #include #include -#include -#include #include +#include +#include + #include "metadata_retriever.h" +#include "imageFile.h" extern "C" { @@ -48,5 +50,20 @@ void update_metadata(Song *sng_updated, Song *sng_old) file.save(); } +void update_cover_art(Cover *cov, const char *stock_path, const char *song_path) +{ + const std::string img_frame = "APIC"; + TagLib::MPEG::File sngF(song_path); + TagLib::ID3v2::Tag *tag = sngF.ID3v2Tag(); + auto frameList = tag->frameListMap()[img_frame.c_str()]; + + if (frameList.isEmpty()) { + // TODO: Apply stock cover art + imageFile stock_img(stock_path); + } else { + // TODO: Extract cover art from song and store it in + // cov->ImagePath + } +} } diff --git a/Models/CoverArt.cs b/Models/CoverArt.cs index 4d925a1..6880421 100644 --- a/Models/CoverArt.cs +++ b/Models/CoverArt.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; +using System.Runtime.InteropServices; using System.Text; using Newtonsoft.Json; @@ -21,4 +22,13 @@ namespace Icarus.Models [JsonIgnore] public List Songs { get; set; } } + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public struct CovArt + { + public int CoverArtId; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] + public string SongTitle; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] + public string ImagePath; + } } diff --git a/Models/Song.cs b/Models/Song.cs index 3eb0a0a..a09f368 100644 --- a/Models/Song.cs +++ b/Models/Song.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel.DataAnnotations.Schema; +using System.Runtime.InteropServices; using Newtonsoft.Json; @@ -8,47 +9,65 @@ namespace Icarus.Models public class Song { [JsonProperty("id")] - public int Id { get; set; } - [JsonProperty("title")] - public string Title { get; set; } - [JsonProperty("album")] - public string AlbumTitle { get; set; } - [JsonProperty("artist")] - public string Artist { get; set; } - [JsonProperty("year")] - public int? Year { get; set; } - [JsonProperty("genre")] - public string Genre { get; set; } - [JsonProperty("duration")] - public int Duration { get; set; } - [JsonProperty("filename")] - public string Filename { get; set; } - [JsonProperty("song_path")] - public string SongPath { get; set; } + public int Id { get; set; } + [JsonProperty("title")] + public string Title { get; set; } + [JsonProperty("album")] + public string AlbumTitle { get; set; } + [JsonProperty("artist")] + public string Artist { get; set; } + [JsonProperty("year")] + public int? Year { get; set; } + [JsonProperty("genre")] + public string Genre { get; set; } + [JsonProperty("duration")] + public int Duration { get; set; } + [JsonProperty("filename")] + public string Filename { get; set; } + [JsonProperty("song_path")] + public string SongPath { get; set; } - [JsonIgnore] - public Album Album { get; set; } - [JsonIgnore] - public int? AlbumId { get; set; } + [JsonIgnore] + public Album Album { get; set; } + [JsonIgnore] + public int? AlbumId { get; set; } - [JsonIgnore] - public Artist SongArtist { get; set; } - [JsonIgnore] - public int? ArtistId { get; set; } + [JsonIgnore] + public Artist SongArtist { get; set; } + [JsonIgnore] + public int? ArtistId { get; set; } - [JsonIgnore] - public Genre SongGenre { get; set; } - [JsonIgnore] - public int? GenreId { get; set; } + [JsonIgnore] + public Genre SongGenre { get; set; } + [JsonIgnore] + public int? GenreId { get; set; } - [JsonIgnore] - public Year SongYear { get; set; } - [JsonIgnore] - public int? YearId { get; set; } + [JsonIgnore] + public Year SongYear { get; set; } + [JsonIgnore] + public int? YearId { get; set; } - [JsonIgnore] - public CoverArt SongCoverArt { get; set; } - [JsonIgnore] - public int? CoverArtId { get; set; } + [JsonIgnore] + public CoverArt SongCoverArt { get; set; } + [JsonIgnore] + public int? CoverArtId { get; set; } + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public struct Sng + { + public int Id; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] + public string Title; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] + public string Artist; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] + public string Album; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] + public string Genre; + public int Year; + public int Duration; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] + public string SongPath; } }