Skip to main content

siglus_scene_vm/runtime/forms/
pcm.rs

1use anyhow::{bail, Result};
2
3use crate::runtime::{CommandContext, Value};
4
5use super::codes::pcm_op;
6
7fn store_or_push_pcm_prop(ctx: &mut CommandContext, op: i32, args: &[Value]) {
8    let form_key = if ctx.ids.form_global_pcm != 0 {
9        ctx.ids.form_global_pcm
10    } else {
11        super::codes::FORM_GLOBAL_PCM
12    };
13    let prop = op;
14    if let Some(v) = args.get(0).cloned() {
15        match v {
16            Value::Str(s) => {
17                ctx.globals
18                    .str_props
19                    .entry(form_key)
20                    .or_default()
21                    .insert(prop, s);
22            }
23            Value::Int(n) => {
24                ctx.globals
25                    .int_props
26                    .entry(form_key)
27                    .or_default()
28                    .insert(prop, n);
29            }
30            _ => {}
31        }
32        ctx.push(Value::Int(0));
33        return;
34    }
35    if let Some(s) = ctx
36        .globals
37        .str_props
38        .get(&form_key)
39        .and_then(|m| m.get(&prop))
40        .cloned()
41    {
42        ctx.push(Value::Str(s));
43        return;
44    }
45    let v = ctx
46        .globals
47        .int_props
48        .get(&form_key)
49        .and_then(|m| m.get(&prop).copied())
50        .unwrap_or(0);
51    ctx.push(Value::Int(v));
52}
53
54fn arg_str<'a>(args: &'a [Value], idx: usize) -> Option<&'a str> {
55    match args.get(idx) {
56        Some(Value::Str(s)) => Some(s.as_str()),
57        _ => None,
58    }
59}
60
61pub fn dispatch(ctx: &mut CommandContext, args: &[Value]) -> Result<bool> {
62    let Some(op) = crate::runtime::forms::prop_access::current_op_from_ctx_or_args(ctx, args)
63    else {
64        bail!("PCM form expects an element opcode");
65    };
66    let args = crate::runtime::forms::prop_access::params_without_op(ctx, args);
67
68    match op {
69        pcm_op::PLAY => {
70            let name = match arg_str(args, 0) {
71                Some(s) => s,
72                None => {
73                    store_or_push_pcm_prop(ctx, op, args);
74                    return Ok(true);
75                }
76            };
77            let ok = {
78                let (pcm, audio) = (&mut ctx.pcm, &mut ctx.audio);
79                pcm.play_file_name(audio, name).is_ok()
80            };
81            if !ok {
82                ctx.unknown.record_note(&format!("pcm.play.failed:{name}"));
83            }
84            Ok(true)
85        }
86        pcm_op::STOP => {
87            ctx.pcm.stop(None)?;
88            Ok(true)
89        }
90        _ => {
91            store_or_push_pcm_prop(ctx, op, args);
92            Ok(true)
93        }
94    }
95}