diff --git a/CHANGELOG.md b/CHANGELOG.md index be97bac6..dd36db98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ - Fix ending excursions with `ijkl` only when needed (#207) - Fixed video long-step handling (#207) - Removed confusing auto-generated IDs (#209) +- Fix `play-media` behavior when facing errors (#210) ### Docs diff --git a/src/engine/runtime/fast/fast.ml b/src/engine/runtime/fast/fast.ml index 300697cc..e1b58bcb 100644 --- a/src/engine/runtime/fast/fast.ml +++ b/src/engine/runtime/fast/fast.ml @@ -12,6 +12,7 @@ let create () = let has_detonated = ref false in let wait, detonate = Fut.create () in let wait = Fut.map (fun () -> has_detonated := true) wait in + let detonate () = if !has_detonated then () else detonate () in { wait; has_detonated; detonate } type mode = Normal of hurry_bomb | Counting_for_toc | Fast | Slow diff --git a/src/engine/runtime/step/actions_.ml b/src/engine/runtime/step/actions_.ml index 66a4e126..2e0a443f 100644 --- a/src/engine/runtime/step/actions_.ml +++ b/src/engine/runtime/step/actions_.ml @@ -765,7 +765,7 @@ module Play_media = struct type args = Brr.El.t list let parse_args = Parse.parse_only_els - let log_error = function Ok x -> x | Error x -> Brr.Console.(log [ x ]) + let log_error = function Ok x -> x | Error x -> Brr.Console.(error [ x ]) let do_ ~mode _window elems = only_if_not_counting mode @@ fun _mode -> @@ -791,6 +791,12 @@ module Play_media = struct let e = Brr_io.Media.El.of_el e in let () = if is_speaker_note then Brr_io.Media.El.set_muted e true in let current = Brr_io.Media.El.current_time_s e in + let () = + (* Strangely, without this, at least in my setup, firefox often + waits several seconds before showing the video, even in a very + simple html file just playing the file. *) + Brr_io.Media.El.set_current_time_s e current + in let is_playing = not @@ Brr_io.Media.El.paused e in let undo () = let+ res = @@ -805,22 +811,39 @@ module Play_media = struct let when_slow hurry_bomb = Brr.Console.(log [ "Playing" ]); let fut, activate = Fut.create () in + let activate = + let did = ref false in + fun () -> + let old_did = !did in + did := true; + if not old_did then activate () + in let _ = let+ () = Fast.wait hurry_bomb in - set_current_time_s e (duration_s e); + let duration = duration_s e in + if not @@ Float.is_nan duration then + set_current_time_s e duration; activate () in let _unlisten = - Brr.Ev.listen Brr.Ev.ended + let opts = Brr.Ev.listen_opts ~once:true () in + Brr.Ev.listen ~opts Brr.Ev.ended (fun _ev -> activate ()) (e |> Brr_io.Media.El.to_el |> Brr.El.as_target) in let* err = Brr_io.Media.El.play e in - match err with Ok () -> fut | Error _e -> fut + match err with + | Ok () -> fut + | Error e -> + Brr.Console.(error [ e ]); + activate (); + fut in let when_fast () = Brr.Console.(log [ "Just setting current time" ]); - Fut.return @@ set_current_time_s e (duration_s e) + let duration = duration_s e in + if Float.is_nan duration then Fut.return () + else Fut.return @@ set_current_time_s e duration in match mode with | Fast.Normal hurry_bomb when not (Fast.has_detonated hurry_bomb) ->