Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for rendering images on wezterm #4

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions app/capymanga/src/capymanga.ml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ let command =
Command.async_or_error
~summary:{|Capy manga!|}
[%map_open.Command
let () = return () in
let () = return ()
and use_wezterm = flag "use-wezterm" no_arg ~doc:" Use wezterm to render images" in
fun () ->
let open Deferred.Or_error.Let_syntax in
let app =
Expand All @@ -66,7 +67,7 @@ let command =
|> Outside_world.Chapter_images.register_real
|> Outside_world.Scanlation_group.register_real
in
let%bind () = Capytui.start_with_images app in
let%bind () = Capytui.start_with_images app ~use_wezterm in
Deferred.Or_error.return ()]
;;

Expand Down
2 changes: 2 additions & 0 deletions lib/capytui/src/capy.ml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ let start
?bpaste
?optimize
?target_frames_per_second
?use_wezterm
(app : Node.t Bonsai.Computation.t)
=
Loop.start
Expand All @@ -23,6 +24,7 @@ let start
?bpaste
?optimize
?target_frames_per_second
?use_wezterm
(Bonsai.Computation.map app ~f:(fun app -> app, []))
;;

Expand Down
2 changes: 2 additions & 0 deletions lib/capytui/src/capy.mli
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ val start
-> ?bpaste:bool
-> ?optimize:bool
-> ?target_frames_per_second:int
-> ?use_wezterm:bool
-> Node.t Bonsai.Computation.t
-> unit Async.Deferred.Or_error.t

Expand All @@ -21,6 +22,7 @@ val start_with_images
-> ?bpaste:bool
-> ?optimize:bool
-> ?target_frames_per_second:int
-> ?use_wezterm:bool
-> (Node.t * Image.t list) Bonsai.Computation.t
-> unit Async.Deferred.Or_error.t

Expand Down
3 changes: 3 additions & 0 deletions lib/capytui/src/dune
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
(library
(name capytui)
(libraries core bonsai.driver bonsai notty notty.unix core_unix async)
(foreign_stubs
(language c)
(names stubs))
(preprocess
(pps ppx_jane bonsai.ppx_bonsai)))
92 changes: 78 additions & 14 deletions lib/capytui/src/loop.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,29 @@ open! Core
open Bonsai
open Async

module Stubs = struct
external rows : unit -> int = "caml_ioctl_winsz_rows"
external cols : unit -> int = "caml_ioctl_winsz_cols"
external xpixels : unit -> int = "caml_ioctl_winsz_xpixels"
external ypixels : unit -> int = "caml_ioctl_winsz_ypixels"
end

type window =
{ rows : int
; cols : int
; xpixels : int
; ypixels : int
}

let get_window () =
let open Stubs in
let rows : int = rows ()
and cols : int = cols ()
and xpixels : int = xpixels ()
and ypixels : int = ypixels () in
{ rows; cols; xpixels; ypixels }
;;

let clear_images () =
let _ : _ =
Sys_unix.command
Expand All @@ -12,23 +35,59 @@ let clear_images () =

