with Calendar; use Calendar;
with Libmy.MIDI.Portmidi; use Libmy.MIDI.Portmidi;
with Libmy.MIDI.Porttime; use Libmy.MIDI.Porttime;
with Text_Io;
package body Libmy.MIDI.Scheduler is
task body Keyboard is
Pm_Event : PmEvent;
begin
loop
Pm_Event.Message := Read_handler(Keyb_Addr.all);
accept Send(Message : out Long) do
Message := Pm_Event.Message;
end Send;
end loop;
end Keyboard;
task body Input is
Pm_Event : PmEvent;
begin
loop
Pm_Event.Message := Read_handler(Input_Addr.all);
accept Send(Message : out Long) do
Message := Pm_Event.Message;
end Send;
end loop;
end Input;
task body Output is
Pm_Event : PmEvent;
Pm_Error : PmError;
Date : Time := Clock;
Sync : Duration := 0.0;
begin
loop
accept receive(Message : in Long) do
Pm_Event.Message := Message;
end Receive;
if Pm_Event.Message > 0 then
Pm_Event.PmTimestamp := Pt_time;
Pm_Error := Pm_Write(Output_Addr.All, Pm_Event, 1);
end if;
end loop;
Text_Io.Put_Line("End_output_Drivers" );
exception
when others =>
Text_Io.Put_line("exception in output driver." );
end Output;
task body Scheduler is
task Tempo_Drive is
entry Start(Bpm : in Tempo_Type; Top : in Time);
entry Stop;
entry Halt;
end Tempo_Drive;
task body Tempo_Drive is
Suspended, End_Of_Task : Boolean := False;
Tempo_Message : Message_Type;
Tempo_Date : Time := Clock;
Tempo_Sync : Duration;
begin
while not End_Of_Task loop
select
accept Start(Bpm : in Tempo_Type; Top : in Time) do
Suspended := False;
Text_Io.Put_Line("start global." );
Tempo_Sync := duration(60.0/Float(Bpm)/24.0);
Tempo_Date := Top;
end Start;
or
accept Halt do
Text_Io.Put_Line("Halt global." );
Suspended := True;
End_Of_Task := True;
end Halt;
end select;
while not Suspended loop
select
accept Stop do
Text_Io.Put_Line("Stop global." );
Suspended := True;
end Stop;
or
accept Halt do
Text_Io.Put_Line("Halt global." );
Suspended := True;
End_Of_Task := True;
end Halt;
or
delay until Tempo_Date;
Tempo_Date := Tempo_Date + Tempo_Sync;
Tempo_Message := (16#F8#, 0, 0);
Output.Receive(Pm_Message(Tempo_Message));
end select;
end loop;
end loop;
Text_Io.Put_Line("End_Tempo_Drivers" );
exception
when others =>
Text_Io.Put("Exception in Tempo Driver" );
end Tempo_Drive;
The_Sched : Scheduler_Type := (new Seq_Page_Type, new Seq_Page_Type);
The_Step : positive := 1;
The_Page : Boolean := False;
End_Of_Task : Boolean := False;
Suspended : Boolean := False;
Step_Date : Time := Clock;
Step_Sync : Duration;
Message : Long := 0;
Tempo : Tempo_Type := 240.0;
begin
while not End_Of_Task loop
select
accept Start do
Suspended := False;
Step_Sync := Duration(60.0/Float(Tempo)/16.0);
Step_Date := Clock;
The_Step := 1;
Tempo_Drive.Start(Tempo,
Step_Date);
Composer.Composer.Start(The_Sched(not The_Page),
Tempo,
Step_Date);
end Start;
or
accept Halt do
Suspended := True;
End_Of_Task := True;
Composer.Composer.Halt;
Tempo_Drive.Halt;
end Halt;
end select;
delay until Step_Date;
while not Suspended loop
select
accept Stop do
Suspended := True;
Composer.Composer.Stop;
Tempo_Drive.Stop;
end Stop;
or
accept Halt do
Suspended := True;
End_Of_Task := True;
Composer.Composer.Halt;
Tempo_Drive.Halt;
end Halt;
else
-- Reading data in input while not end of step.
while Step_Date > Clock loop
select
keyboard.Send(Message);
Insert(The_Sched(not The_Page).Keyb(The_Step),
Last_index(The_Sched(not The_Page).Keyb(The_Step)) + 1,
Message,
1);
else
null;
end select;
select
input.Send(Message);
Insert(The_Sched(not The_Page).Keyb(The_Step),
Last_index(The_Sched(not The_Page).Keyb(The_Step)) + 1,
Message,
1);
else
null;
end select;
end loop;
-- Writing Data for current step.
if Last_index(The_Sched(The_Page).Output(The_Step)) /= 0 then
for I in 1..Last_index(The_Sched(The_Page).Output(The_Step)) loop
Output.Receive(Element(The_Sched(The_Page).Output(The_Step), i));
end loop;
Clear(The_Sched(The_Page).Output(The_Step));
end if;
-- Step & page managment.
Step_Date := Step_Date + Step_Sync;
if The_Step = Step_Index_Type'Last then
Text_Io.Put(Character'Val(13) & "Step :" &
Step_Index_Type'Image(The_Step));
Text_Io.Put_Line(", change page..." );
The_Step := 1;
The_Page := not The_Page;
Composer.Composer.Switch(The_Sched(not The_Page));
else
Text_Io.Put(Character'Val(13) & "Step :" &
Step_Index_Type'Image(The_Step));
The_Step := The_Step + 1;
end if;
end select;
end loop;
end loop;
abort Keyboard;
abort Input;
abort Output;
Text_Io.Put_Line("End_scheduler" );
exception
when others =>
Text_Io.Put_Line("Exception in scheduler driver" );
end Scheduler;
end Libmy.MIDI.Scheduler;