3 (defclass blockwise-binary-input-stream
(trivial-gray-stream-mixin)
4 ((refill-buffer-function)
5 (buflen :initarg
:buflen
:initform
256)
7 (buffer-fill :initform
0)
8 (buffer-pointer :initform
0)
12 "This is an input stream that reads input from a function,
13 REFILL-BUFFER-FUNCTION, which has the signature
15 (REFILL-BUFFER-FUNCTION buffer length)
17 where BUFFER is an array of length LENGTH. The function must return two
18 values: the number of bytes read and nil/t depending on whether we've got to
21 There is a STREAM-READ-BYTE function specialized on this class, which 'does
24 (defmethod initialize-instance :after
((stream blockwise-binary-input-stream
)
26 (setf (slot-value stream
'buffer
)
27 (make-array (slot-value stream
'buflen
)
28 :element-type
'(unsigned-byte 8))))
30 (defmethod stream-open ((stream blockwise-binary-input-stream
))
31 "On the superclass, this is a no-op." nil
)
33 (defclass sane-blocking-stream
(blockwise-binary-input-stream)
34 ((device :reader device
:initarg
:device
)
35 (parameters :reader parameters
:initform nil
))
38 "SANE-BLOCKING-STREAM masks reading from a scanner device as reading from a
39 stream. Once STREAM-OPEN has been called on the stream, the PARAMETERS slot will
40 contain an instance of the SANE::PARAMETERS class valid for the scanner. In
41 particular, since sane_start will have been called, the members will be valid at
44 (defmethod initialize-instance :before
((stream sane-blocking-stream
)
46 (unless (subtypep (type-of device
) 'device
)
47 (error "Cannot create a sane-blocking-stream with a device of type ~A"
50 (setf (slot-value stream
'device
) device
)
52 (setf (slot-value stream
'refill-buffer-function
)
53 (lambda (buffer length
) (refill-buffer! buffer
(handle device
)
56 (defmethod stream-open ((stream sane-blocking-stream
))
57 "Open the scanner as a stream. After this operation, the PARAMETERS slot is
59 (ensure-ok (sane-lowlevel::sane_start
(handle (device stream
)))
60 "Could not start scanning operation.")
61 (setf (slot-value stream
'parameters
) (get-parameters (device stream
))))
63 (defmethod stream-read-byte ((stream blockwise-binary-input-stream
))
64 (with-slots (buffer buffer-fill buffer-pointer eof refill-buffer-function
)
67 ((< buffer-pointer buffer-fill
)
69 (aref buffer
(1- buffer-pointer
)))
74 (multiple-value-bind (length-read now-eof
)
75 (funcall refill-buffer-function buffer
(slot-value stream
'buflen
))
77 (setf buffer-fill length-read
)
78 (setf buffer-pointer
0)
79 (stream-read-byte stream
))))))
81 (defun refill-buffer! (buffer handle length
)
84 (with-foreign-objects ((fbuffer :uchar length
)
87 (case (sane-lowlevel::sane_read handle fbuffer
89 (:SANE_STATUS_GOOD nil
)
91 ((:SANE_STATUS_EOF
:SANE_STATUS_CANCELLED
)
95 (error "Unhandled error refilling buffer.")))
97 (iterate (for i from
0 to
(1- (mem-ref length-read
:int
)))
98 (setf (aref buffer i
) (mem-aref fbuffer
:uchar i
)))
100 (values (mem-ref length-read
:int
) eof
))))
102 (defmacro with-open-scanner-stream
(stream device
&body forms
)
103 "Open up a binary gray stream STREAM reading from DEVICE and execute FORMS
106 `(let ((,stream
(make-instance 'sane-blocking-stream
:device
,device
)))
107 (stream-open ,stream
)