I’m trying (yet again) to build a video player/explorer in Julia. Everything is looking pretty good, but one hurdle is the play/pause functionality. I want to be able to control the play/pause with an observable (which is connected to a GUI button), but I run into issues with how to accomplish that. In the following setup I use a Channel and an async:
c = Channel{Bool}(false)
@async for _ in c
println("showing a new frame!")
sleep(1)
put!(c, true)
end
play = Observable(false)
on(play) do p
if p
put!(c, true)
else
take!(c)
end
end
Then, if I
play[] = true
it start working, but the pausing part is problematic. If I “press” pause
play[] = false
the whole thing sometimes stalls and becomes unresponsive.
Is there a known way to deal with this pattern? Or am I close…?
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