Skip to content
ggodart edited this page Jan 6, 2021 · 3 revisions

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 ...

Hooks

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

Clone this wiki locally