musikr: initial flac pic support

Probably broken
This commit is contained in:
Alexander Capehart 2025-02-14 23:22:56 -07:00
parent 61069bd4fe
commit 3dfcf0f67a
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
8 changed files with 202 additions and 8 deletions

View file

@ -0,0 +1,15 @@
#include "picture_shim.hpp"
namespace taglib_shim {
std::unique_ptr<TagLib::String> Picture_mimeType(const TagLib::FLAC::Picture& picture) {
return std::make_unique<TagLib::String>(picture.mimeType());
}
std::unique_ptr<TagLib::String> Picture_description(const TagLib::FLAC::Picture& picture) {
return std::make_unique<TagLib::String>(picture.description());
}
std::unique_ptr<TagLib::ByteVector> Picture_data(const TagLib::FLAC::Picture& picture) {
return std::make_unique<TagLib::ByteVector>(picture.data());
}
}

View file

@ -0,0 +1,12 @@
#pragma once
#include "taglib/flacpicture.h"
#include "taglib/tstring.h"
#include "taglib/tbytevector.h"
#include <memory>
namespace taglib_shim {
std::unique_ptr<TagLib::String> Picture_mimeType(const TagLib::FLAC::Picture& picture);
std::unique_ptr<TagLib::String> Picture_description(const TagLib::FLAC::Picture& picture);
std::unique_ptr<TagLib::ByteVector> Picture_data(const TagLib::FLAC::Picture& picture);
}

View file

@ -33,4 +33,41 @@ namespace taglib_shim
return result;
}
std::unique_ptr<std::vector<PictureRef>> FLACFile_pictureList_to_vector(TagLib::FLAC::File &file)
{
std::unique_ptr<std::vector<PictureRef>> result = std::make_unique<std::vector<PictureRef>>();
const auto pictures = file.pictureList();
for (const auto &picture : pictures)
{
result->push_back(PictureRef(picture));
}
return result;
}
std::unique_ptr<std::vector<PictureRef>> XiphComment_pictureList_to_vector(TagLib::Ogg::XiphComment &comment)
{
std::unique_ptr<std::vector<PictureRef>> result = std::make_unique<std::vector<PictureRef>>();
const auto pictures = comment.pictureList();
for (const auto &picture : pictures)
{
result->push_back(PictureRef(picture));
}
return result;
}
rust::String String_to_string(const TagLib::String &str)
{
return rust::String(str.to8Bit());
}
std::unique_ptr<std::vector<uint8_t>> ByteVector_to_bytes(const TagLib::ByteVector &data)
{
auto result = std::make_unique<std::vector<uint8_t>>();
result->reserve(data.size());
for (size_t i = 0; i < data.size(); i++)
{
result->push_back(static_cast<uint8_t>(data[i]));
}
return result;
}
}

View file

@ -4,8 +4,14 @@
#include "taglib/xiphcomment.h"
#include "taglib/tstring.h"
#include "taglib/tstringlist.h"
#include "taglib/flacpicture.h"
#include "taglib/flacfile.h"
#include "taglib/tbytevector.h"
#include <memory>
#include <iterator>
#include <vector>
#include <string>
#include "rust/cxx.h"
namespace taglib_shim
{
@ -21,6 +27,17 @@ namespace taglib_shim
TagLib::StringList value_;
};
struct PictureRef {
PictureRef(const TagLib::FLAC::Picture* picture) : picture_(picture) {}
const TagLib::FLAC::Picture* get() const { return picture_; }
private:
const TagLib::FLAC::Picture* picture_;
};
std::unique_ptr<std::vector<Property>> SimplePropertyMap_to_vector(const TagLib::SimplePropertyMap &map);
std::unique_ptr<std::vector<TagLib::String>> StringList_to_vector(const TagLib::StringList &list);
std::unique_ptr<std::vector<PictureRef>> FLACFile_pictureList_to_vector(TagLib::FLAC::File &file);
std::unique_ptr<std::vector<PictureRef>> XiphComment_pictureList_to_vector(TagLib::Ogg::XiphComment &comment);
rust::String String_to_string(const TagLib::String &str);
std::unique_ptr<std::vector<uint8_t>> ByteVector_to_bytes(const TagLib::ByteVector &data);
}

