musikr: basic vorbis support
This commit is contained in:
parent
013f25f46f
commit
3aa39a7065
5 changed files with 128 additions and 8 deletions
|
@ -110,6 +110,7 @@ fn main() {
|
|||
cxx_build::bridge("src/taglib/ffi.rs")
|
||||
.file("shim/iostream_shim.cpp")
|
||||
.file("shim/file_shim.cpp")
|
||||
.file("shim/tk_shim.cpp")
|
||||
.include(format!("taglib/pkg/{}/include", arch))
|
||||
.include("shim")
|
||||
.include(".") // Add the current directory to include path
|
||||
|
@ -122,5 +123,7 @@ fn main() {
|
|||
println!("cargo:rerun-if-changed=shim/iostream_shim.cpp");
|
||||
println!("cargo:rerun-if-changed=shim/file_shim.hpp");
|
||||
println!("cargo:rerun-if-changed=shim/file_shim.cpp");
|
||||
println!("cargo:rerun-if-changed=shim/tk_shim.hpp");
|
||||
println!("cargo:rerun-if-changed=shim/tk_shim.cpp");
|
||||
println!("cargo:rerun-if-changed=src/taglib/ffi.rs");
|
||||
}
|
||||
|
|
30
musikr/src/main/jni/shim/tk_shim.cpp
Normal file
30
musikr/src/main/jni/shim/tk_shim.cpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#include "tk_shim.hpp"
|
||||
|
||||
|
||||
namespace taglib_shim {
|
||||
Property::Property(TagLib::String key, TagLib::StringList value) : key_(key), value_(value) {}
|
||||
|
||||
const TagLib::String &Property::key() const {
|
||||
return key_;
|
||||
}
|
||||
|
||||
const TagLib::StringList &Property::value() const {
|
||||
return value_;
|
||||
}
|
||||
std::unique_ptr<std::vector<Property>> SimplePropertyMap_to_vector(const TagLib::SimplePropertyMap &map) {
|
||||
std::unique_ptr<std::vector<Property>> result = std::make_unique<std::vector<Property>>();
|
||||
for (const auto &pair : map) {
|
||||
result->push_back(Property(pair.first, pair.second));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::unique_ptr<std::vector<TagLib::String>> StringList_to_vector(const TagLib::StringList &list) {
|
||||
std::unique_ptr<std::vector<TagLib::String>> result = std::make_unique<std::vector<TagLib::String>>();
|
||||
for (const auto &str : list) {
|
||||
result->push_back(str);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
24
musikr/src/main/jni/shim/tk_shim.hpp
Normal file
24
musikr/src/main/jni/shim/tk_shim.hpp
Normal file
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
#include "taglib/tpropertymap.h"
|
||||
#include "taglib/xiphcomment.h"
|
||||
#include "taglib/tstring.h"
|
||||
#include "taglib/tstringlist.h"
|
||||
#include <memory>
|
||||
#include <iterator>
|
||||
|
||||
namespace taglib_shim {
|
||||
|
||||
struct Property {
|
||||
Property(TagLib::String key, TagLib::StringList value);
|
||||
const TagLib::String &key() const;
|
||||
const TagLib::StringList &value() const;
|
||||
|
||||
private:
|
||||
TagLib::String key_;
|
||||
TagLib::StringList value_;
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
|
@ -3,10 +3,12 @@ pub(crate) mod bindings {
|
|||
unsafe extern "C++" {
|
||||
include!("taglib/taglib.h");
|
||||
include!("taglib/tstring.h");
|
||||
include!("taglib/tstringlist.h");
|
||||
include!("taglib/vorbisfile.h");
|
||||
include!("taglib/xiphcomment.h");
|
||||
include!("shim/iostream_shim.hpp");
|
||||
include!("shim/file_shim.hpp");
|
||||
include!("shim/tk_shim.hpp");
|
||||
|
||||
#[namespace = "TagLib"]
|
||||
type FileRef;
|
||||
|
@ -47,13 +49,11 @@ pub(crate) mod bindings {
|
|||
#[namespace = "TagLib::Ogg::Opus"]
|
||||
#[cxx_name = "File"]
|
||||
type OpusFile;
|
||||
unsafe fn tag(self: Pin<&OpusFile>) -> *mut XiphComment;
|
||||
|
||||
#[namespace = "TagLib::Ogg"]
|
||||
type XiphComment;
|
||||
unsafe fn fieldListMap(self: Pin<&XiphComment>) -> &FieldListMap;
|
||||
|
||||
#[namespace = "TagLib::Ogg"]
|
||||
type FieldListMap;
|
||||
unsafe fn fieldListMap(self: Pin<&XiphComment>) -> &SimplePropertyMap;
|
||||
|
||||
#[namespace = "TagLib::MPEG"]
|
||||
#[cxx_name = "File"]
|
||||
|
@ -94,6 +94,21 @@ pub(crate) mod bindings {
|
|||
#[namespace = "taglib_shim"]
|
||||
unsafe fn File_asAPE(file: *mut File) -> *mut APEFile;
|
||||
|
||||
#[namespace = "TagLib"]
|
||||
type SimplePropertyMap;
|
||||
#[namespace = "taglib_shim"]
|
||||
fn SimplePropertyMap_to_vector(field_list_map: Pin<&SimplePropertyMap>) -> UniquePtr<CxxVector<Property>>;
|
||||
|
||||
#[namespace = "taglib_shim"]
|
||||
type Property;
|
||||
fn key(self: Pin<&Property>) -> &TagString;
|
||||
unsafe fn value(self: Pin<&Property>) -> &StringList;
|
||||
|
||||
#[namespace = "TagLib"]
|
||||
type StringList;
|
||||
#[namespace = "taglib_shim"]
|
||||
fn StringList_to_vector(string_list: Pin<&StringList>) -> UniquePtr<CxxVector<TagString>>;
|
||||
|
||||
#[namespace = "TagLib"]
|
||||
#[cxx_name = "String"]
|
||||
type TagString;
|
||||
|
|
|
@ -2,9 +2,13 @@ mod ffi;
|
|||
mod stream;
|
||||
|
||||
use ffi::bindings;
|
||||
use std::pin::Pin;
|
||||
use std::ffi::CStr;
|
||||
use std::pin::{pin, Pin};
|
||||
use std::collections::HashMap;
|
||||
pub use stream::{RustStream, TagLibStream};
|
||||
|
||||
type XiphComments = HashMap<String, Vec<String>>;
|
||||
|
||||
pub enum File {
|
||||
Unknown {
|
||||
audio_properties: Option<AudioProperties>,
|
||||
|
@ -14,15 +18,18 @@ pub enum File {
|
|||
},
|
||||
FLAC {
|
||||
audio_properties: Option<AudioProperties>,
|
||||
xiph_comments: Option<XiphComments>,
|
||||
},
|
||||
MP4 {
|
||||
audio_properties: Option<AudioProperties>,
|
||||
},
|
||||
OGG {
|
||||
audio_properties: Option<AudioProperties>,
|
||||
xiph_comments: Option<XiphComments>,
|
||||
},
|
||||
Opus {
|
||||
audio_properties: Option<AudioProperties>,
|
||||
xiph_comments: Option<XiphComments>,
|
||||
},
|
||||
WAV {
|
||||
audio_properties: Option<AudioProperties>,
|
||||
|
@ -100,7 +107,7 @@ impl FileRef {
|
|||
let flac_file = ffi::bindings::File_asFLAC(file_ptr);
|
||||
if !flac_file.is_null() {
|
||||
return Some(FileRef {
|
||||
file: File::FLAC { audio_properties }
|
||||
file: File::FLAC { audio_properties, xiph_comments: None }
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -134,15 +141,56 @@ impl FileRef {
|
|||
|
||||
let vorbis_file = ffi::bindings::File_asVorbis(file_ptr);
|
||||
if !vorbis_file.is_null() {
|
||||
let pinned_vorbis_file = Pin::new_unchecked(&*vorbis_file);
|
||||
let xiph_comments = pinned_vorbis_file.tag();
|
||||
let pinned_xiph_comments = Pin::new_unchecked(&*xiph_comments);
|
||||
let xiph_map = pinned_xiph_comments.fieldListMap();
|
||||
let pinned_xiph_map = Pin::new_unchecked(xiph_map);
|
||||
let xiph_comments = ffi::bindings::SimplePropertyMap_to_vector(pinned_xiph_map);
|
||||
|
||||
let mut xiph_safe_map = XiphComments::new();
|
||||
for property in xiph_comments.iter() {
|
||||
let pinned_property = Pin::new_unchecked(property);
|
||||
let tag_key = pinned_property.key();
|
||||
let pinned_key = Pin::new_unchecked(&*tag_key);
|
||||
let c_str = pinned_key.toCString(true);
|
||||
let key = CStr::from_ptr(c_str).to_string_lossy().to_string();
|
||||
|
||||
let tag_values = pinned_property.value();
|
||||
let pinned_values = Pin::new_unchecked(&*tag_values);
|
||||
let cxx_vec_values = ffi::bindings::StringList_to_vector(pinned_values);
|
||||
let values = cxx_vec_values.iter().map(|value| {
|
||||
let pinned_value = Pin::new_unchecked(value);
|
||||
let c_str = pinned_value.toCString(true);
|
||||
CStr::from_ptr(c_str).to_string_lossy().to_string()
|
||||
}).collect();
|
||||
|
||||
xiph_safe_map.insert(key, values);
|
||||
}
|
||||
|
||||
return Some(FileRef {
|
||||
file: File::OGG { audio_properties }
|
||||
file: File::OGG { audio_properties, xiph_comments: Some(xiph_safe_map) }
|
||||
});
|
||||
}
|
||||
|
||||
let opus_file = ffi::bindings::File_asOpus(file_ptr);
|
||||
if !opus_file.is_null() {
|
||||
let pinned_opus_file = Pin::new_unchecked(&*opus_file);
|
||||
let xiph_comments = pinned_opus_file.tag();
|
||||
let pinned_xiph_comments = Pin::new_unchecked(&*xiph_comments);
|
||||
let xiph_map = pinned_xiph_comments.fieldListMap();
|
||||
let pinned_xiph_map = Pin::new_unchecked(xiph_map);
|
||||
let xiph_comments = ffi::bindings::SimplePropertyMap_to_vector(pinned_xiph_map);
|
||||
|
||||
let mut xiph_safe_map = XiphComments::new();
|
||||
for property in xiph_comments.iter() {
|
||||
let pinned_property = Pin::new_unchecked(property);
|
||||
let tag_key = pinned_property.key();
|
||||
let pinned_key = Pin::new_unchecked(&*tag_key);
|
||||
}
|
||||
|
||||
return Some(FileRef {
|
||||
file: File::Opus { audio_properties }
|
||||
file: File::Opus { audio_properties, xiph_comments: Some(xiph_safe_map) }
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue