123 lines
3.4 KiB
Gleam
123 lines
3.4 KiB
Gleam
import gleam/erlang/process.{type Name, type Subject}
|
|
import gleam/otp/actor
|
|
import gleam/result
|
|
import gleam/string
|
|
|
|
import input/key.{type Key}
|
|
import mpv/control as mpv_control
|
|
import ui/control as ui_control
|
|
|
|
pub type State(ui_mpv, mpv_ui, ui_input_keys, ui_input_stream, exit) {
|
|
State(
|
|
ui_mpv: Subject(mpv_control.Control),
|
|
mpv_ui: Subject(ui_control.Control),
|
|
ui_input_keys: Subject(Key),
|
|
ui_input_stream: Subject(List(String)),
|
|
exit: Subject(Nil),
|
|
)
|
|
}
|
|
|
|
pub fn new(
|
|
ui_mpv_name: Name(mpv_control.Control),
|
|
mpv_ui_name: Name(ui_control.Control),
|
|
ui_input_keys_name: Name(Key),
|
|
ui_input_stream_name: Name(List(String)),
|
|
exit: Subject(Nil),
|
|
) -> Result(Nil, String) {
|
|
let ui_mpv: Subject(mpv_control.Control) = process.named_subject(ui_mpv_name)
|
|
let mpv_ui: Subject(ui_control.Control) = process.named_subject(mpv_ui_name)
|
|
|
|
let ui_input_keys: Subject(Key) = process.named_subject(ui_input_keys_name)
|
|
let ui_input_stream: Subject(List(String)) =
|
|
process.named_subject(ui_input_stream_name)
|
|
|
|
case
|
|
actor.new(State(ui_mpv, mpv_ui, ui_input_keys, ui_input_stream, exit))
|
|
|> actor.on_message(handle_message)
|
|
|> actor.start
|
|
{
|
|
Error(start_error) ->
|
|
Error("Could not start ui: " <> string.inspect(start_error))
|
|
Ok(actor.Started(data: ui, ..)) -> {
|
|
echo "ui started"
|
|
|
|
process.spawn(fn() {
|
|
let assert Ok(_) = process.register(process.self(), ui_input_keys_name)
|
|
handle_key(ui, ui_input_keys)
|
|
})
|
|
|
|
process.spawn(fn() {
|
|
let assert Ok(_) = process.register(process.self(), mpv_ui_name)
|
|
handle_mpv_control(ui, mpv_ui)
|
|
})
|
|
|
|
process.spawn(fn() {
|
|
let assert Ok(_) =
|
|
process.register(process.self(), ui_input_stream_name)
|
|
temp_input_stream(ui_input_stream)
|
|
})
|
|
|
|
Ok(Nil)
|
|
}
|
|
}
|
|
}
|
|
|
|
fn handle_message(
|
|
state: State(ui_mpv, mpv_ui, ui_input_keys, ui_input_stream, exit),
|
|
control: ui_control.Control,
|
|
) -> actor.Next(
|
|
State(ui_mpv, mpv_ui, ui_input_keys, ui_input_stream, exit),
|
|
ui_control.Control,
|
|
) {
|
|
case control {
|
|
ui_control.Ack -> {
|
|
echo "ack! use this to re-render?"
|
|
actor.continue(state)
|
|
}
|
|
ui_control.TogglePlayPause -> {
|
|
process.send(state.mpv_ui, ui_control.TogglePlayPause)
|
|
case process.receive(state.mpv_ui, 5000) {
|
|
Error(_) -> echo "mpv not responding: could not toggle pause :("
|
|
Ok(_) -> echo "toggled pause"
|
|
}
|
|
|
|
actor.continue(state)
|
|
}
|
|
ui_control.Exit -> {
|
|
// TODO call `mpv` to exit, wait for response
|
|
process.send(state.exit, Nil)
|
|
actor.stop()
|
|
}
|
|
}
|
|
}
|
|
|
|
/// `handle_key` listens to a subject onto which `input` will send messages with
|
|
/// parsed `Key`s which will be mapped to `Control`s (if possible)
|
|
fn handle_key(
|
|
ui: Subject(ui_control.Control),
|
|
ui_input_keys: Subject(Key),
|
|
) -> Nil {
|
|
let _ =
|
|
process.receive_forever(ui_input_keys)
|
|
|> ui_control.from_key
|
|
|> result.map(process.send(ui, _))
|
|
|
|
handle_key(ui, ui_input_keys)
|
|
}
|
|
|
|
fn handle_mpv_control(
|
|
ui: Subject(ui_control.Control),
|
|
mpv_ui: Subject(ui_control.Control),
|
|
) {
|
|
let control = process.receive_forever(mpv_ui)
|
|
process.send(ui, control)
|
|
|
|
handle_mpv_control(ui, mpv_ui)
|
|
}
|
|
|
|
fn temp_input_stream(ui_input_stream: Subject(List(String))) -> Nil {
|
|
let stream = process.receive_forever(ui_input_stream)
|
|
echo "input stream: " <> string.inspect(stream)
|
|
temp_input_stream(ui_input_stream)
|
|
}
|