View file

@ -25,9 +25,12 @@ mod bridge_impl {
include!("taglib/vorbisfile.h");
include!("taglib/xiphcomment.h");
include!("taglib/tiostream.h");
include!("taglib/flacpicture.h");
include!("taglib/tbytevector.h");
include!("shim/iostream_shim.hpp");
include!("shim/file_shim.hpp");
include!("shim/tk_shim.hpp");
include!("shim/picture_shim.hpp");
#[namespace = "TagLib"]
#[cxx_name = "IOStream"]
@ -64,6 +67,28 @@ mod bridge_impl {
#[cxx_name = "channels"]
fn channels(self: Pin<&CppAudioProperties>) -> i32;
#[namespace = "TagLib::FLAC"]
#[cxx_name = "Picture"]
type CPPFLACPicture;
#[namespace = "taglib_shim"]
fn Picture_mimeType(picture: &CPPFLACPicture) -> UniquePtr<CPPString>;
#[namespace = "taglib_shim"]
fn Picture_description(picture: &CPPFLACPicture) -> UniquePtr<CPPString>;
#[cxx_name = "width"]
fn width(self: Pin<&CPPFLACPicture>) -> i32;
#[cxx_name = "height"]
fn height(self: Pin<&CPPFLACPicture>) -> i32;
#[cxx_name = "colorDepth"]
fn colorDepth(self: Pin<&CPPFLACPicture>) -> i32;
#[cxx_name = "numColors"]
fn numColors(self: Pin<&CPPFLACPicture>) -> i32;
#[namespace = "taglib_shim"]
fn Picture_data(picture: &CPPFLACPicture) -> UniquePtr<CPPByteVector>;
#[namespace = "TagLib"]
#[cxx_name = "ByteVector"]
type CPPByteVector;
#[namespace = "TagLib::Ogg"]
#[cxx_name = "XiphComment"]
type CPPXiphComment;
@ -148,6 +173,20 @@ mod bridge_impl {
type CPPStringList;
#[namespace = "taglib_shim"]
fn StringList_to_vector(string_list: Pin<&CPPStringList>) -> UniquePtr<CxxVector<CPPString>>;
#[namespace = "taglib_shim"]
type PictureRef;
fn get(self: &PictureRef) -> *const CPPFLACPicture;
#[namespace = "taglib_shim"]
fn FLACFile_pictureList_to_vector(file: Pin<&mut CPPFLACFile>) -> UniquePtr<CxxVector<PictureRef>>;
#[namespace = "taglib_shim"]
fn XiphComment_pictureList_to_vector(comment: Pin<&mut CPPXiphComment>) -> UniquePtr<CxxVector<PictureRef>>;
#[namespace = "taglib_shim"]
fn String_to_string(str: &CPPString) -> String;
#[namespace = "taglib_shim"]
fn ByteVector_to_bytes(data: &CPPByteVector) -> UniquePtr<CxxVector<u8>>;
}
}

View file

@ -1,5 +1,7 @@
pub use super::bridge::CPPFLACFile;
pub use super::bridge::CPPFLACPicture;
pub use super::xiph::XiphComment;
use super::bridge::{FLACFile_pictureList_to_vector, String_to_string, ByteVector_to_bytes, Picture_mimeType, Picture_description, Picture_data};
use std::pin::Pin;
pub struct FLACFile<'a> {
@ -25,9 +27,63 @@ impl<'a> FLACFile<'a> {
let tag_ref = unsafe {
// SAFETY: This pointer is a valid type, and can only used and accessed
// via this function and thus cannot be mutated, satisfying the aliasing rules.
tag.as_ref()
tag.as_mut()
};
let tag_pin = tag_ref.map(|tag| unsafe { Pin::new_unchecked(tag) });
tag_pin.map(|tag| XiphComment::new(tag))
}
}
pub fn picture_list(&mut self) -> Vec<Picture<'a>> {
let pictures = FLACFile_pictureList_to_vector(self.this.as_mut());
let mut result = Vec::new();
for picture_ref in pictures.iter() {
let picture_ptr = picture_ref.get();
let picture_ref = unsafe {
// SAFETY: This pointer is a valid type, and can only used and accessed
// via this function and thus cannot be mutated, satisfying the aliasing rules.
picture_ptr.as_ref().unwrap()
};
let picture_pin = unsafe { Pin::new_unchecked(picture_ref) };
result.push(Picture::new(picture_pin));
}
result
}
}
pub struct Picture<'a> {
this: Pin<&'a CPPFLACPicture>
}
impl<'a> Picture<'a> {
pub(super) fn new(this: Pin<&'a CPPFLACPicture>) -> Self {
Self { this }
}
pub fn mime_type(&self) -> String {
String_to_string(Picture_mimeType(self.this.get_ref()).as_ref().unwrap())
}
pub fn description(&self) -> String {
String_to_string(Picture_description(self.this.get_ref()).as_ref().unwrap())
}
pub fn width(&self) -> i32 {
self.this.width()
}
pub fn height(&self) -> i32 {
self.this.height()
}
pub fn color_depth(&self) -> i32 {
self.this.colorDepth()
}
pub fn num_colors(&self) -> i32 {
self.this.numColors()
}
pub fn data(&self) -> Vec<u8> {
ByteVector_to_bytes(Picture_data(self.this.get_ref()).as_ref().unwrap()).iter().map(|b| *b).collect()
}
}

