musikr: add format-specific file api
This commit is contained in:
parent
005898d776
commit
16fc14a4da
4 changed files with 188 additions and 32 deletions
|
@ -54,6 +54,27 @@ const TagLib::String& File_tag_title(const TagLib::File& file) {
|
|||
return empty_string;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
return str.toCString(true);
|
||||
|
|
|
@ -8,6 +8,14 @@
|
|||
#include <taglib/tstring.h>
|
||||
#include <taglib/audioproperties.h>
|
||||
#include <cstdint>
|
||||
#include <taglib/mpegfile.h>
|
||||
#include <taglib/flacfile.h>
|
||||
#include <taglib/mp4file.h>
|
||||
#include <taglib/oggfile.h>
|
||||
#include <taglib/opusfile.h>
|
||||
#include <taglib/wavfile.h>
|
||||
#include <taglib/wavpackfile.h>
|
||||
#include <taglib/apefile.h>
|
||||
|
||||
namespace taglib_shim {
|
||||
|
||||
|
@ -50,26 +58,45 @@ 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);
|
||||
|
||||
// File type checking functions
|
||||
bool File_isMPEG(const TagLib::File& file) {
|
||||
return dynamic_cast<const TagLib::MPEG::File*>(&file) != nullptr;
|
||||
}
|
||||
|
||||
bool File_isFLAC(const TagLib::File& file) {
|
||||
return dynamic_cast<const TagLib::FLAC::File*>(&file) != nullptr;
|
||||
}
|
||||
|
||||
bool File_isMP4(const TagLib::File& file) {
|
||||
return dynamic_cast<const TagLib::MP4::File*>(&file) != nullptr;
|
||||
}
|
||||
|
||||
bool File_isOgg(const TagLib::File& file) {
|
||||
return dynamic_cast<const TagLib::Ogg::File*>(&file) != nullptr;
|
||||
}
|
||||
|
||||
bool File_isOpus(const TagLib::File& file) {
|
||||
return dynamic_cast<const TagLib::Ogg::Opus::File*>(&file) != nullptr;
|
||||
}
|
||||
|
||||
bool File_isWAV(const TagLib::File& file) {
|
||||
return dynamic_cast<const TagLib::RIFF::WAV::File*>(&file) != nullptr;
|
||||
}
|
||||
|
||||
bool File_isWavPack(const TagLib::File& file) {
|
||||
return dynamic_cast<const TagLib::WavPack::File*>(&file) != nullptr;
|
||||
}
|
||||
|
||||
bool File_isAPE(const TagLib::File& file) {
|
||||
return dynamic_cast<const TagLib::APE::File*>(&file) != nullptr;
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
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);
|
||||
|
||||
// String utilities
|
||||
const char* to_string(const TagLib::String& str);
|
||||
|
|
|
@ -36,6 +36,24 @@ pub(crate) mod bindings {
|
|||
#[namespace = "taglib_shim"]
|
||||
fn File_tag_title(file: &File) -> &TagString;
|
||||
|
||||
// File type checking functions
|
||||
#[namespace = "taglib_shim"]
|
||||
fn File_isMPEG(file: &File) -> bool;
|
||||
#[namespace = "taglib_shim"]
|
||||
fn File_isFLAC(file: &File) -> bool;
|
||||
#[namespace = "taglib_shim"]
|
||||
fn File_isMP4(file: &File) -> bool;
|
||||
#[namespace = "taglib_shim"]
|
||||
fn File_isOgg(file: &File) -> bool;
|
||||
#[namespace = "taglib_shim"]
|
||||
fn File_isOpus(file: &File) -> bool;
|
||||
#[namespace = "taglib_shim"]
|
||||
fn File_isWAV(file: &File) -> bool;
|
||||
#[namespace = "taglib_shim"]
|
||||
fn File_isWavPack(file: &File) -> bool;
|
||||
#[namespace = "taglib_shim"]
|
||||
fn File_isAPE(file: &File) -> bool;
|
||||
|
||||
// Audio Properties methods
|
||||
#[namespace = "taglib_shim"]
|
||||
unsafe fn File_audioProperties(file: &File) -> *const AudioProperties;
|
||||
|
@ -55,3 +73,15 @@ pub(crate) mod bindings {
|
|||
fn isEmpty(s: &TagString) -> bool;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
// File type checking functions
|
||||
pub fn File_isMPEG(file: *const bindings::File) -> bool;
|
||||
pub fn File_isFLAC(file: *const bindings::File) -> bool;
|
||||
pub fn File_isMP4(file: *const bindings::File) -> bool;
|
||||
pub fn File_isOgg(file: *const bindings::File) -> bool;
|
||||
pub fn File_isOpus(file: *const bindings::File) -> bool;
|
||||
pub fn File_isWAV(file: *const bindings::File) -> bool;
|
||||
pub fn File_isWavPack(file: *const bindings::File) -> bool;
|
||||
pub fn File_isAPE(file: *const bindings::File) -> bool;
|
||||
}
|
||||
|
|
|
@ -13,22 +13,83 @@ pub struct AudioProperties {
|
|||
pub channels: i32,
|
||||
}
|
||||
|
||||
// Store extracted tag data instead of C++ reference
|
||||
#[derive(Default)]
|
||||
pub struct File {
|
||||
title: Option<String>,
|
||||
audio_properties: Option<AudioProperties>,
|
||||
pub enum File {
|
||||
Unknown {
|
||||
title: Option<String>,
|
||||
audio_properties: Option<AudioProperties>,
|
||||
},
|
||||
MP3 {
|
||||
title: Option<String>,
|
||||
audio_properties: Option<AudioProperties>,
|
||||
},
|
||||
FLAC {
|
||||
title: Option<String>,
|
||||
audio_properties: Option<AudioProperties>,
|
||||
},
|
||||
MP4 {
|
||||
title: Option<String>,
|
||||
audio_properties: Option<AudioProperties>,
|
||||
},
|
||||
OGG {
|
||||
title: Option<String>,
|
||||
audio_properties: Option<AudioProperties>,
|
||||
},
|
||||
Opus {
|
||||
title: Option<String>,
|
||||
audio_properties: Option<AudioProperties>,
|
||||
},
|
||||
WAV {
|
||||
title: Option<String>,
|
||||
audio_properties: Option<AudioProperties>,
|
||||
},
|
||||
WavPack {
|
||||
title: Option<String>,
|
||||
audio_properties: Option<AudioProperties>,
|
||||
},
|
||||
APE {
|
||||
title: Option<String>,
|
||||
audio_properties: Option<AudioProperties>,
|
||||
},
|
||||
}
|
||||
|
||||
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> {
|
||||
self.title.as_deref()
|
||||
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> {
|
||||
self.audio_properties.as_ref()
|
||||
match self {
|
||||
File::Unknown { audio_properties, .. } |
|
||||
File::MP3 { audio_properties, .. } |
|
||||
File::FLAC { audio_properties, .. } |
|
||||
File::MP4 { audio_properties, .. } |
|
||||
File::OGG { audio_properties, .. } |
|
||||
File::Opus { audio_properties, .. } |
|
||||
File::WAV { audio_properties, .. } |
|
||||
File::WavPack { audio_properties, .. } |
|
||||
File::APE { audio_properties, .. } => audio_properties.as_ref()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,15 +149,32 @@ impl FileRef {
|
|||
}
|
||||
};
|
||||
|
||||
// Determine file type and create appropriate variant
|
||||
let file = {
|
||||
if ffi::bindings::File_isMPEG(file_ptr) {
|
||||
File::MP3 { title, audio_properties }
|
||||
} else if ffi::bindings::File_isFLAC(file_ptr) {
|
||||
File::FLAC { title, audio_properties }
|
||||
} else if ffi::bindings::File_isMP4(file_ptr) {
|
||||
File::MP4 { title, audio_properties }
|
||||
} else if ffi::bindings::File_isOpus(file_ptr) {
|
||||
File::Opus { title, audio_properties }
|
||||
} else if ffi::bindings::File_isOgg(file_ptr) {
|
||||
File::OGG { title, audio_properties }
|
||||
} else if ffi::bindings::File_isWAV(file_ptr) {
|
||||
File::WAV { title, audio_properties }
|
||||
} else if ffi::bindings::File_isWavPack(file_ptr) {
|
||||
File::WavPack { title, audio_properties }
|
||||
} else if ffi::bindings::File_isAPE(file_ptr) {
|
||||
File::APE { title, audio_properties }
|
||||
} else {
|
||||
File::Unknown { title, audio_properties }
|
||||
}
|
||||
};
|
||||
|
||||
// Clean up C++ objects - they will be dropped when inner is dropped
|
||||
drop(inner);
|
||||
|
||||
// Create File with extracted data
|
||||
let file = File {
|
||||
title,
|
||||
audio_properties,
|
||||
};
|
||||
|
||||
Some(FileRef { file })
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue