Add central reset function.

This commit is contained in:
Pim Kunis 2020-10-11 16:26:37 +02:00
parent 95a0712041
commit 362826eb2f

View file

@ -2,7 +2,7 @@ defmodule MIDITools.Player do
use GenServer use GenServer
@moduledoc """ @moduledoc """
A GenServer for playing a schedule of MIDI commands at certain times. A GenServer for playing a schedule of MIDI commands at predefined times.
""" """
# Client API # Client API
@ -16,18 +16,19 @@ defmodule MIDITools.Player do
end end
@doc """ @doc """
Set the current schedule and total duration for the MIDI player. Generate the current schedule defined by the given events.
The list of events is internally converted to MIDI commands. The list of events is internally converted to MIDI commands.
If multiple events are scheduled on the same time, If multiple events are scheduled on the same time,
then they are executed in the same order as in the list. then they are executed in the same order as in the list.
The duration makes sure the player plays a (potential) pause after the last The duration makes sure the player plays a (potential) pause after the last
midi command. midi command.
See `MIDITools.Event` to create events.
""" """
@spec set_schedule([MIDITools.Event.t()], non_neg_integer()) :: :ok @spec generate_schedule([MIDITools.Event.t()], non_neg_integer()) :: :ok
def set_schedule(events, duration) do def generate_schedule(events, duration) when duration > 0 do
schedule = convert_events(events) GenServer.call(__MODULE__, {:generate_schedule, events, duration})
GenServer.call(__MODULE__, {:set_schedule, schedule, duration})
end end
@doc """ @doc """
@ -90,33 +91,25 @@ defmodule MIDITools.Player do
end end
@impl GenServer @impl GenServer
def handle_call({:set_schedule, schedule, duration}, _from, state) do def handle_call({:generate_schedule, events, duration}, _from, state) do
state = %{state | schedule: convert_events(events)}
{:reply, :ok, %{state | schedule: schedule, schedule_left: schedule, duration: duration}} {:reply, :ok, %{reset(state) | duration: duration}}
end
def handle_call(:play, _from, %{timer: timer, schedule: schedule} = state) do
if timer != nil do
Process.cancel_timer(timer, info: false)
end end
def handle_call(:play, _from, %{schedule: schedule} = state) do
start_time = Timex.now() start_time = Timex.now()
timer = start_timer(schedule, start_time) timer = start_timer(schedule, start_time)
{:reply, :ok, {:reply, :ok,
%{state | timer: timer, start_time: start_time, schedule_left: schedule, pause_time: nil}} %{reset(state) | timer: timer, start_time: start_time}}
end end
def handle_call({:set_repeat, repeat}, _from, state) do def handle_call({:set_repeat, repeat}, _from, state) do
{:reply, :ok, %{state | repeat: repeat}} {:reply, :ok, %{state | repeat: repeat}}
end end
def handle_call(:stop_playing, _from, %{timer: timer} = state) do def handle_call(:stop_playing, _from, state) do
if timer != nil do {:reply, :ok, reset(state)}
Process.cancel_timer(timer, info: false)
end
{:reply, :ok, %{state | timer: nil, pause_time: nil}}
end end
def handle_call(:pause, _from, %{pause_time: pause_time} = state) when pause_time != nil do def handle_call(:pause, _from, %{pause_time: pause_time} = state) when pause_time != nil do
@ -223,4 +216,12 @@ defmodule MIDITools.Player do
end) end)
|> Enum.sort() |> Enum.sort()
end end
defp reset(%{timer: timer, schedule: schedule} = state) do
if timer != nil do
Process.cancel_timer(timer, info: false)
end
%{state | timer: nil, pause_time: nil, schedule_left: schedule}
end
end end