@@ 90,17 90,13 @@ functor BlockStreamFromStatefulFn (S: ST
end = struct
structure SampleMatrix = S.SampleMatrix
-
- datatype action =
- ACT_READ
- | ACT_SEEK of SampleStreamTypes.seek_mode * RealTime.t
datatype block_stream =
- BLOCK of RealTime.t * SampleMatrix.matrix * (action -> block_stream)
- | END of RealTime.t * (action -> block_stream)
+ BLOCK of RealTime.t * SampleMatrix.matrix * (unit -> block_stream)
+ | END of RealTime.t
datatype read_state =
- READ of RealTime.t * SampleMatrix.matrix * (action -> block_stream)
+ READ of RealTime.t * SampleMatrix.matrix * (unit -> block_stream)
| UNREAD of S.stream
| EOS of RealTime.t
@@ 111,59 107,57 @@ functor BlockStreamFromStatefulFn (S: ST
channels : int,
blocksize : int,
time : RealTime.t,
- seekable : SampleStreamTypes.seekable,
bstr : block_stream
}
type new_args = { blocksize : int } * S.new_args
fun thunk_for (upstream : S.stream, blocksize : int)
- : (action -> block_stream) =
+ : (unit -> block_stream) =
let val rs : read_state ref = ref (UNREAD upstream)
-
- fun read () =
- case (! rs) of
- READ result => BLOCK result
- | UNREAD upstream =>
- (case S.read (upstream, blocksize) of
- NONE =>
- let val t = S.time upstream
- in
- rs := EOS t;
- END (t, thunk_for (upstream, blocksize))
- end
- | SOME matrix =>
- let val result =
- (S.time upstream, matrix,
- thunk_for (upstream, blocksize))
- in
- rs := READ result;
- BLOCK result
- end)
- | EOS t => END (t, thunk_for (upstream, blocksize))
-
- fun seek (m, t) =
- case S.seek (upstream, m, t) of
- false => END (t, thunk_for (upstream, blocksize))
- | true =>
- case thunk_for (upstream, blocksize) ACT_READ of
- BLOCK result => (rs := READ result;
- BLOCK result) (* will be discarded *)
- | END (t, thunk) => END (t, thunk)
in
- fn action => case action of
- ACT_READ => read ()
- | ACT_SEEK (m, t) => seek (m, t)
+ fn () =>
+ case (!rs) of
+ READ result => BLOCK result
+ | UNREAD upstream =>
+ (case S.read (upstream, blocksize) of
+ NONE =>
+ let val t = S.time upstream
+ in
+ rs := EOS t;
+ END t
+ end
+ | SOME matrix =>
+ let val result =
+ (S.time upstream, matrix,
+ thunk_for (upstream, blocksize))
+ in
+ rs := READ result;
+ BLOCK result
+ end)
+ | EOS t => END t
end
fun rate ({ rate, ... } : stream) = rate
fun channels ({ channels, ... } : stream) = channels
fun blocksize ({ blocksize, ... } : stream) = blocksize
fun time ({ time, ... } : stream) = time
- fun seekable ({ seekable, ... } : stream) = seekable
-
- fun read (s as { rate, channels, blocksize, time, seekable, bstr }
- : stream) =
+
+ (* Seeking isn't possible - our read-thunk needs to be the only
+ thing that reads on the underlying mutable stream, and it can't
+ allow the stream to be relocated under it.
+
+ If seeking is essential, alternatives may include:
+ - Finding a way that does not use a stateful stream!
+ - Going via a random-access (which is seekable because it
+ caches the whole stream)
+ - Managing seeks at a higher level, discarding and rebuilding
+ the block stream entirely when the underlying stateful
+ stream needs to be relocated
+ *)
+ fun seekable s = SampleStreamTypes.NON_SEEKABLE
+
+ fun read (s as { rate, channels, blocksize, time, bstr } : stream) =
case bstr of
END _ => NONE
| BLOCK (time, matrix, thunk) =>
@@ 171,40 165,20 @@ functor BlockStreamFromStatefulFn (S: ST
channels = channels,
blocksize = blocksize,
time = time,
- seekable = seekable,
- bstr = thunk ACT_READ
+ bstr = thunk ()
},
matrix)
fun foldl f = BlockStreamFolder.makeFoldl (read, f)
- fun seek (s as { rate, channels, blocksize, time, seekable, bstr }
- : stream, m, t) =
- case seekable of
- SampleStreamTypes.NON_SEEKABLE => NONE
- | _ =>
- let val thunk = case bstr of END (_, thunk) => thunk
- | BLOCK (_, _, thunk) => thunk
- in
- case thunk (ACT_SEEK (m, t)) of
- END _ => NONE
- | BLOCK (time, matrix, thunk) =>
- SOME { rate = rate,
- channels = channels,
- blocksize = blocksize,
- time = time,
- seekable = seekable,
- bstr = thunk ACT_READ
- }
- end
+ fun seek (s, m, t) = NONE
fun wrap ({ blocksize : int }, upstream : S.stream) : stream = {
rate = S.rate upstream,
channels = S.channels upstream,
blocksize = blocksize,
time = S.time upstream,
- seekable = S.seekable upstream,
- bstr = thunk_for (upstream, blocksize) ACT_READ
+ bstr = thunk_for (upstream, blocksize) ()
}
fun new (args, theirArgs) : stream =