nandi/jolt-nativepublic Fork 0
aabacba05769796ca2b8dde03e3f925d33ba6653
Commits
Clone
git clone https://git.rickub.com/nandi/jolt-native.git
git clone ssh://git@rickub.com/nandi/jolt-native.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Let the window be renamed after it opens 5adddc7 · on aabacba05769796ca2b8dde03e3f925d33ba6653 · nandi · 19d ago
ffi.jolt · 144 lines · 7.0 KBGDScript3 Blame HistoryRaw
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
(ns glimmer-vidya.ffi
  "Raw bindings for Vidya's retained-tree ABI (`ffi/include/vidya_tree.h`).

  Nothing here interprets a prop or an event; that is
  `glimmer-vidya.core`'s job. This namespace exists so the boundary is one
  readable list of symbols, and so the marshalling rules that come with it 
  which pointers die when, which calls must stay on the window thread  are
  stated once.

  **Strings returned by this library are borrowed.** `node-get-str`,
  `event-name` and `event-text` all answer the same scratch buffer, which the
  next such call overwrites. Jolt copies a `:string` return into a Scheme
  string as it crosses, so holding the value is safe; holding the *pointer* is
  not, and there is no way to do that from here anyway.

  **Every call belongs to the thread that opened the window.** The library
  keeps its state in thread-local storage, so a call from anywhere else is
  inert rather than unsound  but it is still a bug. `glimmer-vidya.core`
  routes off-thread work through glimmer's `schedule`."
  (:require [jolt.ffi :as ffi]))

;; --- window and frame (shared with the push/pop ABI) -------------------------
(ffi/defcfn raw-open "vidya_open" [:int :int :string] :int)
(ffi/defcfn close! "vidya_close" [] :void)
(ffi/defcfn raw-should-close "vidya_should_close" [] :int)
(ffi/defcfn set-title! "vidya_set_title" [:string] :void)
(ffi/defcfn set-target-fps! "vidya_set_target_fps" [:int] :void)
(ffi/defcfn set-mode! "vidya_set_mode" [:int] :void)
(ffi/defcfn raw-load-font "vidya_load_font" [:string :int] :int)

;; --- the tree ----------------------------------------------------------------
(ffi/defcfn tree-root "vidya_tree_root" [] :int)
(ffi/defcfn node-new "vidya_node_new" [:string] :int)
(ffi/defcfn node-free! "vidya_node_free" [:int] :void)
(ffi/defcfn raw-node-exists "vidya_node_exists" [:int] :int)

(ffi/defcfn node-set-str! "vidya_node_set_str" [:int :string :string] :void)
(ffi/defcfn node-set-num! "vidya_node_set_num" [:int :string :double] :void)
(ffi/defcfn raw-node-set-bool "vidya_node_set_bool" [:int :string :int] :void)
(ffi/defcfn node-clear-props! "vidya_node_clear_props" [:int] :void)

(ffi/defcfn node-get-str "vidya_node_get_str" [:int :string] :string)
(ffi/defcfn node-get-num "vidya_node_get_num" [:int :string] :double)
(ffi/defcfn raw-node-get-bool "vidya_node_get_bool" [:int :string] :int)

(ffi/defcfn node-tag "vidya_node_tag" [:int] :string)
(ffi/defcfn node-child-count "vidya_node_child_count" [:int] :int)
(ffi/defcfn node-child-at "vidya_node_child_at" [:int :int] :int)
(ffi/defcfn tree-dump "vidya_tree_dump" [:int] :string)

(ffi/defcfn raw-node-append "vidya_node_append" [:int :int] :int)
(ffi/defcfn node-remove! "vidya_node_remove" [:int :int] :void)
(ffi/defcfn raw-node-insert-after "vidya_node_insert_after" [:int :int :int] :int)
(ffi/defcfn raw-node-replace "vidya_node_replace" [:int :int :int] :int)

;; --- frame and events --------------------------------------------------------
(ffi/defcfn tree-frame! "vidya_tree_frame" [] :void)
(ffi/defcfn raw-poll-event "vidya_tree_poll_event" [] :int)
(ffi/defcfn event-node "vidya_tree_event_node" [] :int)
(ffi/defcfn event-name "vidya_tree_event_name" [] :string)
(ffi/defcfn event-text "vidya_tree_event_text" [] :string)
(ffi/defcfn event-num "vidya_tree_event_num" [] :double)


