Support pausing and resuming schedule playback.

This commit is contained in:
Pim Kunis 2020-10-10 23:03:56 +02:00
parent 12e17d261f
commit e12fd31c92

View file

@ -23,22 +23,30 @@ defmodule MIDITools.Player do
GenServer.call(__MODULE__, :stop_playing) GenServer.call(__MODULE__, :stop_playing)
end end
def pause do
GenServer.call(__MODULE__, :pause)
end
def resume do
GenServer.call(__MODULE__, :resume)
end
# Server callbacks # Server callbacks
@impl true @impl true
def init(_arg) do def init(_arg) do
{:ok, synth} = MIDISynth.start_link([]) {:ok, synth} = MIDISynth.start_link([])
epoch = Timex.epoch() |> Timex.to_datetime()
{:ok, {:ok,
%{ %{
timer: nil, timer: nil,
schedule: [], schedule: [],
schedule_left: [], schedule_left: [],
start_time: epoch, start_time: nil,
duration: 0, duration: 0,
synth: synth, synth: synth,
repeat: false repeat: false,
pause_time: nil
}} }}
end end
@ -55,7 +63,8 @@ defmodule MIDITools.Player do
start_time = Timex.now() start_time = Timex.now()
timer = start_timer(schedule, start_time) timer = start_timer(schedule, start_time)
{:reply, :ok, %{state | timer: timer, start_time: start_time, schedule_left: schedule}} {:reply, :ok,
%{state | timer: timer, start_time: start_time, schedule_left: schedule, pause_time: nil}}
end end
def handle_call({:set_repeat, repeat}, _from, state) do def handle_call({:set_repeat, repeat}, _from, state) do
@ -63,8 +72,42 @@ defmodule MIDITools.Player do
end end
def handle_call(:stop_playing, _from, %{timer: timer} = state) do def handle_call(:stop_playing, _from, %{timer: timer} = state) do
if timer != nil do
Process.cancel_timer(timer, info: false) Process.cancel_timer(timer, info: false)
{:reply, :ok, %{state | timer: nil}} end
{:reply, :ok, %{state | timer: nil, pause_time: nil}}
end
def handle_call(:pause, _from, %{pause_time: pause_time} = state) when pause_time != nil do
{:reply, {:error, :already_paused}, state}
end
def handle_call(:pause, _from, %{timer: nil} = state) do
{:reply, {:error, :not_started}, state}
end
def handle_call(:pause, _from, %{timer: timer} = state) do
Process.cancel_timer(timer, info: false)
pause_time = Timex.now()
{:reply, :ok, %{state | timer: nil, pause_time: pause_time}}
end
def handle_call(:resume, _from, %{pause_time: nil} = state) do
{:reply, {:error, :not_paused}, state}
end
def handle_call(
:resume,
_from,
%{start_time: start_time, pause_time: pause_time, schedule_left: schedule_left} = state
) do
time_since_pause = Timex.diff(Timex.now(), pause_time, :millisecond)
start_time = DateTime.add(start_time, time_since_pause, :millisecond)
timer = start_timer(schedule_left, start_time)
{:reply, :ok, %{state | timer: timer, start_time: start_time, pause_time: nil}}
end end
@impl true @impl true