musikr: cleanup and cover stuff
This commit is contained in:
parent
8415db30ff
commit
57eb30701d
16 changed files with 138 additions and 121 deletions
|
@ -33,6 +33,10 @@ namespace taglib_shim {
|
|||
return std::make_unique<TagLib::ByteVector>(frame.picture());
|
||||
}
|
||||
|
||||
uint32_t AttachedPictureFrame_type(const TagLib::ID3v2::AttachedPictureFrame& frame) {
|
||||
return static_cast<uint32_t>(frame.type());
|
||||
}
|
||||
|
||||
std::unique_ptr<TagLib::StringList> TextIdentificationFrame_fieldList(const TagLib::ID3v2::TextIdentificationFrame& frame) {
|
||||
return std::make_unique<TagLib::StringList>(frame.fieldList());
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ namespace taglib_shim {
|
|||
|
||||
// Frame data access
|
||||
std::unique_ptr<TagLib::ByteVector> AttachedPictureFrame_picture(const TagLib::ID3v2::AttachedPictureFrame& frame);
|
||||
uint32_t AttachedPictureFrame_type(const TagLib::ID3v2::AttachedPictureFrame& frame);
|
||||
std::unique_ptr<TagLib::StringList> TextIdentificationFrame_fieldList(const TagLib::ID3v2::TextIdentificationFrame& frame);
|
||||
std::unique_ptr<TagLib::StringList> UserTextIdentificationFrame_fieldList(const TagLib::ID3v2::UserTextIdentificationFrame& frame);
|
||||
|
||||
|
|
|
@ -29,4 +29,8 @@ namespace taglib_shim {
|
|||
std::unique_ptr<TagLib::ByteVector> Picture_data(const TagLib::FLAC::Picture& picture) {
|
||||
return std::make_unique<TagLib::ByteVector>(picture.data());
|
||||
}
|
||||
|
||||
uint32_t Picture_type(const TagLib::FLAC::Picture& picture) {
|
||||
return static_cast<uint32_t>(picture.type());
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
#include "taglib/flacpicture.h"
|
||||
#include "taglib/tstring.h"
|
||||
#include "taglib/tbytevector.h"
|
||||
#include "taglib/tpicturetype.h"
|
||||
#include "tk_shim.hpp"
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
@ -22,5 +23,6 @@ namespace taglib_shim {
|
|||
|
||||
std::unique_ptr<std::vector<PicturePointer>> PictureList_to_vector(const PictureList& list);
|
||||
|
||||
uint32_t Picture_type(const TagLib::FLAC::Picture& picture);
|
||||
std::unique_ptr<TagLib::ByteVector> Picture_data(const TagLib::FLAC::Picture& picture);
|
||||
}
|
|
@ -6,7 +6,12 @@ use jni::{
|
|||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::taglib::{audioproperties, id3v1, id3v2, mp4, xiph};
|
||||
use crate::taglib::{
|
||||
audioproperties,
|
||||
flac::PictureType,
|
||||
id3v1, id3v2, mp4,
|
||||
xiph::{self, FLACPictureList},
|
||||
};
|
||||
|
||||
use crate::tagmap::JTagMap;
|
||||
|
||||
|
@ -84,7 +89,9 @@ impl<'local, 'file_ref> JMetadataBuilder<'local, 'file_ref> {
|
|||
first_pic = picture_frame.picture().map(|p| p.to_vec());
|
||||
}
|
||||
// TODO: Check for front cover type when bindings are available
|
||||
if front_cover_pic.is_none() {
|
||||
if let (Some(PictureType::FrontCover), None) =
|
||||
(picture_frame.picture_type(), &front_cover_pic)
|
||||
{
|
||||
front_cover_pic = picture_frame.picture().map(|p| p.to_vec());
|
||||
}
|
||||
}
|
||||
|
@ -95,13 +102,12 @@ impl<'local, 'file_ref> JMetadataBuilder<'local, 'file_ref> {
|
|||
self.cover = front_cover_pic.or(first_pic);
|
||||
}
|
||||
|
||||
pub fn set_xiph(&mut self, tag: &xiph::XiphComment) {
|
||||
pub fn set_xiph(&mut self, tag: &mut xiph::XiphComment<'file_ref>) {
|
||||
for (key, values) in tag.field_list_map().to_hashmap() {
|
||||
let values: Vec<String> = values.to_vec().into_iter().map(|s| s.to_string()).collect();
|
||||
self.xiph.add_id_list(key.to_uppercase(), values);
|
||||
}
|
||||
|
||||
// TODO: Handle FLAC pictures when bindings are available
|
||||
self.set_flac_pictures(&tag.picture_list());
|
||||
}
|
||||
|
||||
pub fn set_mp4(&mut self, tag: &mp4::MP4Tag) {
|
||||
|
@ -159,6 +165,14 @@ impl<'local, 'file_ref> JMetadataBuilder<'local, 'file_ref> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn set_flac_pictures(&mut self, pictures: &FLACPictureList<'file_ref>) {
|
||||
for picture in pictures.to_vec().into_iter() {
|
||||
if let Some(PictureType::FrontCover) = picture.picture_type() {
|
||||
self.cover = Some(picture.data().to_vec());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_properties(&mut self, properties: audioproperties::AudioProperties<'file_ref>) {
|
||||
self.properties = Some(properties);
|
||||
}
|
||||
|
|
|
@ -34,21 +34,28 @@ pub extern "C" fn Java_org_oxycblt_musikr_metadata_MetadataJNI_openFile<'local>(
|
|||
}
|
||||
if let Some(vorbis) = file.as_vorbis() {
|
||||
jbuilder.set_mime_type("audio/ogg");
|
||||
if let Some(tag) = vorbis.xiph_comments() {
|
||||
jbuilder.set_xiph(&tag);
|
||||
if let Some(mut tag) = vorbis.xiph_comments() {
|
||||
jbuilder.set_xiph(&mut tag);
|
||||
}
|
||||
}
|
||||
if let Some(opus) = file.as_opus() {
|
||||
jbuilder.set_mime_type("audio/opus");
|
||||
if let Some(tag) = opus.xiph_comments() {
|
||||
jbuilder.set_xiph(&tag);
|
||||
if let Some(mut tag) = opus.xiph_comments() {
|
||||
jbuilder.set_xiph(&mut tag);
|
||||
}
|
||||
}
|
||||
if let Some(mut flac) = file.as_flac() {
|
||||
jbuilder.set_mime_type("audio/flac");
|
||||
if let Some(tag) = flac.xiph_comments() {
|
||||
jbuilder.set_xiph(&tag);
|
||||
if let Some(tag) = flac.id3v1_tag() {
|
||||
jbuilder.set_id3v1(&tag);
|
||||
}
|
||||
if let Some(tag) = flac.id3v2_tag() {
|
||||
jbuilder.set_id3v2(&tag);
|
||||
}
|
||||
if let Some(mut tag) = flac.xiph_comments() {
|
||||
jbuilder.set_xiph(&mut tag);
|
||||
}
|
||||
jbuilder.set_flac_pictures(&flac.picture_list());
|
||||
}
|
||||
if let Some(mut mpeg) = file.as_mpeg() {
|
||||
jbuilder.set_mime_type("audio/mpeg");
|
||||
|
|
|
@ -129,8 +129,9 @@ mod bridge_impl {
|
|||
#[cxx_name = "Picture"]
|
||||
type CPPFLACPicture;
|
||||
#[namespace = "taglib_shim"]
|
||||
fn Picture_type(picture: &CPPFLACPicture) -> u32;
|
||||
#[namespace = "taglib_shim"]
|
||||
fn Picture_data(picture: &CPPFLACPicture) -> UniquePtr<CPPByteVector>;
|
||||
|
||||
// XIPHComment
|
||||
|
||||
#[namespace = "TagLib::Ogg"]
|
||||
|
@ -305,6 +306,8 @@ mod bridge_impl {
|
|||
#[cxx_name = "AttachedPictureFrame"]
|
||||
type CPPID3v2AttachedPictureFrame;
|
||||
#[namespace = "taglib_shim"]
|
||||
fn AttachedPictureFrame_type(frame: &CPPID3v2AttachedPictureFrame) -> u32;
|
||||
#[namespace = "taglib_shim"]
|
||||
fn AttachedPictureFrame_picture(
|
||||
frame: &CPPID3v2AttachedPictureFrame,
|
||||
) -> UniquePtr<CPPByteVector>;
|
||||
|
@ -336,6 +339,60 @@ mod bridge_impl {
|
|||
}
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
pub enum PictureType {
|
||||
Other,
|
||||
FileIcon,
|
||||
OtherFileIcon,
|
||||
FrontCover,
|
||||
BackCover,
|
||||
LeafletPage,
|
||||
Media,
|
||||
LeadArtist,
|
||||
Artist,
|
||||
Conductor,
|
||||
Band,
|
||||
Composer,
|
||||
Lyricist,
|
||||
RecordingLocation,
|
||||
DuringRecording,
|
||||
DuringPerformance,
|
||||
MovieScreenCapture,
|
||||
ColoredFish,
|
||||
Illustration,
|
||||
BandLogo,
|
||||
PublisherLogo,
|
||||
}
|
||||
|
||||
impl PictureType {
|
||||
pub fn from_u32(value: u32) -> Option<Self> {
|
||||
match value {
|
||||
0 => Some(Self::Other),
|
||||
1 => Some(Self::FileIcon),
|
||||
2 => Some(Self::OtherFileIcon),
|
||||
3 => Some(Self::FrontCover),
|
||||
4 => Some(Self::BackCover),
|
||||
5 => Some(Self::LeafletPage),
|
||||
6 => Some(Self::Media),
|
||||
7 => Some(Self::LeadArtist),
|
||||
8 => Some(Self::Artist),
|
||||
9 => Some(Self::Conductor),
|
||||
10 => Some(Self::Band),
|
||||
11 => Some(Self::Composer),
|
||||
12 => Some(Self::Lyricist),
|
||||
13 => Some(Self::RecordingLocation),
|
||||
14 => Some(Self::DuringRecording),
|
||||
15 => Some(Self::DuringPerformance),
|
||||
16 => Some(Self::MovieScreenCapture),
|
||||
17 => Some(Self::ColoredFish),
|
||||
18 => Some(Self::Illustration),
|
||||
19 => Some(Self::BandLogo),
|
||||
20 => Some(Self::PublisherLogo),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
pub enum MP4ItemType {
|
||||
Void,
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
pub use super::bridge::CPPFLACFile;
|
||||
pub use super::bridge::CPPFLACPicture;
|
||||
pub use super::bridge::PictureType;
|
||||
use super::bridge::{
|
||||
CPPPictureList, FLACFile_pictureList, PictureList_to_vector, Picture_data,
|
||||
CPPPictureList, FLACFile_pictureList, PictureList_to_vector, Picture_data, Picture_type,
|
||||
};
|
||||
use super::id3v1::ID3v1Tag;
|
||||
use super::id3v2::ID3v2Tag;
|
||||
use super::this::{OwnedThis, RefThis, RefThisMut, ThisMut};
|
||||
use super::tk::{ByteVector, OwnedByteVector};
|
||||
pub use super::xiph::XiphComment;
|
||||
use super::xiph::XiphComment;
|
||||
|
||||
pub struct FLACFile<'file_ref> {
|
||||
this: RefThisMut<'file_ref, CPPFLACFile>,
|
||||
|
@ -29,10 +30,10 @@ impl<'file_ref> FLACFile<'file_ref> {
|
|||
tag_this.map(|this| XiphComment::new(this))
|
||||
}
|
||||
|
||||
pub fn picture_list(&mut self) -> PictureList<'file_ref> {
|
||||
pub fn picture_list(&mut self) -> FLACPictureList<'file_ref> {
|
||||
let pictures = FLACFile_pictureList(self.this.pin_mut());
|
||||
let this = OwnedThis::new(pictures).unwrap();
|
||||
PictureList::new(this)
|
||||
FLACPictureList::new(this)
|
||||
}
|
||||
|
||||
pub fn id3v1_tag(&mut self) -> Option<ID3v1Tag<'file_ref>> {
|
||||
|
@ -50,16 +51,16 @@ impl<'file_ref> FLACFile<'file_ref> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct PictureList<'file_ref> {
|
||||
pub struct FLACPictureList<'file_ref> {
|
||||
this: OwnedThis<'file_ref, CPPPictureList>,
|
||||
}
|
||||
|
||||
impl<'file_ref> PictureList<'file_ref> {
|
||||
impl<'file_ref> FLACPictureList<'file_ref> {
|
||||
pub(super) fn new(this: OwnedThis<'file_ref, CPPPictureList>) -> Self {
|
||||
Self { this }
|
||||
}
|
||||
|
||||
pub fn to_vec(&self) -> Vec<Picture<'file_ref>> {
|
||||
pub fn to_vec(&self) -> Vec<FLACPicture<'file_ref>> {
|
||||
let pictures = PictureList_to_vector(self.this.as_ref());
|
||||
let mut result = Vec::new();
|
||||
for picture_ptr in pictures.iter() {
|
||||
|
@ -70,19 +71,20 @@ impl<'file_ref> PictureList<'file_ref> {
|
|||
picture_ptr.as_ref().unwrap()
|
||||
};
|
||||
let picture_this = RefThis::new(picture_ref);
|
||||
result.push(Picture::new(picture_this));
|
||||
result.push(FLACPicture { this: picture_this });
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Picture<'file_ref> {
|
||||
pub struct FLACPicture<'file_ref> {
|
||||
this: RefThis<'file_ref, CPPFLACPicture>,
|
||||
}
|
||||
|
||||
impl<'file_ref> Picture<'file_ref> {
|
||||
pub(super) fn new(this: RefThis<'file_ref, CPPFLACPicture>) -> Self {
|
||||
Self { this }
|
||||
impl<'file_ref> FLACPicture<'file_ref> {
|
||||
pub fn picture_type(&self) -> Option<PictureType> {
|
||||
let picture_type = Picture_type(self.this.as_ref());
|
||||
PictureType::from_u32(picture_type)
|
||||
}
|
||||
|
||||
pub fn data(&self) -> OwnedByteVector<'file_ref> {
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
use super::bridge::{
|
||||
self, CPPID3v2AttachedPictureFrame, CPPID3v2Frame, CPPID3v2FrameList,
|
||||
CPPID3v2Tag, CPPID3v2TextIdentificationFrame, CPPID3v2UserTextIdentificationFrame,
|
||||
self, CPPID3v2AttachedPictureFrame, CPPID3v2Frame, CPPID3v2FrameList, CPPID3v2Tag,
|
||||
CPPID3v2TextIdentificationFrame, CPPID3v2UserTextIdentificationFrame,
|
||||
};
|
||||
use super::this::{OwnedThis, RefThis, RefThisMut};
|
||||
use super::tk::{self, ByteVector, OwnedByteVector, OwnedStringList, StringList};
|
||||
|
||||
pub use super::bridge::PictureType;
|
||||
|
||||
pub struct ID3v2Tag<'file_ref> {
|
||||
this: RefThisMut<'file_ref, CPPID3v2Tag>,
|
||||
}
|
||||
|
@ -16,7 +18,7 @@ impl<'file_ref> ID3v2Tag<'file_ref> {
|
|||
|
||||
pub fn frames(&self) -> Option<FrameList<'file_ref>> {
|
||||
let frames = bridge::Tag_frameList(self.this.as_ref());
|
||||
let this = unsafe { OwnedThis::new(frames) };
|
||||
let this = OwnedThis::new(frames);
|
||||
this.map(|this| FrameList::new(this))
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +39,7 @@ impl<'file_ref> FrameList<'file_ref> {
|
|||
.map(|frame| {
|
||||
let frame_ptr = frame.get();
|
||||
let frame_ref = unsafe { frame_ptr.as_ref().unwrap() };
|
||||
let frame_this = unsafe { RefThis::new(frame_ref) };
|
||||
let frame_this = RefThis::new(frame_ref);
|
||||
Frame::new(frame_this)
|
||||
})
|
||||
.collect()
|
||||
|
@ -94,7 +96,7 @@ impl<'file_ref> TextIdentificationFrame<'file_ref> {
|
|||
|
||||
pub fn field_list(&self) -> Option<OwnedStringList<'file_ref>> {
|
||||
let field_list = bridge::TextIdentificationFrame_fieldList(self.this.as_ref());
|
||||
let this = unsafe { OwnedThis::new(field_list) };
|
||||
let this = OwnedThis::new(field_list);
|
||||
this.map(|this| StringList::new(this))
|
||||
}
|
||||
}
|
||||
|
@ -110,7 +112,7 @@ impl<'file_ref> UserTextIdentificationFrame<'file_ref> {
|
|||
|
||||
pub fn values(&self) -> Option<OwnedStringList<'file_ref>> {
|
||||
let values = bridge::UserTextIdentificationFrame_fieldList(self.this.as_ref());
|
||||
let this = unsafe { OwnedThis::new(values) };
|
||||
let this = OwnedThis::new(values);
|
||||
this.map(|this| StringList::new(this))
|
||||
}
|
||||
}
|
||||
|
@ -124,9 +126,14 @@ impl<'file_ref> AttachedPictureFrame<'file_ref> {
|
|||
Self { this }
|
||||
}
|
||||
|
||||
pub fn picture_type(&self) -> Option<PictureType> {
|
||||
let picture_type = bridge::AttachedPictureFrame_type(self.this.as_ref());
|
||||
PictureType::from_u32(picture_type)
|
||||
}
|
||||
|
||||
pub fn picture(&self) -> Option<OwnedByteVector<'file_ref>> {
|
||||
let picture = bridge::AttachedPictureFrame_picture(self.this.as_ref());
|
||||
let this = unsafe { OwnedThis::new(picture) };
|
||||
let this = OwnedThis::new(picture);
|
||||
this.map(|this| ByteVector::new(this))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use super::bridge::{self, CPPIOStream};
|
||||
use cxx::UniquePtr;
|
||||
use std::io::{Seek, SeekFrom};
|
||||
use std::io::SeekFrom;
|
||||
|
||||
pub trait IOStream {
|
||||
fn read_block(&mut self, buffer: &mut [u8]) -> usize;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
pub use super::bridge::CPPMP4Tag;
|
||||
use super::bridge::{
|
||||
CPPIntPair, CPPItemMap, CPPMP4File, CPPMP4Item, ItemMap_to_entries,
|
||||
MP4ItemType,
|
||||
CPPIntPair, CPPItemMap, CPPMP4File, CPPMP4Item, ItemMap_to_entries, MP4ItemType,
|
||||
};
|
||||
use super::this::{OwnedThis, RefThis, RefThisMut};
|
||||
use super::tk;
|
||||
|
@ -148,7 +147,7 @@ impl<'file_ref> CoverArtList<'file_ref> {
|
|||
.map(|ca| {
|
||||
let format = CoverArtFormat::from_u32(ca.format());
|
||||
let data = ca.data();
|
||||
let data_this = unsafe { RefThis::new(&*data) };
|
||||
let data_this = RefThis::new(&*data);
|
||||
let data = tk::ByteVector::new(data_this).to_vec();
|
||||
CoverArt { format, data }
|
||||
})
|
||||
|
@ -193,10 +192,6 @@ pub struct CoverArt {
|
|||
}
|
||||
|
||||
impl CoverArt {
|
||||
pub fn new(format: CoverArtFormat, data: Vec<u8>) -> Self {
|
||||
Self { format, data }
|
||||
}
|
||||
|
||||
pub fn format(&self) -> CoverArtFormat {
|
||||
self.format
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::bridge::{CPPMPEGFile};
|
||||
use super::bridge::CPPMPEGFile;
|
||||
use super::id3v1::ID3v1Tag;
|
||||
use super::id3v2::ID3v2Tag;
|
||||
use super::this::{RefThisMut, ThisMut};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::bridge::{CPPWAVFile};
|
||||
use super::bridge::CPPWAVFile;
|
||||
use super::id3v2::ID3v2Tag;
|
||||
use super::this::RefThisMut;
|
||||
|
||||
|
|
|
@ -3,53 +3,21 @@ use cxx::{memory::UniquePtrTarget, UniquePtr};
|
|||
use std::marker::PhantomData;
|
||||
use std::pin::Pin;
|
||||
|
||||
/// A taglib-FFI-specific trait representing a C++ object returned by the library.
|
||||
///
|
||||
/// `This` instances must hold the following contract:
|
||||
/// - This object will remain valid as long as TagLib's FileRef object is valid,
|
||||
/// and will be dropped when the FileRef is dropped.
|
||||
/// - This object will not move or be mutated over the FileRef's lifetime, this way
|
||||
/// it can be temporarily pinned for use as a `this` pointer.
|
||||
pub trait This<'file_ref, T: TagLibAllocated>: AsRef<T> {}
|
||||
|
||||
/// A taglib-FFI-specific trait representing a C++ object returned by the library.
|
||||
///
|
||||
/// This trait is used to provide a temporary pin of the object for use in C++
|
||||
/// member function calls.
|
||||
///
|
||||
/// `ThisMut` instances must hold the following contract:
|
||||
/// - This object will remain valid as long as TagLib's FileRef object is valid,
|
||||
/// and will be dropped when the FileRef is dropped.
|
||||
/// - This object will not move over the FileRef's lifetime, this way it can be
|
||||
/// temporarily pinned for use as a `this` pointer.
|
||||
pub trait ThisMut<'file_ref, T: TagLibAllocated>: This<'file_ref, T> {
|
||||
fn pin_mut(&mut self) -> Pin<&mut T>;
|
||||
}
|
||||
|
||||
/// A [This] instance that is a reference to a C++ object.
|
||||
pub struct RefThis<'file_ref, T: TagLibRef> {
|
||||
this: &'file_ref T,
|
||||
}
|
||||
|
||||
impl<'file_ref, T: TagLibRef> RefThis<'file_ref, T> {
|
||||
/// Create a new [RefThis] from a reference to a C++ object.
|
||||
///
|
||||
/// This is safe to call assuming the contract of [This] is upheld. Since this
|
||||
/// contract cannot be enforced by the Rust compiler, it is the caller's
|
||||
/// responsibility to ensure that the reference is valid for the lifetime of
|
||||
/// the `'file_ref` parameter. More or less, if it comes from the TagLib FFI
|
||||
/// interface, it is safe to use this.
|
||||
pub fn new(this: &'file_ref T) -> Self {
|
||||
// Rough informal contact is that the reference points to a C++ object
|
||||
// that will live and not move for as long as 'file_ref.
|
||||
Self { this }
|
||||
}
|
||||
|
||||
/// Get a pointer to the C++ object.
|
||||
///
|
||||
/// This can be used to pass the object to FFI functions that take a pointer.
|
||||
///
|
||||
/// This is safe to call assuming the contract of [This] is upheld.
|
||||
pub fn ptr(&self) -> *const T {
|
||||
self.this as *const T
|
||||
}
|
||||
|
@ -63,39 +31,19 @@ impl<'file_ref, T: TagLibRef> AsRef<T> for RefThis<'file_ref, T> {
|
|||
|
||||
impl<'file_ref, T: TagLibRef> This<'file_ref, T> for RefThis<'file_ref, T> {}
|
||||
|
||||
/// A [ThisMut] instance that is a reference to a C++ object.
|
||||
///
|
||||
/// This is similar to [RefThis], but allows mutating the object.
|
||||
pub struct RefThisMut<'file_ref, T: TagLibRef> {
|
||||
this: &'file_ref mut T,
|
||||
}
|
||||
|
||||
impl<'file_ref, T: TagLibRef> RefThisMut<'file_ref, T> {
|
||||
/// Create a new [RefThisMut] from a reference to a C++ object.
|
||||
///
|
||||
/// This is safe to call assuming the contract of [ThisMut] is upheld. Since
|
||||
/// this contract cannot be enforced by the Rust compiler, it is the caller's
|
||||
/// responsibility to ensure that the reference is valid for the lifetime of
|
||||
/// the `'file_ref` parameter. More or less, if it comes from the TagLib FFI
|
||||
/// interface, it is safe to use this.
|
||||
pub fn new(this: &'file_ref mut T) -> Self {
|
||||
Self { this }
|
||||
}
|
||||
|
||||
/// Get a pointer to the C++ object.
|
||||
///
|
||||
/// This can be used to pass the object to FFI functions that take a pointer.
|
||||
///
|
||||
/// This is safe to call assuming the contract of [ThisMut] is upheld.
|
||||
pub fn ptr(&self) -> *const T {
|
||||
self.this as *const T
|
||||
}
|
||||
|
||||
/// Get a pointer to the C++ object.
|
||||
///
|
||||
/// This can be used to pass the object to FFI functions that take a pointer.
|
||||
///
|
||||
/// This is safe to call assuming the contract of [ThisMut] is upheld.
|
||||
pub fn ptr_mut(&mut self) -> *mut T {
|
||||
self.this as *mut T
|
||||
}
|
||||
|
@ -115,26 +63,12 @@ impl<'file_ref, T: TagLibRef> ThisMut<'file_ref, T> for RefThisMut<'file_ref, T>
|
|||
}
|
||||
}
|
||||
|
||||
/// A [This] instance that is "owned" by the caller.
|
||||
///
|
||||
/// "Owned" in this context only really means that the object is not a rust reference.
|
||||
/// In practice, all "owned" taglib objects are actually shared references, and are
|
||||
/// thus tied to the lifetime of the `'file_ref` parameter.
|
||||
pub struct OwnedThis<'file_ref, T: TagLibShared + UniquePtrTarget> {
|
||||
_data: PhantomData<&'file_ref ()>,
|
||||
this: UniquePtr<T>,
|
||||
}
|
||||
|
||||
impl<'file_ref, T: TagLibShared + UniquePtrTarget> OwnedThis<'file_ref, T> {
|
||||
/// Create a new [OwnedThis] from a [UniquePtr].
|
||||
///
|
||||
/// This is safe to call assuming the contract of [This] is upheld. Since this
|
||||
/// contract cannot be enforced by the Rust compiler, it is the caller's
|
||||
/// responsibility to ensure that the `UniquePtr` is valid for the lifetime of
|
||||
/// the `'file_ref` parameter. More or less, if it comes from the TagLib FFI
|
||||
/// interface, it is safe to use this.
|
||||
///
|
||||
/// This will return `None` if the `UniquePtr` is `null`.
|
||||
pub fn new(this: UniquePtr<T>) -> Option<Self> {
|
||||
if !this.is_null() {
|
||||
Some(Self {
|
||||
|
|
|
@ -71,9 +71,6 @@ impl<'file_ref, T: This<'file_ref, InnerStringList>> StringList<'file_ref, T> {
|
|||
}
|
||||
|
||||
pub type OwnedStringList<'file_ref> = StringList<'file_ref, OwnedThis<'file_ref, InnerStringList>>;
|
||||
pub type RefStringList<'file_ref> = StringList<'file_ref, RefThis<'file_ref, InnerStringList>>;
|
||||
pub type RefStringListMut<'file_ref> =
|
||||
StringList<'file_ref, RefThisMut<'file_ref, InnerStringList>>;
|
||||
|
||||
pub struct ByteVector<'file_ref, T: This<'file_ref, InnerByteVector>> {
|
||||
_data: PhantomData<&'file_ref InnerByteVector>,
|
||||
|
@ -114,9 +111,6 @@ impl<'file_ref, T: This<'file_ref, InnerByteVector>> ByteVector<'file_ref, T> {
|
|||
}
|
||||
|
||||
pub type OwnedByteVector<'file_ref> = ByteVector<'file_ref, OwnedThis<'file_ref, InnerByteVector>>;
|
||||
pub type RefByteVector<'file_ref> = ByteVector<'file_ref, RefThis<'file_ref, InnerByteVector>>;
|
||||
pub type RefByteVectorMut<'file_ref> =
|
||||
ByteVector<'file_ref, RefThisMut<'file_ref, InnerByteVector>>;
|
||||
|
||||
pub struct ByteVectorList<'file_ref, T: This<'file_ref, InnerByteVectorList>> {
|
||||
_data: PhantomData<&'file_ref InnerByteVectorList>,
|
||||
|
@ -135,14 +129,10 @@ impl<'file_ref, T: This<'file_ref, InnerByteVectorList>> ByteVectorList<'file_re
|
|||
let cxx_values = bridge::ByteVectorList_to_vector(self.this.as_ref());
|
||||
cxx_values
|
||||
.iter()
|
||||
.map(|value| ByteVector::new(unsafe { RefThis::new(value) }).to_vec())
|
||||
.map(|value| ByteVector::new(RefThis::new(value)).to_vec())
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
pub type OwnedByteVectorList<'file_ref> =
|
||||
ByteVectorList<'file_ref, OwnedThis<'file_ref, InnerByteVectorList>>;
|
||||
pub type RefByteVectorList<'file_ref> =
|
||||
ByteVectorList<'file_ref, RefThis<'file_ref, InnerByteVectorList>>;
|
||||
pub type RefByteVectorListMut<'file_ref> =
|
||||
ByteVectorList<'file_ref, RefThisMut<'file_ref, InnerByteVectorList>>;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
pub use super::bridge::CPPXiphComment;
|
||||
use super::bridge::{CPPFieldListMap, FieldListMap_to_entries, XiphComment_pictureList};
|
||||
pub use super::flac::PictureList;
|
||||
pub use super::flac::FLACPictureList;
|
||||
use super::this::{OwnedThis, RefThis, RefThisMut, ThisMut};
|
||||
use super::tk;
|
||||
use std::collections::HashMap;
|
||||
|
@ -20,10 +20,10 @@ impl<'file_ref> XiphComment<'file_ref> {
|
|||
FieldListMap::new(map_this)
|
||||
}
|
||||
|
||||
pub fn picture_list(&mut self) -> PictureList<'file_ref> {
|
||||
pub fn picture_list(&mut self) -> FLACPictureList<'file_ref> {
|
||||
let pictures = XiphComment_pictureList(self.this.pin_mut());
|
||||
let pictures_this = OwnedThis::new(pictures).unwrap();
|
||||
PictureList::new(pictures_this)
|
||||
FLACPictureList::new(pictures_this)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue