Previous: Scheduling in Marsyas, Up: Scheduling
The scheduler is made up of a collection of files from those used by the scheduler to those that support it. The classes directly related to the scheduler along with their relationships is shown in See fig:asch1.
Each MarSystem object has its own scheduler. This makes it possbile to post events on the MarSystem object directly. However, once a MarSystem is contained within another (within a Composite) it no longer responds to tick messages. This means that the schedulers in any of the contained objects will remain dormant. Therefore the only operational scheduler in a network is the one in the MarSystem being ticked.
Posting events on the scheduler is done through a number of
updctrl methods. Each one takes a TmTime class as its
first parameter.
void updctrl(EvEvent* me);
void updctrl(TmTime t, EvEvent* ev);
void updctrl(TmTime t, Repeat rep, EvEvent* ev);
void updctrl(TmTime t, std::string cname, MarControlPtr control);
void updctrl(TmTime t, Repeat rep, std::string cname, MarControlPtr control);
Additional methods for adding and removing timers and discovering the
current time on a timer are available. The updtimer method is
provided to modify timer parameters at run-time.
mrs_natural getTime(std::string timer_name);
void updtimer(std::string cname, TmControlValue value);
void addTimer(std::string class_name, std::string identifier);
void addTimer(TmTimer* t);
void removeTimer(std::string name);
It is the schedulers job to see that events are passed to the correct timer when they are posted. On each network tick the scheduler prompts each of the timers it manages to dispatch their pending events.
Timers define a control rate on which events may be scheduled. It is also the job of the timer to manage a queue of events and dispatch them at their scheduled dispatch time.
Creating a custom timer is simply a matter of defining its control rate, its units (ie seconds), and implementing a function to count the elapsed time between ticks. See the TmSampleCount timer as an example of a custom timer.
Events are the actions that happen at specified points in time. In
Marsyas events inherit from the EvEvent. Custom events are
constructed by inheriting from EvEvent and overriding the
dispatch and clone methods.
The overridden EvEvent::dispatch method is where the custom
event action is defined. Since Marsyas is not threaded the network will
block during dispatch. This could result in breaks in audio for
real-time audio if the action takes too much time.
The clone method is intended to be used by the TmTimer to
copy the event when it's posted. This would force the user to take care
of its deletion and avoid confusion about who must do this. At this time
clone is not used for this task so that once an EvEvent is posted
it is under the control of the TmTimer it was posted on. It
should not be reposted or deleted by the user. The search is on for a
better solution.
EvEvent supports repetition without having to create new
events. The setRepeat(Repeat r) method takes a Repeat
object that defines how to repeat the event. The default behaviour is
no repetition. A true value from the repeat() method tells the
scheduler to repeat the event. This method queries the supplied
Repeat object. The getRepeatInterval() returns the repeat
rate. The repeat_interval(string interval) may be used to convert
the supplied interval to a count. It is used in the
EvEvent::doRepeat() method.
Repetition of events is defined using the Repeat class. This
class is simply a tuple of the repetition time interval and repetition
count. There are three ways to define repetition. Repeat()
defines no repetition. Repeat(string interval) defines an
infinite repetition at a rate specified by the supplied interval.
Repeat(string interval, mrs_natural count) defines a finite
repetition of count repeats to occur every interval.
Time is specified as a single string without a timer name. It is assumed that the specified interval time will be meaningful on the timer that the event is posted in.
Time is specified using the TmTime class as
TmTime(string timer, string time). The first parameter is the
name of the timer on which the second parameter has meaning. As an
example, TmTime("TmSampleCount/Virtual","5s") specifies 5 seconds
from the point of time it is used on the TmSampleCount timer called
Virtual.
Rather than instantiating timers and adding them to the scheduler using
the MarSystem::addtimer(TmTimer* tmr) method, timers may be
specified and added by name using the
MarSystem::addtimer(string name, string ident) method where name
is the timer name, ie TmSampleCount, and ident is the unique identifier,
ie Virtual. Of course, if the timer name is not known then this method
will fail. New timers can be added to the factory using the method
laid out in TmTimerManager.cpp. See Timer Factory.