core-media 0.7.1

Safe bindings to CoreMedia framework
Documentation
use core_foundation::{
    base::{kCFAllocatorDefault, CFAllocatorRef, TCFType},
    dictionary::{CFDictionary, CFDictionaryRef},
    number::CFNumber,
    string::{CFString, CFStringRef},
};
#[cfg(feature = "objc")]
use objc2::encode::{Encode, Encoding};

pub type CMTimeValue = i64;
pub type CMTimeScale = i32;
pub type CMTimeEpoch = i64;
pub type CMTimeFlags = u32;

pub const kCMTimeFlags_Valid: CMTimeFlags = 1 << 0;
pub const kCMTimeFlags_HasBeenRounded: CMTimeFlags = 1 << 1;
pub const kCMTimeFlags_PositiveInfinity: CMTimeFlags = 1 << 2;
pub const kCMTimeFlags_NegativeInfinity: CMTimeFlags = 1 << 3;
pub const kCMTimeFlags_Indefinite: CMTimeFlags = 1 << 4;
pub const kCMTimeFlags_ImpliedValueFlagsMask: CMTimeFlags = kCMTimeFlags_PositiveInfinity | kCMTimeFlags_NegativeInfinity | kCMTimeFlags_Indefinite;

#[repr(C, packed(4))]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct CMTime {
    pub value: CMTimeValue,
    pub timescale: CMTimeScale,
    pub flags: CMTimeFlags,
    pub epoch: CMTimeEpoch,
}

extern "C" {
    pub static kCMTimeInvalid: CMTime;
    pub static kCMTimeIndefinite: CMTime;
    pub static kCMTimePositiveInfinity: CMTime;
    pub static kCMTimeNegativeInfinity: CMTime;
    pub static kCMTimeZero: CMTime;

    pub fn CMTimeMake(value: CMTimeValue, timescale: CMTimeScale) -> CMTime;
    pub fn CMTimeMakeWithEpoch(value: CMTimeValue, timescale: CMTimeScale, epoch: CMTimeEpoch) -> CMTime;
    pub fn CMTimeMakeWithSeconds(seconds: f64, preferredTimeScale: i32) -> CMTime;
    pub fn CMTimeGetSeconds(time: CMTime) -> f64;
}

pub type CMTimeRoundingMethod = u32;

pub const kCMTimeRoundingMethod_RoundHalfAwayFromZero: CMTimeRoundingMethod = 1;
pub const kCMTimeRoundingMethod_RoundTowardZero: CMTimeRoundingMethod = 2;
pub const kCMTimeRoundingMethod_RoundAwayFromZero: CMTimeRoundingMethod = 3;
pub const kCMTimeRoundingMethod_QuickTime: CMTimeRoundingMethod = 4;
pub const kCMTimeRoundingMethod_RoundTowardPositiveInfinity: CMTimeRoundingMethod = 5;
pub const kCMTimeRoundingMethod_RoundTowardNegativeInfinity: CMTimeRoundingMethod = 6;
pub const kCMTimeRoundingMethod_Default: CMTimeRoundingMethod = kCMTimeRoundingMethod_RoundHalfAwayFromZero;

extern "C" {
    pub fn CMTimeConvertScale(time: CMTime, newTimescale: CMTimeScale, method: CMTimeRoundingMethod) -> CMTime;
    pub fn CMTimeAdd(lhs: CMTime, rhs: CMTime) -> CMTime;
    pub fn CMTimeSubtract(lhs: CMTime, rhs: CMTime) -> CMTime;
    pub fn CMTimeMultiply(time: CMTime, multiplier: i32) -> CMTime;
    pub fn CMTimeMultiplyByFloat64(time: CMTime, multiplier: f64) -> CMTime;
    pub fn CMTimeMultiplyByRatio(time: CMTime, multiplier: i32, divisor: i32) -> CMTime;
    pub fn CMTimeCompare(time1: CMTime, time2: CMTime) -> i32;
    pub fn CMTimeMinimum(time1: CMTime, time2: CMTime) -> CMTime;
    pub fn CMTimeMaximum(time1: CMTime, time2: CMTime) -> CMTime;
    pub fn CMTimeAbsoluteValue(time: CMTime) -> CMTime;
    pub fn CMTimeCopyAsDictionary(time: CMTime, allocator: CFAllocatorRef) -> CFDictionaryRef;
    pub fn CMTimeMakeFromDictionary(dictionaryRepresentation: CFDictionaryRef) -> CMTime;

    pub static kCMTimeValueKey: CFStringRef;
    pub static kCMTimeScaleKey: CFStringRef;
    pub static kCMTimeEpochKey: CFStringRef;
    pub static kCMTimeFlagsKey: CFStringRef;

    pub fn CMTimeCopyDescription(allocator: CFAllocatorRef, time: CMTime) -> CFStringRef;
    pub fn CMTimeShow(time: CMTime);
}

