diff --git a/lib/midi_player.ex b/lib/midi_player.ex index 1573d35..8fc2f5c 100644 --- a/lib/midi_player.ex +++ b/lib/midi_player.ex @@ -5,6 +5,8 @@ defmodule MIDIPlayer do A GenServer for playing a schedule of MIDI commands at predefined times. """ + @type schedule :: [{non_neg_integer(), binary()}] + # Client API @doc """ @@ -66,11 +68,23 @@ defmodule MIDIPlayer do @doc """ Resume playback on the player after it has been paused. """ - @spec(resume() :: :ok, {:error, :not_paused}) + @spec resume() :: :ok | {:error, :not_paused} def resume do GenServer.call(__MODULE__, :resume) end + @doc """ + Get the current schedule of the player. + + The schedule is a list of tuples of a time in milliseconds and the + corresponding bitstream of MIDI commands to be played at that time. + The list is guaranteed to be ascending in time. + """ + @spec get_schedule() :: schedule() + def get_schedule do + GenServer.call(__MODULE__, :get_schedule) + end + # Server callbacks @impl GenServer @@ -142,6 +156,10 @@ defmodule MIDIPlayer do {:reply, :ok, %{state | timer: timer, start_time: start_time, pause_time: nil}} end + def handle_call(:get_schedule, _from, %{schedule: schedule} = state) do + {:reply, schedule, state} + end + @impl GenServer def handle_info( :play, diff --git a/test/player_test.exs b/test/player_test.exs index 9cc48a6..7a00326 100644 --- a/test/player_test.exs +++ b/test/player_test.exs @@ -39,4 +39,20 @@ defmodule MIDIPlayerTest do Player.pause() assert {:error, :already_paused} = Player.pause() end + + test "event conversion" do + event1 = MIDIPlayer.Event.ChangeProgram.new(0, 1, 40) + event2 = MIDIPlayer.Event.Note.new(0, 60, 1, 1000, 127) + events = [event1, event2] + duration = 100 + assert :ok = Player.generate_schedule(events, duration) + + change_program = MIDISynth.Command.change_program(0, 40) + note_on = MIDISynth.Command.note_on(0, 60, 127) + note_off = MIDISynth.Command.note_off(0, 60) + + [command1, command2] = Player.get_schedule() + assert {1, <<^change_program::binary-size(2), ^note_on::binary-size(3)>>} = command1 + assert {1000, ^note_off} = command2 + end end