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;
|
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
|
// String utilities
|
||||||
const char* to_string(const TagLib::String& str) {
|
const char* to_string(const TagLib::String& str) {
|
||||||
return str.toCString(true);
|
return str.toCString(true);
|
||||||
|
|
|
@ -8,6 +8,14 @@
|
||||||
#include <taglib/tstring.h>
|
#include <taglib/tstring.h>
|
||||||
#include <taglib/audioproperties.h>
|
#include <taglib/audioproperties.h>
|
||||||
#include <cstdint>
|
#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 {
|
namespace taglib_shim {
|
||||||
|
|
||||||
|
@ -50,26 +58,45 @@ 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);
|
||||||
|
|
||||||
|
// 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
|
// Audio Properties methods
|
||||||
const TagLib::AudioProperties* File_audioProperties(const TagLib::File& file) {
|
const TagLib::AudioProperties* File_audioProperties(const TagLib::File& file);
|
||||||
return file.audioProperties();
|
int AudioProperties_length(const TagLib::AudioProperties* properties);
|
||||||
}
|
int AudioProperties_bitrate(const TagLib::AudioProperties* properties);
|
||||||
|
int AudioProperties_sampleRate(const TagLib::AudioProperties* properties);
|
||||||
int AudioProperties_length(const TagLib::AudioProperties* properties) {
|
int AudioProperties_channels(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);
|
||||||
|
|
|
@ -36,6 +36,24 @@ pub(crate) mod bindings {
|
||||||
#[namespace = "taglib_shim"]
|
#[namespace = "taglib_shim"]
|
||||||
fn File_tag_title(file: &File) -> &TagString;
|
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
|
// Audio Properties methods
|
||||||
#[namespace = "taglib_shim"]
|
#[namespace = "taglib_shim"]
|
||||||
unsafe fn File_audioProperties(file: &File) -> *const AudioProperties;
|
unsafe fn File_audioProperties(file: &File) -> *const AudioProperties;
|
||||||
|
@ -55,3 +73,15 @@ pub(crate) mod bindings {
|
||||||
fn isEmpty(s: &TagString) -> bool;
|
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,
|
pub channels: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store extracted tag data instead of C++ reference
|
pub enum File {
|
||||||
#[derive(Default)]
|
Unknown {
|
||||||
pub struct File {
|
title: Option<String>,
|
||||||
title: Option<String>,
|
audio_properties: Option<AudioProperties>,
|
||||||
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 {
|
impl File {
|
||||||
/// Get the title of the file, if available
|
/// Get the title of the file, if available
|
||||||
pub fn title(&self) -> Option<&str> {
|
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
|
/// Get the audio properties of the file, if available
|
||||||
pub fn audio_properties(&self) -> Option<&AudioProperties> {
|
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
|
// Clean up C++ objects - they will be dropped when inner is dropped
|
||||||
drop(inner);
|
drop(inner);
|
||||||
|
|
||||||
// Create File with extracted data
|
|
||||||
let file = File {
|
|
||||||
title,
|
|
||||||
audio_properties,
|
|
||||||
};
|
|
||||||
|
|
||||||
Some(FileRef { file })
|
Some(FileRef { file })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue