diff --git a/musikr/src/main/jni/shim/iostream_shim.hpp b/musikr/src/main/jni/shim/iostream_shim.hpp index 2826057a2..dc931f5da 100644 --- a/musikr/src/main/jni/shim/iostream_shim.hpp +++ b/musikr/src/main/jni/shim/iostream_shim.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include namespace taglib_shim { @@ -49,6 +50,27 @@ const TagLib::File& FileRef_file(const TagLib::FileRef& ref); bool File_tag(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 const char* to_string(const TagLib::String& str); bool isEmpty(const TagLib::String& str); diff --git a/musikr/src/main/jni/src/taglib/ffi.rs b/musikr/src/main/jni/src/taglib/ffi.rs index fb64e2ae2..e435ba1f2 100644 --- a/musikr/src/main/jni/src/taglib/ffi.rs +++ b/musikr/src/main/jni/src/taglib/ffi.rs @@ -12,6 +12,8 @@ pub(crate) mod bindings { #[namespace = "TagLib"] #[cxx_name = "String"] type TagString; + #[namespace = "TagLib"] + type AudioProperties; #[namespace = "taglib_shim"] type RustIOStream; @@ -34,6 +36,18 @@ pub(crate) mod bindings { #[namespace = "taglib_shim"] 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 #[namespace = "taglib_shim"] unsafe fn to_string(s: &TagString) -> *const c_char; diff --git a/musikr/src/main/jni/src/taglib/mod.rs b/musikr/src/main/jni/src/taglib/mod.rs index 8001deb94..28aa1cd0c 100644 --- a/musikr/src/main/jni/src/taglib/mod.rs +++ b/musikr/src/main/jni/src/taglib/mod.rs @@ -4,10 +4,20 @@ mod stream; pub use stream::{RustStream, TagLibStream}; 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 #[derive(Default)] pub struct File { title: Option, + audio_properties: Option, } impl File { @@ -15,6 +25,11 @@ impl File { pub fn title(&self) -> Option<&str> { 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 @@ -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 drop(inner); // Create File with extracted data - let file = File { title }; + let file = File { + title, + audio_properties, + }; Some(FileRef { file }) }