Tricky implementing taglib's APIC extracting/saving feature, but I got it. Left some TODO's on where to pick up #56

This commit is contained in:
kdeng00
2019-08-11 17:51:42 -04:00
parent 023c467a9d
commit 51d40f270d
11 changed files with 183 additions and 68 deletions
+28 -3
View File
@@ -67,15 +67,22 @@ namespace Icarus.Controllers.Managers
DirectoryManager.create_directory(SongManager.ConvertSongToSng(song), DirectoryManager.create_directory(SongManager.ConvertSongToSng(song),
_rootCoverArtPath, imgPath); _rootCoverArtPath, imgPath);
var imagePath = imgPath.ToString().Substring(0, strCount); var imagePath = imgPath.ToString().Substring(0, strCount) +
imagePath += song.Title + ".png"; song.Title + ".png";
var coverArt = new CoverArt var coverArt = new CoverArt
{ {
SongTitle = song.Title, SongTitle = song.Title,
ImagePath = imagePath 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); var imgBytes = metaData.RetrieveCoverArtBytes(song);
if (imgBytes != null) if (imgBytes != null)
@@ -89,6 +96,7 @@ namespace Icarus.Controllers.Managers
coverArt.ImagePath = _rootCoverArtPath + "CoverArt.png"; coverArt.ImagePath = _rootCoverArtPath + "CoverArt.png";
metaData.UpdateCoverArt(song, coverArt); metaData.UpdateCoverArt(song, coverArt);
} }
*/
return coverArt; return coverArt;
} }
@@ -101,6 +109,23 @@ namespace Icarus.Controllers.Managers
return null; 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() private void Initialize()
{ {
var stockCover = _rootCoverArtPath + "CoverArt.png"; var stockCover = _rootCoverArtPath + "CoverArt.png";
+3 -3
View File
@@ -16,7 +16,7 @@ namespace Icarus.Controllers.Managers
#region Methods #region Methods
#region C++ libs #region C++ libs
[DllImport("libicarus.so")] [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")] [DllImport("libicarus.so")]
public static extern void copy_stock_cover_art(string target_path, string source_path); 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); public static extern void delete_cover_art(string cover_art_path, string stock_path);
[DllImport("libicarus.so")] [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")] [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
#endregion #endregion
} }
-21
View File
@@ -760,26 +760,5 @@ namespace Icarus.Controllers.Managers
yearStore.DeleteYear(year); yearStore.DeleteYear(year);
} }
#endregion #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
} }
} }
+10 -2
View File
@@ -58,11 +58,17 @@ namespace Icarus.Controllers.Utilities
#region C++ Libs #region C++ Libs
[DllImport("libicarus.so")] [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")] [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 #endregion
// TODO: Remove this when the update_cover_art(..) has been implemented
/**
public byte[] RetrieveCoverArtBytes(Song song) public byte[] RetrieveCoverArtBytes(Song song)
{ {
try try
@@ -81,7 +87,9 @@ namespace Icarus.Controllers.Utilities
return null; return null;
} }
*/
// TODO: Remove this when the update_cover_art(..) has been implemented
public void UpdateCoverArt(Song song, CoverArt coverArt) public void UpdateCoverArt(Song song, CoverArt coverArt)
{ {
Console.WriteLine("Updating song's cover art"); Console.WriteLine("Updating song's cover art");
+2
View File
@@ -7,11 +7,13 @@ set(CMAKE_CXX_STANDARD 17)
set(SOURCES set(SOURCES
src/directory_manager.cpp src/directory_manager.cpp
src/imageFile.cpp
src/metadata_retriever.cpp src/metadata_retriever.cpp
) )
set(HEADERS set(HEADERS
include/models.h include/models.h
include/directory_manager.h include/directory_manager.h
include/imageFile.h
include/metadata_retriever.h include/metadata_retriever.h
) )
+38
View File
@@ -0,0 +1,38 @@
#include <iostream>
#include <taglib/attachedpictureframe.h>
#include <taglib/mpegfile.h>
#include <taglib/tag.h>
#include <taglib/tfile.h>
#include <taglib/tfilestream.h>
#include <taglib/fileref.h>
#include <taglib/tbytevector.h>
#include <taglib/tbytevectorstream.h>
#include <taglib/tpropertymap.h>
#include <taglib/id3v2tag.h>
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; }
};
+7
View File
@@ -10,3 +10,10 @@ struct Song
int Duration; int Duration;
char SongPath[1024]; char SongPath[1024];
}; };
struct Cover
{
int Id;
char SongTitle[1024];
char ImagePath[1024];
};
+10
View File
@@ -0,0 +1,10 @@
#include "imageFile.h"
imageFile::imageFile(const char *file) : TagLib::File(file)
{
}
TagLib::ByteVector imageFile::data()
{
return readBlock(length());
}
+19 -2
View File
@@ -1,10 +1,12 @@
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <taglib/tag.h>
#include <taglib/fileref.h>
#include <string.h> #include <string.h>
#include <taglib/tag.h>
#include <taglib/fileref.h>
#include "metadata_retriever.h" #include "metadata_retriever.h"
#include "imageFile.h"
extern "C" extern "C"
{ {
@@ -48,5 +50,20 @@ void update_metadata(Song *sng_updated, Song *sng_old)
file.save(); 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
}
}
} }
+10
View File
@@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using System.Runtime.InteropServices;
using System.Text; using System.Text;
using Newtonsoft.Json; using Newtonsoft.Json;
@@ -21,4 +22,13 @@ namespace Icarus.Models
[JsonIgnore] [JsonIgnore]
public List<Song> Songs { get; set; } public List<Song> 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;
}
} }
+56 -37
View File
@@ -1,5 +1,6 @@
using System; using System;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using System.Runtime.InteropServices;
using Newtonsoft.Json; using Newtonsoft.Json;
@@ -8,47 +9,65 @@ namespace Icarus.Models
public class Song public class Song
{ {
[JsonProperty("id")] [JsonProperty("id")]
public int Id { get; set; } public int Id { get; set; }
[JsonProperty("title")] [JsonProperty("title")]
public string Title { get; set; } public string Title { get; set; }
[JsonProperty("album")] [JsonProperty("album")]
public string AlbumTitle { get; set; } public string AlbumTitle { get; set; }
[JsonProperty("artist")] [JsonProperty("artist")]
public string Artist { get; set; } public string Artist { get; set; }
[JsonProperty("year")] [JsonProperty("year")]
public int? Year { get; set; } public int? Year { get; set; }
[JsonProperty("genre")] [JsonProperty("genre")]
public string Genre { get; set; } public string Genre { get; set; }
[JsonProperty("duration")] [JsonProperty("duration")]
public int Duration { get; set; } public int Duration { get; set; }
[JsonProperty("filename")] [JsonProperty("filename")]
public string Filename { get; set; } public string Filename { get; set; }
[JsonProperty("song_path")] [JsonProperty("song_path")]
public string SongPath { get; set; } public string SongPath { get; set; }
[JsonIgnore] [JsonIgnore]
public Album Album { get; set; } public Album Album { get; set; }
[JsonIgnore] [JsonIgnore]
public int? AlbumId { get; set; } public int? AlbumId { get; set; }
[JsonIgnore] [JsonIgnore]
public Artist SongArtist { get; set; } public Artist SongArtist { get; set; }
[JsonIgnore] [JsonIgnore]
public int? ArtistId { get; set; } public int? ArtistId { get; set; }
[JsonIgnore] [JsonIgnore]
public Genre SongGenre { get; set; } public Genre SongGenre { get; set; }
[JsonIgnore] [JsonIgnore]
public int? GenreId { get; set; } public int? GenreId { get; set; }
[JsonIgnore] [JsonIgnore]
public Year SongYear { get; set; } public Year SongYear { get; set; }
[JsonIgnore] [JsonIgnore]
public int? YearId { get; set; } public int? YearId { get; set; }
[JsonIgnore] [JsonIgnore]
public CoverArt SongCoverArt { get; set; } public CoverArt SongCoverArt { get; set; }
[JsonIgnore] [JsonIgnore]
public int? CoverArtId { get; set; } 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;
} }
} }