1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
extern crate alass_util;

use crate::util::*;
use crate::result_codes::*;
use crate::catch_panic;

use std::ptr;
use std::os::raw::c_char;

use alass_util::*;
use alass_util::TimeSpansSaveError::*;

use subparse::timetypes::TimeSpan as SubTimeSpan;
use subparse::timetypes::TimePoint as SubTimePoint;

use log::error;

static DEFAULT_SPANS_CAPACITY: usize = 2000;

///
/// Creates a new `TimeSpans` buffer ready to accept data (see `alass_timespans_push()`).
/// 
#[catch_panic(ptr::null_mut())]
#[no_mangle]
pub extern "C" fn alass_timespans_new() -> *mut TimeSpans {
    to_ptr(TimeSpans(Vec::with_capacity(DEFAULT_SPANS_CAPACITY)))
}

///
/// Appends timespan to `TimeSpans` buffer. Start and end times are in milliseconds.
/// 
#[catch_panic(ALASS_INTERNAL_ERROR)]
#[no_mangle]
pub extern "C" fn alass_timespans_push(spans: *mut TimeSpans, start_time: i64, end_time: i64) -> ResultCode {
    if spans.is_null() {
        error!("Invalid parameter: spans is null");
        return ALASS_INVALID_PARAMS;
    }

    if start_time > end_time {
        error!("Invalid parameter: invalid timespan");
        return ALASS_INVALID_PARAMS;
    }

    let spans = from_ptr(spans);
    let start = SubTimePoint::from_msecs(start_time);
    let end = SubTimePoint::from_msecs(end_time);
    spans.push(SubTimeSpan::new(start, end));

    ALASS_SUCCESS
}

///
/// Computes timespans given detected voice-activity.
/// 
#[catch_panic(ptr::null_mut())]
#[no_mangle]
pub extern "C" fn alass_timespans_compute(activity: *mut VoiceActivity) -> *mut TimeSpans {
    if activity.is_null() {
        error!("Invalid parameter: voice activity pointer is null");
        return ptr::null_mut()
    }

    let activity = &*from_ptr(activity);
    let spans = TimeSpans::from(activity);
    to_ptr(spans)
}

///
/// Saves timespans to disk with the given `filename` (see `alass_timespans_load_raw()`).
/// 
#[catch_panic(ALASS_INTERNAL_ERROR)]
#[no_mangle]
pub extern "C" fn alass_timespans_save_raw(spans: *mut TimeSpans, filename: *const c_char) -> ResultCode {
    if spans.is_null() {
        error!("Invalid parameter: spans is null");
        return ALASS_INVALID_PARAMS;
    }

    let filename_str = from_cstring(filename);
    if filename_str.is_none() {
        error!("Invalid parameter: filename is invalid");
        return ALASS_INVALID_PARAMS;
    }

    let filename_str = filename_str.unwrap();
    let spans = from_ptr(spans);
    match spans.save(&filename_str) {
        Ok(()) => ALASS_SUCCESS,
        Err(e) => {
            error!("{}", e);
            match e {
                SerializeError { .. } => ALASS_SERIALIZE_ERROR,
                WriteError { .. } => ALASS_WRITE_ERROR
            }
        }
    }
}

///
/// Loads cached timespans from disk (see `alass_timespans_save_raw()`). Returns
/// null if no file exists at the given path.
/// 
#[catch_panic(ptr::null_mut())]
#[no_mangle]
pub extern "C" fn alass_timespans_load_raw(filename: *const c_char) -> *mut TimeSpans {
    let filename_str = from_cstring(filename);
    if filename_str.is_none() {
        error!("Invalid parameter: filename is invalid");
        return ptr::null_mut();
    }

    match TimeSpans::load(&filename_str.unwrap()) {
        Ok(spans) => to_ptr(spans),
        Err(e) => {
            error!("{}", e);
            ptr::null_mut()
        }
    }
}

///
/// Loads timespans from subtitle file. Returns null if no file exists at the given path.
/// 
#[catch_panic(ptr::null_mut())]
#[no_mangle]
pub extern "C" fn alass_timespans_load_subtitle(filename: *const c_char, sub_encoding: *const c_char) -> *mut TimeSpans {
    let filename_str = from_cstring(filename);
    if filename_str.is_none() {
        error!("Invalid parameter: filename is invalid");
        return ptr::null_mut();
    }

    let sub_encoding_str = from_cstring(sub_encoding);

    match open_sub_file(&filename_str.unwrap(), sub_encoding_str) {
        Ok((sub_file, _)) => match TimeSpans::from_sub_file(&sub_file) {
            Ok(spans) => to_ptr(spans),
            Err(e) => {
                error!("{}", e);
                ptr::null_mut()
            }
        },
        Err(e) => {
            error!("{}", e);
            ptr::null_mut()
        }
    }
}

///
/// Deallocates `TimeSpans` instance.
/// 
#[catch_panic]
#[no_mangle]
pub extern "C" fn alass_timespans_free(spans: *mut TimeSpans) {
    if !spans.is_null() {
        drop(from_ptr_owned(spans));
    }
}