let devtype = cubeb_backend::DeviceType::from_bits_truncate(device_type);
// Hold the lock across callback invocation to ensure // unregistration cannot complete while a callback is in // progress, preventing use-after-free of user_ptr. let cbs = self.callbacks.lock().unwrap();
run_in_callback(|| { if devtype.contains(cubeb_backend::DeviceType::INPUT) { iflet Some(cb) = cbs.input_cb { unsafe { cb(ptr::null_mut(), cbs.input_user_ptr as *mut c_void) }
}
} if devtype.contains(cubeb_backend::DeviceType::OUTPUT) { iflet Some(cb) = cbs.output_cb { unsafe { cb(ptr::null_mut(), cbs.output_user_ptr as *mut c_void) }
}
}
});
let params = AUDIOIPC_INIT_PARAMS.with(|p| p.replace(None).unwrap()); let thread_create_callback = params.thread_create_callback; let thread_destroy_callback = params.thread_destroy_callback;
let server_connection = unsafe { sys::Pipe::from_raw_handle(PlatformHandle::new(params.server_connection)) };
let rpc_thread = ipccore::EventLoopThread::new( "AudioIPC Client RPC".to_string(),
None, move || register_thread(thread_create_callback), move || unregister_thread(thread_destroy_callback),
)
.map_err(|_| Error::Error)?; let rpc = rpc_thread
.handle()
.bind_client::<CubebClient>(server_connection)
.map_err(|_| Error::Error)?; let rpc2 = rpc.clone();
// Don't let errors bubble from here. Later calls against this context // will return errors the caller expects to handle. let _ = send_recv!(rpc, ClientConnect => ClientConnected);
let backend_id = send_recv!(rpc, ContextGetBackendId => ContextBackendId())
.unwrap_or_else(|_| "(remote error)".to_string()); let backend_id = CString::new(backend_id).expect("backend_id query failed");
fn device_collection_destroy(
&mutself,
collection: Box<[cubeb_backend::DeviceInfo]>,
) -> Result<()> {
assert_not_in_callback(); for dev in collection { let dev = ffi::cubeb_device_info::from(dev); if !dev.device_id.is_null() { let _ = unsafe { CString::from_raw(dev.device_id as *mut _) };
} if !dev.group_id.is_null() { let _ = unsafe { CString::from_raw(dev.group_id as *mut _) };
} if !dev.vendor_name.is_null() { let _ = unsafe { CString::from_raw(dev.vendor_name as *mut _) };
} if !dev.friendly_name.is_null() { let _ = unsafe { CString::from_raw(dev.friendly_name as *mut _) };
}
}
Ok(())
}
fn stream_init(
&mutself,
stream_name: Option<&CStr>,
input_device: DeviceId,
input_stream_params: Option<&StreamParamsRef>,
output_device: DeviceId,
output_stream_params: Option<&StreamParamsRef>,
latency_frames: u32, // These params aren't sent to the server
data_callback: ffi::cubeb_data_callback,
state_callback: ffi::cubeb_state_callback,
user_ptr: *mut c_void,
) -> Result<Stream> {
assert_not_in_callback();
let stream_name = stream_name.map(|name| name.to_bytes_with_nul().to_vec());
let input_stream_params = input_stream_params.map(messages::StreamParams::from); let output_stream_params = output_stream_params.map(messages::StreamParams::from);
let params = messages::StreamCreateParams {
stream_name,
input_device: input_device as usize,
input_stream_params,
output_device: output_device as usize,
output_stream_params,
latency_frames,
};
stream::init(self, params, data_callback, state_callback, user_ptr)
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.