From e1dc3c1de7b1ea77556fdd64c635727b9f094332 Mon Sep 17 00:00:00 2001 From: Alexander Heldt Date: Tue, 18 Nov 2025 21:25:35 +0100 Subject: [PATCH] wip --- src/mpv/control.gleam | 4 +++ src/mpv/mpv.gleam | 75 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 69 insertions(+), 10 deletions(-) diff --git a/src/mpv/control.gleam b/src/mpv/control.gleam index 690beaf..9db8c55 100644 --- a/src/mpv/control.gleam +++ b/src/mpv/control.gleam @@ -10,6 +10,8 @@ import tcp/tcp.{type Socket} pub type Control { TogglePlayPause + Search + Exit } @@ -18,6 +20,7 @@ pub type ControlError { } pub fn from_key(key: Key) -> Result(Control, Nil) { + echo key case key { key.Char(char) -> char_control(char) _ -> Error(Nil) @@ -28,6 +31,7 @@ fn char_control(char: String) -> Result(Control, Nil) { case char { " " -> Ok(TogglePlayPause) "q" -> Ok(Exit) + "/" -> Ok(Search) _ -> Error(Nil) } } diff --git a/src/mpv/mpv.gleam b/src/mpv/mpv.gleam index ab8d2b1..cd170fe 100644 --- a/src/mpv/mpv.gleam +++ b/src/mpv/mpv.gleam @@ -4,13 +4,13 @@ import gleam/otp/actor import gleam/result import gleam/string -import input/key +import input/key.{type Key} import mpv/control.{type Control} import tcp/reason import tcp/tcp.{type Socket} -type State(socket, exit) { - State(socket: Socket, exit: Subject(Nil)) +type State(socket, input, exit) { + State(socket: Socket, inject: Subject(Key), exit: Subject(Nil)) } pub fn new(exit: Subject(Nil)) -> Result(Nil, String) { @@ -20,8 +20,14 @@ pub fn new(exit: Subject(Nil)) -> Result(Nil, String) { case tcp.connect(socket_path) { Error(r) -> Error("Could not connect to mpv: " <> reason.to_string(r)) Ok(socket) -> { + let input_name = process.new_name("input") + let input = process.named_subject(input_name) + + let inject_name = process.new_name("inject") + let inject = process.named_subject(inject_name) + case - actor.new(State(socket, exit)) + actor.new(State(socket, inject, exit)) |> actor.on_message(handle_message) |> actor.start { @@ -30,7 +36,29 @@ pub fn new(exit: Subject(Nil)) -> Result(Nil, String) { Ok(actor.Started(data:, ..)) -> { echo "waiting for input" key.start_raw_shell() - process.spawn(fn() { read_input(data) }) + + // read_input should just have access to input, for sending + + // input hnadler should register both inject and input + process.spawn(fn() { + echo "registering?" + let register_input = process.register(process.self(), input_name) + let register_inject = process.register(process.self(), inject_name) + + case register_input, register_inject { + Ok(_), Ok(_) -> { + echo "registered both" + input_handler(data, input, inject) + } + _, _ -> { + echo "failed to register" + Error("TODO panic?") + } + } + }) + + process.spawn(fn() { read_input(input) }) + Ok(Nil) } } @@ -39,10 +67,14 @@ pub fn new(exit: Subject(Nil)) -> Result(Nil, String) { } fn handle_message( - state: State(socket, exit), + state: State(socket, inject, exit), control: Control, -) -> actor.Next(State(socket, exit), Control) { +) -> actor.Next(State(socket, inject, exit), Control) { case control { + control.Search -> { + process.send(state.inject, key.Continue(["$"])) + actor.continue(state) + } control.TogglePlayPause -> { echo "toggling play/pause" @@ -65,14 +97,37 @@ fn handle_message( } } -fn read_input(subject: Subject(Control)) -> Nil { +fn read_input(input: Subject(Control)) -> Nil { + echo "### read_input" case key.read_input_until_key([]) |> control.from_key { Error(_) -> Nil - Ok(control) -> process.send(subject, control) + Ok(control) -> process.send(input, control) } - read_input(subject) + read_input(input) +} + +fn input_handler( + actor: Subject(Control), + input: Subject(Control), + inject: Subject(Key), +) { + echo "### input_handler" + case + process.new_selector() + |> process.select_map(input, fn(i) { Ok(i) }) + |> process.select_map(inject, control.from_key) + |> process.selector_receive_forever + { + Error(_) -> Nil + Ok(c) -> { + echo "input_handler: " <> string.inspect(c) + process.send(actor, c) + } + } + + input_handler(actor, input, inject) }