Here is a short attempt at something that might do what you want. You have a “frame producer” task that is pushing frames into a channel that is being consumed in another task that shows these frames. You have another channel for changing the state of the task showing the frames so that it will stop playing which can be called from “toplevel”.
using Observables
@enum MovieState begin
PAUSED
PLAYING
end
const FRAME_CHANNEL = Channel{Float64}() # could buffer frames?
const STATE_CHANNEL = Channel{MovieState}()
function movie_controller()
state = PLAYING
while true
if isready(STATE_CHANNEL)
state = take!(STATE_CHANNEL)
while state == PAUSED # wait for someone to unpause us
state = take!(STATE_CHANNEL)
end
end
if state == PLAYING
frame = take!(FRAME_CHANNEL)
println("Showing frame: $frame")
end
end
end
function frame_producer()
while true
v = rand() # time to produce a frame
sleep(v)
push!(FRAME_CHANNEL, v)
end
end
@async movie_controller()
@async frame_producer()
play = Observable(false)
on(play) do p
push!(STATE_CHANNEL, p ? PLAYING : PAUSED)
end