diff --git a/src/mpv/control.gleam b/src/mpv/control.gleam index b505ec5..ad5b38d 100644 --- a/src/mpv/control.gleam +++ b/src/mpv/control.gleam @@ -1,5 +1,8 @@ import gleam/json import gleam/result +import gleam/string + +import mpv/internal/control as internal_control import mpv/key.{type Key, Char} import tcp/reason.{type Reason} import tcp/tcp.{type Socket} @@ -38,6 +41,30 @@ pub fn toggle_play_pause(socket: Socket) -> Result(Nil, ControlError) { } } +// https://mpv.io/manual/master/#command-interface-playback-time +pub type PlaybackTime { + PlaybackTime(data: Float) +} + +pub fn get_playback_time(socket: Socket) -> Result(PlaybackTime, ControlError) { + let command = + json.object([ + #( + "command", + json.array(["get_property_string", "playback-time"], of: json.string), + ), + ]) + + case send_command(socket, command) { + Error(r) -> Error(ControlError(reason.to_string(r))) + Ok(json_string) -> + case internal_control.parse_playback_time(json_string) { + Error(e) -> Error(ControlError(string.inspect(e))) + Ok(data) -> Ok(PlaybackTime(data)) + } + } +} + fn send_command(socket: Socket, command: json.Json) -> Result(String, Reason) { result.try(tcp.send(socket, json.to_string(command) <> "\n"), fn(_) { let timeout_ms = 10_000 diff --git a/src/mpv/internal/control.gleam b/src/mpv/internal/control.gleam new file mode 100644 index 0000000..597a695 --- /dev/null +++ b/src/mpv/internal/control.gleam @@ -0,0 +1,25 @@ +import gleam/dynamic/decode +import gleam/float +import gleam/json +import gleam/string + +pub fn parse_playback_time( + json_string: String, +) -> Result(Float, json.DecodeError) { + let decoder = { + let float_dececoder = fn(data_string) { + case float.parse(data_string) { + Error(_) -> decode.failure(0.0, "data") + Ok(float_value) -> decode.success(float_value) + } + } + use data <- decode.field( + "data", + decode.then(decode.string, float_dececoder), + ) + + decode.success(data) + } + + json.parse(from: string.trim(json_string), using: decoder) +} diff --git a/src/mpv/mpv.gleam b/src/mpv/mpv.gleam index b4eba13..e433703 100644 --- a/src/mpv/mpv.gleam +++ b/src/mpv/mpv.gleam @@ -1,4 +1,5 @@ import gleam/erlang/process.{type Subject} +import gleam/float import gleam/otp/actor import gleam/result import gleam/string @@ -44,10 +45,17 @@ fn handle_message( 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 -> { diff --git a/test/mpv/control_test.gleam b/test/mpv/control_test.gleam index 8a6de30..66cb559 100644 --- a/test/mpv/control_test.gleam +++ b/test/mpv/control_test.gleam @@ -2,6 +2,7 @@ import gleam/list import gleeunit import mpv/control.{type Control} +import mpv/internal/control as control_internal import mpv/key.{type Key, Char} pub fn main() -> Nil { @@ -22,3 +23,11 @@ pub fn control_from_key_test() { assert tc.expected == control.from_key(tc.key) }) } + +pub fn parse_playback_time_test() { + let json_string = + "{\"data\":\"123.456789\",\"request_id\":0,\"error\":\"success\"}\n" + + let assert Ok(data) = control_internal.parse_playback_time(json_string) + assert data == 123.456789 +}