musikr: add mp4 file

This commit is contained in:
Alexander Capehart 2025-02-17 15:20:21 -07:00
parent f939e9d251
commit a3f01f152b
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
4 changed files with 46 additions and 9 deletions

View file

@ -27,6 +27,9 @@ mod bridge_impl {
include!("taglib/tiostream.h");
include!("taglib/flacpicture.h");
include!("taglib/tbytevector.h");
include!("taglib/mp4file.h");
include!("taglib/mp4tag.h");
include!("taglib/mp4item.h");
include!("shim/iostream_shim.hpp");
include!("shim/file_shim.hpp");
include!("shim/tk_shim.hpp");
@ -123,6 +126,8 @@ mod bridge_impl {
#[namespace = "TagLib::MP4"]
#[cxx_name = "File"]
type CPPMP4File;
#[cxx_name = "tag"]
fn MP4Tag(self: &CPPMP4File) -> *mut CPPMP4Tag;
#[namespace = "TagLib::RIFF::WAV"]
#[cxx_name = "File"]

View file

@ -2,6 +2,7 @@ use super::audioproperties::AudioProperties;
use super::bridge::{self, CPPFile, CPPMPEGFile};
use super::flac::FLACFile;
use super::id3v2::ID3v2Tag;
use super::mp4::MP4File;
use super::mpeg::MPEGFile;
use super::ogg::OpusFile;
use super::ogg::VorbisFile;
@ -38,7 +39,7 @@ impl<'file_ref> File<'file_ref> {
// This FFI function will be a simple C++ dynamic_cast, which checks if
// the file can be cased down to an opus file. If the cast fails, a null
// pointer is returned, which will be handled by as_ref's null checking.
bridge::File_asOpus(self.this.ptr_mut() as *mut CPPFile)
bridge::File_asOpus(self.this.ptr_mut())
};
let opus_ref = unsafe {
// SAFETY:
@ -59,7 +60,7 @@ impl<'file_ref> File<'file_ref> {
// This FFI function will be a simple C++ dynamic_cast, which checks if
// the file can be cased down to an opus file. If the cast fails, a null
// pointer is returned, which will be handled by as_ref's null checking.
bridge::File_asVorbis(self.this.ptr_mut() as *mut CPPFile)
bridge::File_asVorbis(self.this.ptr_mut())
};
let vorbis_ref = unsafe {
// SAFETY:
@ -80,7 +81,7 @@ impl<'file_ref> File<'file_ref> {
// This FFI function will be a simple C++ dynamic_cast, which checks if
// the file can be cased down to an opus file. If the cast fails, a null
// pointer is returned, which will be handled by as_ref's null checking.
bridge::File_asFLAC(self.this.ptr_mut() as *mut CPPFile)
bridge::File_asFLAC(self.this.ptr_mut())
};
let flac_ref = unsafe {
// SAFETY:
@ -101,7 +102,7 @@ impl<'file_ref> File<'file_ref> {
// This FFI function will be a simple C++ dynamic_cast, which checks if
// the file can be cased down to an MPEG file. If the cast fails, a null
// pointer is returned, which will be handled by as_ref's null checking.
bridge::File_asMPEG(self.this.ptr_mut() as *mut CPPFile)
bridge::File_asMPEG(self.this.ptr_mut())
};
let mpeg_ref = unsafe {
// SAFETY:
@ -115,4 +116,14 @@ impl<'file_ref> File<'file_ref> {
let mpeg_this = mpeg_ref.map(|mpeg| unsafe { RefThisMut::new(mpeg) });
mpeg_this.map(|this| MPEGFile::new(this))
}
pub fn as_mp4(&mut self) -> Option<MP4File<'file_ref>> {
let mp4_file = unsafe {
bridge::File_asMP4(self.this.ptr_mut())
};
let mp4_ref = unsafe { mp4_file.as_mut() };
let mp4_this = mp4_ref.map(|mp4| unsafe { RefThisMut::new(mp4) });
mp4_this.map(|this| MP4File::new(this))
}
}

View file

@ -1,5 +1,5 @@
pub mod bridge;
pub mod this;
mod bridge;
mod this;
pub mod iostream;
pub mod file_ref;
pub mod file;

View file

@ -1,16 +1,37 @@
pub use super::bridge::CPPMP4Tag;
use super::bridge::{CPPItemMap, ItemMap_to_entries, CPPItemMapEntry, CPPMP4Item, MP4ItemType, CPPIntPair};
use super::bridge::{CPPFile, CPPIntPair, CPPItemMap, CPPItemMapEntry, CPPMP4File, CPPMP4Item, ItemMap_to_entries, MP4ItemType};
use super::tk;
use super::this::{OwnedThis, RefThis, RefThisMut, ThisMut, This};
use std::collections::HashMap;
use std::pin::Pin;
pub struct MP4File<'file_ref> {
this: RefThisMut<'file_ref, CPPMP4File>,
}
impl<'file_ref> MP4File<'file_ref> {
pub fn new(this: RefThisMut<'file_ref, CPPMP4File>) -> Self {
Self { this }
}
pub fn tag(&self) -> Option<MP4Tag<'file_ref>> {
let this = self.this.as_ref();
let tag = unsafe { this.MP4Tag() };
let tag_ref = unsafe { tag.as_ref() };
tag_ref.map(|tag| {
// SAFETY: The tag pointer is guaranteed to be valid for the lifetime of self
let tag_this = unsafe { RefThis::new(tag) };
MP4Tag::new(tag_this)
})
}
}
pub struct MP4Tag<'file_ref> {
this: RefThisMut<'file_ref, CPPMP4Tag>,
this: RefThis<'file_ref, CPPMP4Tag>,
}
impl<'file_ref> MP4Tag<'file_ref> {
pub fn new(this: RefThisMut<'file_ref, CPPMP4Tag>) -> Self {
pub fn new(this: RefThis<'file_ref, CPPMP4Tag>) -> Self {
Self { this }
}