musikr: add basic mp4 tag
This commit is contained in:
parent
6ef79a9aa5
commit
65d8959bcf
6 changed files with 126 additions and 13 deletions
|
@ -123,6 +123,7 @@ fn main() {
|
|||
.file("shim/xiph_shim.cpp")
|
||||
.file("shim/id3v1_shim.cpp")
|
||||
.file("shim/id3v2_shim.cpp")
|
||||
.file("shim/mp4_shim.cpp")
|
||||
.include(format!("taglib/pkg/{}/include", target))
|
||||
.include(".") // Add the current directory to include path
|
||||
.flag_if_supported("-std=c++14");
|
||||
|
|
27
musikr/src/main/jni/shim/mp4_shim.cpp
Normal file
27
musikr/src/main/jni/shim/mp4_shim.cpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
#include "mp4_shim.hpp"
|
||||
#include <taglib/tstring.h>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace taglib_shim {
|
||||
ItemMapEntry::ItemMapEntry(TagLib::String key, TagLib::MP4::Item value)
|
||||
: key_(std::move(key)), value_(std::move(value)) {}
|
||||
|
||||
const TagLib::String& ItemMapEntry::key() const {
|
||||
return key_;
|
||||
}
|
||||
|
||||
const TagLib::MP4::Item& ItemMapEntry::value() const {
|
||||
return value_;
|
||||
}
|
||||
|
||||
std::unique_ptr<std::vector<ItemMapEntry>> ItemMap_to_entries(const TagLib::MP4::ItemMap& map) {
|
||||
auto entries = std::make_unique<std::vector<ItemMapEntry>>();
|
||||
|
||||
for (auto it = map.begin(); it != map.end(); ++it) {
|
||||
entries->emplace_back(it->first, it->second);
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
}
|
22
musikr/src/main/jni/shim/mp4_shim.hpp
Normal file
22
musikr/src/main/jni/shim/mp4_shim.hpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <taglib/mp4tag.h>
|
||||
#include <taglib/mp4item.h>
|
||||
#include <taglib/tstring.h>
|
||||
#include "rust/cxx.h"
|
||||
|
||||
namespace taglib_shim {
|
||||
class ItemMapEntry {
|
||||
public:
|
||||
ItemMapEntry(TagLib::String key, TagLib::MP4::Item value);
|
||||
const TagLib::String& key() const;
|
||||
const TagLib::MP4::Item& value() const;
|
||||
|
||||
private:
|
||||
TagLib::String key_;
|
||||
TagLib::MP4::Item value_;
|
||||
};
|
||||
|
||||
std::unique_ptr<std::vector<ItemMapEntry>> ItemMap_to_entries(const TagLib::MP4::ItemMap& map);
|
||||
}
|
|
@ -34,6 +34,7 @@ mod bridge_impl {
|
|||
include!("shim/xiph_shim.hpp");
|
||||
include!("shim/id3v2_shim.hpp");
|
||||
include!("shim/id3v1_shim.hpp");
|
||||
include!("shim/mp4_shim.hpp");
|
||||
include!("taglib/mpegfile.h");
|
||||
|
||||
#[namespace = "TagLib"]
|
||||
|
@ -45,15 +46,12 @@ mod bridge_impl {
|
|||
#[cxx_name = "FileRef"]
|
||||
type CPPFileRef;
|
||||
unsafe fn new_FileRef(stream: *mut CPPIOStream) -> UniquePtr<CPPFileRef>;
|
||||
#[cxx_name = "isNull"]
|
||||
fn isNull(self: Pin<&CPPFileRef>) -> bool;
|
||||
#[cxx_name = "file"]
|
||||
fn file(self: Pin<&CPPFileRef>) -> *mut CPPFile;
|
||||
|
||||
#[namespace = "TagLib"]
|
||||
#[cxx_name = "File"]
|
||||
type CPPFile;
|
||||
#[cxx_name = "audioProperties"]
|
||||
fn audioProperties(self: Pin<&CPPFile>) -> *mut CppAudioProperties;
|
||||
#[namespace = "taglib_shim"]
|
||||
unsafe fn File_asVorbis(file: *mut CPPFile) -> *mut CPPVorbisFile;
|
||||
|
@ -71,13 +69,9 @@ mod bridge_impl {
|
|||
#[namespace = "TagLib"]
|
||||
#[cxx_name = "AudioProperties"]
|
||||
type CppAudioProperties;
|
||||
#[cxx_name = "lengthInMilliseconds"]
|
||||
fn lengthInMilliseconds(self: Pin<&CppAudioProperties>) -> i32;
|
||||
#[cxx_name = "bitrate"]
|
||||
fn bitrate(self: Pin<&CppAudioProperties>) -> i32;
|
||||
#[cxx_name = "sampleRate"]
|
||||
fn sampleRate(self: Pin<&CppAudioProperties>) -> i32;
|
||||
#[cxx_name = "channels"]
|
||||
fn channels(self: Pin<&CppAudioProperties>) -> i32;
|
||||
|
||||
#[namespace = "TagLib::Ogg::Vorbis"]
|
||||
|
@ -97,7 +91,6 @@ mod bridge_impl {
|
|||
#[namespace = "TagLib::FLAC"]
|
||||
#[cxx_name = "File"]
|
||||
type CPPFLACFile;
|
||||
#[cxx_name = "xiphComment"]
|
||||
fn xiphComment(self: Pin<&mut CPPFLACFile>, create: bool) -> *mut CPPXiphComment;
|
||||
#[namespace = "taglib_shim"]
|
||||
fn FLACFile_pictureList(file: Pin<&mut CPPFLACFile>) -> UniquePtr<CPPPictureList>;
|
||||
|
@ -118,7 +111,6 @@ mod bridge_impl {
|
|||
#[namespace = "TagLib::MPEG"]
|
||||
#[cxx_name = "File"]
|
||||
type CPPMPEGFile;
|
||||
#[cxx_name = "ID3v2Tag"]
|
||||
fn ID3v2Tag(self: Pin<&mut CPPMPEGFile>, create: bool) -> *mut CPPID3v2Tag;
|
||||
|
||||
#[namespace = "TagLib::MP4"]
|
||||
|
@ -140,7 +132,6 @@ mod bridge_impl {
|
|||
type CPPXiphComment;
|
||||
// Explicit lifecycle definition to state while the Pin is temporary, the CPPFieldListMap
|
||||
// ref returned actually has the same lifetime as the CPPXiphComment.
|
||||
#[cxx_name = "fieldListMap"]
|
||||
fn fieldListMap<'slf, 'file_ref>(self: Pin<&'slf CPPXiphComment>) -> &'file_ref CPPFieldListMap;
|
||||
|
||||
#[namespace = "TagLib"]
|
||||
|
@ -154,9 +145,7 @@ mod bridge_impl {
|
|||
#[namespace = "taglib_shim"]
|
||||
#[cxx_name = "FieldListEntry"]
|
||||
type CPPFieldListEntry;
|
||||
#[cxx_name = "key"]
|
||||
fn key(self: Pin<&CPPFieldListEntry>) -> &CPPString;
|
||||
#[cxx_name = "value"]
|
||||
fn value(self: Pin<&CPPFieldListEntry>) -> &CPPStringList;
|
||||
|
||||
#[namespace = "TagLib::ID3v2"]
|
||||
|
@ -221,7 +210,6 @@ mod bridge_impl {
|
|||
#[namespace = "TagLib"]
|
||||
#[cxx_name = "String"]
|
||||
type CPPString;
|
||||
#[cxx_name = "toCString"]
|
||||
fn toCString(self: Pin<&CPPString>, unicode: bool) -> *const c_char;
|
||||
|
||||
#[namespace = "TagLib"]
|
||||
|
@ -249,6 +237,27 @@ mod bridge_impl {
|
|||
fn ID3v1Tag_genreIndex(tag: Pin<&CPPID3v1Tag>) -> u32;
|
||||
fn ID3v1Tag_year(tag: Pin<&CPPID3v1Tag>) -> u32;
|
||||
fn ID3v1Tag_track(tag: Pin<&CPPID3v1Tag>) -> u32;
|
||||
|
||||
#[namespace = "TagLib::MP4"]
|
||||
#[cxx_name = "Tag"]
|
||||
type CPPMP4Tag;
|
||||
|
||||
#[namespace = "TagLib::MP4"]
|
||||
#[cxx_name = "ItemMap"]
|
||||
type CPPItemMap;
|
||||
fn itemMap<'slf, 'file_ref>(self: Pin<&'slf CPPMP4Tag>) -> &'file_ref CPPItemMap;
|
||||
fn ItemMap_to_entries(map: Pin<&CPPItemMap>) -> UniquePtr<CxxVector<CPPItemMapEntry>>;
|
||||
|
||||
#[namespace = "taglib_shim"]
|
||||
#[cxx_name = "ItemMapEntry"]
|
||||
type CPPItemMapEntry;
|
||||
fn key(self: Pin<&CPPItemMapEntry>) -> &CPPString;
|
||||
fn value(self: Pin<&CPPItemMapEntry>) -> &CPPMP4Item;
|
||||
|
||||
#[namespace = "TagLib::MP4"]
|
||||
#[cxx_name = "Item"]
|
||||
type CPPMP4Item;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,3 +11,4 @@ pub mod xiph;
|
|||
pub mod tk;
|
||||
pub mod id3v2;
|
||||
pub mod id3v1;
|
||||
pub mod mp4;
|
||||
|
|
53
musikr/src/main/jni/src/taglib/mp4.rs
Normal file
53
musikr/src/main/jni/src/taglib/mp4.rs
Normal file
|
@ -0,0 +1,53 @@
|
|||
pub use super::bridge::CPPMP4Tag;
|
||||
use super::bridge::{CPPItemMap, ItemMap_to_entries, CPPItemMapEntry};
|
||||
use super::tk;
|
||||
use super::this::{OwnedThis, RefThis, RefThisMut, ThisMut, This};
|
||||
use std::collections::HashMap;
|
||||
use std::pin::Pin;
|
||||
|
||||
pub struct MP4Tag<'file_ref> {
|
||||
this: RefThisMut<'file_ref, CPPMP4Tag>,
|
||||
}
|
||||
|
||||
impl<'file_ref> MP4Tag<'file_ref> {
|
||||
pub fn new(this: RefThisMut<'file_ref, CPPMP4Tag>) -> Self {
|
||||
Self { this }
|
||||
}
|
||||
|
||||
pub fn item_map<'slf>(&'slf self) -> ItemMap<'file_ref> {
|
||||
let map: &'file_ref CPPItemMap = self.this.pin().itemMap();
|
||||
let map_this = unsafe { RefThis::new(map) };
|
||||
ItemMap::new(map_this)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ItemMap<'file_ref> {
|
||||
this: RefThis<'file_ref, CPPItemMap>,
|
||||
}
|
||||
|
||||
impl<'file_ref> ItemMap<'file_ref> {
|
||||
pub fn new(this: RefThis<'file_ref, CPPItemMap>) -> Self {
|
||||
Self { this }
|
||||
}
|
||||
|
||||
pub fn to_hashmap(&self) -> HashMap<String, ()> {
|
||||
let cxx_vec = ItemMap_to_entries(self.this.pin());
|
||||
cxx_vec
|
||||
.iter()
|
||||
.map(|property| {
|
||||
// SAFETY:
|
||||
// - This pin is only used in this unsafe scope.
|
||||
// - The pin is used as a C++ this pointer in the ffi call, which does
|
||||
// not change address by C++ semantics.
|
||||
// - The values returned are copied and thus not dependent on the address
|
||||
// of self.
|
||||
let property_pin = unsafe { Pin::new_unchecked(property) };
|
||||
let key_ref = property_pin.key();
|
||||
let key_this = unsafe { RefThis::new(key_ref) };
|
||||
let key = tk::String::new(key_this).to_string();
|
||||
// For now, we're just returning () as a placeholder for MP4::Item
|
||||
(key, ())
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue