musikr: implement main flow
This commit is contained in:
parent
de9a60d182
commit
8415db30ff
19 changed files with 294 additions and 174 deletions
|
@ -1,10 +1,12 @@
|
|||
use jni::{objects::{JByteArray, JClass, JMap, JObject, JString, JValueGen}, sys::jlong, JNIEnv};
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
|
||||
use crate::taglib::{
|
||||
id3v1, id3v2, xiph, mp4, tk, audioproperties,
|
||||
use jni::{
|
||||
objects::{JObject, JValueGen},
|
||||
sys::jlong,
|
||||
JNIEnv,
|
||||
};
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::taglib::{audioproperties, id3v1, id3v2, mp4, xiph};
|
||||
|
||||
use crate::tagmap::JTagMap;
|
||||
|
||||
|
@ -56,7 +58,8 @@ impl<'local, 'file_ref> JMetadataBuilder<'local, 'file_ref> {
|
|||
for mut frame in frames.to_vec() {
|
||||
if let Some(text_frame) = frame.as_text_identification() {
|
||||
if let Some(field_list) = text_frame.field_list() {
|
||||
let values: Vec<String> = field_list.to_vec()
|
||||
let values: Vec<String> = field_list
|
||||
.to_vec()
|
||||
.into_iter()
|
||||
.map(|s| s.to_string())
|
||||
.collect();
|
||||
|
@ -110,7 +113,10 @@ impl<'local, 'file_ref> JMetadataBuilder<'local, 'file_ref> {
|
|||
let covers = cover_list.to_vec();
|
||||
// Prefer PNG/JPEG covers
|
||||
let preferred_cover = covers.iter().find(|c| {
|
||||
matches!(c.format(), mp4::CoverArtFormat::PNG | mp4::CoverArtFormat::JPEG)
|
||||
matches!(
|
||||
c.format(),
|
||||
mp4::CoverArtFormat::PNG | mp4::CoverArtFormat::JPEG
|
||||
)
|
||||
});
|
||||
|
||||
if let Some(cover) = preferred_cover {
|
||||
|
@ -125,7 +131,8 @@ impl<'local, 'file_ref> JMetadataBuilder<'local, 'file_ref> {
|
|||
if let Some(data) = item.data() {
|
||||
match data {
|
||||
mp4::MP4Data::StringList(list) => {
|
||||
let values: Vec<String> = list.to_vec().into_iter().map(|s| s.to_string()).collect();
|
||||
let values: Vec<String> =
|
||||
list.to_vec().into_iter().map(|s| s.to_string()).collect();
|
||||
if key.starts_with("----") {
|
||||
if let Some(split_idx) = key.find(':') {
|
||||
let (atom_name, atom_desc) = key.split_at(split_idx);
|
||||
|
@ -158,12 +165,18 @@ impl<'local, 'file_ref> JMetadataBuilder<'local, 'file_ref> {
|
|||
|
||||
pub fn build(&self) -> JObject {
|
||||
// Create Properties object
|
||||
let properties_class = self.env.borrow_mut().find_class("org/oxycblt/musikr/metadata/Properties").unwrap();
|
||||
let properties_class = self
|
||||
.env
|
||||
.borrow_mut()
|
||||
.find_class("org/oxycblt/musikr/metadata/Properties")
|
||||
.unwrap();
|
||||
let properties = if let Some(props) = &self.properties {
|
||||
let mime_type = self.mime_type.as_deref().unwrap_or("").to_string();
|
||||
let j_mime_type = self.env.borrow().new_string(mime_type).unwrap();
|
||||
|
||||
self.env.borrow_mut().new_object(
|
||||
self.env
|
||||
.borrow_mut()
|
||||
.new_object(
|
||||
properties_class,
|
||||
"(Ljava/lang/String;JII)V",
|
||||
&[
|
||||
|
@ -172,27 +185,47 @@ impl<'local, 'file_ref> JMetadataBuilder<'local, 'file_ref> {
|
|||
(props.bitrate() as i32).into(),
|
||||
(props.sample_rate() as i32).into(),
|
||||
],
|
||||
).unwrap()
|
||||
)
|
||||
.unwrap()
|
||||
} else {
|
||||
let empty_mime = self.env.borrow().new_string("").unwrap();
|
||||
self.env.borrow_mut().new_object(
|
||||
self.env
|
||||
.borrow_mut()
|
||||
.new_object(
|
||||
properties_class,
|
||||
"(Ljava/lang/String;JII)V",
|
||||
&[JValueGen::from(&empty_mime), 0i64.into(), 0i32.into(), 0i32.into()],
|
||||
).unwrap()
|
||||
&[
|
||||
JValueGen::from(&empty_mime),
|
||||
0i64.into(),
|
||||
0i32.into(),
|
||||
0i32.into(),
|
||||
],
|
||||
)
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
// Create cover byte array if present
|
||||
let cover_array = if let Some(cover_data) = &self.cover {
|
||||
let array = self.env.borrow().new_byte_array(cover_data.len() as i32).unwrap();
|
||||
self.env.borrow().set_byte_array_region(&array, 0, bytemuck::cast_slice(cover_data)).unwrap();
|
||||
let array = self
|
||||
.env
|
||||
.borrow()
|
||||
.new_byte_array(cover_data.len() as i32)
|
||||
.unwrap();
|
||||
self.env
|
||||
.borrow()
|
||||
.set_byte_array_region(&array, 0, bytemuck::cast_slice(cover_data))
|
||||
.unwrap();
|
||||
array.into()
|
||||
} else {
|
||||
JObject::null()
|
||||
};
|
||||
|
||||
// Create Metadata object
|
||||
let metadata_class = self.env.borrow_mut().find_class("org/oxycblt/musikr/metadata/Metadata").unwrap();
|
||||
let metadata_class = self
|
||||
.env
|
||||
.borrow_mut()
|
||||
.find_class("org/oxycblt/musikr/metadata/Metadata")
|
||||
.unwrap();
|
||||
self.env.borrow_mut().new_object(
|
||||
metadata_class,
|
||||
"(Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;[BLorg/oxycblt/musikr/metadata/Properties;)V",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::taglib::iostream::IOStream;
|
||||
use crate::SharedEnv;
|
||||
use jni::objects::{JObject, JValue};
|
||||
use std::io::{Read, Seek, SeekFrom, Write};
|
||||
use std::io::SeekFrom;
|
||||
|
||||
pub struct JInputStream<'local> {
|
||||
env: SharedEnv<'local>,
|
||||
|
|
|
@ -1,36 +1,79 @@
|
|||
use jni::objects::{JClass, JObject};
|
||||
use jni::sys::jstring;
|
||||
use jni::sys::jobject;
|
||||
use jni::JNIEnv;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
mod jbuilder;
|
||||
mod jstream;
|
||||
mod taglib;
|
||||
mod tagmap;
|
||||
mod jbuilder;
|
||||
|
||||
use jbuilder::JMetadataBuilder;
|
||||
use jstream::JInputStream;
|
||||
use taglib::file_ref::FileRef;
|
||||
use jbuilder::JMetadataBuilder;
|
||||
|
||||
type SharedEnv<'local> = Rc<RefCell<JNIEnv<'local>>>;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Java_org_oxycblt_musikr_metadata_MetadataJNI_openFile<'local>(
|
||||
mut env: JNIEnv<'local>,
|
||||
env: JNIEnv<'local>,
|
||||
_class: JClass<'local>,
|
||||
input: JObject<'local>,
|
||||
) -> jstring {
|
||||
) -> jobject {
|
||||
// Create JInputStream from the Java input stream
|
||||
let shared_env = Rc::new(RefCell::new(env));
|
||||
let mut stream = JInputStream::new(shared_env.clone(), input);
|
||||
let stream = JInputStream::new(shared_env.clone(), input);
|
||||
let file_ref = FileRef::new(stream);
|
||||
let file = file_ref.file();
|
||||
let mut jbuilder = JMetadataBuilder::new(shared_env.clone());
|
||||
match file {
|
||||
Some(mut file) => {
|
||||
if let Some(properties) = file.audio_properties() {
|
||||
jbuilder.set_properties(properties);
|
||||
}
|
||||
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(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 flac) = file.as_flac() {
|
||||
jbuilder.set_mime_type("audio/flac");
|
||||
if let Some(tag) = flac.xiph_comments() {
|
||||
jbuilder.set_xiph(&tag);
|
||||
}
|
||||
}
|
||||
if let Some(mut mpeg) = file.as_mpeg() {
|
||||
jbuilder.set_mime_type("audio/mpeg");
|
||||
if let Some(tag) = mpeg.id3v1_tag() {
|
||||
jbuilder.set_id3v1(&tag);
|
||||
}
|
||||
if let Some(tag) = mpeg.id3v2_tag() {
|
||||
jbuilder.set_id3v2(&tag);
|
||||
}
|
||||
}
|
||||
if let Some(mp4) = file.as_mp4() {
|
||||
jbuilder.set_mime_type("audio/mp4");
|
||||
if let Some(tag) = mp4.tag() {
|
||||
jbuilder.set_mp4(&tag);
|
||||
}
|
||||
}
|
||||
if let Some(mut wav) = file.as_wav() {
|
||||
jbuilder.set_mime_type("audio/wav");
|
||||
if let Some(tag) = wav.id3v2_tag() {
|
||||
jbuilder.set_id3v2(&tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
||||
|
||||
// Return the title
|
||||
let output = shared_env
|
||||
.borrow_mut()
|
||||
.new_string("title")
|
||||
.expect("Couldn't create string!");
|
||||
output.into_raw()
|
||||
jbuilder.build().into_raw()
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use super::bridge::CppAudioProperties;
|
||||
use super::this::{RefThis, This};
|
||||
use std::pin::Pin;
|
||||
use super::this::RefThis;
|
||||
|
||||
pub struct AudioProperties<'file_ref> {
|
||||
this: RefThis<'file_ref, CppAudioProperties>,
|
||||
|
|
|
@ -51,7 +51,9 @@ mod bridge_impl {
|
|||
#[namespace = "TagLib"]
|
||||
#[cxx_name = "IOStream"]
|
||||
type CPPIOStream<'io_stream>;
|
||||
fn wrap_RsIOStream<'io_stream>(stream: Box<DynIOStream<'io_stream>>) -> UniquePtr<CPPIOStream<'io_stream>>;
|
||||
fn wrap_RsIOStream<'io_stream>(
|
||||
stream: Box<DynIOStream<'io_stream>>,
|
||||
) -> UniquePtr<CPPIOStream<'io_stream>>;
|
||||
|
||||
#[namespace = "TagLib"]
|
||||
#[cxx_name = "FileRef"]
|
||||
|
@ -258,9 +260,7 @@ mod bridge_impl {
|
|||
#[cxx_name = "FrameList"]
|
||||
type CPPID3v2FrameList;
|
||||
#[namespace = "taglib_shim"]
|
||||
fn FrameList_to_vector(
|
||||
list: &CPPID3v2FrameList,
|
||||
) -> UniquePtr<CxxVector<CPPFramePointer>>;
|
||||
fn FrameList_to_vector(list: &CPPID3v2FrameList) -> UniquePtr<CxxVector<CPPFramePointer>>;
|
||||
|
||||
#[namespace = "taglib_shim"]
|
||||
#[cxx_name = "FramePointer"]
|
||||
|
@ -318,9 +318,7 @@ mod bridge_impl {
|
|||
#[cxx_name = "StringList"]
|
||||
type CPPStringList;
|
||||
#[namespace = "taglib_shim"]
|
||||
fn StringList_to_vector(
|
||||
string_list: &CPPStringList,
|
||||
) -> UniquePtr<CxxVector<CPPString>>;
|
||||
fn StringList_to_vector(string_list: &CPPStringList) -> UniquePtr<CxxVector<CPPString>>;
|
||||
|
||||
#[namespace = "TagLib"]
|
||||
#[cxx_name = "ByteVector"]
|
||||
|
@ -332,7 +330,9 @@ mod bridge_impl {
|
|||
#[cxx_name = "ByteVectorList"]
|
||||
type CPPByteVectorList;
|
||||
#[namespace = "taglib_shim"]
|
||||
fn ByteVectorList_to_vector(list: &CPPByteVectorList) -> UniquePtr<CxxVector<CPPByteVector>>;
|
||||
fn ByteVectorList_to_vector(
|
||||
list: &CPPByteVectorList,
|
||||
) -> UniquePtr<CxxVector<CPPByteVector>>;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
use super::audioproperties::AudioProperties;
|
||||
use super::bridge::{self, CPPFile, CPPMPEGFile};
|
||||
use super::bridge::{self, CPPFile};
|
||||
use super::flac::FLACFile;
|
||||
use super::id3v2::ID3v2Tag;
|
||||
use super::mp4::MP4File;
|
||||
use super::mpeg::MPEGFile;
|
||||
use super::ogg::OpusFile;
|
||||
use super::ogg::VorbisFile;
|
||||
use super::this::{RefThisMut, RefThis, This, ThisMut};
|
||||
use std::pin::Pin;
|
||||
use super::riff::WAVFile;
|
||||
use super::this::{RefThis, RefThisMut};
|
||||
|
||||
pub struct File<'file_ref> {
|
||||
this: RefThisMut<'file_ref, CPPFile>
|
||||
this: RefThisMut<'file_ref, CPPFile>,
|
||||
}
|
||||
|
||||
impl<'file_ref> File<'file_ref> {
|
||||
|
@ -118,12 +117,16 @@ impl<'file_ref> File<'file_ref> {
|
|||
}
|
||||
|
||||
pub fn as_mp4(&mut self) -> Option<MP4File<'file_ref>> {
|
||||
let mp4_file = unsafe {
|
||||
bridge::File_asMP4(self.this.ptr_mut())
|
||||
};
|
||||
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| RefThisMut::new(mp4));
|
||||
mp4_this.map(|this| MP4File::new(this))
|
||||
}
|
||||
|
||||
pub fn as_wav(&mut self) -> Option<WAVFile<'file_ref>> {
|
||||
let wav_file = unsafe { bridge::File_asWAV(self.this.ptr_mut()) };
|
||||
let wav_ref = unsafe { wav_file.as_mut() };
|
||||
let wav_this = wav_ref.map(|wav| RefThisMut::new(wav));
|
||||
wav_this.map(|this| WAVFile::new(this))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
pub use super::bridge::CPPFLACFile;
|
||||
pub use super::bridge::CPPFLACPicture;
|
||||
use super::bridge::{CPPPictureList, FLACFile_pictureList, PictureList_to_vector, Picture_data, CPPByteVector};
|
||||
use super::bridge::{
|
||||
CPPPictureList, FLACFile_pictureList, PictureList_to_vector, Picture_data,
|
||||
};
|
||||
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::this::{OwnedThis, RefThisMut, RefThis, This, ThisMut};
|
||||
use cxx::UniquePtr;
|
||||
use std::marker::PhantomData;
|
||||
use std::pin::Pin;
|
||||
|
||||
pub struct FLACFile<'file_ref> {
|
||||
this: RefThisMut<'file_ref, CPPFLACFile>
|
||||
this: RefThisMut<'file_ref, CPPFLACFile>,
|
||||
}
|
||||
|
||||
impl<'file_ref> FLACFile<'file_ref> {
|
||||
|
@ -19,7 +18,6 @@ impl<'file_ref> FLACFile<'file_ref> {
|
|||
Self { this }
|
||||
}
|
||||
|
||||
|
||||
pub fn xiph_comments(&mut self) -> Option<XiphComment<'file_ref>> {
|
||||
let tag = self.this.pin_mut().xiphComment(false);
|
||||
let tag_ref = unsafe {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use super::bridge::{self, CPPID3v1Tag};
|
||||
use super::this::{RefThisMut, RefThis, This, OwnedThis};
|
||||
use super::tk::{String, OwnedString};
|
||||
use super::this::{OwnedThis, RefThisMut};
|
||||
use super::tk::{OwnedString, String};
|
||||
|
||||
pub struct ID3v1Tag<'file_ref> {
|
||||
this: RefThisMut<'file_ref, CPPID3v1Tag>,
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use super::bridge::{
|
||||
self, CPPID3v2AttachedPictureFrame, CPPID3v2Frame, CPPID3v2FrameList, CPPID3v2Tag,
|
||||
CPPID3v2TextIdentificationFrame, CPPID3v2UserTextIdentificationFrame, CPPStringList, CPPByteVector,
|
||||
self, CPPID3v2AttachedPictureFrame, CPPID3v2Frame, CPPID3v2FrameList,
|
||||
CPPID3v2Tag, CPPID3v2TextIdentificationFrame, CPPID3v2UserTextIdentificationFrame,
|
||||
};
|
||||
use super::tk::{self, ByteVector, StringList, OwnedByteVector, OwnedStringList};
|
||||
use super::this::{OwnedThis, RefThisMut, RefThis, This};
|
||||
use super::this::{OwnedThis, RefThis, RefThisMut};
|
||||
use super::tk::{self, ByteVector, OwnedByteVector, OwnedStringList, StringList};
|
||||
|
||||
pub struct ID3v2Tag<'file_ref> {
|
||||
this: RefThisMut<'file_ref, CPPID3v2Tag>,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use super::bridge::{self, CPPIOStream};
|
||||
use cxx::UniquePtr;
|
||||
use std::io::{Read, Seek, SeekFrom, Write};
|
||||
use std::pin::Pin;
|
||||
use std::io::{Seek, SeekFrom};
|
||||
|
||||
pub trait IOStream {
|
||||
fn read_block(&mut self, buffer: &mut [u8]) -> usize;
|
||||
|
@ -22,9 +21,7 @@ impl<'io_stream> BridgedIOStream<'io_stream> {
|
|||
pub fn new<T: IOStream + 'io_stream>(stream: T) -> Self {
|
||||
let rs_stream: Box<DynIOStream<'io_stream>> = Box::new(DynIOStream(Box::new(stream)));
|
||||
let cpp_stream: UniquePtr<CPPIOStream<'io_stream>> = bridge::wrap_RsIOStream(rs_stream);
|
||||
BridgedIOStream {
|
||||
cpp_stream,
|
||||
}
|
||||
BridgedIOStream { cpp_stream }
|
||||
}
|
||||
|
||||
pub fn cpp_stream(&self) -> &UniquePtr<CPPIOStream> {
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
mod bridge;
|
||||
mod this;
|
||||
pub mod iostream;
|
||||
pub mod file_ref;
|
||||
pub mod file;
|
||||
pub mod audioproperties;
|
||||
pub mod ogg;
|
||||
pub mod mpeg;
|
||||
mod bridge;
|
||||
pub mod file;
|
||||
pub mod file_ref;
|
||||
pub mod flac;
|
||||
pub mod xiph;
|
||||
pub mod tk;
|
||||
pub mod id3v2;
|
||||
pub mod id3v1;
|
||||
pub mod id3v2;
|
||||
pub mod iostream;
|
||||
pub mod mp4;
|
||||
pub mod mpeg;
|
||||
pub mod ogg;
|
||||
pub mod riff;
|
||||
mod this;
|
||||
pub mod tk;
|
||||
pub mod xiph;
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
pub use super::bridge::CPPMP4Tag;
|
||||
use super::bridge::{CPPFile, CPPIntPair, CPPItemMap, CPPItemMapEntry, CPPMP4File, CPPMP4Item, ItemMap_to_entries, MP4ItemType};
|
||||
use super::bridge::{
|
||||
CPPIntPair, CPPItemMap, CPPMP4File, CPPMP4Item, ItemMap_to_entries,
|
||||
MP4ItemType,
|
||||
};
|
||||
use super::this::{OwnedThis, RefThis, RefThisMut};
|
||||
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>,
|
||||
|
@ -53,8 +55,8 @@ impl<'file_ref> ItemMap<'file_ref> {
|
|||
|
||||
pub fn to_hashmap(&self) -> HashMap<String, MP4Item<'file_ref>> {
|
||||
let cxx_vec = ItemMap_to_entries(self.this.as_ref());
|
||||
let vec: Vec<(String, MP4Item<'file_ref>)> =
|
||||
cxx_vec.iter()
|
||||
let vec: Vec<(String, MP4Item<'file_ref>)> = cxx_vec
|
||||
.iter()
|
||||
.map(|property| {
|
||||
// SAFETY:
|
||||
// - This pin is only used in this unsafe scope.
|
||||
|
@ -101,24 +103,30 @@ impl<'file_ref> MP4Item<'file_ref> {
|
|||
let pair = super::bridge::Item_toIntPair(self.this.as_ref());
|
||||
let pair_this = OwnedThis::new(pair).unwrap();
|
||||
Some(MP4Data::IntPair(IntPair::new(pair_this)))
|
||||
},
|
||||
}
|
||||
MP4ItemType::Byte => Some(MP4Data::Byte(self.this.as_ref().toByte())),
|
||||
MP4ItemType::UInt => Some(MP4Data::UInt(self.this.as_ref().toUInt())),
|
||||
MP4ItemType::LongLong => Some(MP4Data::LongLong(super::bridge::Item_toLongLong(self.this.as_ref()))),
|
||||
MP4ItemType::LongLong => Some(MP4Data::LongLong(super::bridge::Item_toLongLong(
|
||||
self.this.as_ref(),
|
||||
))),
|
||||
MP4ItemType::StringList => {
|
||||
let string_list = super::bridge::Item_toStringList(self.this.as_ref());
|
||||
let string_list_this = OwnedThis::new(string_list).unwrap();
|
||||
Some(MP4Data::StringList(tk::StringList::new(string_list_this)))
|
||||
},
|
||||
}
|
||||
MP4ItemType::ByteVectorList => {
|
||||
let byte_vector_list = super::bridge::Item_toByteVectorList(self.this.as_ref());
|
||||
let byte_vector_list_this = OwnedThis::new(byte_vector_list).unwrap();
|
||||
Some(MP4Data::ByteVectorList(tk::ByteVectorList::new(byte_vector_list_this)))
|
||||
},
|
||||
Some(MP4Data::ByteVectorList(tk::ByteVectorList::new(
|
||||
byte_vector_list_this,
|
||||
)))
|
||||
}
|
||||
MP4ItemType::CoverArtList => {
|
||||
let cover_art_list = super::bridge::Item_toCoverArtList(self.this.as_ref());
|
||||
let cover_art_list_this = OwnedThis::new(cover_art_list).unwrap();
|
||||
Some(MP4Data::CoverArtList(CoverArtList::new(cover_art_list_this)))
|
||||
Some(MP4Data::CoverArtList(CoverArtList::new(
|
||||
cover_art_list_this,
|
||||
)))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use super::bridge::{self, CPPMPEGFile};
|
||||
use super::bridge::{CPPMPEGFile};
|
||||
use super::id3v1::ID3v1Tag;
|
||||
use super::id3v2::ID3v2Tag;
|
||||
use super::this::{RefThisMut, This, ThisMut};
|
||||
use std::pin::Pin;
|
||||
use super::this::{RefThisMut, ThisMut};
|
||||
|
||||
pub struct MPEGFile<'file_ref> {
|
||||
this: RefThisMut<'file_ref, CPPMPEGFile>,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
pub use super::bridge::{CPPOpusFile, CPPVorbisFile};
|
||||
use super::this::RefThisMut;
|
||||
use super::xiph::XiphComment;
|
||||
use super::this::{RefThisMut, RefThis, This};
|
||||
use std::pin::Pin;
|
||||
|
||||
pub struct VorbisFile<'file_ref> {
|
||||
this: RefThisMut<'file_ref, CPPVorbisFile>,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use super::bridge::{self, CPPWAVFile};
|
||||
use super::bridge::{CPPWAVFile};
|
||||
use super::id3v2::ID3v2Tag;
|
||||
use super::this::{RefThisMut, This, ThisMut};
|
||||
use std::pin::Pin;
|
||||
use super::this::RefThisMut;
|
||||
|
||||
pub struct WAVFile<'file_ref> {
|
||||
this: RefThisMut<'file_ref, CPPWAVFile>,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use super::bridge::{TagLibAllocated, TagLibRef, TagLibShared};
|
||||
use cxx::{memory::UniquePtrTarget, UniquePtr};
|
||||
use std::marker::PhantomData;
|
||||
use std::pin::Pin;
|
||||
use cxx::{UniquePtr, memory::UniquePtrTarget};
|
||||
use super::bridge::{TagLibAllocated, TagLibRef, TagLibShared};
|
||||
|
||||
/// A taglib-FFI-specific trait representing a C++ object returned by the library.
|
||||
///
|
||||
|
@ -10,7 +10,7 @@ use super::bridge::{TagLibAllocated, TagLibRef, TagLibShared};
|
|||
/// 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> {}
|
||||
pub trait This<'file_ref, T: TagLibAllocated>: AsRef<T> {}
|
||||
|
||||
/// A taglib-FFI-specific trait representing a C++ object returned by the library.
|
||||
///
|
||||
|
@ -22,13 +22,13 @@ pub trait This<'file_ref, T: TagLibAllocated> : AsRef<T> {}
|
|||
/// 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> {
|
||||
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
|
||||
this: &'file_ref T,
|
||||
}
|
||||
|
||||
impl<'file_ref, T: TagLibRef> RefThis<'file_ref, T> {
|
||||
|
@ -155,9 +155,10 @@ impl<'file_ref, T: TagLibShared + UniquePtrTarget> AsRef<T> for OwnedThis<'file_
|
|||
|
||||
impl<'file_ref, T: TagLibShared + UniquePtrTarget> This<'file_ref, T> for OwnedThis<'file_ref, T> {}
|
||||
|
||||
impl<'file_ref, T: TagLibShared + UniquePtrTarget> ThisMut<'file_ref, T> for OwnedThis<'file_ref, T> {
|
||||
impl<'file_ref, T: TagLibShared + UniquePtrTarget> ThisMut<'file_ref, T>
|
||||
for OwnedThis<'file_ref, T>
|
||||
{
|
||||
fn pin_mut(&mut self) -> Pin<&mut T> {
|
||||
self.this.as_mut().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
use super::bridge;
|
||||
use super::this::{RefThis, RefThisMut, This, OwnedThis};
|
||||
use cxx::{memory::UniquePtrTarget, UniquePtr};
|
||||
use super::this::{OwnedThis, RefThis, RefThisMut, This};
|
||||
use std::marker::PhantomData;
|
||||
use std::pin::Pin;
|
||||
use std::{ffi::CStr, string::ToString};
|
||||
|
||||
pub use bridge::CPPString as InnerString;
|
||||
pub use bridge::CPPStringList as InnerStringList;
|
||||
pub use bridge::CPPByteVector as InnerByteVector;
|
||||
pub use bridge::CPPByteVectorList as InnerByteVectorList;
|
||||
pub use bridge::CPPString as InnerString;
|
||||
pub use bridge::CPPStringList as InnerStringList;
|
||||
|
||||
pub struct String<'file_ref, T: This<'file_ref, InnerString>> {
|
||||
_data: PhantomData<&'file_ref ()>,
|
||||
|
@ -17,7 +15,10 @@ pub struct String<'file_ref, T: This<'file_ref, InnerString>> {
|
|||
|
||||
impl<'file_ref, T: This<'file_ref, InnerString>> String<'file_ref, T> {
|
||||
pub(super) fn new(this: T) -> Self {
|
||||
Self { _data: PhantomData, this }
|
||||
Self {
|
||||
_data: PhantomData,
|
||||
this,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,13 +50,12 @@ pub struct StringList<'file_ref, T: This<'file_ref, InnerStringList>> {
|
|||
this: 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>>;
|
||||
|
||||
impl<'file_ref, T: This<'file_ref, InnerStringList>> StringList<'file_ref, T> {
|
||||
pub(super) fn new(this: T) -> Self {
|
||||
Self { _data: PhantomData, this }
|
||||
Self {
|
||||
_data: PhantomData,
|
||||
this,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_vec(&self) -> Vec<std::string::String> {
|
||||
|
@ -70,6 +70,11 @@ 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>,
|
||||
this: T,
|
||||
|
@ -77,7 +82,10 @@ pub struct ByteVector<'file_ref, T: This<'file_ref, InnerByteVector>> {
|
|||
|
||||
impl<'file_ref, T: This<'file_ref, InnerByteVector>> ByteVector<'file_ref, T> {
|
||||
pub(super) fn new(this: T) -> Self {
|
||||
Self { _data: PhantomData, this }
|
||||
Self {
|
||||
_data: PhantomData,
|
||||
this,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_vec(&self) -> Vec<u8> {
|
||||
|
@ -107,7 +115,8 @@ 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 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>,
|
||||
|
@ -116,7 +125,10 @@ pub struct ByteVectorList<'file_ref, T: This<'file_ref, InnerByteVectorList>> {
|
|||
|
||||
impl<'file_ref, T: This<'file_ref, InnerByteVectorList>> ByteVectorList<'file_ref, T> {
|
||||
pub(super) fn new(this: T) -> Self {
|
||||
Self { _data: PhantomData, this }
|
||||
Self {
|
||||
_data: PhantomData,
|
||||
this,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_vec(&self) -> Vec<Vec<u8>> {
|
||||
|
@ -128,7 +140,9 @@ impl<'file_ref, T: This<'file_ref, InnerByteVectorList>> ByteVectorList<'file_re
|
|||
}
|
||||
}
|
||||
|
||||
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>>;
|
||||
|
||||
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,10 +1,9 @@
|
|||
pub use super::bridge::CPPXiphComment;
|
||||
use super::bridge::{CPPFieldListMap, FieldListMap_to_entries, XiphComment_pictureList};
|
||||
pub use super::flac::PictureList;
|
||||
use super::this::{OwnedThis, RefThis, RefThisMut, ThisMut};
|
||||
use super::tk;
|
||||
use super::this::{OwnedThis, RefThis, RefThisMut, ThisMut, This};
|
||||
use std::collections::HashMap;
|
||||
use std::pin::Pin;
|
||||
|
||||
pub struct XiphComment<'file_ref> {
|
||||
this: RefThisMut<'file_ref, CPPXiphComment>,
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
use jni::{
|
||||
objects::{JObject, JValueGen},
|
||||
JNIEnv,
|
||||
};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use jni::{objects::{JObject, JValueGen}, JNIEnv};
|
||||
|
||||
pub struct JTagMap<'local> {
|
||||
env: Rc<RefCell<JNIEnv<'local>>>,
|
||||
|
@ -27,7 +30,12 @@ impl<'local> JTagMap<'local> {
|
|||
self.map.entry(id).or_default().extend(values);
|
||||
}
|
||||
|
||||
pub fn add_combined(&mut self, id: impl Into<String>, description: impl Into<String>, value: impl Into<String>) {
|
||||
pub fn add_combined(
|
||||
&mut self,
|
||||
id: impl Into<String>,
|
||||
description: impl Into<String>,
|
||||
value: impl Into<String>,
|
||||
) {
|
||||
let id = id.into();
|
||||
let description = description.into();
|
||||
let value = value.into();
|
||||
|
@ -36,8 +44,16 @@ impl<'local> JTagMap<'local> {
|
|||
}
|
||||
|
||||
pub fn get_object(&self) -> JObject {
|
||||
let map_class = self.env.borrow_mut().find_class("java/util/HashMap").unwrap();
|
||||
let map = self.env.borrow_mut().new_object(&map_class, "()V", &[]).unwrap();
|
||||
let map_class = self
|
||||
.env
|
||||
.borrow_mut()
|
||||
.find_class("java/util/HashMap")
|
||||
.unwrap();
|
||||
let map = self
|
||||
.env
|
||||
.borrow_mut()
|
||||
.new_object(&map_class, "()V", &[])
|
||||
.unwrap();
|
||||
|
||||
for (key, values) in &self.map {
|
||||
let j_key = self.env.borrow().new_string(key).unwrap();
|
||||
|
@ -47,26 +63,38 @@ impl<'local> JTagMap<'local> {
|
|||
.collect();
|
||||
|
||||
// Create ArrayList for values
|
||||
let array_list_class = self.env.borrow_mut().find_class("java/util/ArrayList").unwrap();
|
||||
let array_list = self.env.borrow_mut().new_object(array_list_class, "()V", &[]).unwrap();
|
||||
let array_list_class = self
|
||||
.env
|
||||
.borrow_mut()
|
||||
.find_class("java/util/ArrayList")
|
||||
.unwrap();
|
||||
let array_list = self
|
||||
.env
|
||||
.borrow_mut()
|
||||
.new_object(array_list_class, "()V", &[])
|
||||
.unwrap();
|
||||
|
||||
for value in j_values {
|
||||
self.env.borrow_mut()
|
||||
self.env
|
||||
.borrow_mut()
|
||||
.call_method(
|
||||
&array_list,
|
||||
"add",
|
||||
"(Ljava/lang/Object;)Z",
|
||||
&[JValueGen::from(&value)]
|
||||
).unwrap();
|
||||
&[JValueGen::from(&value)],
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
self.env.borrow_mut()
|
||||
self.env
|
||||
.borrow_mut()
|
||||
.call_method(
|
||||
&map,
|
||||
"put",
|
||||
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
|
||||
&[JValueGen::from(&j_key), JValueGen::from(&array_list)]
|
||||
).unwrap();
|
||||
&[JValueGen::from(&j_key), JValueGen::from(&array_list)],
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
map
|
||||
|
|
Loading…
Reference in a new issue