#[cfg(feature = "objc")]
unsafe impl Encode for CMTime {
    const ENCODING: Encoding = Encoding::Struct("?", &[CMTimeValue::ENCODING, CMTimeScale::ENCODING, CMTimeFlags::ENCODING, CMTimeEpoch::ENCODING]);
}

impl CMTime {
    #[inline]
    pub fn make(value: CMTimeValue, timescale: CMTimeScale) -> Self {
        unsafe { CMTimeMake(value, timescale) }
    }

    #[inline]
    pub fn make_with_epoch(value: CMTimeValue, timescale: CMTimeScale, epoch: CMTimeEpoch) -> Self {
        unsafe { CMTimeMakeWithEpoch(value, timescale, epoch) }
    }

    #[inline]
    pub fn make_with_seconds(seconds: f64, preferred_time_scale: i32) -> Self {
        unsafe { CMTimeMakeWithSeconds(seconds, preferred_time_scale) }
    }

    #[inline]
    pub fn get_seconds(&self) -> f64 {
        unsafe { CMTimeGetSeconds(*self) }
    }

    #[inline]
    pub fn convert_scale(&self, new_timescale: CMTimeScale, method: CMTimeRoundingMethod) -> Self {
        unsafe { CMTimeConvertScale(*self, new_timescale, method) }
    }

    #[inline]
    pub fn add(&self, time: CMTime) -> Self {
        unsafe { CMTimeAdd(*self, time) }
    }

    #[inline]
    pub fn subtract(&self, time: CMTime) -> Self {
        unsafe { CMTimeSubtract(*self, time) }
    }

    #[inline]
    pub fn multiply(&self, multiplier: i32) -> Self {
        unsafe { CMTimeMultiply(*self, multiplier) }
    }

    #[inline]
    pub fn multiply_by_float64(&self, multiplier: f64) -> Self {
        unsafe { CMTimeMultiplyByFloat64(*self, multiplier) }
    }

    #[inline]
    pub fn multiply_by_ratio(&self, multiplier: i32, divisor: i32) -> Self {
        unsafe { CMTimeMultiplyByRatio(*self, multiplier, divisor) }
    }

    #[inline]
    pub fn compare(&self, time: CMTime) -> i32 {
        unsafe { CMTimeCompare(*self, time) }
    }

    #[inline]
    pub fn minimum(&self, time: CMTime) -> Self {
        unsafe { CMTimeMinimum(*self, time) }
    }

    #[inline]
    pub fn maximum(&self, time: CMTime) -> Self {
        unsafe { CMTimeMaximum(*self, time) }
    }

    #[inline]
    pub fn absolute_value(&self) -> Self {
        unsafe { CMTimeAbsoluteValue(*self) }
    }

    #[inline]
    pub fn copy_as_dictionary(&self) -> Option<CFDictionary<CFString, CFNumber>> {
        unsafe {
            let dict = CMTimeCopyAsDictionary(*self, kCFAllocatorDefault);
            if dict.is_null() {
                None
            } else {
                Some(TCFType::wrap_under_create_rule(dict))
            }
        }
    }

    #[inline]
    pub fn make_from_dictionary(dictionary_representation: &CFDictionary<CFString, CFNumber>) -> Self {
        unsafe { CMTimeMakeFromDictionary(dictionary_representation.as_concrete_TypeRef()) }
    }

    #[inline]
    pub fn copy_description(&self) -> Option<CFString> {
        unsafe {
            let description = CMTimeCopyDescription(kCFAllocatorDefault, *self);
            if description.is_null() {
                None
            } else {
                Some(TCFType::wrap_under_create_rule(description))
            }
        }
    }

    #[inline]
    pub fn show(&self) {
        unsafe { CMTimeShow(*self) }
    }
}