;; --- the window --------------------------------------------------------------
;; Its size in points, following the window as it is dragged. Points rather
;; than pixels because a caller asking is about to lay something out.
(ffi/defcfn screen-width "vidya_screen_width" [] :float)
(ffi/defcfn screen-height "vidya_screen_height" [] :float)

;; --- live frames -------------------------------------------------------------
;; Pixels pushed in under a name, painted by an `:image` whose `:feed` names it.
;; `rgba` is a foreign pointer to width*height*4 bytes, copied before the call
;; returns  the backend keeps nothing, so the caller may reuse its buffer. The
;; pointer form is the point: a video frame moved through jolt as a byte array
;; would be copied twice a frame for nothing.
(ffi/defcfn raw-frame-rgba "vidya_frame_rgba" [:string :int :int :pointer] :int)
(ffi/defcfn raw-frame-drop "vidya_frame_drop" [:string] :int)

;; --- the clipboard -----------------------------------------------------------
;; Not an event: egui carries clipboard text into a frame and nothing else, so a
;; pasted picture is asked for rather than waited for.
(ffi/defcfn raw-clipboard-image-png "vidya_clipboard_image_png" [:string] :int)

;; --- the browser -------------------------------------------------------------
;; Leaving for a page and coming back is the platform's business: xdg-open on a
;; desktop, an ACTION_VIEW intent on Android.
(ffi/defcfn raw-open-url "vidya_open_url" [:string] :int)

;; --- the platform's picture chooser ------------------------------------------
;; Opened here, answered later: the reader leaves for a screen of the system's
;; own, so the pick is polled for rather than returned.
(ffi/defcfn raw-pick-image "vidya_pick_image" [] :int)
(ffi/defcfn raw-picked-image "vidya_picked_image" [:string] :int)

;; --- the int/bool seam -------------------------------------------------------
;; C has no booleans; every predicate here crosses as 0 or 1. Converting at the
;; binding rather than at each call site keeps the rest of the backend written
;; in jolt's own truthiness.

(def dark-mode 0)
(def light-mode 1)

(defn open!
  [width height title]
  (not (zero? (raw-open width height title))))

(defn should-close? [] (not (zero? (raw-should-close))))
(defn load-font! [path] (not (zero? (raw-load-font path 32))))
(defn node-exists? [node] (not (zero? (raw-node-exists node))))
(defn node-set-bool! [node key value] (raw-node-set-bool node key (if value 1 0)))
(defn node-get-bool [node key] (not (zero? (raw-node-get-bool node key))))
(defn node-append! [parent child] (not (zero? (raw-node-append parent child))))
(defn clipboard-image-png!
  "Write the clipboard's picture to `path` as a PNG; true when there was one."
  [path]
  (not (zero? (raw-clipboard-image-png path))))
(defn open-url!
  "Hand `url` to the platform's browser; true when something took it."
  [url]
  (not (zero? (raw-open-url url))))
(defn pick-image!
  "Open the platform's picture chooser; true when one opened."
  []
  (not (zero? (raw-pick-image))))
(defn picked-image!
  "Move the picture chosen since the last call to `path`; true when there was
  one."
  [path]
  (not (zero? (raw-picked-image path))))
(defn frame-rgba!
  "Paint `rgba` — a pointer to width*height*4 un-premultiplied bytes — under
  `key`. True when the frame was accepted; false for dimensions the length does
  not match."
  [key width height rgba]
  (not (zero? (raw-frame-rgba key width height rgba))))
(defn frame-drop!
  "Forget the feed named `key`; true when there was one."
  [key]
  (not (zero? (raw-frame-drop key))))
(defn node-insert-after! [parent child sibling]
  (not (zero? (raw-node-insert-after parent child sibling))))
(defn node-replace! [parent old new] (not (zero? (raw-node-replace parent old new))))
(defn poll-event! [] (not (zero? (raw-poll-event))))