musikr: add audioproperties to metajni interface

This commit is contained in:
Alexander Capehart 2025-02-08 15:08:38 -07:00
parent 2ee9556564
commit 005898d776
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
3 changed files with 70 additions and 1 deletions

View file

@ -6,6 +6,7 @@
#include <taglib/fileref.h> #include <taglib/fileref.h>
#include <taglib/tag.h> #include <taglib/tag.h>
#include <taglib/tstring.h> #include <taglib/tstring.h>
#include <taglib/audioproperties.h>
#include <cstdint> #include <cstdint>
namespace taglib_shim { namespace taglib_shim {
@ -49,6 +50,27 @@ const TagLib::File& FileRef_file(const TagLib::FileRef& ref);
bool File_tag(const TagLib::File& file); bool File_tag(const TagLib::File& file);
const TagLib::String& File_tag_title(const TagLib::File& file); const TagLib::String& File_tag_title(const TagLib::File& file);
// Audio Properties methods
const TagLib::AudioProperties* File_audioProperties(const TagLib::File& file) {
return file.audioProperties();
}
int AudioProperties_length(const TagLib::AudioProperties* properties) {
return properties->length();
}
int AudioProperties_bitrate(const TagLib::AudioProperties* properties) {
return properties->bitrate();
}
int AudioProperties_sampleRate(const TagLib::AudioProperties* properties) {
return properties->sampleRate();
}
int AudioProperties_channels(const TagLib::AudioProperties* properties) {
return properties->channels();
}
// String utilities // String utilities
const char* to_string(const TagLib::String& str); const char* to_string(const TagLib::String& str);
bool isEmpty(const TagLib::String& str); bool isEmpty(const TagLib::String& str);

View file

@ -12,6 +12,8 @@ pub(crate) mod bindings {
#[namespace = "TagLib"] #[namespace = "TagLib"]
#[cxx_name = "String"] #[cxx_name = "String"]
type TagString; type TagString;
#[namespace = "TagLib"]
type AudioProperties;
#[namespace = "taglib_shim"] #[namespace = "taglib_shim"]
type RustIOStream; type RustIOStream;
@ -34,6 +36,18 @@ pub(crate) mod bindings {
#[namespace = "taglib_shim"] #[namespace = "taglib_shim"]
fn File_tag_title(file: &File) -> &TagString; fn File_tag_title(file: &File) -> &TagString;
// Audio Properties methods
#[namespace = "taglib_shim"]
unsafe fn File_audioProperties(file: &File) -> *const AudioProperties;
#[namespace = "taglib_shim"]
unsafe fn AudioProperties_length(properties: *const AudioProperties) -> i32;
#[namespace = "taglib_shim"]
unsafe fn AudioProperties_bitrate(properties: *const AudioProperties) -> i32;
#[namespace = "taglib_shim"]
unsafe fn AudioProperties_sampleRate(properties: *const AudioProperties) -> i32;
#[namespace = "taglib_shim"]
unsafe fn AudioProperties_channels(properties: *const AudioProperties) -> i32;
// String conversion utilities // String conversion utilities
#[namespace = "taglib_shim"] #[namespace = "taglib_shim"]
unsafe fn to_string(s: &TagString) -> *const c_char; unsafe fn to_string(s: &TagString) -> *const c_char;

View file

@ -4,10 +4,20 @@ mod stream;
pub use stream::{RustStream, TagLibStream}; pub use stream::{RustStream, TagLibStream};
use ffi::bindings; use ffi::bindings;
/// Audio properties of a media file
#[derive(Default)]
pub struct AudioProperties {
pub length: i32,
pub bitrate: i32,
pub sample_rate: i32,
pub channels: i32,
}
// Store extracted tag data instead of C++ reference // Store extracted tag data instead of C++ reference
#[derive(Default)] #[derive(Default)]
pub struct File { pub struct File {
title: Option<String>, title: Option<String>,
audio_properties: Option<AudioProperties>,
} }
impl File { impl File {
@ -15,6 +25,11 @@ impl File {
pub fn title(&self) -> Option<&str> { pub fn title(&self) -> Option<&str> {
self.title.as_deref() self.title.as_deref()
} }
/// Get the audio properties of the file, if available
pub fn audio_properties(&self) -> Option<&AudioProperties> {
self.audio_properties.as_ref()
}
} }
// Safe wrapper for FileRef that owns extracted data // Safe wrapper for FileRef that owns extracted data
@ -58,11 +73,29 @@ impl FileRef {
} }
}; };
// Extract audio properties
let audio_properties = unsafe {
let props_ptr = ffi::bindings::File_audioProperties(file_ptr);
if !props_ptr.is_null() {
Some(AudioProperties {
length: ffi::bindings::AudioProperties_length(props_ptr),
bitrate: ffi::bindings::AudioProperties_bitrate(props_ptr),
sample_rate: ffi::bindings::AudioProperties_sampleRate(props_ptr),
channels: ffi::bindings::AudioProperties_channels(props_ptr),
})
} else {
None
}
};
// Clean up C++ objects - they will be dropped when inner is dropped // Clean up C++ objects - they will be dropped when inner is dropped
drop(inner); drop(inner);
// Create File with extracted data // Create File with extracted data
let file = File { title }; let file = File {
title,
audio_properties,
};
Some(FileRef { file }) Some(FileRef { file })
} }