let draw_command_for_image
{ Image.row; column; url; dimensions = { height; width }; scale }
~use_wezterm
=
let args =
List.concat
[ [ "kitten"; "icat"; "--silent" ]
; (if scale then [ "--scale-up" ] else [])
; [ "--place"
; [%string "'%{width#Int}x%{height#Int}@%{column#Int}x%{row#Int}'"]
; [%string "'%{url}'"]
if not use_wezterm
then (
let args =
List.concat
[ [ "kitten"; "icat"; "--silent" ]
; (if scale then [ "--scale-up" ] else [])
; [ "--place"
; [%string "'%{width#Int}x%{height#Int}@%{column#Int}x%{row#Int}'"]
; [%string "'%{url}'"]
]
]
]
in
String.concat ~sep:" " args ^ " >/dev/tty </dev/tty 2>/dev/null"
in
String.concat ~sep:" " args ^ " >/dev/tty </dev/tty 2>/dev/null")
else (
let _r_width, _r_height =
let window = get_window () in
let height =
Int.of_float
(0.5
*. Int.to_float window.ypixels
*. (Int.to_float height /. Int.to_float window.rows))
in
let width =
Int.of_float
(0.5
*. Int.to_float window.xpixels
*. (Int.to_float width /. Int.to_float window.cols))
in
width, height
in
let args =
List.concat
[ [ [%string "curl -s '%{url}' > /tmp/capy-img && "]
; "wezterm"
; "imgcat"
]
; [ "--position"
; [%string "'%{column#Int},%{row#Int}'"]
(* ; [%string "--width '%{width#Int}'"] *)
; [%string "--height '%{height#Int}'"]
(* ; [%string "--resize '%{r_width#Int}x%{r_height#Int}'"] *)
; "/tmp/capy-img"
]
]
in
String.concat ~sep:" " args ^ " >/dev/tty </dev/tty 2>/dev/null")
;;

let draw_images images =
let draw_images images ~use_wezterm =
(* TODO: Currently drawing images is really slow and blocks user input. *)
if true then clear_images ();
if not use_wezterm then clear_images ();
match images with
| [] -> None
(* TODO: This was an attempt at making a cancellable image renderer. The
Expand All @@ -42,7 +101,9 @@ let draw_images images =
(* | `In_the_parent pid -> Some pid *)
(* | `In_the_child -> *)
List.iter images ~f:(fun image ->
let _ : _ = Sys_unix.command (draw_command_for_image image) in
let _ : _ =
Sys_unix.command (draw_command_for_image image ~use_wezterm)
in
());
None
;;
Expand All @@ -54,6 +115,7 @@ let start
; bpaste
; optimize
; target_frames_per_second
; use_wezterm
; app
}
=
Expand Down Expand Up @@ -102,7 +164,7 @@ let start
let draw_process_pid : Pid.t option =
if is_first_frame
|| not ([%equal: Image.t list] (snd result) (snd prev_result))
then draw_images images
then draw_images images ~use_wezterm
else None
in
let go () = go ~draw_process_pid in
Expand Down Expand Up @@ -145,6 +207,7 @@ let start
?bpaste
?(optimize = true)
?(target_frames_per_second = 60)
?(use_wezterm = false)
(app : (Node.t * Image.t list) Computation.t)
=
Deferred.Or_error.try_with (fun () ->
Expand All @@ -156,6 +219,7 @@ let start
~bpaste
~optimize
~target_frames_per_second
~use_wezterm
~app
in
start params)
Expand Down
1 change: 1 addition & 0 deletions lib/capytui/src/loop.mli
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ val start
-> ?bpaste:bool
-> ?optimize:bool
-> ?target_frames_per_second:int
-> ?use_wezterm:bool
-> (Node.t * Image.t list) Computation.t
-> unit Deferred.Or_error.t
4 changes: 4 additions & 0 deletions lib/capytui/src/start_params.ml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type t =
; bpaste : bool option
; optimize : bool
; target_frames_per_second : int
; use_wezterm: bool
; app : (Node.t * Image.t list) Computation.t
}

Expand All @@ -18,6 +19,7 @@ let sanity_check_exn
; bpaste = _
; optimize = _
; target_frames_per_second
; use_wezterm = _
; app = _
}
=
Expand All @@ -37,6 +39,7 @@ let create_exn
~bpaste
~optimize
~target_frames_per_second
~use_wezterm
~app
=
let out =
Expand All @@ -46,6 +49,7 @@ let create_exn
; bpaste
; optimize
; target_frames_per_second
; use_wezterm
; app
}
in
Expand Down
2 changes: 2 additions & 0 deletions lib/capytui/src/start_params.mli
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type t = private
; bpaste : bool option
; optimize : bool
; target_frames_per_second : int
; use_wezterm: bool
; app : (Node.t * Image.t list) Computation.t
}

Expand All @@ -18,5 +19,6 @@ val create_exn
-> bpaste:bool option
-> optimize:bool
-> target_frames_per_second:int
-> use_wezterm: bool
-> app:(Node.t * Image.t list) Computation.t
-> t
38 changes: 38 additions & 0 deletions lib/capytui/src/stubs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include <caml/alloc.h>
#include <caml/custom.h>
#include <caml/memory.h>
#include <caml/mlvalues.h>

#include <sys/ioctl.h>

CAMLprim value caml_ioctl_winsz_rows(value unit) {
CAMLparam1(unit);

struct winsize sz;
ioctl(0, TIOCGWINSZ, &sz);
CAMLreturn(Int_val(sz.ws_row));
}

CAMLprim value caml_ioctl_winsz_cols(value unit) {
CAMLparam1(unit);

struct winsize sz;
ioctl(0, TIOCGWINSZ, &sz);
CAMLreturn(Int_val(sz.ws_col));
}

CAMLprim value caml_ioctl_winsz_xpixels(value unit) {
CAMLparam1(unit);

struct winsize sz;
ioctl(0, TIOCGWINSZ, &sz);
CAMLreturn(Int_val(sz.ws_xpixel));
}

CAMLprim value caml_ioctl_winsz_ypixels(value unit) {
CAMLparam1(unit);

struct winsize sz;
ioctl(0, TIOCGWINSZ, &sz);
CAMLreturn(Int_val(sz.ws_ypixel));
}
Loading