use std;
use fmod::{self, ChannelControl};
#[allow(unused_macros)]
macro_rules! show {
($e:expr) => { println!("{}: {:?}", stringify!($e), $e); }
}
static INDENT : std::sync::atomic::AtomicU64 =
std::sync::atomic::AtomicU64::new (0);
pub fn write_info_system <W : std::io::Write>
(writer : &mut W, system : &fmod::System) -> Result <(), std::io::Error>
{
let indent = indent_string();
writeln!(writer, "{indent}# fmod system info #")?;
writeln!(writer, "{}{:<36} {}", indent, "fmod system: version:",
system.get_version_string().unwrap())?;
writeln!(writer, "{}{:<36} {:?}", indent, "fmod system: output:",
system.get_output().unwrap())?;
writeln!(writer, "{}{:<36} {:?}", indent, "fmod system: num drivers:",
system.get_num_drivers().unwrap())?;
for i in 0..system.get_num_drivers().unwrap() {
let driver_info = system.get_driver_info (i).unwrap();
writeln!(writer, "{indent}fmod system: driver info[{i}]:")?;
writeln!(writer, "{indent} {driver_info:?}")?;
}
writeln!(writer, "{}{:<36} {:?}", indent, "fmod system: record num drivers:",
system.get_record_num_drivers().unwrap())?;
for i in 0..system.get_record_num_drivers().unwrap().0 {
let (info, state) = system.get_record_driver_info (i).unwrap();
writeln!(writer, "{indent}fmod system: record driver info[{i}]:")?;
writeln!(writer, "{indent} {info:?}")?;
writeln!(writer, "{indent} {state:?}")?;
}
writeln!(writer, "{}{:<36} {}", indent, "fmod system: driver:",
system.get_driver().unwrap())?;
writeln!(writer, "{}{:<36} {}", indent, "fmod system: software channels:",
system.get_software_channels().unwrap())?;
writeln!(writer, "{}{:<36} {:?}", indent, "fmod system: channels playing:",
system.get_channels_playing().unwrap())?;
let (samplerate, speakermode, numrawspeakers) =
system.get_software_format().unwrap();
writeln!(writer, "{indent}fmod system: software format:")?;
writeln!(writer, "{indent} sample rate: {samplerate}")?;
writeln!(writer, "{indent} speaker mode: {speakermode:?}")?;
writeln!(writer, "{indent} num raw speakers: {numrawspeakers}")?;
writeln!(writer, "{}{:<36} {:?}", indent, "fmod system: dsp buffer size:",
system.get_dsp_buffer_size().unwrap())?;
writeln!(writer, "{indent}fmod system: speaker mode channels:")?;
for i in 0..fmod::Speakermode::MAX as u32 {
use fmod::FromPrimitive;
let mode = fmod::Speakermode::from_u32 (i).unwrap();
writeln!(writer, "{} {:?}: {}",
indent, mode, system.get_speaker_mode_channels (mode).unwrap())?;
}
writeln!(writer, "{indent}fmod system: num plugins:")?;
writeln!(writer, "{} Plugintype::Output: {:?}", indent,
system.get_num_plugins (fmod::Plugintype::Output).unwrap())?;
writeln!(writer, "{} Plugintype::Codec: {:?}", indent,
system.get_num_plugins (fmod::Plugintype::Codec).unwrap())?;
writeln!(writer, "{} Plugintype::DSP: {:?}", indent,
system.get_num_plugins (fmod::Plugintype::Dsp).unwrap())?;
writeln!(writer, "{}{:<36} {:?}", indent, "fmod system: output by plugin:",
system.get_output_by_plugin().unwrap())?;
writeln!(writer, "{}{:<36} {:?}", indent, "fmod system: 3d num listeners:",
system.get_3d_num_listeners().unwrap())?;
for i in 0..system.get_3d_num_listeners().unwrap() {
let attributes = system.get_3d_listener_attributes (i).unwrap();
writeln!(writer, "{indent}fmod system: 3d listener attributes[{i}]:")?;
writeln!(writer, "{} pos: {:?}", indent, attributes.pos)?;
writeln!(writer, "{} vel: {:?}", indent, attributes.vel)?;
writeln!(writer, "{} forward: {:?}", indent, attributes.forward)?;
writeln!(writer, "{} up: {:?}", indent, attributes.up)?;
}
writeln!(writer, "{indent}fmod system: 3d speaker position:")?;
let driver_id = system.get_driver().unwrap();
let driver_info = system.get_driver_info (driver_id).unwrap();
for i in 0..driver_info.speakermodechannels as u32 {
use fmod::FromPrimitive;
let speaker = fmod::Speaker::from_u32 (i).unwrap();
writeln!(writer, "{} {:?}: {:?}",
indent, speaker, system.get_speaker_position (speaker).unwrap())?;
}
let (doppler_scale, distance_factor, roll_off_scale) =
system.get_3d_settings().unwrap();
writeln!(writer, "{indent}fmod system: 3d settings:")?;
writeln!(writer, "{indent} doppler scale: {doppler_scale}")?;
writeln!(writer, "{indent} distance factor: {distance_factor}")?;
writeln!(writer, "{indent} roll off scale: {roll_off_scale}")?;
let (buffer_size, time_unit) = system.get_stream_buffer_size().unwrap();
writeln!(writer, "{}{:<36} ({}, {:?})", indent,
"fmod system: stream buffer size:", buffer_size, time_unit)?;
writeln!(writer, "{}{:<36} {:?}", indent, "fmod system: cpu usage:",
system.get_cpu_usage().unwrap())?;
writeln!(writer, "{}{:<36} {:?}", indent, "fmod system: sound ram:",
system.get_sound_ram().unwrap())?;
writeln!(writer, "{indent}fmod system: reverb properties:")?;
for i in 0..fmod::dsp::REVERB_MAXINSTANCES as i32 {
writeln!(writer, "{indent} instance[{i}]:")?;
indent_bump (4);
let properties = show_reverb_properties (&system.get_reverb_properties (i)
.unwrap());
indent_unbump (4);
write!(writer, "{properties}")?;
}
writeln!(writer, "{}{:<36} {}", indent, "fmod system: geometry settings:",
system.get_geometry_settings().unwrap())?;
Ok(())
}
pub fn write_info_reverb3d <W : std::io::Write>
(writer : &mut W, reverb : &fmod::Reverb3d) -> Result <(), std::io::Error>
{
let indent = indent_string();
writeln!(writer, "{indent}# fmod reverb info #")?;
writeln!(writer, "{}fmod reverb: active: {}", indent,
reverb.get_active().unwrap())?;
let attributes = reverb.get_3d_attributes().unwrap();
writeln!(writer, "{indent}fmod reverb: 3d attributes:")?;
writeln!(writer, "{} position: {:?}", indent, attributes.position)?;
writeln!(writer, "{} min distance: {:?}", indent, attributes.mindistance)?;
writeln!(writer, "{} max distance: {:?}", indent, attributes.maxdistance)?;
write!(writer, "{}fmod reverb: properties: {}", indent,
show_reverb_properties (&reverb.get_properties().unwrap()))?;
Ok(())
}
pub fn write_info_dsp <W : std::io::Write>
(writer : &mut W, dsp : &fmod::Dsp) -> Result <(), std::io::Error>
{
let indent = indent_string();
writeln!(writer, "{indent}# fmod dsp info #")?;
writeln!(writer, "{}{:<24} {:?}", indent, "fmod dsp: type:",
dsp.get_type().unwrap())?;
writeln!(writer, "{}{:<24} {}", indent, "fmod dsp: active:",
dsp.get_active().unwrap())?;
writeln!(writer, "{}{:<24} {}", indent, "fmod dsp: bypass:",
dsp.get_bypass().unwrap())?;
writeln!(writer, "{}{:<24} {}", indent, "fmod dsp: num inputs:",
dsp.get_num_inputs().unwrap())?;
writeln!(writer, "{}{:<24} {}", indent, "fmod dsp: num outputs:",
dsp.get_num_outputs().unwrap())?;
Ok(())
}
pub fn write_info_channel <W : std::io::Write> (
writer : &mut W,
channel : &fmod::Channel
) -> Result <(), std::io::Error> {
let indent = indent_string();
writeln!(writer, "{indent}# fmod channel info #")?;
writeln!(writer, "{}{:<36} {}", indent, "fmod channel: index:",
channel.get_index().unwrap())?;
writeln!(writer, "{}{:<36} {}", indent, "fmod channel: channel group:",
channel.get_channel_group().unwrap().get_name().unwrap())?;
writeln!(writer, "{}{:<36} {}", indent, "fmod channel: priority:",
channel.get_priority().unwrap())?;
writeln!(writer, "{}{:<36} {}", indent, "fmod channel: is virtual:",
channel.is_virtual().unwrap())?;
writeln!(writer, "{}{:<36} {}", indent, "fmod channel: position (ms):",
channel.get_position (fmod::Timeunit::MS).unwrap())?;
writeln!(writer, "{}{:<36} {}", indent, "fmod channel: loop count:",
channel.get_loop_count().unwrap())?;
let (loop_start, loop_end) =
channel.get_loop_points (fmod::Timeunit::MS, fmod::Timeunit::MS).unwrap();
writeln!(writer, "{}{:<36} (start: {}, end: {})", indent,
"fmod channel: loop points (ms):", loop_start, loop_end)?;
writeln!(writer, "{}{:<36} {}", indent, "fmod channel: frequency:",
channel.get_frequency().unwrap())?;
writeln!(writer, "{indent}fmod channel: channel control:")?;
write_info_channel_control (writer, channel)?;
Ok(())
}
pub fn write_info_channel_control <W : std::io::Write, C : ChannelControl> (
writer : &mut W,
control : &C
) -> Result <(), std::io::Error> {
let indent = indent_string();
writeln!(writer, "{indent}# fmod channel control info #")?;
writeln!(writer, "{}{:<36} Mode({:b})", indent, "fmod channel control: mode:",
control.get_mode().unwrap())?;
writeln!(writer, "{}{:<36} {}", indent, "fmod channel control: is playing:",
control.is_playing().unwrap())?;
writeln!(writer, "{}{:<36} {}", indent, "fmod channel control: paused:",
control.get_paused().unwrap())?;
writeln!(writer, "{}{:<36} {}", indent, "fmod channel control: volume:",
control.get_volume().unwrap())?;
writeln!(writer, "{}{:<36} {}", indent, "fmod channel control: mute:",
control.get_mute().unwrap())?;
writeln!(writer, "{}{:<36} {}", indent, "fmod channel control: audibility:",
control.get_audibility().unwrap())?;
writeln!(writer, "{}{:<36} {}", indent, "fmod channel control: low pass gain:",
control.get_low_pass_gain().unwrap())?;
let delay = control.get_delay().unwrap();
writeln!(writer, "{}{:<36} {:?}", indent, "fmod channel control: delay:",
delay)?;
writeln!(writer, "{indent}fmod channel control: reverb properties (wet level):")?;
for i in 0..fmod::dsp::REVERB_MAXINSTANCES as i32 {
writeln!(writer, "{} instance[{}]: {}",
indent, i, control.get_reverb_properties (i).unwrap())?;
}
let num_dsps = control.get_num_dsps().unwrap();
writeln!(writer, "{}{:<36} {}", indent, "fmod channel control: num dsps:",
num_dsps)?;
for i in 0..num_dsps {
writeln!(writer, "{indent}fmod channel control: dsp[{i}]:")?;
let dsp = control.get_dsp (i as i32).unwrap();
indent_bump (4);
write_info_dsp (writer, &dsp)?;
indent_unbump (4);
}
match control.get_3d_attributes() {
Ok ((position, velocity)) => {
writeln!(writer, "{indent}fmod channel control: 3d attributes:")?;
writeln!(writer, "{indent} position: {position:?}")?;
writeln!(writer, "{indent} velocity: {velocity:?}")?;
writeln!(writer, "{}{:<36} {:?}", indent,
"fmod channel control: 3d min max distance:",
control.get_3d_min_max_distance().unwrap())?;
writeln!(writer, "{}{:<36} {}", indent, "fmod channel control: 3d spread:",
control.get_3d_spread().unwrap())?;
writeln!(writer, "{}{:<36} {}", indent, "fmod channel control: 3d doppler level:",
control.get_3d_doppler_level().unwrap())?;
writeln!(writer, "{}{:<36} {:?}", indent,
"fmod channel control: 3d custom rolloff:",
control.get_3d_custom_rolloff().unwrap())?;
writeln!(writer, "{}{:<36} {:?}", indent,
"fmod channel control: 3d distance filter:",
control.get_3d_distance_filter().unwrap())?;
writeln!(writer, "{}{:<36} {:?}", indent,
"fmod channel control: 3d occlusion:",
control.get_3d_occlusion().unwrap())?;
writeln!(writer, "{}{:<36} {:?}", indent,
"fmod channel control: 3d cone orientation:",
control.get_3d_cone_orientation().unwrap())?;
let (inside_cone_angle, outside_cone_angle, outside_volume) =
control.get_3d_cone_settings().unwrap();
writeln!(writer, "{indent}fmod channel control: 3d cone settings:")?;
writeln!(writer, "{indent} inside cone angle: {inside_cone_angle}")?;
writeln!(writer, "{indent} outside cone angle: {outside_cone_angle}")?;
writeln!(writer, "{indent} outside volume: {outside_volume}")?;
}
Err (fmod::Error::Needs3d) => {}
err => {
writeln!(writer, "channel control 3d attributes error: {err:?}")?;
unreachable!()
}
}
Ok (())
}
pub fn write_info_channel_group <W : std::io::Write> (
writer : &mut W,
group : &fmod::ChannelGroup
) -> Result <(), std::io::Error> {
let indent = indent_string();
writeln!(writer, "{indent}# fmod channel group info #")?;
writeln!(writer, "{}{:<40} {}", indent, "fmod channel group: name:",
group.get_name().unwrap())?;
writeln!(writer, "{}{:<40} {}", indent, "fmod channel group: is master:",
group.is_master().unwrap())?;
if let Ok (Some (parent_group)) = group.get_parent_group() {
writeln!(writer, "{}{:<40} {}", indent, "fmod channel group: parent group:",
parent_group.get_name().unwrap())?;
}
let num_groups = group.get_num_groups().unwrap();
writeln!(writer, "{}{:<40} {}", indent, "fmod channel group: num groups:",
num_groups)?;
let num_channels = group.get_num_channels().unwrap();
writeln!(writer, "{}{:<40} {}", indent, "fmod channel group: num channels:",
num_channels)?;
for i in 0..num_channels {
writeln!(writer, "{indent}fmod channel group: channel[{i}]:")?;
indent_bump (4);
write_info_channel (writer, &group.get_channel (i).unwrap())?;
indent_unbump (4);
}
writeln!(writer, "{indent}fmod channelgroup: channel control:")?;
write_info_channel_control (writer, group)?;
Ok(())
}
pub fn write_info_sound <W : std::io::Write> (
writer : &mut W,
sound : &fmod::Sound
) -> Result <(), std::io::Error> {
let indent = indent_string();
writeln!(writer, "{indent}# fmod sound info #")?;
writeln!(writer, "{}{:<32} {}", indent, "fmod sound: name:",
sound.get_name().unwrap())?;
writeln!(writer, "{}{:<32} {}", indent, "fmod sound: length (ms):",
sound.get_length (fmod::Timeunit::MS).unwrap())?;
writeln!(writer, "{}{:<32} {:?}", indent, "fmod sound: format:",
sound.get_format().unwrap())?;
writeln!(writer, "{}{:<32} {}", indent, "fmod sound: num sub sounds:",
sound.get_num_sub_sounds().unwrap())?;
writeln!(writer, "{}{:<32} {:?}", indent, "fmod sound: num tags:",
sound.get_num_tags().unwrap())?;
writeln!(writer, "{}{:<32} {:?}", indent, "fmod sound: open state:",
sound.get_open_state().unwrap())?;
writeln!(writer, "{}{:<32} Mode({:b})", indent, "fmod sound: mode:",
sound.get_mode().unwrap())?;
writeln!(writer, "{}{:<32} {}", indent, "fmod sound: loop count:",
sound.get_loop_count().unwrap())?;
let (loop_start, loop_end) =
sound.get_loop_points (fmod::Timeunit::MS, fmod::Timeunit::MS).unwrap();
writeln!(writer, "{}{:<32} (start: {}, end: {})", indent,
"fmod sound: loop points (ms):",
loop_start, loop_end)?;
let (frequency, priority) = sound.get_defaults().unwrap();
writeln!(writer, "{indent}fmod sound: defaults:")?;
writeln!(writer, "{indent} frequency: {frequency}")?;
writeln!(writer, "{indent} priority: {priority}")?;
writeln!(writer, "{}{:<32} {}", indent, "fmod sound: num sync points:",
sound.get_num_sync_points().unwrap())?;
writeln!(writer, "{}{:<32} {:?}", indent, "fmod sound: 3d min max distance:",
sound.get_3d_min_max_distance().unwrap())?;
let (inside_cone_angle, outside_cone_angle, outside_volume)
= sound.get_3d_cone_settings().unwrap();
writeln!(writer, "{indent}fmod sound: 3d cone settings:")?;
writeln!(writer, "{indent} inside cone angle: {inside_cone_angle}")?;
writeln!(writer, "{indent} outside cone angle: {outside_cone_angle}")?;
writeln!(writer, "{indent} outside volume: {outside_volume}")?;
Ok(())
}
pub fn show_reverb_properties (reverb_properties : &fmod::reverb3d::Properties)
-> String
{
use std::fmt::Write;
let indent = indent_string();
let mut s = String::new();
writeln!(s, "{indent}ReverbProperties {{").unwrap();
writeln!(s, "{} {:<22} {}", indent, "decay time:",
reverb_properties.decay_time).unwrap();
writeln!(s, "{} {:<22} {}", indent, "early delay:",
reverb_properties.early_delay).unwrap();
writeln!(s, "{} {:<22} {}", indent, "late delay:",
reverb_properties.late_delay).unwrap();
writeln!(s, "{} {:<22} {}", indent, "hf reference:",
reverb_properties.hf_reference).unwrap();
writeln!(s, "{} {:<22} {}", indent, "hf decay ratio:",
reverb_properties.hf_decay_ratio).unwrap();
writeln!(s, "{} {:<22} {}", indent, "diffusion:",
reverb_properties.diffusion).unwrap();
writeln!(s, "{} {:<22} {}", indent, "density:",
reverb_properties.density).unwrap();
writeln!(s, "{} {:<22} {}", indent, "low shelf frequency:",
reverb_properties.low_shelf_frequency).unwrap();
writeln!(s, "{} {:<22} {}", indent, "low shelf gain:",
reverb_properties.low_shelf_gain).unwrap();
writeln!(s, "{} {:<22} {}", indent, "high cut:",
reverb_properties.high_cut).unwrap();
writeln!(s, "{} {:<22} {}", indent, "early late mix:",
reverb_properties.early_late_mix).unwrap();
writeln!(s, "{} {:<22} {}", indent, "wet level:",
reverb_properties.wet_level).unwrap();
writeln!(s, "{indent}}}").unwrap();
s
}
fn indent_bump (spaces : u64) -> String {
INDENT.fetch_add (spaces, std::sync::atomic::Ordering::SeqCst);
indent_string()
}
fn indent_unbump (spaces : u64) -> String {
INDENT.fetch_sub (spaces, std::sync::atomic::Ordering::SeqCst);
indent_string()
}
fn indent_string () -> String {
use std::iter::FromIterator;
let indent = INDENT.load (std::sync::atomic::Ordering::SeqCst) as usize;
String::from_iter (std::iter::repeat_n (' ', indent))
}
fn _pretty_indent (d : &dyn std::fmt::Debug) -> String {
let indent = indent_string();
let s = format!("{d:#?}");
let mut lines = s.lines();
let first = lines.next().unwrap();
let mut rest : String = lines.map (|line| format!("{indent}{line}\n"))
.collect();
rest.pop().unwrap();
[first.to_string(), "\n".to_string(), rest].concat()
}