-
Notifications
You must be signed in to change notification settings - Fork 131
Hooks and noloop
By default, declaration code like $item = new ...
, or my $var = ...
is pulled out of the user loop code and put in the start-up code, so it is only run once. If you want to force additional code out of the loop code, you can use add # noloop=start/stop
comments before and after the code segment, or you can add a # noloop
comment to the end of the record. For example:
# Example of noloop record comments
my $weather_wind_gust_threshold=$config_parms{weather_wind_gust_threshold}; # noloop
$weather_wind_gust_threshold=12 unless $weather_wind_gust_threshold; # noloop
# Example of noloop block comments
# noloop=start
my $mp3names;
while ( my $mp3name = <d:/library/*.m3u> )
{
$mp3name =~ s#^.*/##; # remove path
$mp3name =~ s#\..*$##; # remove extension
$mp3names .= "," if $mp3names;
$mp3names .= $mp3name;
}
# noloop=stop
$v_play_music = new Voice_Cmd("Play [$mp3names]");
if ($state = said $v_play_music) {
... more code here ...
If you want to have a user defined function called once per loop, but you want it before or after all the other user code has been called, use the &MainLoop_pre_add
_hook and &MainLoop_post_add
_hook functions to add callbacks to your functions. For example:
$v_hook_pre_add = new Voice_Cmd 'Add pre code hook';
$v_hook_pre_drop = new Voice_Cmd 'Drop pre code hook';
$v_hook_post_add = new Voice_Cmd 'Add post code hook';
$v_hook_post_drop = new Voice_Cmd 'Drop post code hook';
&MainLoop_pre_add_hook( \&test_hook_pre) if said $v_hook_pre_add;
&MainLoop_pre_drop_hook( \&test_hook_pre) if said $v_hook_pre_drop;
&MainLoop_post_add_hook( \&test_hook_post) if said $v_hook_post_add;
&MainLoop_post_drop_hook(\&test_hook_post) if said $v_hook_post_drop;
sub test_hook_pre { print "<"; }
sub test_hook_post { print ">"; }
If you want your hook code to last between code reloads (e.g. added by start-up code from a module), set 2nd argument to 'persistent' (a value of 1 will also work ... grandfathered in for old code). For example:
&main::MainLoop_post_drop_hook( \&jabber::process, 'persistent' );
If you want that hook to run first, before all other hooks of that type, set the 2nd argument to 'first', or 'persisent_first'. Otherwise the hook is pushed to the end of the list, so it is run in the order the hooks were added.
Here is a list of all the code hook locations:
MainLoop_pre => Run before user code
MainLoop_post => Run before user code
Serial_data => Run on any incoming serial data
Serial_match => Run when incoming serial data matches and item
State_change => Run when items change states
Play_parms => Run before playing wav files, so you can set play parms
Play_pre => Run before playing wav files
Play_post => Run after playing wav files
Speak_parms => Run before speaking text files, so you can set speak parms
Speak_pre => Run before speaking text files
Speak_post => Run after speaking text files
Log => Run on all print_log, display, speak, and play calls.
Reload_pre => Run before reload
Reload_post => Run after reload
Exit => Run on exit
If you want to use a hook to modify parameters for the subsequent MisterHouse function, use a _parm
hook, which passes parameters in by reference rather than by value. For example, this will add a to_file
option to all speak calls:
&Speak_parms_add_hook(\&speak_parm_update) if $Reload;
sub speak_parm_update {
my ($parms_ref) = @_;
$$parms_ref{to_file} = "somename.wav";
}
To monitor text sent to print_log, display, play, and speak
, try this:
&Log_add_hook(\&my_log) if $Reload;
sub my_log {
my ($type) = shift @_;
my ($text) = shift @_;
my (%parms) = @_;
print "type=$type text=$text\n";
}
For more examples on code hooks, see mh/code/examples/test_code_hooks.pl