chromaprint 0.1.2

Bindings to Chromaprint
Documentation
extern crate libc;

use std::ffi::CStr;
use std::{ptr, mem, slice};

pub type ChromaprintContext = *mut ::libc::c_void;
pub type ChromaprintAlgorithm = ::libc::c_int;
pub const CHROMAPRINT_ALGORITHM_TEST1: ChromaprintAlgorithm = 0;
pub const CHROMAPRINT_ALGORITHM_TEST2: ChromaprintAlgorithm = 1;
pub const CHROMAPRINT_ALGORITHM_TEST3: ChromaprintAlgorithm = 2;
pub const CHROMAPRINT_ALGORITHM_TEST4: ChromaprintAlgorithm = 3;
pub const CHROMAPRINT_ALGORITHM_DEFAULT: ChromaprintAlgorithm  = CHROMAPRINT_ALGORITHM_TEST2;
#[link(name = "chromaprint")]
extern "C" {
    pub fn chromaprint_get_version() -> *const ::libc::c_char;
    pub fn chromaprint_new(algorithm: ChromaprintAlgorithm)
     -> *mut ChromaprintContext;
    pub fn chromaprint_free(ctx: *mut ChromaprintContext) -> ();
    pub fn chromaprint_get_algorithm(ctx: *mut ChromaprintContext)
     -> ChromaprintAlgorithm;
    pub fn chromaprint_set_option(ctx: *mut ChromaprintContext,
                                  name: *const ::libc::c_char,
                                  value: ::libc::c_int) -> ::libc::c_int;
    pub fn chromaprint_start(ctx: *mut ChromaprintContext,
                             sample_rate: ::libc::c_int,
                             num_channels: ::libc::c_int) -> ::libc::c_int;
    pub fn chromaprint_feed(ctx: *mut ChromaprintContext,
                            data: *const ::libc::c_void, size: ::libc::c_int)
     -> ::libc::c_int;
    pub fn chromaprint_finish(ctx: *mut ChromaprintContext) -> ::libc::c_int;
    pub fn chromaprint_get_fingerprint(ctx: *mut ChromaprintContext,
                                       fingerprint: *mut *mut ::libc::c_char)
     -> ::libc::c_int;
    pub fn chromaprint_get_raw_fingerprint(ctx: *mut ChromaprintContext,
                                           fingerprint:
                                               *mut *mut ::libc::c_void,
                                           size: *mut ::libc::c_int)
     -> ::libc::c_int;
    pub fn chromaprint_encode_fingerprint(fp: *const ::libc::c_void,
                                          size: ::libc::c_int,
                                          algorithm: ::libc::c_int,
                                          encoded_fp:
                                              *mut *mut ::libc::c_void,
                                          encoded_size: *mut ::libc::c_int,
                                          base64: ::libc::c_int)
     -> ::libc::c_int;
    pub fn chromaprint_decode_fingerprint(encoded_fp: *const ::libc::c_void,
                                          encoded_size: ::libc::c_int,
                                          fp: *mut *mut ::libc::c_void,
                                          size: *mut ::libc::c_int,
                                          algorithm: *mut ::libc::c_int,
                                          base64: ::libc::c_int)
     -> ::libc::c_int;
    pub fn chromaprint_dealloc(ptr: *mut ::libc::c_void) -> ();
}

pub struct Chromaprint {
    ctx: *mut ChromaprintContext,
}

impl Chromaprint {
    pub fn new() -> Chromaprint {
        unsafe {
            Chromaprint {
                ctx:  chromaprint_new(CHROMAPRINT_ALGORITHM_DEFAULT),
            }
        }
    }

    pub fn version() -> String {
        String::from_utf8(unsafe { CStr::from_ptr(chromaprint_get_version()).to_bytes().to_vec() }).unwrap()
    }

    pub fn algorithm(&self) -> ChromaprintAlgorithm {
        unsafe { chromaprint_get_algorithm(self.ctx) }
    }

    pub fn start(&mut self, sample_rate: ::libc::c_int, num_channels: ::libc::c_int) -> bool {
        unsafe { chromaprint_start(self.ctx, sample_rate, num_channels) == 1 }
    }

    pub fn feed(&mut self, data: &[u8]) -> bool {
        unsafe { chromaprint_feed(self.ctx, data.as_ptr() as *const ::libc::c_void, data.len() as ::libc::c_int) == 1 }
    }

    pub fn finish(&mut self) -> bool {
        unsafe { chromaprint_finish(self.ctx) == 1 }
    }

    pub fn fingerprint(&mut self) -> Option<String> {
        let mut fingerprint: *mut ::libc::c_char = ptr::null_mut();
        if unsafe { chromaprint_get_fingerprint(self.ctx, &mut fingerprint) } == 1 {
            let ret = String::from_utf8(unsafe { CStr::from_ptr(fingerprint) }.to_bytes().to_vec()).ok();
            unsafe { chromaprint_dealloc(fingerprint as *mut ::libc::c_void) }
            return ret;
        }
        None
    }

    pub fn raw_fingerprint(&mut self) -> Option<Vec<::libc::c_int>> {
        let mut array: *mut ::libc::c_int = ptr::null_mut();
        let mut size: ::libc::c_int = 0;
        if unsafe { chromaprint_get_raw_fingerprint(self.ctx, mem::transmute::<_, *mut *mut ::libc::c_void>(&mut array), &mut size) } == 1 {
            let fingerprint = unsafe { slice::from_raw_parts(array, size as usize).to_vec() };
            unsafe { chromaprint_dealloc(array as *mut ::libc::c_void) }
            return Some(fingerprint);
        }
        None
    }

    pub fn encode(raw_fingerprint: &[::libc::c_int], algorithm: ChromaprintAlgorithm, base64: bool) -> Option<Vec<u8>> {
        let mut array: *mut u8 = ptr::null_mut();
        let mut size: ::libc::c_int = 0;
        let result = unsafe { 
            chromaprint_encode_fingerprint(raw_fingerprint.as_ptr() as *const ::libc::c_void, 
                                           raw_fingerprint.len() as ::libc::c_int, algorithm, 
                                           mem::transmute::<_, *mut *mut ::libc::c_void>(&mut array), 
                                           &mut size, base64 as ::libc::c_int) 
        };
        if result == 1 {
            let encoded = unsafe { slice::from_raw_parts(array, size as usize).to_vec() };
            unsafe { chromaprint_dealloc(array as *mut ::libc::c_void) }
            return Some(encoded);
        }
        None
    }

    pub fn decode(encoded_fingerprint: &[u8], base64: bool) -> Option<(Vec<::libc::c_int>, ChromaprintAlgorithm)> {
        let mut array: *mut ::libc::c_int = ptr::null_mut();
        let mut size: ::libc::c_int = 0;
        let mut algorithm: ChromaprintAlgorithm = -1;
        let result = unsafe {
            chromaprint_decode_fingerprint(encoded_fingerprint.as_ptr() as *const ::libc::c_void, 
                                           encoded_fingerprint.len() as ::libc::c_int, 
                                           mem::transmute::<_, *mut *mut ::libc::c_void>(&mut array), 
                                           &mut size, &mut algorithm, base64 as ::libc::c_int)
        };
        if result == 1 {
            let decoded = unsafe { slice::from_raw_parts(array, size as usize).to_vec() };
            unsafe { chromaprint_dealloc(array as *mut ::libc::c_void) }
            return Some((decoded, algorithm));
        }
        None
    }
}

impl Drop for Chromaprint {
    fn drop(&mut self) {
        unsafe { chromaprint_free(self.ctx); }
    }
}