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 *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 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 ()>; 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::() 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:: *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