main f2d166b

stream.go RawHistoryFolder

1package screencast
2
3import (
4	"time"
5
6	"github.com/bnema/neferwl/internal/ports"
7	"github.com/bnema/purego-pipewire/pipewire"
8	"github.com/bnema/zerobus"
9)
10
11// stream is one cast of a session: a PipeWire node fed with frames that the
12// wayland server renders. Everything here is touched by the owner goroutine
13// only; the PipeWire handler runs on it too, inside Loop.Iterate.
14type stream struct {
15	used bool
16	sess *session
17	id   uint32 // number in the object path
18	cast uint64 // ID in the ports.CastCommands
19	path string
20
21	// Target.
22	output string
23	window ports.WindowID
24	cursor bool
25	maxFPS int
26	// Stream.Parameters: position and size in the compositor space.
27	px, py, pw, ph int32
28
29	// Lifecycle.
30	needOpen  bool // CastOpen is yet to be sent
31	opened    bool // CastOpen was sent
32	needClose bool // CastClose is yet to be sent
33	closing   bool // the session ended: free once no frame is in flight
34	stopped   bool // CastStopped came: the wayland side is done
35
36	// Negotiation.
37	w, h       int // size of the target, from CastSize
38	haveSize   bool
39	needResize bool
40	src        videoSource
41	h2         streamHandler
42	pwState    int32 // last state of the PipeWire stream; -2 before the first
43	seenState  bool  // a state above UNCONNECTED was seen
44	nodeID     uint32
45	announced  bool // PipeWireStreamAdded was sent
46	format     pipewire.VideoFormat
47	fw, fh     int // size the format was negotiated at; 0 while renegotiating
48
49	// Frames.
50	dirty    bool
51	forced   bool // the first frame after STREAMING is not paced by damage
52	inflight bool
53	buf      *pipewire.VideoBuffer
54	lastReq  time.Time
55	seq      uint64
56	pts      time.Duration
57	errs     int // consecutive failed frames
58}
59
60// streamHandler is the pipewire.VideoHandler of a stream. Its callbacks run
61// inside Loop.Iterate: they only record, the pump acts.
62type streamHandler struct{ st *stream }
63
64func (h *streamHandler) StateChanged(state int32, nodeID uint32, _ string) {
65	st := h.st
66	st.pwState = state
67	if nodeID != 0 {
68		st.nodeID = nodeID
69	}
70	if state > pipewire.StreamStateUnconnected {
71		st.seenState = true
72	}
73	if state == pipewire.StreamStateStreaming {
74		st.forced = true
75	}
76}
77
78func (h *streamHandler) FormatChanged(f pipewire.VideoFormat, w, hh, _ int) {
79	h.st.format, h.st.fw, h.st.fh = f, w, hh
80	// A new format shows a new picture: the first frame is not paced by damage.
81	h.st.forced = true
82}
83
84// BuffersChanged: the next pump looks for a free buffer anyway.
85func (h *streamHandler) BuffersChanged() {}
86
87// close ends the stream on the wayland side; the slot is freed by reap once
88// no frame is in flight.
89func (st *stream) close() {
90	if st.closing {
91		return
92	}
93	st.closing = true
94	st.needOpen = false
95	st.needClose = st.opened && !st.stopped
96}
97
98// encodeParameters writes the a{sv} of Stream.Parameters.
99func encodeParameters(e *zerobus.Encoder, st *stream) {
100	a := e.BeginArray('{')
101	e.Struct()
102	e.Str("position")
103	e.Variant("(ii)")
104	e.Struct()
105	e.Int32(st.px)
106	e.Int32(st.py)
107	e.Struct()
108	e.Str("size")
109	e.Variant("(ii)")
110	e.Struct()
111	e.Int32(st.pw)
112	e.Int32(st.ph)
113	e.EndArray(a)
114}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 25

Tags 10

↑↓ moveenter openesc close