nandi/jolt-nativepublic Fork 0
fc16d8e4f1cf0b5245d833bf4521e99d73b72df4
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.

Bring vidya in cfd3e36 · on fc16d8e4f1cf0b5245d833bf4521e99d73b72df4 · nandi · 19d ago
ffi.jolt · 121 lines · 6.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
(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-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)

;; --- 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 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 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))))