2280 lines
110 KiB
Rust
2280 lines
110 KiB
Rust
use ::libc;
|
|
extern "C" {
|
|
pub type _IO_wide_data;
|
|
pub type _IO_codecvt;
|
|
pub type _IO_marker;
|
|
pub type _snd_mixer;
|
|
pub type _snd_mixer_selem_id;
|
|
pub type _snd_mixer_elem;
|
|
pub type _snd_mixer_class;
|
|
pub type _snd_pcm;
|
|
pub type _snd_pcm_hw_params;
|
|
pub type _snd_output;
|
|
#[no_mangle]
|
|
static mut stderr: *mut FILE;
|
|
#[no_mangle]
|
|
fn fflush(__stream: *mut FILE) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn fprintf(_: *mut FILE, _: *const libc::c_char, _: ...) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn printf(_: *const libc::c_char, _: ...) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn vfprintf(_: *mut FILE, _: *const libc::c_char, _: ::std::ffi::VaList)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn atoi(__nptr: *const libc::c_char) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn malloc(_: libc::c_ulong) -> *mut libc::c_void;
|
|
#[no_mangle]
|
|
fn free(__ptr: *mut libc::c_void);
|
|
#[no_mangle]
|
|
fn memcpy(_: *mut libc::c_void, _: *const libc::c_void, _: libc::c_ulong)
|
|
-> *mut libc::c_void;
|
|
#[no_mangle]
|
|
fn memset(_: *mut libc::c_void, _: libc::c_int, _: libc::c_ulong)
|
|
-> *mut libc::c_void;
|
|
#[no_mangle]
|
|
fn strcpy(_: *mut libc::c_char, _: *const libc::c_char)
|
|
-> *mut libc::c_char;
|
|
#[no_mangle]
|
|
fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn strncmp(_: *const libc::c_char, _: *const libc::c_char,
|
|
_: libc::c_ulong) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn strdup(_: *const libc::c_char) -> *mut libc::c_char;
|
|
#[no_mangle]
|
|
fn strrchr(_: *const libc::c_char, _: libc::c_int) -> *mut libc::c_char;
|
|
#[no_mangle]
|
|
fn strtok(_: *mut libc::c_char, _: *const libc::c_char)
|
|
-> *mut libc::c_char;
|
|
#[no_mangle]
|
|
fn strlen(_: *const libc::c_char) -> libc::c_ulong;
|
|
#[no_mangle]
|
|
fn strerror(_: libc::c_int) -> *mut libc::c_char;
|
|
#[no_mangle]
|
|
fn __errno_location() -> *mut libc::c_int;
|
|
#[no_mangle]
|
|
fn sleep(__seconds: libc::c_uint) -> libc::c_uint;
|
|
#[no_mangle]
|
|
fn usleep(__useconds: __useconds_t) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn pthread_create(__newthread: *mut pthread_t,
|
|
__attr: *const pthread_attr_t,
|
|
__start_routine:
|
|
Option<unsafe extern "C" fn(_: *mut libc::c_void)
|
|
-> *mut libc::c_void>,
|
|
__arg: *mut libc::c_void) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn pthread_join(__th: pthread_t, __thread_return: *mut *mut libc::c_void)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn pthread_attr_init(__attr: *mut pthread_attr_t) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn pthread_attr_destroy(__attr: *mut pthread_attr_t) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn pthread_attr_setstacksize(__attr: *mut pthread_attr_t,
|
|
__stacksize: size_t) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn pthread_setschedparam(__target_thread: pthread_t,
|
|
__policy: libc::c_int,
|
|
__param: *const sched_param) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn pthread_mutex_lock(__mutex: *mut pthread_mutex_t) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn pthread_mutex_unlock(__mutex: *mut pthread_mutex_t) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn logtime() -> *const libc::c_char;
|
|
#[no_mangle]
|
|
fn logprint(fmt: *const libc::c_char, _: ...);
|
|
#[no_mangle]
|
|
fn next_param(src: *mut libc::c_char, c: libc::c_char)
|
|
-> *mut libc::c_char;
|
|
#[no_mangle]
|
|
fn gettime_ms() -> u32_t;
|
|
#[no_mangle]
|
|
fn touch_memory(buf: *mut u8_t, size: size_t);
|
|
#[no_mangle]
|
|
fn output_init_common(level: log_level, device: *const libc::c_char,
|
|
output_buf_size: libc::c_uint,
|
|
rates: *mut libc::c_uint, idle: libc::c_uint);
|
|
#[no_mangle]
|
|
fn output_close_common();
|
|
#[no_mangle]
|
|
fn _output_frames(avail: frames_t) -> frames_t;
|
|
#[no_mangle]
|
|
fn _apply_cross(outputbuf_0: *mut buffer, out_frames: frames_t,
|
|
cross_gain_in: s32_t, cross_gain_out: s32_t,
|
|
cross_ptr: *mut *mut s32_t);
|
|
#[no_mangle]
|
|
fn _scale_and_pack_frames(outputptr: *mut libc::c_void,
|
|
inputptr: *mut s32_t, cnt: frames_t,
|
|
gainL: s32_t, gainR: s32_t,
|
|
format: output_format);
|
|
#[no_mangle]
|
|
fn _apply_gain(outputbuf_0: *mut buffer, count: frames_t, gainL: s32_t,
|
|
gainR: s32_t);
|
|
#[no_mangle]
|
|
fn snd_pcm_open(pcm: *mut *mut snd_pcm_t, name: *const libc::c_char,
|
|
stream: snd_pcm_stream_t, mode: libc::c_int)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_pcm_close(pcm: *mut snd_pcm_t) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_pcm_hw_params(pcm: *mut snd_pcm_t,
|
|
params: *mut snd_pcm_hw_params_t) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_pcm_start(pcm: *mut snd_pcm_t) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_pcm_state(pcm: *mut snd_pcm_t) -> snd_pcm_state_t;
|
|
#[no_mangle]
|
|
fn snd_pcm_delay(pcm: *mut snd_pcm_t, delayp: *mut snd_pcm_sframes_t)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_pcm_avail_update(pcm: *mut snd_pcm_t) -> snd_pcm_sframes_t;
|
|
#[no_mangle]
|
|
fn snd_pcm_writei(pcm: *mut snd_pcm_t, buffer: *const libc::c_void,
|
|
size: snd_pcm_uframes_t) -> snd_pcm_sframes_t;
|
|
#[no_mangle]
|
|
fn snd_pcm_wait(pcm: *mut snd_pcm_t, timeout: libc::c_int) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_pcm_recover(pcm: *mut snd_pcm_t, err: libc::c_int,
|
|
silent: libc::c_int) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_pcm_hw_params_any(pcm: *mut snd_pcm_t,
|
|
params: *mut snd_pcm_hw_params_t) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_pcm_hw_params_sizeof() -> size_t;
|
|
#[no_mangle]
|
|
fn snd_pcm_hw_params_set_access(pcm: *mut snd_pcm_t,
|
|
params: *mut snd_pcm_hw_params_t,
|
|
_access: snd_pcm_access_t) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_pcm_hw_params_set_format(pcm: *mut snd_pcm_t,
|
|
params: *mut snd_pcm_hw_params_t,
|
|
val: snd_pcm_format_t) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_pcm_hw_params_set_channels(pcm: *mut snd_pcm_t,
|
|
params: *mut snd_pcm_hw_params_t,
|
|
val: libc::c_uint) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_pcm_hw_params_test_rate(pcm: *mut snd_pcm_t,
|
|
params: *mut snd_pcm_hw_params_t,
|
|
val: libc::c_uint, dir: libc::c_int)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_pcm_hw_params_set_rate(pcm: *mut snd_pcm_t,
|
|
params: *mut snd_pcm_hw_params_t,
|
|
val: libc::c_uint, dir: libc::c_int)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_pcm_hw_params_set_rate_resample(pcm: *mut snd_pcm_t,
|
|
params: *mut snd_pcm_hw_params_t,
|
|
val: libc::c_uint) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_pcm_hw_params_get_period_size(params: *const snd_pcm_hw_params_t,
|
|
frames: *mut snd_pcm_uframes_t,
|
|
dir: *mut libc::c_int)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_pcm_hw_params_set_period_size_near(pcm: *mut snd_pcm_t,
|
|
params:
|
|
*mut snd_pcm_hw_params_t,
|
|
val: *mut snd_pcm_uframes_t,
|
|
dir: *mut libc::c_int)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_pcm_hw_params_set_periods_near(pcm: *mut snd_pcm_t,
|
|
params: *mut snd_pcm_hw_params_t,
|
|
val: *mut libc::c_uint,
|
|
dir: *mut libc::c_int)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_pcm_hw_params_set_buffer_time_near(pcm: *mut snd_pcm_t,
|
|
params:
|
|
*mut snd_pcm_hw_params_t,
|
|
val: *mut libc::c_uint,
|
|
dir: *mut libc::c_int)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_pcm_hw_params_get_buffer_size(params: *const snd_pcm_hw_params_t,
|
|
val: *mut snd_pcm_uframes_t)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_pcm_hw_params_set_buffer_size_near(pcm: *mut snd_pcm_t,
|
|
params:
|
|
*mut snd_pcm_hw_params_t,
|
|
val: *mut snd_pcm_uframes_t)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_pcm_format_name(format: snd_pcm_format_t) -> *const libc::c_char;
|
|
#[no_mangle]
|
|
fn snd_mixer_find_selem(mixer: *mut snd_mixer_t,
|
|
id: *const snd_mixer_selem_id_t)
|
|
-> *mut snd_mixer_elem_t;
|
|
#[no_mangle]
|
|
fn snd_device_name_free_hint(hints: *mut *mut libc::c_void)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_pcm_mmap_begin(pcm: *mut snd_pcm_t,
|
|
areas: *mut *const snd_pcm_channel_area_t,
|
|
offset: *mut snd_pcm_uframes_t,
|
|
frames: *mut snd_pcm_uframes_t) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_pcm_mmap_commit(pcm: *mut snd_pcm_t, offset: snd_pcm_uframes_t,
|
|
frames: snd_pcm_uframes_t) -> snd_pcm_sframes_t;
|
|
#[no_mangle]
|
|
fn snd_device_name_get_hint(hint: *const libc::c_void,
|
|
id: *const libc::c_char) -> *mut libc::c_char;
|
|
#[no_mangle]
|
|
fn snd_lib_error_set_handler(handler: snd_lib_error_handler_t)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_device_name_hint(card: libc::c_int, iface: *const libc::c_char,
|
|
hints: *mut *mut *mut libc::c_void)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_mixer_selem_id_set_index(obj: *mut snd_mixer_selem_id_t,
|
|
val: libc::c_uint);
|
|
#[no_mangle]
|
|
fn snd_mixer_selem_id_set_name(obj: *mut snd_mixer_selem_id_t,
|
|
val: *const libc::c_char);
|
|
#[no_mangle]
|
|
fn snd_mixer_close(mixer: *mut snd_mixer_t) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_mixer_selem_has_playback_switch(elem: *mut snd_mixer_elem_t)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_mixer_selem_set_playback_switch_all(elem: *mut snd_mixer_elem_t,
|
|
value: libc::c_int)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_mixer_selem_get_playback_dB_range(elem: *mut snd_mixer_elem_t,
|
|
min: *mut libc::c_long,
|
|
max: *mut libc::c_long)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_mixer_selem_get_playback_volume_range(elem: *mut snd_mixer_elem_t,
|
|
min: *mut libc::c_long,
|
|
max: *mut libc::c_long)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_output_stdio_attach(outputp: *mut *mut snd_output_t, fp: *mut FILE,
|
|
_close: libc::c_int) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_pcm_dump(pcm: *mut snd_pcm_t, out: *mut snd_output_t)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_mixer_selem_set_playback_volume(elem: *mut snd_mixer_elem_t,
|
|
channel:
|
|
snd_mixer_selem_channel_id_t,
|
|
value: libc::c_long)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_mixer_selem_set_playback_dB(elem: *mut snd_mixer_elem_t,
|
|
channel: snd_mixer_selem_channel_id_t,
|
|
value: libc::c_long, dir: libc::c_int)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_mixer_selem_get_playback_volume(elem: *mut snd_mixer_elem_t,
|
|
channel:
|
|
snd_mixer_selem_channel_id_t,
|
|
value: *mut libc::c_long)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_mixer_selem_id_sizeof() -> size_t;
|
|
#[no_mangle]
|
|
fn snd_mixer_open(mixer: *mut *mut snd_mixer_t, mode: libc::c_int)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_mixer_attach(mixer: *mut snd_mixer_t, name: *const libc::c_char)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_mixer_selem_register(mixer: *mut snd_mixer_t,
|
|
options: *mut snd_mixer_selem_regopt,
|
|
classp: *mut *mut snd_mixer_class_t)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_mixer_load(mixer: *mut snd_mixer_t) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_strerror(errnum: libc::c_int) -> *const libc::c_char;
|
|
#[no_mangle]
|
|
fn snd_mixer_first_elem(mixer: *mut snd_mixer_t) -> *mut snd_mixer_elem_t;
|
|
#[no_mangle]
|
|
fn snd_mixer_elem_next(elem: *mut snd_mixer_elem_t)
|
|
-> *mut snd_mixer_elem_t;
|
|
#[no_mangle]
|
|
fn snd_mixer_selem_has_playback_volume(elem: *mut snd_mixer_elem_t)
|
|
-> libc::c_int;
|
|
#[no_mangle]
|
|
fn snd_mixer_selem_get_id(element: *mut snd_mixer_elem_t,
|
|
id: *mut snd_mixer_selem_id_t);
|
|
#[no_mangle]
|
|
fn snd_mixer_selem_id_get_name(obj: *const snd_mixer_selem_id_t)
|
|
-> *const libc::c_char;
|
|
#[no_mangle]
|
|
fn snd_mixer_selem_id_get_index(obj: *const snd_mixer_selem_id_t)
|
|
-> libc::c_uint;
|
|
#[no_mangle]
|
|
fn mlockall(__flags: libc::c_int) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn mallopt(__param: libc::c_int, __val: libc::c_int) -> libc::c_int;
|
|
#[no_mangle]
|
|
fn log10(_: libc::c_double) -> libc::c_double;
|
|
#[no_mangle]
|
|
fn floor(_: libc::c_double) -> libc::c_double;
|
|
#[no_mangle]
|
|
static mut silencebuf: *mut u8_t;
|
|
#[no_mangle]
|
|
static mut output: outputstate;
|
|
#[no_mangle]
|
|
static mut outputbuf: *mut buffer;
|
|
}
|
|
pub type __builtin_va_list = [__va_list_tag; 1];
|
|
#[derive(Copy, Clone)]
|
|
#[repr(C)]
|
|
pub struct __va_list_tag {
|
|
pub gp_offset: libc::c_uint,
|
|
pub fp_offset: libc::c_uint,
|
|
pub overflow_arg_area: *mut libc::c_void,
|
|
pub reg_save_area: *mut libc::c_void,
|
|
}
|
|
pub type size_t = libc::c_ulong;
|
|
pub type va_list = __builtin_va_list;
|
|
pub type __uint8_t = libc::c_uchar;
|
|
pub type __int32_t = libc::c_int;
|
|
pub type __uint32_t = libc::c_uint;
|
|
pub type __off_t = libc::c_long;
|
|
pub type __off64_t = libc::c_long;
|
|
pub type __useconds_t = libc::c_uint;
|
|
#[derive(Copy, Clone)]
|
|
#[repr(C)]
|
|
pub struct _IO_FILE {
|
|
pub _flags: libc::c_int,
|
|
pub _IO_read_ptr: *mut libc::c_char,
|
|
pub _IO_read_end: *mut libc::c_char,
|
|
pub _IO_read_base: *mut libc::c_char,
|
|
pub _IO_write_base: *mut libc::c_char,
|
|
pub _IO_write_ptr: *mut libc::c_char,
|
|
pub _IO_write_end: *mut libc::c_char,
|
|
pub _IO_buf_base: *mut libc::c_char,
|
|
pub _IO_buf_end: *mut libc::c_char,
|
|
pub _IO_save_base: *mut libc::c_char,
|
|
pub _IO_backup_base: *mut libc::c_char,
|
|
pub _IO_save_end: *mut libc::c_char,
|
|
pub _markers: *mut _IO_marker,
|
|
pub _chain: *mut _IO_FILE,
|
|
pub _fileno: libc::c_int,
|
|
pub _flags2: libc::c_int,
|
|
pub _old_offset: __off_t,
|
|
pub _cur_column: libc::c_ushort,
|
|
pub _vtable_offset: libc::c_schar,
|
|
pub _shortbuf: [libc::c_char; 1],
|
|
pub _lock: *mut libc::c_void,
|
|
pub _offset: __off64_t,
|
|
pub _codecvt: *mut _IO_codecvt,
|
|
pub _wide_data: *mut _IO_wide_data,
|
|
pub _freeres_list: *mut _IO_FILE,
|
|
pub _freeres_buf: *mut libc::c_void,
|
|
pub __pad5: size_t,
|
|
pub _mode: libc::c_int,
|
|
pub _unused2: [libc::c_char; 20],
|
|
}
|
|
pub type _IO_lock_t = ();
|
|
pub type FILE = _IO_FILE;
|
|
pub type int32_t = __int32_t;
|
|
pub type u_int8_t = __uint8_t;
|
|
pub type u_int32_t = __uint32_t;
|
|
#[derive(Copy, Clone)]
|
|
#[repr(C)]
|
|
pub struct __pthread_internal_list {
|
|
pub __prev: *mut __pthread_internal_list,
|
|
pub __next: *mut __pthread_internal_list,
|
|
}
|
|
pub type __pthread_list_t = __pthread_internal_list;
|
|
#[derive(Copy, Clone)]
|
|
#[repr(C)]
|
|
pub struct __pthread_mutex_s {
|
|
pub __lock: libc::c_int,
|
|
pub __count: libc::c_uint,
|
|
pub __owner: libc::c_int,
|
|
pub __nusers: libc::c_uint,
|
|
pub __kind: libc::c_int,
|
|
pub __spins: libc::c_short,
|
|
pub __elision: libc::c_short,
|
|
pub __list: __pthread_list_t,
|
|
}
|
|
pub type pthread_t = libc::c_ulong;
|
|
#[derive(Copy, Clone)]
|
|
#[repr(C)]
|
|
pub union pthread_attr_t {
|
|
pub __size: [libc::c_char; 56],
|
|
pub __align: libc::c_long,
|
|
}
|
|
#[derive(Copy, Clone)]
|
|
#[repr(C)]
|
|
pub union pthread_mutex_t {
|
|
pub __data: __pthread_mutex_s,
|
|
pub __size: [libc::c_char; 40],
|
|
pub __align: libc::c_long,
|
|
}
|
|
#[derive(Copy, Clone)]
|
|
#[repr(C)]
|
|
pub struct sched_param {
|
|
pub sched_priority: libc::c_int,
|
|
}
|
|
pub type u8_t = u_int8_t;
|
|
pub type u32_t = u_int32_t;
|
|
pub type s32_t = int32_t;
|
|
pub type frames_t = u32_t;
|
|
pub type log_level = libc::c_uint;
|
|
pub const lSDEBUG: log_level = 4;
|
|
pub const lDEBUG: log_level = 3;
|
|
pub const lINFO: log_level = 2;
|
|
pub const lWARN: log_level = 1;
|
|
pub const lERROR: log_level = 0;
|
|
#[derive(Copy, Clone)]
|
|
#[repr(C)]
|
|
pub struct buffer {
|
|
pub buf: *mut u8_t,
|
|
pub readp: *mut u8_t,
|
|
pub writep: *mut u8_t,
|
|
pub wrap: *mut u8_t,
|
|
pub size: size_t,
|
|
pub base_size: size_t,
|
|
pub mutex: pthread_mutex_t,
|
|
}
|
|
pub type output_state = libc::c_int;
|
|
pub const OUTPUT_START_AT: output_state = 5;
|
|
pub const OUTPUT_SKIP_FRAMES: output_state = 4;
|
|
pub const OUTPUT_PAUSE_FRAMES: output_state = 3;
|
|
pub const OUTPUT_RUNNING: output_state = 2;
|
|
pub const OUTPUT_BUFFER: output_state = 1;
|
|
pub const OUTPUT_STOPPED: output_state = 0;
|
|
pub const OUTPUT_OFF: output_state = -1;
|
|
pub type output_format = libc::c_uint;
|
|
pub const S16_LE: output_format = 3;
|
|
pub const S24_3LE: output_format = 2;
|
|
pub const S24_LE: output_format = 1;
|
|
pub const S32_LE: output_format = 0;
|
|
pub type fade_state = libc::c_uint;
|
|
pub const FADE_ACTIVE: fade_state = 2;
|
|
pub const FADE_DUE: fade_state = 1;
|
|
pub const FADE_INACTIVE: fade_state = 0;
|
|
pub type fade_dir = libc::c_uint;
|
|
pub const FADE_CROSS: fade_dir = 3;
|
|
pub const FADE_DOWN: fade_dir = 2;
|
|
pub const FADE_UP: fade_dir = 1;
|
|
pub type fade_mode = libc::c_uint;
|
|
pub const FADE_INOUT: fade_mode = 4;
|
|
pub const FADE_OUT: fade_mode = 3;
|
|
pub const FADE_IN: fade_mode = 2;
|
|
pub const FADE_CROSSFADE: fade_mode = 1;
|
|
pub const FADE_NONE: fade_mode = 0;
|
|
#[derive(Copy, Clone)]
|
|
#[repr(C)]
|
|
pub struct outputstate {
|
|
pub state: output_state,
|
|
pub format: output_format,
|
|
pub device: *const libc::c_char,
|
|
pub buffer: libc::c_uint,
|
|
pub period: libc::c_uint,
|
|
pub track_started: bool,
|
|
pub write_cb: Option<unsafe extern "C" fn(_: frames_t, _: bool, _: s32_t,
|
|
_: s32_t, _: s32_t, _: s32_t,
|
|
_: *mut *mut s32_t)
|
|
-> libc::c_int>,
|
|
pub start_frames: libc::c_uint,
|
|
pub frames_played: libc::c_uint,
|
|
pub frames_played_dmp: libc::c_uint,
|
|
pub current_sample_rate: libc::c_uint,
|
|
pub supported_rates: [libc::c_uint; 18],
|
|
pub default_sample_rate: libc::c_uint,
|
|
pub error_opening: bool,
|
|
pub device_frames: libc::c_uint,
|
|
pub updated: u32_t,
|
|
pub track_start_time: u32_t,
|
|
pub current_replay_gain: u32_t,
|
|
pub c2rust_unnamed: C2RustUnnamed,
|
|
pub next_sample_rate: libc::c_uint,
|
|
pub track_start: *mut u8_t,
|
|
pub gainL: u32_t,
|
|
pub gainR: u32_t,
|
|
pub invert: bool,
|
|
pub next_replay_gain: u32_t,
|
|
pub threshold: libc::c_uint,
|
|
pub fade: fade_state,
|
|
pub fade_start: *mut u8_t,
|
|
pub fade_end: *mut u8_t,
|
|
pub fade_dir: fade_dir,
|
|
pub fade_mode: fade_mode,
|
|
pub fade_secs: libc::c_uint,
|
|
pub rate_delay: libc::c_uint,
|
|
pub delay_active: bool,
|
|
pub stop_time: u32_t,
|
|
pub idle_to: u32_t,
|
|
}
|
|
#[derive(Copy, Clone)]
|
|
#[repr(C)]
|
|
pub union C2RustUnnamed {
|
|
pub pause_frames: u32_t,
|
|
pub skip_frames: u32_t,
|
|
pub start_at: u32_t,
|
|
}
|
|
pub type snd_mixer_t = _snd_mixer;
|
|
pub type snd_mixer_selem_id_t = _snd_mixer_selem_id;
|
|
pub type snd_mixer_elem_t = _snd_mixer_elem;
|
|
pub type snd_mixer_class_t = _snd_mixer_class;
|
|
#[derive(Copy, Clone)]
|
|
#[repr(C)]
|
|
pub struct snd_mixer_selem_regopt {
|
|
pub ver: libc::c_int,
|
|
pub abstract_0: snd_mixer_selem_regopt_abstract,
|
|
pub device: *const libc::c_char,
|
|
pub playback_pcm: *mut snd_pcm_t,
|
|
pub capture_pcm: *mut snd_pcm_t,
|
|
}
|
|
pub type snd_pcm_t = _snd_pcm;
|
|
pub type snd_mixer_selem_regopt_abstract = libc::c_uint;
|
|
pub const SND_MIXER_SABSTRACT_BASIC: snd_mixer_selem_regopt_abstract = 1;
|
|
pub const SND_MIXER_SABSTRACT_NONE: snd_mixer_selem_regopt_abstract = 0;
|
|
// ouput device
|
|
#[derive(Copy, Clone)]
|
|
#[repr(C)]
|
|
pub struct C2RustUnnamed_0 {
|
|
pub device: [libc::c_char; 129],
|
|
pub ctl: *mut libc::c_char,
|
|
pub mixer_ctl: *mut libc::c_char,
|
|
pub format: snd_pcm_format_t,
|
|
pub buffer_size: snd_pcm_uframes_t,
|
|
pub period_size: snd_pcm_uframes_t,
|
|
pub rate: libc::c_uint,
|
|
pub mmap: bool,
|
|
pub reopen: bool,
|
|
pub write_buf: *mut u8_t,
|
|
pub volume_mixer_name: *const libc::c_char,
|
|
pub mixer_linear: bool,
|
|
pub mixer_elem: *mut snd_mixer_elem_t,
|
|
pub mixer_handle: *mut snd_mixer_t,
|
|
pub mixer_min: libc::c_long,
|
|
pub mixer_max: libc::c_long,
|
|
}
|
|
pub type snd_pcm_uframes_t = libc::c_ulong;
|
|
pub type snd_pcm_format_t = _snd_pcm_format;
|
|
pub type _snd_pcm_format = libc::c_int;
|
|
pub const SND_PCM_FORMAT_U20: _snd_pcm_format = 27;
|
|
pub const SND_PCM_FORMAT_S20: _snd_pcm_format = 25;
|
|
pub const SND_PCM_FORMAT_IEC958_SUBFRAME: _snd_pcm_format = 18;
|
|
pub const SND_PCM_FORMAT_FLOAT64: _snd_pcm_format = 16;
|
|
pub const SND_PCM_FORMAT_FLOAT: _snd_pcm_format = 14;
|
|
pub const SND_PCM_FORMAT_U32: _snd_pcm_format = 12;
|
|
pub const SND_PCM_FORMAT_S32: _snd_pcm_format = 10;
|
|
pub const SND_PCM_FORMAT_U24: _snd_pcm_format = 8;
|
|
pub const SND_PCM_FORMAT_S24: _snd_pcm_format = 6;
|
|
pub const SND_PCM_FORMAT_U16: _snd_pcm_format = 4;
|
|
pub const SND_PCM_FORMAT_S16: _snd_pcm_format = 2;
|
|
pub const SND_PCM_FORMAT_LAST: _snd_pcm_format = 52;
|
|
pub const SND_PCM_FORMAT_DSD_U32_BE: _snd_pcm_format = 52;
|
|
pub const SND_PCM_FORMAT_DSD_U16_BE: _snd_pcm_format = 51;
|
|
pub const SND_PCM_FORMAT_DSD_U32_LE: _snd_pcm_format = 50;
|
|
pub const SND_PCM_FORMAT_DSD_U16_LE: _snd_pcm_format = 49;
|
|
pub const SND_PCM_FORMAT_DSD_U8: _snd_pcm_format = 48;
|
|
pub const SND_PCM_FORMAT_G723_40_1B: _snd_pcm_format = 47;
|
|
pub const SND_PCM_FORMAT_G723_40: _snd_pcm_format = 46;
|
|
pub const SND_PCM_FORMAT_G723_24_1B: _snd_pcm_format = 45;
|
|
pub const SND_PCM_FORMAT_G723_24: _snd_pcm_format = 44;
|
|
pub const SND_PCM_FORMAT_U18_3BE: _snd_pcm_format = 43;
|
|
pub const SND_PCM_FORMAT_U18_3LE: _snd_pcm_format = 42;
|
|
pub const SND_PCM_FORMAT_S18_3BE: _snd_pcm_format = 41;
|
|
pub const SND_PCM_FORMAT_S18_3LE: _snd_pcm_format = 40;
|
|
pub const SND_PCM_FORMAT_U20_3BE: _snd_pcm_format = 39;
|
|
pub const SND_PCM_FORMAT_U20_3LE: _snd_pcm_format = 38;
|
|
pub const SND_PCM_FORMAT_S20_3BE: _snd_pcm_format = 37;
|
|
pub const SND_PCM_FORMAT_S20_3LE: _snd_pcm_format = 36;
|
|
pub const SND_PCM_FORMAT_U24_3BE: _snd_pcm_format = 35;
|
|
pub const SND_PCM_FORMAT_U24_3LE: _snd_pcm_format = 34;
|
|
pub const SND_PCM_FORMAT_S24_3BE: _snd_pcm_format = 33;
|
|
pub const SND_PCM_FORMAT_S24_3LE: _snd_pcm_format = 32;
|
|
pub const SND_PCM_FORMAT_SPECIAL: _snd_pcm_format = 31;
|
|
pub const SND_PCM_FORMAT_U20_BE: _snd_pcm_format = 28;
|
|
pub const SND_PCM_FORMAT_U20_LE: _snd_pcm_format = 27;
|
|
pub const SND_PCM_FORMAT_S20_BE: _snd_pcm_format = 26;
|
|
pub const SND_PCM_FORMAT_S20_LE: _snd_pcm_format = 25;
|
|
pub const SND_PCM_FORMAT_GSM: _snd_pcm_format = 24;
|
|
pub const SND_PCM_FORMAT_MPEG: _snd_pcm_format = 23;
|
|
pub const SND_PCM_FORMAT_IMA_ADPCM: _snd_pcm_format = 22;
|
|
pub const SND_PCM_FORMAT_A_LAW: _snd_pcm_format = 21;
|
|
pub const SND_PCM_FORMAT_MU_LAW: _snd_pcm_format = 20;
|
|
pub const SND_PCM_FORMAT_IEC958_SUBFRAME_BE: _snd_pcm_format = 19;
|
|
pub const SND_PCM_FORMAT_IEC958_SUBFRAME_LE: _snd_pcm_format = 18;
|
|
pub const SND_PCM_FORMAT_FLOAT64_BE: _snd_pcm_format = 17;
|
|
pub const SND_PCM_FORMAT_FLOAT64_LE: _snd_pcm_format = 16;
|
|
pub const SND_PCM_FORMAT_FLOAT_BE: _snd_pcm_format = 15;
|
|
pub const SND_PCM_FORMAT_FLOAT_LE: _snd_pcm_format = 14;
|
|
pub const SND_PCM_FORMAT_U32_BE: _snd_pcm_format = 13;
|
|
pub const SND_PCM_FORMAT_U32_LE: _snd_pcm_format = 12;
|
|
pub const SND_PCM_FORMAT_S32_BE: _snd_pcm_format = 11;
|
|
pub const SND_PCM_FORMAT_S32_LE: _snd_pcm_format = 10;
|
|
pub const SND_PCM_FORMAT_U24_BE: _snd_pcm_format = 9;
|
|
pub const SND_PCM_FORMAT_U24_LE: _snd_pcm_format = 8;
|
|
pub const SND_PCM_FORMAT_S24_BE: _snd_pcm_format = 7;
|
|
pub const SND_PCM_FORMAT_S24_LE: _snd_pcm_format = 6;
|
|
pub const SND_PCM_FORMAT_U16_BE: _snd_pcm_format = 5;
|
|
pub const SND_PCM_FORMAT_U16_LE: _snd_pcm_format = 4;
|
|
pub const SND_PCM_FORMAT_S16_BE: _snd_pcm_format = 3;
|
|
pub const SND_PCM_FORMAT_S16_LE: _snd_pcm_format = 2;
|
|
pub const SND_PCM_FORMAT_U8: _snd_pcm_format = 1;
|
|
pub const SND_PCM_FORMAT_S8: _snd_pcm_format = 0;
|
|
pub const SND_PCM_FORMAT_UNKNOWN: _snd_pcm_format = -1;
|
|
pub type snd_mixer_selem_channel_id_t = _snd_mixer_selem_channel_id;
|
|
pub type _snd_mixer_selem_channel_id = libc::c_int;
|
|
pub const SND_MIXER_SCHN_MONO: _snd_mixer_selem_channel_id = 0;
|
|
pub const SND_MIXER_SCHN_LAST: _snd_mixer_selem_channel_id = 31;
|
|
pub const SND_MIXER_SCHN_REAR_CENTER: _snd_mixer_selem_channel_id = 8;
|
|
pub const SND_MIXER_SCHN_SIDE_RIGHT: _snd_mixer_selem_channel_id = 7;
|
|
pub const SND_MIXER_SCHN_SIDE_LEFT: _snd_mixer_selem_channel_id = 6;
|
|
pub const SND_MIXER_SCHN_WOOFER: _snd_mixer_selem_channel_id = 5;
|
|
pub const SND_MIXER_SCHN_FRONT_CENTER: _snd_mixer_selem_channel_id = 4;
|
|
pub const SND_MIXER_SCHN_REAR_RIGHT: _snd_mixer_selem_channel_id = 3;
|
|
pub const SND_MIXER_SCHN_REAR_LEFT: _snd_mixer_selem_channel_id = 2;
|
|
pub const SND_MIXER_SCHN_FRONT_RIGHT: _snd_mixer_selem_channel_id = 1;
|
|
pub const SND_MIXER_SCHN_FRONT_LEFT: _snd_mixer_selem_channel_id = 0;
|
|
pub const SND_MIXER_SCHN_UNKNOWN: _snd_mixer_selem_channel_id = -1;
|
|
pub type snd_pcm_hw_params_t = _snd_pcm_hw_params;
|
|
pub type snd_pcm_stream_t = _snd_pcm_stream;
|
|
pub type _snd_pcm_stream = libc::c_uint;
|
|
pub const SND_PCM_STREAM_LAST: _snd_pcm_stream = 1;
|
|
pub const SND_PCM_STREAM_CAPTURE: _snd_pcm_stream = 1;
|
|
pub const SND_PCM_STREAM_PLAYBACK: _snd_pcm_stream = 0;
|
|
pub type snd_pcm_sframes_t = libc::c_long;
|
|
pub const SND_PCM_STATE_DISCONNECTED: _snd_pcm_state = 8;
|
|
pub type snd_pcm_state_t = _snd_pcm_state;
|
|
pub type _snd_pcm_state = libc::c_uint;
|
|
pub const SND_PCM_STATE_PRIVATE1: _snd_pcm_state = 1024;
|
|
pub const SND_PCM_STATE_LAST: _snd_pcm_state = 8;
|
|
pub const SND_PCM_STATE_SUSPENDED: _snd_pcm_state = 7;
|
|
pub const SND_PCM_STATE_PAUSED: _snd_pcm_state = 6;
|
|
pub const SND_PCM_STATE_DRAINING: _snd_pcm_state = 5;
|
|
pub const SND_PCM_STATE_XRUN: _snd_pcm_state = 4;
|
|
pub const SND_PCM_STATE_RUNNING: _snd_pcm_state = 3;
|
|
pub const SND_PCM_STATE_PREPARED: _snd_pcm_state = 2;
|
|
pub const SND_PCM_STATE_SETUP: _snd_pcm_state = 1;
|
|
pub const SND_PCM_STATE_OPEN: _snd_pcm_state = 0;
|
|
pub type snd_output_t = _snd_output;
|
|
pub type snd_pcm_access_t = _snd_pcm_access;
|
|
pub type _snd_pcm_access = libc::c_uint;
|
|
pub const SND_PCM_ACCESS_LAST: _snd_pcm_access = 4;
|
|
pub const SND_PCM_ACCESS_RW_NONINTERLEAVED: _snd_pcm_access = 4;
|
|
pub const SND_PCM_ACCESS_RW_INTERLEAVED: _snd_pcm_access = 3;
|
|
pub const SND_PCM_ACCESS_MMAP_COMPLEX: _snd_pcm_access = 2;
|
|
pub const SND_PCM_ACCESS_MMAP_NONINTERLEAVED: _snd_pcm_access = 1;
|
|
pub const SND_PCM_ACCESS_MMAP_INTERLEAVED: _snd_pcm_access = 0;
|
|
pub type snd_lib_error_handler_t
|
|
=
|
|
Option<unsafe extern "C" fn(_: *const libc::c_char, _: libc::c_int,
|
|
_: *const libc::c_char, _: libc::c_int,
|
|
_: *const libc::c_char, _: ...) -> ()>;
|
|
pub type snd_pcm_channel_area_t = _snd_pcm_channel_area;
|
|
#[derive(Copy, Clone)]
|
|
#[repr(C)]
|
|
pub struct _snd_pcm_channel_area {
|
|
pub addr: *mut libc::c_void,
|
|
pub first: libc::c_uint,
|
|
pub step: libc::c_uint,
|
|
}
|
|
static mut fmts: [snd_pcm_format_t; 5] =
|
|
[SND_PCM_FORMAT_S32_LE, SND_PCM_FORMAT_S24_LE, SND_PCM_FORMAT_S24_3LE,
|
|
SND_PCM_FORMAT_S16_LE, SND_PCM_FORMAT_UNKNOWN];
|
|
static mut alsa: C2RustUnnamed_0 =
|
|
C2RustUnnamed_0{device: [0; 129],
|
|
ctl: 0 as *const libc::c_char as *mut libc::c_char,
|
|
mixer_ctl: 0 as *const libc::c_char as *mut libc::c_char,
|
|
format: SND_PCM_FORMAT_S8,
|
|
buffer_size: 0,
|
|
period_size: 0,
|
|
rate: 0,
|
|
mmap: false,
|
|
reopen: false,
|
|
write_buf: 0 as *const u8_t as *mut u8_t,
|
|
volume_mixer_name: 0 as *const libc::c_char,
|
|
mixer_linear: false,
|
|
mixer_elem:
|
|
0 as *const snd_mixer_elem_t as *mut snd_mixer_elem_t,
|
|
mixer_handle: 0 as *const snd_mixer_t as *mut snd_mixer_t,
|
|
mixer_min: 0,
|
|
mixer_max: 0,};
|
|
static mut pcmp: *mut snd_pcm_t = 0 as *const snd_pcm_t as *mut snd_pcm_t;
|
|
static mut loglevel: log_level = lERROR;
|
|
static mut running: bool = 1 as libc::c_int != 0;
|
|
unsafe extern "C" fn ctl4device(mut device: *const libc::c_char)
|
|
-> *mut libc::c_char {
|
|
let mut ctl: *mut libc::c_char = 0 as *mut libc::c_char;
|
|
if strncmp(device, b"hw:\x00" as *const u8 as *const libc::c_char,
|
|
3 as libc::c_int as libc::c_ulong) == 0 {
|
|
ctl = strdup(device)
|
|
} else if strncmp(device,
|
|
b"plughw:\x00" as *const u8 as *const libc::c_char,
|
|
7 as libc::c_int as libc::c_ulong) == 0 {
|
|
ctl = strdup(device.offset(4 as libc::c_int as isize))
|
|
}
|
|
if !ctl.is_null() {
|
|
let mut comma: *mut libc::c_char = 0 as *mut libc::c_char;
|
|
comma = strrchr(ctl, ',' as i32);
|
|
if !comma.is_null() { *comma = '\u{0}' as i32 as libc::c_char }
|
|
} else { ctl = strdup(device) }
|
|
return ctl;
|
|
}
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn list_devices() {
|
|
let mut hints: *mut *mut libc::c_void = 0 as *mut *mut libc::c_void;
|
|
let mut n: *mut *mut libc::c_void = 0 as *mut *mut libc::c_void;
|
|
if snd_device_name_hint(-(1 as libc::c_int),
|
|
b"pcm\x00" as *const u8 as *const libc::c_char,
|
|
&mut hints) >= 0 as libc::c_int {
|
|
n = hints;
|
|
printf(b"Output devices:\n\x00" as *const u8 as *const libc::c_char);
|
|
while !(*n).is_null() {
|
|
let mut name: *mut libc::c_char =
|
|
snd_device_name_get_hint(*n,
|
|
b"NAME\x00" as *const u8 as
|
|
*const libc::c_char);
|
|
let mut desc: *mut libc::c_char =
|
|
snd_device_name_get_hint(*n,
|
|
b"DESC\x00" as *const u8 as
|
|
*const libc::c_char);
|
|
if !name.is_null() {
|
|
printf(b" %-30s\x00" as *const u8 as *const libc::c_char,
|
|
name);
|
|
}
|
|
if !desc.is_null() {
|
|
let mut s1: *mut libc::c_char =
|
|
strtok(desc,
|
|
b"\n\x00" as *const u8 as *const libc::c_char);
|
|
let mut s2: *mut libc::c_char =
|
|
strtok(0 as *mut libc::c_char,
|
|
b"\n\x00" as *const u8 as *const libc::c_char);
|
|
if !s1.is_null() {
|
|
printf(b" - %s\x00" as *const u8 as *const libc::c_char,
|
|
s1);
|
|
}
|
|
if !s2.is_null() {
|
|
printf(b" - %s\x00" as *const u8 as *const libc::c_char,
|
|
s2);
|
|
}
|
|
}
|
|
printf(b"\n\x00" as *const u8 as *const libc::c_char);
|
|
if !name.is_null() { free(name as *mut libc::c_void); }
|
|
if !desc.is_null() { free(desc as *mut libc::c_void); }
|
|
n = n.offset(1)
|
|
}
|
|
snd_device_name_free_hint(hints);
|
|
}
|
|
printf(b"\n\x00" as *const u8 as *const libc::c_char);
|
|
}
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn list_mixers(mut output_device: *const libc::c_char) {
|
|
let mut err: libc::c_int = 0;
|
|
let mut handle: *mut snd_mixer_t = 0 as *mut snd_mixer_t;
|
|
let mut sid: *mut snd_mixer_selem_id_t = 0 as *mut snd_mixer_selem_id_t;
|
|
let mut elem: *mut snd_mixer_elem_t = 0 as *mut snd_mixer_elem_t;
|
|
let mut ctl: *mut libc::c_char = ctl4device(output_device);
|
|
let mut fresh0 =
|
|
::std::vec::from_elem(0, snd_mixer_selem_id_sizeof() as usize);
|
|
sid = fresh0.as_mut_ptr() as *mut snd_mixer_selem_id_t;
|
|
memset(sid as *mut libc::c_void, 0 as libc::c_int,
|
|
snd_mixer_selem_id_sizeof());
|
|
if loglevel as libc::c_uint >= lINFO as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d listing mixers for: %s\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 12],
|
|
&[libc::c_char; 12]>(b"list_mixers\x00")).as_ptr(),
|
|
139 as libc::c_int, output_device);
|
|
}
|
|
err = snd_mixer_open(&mut handle, 0 as libc::c_int);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d open error: %s\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 12],
|
|
&[libc::c_char; 12]>(b"list_mixers\x00")).as_ptr(),
|
|
142 as libc::c_int, snd_strerror(err));
|
|
return
|
|
}
|
|
err = snd_mixer_attach(handle, ctl);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d attach error: %s\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 12],
|
|
&[libc::c_char; 12]>(b"list_mixers\x00")).as_ptr(),
|
|
146 as libc::c_int, snd_strerror(err));
|
|
snd_mixer_close(handle);
|
|
free(ctl as *mut libc::c_void);
|
|
return
|
|
}
|
|
free(ctl as *mut libc::c_void);
|
|
err =
|
|
snd_mixer_selem_register(handle, 0 as *mut snd_mixer_selem_regopt,
|
|
0 as *mut *mut snd_mixer_class_t);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d register error: %s\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 12],
|
|
&[libc::c_char; 12]>(b"list_mixers\x00")).as_ptr(),
|
|
153 as libc::c_int, snd_strerror(err));
|
|
snd_mixer_close(handle);
|
|
return
|
|
}
|
|
err = snd_mixer_load(handle);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d load error: %s\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 12],
|
|
&[libc::c_char; 12]>(b"list_mixers\x00")).as_ptr(),
|
|
158 as libc::c_int, snd_strerror(err));
|
|
snd_mixer_close(handle);
|
|
return
|
|
}
|
|
printf(b"Volume controls for %s\n\x00" as *const u8 as
|
|
*const libc::c_char, output_device);
|
|
elem = snd_mixer_first_elem(handle);
|
|
while !elem.is_null() {
|
|
if snd_mixer_selem_has_playback_volume(elem) != 0 {
|
|
snd_mixer_selem_get_id(elem, sid);
|
|
printf(b" %s\x00" as *const u8 as *const libc::c_char,
|
|
snd_mixer_selem_id_get_name(sid));
|
|
if snd_mixer_selem_id_get_index(sid) != 0 {
|
|
printf(b",%d\x00" as *const u8 as *const libc::c_char,
|
|
snd_mixer_selem_id_get_index(sid));
|
|
}
|
|
printf(b"\n\x00" as *const u8 as *const libc::c_char);
|
|
}
|
|
elem = snd_mixer_elem_next(elem)
|
|
}
|
|
printf(b"\n\x00" as *const u8 as *const libc::c_char);
|
|
snd_mixer_close(handle);
|
|
}
|
|
// LMS volume map for SqueezePlay sends values in range ~ -72..0 dB
|
|
unsafe extern "C" fn set_mixer(mut setmax: bool, mut ldB: libc::c_float,
|
|
mut rdB: libc::c_float) {
|
|
let mut err: libc::c_int = 0;
|
|
let mut nleft: libc::c_long = 0;
|
|
let mut nright: libc::c_long = 0;
|
|
if alsa.mixer_linear {
|
|
let mut lraw: libc::c_long = 0;
|
|
let mut rraw: libc::c_long = 0;
|
|
if setmax {
|
|
rraw = alsa.mixer_max;
|
|
lraw = rraw
|
|
} else {
|
|
lraw =
|
|
((if ldB > -(72 as libc::c_int) as libc::c_float {
|
|
(72 as libc::c_int as libc::c_double) +
|
|
floor(ldB as libc::c_double)
|
|
} else { 0 as libc::c_int as libc::c_double }) /
|
|
72 as libc::c_int as libc::c_double *
|
|
(alsa.mixer_max - alsa.mixer_min) as libc::c_double +
|
|
alsa.mixer_min as libc::c_double) as libc::c_long;
|
|
rraw =
|
|
((if rdB > -(72 as libc::c_int) as libc::c_float {
|
|
(72 as libc::c_int as libc::c_double) +
|
|
floor(rdB as libc::c_double)
|
|
} else { 0 as libc::c_int as libc::c_double }) /
|
|
72 as libc::c_int as libc::c_double *
|
|
(alsa.mixer_max - alsa.mixer_min) as libc::c_double +
|
|
alsa.mixer_min as libc::c_double) as libc::c_long
|
|
}
|
|
if loglevel as libc::c_uint >= lDEBUG as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d setting vol raw [%ld..%ld]\n\x00" as *const u8
|
|
as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"set_mixer\x00")).as_ptr(),
|
|
193 as libc::c_int, alsa.mixer_min, alsa.mixer_max);
|
|
}
|
|
err =
|
|
snd_mixer_selem_set_playback_volume(alsa.mixer_elem,
|
|
SND_MIXER_SCHN_FRONT_LEFT,
|
|
lraw);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d error setting left volume: %s\n\x00" as
|
|
*const u8 as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"set_mixer\x00")).as_ptr(),
|
|
195 as libc::c_int, snd_strerror(err));
|
|
}
|
|
err =
|
|
snd_mixer_selem_set_playback_volume(alsa.mixer_elem,
|
|
SND_MIXER_SCHN_FRONT_RIGHT,
|
|
rraw);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d error setting right volume: %s\n\x00" as
|
|
*const u8 as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"set_mixer\x00")).as_ptr(),
|
|
198 as libc::c_int, snd_strerror(err));
|
|
}
|
|
} else {
|
|
// set db directly
|
|
if loglevel as libc::c_uint >= lDEBUG as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d setting vol dB [%ld..%ld]\n\x00" as *const u8
|
|
as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"set_mixer\x00")).as_ptr(),
|
|
202 as libc::c_int, alsa.mixer_min, alsa.mixer_max);
|
|
}
|
|
if setmax {
|
|
// set to 0dB if available as this should be max volume for music recored at max pcm values
|
|
if alsa.mixer_max >= 0 as libc::c_int as libc::c_long &&
|
|
alsa.mixer_min <= 0 as libc::c_int as libc::c_long {
|
|
rdB = 0 as libc::c_int as libc::c_float;
|
|
ldB = rdB
|
|
} else { rdB = alsa.mixer_max as libc::c_float; ldB = rdB }
|
|
}
|
|
err =
|
|
snd_mixer_selem_set_playback_dB(alsa.mixer_elem,
|
|
SND_MIXER_SCHN_FRONT_LEFT,
|
|
(100 as libc::c_int as
|
|
libc::c_float * ldB) as
|
|
libc::c_long,
|
|
1 as libc::c_int);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d error setting left volume: %s\n\x00" as
|
|
*const u8 as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"set_mixer\x00")).as_ptr(),
|
|
212 as libc::c_int, snd_strerror(err));
|
|
}
|
|
err =
|
|
snd_mixer_selem_set_playback_dB(alsa.mixer_elem,
|
|
SND_MIXER_SCHN_FRONT_RIGHT,
|
|
(100 as libc::c_int as
|
|
libc::c_float * rdB) as
|
|
libc::c_long,
|
|
1 as libc::c_int);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d error setting right volume: %s\n\x00" as
|
|
*const u8 as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"set_mixer\x00")).as_ptr(),
|
|
215 as libc::c_int, snd_strerror(err));
|
|
}
|
|
}
|
|
err =
|
|
snd_mixer_selem_get_playback_volume(alsa.mixer_elem,
|
|
SND_MIXER_SCHN_FRONT_LEFT,
|
|
&mut nleft);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d error getting left vol: %s\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"set_mixer\x00")).as_ptr(),
|
|
220 as libc::c_int, snd_strerror(err));
|
|
}
|
|
err =
|
|
snd_mixer_selem_get_playback_volume(alsa.mixer_elem,
|
|
SND_MIXER_SCHN_FRONT_RIGHT,
|
|
&mut nright);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d error getting right vol: %s\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"set_mixer\x00")).as_ptr(),
|
|
223 as libc::c_int, snd_strerror(err));
|
|
}
|
|
if loglevel as libc::c_uint >= lDEBUG as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d %s left: %3.1fdB -> %ld right: %3.1fdB -> %ld\n\x00"
|
|
as *const u8 as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"set_mixer\x00")).as_ptr(),
|
|
226 as libc::c_int, alsa.volume_mixer_name,
|
|
ldB as libc::c_double, nleft, rdB as libc::c_double, nright);
|
|
};
|
|
}
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn set_volume(mut left: libc::c_uint,
|
|
mut right: libc::c_uint) {
|
|
let mut ldB: libc::c_float = 0.;
|
|
let mut rdB: libc::c_float = 0.;
|
|
if alsa.volume_mixer_name.is_null() {
|
|
if loglevel as libc::c_uint >= lDEBUG as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d setting internal gain left: %u right: %u\n\x00"
|
|
as *const u8 as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 11],
|
|
&[libc::c_char; 11]>(b"set_volume\x00")).as_ptr(),
|
|
233 as libc::c_int, left, right);
|
|
}
|
|
pthread_mutex_lock(&mut (*outputbuf).mutex);
|
|
output.gainL = left;
|
|
output.gainR = right;
|
|
pthread_mutex_unlock(&mut (*outputbuf).mutex);
|
|
return
|
|
} else {
|
|
pthread_mutex_lock(&mut (*outputbuf).mutex);
|
|
output.gainL = 0x10000 as libc::c_int as u32_t;
|
|
output.gainR = 0x10000 as libc::c_int as u32_t;
|
|
pthread_mutex_unlock(&mut (*outputbuf).mutex);
|
|
}
|
|
// convert 16.16 fixed point to dB
|
|
ldB =
|
|
(20 as libc::c_int as libc::c_double *
|
|
log10((left as libc::c_float / 65536.0f32) as libc::c_double)) as
|
|
libc::c_float;
|
|
rdB =
|
|
(20 as libc::c_int as libc::c_double *
|
|
log10((right as libc::c_float / 65536.0f32) as libc::c_double))
|
|
as libc::c_float;
|
|
set_mixer(0 as libc::c_int != 0, ldB, rdB);
|
|
}
|
|
unsafe extern "C" fn alsa_error_handler(mut file: *const libc::c_char,
|
|
mut line: libc::c_int,
|
|
mut function: *const libc::c_char,
|
|
mut err: libc::c_int,
|
|
mut fmt: *const libc::c_char,
|
|
mut args: ...) -> *mut libc::c_void {
|
|
let mut args_0: ::std::ffi::VaListImpl;
|
|
if loglevel as libc::c_uint >= lINFO as libc::c_int as libc::c_uint &&
|
|
err == 0 as libc::c_int ||
|
|
loglevel as libc::c_uint >= lDEBUG as libc::c_int as libc::c_uint {
|
|
fprintf(stderr,
|
|
b"%s ALSA %s:%d \x00" as *const u8 as *const libc::c_char,
|
|
logtime(), function, line);
|
|
args_0 = args.clone();
|
|
vfprintf(stderr, fmt, args_0.as_va_list());
|
|
fprintf(stderr, b"\n\x00" as *const u8 as *const libc::c_char);
|
|
fflush(stderr);
|
|
}
|
|
return 0 as *mut libc::c_void;
|
|
}
|
|
unsafe extern "C" fn alsa_close() {
|
|
let mut err: libc::c_int = 0;
|
|
err = snd_pcm_close(pcmp);
|
|
if err < 0 as libc::c_int {
|
|
if loglevel as libc::c_uint >= lINFO as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d snd_pcm_close error: %s\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 11],
|
|
&[libc::c_char; 11]>(b"alsa_close\x00")).as_ptr(),
|
|
268 as libc::c_int, snd_strerror(err));
|
|
}
|
|
};
|
|
}
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn test_open(mut device: *const libc::c_char,
|
|
mut rates: *mut libc::c_uint,
|
|
mut userdef_rates: bool) -> bool {
|
|
let mut err: libc::c_int = 0;
|
|
let mut pcm: *mut snd_pcm_t = 0 as *mut snd_pcm_t;
|
|
let mut hw_params: *mut snd_pcm_hw_params_t =
|
|
0 as *mut snd_pcm_hw_params_t;
|
|
let mut fresh1 =
|
|
::std::vec::from_elem(0, snd_pcm_hw_params_sizeof() as usize);
|
|
hw_params = fresh1.as_mut_ptr() as *mut snd_pcm_hw_params_t;
|
|
memset(hw_params as *mut libc::c_void, 0 as libc::c_int,
|
|
snd_pcm_hw_params_sizeof());
|
|
// open device
|
|
err =
|
|
snd_pcm_open(&mut pcm, device, SND_PCM_STREAM_PLAYBACK,
|
|
0 as libc::c_int);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d playback open error: %s\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"test_open\x00")).as_ptr(),
|
|
281 as libc::c_int, snd_strerror(err));
|
|
return 0 as libc::c_int != 0
|
|
}
|
|
// get max params
|
|
err = snd_pcm_hw_params_any(pcm, hw_params);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d hwparam init error: %s\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"test_open\x00")).as_ptr(),
|
|
287 as libc::c_int, snd_strerror(err));
|
|
return 0 as libc::c_int != 0
|
|
}
|
|
// find supported sample rates to enable client side resampling of non supported rates
|
|
if !userdef_rates {
|
|
let mut i: libc::c_uint = 0;
|
|
let mut ind: libc::c_uint = 0;
|
|
let mut ref_0: [libc::c_uint; 18] =
|
|
[768000 as libc::c_int as libc::c_uint,
|
|
705600 as libc::c_int as libc::c_uint,
|
|
384000 as libc::c_int as libc::c_uint,
|
|
352800 as libc::c_int as libc::c_uint,
|
|
192000 as libc::c_int as libc::c_uint,
|
|
176400 as libc::c_int as libc::c_uint,
|
|
96000 as libc::c_int as libc::c_uint,
|
|
88200 as libc::c_int as libc::c_uint,
|
|
48000 as libc::c_int as libc::c_uint,
|
|
44100 as libc::c_int as libc::c_uint,
|
|
32000 as libc::c_int as libc::c_uint,
|
|
24000 as libc::c_int as libc::c_uint,
|
|
22500 as libc::c_int as libc::c_uint,
|
|
16000 as libc::c_int as libc::c_uint,
|
|
12000 as libc::c_int as libc::c_uint,
|
|
11025 as libc::c_int as libc::c_uint,
|
|
8000 as libc::c_int as libc::c_uint,
|
|
0 as libc::c_int as libc::c_uint];
|
|
i = 0 as libc::c_int as libc::c_uint;
|
|
ind = 0 as libc::c_int as libc::c_uint;
|
|
while ref_0[i as usize] != 0 {
|
|
if snd_pcm_hw_params_test_rate(pcm, hw_params, ref_0[i as usize],
|
|
0 as libc::c_int) ==
|
|
0 as libc::c_int {
|
|
let fresh2 = ind;
|
|
ind = ind.wrapping_add(1);
|
|
*rates.offset(fresh2 as isize) = ref_0[i as usize]
|
|
}
|
|
i = i.wrapping_add(1)
|
|
}
|
|
}
|
|
err = snd_pcm_close(pcm);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d snd_pcm_close error: %s\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"test_open\x00")).as_ptr(),
|
|
304 as libc::c_int, snd_strerror(err));
|
|
return 0 as libc::c_int != 0
|
|
}
|
|
return 1 as libc::c_int != 0;
|
|
}
|
|
unsafe extern "C" fn pcm_probe(mut device: *const libc::c_char) -> bool {
|
|
let mut err: libc::c_int = 0;
|
|
let mut pcm: *mut snd_pcm_t = 0 as *mut snd_pcm_t;
|
|
err =
|
|
snd_pcm_open(&mut pcm, device, SND_PCM_STREAM_PLAYBACK,
|
|
0 as libc::c_int);
|
|
if err < 0 as libc::c_int { return 0 as libc::c_int != 0 }
|
|
err = snd_pcm_close(pcm);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d snd_pcm_close error: %s\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"pcm_probe\x00")).as_ptr(),
|
|
320 as libc::c_int, snd_strerror(err));
|
|
}
|
|
return 1 as libc::c_int != 0;
|
|
}
|
|
unsafe extern "C" fn alsa_open(mut device: *const libc::c_char,
|
|
mut sample_rate: libc::c_uint,
|
|
mut alsa_buffer: libc::c_uint,
|
|
mut alsa_period: libc::c_uint) -> libc::c_int {
|
|
let mut err: libc::c_int = 0;
|
|
let mut hw_params: *mut snd_pcm_hw_params_t =
|
|
0 as *mut snd_pcm_hw_params_t;
|
|
let mut fresh3 =
|
|
::std::vec::from_elem(0, snd_pcm_hw_params_sizeof() as usize);
|
|
hw_params = fresh3.as_mut_ptr() as *mut snd_pcm_hw_params_t;
|
|
memset(hw_params as *mut libc::c_void, 0 as libc::c_int,
|
|
snd_pcm_hw_params_sizeof());
|
|
// close if already open
|
|
if !pcmp.is_null() { alsa_close(); }
|
|
// reset params
|
|
alsa.rate = 0 as libc::c_int as libc::c_uint;
|
|
alsa.period_size = 0 as libc::c_int as snd_pcm_uframes_t;
|
|
strcpy(alsa.device.as_mut_ptr(), device);
|
|
if strlen(device) >
|
|
(128 as libc::c_int - 4 as libc::c_int - 1 as libc::c_int) as
|
|
libc::c_ulong {
|
|
logprint(b"%s %s:%d device name too long: %s\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"alsa_open\x00")).as_ptr(),
|
|
347 as libc::c_int, device);
|
|
return -(1 as libc::c_int)
|
|
}
|
|
if loglevel as libc::c_uint >= lINFO as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d opening device at: %u\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"alsa_open\x00")).as_ptr(),
|
|
351 as libc::c_int, sample_rate);
|
|
}
|
|
let mut retry: bool = false;
|
|
loop {
|
|
// open device
|
|
err =
|
|
snd_pcm_open(&mut pcmp, alsa.device.as_mut_ptr(),
|
|
SND_PCM_STREAM_PLAYBACK, 0 as libc::c_int);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d playback open error: %s\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"alsa_open\x00")).as_ptr(),
|
|
357 as libc::c_int, snd_strerror(err));
|
|
return err
|
|
}
|
|
// init params
|
|
memset(hw_params as *mut libc::c_void, 0 as libc::c_int,
|
|
snd_pcm_hw_params_sizeof());
|
|
err = snd_pcm_hw_params_any(pcmp, hw_params);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d hwparam init error: %s\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"alsa_open\x00")).as_ptr(),
|
|
364 as libc::c_int, snd_strerror(err));
|
|
return err
|
|
}
|
|
// open hw: devices without resampling, if sample rate fails try plughw: with resampling
|
|
let mut hw: bool =
|
|
strncmp(alsa.device.as_mut_ptr(),
|
|
b"hw:\x00" as *const u8 as *const libc::c_char,
|
|
3 as libc::c_int as libc::c_ulong) == 0;
|
|
retry = 0 as libc::c_int != 0;
|
|
err =
|
|
snd_pcm_hw_params_set_rate_resample(pcmp, hw_params,
|
|
!hw as libc::c_int as
|
|
libc::c_uint);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d resampling setup failed: %s\n\x00" as
|
|
*const u8 as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"alsa_open\x00")).as_ptr(),
|
|
373 as libc::c_int, snd_strerror(err));
|
|
return err
|
|
}
|
|
err =
|
|
snd_pcm_hw_params_set_rate(pcmp, hw_params, sample_rate,
|
|
0 as libc::c_int);
|
|
if err < 0 as libc::c_int {
|
|
if hw {
|
|
strcpy(alsa.device.as_mut_ptr().offset(4 as libc::c_int as
|
|
isize), device);
|
|
memcpy(alsa.device.as_mut_ptr() as *mut libc::c_void,
|
|
b"plug\x00" as *const u8 as *const libc::c_char as
|
|
*const libc::c_void,
|
|
4 as libc::c_int as libc::c_ulong);
|
|
if loglevel as libc::c_uint >=
|
|
lINFO as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d reopening device %s in plug mode as %s for resampling\n\x00"
|
|
as *const u8 as *const libc::c_char,
|
|
logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"alsa_open\x00")).as_ptr(),
|
|
381 as libc::c_int, device,
|
|
alsa.device.as_mut_ptr());
|
|
}
|
|
snd_pcm_close(pcmp);
|
|
retry = 1 as libc::c_int != 0
|
|
}
|
|
}
|
|
if !retry { break ; }
|
|
}
|
|
// set access
|
|
if !alsa.mmap ||
|
|
snd_pcm_hw_params_set_access(pcmp, hw_params,
|
|
SND_PCM_ACCESS_MMAP_INTERLEAVED) <
|
|
0 as libc::c_int {
|
|
err =
|
|
snd_pcm_hw_params_set_access(pcmp, hw_params,
|
|
SND_PCM_ACCESS_RW_INTERLEAVED);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d access type not available: %s\n\x00" as
|
|
*const u8 as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"alsa_open\x00")).as_ptr(),
|
|
392 as libc::c_int, snd_strerror(err));
|
|
return err
|
|
}
|
|
alsa.mmap = 0 as libc::c_int != 0
|
|
}
|
|
// set the sample format
|
|
let mut fmt: *mut snd_pcm_format_t =
|
|
if alsa.format as libc::c_int != 0 {
|
|
&mut alsa.format
|
|
} else { fmts.as_mut_ptr() };
|
|
loop {
|
|
if snd_pcm_hw_params_set_format(pcmp, hw_params, *fmt) >=
|
|
0 as libc::c_int {
|
|
if loglevel as libc::c_uint >=
|
|
lINFO as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d opened device %s using format: %s sample rate: %u mmap: %u\n\x00"
|
|
as *const u8 as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"alsa_open\x00")).as_ptr(),
|
|
422 as libc::c_int, alsa.device.as_mut_ptr(),
|
|
snd_pcm_format_name(*fmt), sample_rate,
|
|
alsa.mmap as libc::c_int);
|
|
}
|
|
alsa.format = *fmt;
|
|
break ;
|
|
} else {
|
|
if alsa.format as u64 != 0 {
|
|
logprint(b"%s %s:%d unable to open audio device requested format: %s\n\x00"
|
|
as *const u8 as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"alsa_open\x00")).as_ptr(),
|
|
427 as libc::c_int,
|
|
snd_pcm_format_name(alsa.format));
|
|
return -(1 as libc::c_int)
|
|
}
|
|
fmt = fmt.offset(1);
|
|
if *fmt as libc::c_int == SND_PCM_FORMAT_UNKNOWN as libc::c_int {
|
|
logprint(b"%s %s:%d unable to open audio device with any supported format\n\x00"
|
|
as *const u8 as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"alsa_open\x00")).as_ptr(),
|
|
432 as libc::c_int);
|
|
return -(1 as libc::c_int)
|
|
}
|
|
if !(*fmt as libc::c_int != SND_PCM_FORMAT_UNKNOWN as libc::c_int)
|
|
{
|
|
break ;
|
|
}
|
|
}
|
|
}
|
|
// set the output format to be used by _scale_and_pack
|
|
match alsa.format as libc::c_int {
|
|
10 => { output.format = S32_LE }
|
|
6 => { output.format = S24_LE }
|
|
32 => { output.format = S24_3LE }
|
|
2 => { output.format = S16_LE }
|
|
_ => { }
|
|
}
|
|
// set channels
|
|
err =
|
|
snd_pcm_hw_params_set_channels(pcmp, hw_params,
|
|
2 as libc::c_int as libc::c_uint);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d channel count not available: %s\n\x00" as
|
|
*const u8 as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"alsa_open\x00")).as_ptr(),
|
|
465 as libc::c_int, snd_strerror(err));
|
|
return err
|
|
}
|
|
// set period size - value of < 50 treated as period count, otherwise size in bytes
|
|
if alsa_period < 50 as libc::c_int as libc::c_uint {
|
|
let mut count: libc::c_uint = alsa_period;
|
|
err =
|
|
snd_pcm_hw_params_set_periods_near(pcmp, hw_params, &mut count,
|
|
0 as *mut libc::c_int);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d unable to set period count %s\n\x00" as
|
|
*const u8 as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"alsa_open\x00")).as_ptr(),
|
|
473 as libc::c_int, snd_strerror(err));
|
|
return err
|
|
}
|
|
} else {
|
|
let mut size: snd_pcm_uframes_t = alsa_period as snd_pcm_uframes_t;
|
|
let mut dir: libc::c_int = 0 as libc::c_int;
|
|
err =
|
|
snd_pcm_hw_params_set_period_size_near(pcmp, hw_params, &mut size,
|
|
&mut dir);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d unable to set period size %s\n\x00" as
|
|
*const u8 as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"alsa_open\x00")).as_ptr(),
|
|
480 as libc::c_int, snd_strerror(err));
|
|
return err
|
|
}
|
|
}
|
|
// set buffer size - value of < 500 treated as buffer time in ms, otherwise size in bytes
|
|
if alsa_buffer < 500 as libc::c_int as libc::c_uint {
|
|
let mut time: libc::c_uint =
|
|
alsa_buffer.wrapping_mul(1000 as libc::c_int as libc::c_uint);
|
|
let mut dir_0: libc::c_int = 0 as libc::c_int;
|
|
err =
|
|
snd_pcm_hw_params_set_buffer_time_near(pcmp, hw_params, &mut time,
|
|
&mut dir_0);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d unable to set buffer time %s\n\x00" as
|
|
*const u8 as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"alsa_open\x00")).as_ptr(),
|
|
490 as libc::c_int, snd_strerror(err));
|
|
return err
|
|
}
|
|
} else {
|
|
let mut size_0: snd_pcm_uframes_t = alsa_buffer as snd_pcm_uframes_t;
|
|
err =
|
|
snd_pcm_hw_params_set_buffer_size_near(pcmp, hw_params,
|
|
&mut size_0);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d unable to set buffer size %s\n\x00" as
|
|
*const u8 as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"alsa_open\x00")).as_ptr(),
|
|
496 as libc::c_int, snd_strerror(err));
|
|
return err
|
|
}
|
|
}
|
|
// get period_size
|
|
err =
|
|
snd_pcm_hw_params_get_period_size(hw_params, &mut alsa.period_size,
|
|
0 as *mut libc::c_int);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d unable to get period size: %s\n\x00" as *const u8
|
|
as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"alsa_open\x00")).as_ptr(),
|
|
503 as libc::c_int, snd_strerror(err));
|
|
return err
|
|
}
|
|
// get buffer_size
|
|
err = snd_pcm_hw_params_get_buffer_size(hw_params, &mut alsa.buffer_size);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d unable to get buffer size: %s\n\x00" as *const u8
|
|
as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"alsa_open\x00")).as_ptr(),
|
|
509 as libc::c_int, snd_strerror(err));
|
|
return err
|
|
}
|
|
if loglevel as libc::c_uint >= lINFO as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d buffer: %u period: %u -> buffer size: %u period size: %u\n\x00"
|
|
as *const u8 as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"alsa_open\x00")).as_ptr(),
|
|
513 as libc::c_int, alsa_buffer, alsa_period,
|
|
alsa.buffer_size, alsa.period_size);
|
|
}
|
|
// ensure we have two buffer sizes of samples before starting output
|
|
output.start_frames =
|
|
alsa.buffer_size.wrapping_mul(2 as libc::c_int as libc::c_ulong) as
|
|
libc::c_uint;
|
|
// create an intermediate buffer for non mmap case for all but NATIVE_FORMAT
|
|
// this is used to pack samples into the output format before calling writei
|
|
if !alsa.mmap && alsa.write_buf.is_null() &&
|
|
alsa.format as libc::c_int != SND_PCM_FORMAT_S32_LE as libc::c_int
|
|
{
|
|
alsa.write_buf =
|
|
malloc(alsa.buffer_size.wrapping_mul(8 as libc::c_int as
|
|
libc::c_ulong)) as
|
|
*mut u8_t;
|
|
if alsa.write_buf.is_null() {
|
|
logprint(b"%s %s:%d unable to malloc write_buf\n\x00" as *const u8
|
|
as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"alsa_open\x00")).as_ptr(),
|
|
523 as libc::c_int);
|
|
return -(1 as libc::c_int)
|
|
}
|
|
}
|
|
// set params
|
|
err = snd_pcm_hw_params(pcmp, hw_params);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d unable to set hw params: %s\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 10],
|
|
&[libc::c_char; 10]>(b"alsa_open\x00")).as_ptr(),
|
|
530 as libc::c_int, snd_strerror(err));
|
|
return err
|
|
}
|
|
// dump info
|
|
if loglevel as libc::c_uint == lSDEBUG as libc::c_int as libc::c_uint {
|
|
static mut debug_output: *mut snd_output_t =
|
|
0 as *const snd_output_t as *mut snd_output_t;
|
|
snd_output_stdio_attach(&mut debug_output, stderr, 0 as libc::c_int);
|
|
snd_pcm_dump(pcmp, debug_output);
|
|
}
|
|
// this indicates we have opened the device ok
|
|
alsa.rate = sample_rate;
|
|
return 0 as libc::c_int;
|
|
}
|
|
unsafe extern "C" fn _write_frames(mut out_frames: frames_t,
|
|
mut silence: bool, mut gainL: s32_t,
|
|
mut gainR: s32_t, mut cross_gain_in: s32_t,
|
|
mut cross_gain_out: s32_t,
|
|
mut cross_ptr: *mut *mut s32_t)
|
|
-> libc::c_int {
|
|
let mut areas: *const snd_pcm_channel_area_t =
|
|
0 as *const snd_pcm_channel_area_t;
|
|
let mut offset: snd_pcm_uframes_t = 0;
|
|
let mut outputptr: *mut libc::c_void = 0 as *mut libc::c_void;
|
|
let mut inputptr: *mut s32_t = 0 as *mut s32_t;
|
|
let mut err: libc::c_int = 0;
|
|
if alsa.mmap {
|
|
let mut alsa_frames: snd_pcm_uframes_t =
|
|
out_frames as snd_pcm_uframes_t;
|
|
snd_pcm_avail_update(pcmp);
|
|
err =
|
|
snd_pcm_mmap_begin(pcmp, &mut areas, &mut offset,
|
|
&mut alsa_frames);
|
|
if err < 0 as libc::c_int {
|
|
if loglevel as libc::c_uint >=
|
|
lWARN as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d error from mmap_begin: %s\n\x00" as
|
|
*const u8 as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 14],
|
|
&[libc::c_char; 14]>(b"_write_frames\x00")).as_ptr(),
|
|
565 as libc::c_int, snd_strerror(err));
|
|
}
|
|
return -(1 as libc::c_int)
|
|
}
|
|
out_frames = alsa_frames as frames_t
|
|
}
|
|
if !silence {
|
|
// applying cross fade is delayed until this point as mmap_begin can change out_frames
|
|
if output.fade as libc::c_uint ==
|
|
FADE_ACTIVE as libc::c_int as libc::c_uint &&
|
|
output.fade_dir as libc::c_uint ==
|
|
FADE_CROSS as libc::c_int as libc::c_uint &&
|
|
!(*cross_ptr).is_null() {
|
|
_apply_cross(outputbuf, out_frames, cross_gain_in, cross_gain_out,
|
|
cross_ptr);
|
|
}
|
|
}
|
|
inputptr =
|
|
if silence as libc::c_int != 0 {
|
|
silencebuf
|
|
} else { (*outputbuf).readp } as *mut s32_t;
|
|
if alsa.mmap as libc::c_int != 0 ||
|
|
alsa.format as libc::c_int != SND_PCM_FORMAT_S32_LE as libc::c_int
|
|
{
|
|
outputptr =
|
|
if alsa.mmap as libc::c_int != 0 {
|
|
(*areas.offset(0 as libc::c_int as
|
|
isize)).addr.offset(((*areas.offset(0 as
|
|
libc::c_int
|
|
as
|
|
isize)).first
|
|
as
|
|
libc::c_ulong).wrapping_add(offset.wrapping_mul((*areas.offset(0
|
|
as
|
|
libc::c_int
|
|
as
|
|
isize)).step
|
|
as
|
|
libc::c_ulong)).wrapping_div(8
|
|
as
|
|
libc::c_int
|
|
as
|
|
libc::c_ulong)
|
|
as isize)
|
|
} else { alsa.write_buf as *mut libc::c_void };
|
|
_scale_and_pack_frames(outputptr, inputptr, out_frames, gainL, gainR,
|
|
output.format);
|
|
} else {
|
|
outputptr = inputptr as *mut libc::c_void;
|
|
if !silence {
|
|
if gainL != 0x10000 as libc::c_int ||
|
|
gainR != 0x10000 as libc::c_int {
|
|
_apply_gain(outputbuf, out_frames, gainL, gainR);
|
|
}
|
|
}
|
|
}
|
|
if alsa.mmap {
|
|
let mut w: snd_pcm_sframes_t =
|
|
snd_pcm_mmap_commit(pcmp, offset,
|
|
out_frames as snd_pcm_uframes_t);
|
|
if w < 0 as libc::c_int as libc::c_long ||
|
|
w != out_frames as libc::c_long {
|
|
if loglevel as libc::c_uint >=
|
|
lWARN as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d mmap_commit error\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 14],
|
|
&[libc::c_char; 14]>(b"_write_frames\x00")).as_ptr(),
|
|
615 as libc::c_int);
|
|
}
|
|
return -(1 as libc::c_int)
|
|
}
|
|
} else {
|
|
let mut w_0: snd_pcm_sframes_t =
|
|
snd_pcm_writei(pcmp, outputptr, out_frames as snd_pcm_uframes_t);
|
|
if w_0 < 0 as libc::c_int as libc::c_long {
|
|
//if (w != -EAGAIN && ((err = snd_pcm_recover(pcmp, w, 1)) < 0)) {
|
|
err = snd_pcm_recover(pcmp, w_0 as libc::c_int, 1 as libc::c_int);
|
|
if err < 0 as libc::c_int {
|
|
static mut recover_count: libc::c_uint =
|
|
0 as libc::c_int as libc::c_uint;
|
|
if loglevel as libc::c_uint >=
|
|
lWARN as libc::c_int as libc::c_uint {
|
|
recover_count = recover_count.wrapping_add(1);
|
|
logprint(b"%s %s:%d recover failed: %s [%u]\n\x00" as
|
|
*const u8 as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 14],
|
|
&[libc::c_char; 14]>(b"_write_frames\x00")).as_ptr(),
|
|
626 as libc::c_int, snd_strerror(err),
|
|
recover_count);
|
|
}
|
|
if recover_count >= 10 as libc::c_int as libc::c_uint {
|
|
recover_count = 0 as libc::c_int as libc::c_uint;
|
|
alsa_close();
|
|
pcmp = 0 as *mut snd_pcm_t
|
|
}
|
|
}
|
|
return -(1 as libc::c_int)
|
|
} else {
|
|
if w_0 != out_frames as libc::c_long {
|
|
if loglevel as libc::c_uint >=
|
|
lWARN as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d writei only wrote %u of %u\n\x00" as
|
|
*const u8 as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 14],
|
|
&[libc::c_char; 14]>(b"_write_frames\x00")).as_ptr(),
|
|
636 as libc::c_int, w_0, out_frames);
|
|
}
|
|
}
|
|
out_frames = w_0 as frames_t
|
|
}
|
|
}
|
|
return out_frames as libc::c_int;
|
|
}
|
|
unsafe extern "C" fn output_thread(mut arg: *mut libc::c_void)
|
|
-> *mut libc::c_void {
|
|
let mut start: bool = 1 as libc::c_int != 0;
|
|
let mut output_off: bool =
|
|
output.state as libc::c_int == OUTPUT_OFF as libc::c_int;
|
|
let mut probe_device: bool = !arg.is_null();
|
|
let mut err: libc::c_int = 0;
|
|
while running {
|
|
// disabled output - player is off
|
|
while output_off {
|
|
usleep(100000 as libc::c_int as __useconds_t);
|
|
pthread_mutex_lock(&mut (*outputbuf).mutex);
|
|
output_off =
|
|
output.state as libc::c_int == OUTPUT_OFF as libc::c_int;
|
|
pthread_mutex_unlock(&mut (*outputbuf).mutex);
|
|
if !running { return 0 as *mut libc::c_void }
|
|
}
|
|
// wait until device returns - to allow usb audio devices to be turned off
|
|
if probe_device {
|
|
while !pcm_probe(output.device) {
|
|
if loglevel as libc::c_uint >=
|
|
lDEBUG as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d waiting for device %s to return\n\x00"
|
|
as *const u8 as *const libc::c_char,
|
|
logtime(),
|
|
(*::std::mem::transmute::<&[u8; 14],
|
|
&[libc::c_char; 14]>(b"output_thread\x00")).as_ptr(),
|
|
665 as libc::c_int, output.device);
|
|
}
|
|
sleep(5 as libc::c_int as libc::c_uint);
|
|
}
|
|
probe_device = 0 as libc::c_int != 0
|
|
}
|
|
if pcmp.is_null() || alsa.rate != output.current_sample_rate {
|
|
if loglevel as libc::c_uint >=
|
|
lINFO as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d open output device: %s\n\x00" as *const u8
|
|
as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 14],
|
|
&[libc::c_char; 14]>(b"output_thread\x00")).as_ptr(),
|
|
687 as libc::c_int, output.device);
|
|
}
|
|
pthread_mutex_lock(&mut (*outputbuf).mutex);
|
|
// FIXME - some alsa hardware requires opening twice for a new sample rate to work
|
|
// this is a workaround which should be removed
|
|
if alsa.reopen {
|
|
alsa_open(output.device, output.current_sample_rate,
|
|
output.buffer, output.period);
|
|
}
|
|
if alsa_open(output.device, output.current_sample_rate,
|
|
output.buffer, output.period) != 0 {
|
|
output.error_opening = 1 as libc::c_int != 0;
|
|
pthread_mutex_unlock(&mut (*outputbuf).mutex);
|
|
sleep(5 as libc::c_int as libc::c_uint);
|
|
continue ;
|
|
} else {
|
|
output.error_opening = 0 as libc::c_int != 0;
|
|
start = 1 as libc::c_int != 0;
|
|
pthread_mutex_unlock(&mut (*outputbuf).mutex);
|
|
}
|
|
}
|
|
let mut state: snd_pcm_state_t = snd_pcm_state(pcmp);
|
|
if state as libc::c_uint ==
|
|
SND_PCM_STATE_XRUN as libc::c_int as libc::c_uint {
|
|
if loglevel as libc::c_uint >=
|
|
lINFO as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d XRUN\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 14],
|
|
&[libc::c_char; 14]>(b"output_thread\x00")).as_ptr(),
|
|
717 as libc::c_int);
|
|
}
|
|
err =
|
|
snd_pcm_recover(pcmp, -(32 as libc::c_int), 1 as libc::c_int);
|
|
if err < 0 as libc::c_int {
|
|
if loglevel as libc::c_uint >=
|
|
lINFO as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d XRUN recover failed: %s\n\x00" as
|
|
*const u8 as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 14],
|
|
&[libc::c_char; 14]>(b"output_thread\x00")).as_ptr(),
|
|
719 as libc::c_int, snd_strerror(err));
|
|
}
|
|
}
|
|
start = 1 as libc::c_int != 0
|
|
} else {
|
|
if state as libc::c_uint ==
|
|
SND_PCM_STATE_SUSPENDED as libc::c_int as libc::c_uint {
|
|
err =
|
|
snd_pcm_recover(pcmp, -(86 as libc::c_int),
|
|
1 as libc::c_int);
|
|
if err < 0 as libc::c_int {
|
|
if loglevel as libc::c_uint >=
|
|
lINFO as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d SUSPEND recover failed: %s\n\x00"
|
|
as *const u8 as *const libc::c_char,
|
|
logtime(),
|
|
(*::std::mem::transmute::<&[u8; 14],
|
|
&[libc::c_char; 14]>(b"output_thread\x00")).as_ptr(),
|
|
725 as libc::c_int, snd_strerror(err));
|
|
}
|
|
}
|
|
} else if state as libc::c_uint ==
|
|
SND_PCM_STATE_DISCONNECTED as libc::c_int as
|
|
libc::c_uint {
|
|
if loglevel as libc::c_uint >=
|
|
lINFO as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d Device %s no longer available\n\x00"
|
|
as *const u8 as *const libc::c_char,
|
|
logtime(),
|
|
(*::std::mem::transmute::<&[u8; 14],
|
|
&[libc::c_char; 14]>(b"output_thread\x00")).as_ptr(),
|
|
728 as libc::c_int, output.device);
|
|
}
|
|
alsa_close();
|
|
pcmp = 0 as *mut snd_pcm_t;
|
|
probe_device = 1 as libc::c_int != 0;
|
|
continue ;
|
|
}
|
|
let mut avail: snd_pcm_sframes_t = snd_pcm_avail_update(pcmp);
|
|
if avail < 0 as libc::c_int as libc::c_long {
|
|
err =
|
|
snd_pcm_recover(pcmp, avail as libc::c_int,
|
|
1 as libc::c_int);
|
|
if err < 0 as libc::c_int {
|
|
if err == -(19 as libc::c_int) {
|
|
if loglevel as libc::c_uint >=
|
|
lINFO as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d Device %s no longer available\n\x00"
|
|
as *const u8 as *const libc::c_char,
|
|
logtime(),
|
|
(*::std::mem::transmute::<&[u8; 14],
|
|
&[libc::c_char; 14]>(b"output_thread\x00")).as_ptr(),
|
|
740 as libc::c_int, output.device);
|
|
}
|
|
alsa_close();
|
|
pcmp = 0 as *mut snd_pcm_t;
|
|
probe_device = 1 as libc::c_int != 0;
|
|
continue ;
|
|
} else if loglevel as libc::c_uint >=
|
|
lWARN as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d recover failed: %s\n\x00" as
|
|
*const u8 as *const libc::c_char,
|
|
logtime(),
|
|
(*::std::mem::transmute::<&[u8; 14],
|
|
&[libc::c_char; 14]>(b"output_thread\x00")).as_ptr(),
|
|
746 as libc::c_int, snd_strerror(err));
|
|
}
|
|
}
|
|
start = 1 as libc::c_int != 0
|
|
} else if (avail as libc::c_ulong) < alsa.period_size {
|
|
if start {
|
|
if alsa.mmap as libc::c_int != 0 &&
|
|
{
|
|
err = snd_pcm_start(pcmp);
|
|
(err) < 0 as libc::c_int
|
|
} {
|
|
err = snd_pcm_recover(pcmp, err, 1 as libc::c_int);
|
|
if !(err < 0 as libc::c_int) { continue ; }
|
|
if err == -(19 as libc::c_int) {
|
|
if loglevel as libc::c_uint >=
|
|
lINFO as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d Device %s no longer available\n\x00"
|
|
as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 14],
|
|
&[libc::c_char; 14]>(b"output_thread\x00")).as_ptr(),
|
|
757 as libc::c_int, output.device);
|
|
}
|
|
alsa_close();
|
|
pcmp = 0 as *mut snd_pcm_t;
|
|
probe_device = 1 as libc::c_int != 0
|
|
} else {
|
|
if loglevel as libc::c_uint >=
|
|
lINFO as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d start error: %s\n\x00" as
|
|
*const u8 as *const libc::c_char,
|
|
logtime(),
|
|
(*::std::mem::transmute::<&[u8; 14],
|
|
&[libc::c_char; 14]>(b"output_thread\x00")).as_ptr(),
|
|
763 as libc::c_int,
|
|
snd_strerror(err));
|
|
}
|
|
usleep(10000 as libc::c_int as __useconds_t);
|
|
}
|
|
} else { start = 0 as libc::c_int != 0 }
|
|
} else {
|
|
usleep(10000 as libc::c_int as __useconds_t);
|
|
err = snd_pcm_wait(pcmp, 1000 as libc::c_int);
|
|
if err <= 0 as libc::c_int {
|
|
if err == 0 as libc::c_int {
|
|
if loglevel as libc::c_uint >=
|
|
lINFO as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d pcm wait timeout\n\x00" as
|
|
*const u8 as *const libc::c_char,
|
|
logtime(),
|
|
(*::std::mem::transmute::<&[u8; 14],
|
|
&[libc::c_char; 14]>(b"output_thread\x00")).as_ptr(),
|
|
773 as libc::c_int);
|
|
}
|
|
}
|
|
err = snd_pcm_recover(pcmp, err, 1 as libc::c_int);
|
|
if err < 0 as libc::c_int {
|
|
if loglevel as libc::c_uint >=
|
|
lINFO as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d pcm wait error: %s\n\x00"
|
|
as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 14],
|
|
&[libc::c_char; 14]>(b"output_thread\x00")).as_ptr(),
|
|
776 as libc::c_int,
|
|
snd_strerror(err));
|
|
}
|
|
}
|
|
start = 1 as libc::c_int != 0
|
|
}
|
|
}
|
|
} else {
|
|
// restrict avail to within sensible limits as alsa drivers can return erroneous large values
|
|
// in writei mode restrict to period_size due to size of write_buf
|
|
if alsa.mmap {
|
|
avail =
|
|
if (avail as libc::c_ulong) < alsa.buffer_size {
|
|
avail as libc::c_ulong
|
|
} else { alsa.buffer_size } as snd_pcm_sframes_t
|
|
} else {
|
|
avail =
|
|
if (avail as libc::c_ulong) < alsa.period_size {
|
|
avail as libc::c_ulong
|
|
} else { alsa.period_size } as snd_pcm_sframes_t
|
|
}
|
|
// avoid spinning in cases where wait returns but no bytes available (seen with pulse audio)
|
|
if avail == 0 as libc::c_int as libc::c_long {
|
|
if loglevel as libc::c_uint >=
|
|
lSDEBUG as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d avail 0 - sleeping\n\x00" as
|
|
*const u8 as *const libc::c_char,
|
|
logtime(),
|
|
(*::std::mem::transmute::<&[u8; 14],
|
|
&[libc::c_char; 14]>(b"output_thread\x00")).as_ptr(),
|
|
794 as libc::c_int);
|
|
}
|
|
usleep(10000 as libc::c_int as __useconds_t);
|
|
} else {
|
|
pthread_mutex_lock(&mut (*outputbuf).mutex);
|
|
// turn off if requested
|
|
if output.state as libc::c_int ==
|
|
OUTPUT_OFF as libc::c_int {
|
|
pthread_mutex_unlock(&mut (*outputbuf).mutex);
|
|
if loglevel as libc::c_uint >=
|
|
lINFO as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d disabling output\n\x00" as
|
|
*const u8 as *const libc::c_char,
|
|
logtime(),
|
|
(*::std::mem::transmute::<&[u8; 14],
|
|
&[libc::c_char; 14]>(b"output_thread\x00")).as_ptr(),
|
|
804 as libc::c_int);
|
|
}
|
|
alsa_close();
|
|
pcmp = 0 as *mut snd_pcm_t;
|
|
output_off = 1 as libc::c_int != 0
|
|
} else {
|
|
// measure output delay
|
|
let mut delay: snd_pcm_sframes_t = 0;
|
|
err = snd_pcm_delay(pcmp, &mut delay);
|
|
if err < 0 as libc::c_int {
|
|
if err == -(32 as libc::c_int) {
|
|
// EPIPE indicates underrun - attempt to recover
|
|
pthread_mutex_unlock(&mut (*outputbuf).mutex);
|
|
continue ;
|
|
} else if err == -(5 as libc::c_int) {
|
|
// EIO can occur with non existant pulse server
|
|
pthread_mutex_unlock(&mut (*outputbuf).mutex);
|
|
if loglevel as libc::c_uint >=
|
|
lSDEBUG as libc::c_int as libc::c_uint
|
|
{
|
|
logprint(b"%s %s:%d snd_pcm_delay returns: EIO - sleeping\n\x00"
|
|
as *const u8 as
|
|
*const libc::c_char,
|
|
logtime(),
|
|
(*::std::mem::transmute::<&[u8; 14],
|
|
&[libc::c_char; 14]>(b"output_thread\x00")).as_ptr(),
|
|
833 as libc::c_int);
|
|
}
|
|
usleep(100000 as libc::c_int as __useconds_t);
|
|
continue ;
|
|
} else if loglevel as libc::c_uint >=
|
|
lDEBUG as libc::c_int as
|
|
libc::c_uint {
|
|
logprint(b"%s %s:%d snd_pcm_delay returns: %d\n\x00"
|
|
as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 14],
|
|
&[libc::c_char; 14]>(b"output_thread\x00")).as_ptr(),
|
|
837 as libc::c_int, err);
|
|
}
|
|
} else {
|
|
output.device_frames = delay as libc::c_uint;
|
|
output.updated = gettime_ms();
|
|
output.frames_played_dmp = output.frames_played
|
|
}
|
|
// process frames
|
|
let mut wrote: frames_t =
|
|
_output_frames(avail as frames_t);
|
|
pthread_mutex_unlock(&mut (*outputbuf).mutex);
|
|
// some output devices such as alsa null refuse any data, avoid spinning
|
|
if wrote == 0 {
|
|
if loglevel as libc::c_uint >=
|
|
lSDEBUG as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d wrote 0 - sleeping\n\x00"
|
|
as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 14],
|
|
&[libc::c_char; 14]>(b"output_thread\x00")).as_ptr(),
|
|
852 as libc::c_int);
|
|
}
|
|
usleep(10000 as libc::c_int as __useconds_t);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return 0 as *mut libc::c_void;
|
|
}
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn mixer_init_alsa(mut device: *const libc::c_char,
|
|
mut mixer: *const libc::c_char,
|
|
mut mixer_index: libc::c_int)
|
|
-> libc::c_int {
|
|
let mut err: libc::c_int = 0;
|
|
let mut sid: *mut snd_mixer_selem_id_t = 0 as *mut snd_mixer_selem_id_t;
|
|
err = snd_mixer_open(&mut alsa.mixer_handle, 0 as libc::c_int);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d open error: %s\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 16],
|
|
&[libc::c_char; 16]>(b"mixer_init_alsa\x00")).as_ptr(),
|
|
865 as libc::c_int, snd_strerror(err));
|
|
return -(1 as libc::c_int)
|
|
}
|
|
err = snd_mixer_attach(alsa.mixer_handle, device);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d attach error: %s\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 16],
|
|
&[libc::c_char; 16]>(b"mixer_init_alsa\x00")).as_ptr(),
|
|
869 as libc::c_int, snd_strerror(err));
|
|
snd_mixer_close(alsa.mixer_handle);
|
|
return -(1 as libc::c_int)
|
|
}
|
|
err =
|
|
snd_mixer_selem_register(alsa.mixer_handle,
|
|
0 as *mut snd_mixer_selem_regopt,
|
|
0 as *mut *mut snd_mixer_class_t);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d register error: %s\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 16],
|
|
&[libc::c_char; 16]>(b"mixer_init_alsa\x00")).as_ptr(),
|
|
874 as libc::c_int, snd_strerror(err));
|
|
snd_mixer_close(alsa.mixer_handle);
|
|
return -(1 as libc::c_int)
|
|
}
|
|
err = snd_mixer_load(alsa.mixer_handle);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d load error: %s\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 16],
|
|
&[libc::c_char; 16]>(b"mixer_init_alsa\x00")).as_ptr(),
|
|
879 as libc::c_int, snd_strerror(err));
|
|
snd_mixer_close(alsa.mixer_handle);
|
|
return -(1 as libc::c_int)
|
|
}
|
|
let mut fresh4 =
|
|
::std::vec::from_elem(0, snd_mixer_selem_id_sizeof() as usize);
|
|
sid = fresh4.as_mut_ptr() as *mut snd_mixer_selem_id_t;
|
|
memset(sid as *mut libc::c_void, 0 as libc::c_int,
|
|
snd_mixer_selem_id_sizeof());
|
|
snd_mixer_selem_id_set_index(sid, mixer_index as libc::c_uint);
|
|
snd_mixer_selem_id_set_name(sid, mixer);
|
|
alsa.mixer_elem = snd_mixer_find_selem(alsa.mixer_handle, sid);
|
|
if alsa.mixer_elem.is_null() {
|
|
logprint(b"%s %s:%d error find selem %s\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 16],
|
|
&[libc::c_char; 16]>(b"mixer_init_alsa\x00")).as_ptr(),
|
|
889 as libc::c_int, alsa.mixer_handle);
|
|
snd_mixer_close(alsa.mixer_handle);
|
|
return -(1 as libc::c_int)
|
|
}
|
|
if snd_mixer_selem_has_playback_switch(alsa.mixer_elem) != 0 {
|
|
snd_mixer_selem_set_playback_switch_all(alsa.mixer_elem,
|
|
1 as libc::c_int);
|
|
// unmute
|
|
}
|
|
err =
|
|
snd_mixer_selem_get_playback_dB_range(alsa.mixer_elem,
|
|
&mut alsa.mixer_min,
|
|
&mut alsa.mixer_max);
|
|
if err < 0 as libc::c_int ||
|
|
alsa.mixer_max - alsa.mixer_min <
|
|
1000 as libc::c_int as libc::c_long ||
|
|
alsa.mixer_linear as libc::c_int != 0 {
|
|
alsa.mixer_linear = 1 as libc::c_int != 0;
|
|
// unable to get db range or range is less than 10dB - ignore and set using raw values
|
|
err =
|
|
snd_mixer_selem_get_playback_volume_range(alsa.mixer_elem,
|
|
&mut alsa.mixer_min,
|
|
&mut alsa.mixer_max);
|
|
if err < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d Unable to get volume raw range\n\x00" as
|
|
*const u8 as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 16],
|
|
&[libc::c_char; 16]>(b"mixer_init_alsa\x00")).as_ptr(),
|
|
905 as libc::c_int);
|
|
return -(1 as libc::c_int)
|
|
}
|
|
}
|
|
return 0 as libc::c_int;
|
|
}
|
|
static mut thread: pthread_t = 0;
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn output_init_alsa(mut level: log_level,
|
|
mut device: *const libc::c_char,
|
|
mut output_buf_size: libc::c_uint,
|
|
mut params: *mut libc::c_char,
|
|
mut rates: *mut libc::c_uint,
|
|
mut rate_delay: libc::c_uint,
|
|
mut rt_priority: libc::c_uint,
|
|
mut idle: libc::c_uint,
|
|
mut mixer_device: *mut libc::c_char,
|
|
mut volume_mixer: *mut libc::c_char,
|
|
mut mixer_unmute: bool,
|
|
mut mixer_linear: bool) {
|
|
let mut alsa_buffer: libc::c_uint = 40 as libc::c_int as libc::c_uint;
|
|
let mut alsa_period: libc::c_uint = 4 as libc::c_int as libc::c_uint;
|
|
let mut alsa_sample_fmt: *mut libc::c_char = 0 as *mut libc::c_char;
|
|
let mut alsa_mmap: bool = 1 as libc::c_int != 0;
|
|
let mut alsa_reopen: bool = 0 as libc::c_int != 0;
|
|
let mut volume_mixer_name: *mut libc::c_char =
|
|
next_param(volume_mixer, ',' as i32 as libc::c_char);
|
|
let mut volume_mixer_index: *mut libc::c_char =
|
|
next_param(0 as *mut libc::c_char, ',' as i32 as libc::c_char);
|
|
let mut t: *mut libc::c_char =
|
|
next_param(params, ':' as i32 as libc::c_char);
|
|
let mut c: *mut libc::c_char =
|
|
next_param(0 as *mut libc::c_char, ':' as i32 as libc::c_char);
|
|
let mut s: *mut libc::c_char =
|
|
next_param(0 as *mut libc::c_char, ':' as i32 as libc::c_char);
|
|
let mut m: *mut libc::c_char =
|
|
next_param(0 as *mut libc::c_char, ':' as i32 as libc::c_char);
|
|
let mut r: *mut libc::c_char =
|
|
next_param(0 as *mut libc::c_char, ':' as i32 as libc::c_char);
|
|
if !t.is_null() { alsa_buffer = atoi(t) as libc::c_uint }
|
|
if !c.is_null() { alsa_period = atoi(c) as libc::c_uint }
|
|
if !s.is_null() { alsa_sample_fmt = s }
|
|
if !m.is_null() { alsa_mmap = atoi(m) != 0 }
|
|
if !r.is_null() { alsa_reopen = atoi(r) != 0 }
|
|
loglevel = level;
|
|
if loglevel as libc::c_uint >= lINFO as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d init output\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 17],
|
|
&[libc::c_char; 17]>(b"output_init_alsa\x00")).as_ptr(),
|
|
939 as libc::c_int);
|
|
}
|
|
memset(&mut output as *mut outputstate as *mut libc::c_void,
|
|
0 as libc::c_int,
|
|
::std::mem::size_of::<outputstate>() as libc::c_ulong);
|
|
alsa.mmap = alsa_mmap;
|
|
alsa.write_buf = 0 as *mut u8_t;
|
|
alsa.format = SND_PCM_FORMAT_S8;
|
|
alsa.reopen = alsa_reopen;
|
|
alsa.mixer_handle = 0 as *mut snd_mixer_t;
|
|
alsa.ctl = ctl4device(device);
|
|
alsa.mixer_ctl =
|
|
if !mixer_device.is_null() {
|
|
ctl4device(mixer_device)
|
|
} else { alsa.ctl };
|
|
alsa.volume_mixer_name = volume_mixer_name;
|
|
alsa.mixer_linear = mixer_linear;
|
|
output.format = S32_LE;
|
|
output.buffer = alsa_buffer;
|
|
output.period = alsa_period;
|
|
output.start_frames = 0 as libc::c_int as libc::c_uint;
|
|
output.write_cb =
|
|
Some(_write_frames as
|
|
unsafe extern "C" fn(_: frames_t, _: bool, _: s32_t,
|
|
_: s32_t, _: s32_t, _: s32_t,
|
|
_: *mut *mut s32_t) -> libc::c_int);
|
|
output.rate_delay = rate_delay;
|
|
if !alsa_sample_fmt.is_null() {
|
|
if strcmp(alsa_sample_fmt,
|
|
b"32\x00" as *const u8 as *const libc::c_char) == 0 {
|
|
alsa.format = SND_PCM_FORMAT_S32_LE
|
|
}
|
|
if strcmp(alsa_sample_fmt,
|
|
b"24\x00" as *const u8 as *const libc::c_char) == 0 {
|
|
alsa.format = SND_PCM_FORMAT_S24_LE
|
|
}
|
|
if strcmp(alsa_sample_fmt,
|
|
b"24_3\x00" as *const u8 as *const libc::c_char) == 0 {
|
|
alsa.format = SND_PCM_FORMAT_S24_3LE
|
|
}
|
|
if strcmp(alsa_sample_fmt,
|
|
b"16\x00" as *const u8 as *const libc::c_char) == 0 {
|
|
alsa.format = SND_PCM_FORMAT_S16_LE
|
|
}
|
|
}
|
|
if loglevel as libc::c_uint >= lINFO as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d requested alsa_buffer: %u alsa_period: %u format: %s mmap: %u\n\x00"
|
|
as *const u8 as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 17],
|
|
&[libc::c_char; 17]>(b"output_init_alsa\x00")).as_ptr(),
|
|
979 as libc::c_int, output.buffer, output.period,
|
|
if !alsa_sample_fmt.is_null() {
|
|
alsa_sample_fmt as *const libc::c_char
|
|
} else { b"any\x00" as *const u8 as *const libc::c_char },
|
|
alsa.mmap as libc::c_int);
|
|
}
|
|
snd_lib_error_set_handler(::std::mem::transmute::<Option<unsafe extern "C" fn(_:
|
|
*const libc::c_char,
|
|
_:
|
|
libc::c_int,
|
|
_:
|
|
*const libc::c_char,
|
|
_:
|
|
libc::c_int,
|
|
_:
|
|
*const libc::c_char,
|
|
_:
|
|
...)
|
|
->
|
|
*mut libc::c_void>,
|
|
snd_lib_error_handler_t>(Some(alsa_error_handler
|
|
as
|
|
unsafe extern "C" fn(_:
|
|
*const libc::c_char,
|
|
_:
|
|
libc::c_int,
|
|
_:
|
|
*const libc::c_char,
|
|
_:
|
|
libc::c_int,
|
|
_:
|
|
*const libc::c_char,
|
|
_:
|
|
...)
|
|
->
|
|
*mut libc::c_void)));
|
|
output_init_common(level, device, output_buf_size, rates, idle);
|
|
if !volume_mixer_name.is_null() {
|
|
if mixer_init_alsa(alsa.mixer_ctl, alsa.volume_mixer_name,
|
|
(if !volume_mixer_index.is_null() {
|
|
atoi(volume_mixer_index)
|
|
} else { 0 as libc::c_int })) < 0 as libc::c_int {
|
|
logprint(b"%s %s:%d Initialization of mixer failed, reverting to software volume\n\x00"
|
|
as *const u8 as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 17],
|
|
&[libc::c_char; 17]>(b"output_init_alsa\x00")).as_ptr(),
|
|
989 as libc::c_int);
|
|
alsa.mixer_handle = 0 as *mut snd_mixer_t;
|
|
alsa.volume_mixer_name = 0 as *const libc::c_char
|
|
}
|
|
}
|
|
if mixer_unmute as libc::c_int != 0 && !alsa.volume_mixer_name.is_null() {
|
|
set_mixer(1 as libc::c_int != 0, 0 as libc::c_int as libc::c_float,
|
|
0 as libc::c_int as libc::c_float);
|
|
alsa.volume_mixer_name = 0 as *const libc::c_char
|
|
}
|
|
// RT linux - aim to avoid pagefaults by locking memory:
|
|
// https://rt.wiki.kernel.org/index.php/Threaded_RT-application_with_memory_locking_and_stack_handling_example
|
|
if mlockall(1 as libc::c_int | 2 as libc::c_int) == -(1 as libc::c_int) {
|
|
if loglevel as libc::c_uint >= lINFO as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d unable to lock memory: %s\n\x00" as *const u8
|
|
as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 17],
|
|
&[libc::c_char; 17]>(b"output_init_alsa\x00")).as_ptr(),
|
|
1003 as libc::c_int, strerror(*__errno_location()));
|
|
}
|
|
} else if loglevel as libc::c_uint >= lINFO as libc::c_int as libc::c_uint
|
|
{
|
|
logprint(b"%s %s:%d memory locked\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 17],
|
|
&[libc::c_char; 17]>(b"output_init_alsa\x00")).as_ptr(),
|
|
1005 as libc::c_int);
|
|
}
|
|
mallopt(-(1 as libc::c_int), -(1 as libc::c_int));
|
|
mallopt(-(4 as libc::c_int), 0 as libc::c_int);
|
|
if loglevel as libc::c_uint >= lINFO as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d glibc detected using mallopt\n\x00" as *const u8
|
|
as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 17],
|
|
&[libc::c_char; 17]>(b"output_init_alsa\x00")).as_ptr(),
|
|
1011 as libc::c_int);
|
|
}
|
|
touch_memory(silencebuf,
|
|
(2048 as libc::c_int * 8 as libc::c_int) as size_t);
|
|
touch_memory((*outputbuf).buf, (*outputbuf).size);
|
|
// start output thread
|
|
let mut attr: pthread_attr_t = pthread_attr_t{__size: [0; 56],};
|
|
pthread_attr_init(&mut attr);
|
|
pthread_attr_setstacksize(&mut attr,
|
|
(16384 as libc::c_int +
|
|
64 as libc::c_int * 1024 as libc::c_int) as
|
|
size_t);
|
|
pthread_create(&mut thread, &mut attr,
|
|
Some(output_thread as
|
|
unsafe extern "C" fn(_: *mut libc::c_void)
|
|
-> *mut libc::c_void),
|
|
if *rates.offset(0 as libc::c_int as isize) != 0 {
|
|
b"probe\x00" as *const u8 as *const libc::c_char
|
|
} else { 0 as *const libc::c_char } as *mut libc::c_void);
|
|
pthread_attr_destroy(&mut attr);
|
|
// try to set this thread to real-time scheduler class, only works as root or if user has permission
|
|
let mut param: sched_param = sched_param{sched_priority: 0,};
|
|
param.sched_priority = rt_priority as libc::c_int;
|
|
if pthread_setschedparam(thread, 1 as libc::c_int, &mut param) !=
|
|
0 as libc::c_int {
|
|
if loglevel as libc::c_uint >= lDEBUG as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d unable to set output sched fifo: %s\n\x00" as
|
|
*const u8 as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 17],
|
|
&[libc::c_char; 17]>(b"output_init_alsa\x00")).as_ptr(),
|
|
1029 as libc::c_int, strerror(*__errno_location()));
|
|
}
|
|
} else if loglevel as libc::c_uint >=
|
|
lDEBUG as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d set output sched fifo rt: %u\n\x00" as *const u8
|
|
as *const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 17],
|
|
&[libc::c_char; 17]>(b"output_init_alsa\x00")).as_ptr(),
|
|
1031 as libc::c_int, param.sched_priority);
|
|
};
|
|
}
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn output_close_alsa() {
|
|
if loglevel as libc::c_uint >= lINFO as libc::c_int as libc::c_uint {
|
|
logprint(b"%s %s:%d close output\n\x00" as *const u8 as
|
|
*const libc::c_char, logtime(),
|
|
(*::std::mem::transmute::<&[u8; 18],
|
|
&[libc::c_char; 18]>(b"output_close_alsa\x00")).as_ptr(),
|
|
1036 as libc::c_int);
|
|
}
|
|
pthread_mutex_lock(&mut (*outputbuf).mutex);
|
|
running = 0 as libc::c_int != 0;
|
|
pthread_mutex_unlock(&mut (*outputbuf).mutex);
|
|
pthread_join(thread, 0 as *mut *mut libc::c_void);
|
|
if !alsa.write_buf.is_null() {
|
|
free(alsa.write_buf as *mut libc::c_void);
|
|
}
|
|
if !alsa.ctl.is_null() { free(alsa.ctl as *mut libc::c_void); }
|
|
if !alsa.mixer_ctl.is_null() {
|
|
free(alsa.mixer_ctl as *mut libc::c_void);
|
|
}
|
|
if !alsa.mixer_handle.is_null() { snd_mixer_close(alsa.mixer_handle); }
|
|
output_close_common();
|
|
}
|
|
// ALSA
|