diff --git a/lib/xebow/engine.ex b/lib/xebow/engine.ex index bc54dcf..464b62b 100644 --- a/lib/xebow/engine.ex +++ b/lib/xebow/engine.ex @@ -6,8 +6,6 @@ defmodule Xebow.Engine do use GenServer - import Xebow.Utils, only: [mod: 2] - alias Xebow.Animation defmodule State do @@ -35,22 +33,6 @@ defmodule Xebow.Engine do GenServer.start_link(__MODULE__, {initial_animation, paintables}, name: __MODULE__) end - @doc """ - Cycle to the next animation and play it. - """ - @spec next_animation :: :ok - def next_animation do - GenServer.cast(__MODULE__, :next_animation) - end - - @doc """ - Cycle to the previous animation and play it. - """ - @spec previous_animation :: :ok - def previous_animation do - GenServer.cast(__MODULE__, :previous_animation) - end - @doc """ Play the given animation. @@ -145,31 +127,8 @@ defmodule Xebow.Engine do end @impl GenServer - def handle_cast(:next_animation, state) do - animation_types = Animation.types() - num = Enum.count(animation_types) - current = Enum.find_index(animation_types, &(&1 == state.animation.type)) - next = mod(current + 1, num) - animation_type = Enum.at(animation_types, next) - animation = Animation.new(type: animation_type) - - {:noreply, set_animation(state, animation)} - end - - @impl GenServer - def handle_cast(:previous_animation, state) do - animation_types = Animation.types() - num = Enum.count(animation_types) - current = Enum.find_index(animation_types, &(&1 == state.animation.type)) - previous = mod(current - 1, num) - animation_type = Enum.at(animation_types, previous) - animation = Animation.new(type: animation_type) - - {:noreply, set_animation(state, animation)} - end - - @impl GenServer - def handle_cast({:play_animation, %{loop: loop} = animation}, state) when loop >= 1 do + def handle_cast({:play_animation, %{loop: loop} = animation}, state) + when is_integer(loop) and loop >= 1 do current_animation = state.animation expected_duration = Animation.duration(animation) Process.send_after(self(), {:reset_animation, current_animation}, expected_duration) @@ -188,7 +147,8 @@ defmodule Xebow.Engine do end @impl GenServer - def handle_call({:play_animation, %{loop: loop} = animation}, from, state) when loop >= 1 do + def handle_call({:play_animation, %{loop: loop} = animation}, from, state) + when is_integer(loop) and loop >= 1 do current_animation = state.animation duration = Animation.duration(animation) Process.send_after(self(), {:reply, from, current_animation}, duration) diff --git a/lib/xebow/keys.ex b/lib/xebow/keys.ex index c1fcf08..01ac1be 100644 --- a/lib/xebow/keys.ex +++ b/lib/xebow/keys.ex @@ -73,8 +73,25 @@ defmodule Xebow.Keys do # Client - def start_link([], opts \\ []) do - GenServer.start_link(__MODULE__, [], opts) + @spec start_link(any()) :: GenServer.on_start() + def start_link(_) do + GenServer.start_link(__MODULE__, [], name: __MODULE__) + end + + @doc """ + Cycle to the next animation + """ + @spec next_animation() :: :ok + def next_animation do + GenServer.cast(__MODULE__, :next_animation) + end + + @doc """ + Cycle to the previous animation + """ + @spec previous_animation() :: :ok + def previous_animation do + GenServer.cast(__MODULE__, :previous_animation) end # Server @@ -102,20 +119,65 @@ defmodule Xebow.Keys do poll_timer_ms = 15 :timer.send_interval(poll_timer_ms, self(), :update_pin_values) + animations = + Animation.types() + |> Enum.map(&Animation.new(type: &1)) + {:ok, %{ pins: pins, keyboard_state: keyboard_state, - hid: hid + hid: hid, + animations: animations, + current_animation_index: 0 }} end + @impl GenServer + def handle_cast(:next_animation, state) do + next_index = state.current_animation_index + 1 + + next_index = + case next_index < Enum.count(state.animations) do + true -> next_index + _ -> 0 + end + + animation = Enum.at(state.animations, next_index) + + Xebow.Engine.play_animation(animation) + + state = %{state | current_animation_index: next_index} + + {:noreply, state} + end + + @impl GenServer + def handle_cast(:previous_animation, state) do + previous_index = state.current_animation_index - 1 + + previous_index = + case previous_index < 0 do + true -> Enum.count(state.animations) - 1 + _ -> previous_index + end + + animation = Enum.at(state.animations, previous_index) + + Xebow.Engine.play_animation(animation) + + state = %{state | current_animation_index: previous_index} + + {:noreply, state} + end + @impl GenServer def handle_info({:hid_report, hid_report}, state) do IO.binwrite(state.hid, hid_report) {:noreply, state} end + @impl GenServer def handle_info(:update_pin_values, state) do new_pins = Enum.map(state.pins, fn {pin_number, pin_ref, old_value} -> @@ -158,14 +220,6 @@ defmodule Xebow.Keys do Xebow.Engine.play_animation(animation, async: false) end - def next_animation do - Xebow.Engine.next_animation() - end - - def previous_animation do - Xebow.Engine.previous_animation() - end - def start_wifi_wizard do case VintageNetWizard.run_wizard() do :ok -> flash("green")