ferretro/src/components/mod.rs

262 lines
7.2 KiB
Rust
Raw Normal View History

use crate::prelude::*;
use std::os::raw::c_uint;
use std::rc::Rc;
use crate::retro::ffi::{Message, PixelFormat, HwRenderCallback, SensorInterface, CameraCallback, LogCallback, PerfCallback, LocationCallback, SystemAvInfo, GetProcAddressInterface, MemoryMap, GameGeometry, Language, LogLevel, RumbleEffect, Time, PerfTick, PerfCounter, SensorAction};
use std::path::PathBuf;
#[rustfmt::skip]
#[allow(unused)]
pub trait RetroAvCommonComponent {
fn set_system_av_info(&mut self, system_av_info: &SystemAvInfo) -> bool { false }
}
#[rustfmt::skip]
#[allow(unused)]
pub trait RetroVideoComponent: RetroAvCommonComponent {
fn video_refresh(&mut self, data: &[u8], width: c_uint, height: c_uint, pitch: c_uint) {}
// -- environment callbacks --
fn set_rotation(&mut self, rotation: EnvRotation) -> bool { false }
fn get_overscan(&mut self) -> Option<bool> { None }
fn set_pixel_format(&mut self, format: PixelFormat) -> bool { false }
fn set_hw_render(&mut self, hw_render_callback: &HwRenderCallback) -> bool { false }
fn set_geometry(&mut self, game_geometry: &GameGeometry) -> bool { false }
}
#[rustfmt::skip]
#[allow(unused)]
pub trait RetroAudioComponent: RetroAvCommonComponent {
fn audio_sample(&mut self, left: i16, right: i16) {}
fn audio_sample_batch(&mut self, stereo_pcm: &[i16]) -> usize { 0 }
}
pub struct RetroComponentBase {
retro: LibretroWrapper,
pub video_comps: Vec<Rc<dyn RetroVideoComponent>>,
pub audio_comps: Vec<Rc<dyn RetroAudioComponent>>,
}
#[allow(unused)]
impl RetroCallbacks for RetroComponentBase {
fn libretro_core(&mut self) -> &mut LibretroWrapper {
&mut self.retro
}
fn video_refresh(&mut self, data: &[u8], width: c_uint, height: c_uint, pitch: c_uint) {
for vc in &mut self.video_comps {
// FIXME: can't have more than 1 ref!
// get_mut fails if one component struct impls both Audio&Video!
Rc::get_mut(vc).unwrap().video_refresh(data, width, height, pitch);
}
}
fn video_refresh_dupe(&mut self, width: c_uint, height: c_uint, pitch: c_uint) {
todo!()
}
fn audio_sample(&mut self, left: i16, right: i16) {
todo!()
}
fn audio_sample_batch(&mut self, stereo_pcm: &[i16]) -> usize {
todo!()
}
fn input_poll(&mut self) {
todo!()
}
fn input_state(&mut self, port: u32, device: InputDeviceId, index: InputIndex) -> i16 {
todo!()
}
fn set_rotation(&mut self, rotation: EnvRotation) -> bool {
self.video_comps.iter_mut()
.map(|x| Rc::get_mut(x).unwrap().set_rotation(rotation))
.fold(false, |x, y| x || y) // not "any" because we don't short-circuit
}
fn get_overscan(&mut self) -> Option<bool> {
self.video_comps.iter_mut()
.map(|x| Rc::get_mut(x).unwrap().get_overscan())
.fold(None, |x, y| match (x, y) {
(Some(a), Some(b)) => Some(a || b),
(Some(a), None) | (None, Some(a)) => Some(a),
(None, None) => None,
})
}
fn set_message(&mut self, message: Message) -> bool {
todo!()
}
fn shutdown(&mut self) -> bool {
todo!()
}
fn set_performance_level(&mut self, level: c_uint) -> bool {
todo!()
}
fn get_system_directory(&mut self) -> Option<PathBuf> {
todo!()
}
fn set_pixel_format(&mut self, format: PixelFormat) -> bool {
self.video_comps.iter_mut()
.map(|x| Rc::get_mut(x).unwrap().set_pixel_format(format))
.all(|x| x)
}
fn set_input_descriptors(&mut self, input_descriptors: Vec<InputDescriptor2>) -> bool {
todo!()
}
fn set_hw_render(&mut self, hw_render_callback: &HwRenderCallback) -> bool {
self.video_comps.iter_mut()
.map(|x| Rc::get_mut(x).unwrap().set_hw_render(hw_render_callback))
.all(|x| x)
}
fn get_variable(&mut self, key: &str) -> Option<String> {
todo!()
}
fn set_variables(&mut self, variables: Vec<Variable2>) -> bool {
todo!()
}
fn get_variable_update(&mut self) -> Option<bool> {
todo!()
}
fn set_support_no_game(&mut self, supports_no_game: bool) -> bool {
todo!()
}
fn get_libretro_path(&mut self) -> Option<PathBuf> {
todo!()
}
fn get_input_device_capabilities(&mut self) -> Option<u64> {
todo!()
}
fn get_sensor_interface(&mut self) -> Option<SensorInterface> {
todo!()
}
fn get_camera_interface(&mut self) -> Option<CameraCallback> {
todo!()
}
fn get_log_interface(&mut self) -> Option<LogCallback> {
todo!()
}
fn get_perf_interface(&mut self) -> Option<PerfCallback> {
todo!()
}
fn get_location_interface(&mut self) -> Option<LocationCallback> {
todo!()
}
fn get_core_assets_directory(&mut self) -> Option<PathBuf> {
todo!()
}
fn get_save_directory(&mut self) -> Option<PathBuf> {
todo!()
}
fn set_system_av_info(&mut self, system_av_info: &SystemAvInfo) -> bool {
// TODO: avoid calling twice for components that are registered in both simultaneously
let mut result = false;
for vc in &mut self.video_comps {
result |= Rc::get_mut(vc).unwrap().set_system_av_info(system_av_info);
}
for ac in &mut self.audio_comps {
result |= Rc::get_mut(ac).unwrap().set_system_av_info(system_av_info);
}
result
}
fn set_proc_address_callback(&mut self, cb: GetProcAddressInterface) -> bool {
todo!()
}
fn set_subsystem_info(&mut self, subsystem_info: Vec<SubsystemInfo2>) -> bool {
todo!()
}
fn set_controller_info(&mut self, controller_info: Vec<ControllerDescription2>) -> bool {
todo!()
}
fn set_memory_maps(&mut self, memory_map: MemoryMap) -> bool {
todo!()
}
fn set_geometry(&mut self, game_geometry: &GameGeometry) -> bool {
self.video_comps.iter_mut()
.map(|x| Rc::get_mut(x).unwrap().set_geometry(game_geometry))
.fold(false, |x, y| x || y) // not "any" because we don't short-circuit
}
fn get_username(&mut self) -> Option<String> {
todo!()
}
fn get_language(&mut self) -> Option<Language> {
todo!()
}
fn log_print(&mut self, level: LogLevel, msg: &str) {
todo!()
}
fn set_rumble_state(&mut self, port: c_uint, effect: RumbleEffect, strength: u16) -> bool {
todo!()
}
fn perf_get_time_usec_cb(&mut self) -> Time {
todo!()
}
fn perf_get_counter_cb(&mut self) -> PerfTick {
todo!()
}
fn perf_get_cpu_features_cb(&mut self) -> u64 {
todo!()
}
fn perf_log_cb(&mut self) {
todo!()
}
fn perf_register_cb(&mut self, counter: &mut PerfCounter) {
todo!()
}
fn perf_start_cb(&mut self, counter: &mut PerfCounter) {
todo!()
}
fn perf_stop_cb(&mut self, counter: &mut PerfCounter) {
todo!()
}
fn set_sensor_state(&mut self, port: c_uint, action: SensorAction, rate: c_uint) -> bool {
todo!()
}
fn get_sensor_input(&mut self, port: c_uint, id: c_uint) -> f32 {
todo!()
}
}