View file

@ -24,7 +24,7 @@ impl<'a> VorbisFile<'a> {
let tag_ref = unsafe {
// SAFETY: This pointer is a valid type, and can only used and accessed
// via this function and thus cannot be mutated, satisfying the aliasing rules.
tag.as_ref()
tag.as_mut()
};
let tag_pin = tag_ref.map(|tag| unsafe { Pin::new_unchecked(tag) });
tag_pin.map(|tag| XiphComment::new(tag))
@ -53,7 +53,7 @@ impl <'a> OpusFile<'a> {
let tag_ref = unsafe {
// SAFETY: This pointer is a valid type, and can only used and accessed
// via this function and thus cannot be mutated, satisfying the aliasing rules.
tag.as_ref()
tag.as_mut()
};
let tag_pin = tag_ref.map(|tag| unsafe { Pin::new_unchecked(tag) });
tag_pin.map(|tag| XiphComment::new(tag))

View file

@ -1,19 +1,37 @@
pub use super::bridge::CPPXiphComment;
pub use super::flac::Picture;
use super::bridge::XiphComment_pictureList_to_vector;
use super::tk::SimplePropertyMap;
use std::pin::Pin;
pub struct XiphComment<'a> {
this: Pin<&'a CPPXiphComment>
this: Pin<&'a mut CPPXiphComment>
}
impl<'a> XiphComment<'a> {
pub(super) fn new(this: Pin<&'a CPPXiphComment>) -> Self {
pub(super) fn new(this: Pin<&'a mut CPPXiphComment>) -> Self {
Self { this }
}
pub fn field_list_map(&self) -> SimplePropertyMap<'a> {
let map = self.this.fieldListMap();
pub fn field_list_map(&'a self) -> SimplePropertyMap<'a> {
let map = self.this.as_ref().fieldListMap();
let map_pin = unsafe { Pin::new_unchecked(map) };
SimplePropertyMap::new(map_pin)
}
pub fn picture_list(&mut self) -> Vec<Picture<'a>> {
let pictures = XiphComment_pictureList_to_vector(self.this.as_mut());
let mut result = Vec::new();
for picture_ref in pictures.iter() {
let picture_ptr = picture_ref.get();
let picture_ref = unsafe {
// SAFETY: This pointer is a valid type, and can only used and accessed
// via this function and thus cannot be mutated, satisfying the aliasing rules.
picture_ptr.as_ref().unwrap()
};
let picture_pin = unsafe { Pin::new_unchecked(picture_ref) };
result.push(Picture::new(picture_pin));
}
result
}
}