import gleam/erlang/process.{type Subject} import gleam/float import gleam/otp/actor import gleam/result import gleam/string import input/key import mpv/control.{type Control} import tcp/reason import tcp/tcp.{type Socket} type State(socket, exit) { State(socket: Socket, exit: Subject(Nil)) } pub fn new(exit: Subject(Nil)) -> Result(Nil, String) { // TODO start up mvp here, currently hi-jacking `naviterm`s socket let socket_path = "/tmp/naviterm_mpv" case tcp.connect(socket_path) { Error(r) -> Error("Could not connect to mpv: " <> reason.to_string(r)) Ok(socket) -> { case actor.new(State(socket, exit)) |> actor.on_message(handle_message) |> actor.start { Error(start_error) -> Error("Could not start actor: " <> string.inspect(start_error)) Ok(actor.Started(data:, ..)) -> { echo "waiting for input" key.start_raw_shell() process.spawn(fn() { read_input(data) }) Ok(Nil) } } } } } fn handle_message( state: State(socket, exit), control: Control, ) -> actor.Next(State(socket, exit), Control) { case control { control.TogglePlayPause -> { echo "toggling play/pause" let _ = result.map_error(control.toggle_play_pause(state.socket), fn(err) { echo "Could not toggle play/pause: " <> err.details }) let _ = result.map(control.get_playback_time(state.socket), fn(playback) { echo "playback: " <> float.to_string(playback.data) }) actor.continue(state) } control.Exit -> { process.send(state.exit, Nil) actor.stop() } } } fn read_input(subject: Subject(Control)) -> Nil { case key.read_input_until_key([]) |> control.from_key { Error(_) -> Nil Ok(control) -> process.send(subject, control) } read_input(subject) }