-
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathsegment.lisp
148 lines (117 loc) · 6.02 KB
/
segment.lisp
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
145
146
147
148
(in-package #:org.shirakumo.fraf.harmony)
(stealth-mixin:define-stealth-mixin buffer () mixed::bip-buffer
((from :initform NIL :accessor from)
(from-location :initform NIL :accessor from-location)
(to :initform NIL :accessor to)
(to-location :initform NIL :accessor to-location)))
(defmethod print-object ((buffer buffer) stream)
(print-unreadable-object (buffer stream :type T :identity T)
(format stream "~a <-> ~a" (from buffer) (to buffer))))
(stealth-mixin:define-stealth-mixin segment () mixed:segment
((name :initarg :name :initform NIL :reader name)
(chain :initform NIL :accessor chain)))
(defmethod print-object ((segment segment) stream)
(print-unreadable-object (segment stream :type T :identity (null (name segment)))
(format stream "~@[~s~]" (name segment))))
(defmethod (setf mixed:pack) :after ((buffer buffer) (segment segment))
(typecase segment
((or mixed:source mixed:packer)
(setf (from buffer) segment))
((or mixed:drain mixed:unpacker)
(setf (to buffer) segment))))
(defmethod (setf mixed:output-field) :after ((buffer buffer) (field (eql :buffer)) (location integer) (segment segment))
(setf (from buffer) segment)
(setf (from-location buffer) location))
(defmethod (setf mixed:output-field) :after ((buffer buffer) (field (eql :pack)) (location integer) (segment segment))
(setf (from buffer) segment)
(setf (from-location buffer) location))
(defmethod (setf mixed:input-field) :after ((buffer buffer) (field (eql :buffer)) (location integer) (segment segment))
(setf (to buffer) segment)
(setf (to-location buffer) location))
(defmethod (setf mixed:input-field) :after ((buffer buffer) (field (eql :pack)) (location integer) (segment segment))
(setf (to buffer) segment)
(setf (to-location buffer) location))
(defmethod connect ((from segment) from-loc (to segment) to-loc)
(let ((buffer (or (mixed:output from-loc from) (allocate-buffer *server*))))
(mixed:connect from from-loc to to-loc buffer)))
(defmethod connect ((from segment) (all (eql T)) (to segment) (_all (eql T)))
(loop for i from 0 below (getf (mixed:info from) :outputs)
do (connect from i to i)))
(defmethod connect ((from segment) (all (eql T)) (to mixed:basic-mixer) (_all (eql T)))
(loop for i from 0 below (getf (mixed:info from) :outputs)
do (connect from i to T)))
(defmethod connect ((from segment) (all (eql T)) (to mixed:space-mixer) (_all (eql T)))
(when (< 1 (getf (mixed:info from) :outputs))
(error "Cannot connect a segment with more than one output to a space mixer; dangling buffers."))
(connect from 0 to T))
(defmethod connect ((from segment) (all (eql T)) (to mixed:plane-mixer) (_all (eql T)))
(when (< 1 (getf (mixed:info from) :outputs))
(error "Cannot connect a segment with more than one output to a space mixer; dangling buffers."))
(connect from 0 to T))
(defmethod disconnect ((from segment) from-loc &key (direction :output))
(let ((buffer (ecase direction
(:output (mixed:output from-loc from))
(:input (mixed:input from-loc from)))))
(when buffer
(when (from buffer)
(ignore-errors (setf (mixed:output (from-location buffer) (from buffer)) NIL)))
(when (to buffer)
(ignore-errors (setf (mixed:input (to-location buffer) (to buffer)) NIL)))
(free-buffer buffer *server*))))
(defmethod disconnect ((from segment) (all (eql T)) &key (direction :output))
(when (mixed:handle from)
(loop for i from 0 below (ecase direction
(:output (getf (mixed:info from) :outputs))
(:input (getf (mixed:info from) :inputs)))
do (disconnect from i :direction direction))))
(defmethod mixed:add :before ((segment segment) (chain mixed:chain))
(when (chain segment)
(cerror "Do it anyway." "Segment~% ~a~%is already present on chain~% ~a~%cannot add it to~% ~a"
segment (chain segment) chain)))
(defmethod mixed:add :after ((segment segment) (chain mixed:chain))
(setf (chain segment) chain))
(defmethod mixed:withdraw :after ((segment segment) (chain mixed:chain))
(when (eql (chain segment) chain)
(setf (chain segment) NIL)))
(defmethod mixed:withdraw ((segment segment) (chain (eql T)))
(when (chain segment)
(mixed:withdraw segment (chain segment))))
(defun default-source-end (source)
(disconnect source T))
(defmethod downstream ((segment segment) index)
(to (mixed:output index segment)))
(defmethod upstream ((segment segment) index)
(from (mixed:input index segment)))
(stealth-mixin:define-stealth-mixin source (segment) mixed:source
((repeat :initarg :repeat :initform 0 :accessor repeat)
(repeat-start :initarg :repeat-start :initform 0 :accessor repeat-start)
(on-end :initarg :on-end :initform (constantly NIL) :accessor on-end)
(on-frame-change :initarg :on-frame-change :initform (constantly NIL) :accessor on-frame-change)))
(defmethod (setf mixed:done-p) :around (value (source source))
(if value
(case (repeat source)
((0 NIL)
(call-next-method)
(funcall (on-end source) source))
((T)
(mixed:seek source (repeat-start source) :by :second))
(T
(mixed:seek source (repeat-start source) :by :second)
(decf (repeat source))))
(call-next-method))
value)
(defmethod (setf mixed:frame-position) :before (new (source source))
(funcall (on-frame-change source) source new))
(defmethod mixed:unpacker ((source source))
(to (mixed:pack source)))
;;; Always delegate to pack, since we never want to interfere between
;;; a source and its pack
(defmethod connect ((from source) from-loc (to segment) to-loc)
(connect (mixed:unpacker from) from-loc to to-loc))
(defmethod disconnect ((from source) from-loc &key (direction :output))
(when (mixed:unpacker from)
(disconnect (mixed:unpacker from) from-loc :direction direction)))
(defmethod mixed:volume ((source source))
(mixed:volume (mixed:unpacker source)))
(defmethod (setf mixed:volume) (value (source source))
(setf (mixed:volume (mixed:unpacker source)) value))