diff --git a/musikr/src/main/jni/build.rs b/musikr/src/main/jni/build.rs index a16fc91e4..de1055e88 100644 --- a/musikr/src/main/jni/build.rs +++ b/musikr/src/main/jni/build.rs @@ -110,8 +110,6 @@ fn main() { cxx_build::bridge("src/taglib/ffi.rs") .file("shim/iostream_shim.cpp") .file("shim/file_shim.cpp") - .file("shim/string_shim.cpp") - .file("shim/audioproperties_shim.cpp") .include(format!("taglib/pkg/{}/include", arch)) .include("shim") .include(".") // Add the current directory to include path @@ -124,9 +122,5 @@ 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/string_shim.hpp"); - println!("cargo:rerun-if-changed=shim/string_shim.cpp"); - println!("cargo:rerun-if-changed=shim/audioproperties_shim.hpp"); - println!("cargo:rerun-if-changed=shim/audioproperties_shim.cpp"); println!("cargo:rerun-if-changed=src/taglib/ffi.rs"); } diff --git a/musikr/src/main/jni/shim/audioproperties_shim.cpp b/musikr/src/main/jni/shim/audioproperties_shim.cpp deleted file mode 100644 index 77642f0e0..000000000 --- a/musikr/src/main/jni/shim/audioproperties_shim.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "audioproperties_shim.hpp" -#include - -namespace taglib_shim { - -const TagLib::AudioProperties* File_audioProperties(const TagLib::File& file) { - return file.audioProperties(); -} - -int AudioProperties_lengthInMilliseconds(const TagLib::AudioProperties* properties) { - return properties->lengthInMilliseconds(); -} - -int AudioProperties_bitrateInKilobitsPerSecond(const TagLib::AudioProperties* properties) { - return properties->bitrate(); -} - -int AudioProperties_sampleRateInHz(const TagLib::AudioProperties* properties) { - return properties->sampleRate(); -} - -int AudioProperties_numberOfChannels(const TagLib::AudioProperties* properties) { - return properties->channels(); -} - -} // namespace taglib_shim \ No newline at end of file diff --git a/musikr/src/main/jni/shim/audioproperties_shim.hpp b/musikr/src/main/jni/shim/audioproperties_shim.hpp deleted file mode 100644 index ee0c38970..000000000 --- a/musikr/src/main/jni/shim/audioproperties_shim.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include -#include - -namespace taglib_shim { - -// Audio Properties methods -const TagLib::AudioProperties* File_audioProperties(const TagLib::File& file); -int AudioProperties_lengthInMilliseconds(const TagLib::AudioProperties* properties); -int AudioProperties_bitrateInKilobitsPerSecond(const TagLib::AudioProperties* properties); -int AudioProperties_sampleRateInHz(const TagLib::AudioProperties* properties); -int AudioProperties_numberOfChannels(const TagLib::AudioProperties* properties); - -} // namespace taglib_shim \ No newline at end of file diff --git a/musikr/src/main/jni/shim/file_shim.cpp b/musikr/src/main/jni/shim/file_shim.cpp index 9237dbcf9..617e14c63 100644 --- a/musikr/src/main/jni/shim/file_shim.cpp +++ b/musikr/src/main/jni/shim/file_shim.cpp @@ -2,65 +2,37 @@ namespace taglib_shim { -// FileRef helper functions -bool FileRef_isNull(const TagLib::FileRef& ref) { - return ref.isNull(); -} - -const TagLib::File& FileRef_file(const TagLib::FileRef& ref) { - return *ref.file(); -} - -// File tag methods -bool File_tag(const TagLib::File& file) { - return file.tag() != nullptr; -} - -namespace { - // Keep the empty string as a static member to ensure it lives long enough - const TagLib::String empty_string; -} - -const TagLib::String& File_tag_title(const TagLib::File& file) { - if (auto* tag = file.tag()) { - static TagLib::String title; - title = tag->title(); - return title; - } - return empty_string; -} - // File type checking functions -bool File_isMPEG(const TagLib::File& file) { - return dynamic_cast(&file) != nullptr; +bool File_isMPEG(TagLib::File* file) { + return dynamic_cast(file) != nullptr; } -bool File_isFLAC(const TagLib::File& file) { - return dynamic_cast(&file) != nullptr; +bool File_isFLAC(TagLib::File* file) { + return dynamic_cast(file) != nullptr; } -bool File_isMP4(const TagLib::File& file) { - return dynamic_cast(&file) != nullptr; +bool File_isMP4(TagLib::File* file) { + return dynamic_cast(file) != nullptr; } -bool File_isOgg(const TagLib::File& file) { - return dynamic_cast(&file) != nullptr; +bool File_isOgg(TagLib::File* file) { + return dynamic_cast(file) != nullptr; } -bool File_isOpus(const TagLib::File& file) { - return dynamic_cast(&file) != nullptr; +bool File_isOpus(TagLib::File* file) { + return dynamic_cast(file) != nullptr; } -bool File_isWAV(const TagLib::File& file) { - return dynamic_cast(&file) != nullptr; +bool File_isWAV(TagLib::File* file) { + return dynamic_cast(file) != nullptr; } -bool File_isWavPack(const TagLib::File& file) { - return dynamic_cast(&file) != nullptr; +bool File_isWavPack(TagLib::File* file) { + return dynamic_cast(file) != nullptr; } -bool File_isAPE(const TagLib::File& file) { - return dynamic_cast(&file) != nullptr; +bool File_isAPE(TagLib::File* file) { + return dynamic_cast(file) != nullptr; } } // namespace taglib_shim \ No newline at end of file diff --git a/musikr/src/main/jni/shim/file_shim.hpp b/musikr/src/main/jni/shim/file_shim.hpp index 20b85dfe3..463a72da0 100644 --- a/musikr/src/main/jni/shim/file_shim.hpp +++ b/musikr/src/main/jni/shim/file_shim.hpp @@ -15,29 +15,15 @@ namespace taglib_shim { -// FileRef helper functions -bool FileRef_isNull(const TagLib::FileRef& ref); -const TagLib::File& FileRef_file(const TagLib::FileRef& ref); - -// File tag methods -bool File_tag(const TagLib::File& file); -const TagLib::String& File_tag_title(const TagLib::File& file); - // File type checking functions -bool File_isMPEG(const TagLib::File& file); -bool File_isFLAC(const TagLib::File& file); -bool File_isMP4(const TagLib::File& file); -bool File_isOgg(const TagLib::File& file); -bool File_isOpus(const TagLib::File& file); -bool File_isWAV(const TagLib::File& file); -bool File_isWavPack(const TagLib::File& file); -bool File_isAPE(const TagLib::File& file); +bool File_isMPEG(TagLib::File* file); +bool File_isFLAC(TagLib::File* file); +bool File_isMP4(TagLib::File* file); +bool File_isOgg(TagLib::File* file); +bool File_isOpus(TagLib::File* file); +bool File_isWAV(TagLib::File* file); +bool File_isWavPack(TagLib::File* file); +bool File_isAPE(TagLib::File* file); -// Audio Properties methods -const TagLib::AudioProperties* File_audioProperties(const TagLib::File& file); -int AudioProperties_length(const TagLib::AudioProperties* properties); -int AudioProperties_bitrate(const TagLib::AudioProperties* properties); -int AudioProperties_sampleRate(const TagLib::AudioProperties* properties); -int AudioProperties_channels(const TagLib::AudioProperties* properties); } // namespace taglib_shim \ No newline at end of file diff --git a/musikr/src/main/jni/shim/string_shim.cpp b/musikr/src/main/jni/shim/string_shim.cpp deleted file mode 100644 index 53a1a6dc0..000000000 --- a/musikr/src/main/jni/shim/string_shim.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "string_shim.hpp" - -namespace taglib_shim { - -const char* to_string(const TagLib::String& str) { - return str.toCString(true); -} - -bool isEmpty(const TagLib::String& str) { - return str.isEmpty(); -} - -} // namespace taglib_shim \ No newline at end of file diff --git a/musikr/src/main/jni/shim/string_shim.hpp b/musikr/src/main/jni/shim/string_shim.hpp deleted file mode 100644 index 0d5d725af..000000000 --- a/musikr/src/main/jni/shim/string_shim.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - -namespace taglib_shim { - -// String utilities -const char* to_string(const TagLib::String& str); -bool isEmpty(const TagLib::String& str); - -} // namespace taglib_shim \ No newline at end of file diff --git a/musikr/src/main/jni/src/taglib/ffi.rs b/musikr/src/main/jni/src/taglib/ffi.rs index 277178895..956171880 100644 --- a/musikr/src/main/jni/src/taglib/ffi.rs +++ b/musikr/src/main/jni/src/taglib/ffi.rs @@ -5,8 +5,6 @@ pub(crate) mod bindings { include!("taglib/tstring.h"); include!("shim/iostream_shim.hpp"); include!("shim/file_shim.hpp"); - include!("shim/string_shim.hpp"); - include!("shim/audioproperties_shim.hpp"); #[namespace = "TagLib"] type FileRef; @@ -30,49 +28,39 @@ pub(crate) mod bindings { fn new_FileRef_from_stream(stream: UniquePtr) -> UniquePtr; // FileRef helper functions - #[namespace = "taglib_shim"] - fn FileRef_isNull(ref_: &FileRef) -> bool; - #[namespace = "taglib_shim"] - fn FileRef_file(ref_: &FileRef) -> &File; + fn isNull(self: Pin<&FileRef>) -> bool; + fn file(self: Pin<&FileRef>) -> *mut File; - // File tag methods - #[namespace = "taglib_shim"] - fn File_tag_title(file: &File) -> &TagString; + fn audioProperties(self: Pin<&File>) -> *mut AudioProperties; // File type checking functions #[namespace = "taglib_shim"] - fn File_isMPEG(file: &File) -> bool; + unsafe fn File_isMPEG(file: *mut File) -> bool; #[namespace = "taglib_shim"] - fn File_isFLAC(file: &File) -> bool; + unsafe fn File_isFLAC(file: *mut File) -> bool; #[namespace = "taglib_shim"] - fn File_isMP4(file: &File) -> bool; + unsafe fn File_isMP4(file: *mut File) -> bool; #[namespace = "taglib_shim"] - fn File_isOgg(file: &File) -> bool; + unsafe fn File_isOgg(file: *mut File) -> bool; #[namespace = "taglib_shim"] - fn File_isOpus(file: &File) -> bool; + unsafe fn File_isOpus(file: *mut File) -> bool; #[namespace = "taglib_shim"] - fn File_isWAV(file: &File) -> bool; + unsafe fn File_isWAV(file: *mut File) -> bool; #[namespace = "taglib_shim"] - fn File_isWavPack(file: &File) -> bool; + unsafe fn File_isWavPack(file: *mut File) -> bool; #[namespace = "taglib_shim"] - fn File_isAPE(file: &File) -> bool; + unsafe fn File_isAPE(file: *mut File) -> bool; - // Audio Properties methods - #[namespace = "taglib_shim"] - unsafe fn File_audioProperties(file: &File) -> *const AudioProperties; - #[namespace = "taglib_shim"] - unsafe fn AudioProperties_lengthInMilliseconds(properties: *const AudioProperties) -> i32; - #[namespace = "taglib_shim"] - unsafe fn AudioProperties_bitrateInKilobitsPerSecond(properties: *const AudioProperties) -> i32; - #[namespace = "taglib_shim"] - unsafe fn AudioProperties_sampleRateInHz(properties: *const AudioProperties) -> i32; - #[namespace = "taglib_shim"] - unsafe fn AudioProperties_numberOfChannels(properties: *const AudioProperties) -> i32; + // AudioProperties methods + fn lengthInMilliseconds(self: Pin<&AudioProperties>) -> i32; + fn bitrate(self: Pin<&AudioProperties>) -> i32; + fn sampleRate(self: Pin<&AudioProperties>) -> i32; + fn channels(self: Pin<&AudioProperties>) -> i32; // String conversion utilities #[namespace = "taglib_shim"] - unsafe fn to_string(s: &TagString) -> *const c_char; + unsafe fn toCString(self: Pin<&TagString>, unicode: bool) -> *const c_char; #[namespace = "taglib_shim"] - fn isEmpty(s: &TagString) -> bool; + fn isEmpty(self: Pin<&TagString>) -> bool; } } diff --git a/musikr/src/main/jni/src/taglib/mod.rs b/musikr/src/main/jni/src/taglib/mod.rs index a2432b598..ecab3413f 100644 --- a/musikr/src/main/jni/src/taglib/mod.rs +++ b/musikr/src/main/jni/src/taglib/mod.rs @@ -1,6 +1,9 @@ mod ffi; mod stream; +use std::pin::{pin, Pin}; + +use cxx::UniquePtr; pub use stream::{RustStream, TagLibStream}; use ffi::bindings; @@ -15,39 +18,30 @@ pub struct AudioProperties { pub enum File { Unknown { - title: Option, audio_properties: Option, }, MP3 { - title: Option, audio_properties: Option, }, FLAC { - title: Option, audio_properties: Option, }, MP4 { - title: Option, audio_properties: Option, }, OGG { - title: Option, audio_properties: Option, }, Opus { - title: Option, audio_properties: Option, }, WAV { - title: Option, audio_properties: Option, }, WavPack { - title: Option, audio_properties: Option, }, APE { - title: Option, audio_properties: Option, }, } @@ -55,28 +49,12 @@ pub enum File { impl Default for File { fn default() -> Self { File::Unknown { - title: None, audio_properties: None, } } } impl File { - /// Get the title of the file, if available - pub fn title(&self) -> Option<&str> { - match self { - File::Unknown { title, .. } | - File::MP3 { title, .. } | - File::FLAC { title, .. } | - File::MP4 { title, .. } | - File::OGG { title, .. } | - File::Opus { title, .. } | - File::WAV { title, .. } | - File::WavPack { title, .. } | - File::APE { title, .. } => title.as_deref() - } - } - /// Get the audio properties of the file, if available pub fn audio_properties(&self) -> Option<&AudioProperties> { match self { @@ -111,38 +89,26 @@ impl FileRef { let iostream = unsafe { ffi::bindings::new_rust_iostream(raw_stream) }; // Create FileRef from iostream - let inner = ffi::bindings::new_FileRef_from_stream(iostream); - if ffi::bindings::FileRef_isNull(&inner) { + let file_ref = ffi::bindings::new_FileRef_from_stream(iostream); + if file_ref.is_null() { return None; } // Extract data from C++ objects - let file_ref = &inner; - let file_ptr = ffi::bindings::FileRef_file(&file_ref); - - // Extract title - let title = { - let title = ffi::bindings::File_tag_title(file_ptr); - if ffi::bindings::isEmpty(title) { - None - } else { - let cstr = unsafe { ffi::bindings::to_string(title) }; - unsafe { std::ffi::CStr::from_ptr(cstr) } - .to_str() - .ok() - .map(|s| s.to_owned()) - } - }; + let pinned_file_ref = unsafe { Pin::new_unchecked(file_ref.as_ref().unwrap()) }; + let file_ptr = pinned_file_ref.file(); // Extract audio properties - let audio_properties = unsafe { - let props_ptr = ffi::bindings::File_audioProperties(file_ptr); + let audio_properties = { + let pinned_file = unsafe { Pin::new_unchecked(&*file_ptr) }; + let props_ptr = pinned_file.audioProperties(); if !props_ptr.is_null() { + let props = unsafe { Pin::new_unchecked(&*props_ptr) }; Some(AudioProperties { - length_in_milliseconds: ffi::bindings::AudioProperties_lengthInMilliseconds(props_ptr), - bitrate_in_kilobits_per_second: ffi::bindings::AudioProperties_bitrateInKilobitsPerSecond(props_ptr), - sample_rate_in_hz: ffi::bindings::AudioProperties_sampleRateInHz(props_ptr), - number_of_channels: ffi::bindings::AudioProperties_numberOfChannels(props_ptr), + length_in_milliseconds: props.lengthInMilliseconds(), + bitrate_in_kilobits_per_second: props.bitrate(), + sample_rate_in_hz: props.sampleRate(), + number_of_channels: props.channels(), }) } else { None @@ -150,30 +116,30 @@ impl FileRef { }; // Determine file type and create appropriate variant - let file = { + let file = unsafe { if ffi::bindings::File_isMPEG(file_ptr) { - File::MP3 { title, audio_properties } + File::MP3 { audio_properties } } else if ffi::bindings::File_isFLAC(file_ptr) { - File::FLAC { title, audio_properties } + File::FLAC { audio_properties } } else if ffi::bindings::File_isMP4(file_ptr) { - File::MP4 { title, audio_properties } + File::MP4 { audio_properties } } else if ffi::bindings::File_isOpus(file_ptr) { - File::Opus { title, audio_properties } + File::Opus { audio_properties } } else if ffi::bindings::File_isOgg(file_ptr) { - File::OGG { title, audio_properties } + File::OGG { audio_properties } } else if ffi::bindings::File_isWAV(file_ptr) { - File::WAV { title, audio_properties } + File::WAV { audio_properties } } else if ffi::bindings::File_isWavPack(file_ptr) { - File::WavPack { title, audio_properties } + File::WavPack { audio_properties } } else if ffi::bindings::File_isAPE(file_ptr) { - File::APE { title, audio_properties } + File::APE { audio_properties } } else { - File::Unknown { title, audio_properties } + File::Unknown { audio_properties } } }; - // Clean up C++ objects - they will be dropped when inner is dropped - drop(inner); + // Clean up C++ objects - they will be dropped when file_ref is dropped + drop(file_ref); Some(FileRef { file }) }