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:
@@ -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";
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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");
|
||||||
|
|||||||
@@ -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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
};
|
||||||
@@ -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];
|
||||||
|
};
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#include "imageFile.h"
|
||||||
|
|
||||||
|
imageFile::imageFile(const char *file) : TagLib::File(file)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TagLib::ByteVector imageFile::data()
|
||||||
|
{
|
||||||
|
return readBlock(length());
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user