Sophie

Sophie

distrib > Mandriva > 2008.1 > i586 > media > contrib-updates > by-pkgid > c7095aefea7b97fbd2a596dcbfb9d481 > files > 460

asterisk-docs-1.4.26.1-1mdv2008.1.i586.rpm

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Macros</title><link rel="stylesheet" href="styles.css" type="text/css" /><meta name="generator" content="DocBook XSL Stylesheets V1.69.1" /><link rel="start" href="index.html" title="Asterisk™: The Future of Telephony" /><link rel="up" href="asterisk-CHP-6.html" title="Chapter 6. More Dialplan Concepts" /><link rel="prev" href="asterisk-CHP-6-SECT-4.html" title="Voicemail" /><link rel="next" href="asterisk-CHP-6-SECT-6.html" title="Using the Asterisk Database (AstDB)" /></head><body><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Macros</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="asterisk-CHP-6-SECT-4.html">Prev</a> </td><th width="60%" align="center">Chapter 6. More Dialplan Concepts</th><td width="20%" align="right"> <a accesskey="n" href="asterisk-CHP-6-SECT-6.html">Next</a></td></tr></table><hr /></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="asterisk-CHP-6-SECT-5"></a>Macros</h2></div></div></div><p>Macros<sup>[<a id="id4133356" href="#ftn.id4133356">84</a>]</sup> are<a id="ch06_macros" class="indexterm"></a> a very useful construct designed to avoid repetition in the
    dialplan. They also help in making changes to the dialplan. To illustrate
    this point, let’s look at our sample dialplan again. If you remember the
    changes we made for voicemail, we ended up with the following for John’s
    extension:</p><a id="I_programlisting6_tt951"></a><pre class="programlisting">exten =&gt; 101,1,Dial(${JOHN},10)
exten =&gt; 101,n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail)
exten =&gt; 101,n(unavail),Voicemail(101@default,u)
exten =&gt; 101,n,Hangup()
exten =&gt; 101,n(busy),VoiceMail(101@default,b)
exten =&gt; 101,n,Hangup()</pre><p>Now imagine you have a hundred users on your Asterisk system—setting
    up the extensions would involve a lot of copying and pasting. Then imagine
    that you need to make a change to the way your extensions work. That would
    involve a lot of editing, and you’d be almost certain to have
    errors.</p><p>Instead, you can define a macro that contains a list of steps to
    take, and then have all of the phone extensions refer to that macro. All
    you need to change is the macro, and everything in the dialplan that
    references that macro will change as well.</p><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title"><a id="asterisk-CHP-6-NOTE-35"></a>Tip</h3><p>If you’re familiar with computer programming, you’ll recognize
      that macros are similar to subroutines in many modern programming
      languages. If you’re not familiar with computer programming, don’t
      worry—we’ll walk you through creating a macro.</p></div><p>The best way to appreciate macros is to see one in action, so let’s
    move right along.</p><div class="sect2" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="asterisk-CHP-6-SECT-5.1"></a>Defining Macros</h3></div></div></div><p>Let’s take the dialplan logic we used above to set up voicemail
      for John and turn it into a macro. Then we’ll use the macro to give John
      and Jane (and the rest of their coworkers) the same
      functionality.</p><p>Macro definitions look a lot like contexts. (In fact, you could
      argue that they really are small, limited contexts.) You define a macro
      by placing <code class="literal">macro-</code> and the name of
      your macro in square brackets, like this:</p><a id="I_programlisting6_tt952"></a><pre class="programlisting">[macro-voicemail]</pre><p>Macro names must start with <code class="literal">macro-</code>. This distinguishes them from regular
      contexts. The commands within the macro are built almost identically to
      anything else in the dialplan; the only limiting factor is that macros
      use only the <code class="literal">s</code> extension. Let’s add
      our voicemail logic to the macro, changing the extension to <code class="literal">s</code> as we go:</p><a id="I_programlisting6_tt953"></a><pre class="programlisting">[macro-voicemail]
exten =&gt; s,1,Dial(${JOHN},10)
exten =&gt; s,n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail)
exten =&gt; s,n(unavail),Voicemail(101@default,u)
exten =&gt; s,n,Hangup()
exten =&gt; s,n(busy),VoiceMail(101@default,b)
exten =&gt; s,n,Hangup()</pre><p>That’s a start, but it’s not perfect, as it’s still specific to
      John and his mailbox number. To make the macro generic so that it will
      work not only for John but also for all of his coworkers, we’ll take
      advantage of another property of macros: arguments. But first, let’s see
      how we call macros in our dialplan.</p></div><div class="sect2" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="asterisk-CHP-6-SECT-5.2"></a>Calling Macros from the Dialplan</h3></div></div></div><p>To use a macro<a id="I_indexterm6_tt954" class="indexterm"></a> in our dialplan, we use the <code class="literal">Macro()</code> application. This application calls
      the specified macro and passes it any arguments. For example, to call
      our voicemail macro from our dialplan, we can do the following:</p><a id="I_programlisting6_tt955"></a><pre class="programlisting">exten =&gt; 101,1,Macro(voicemail)</pre><p>The <code class="literal">Macro()</code>
      application<a id="I_indexterm6_tt956" class="indexterm"></a> also defines several special variables for our use. They
      include:</p><div class="variablelist"><dl><dt><span class="term">
              <code class="literal">${MACRO_CONTEXT}</code>
            </span></dt><dd><p>The original context<a id="I_indexterm6_tt957" class="indexterm"></a> in which the macro was called.</p></dd><dt><span class="term">
              <code class="literal">${MACRO_EXTEN}</code>
            </span></dt><dd><p>The original extension in<a id="I_indexterm6_tt958" class="indexterm"></a> which the macro was called.</p></dd><dt><span class="term">
              <code class="literal">${MACRO_PRIORITY}</code>
            </span></dt><dd><p>The original priority in which<a id="I_indexterm6_tt959" class="indexterm"></a> the macro was called.</p></dd><dt><span class="term">
              <code class="literal">${ARG</code>
              <em class="replaceable"><code>n</code></em>
              <code class="literal">}</code>
            </span></dt><dd><p>The <em class="replaceable"><code>n</code></em>th argument passed<a id="I_indexterm6_tt960" class="indexterm"></a> to the macro. For example, the first argument would
            be <code class="literal">${ARG1}</code>, the second <code class="literal">${ARG2}</code>, and so on.</p></dd></dl></div><p>As we explained earlier, the way we initially defined our macro
      was hardcoded for John, instead of being generic. Let’s change our macro
      to use <code class="literal">${MACRO_EXTEN}</code> instead of
      <code class="literal">101</code> for the mailbox number. That way,
      if we call the macro from extension 101 the voicemail messages will go
      to mailbox 101, and if we call the macro from extension 102 messages
      will go to mailbox 102, and so on:</p><a id="I_programlisting6_tt961"></a><pre class="programlisting">[macro-voicemail]
exten =&gt; s,1,Dial(${JOHN},10)
exten =&gt; s,n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail)
exten =&gt; s,n(unavail),Voicemail(${MACRO_EXTEN}@default,u)
exten =&gt; s,n,Hangup()
exten =&gt; s,n(busy),VoiceMail(${MACRO_EXTEN}@default,b)
exten =&gt; s,n,Hangup()</pre></div><div class="sect2" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="asterisk-CHP-6-SECT-5.3"></a>Using Arguments in Macros</h3></div></div></div><p>Okay, now we’re <a id="I_indexterm6_tt962" class="indexterm"></a><a id="I_indexterm6_tt963" class="indexterm"></a>getting closer to having the macro the way we want it, but
      we still have one thing left to change; we need to pass in the channel
      to dial, as it’s currently still hardcoded for <code class="literal">${JOHN}</code> (remember that we defined the variable
      <code class="literal">JOHN</code> as the channel to call when we
      want to reach John). Let’s pass in the channel as an argument, and then
      our first macro will be complete:</p><a id="I_programlisting6_tt964"></a><pre class="programlisting">[macro-voicemail]
exten =&gt; s,1,Dial(${ARG1},10)
exten =&gt; s,n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail)
exten =&gt; s,n(unavail),Voicemail(${MCARO_EXTEN}@default,u)
exten =&gt; s,n,Hangup()
exten =&gt; s,n(busy),VoiceMail(${MCARO_EXTEN}@default,b)
exten =&gt; s,n,Hangup()</pre><p>Now that our macro is done, we can use it in our dialplan. Here’s
      how we can call our macro to provide voicemail to John, Jane, and
      Jack:</p><a id="I_programlisting6_tt965"></a><pre class="programlisting">exten =&gt; 101,1,Macro(voicemail,${JOHN})
exten =&gt; 102,1,Macro(voicemail,${JANE})
exten =&gt; 103,1,Macro(voicemail,${JACK})</pre><p>With 50 or more users, this dialplan will still look neat and
      organized; we’ll simply have one line per user, referencing a macro that
      can be as complicated as required. We could even have a few different
      macros for various user types, such as <code class="literal">executives</code>, <code class="literal">courtesy_phones</code>, <code class="literal">call_center_agents</code>, <code class="literal">analog_sets</code>, <code class="literal">sales_department</code>, and so on.</p><p>A more advanced version of the macro might look something like
      this:</p><a id="I_programlisting6_tt966"></a><pre class="programlisting">[macro-voicemail]
exten =&gt; s,1,Dial(${ARG1},20)
exten =&gt; s,n,Goto(s-${DIALSTATUS},1)
exten =&gt; s-NOANSWER,1,Voicemail(${MACRO_EXTEN},u)
exten =&gt; s-NOANSWER,n,Goto(incoming,s,1)
exten =&gt; s-BUSY,1,Voicemail(${MACRO_EXTEN},b)
exten =&gt; s-BUSY,n,Goto(incoming,s,1)
exten =&gt; _s-.,1,Goto(s-NOANSWER,1)</pre><p>This macro depends on a nice side effect of the <code class="literal">Dial()</code> application: when you use the <code class="literal">Dial()</code> application, it sets the <code class="literal">DIALSTATUS</code> variable to indicate whether the
      call was successful or not. In this case, we’re handling the <code class="literal">NOANSWER</code> and <code class="literal">BUSY</code> cases, and treating all other result
      codes as a <code class="literal">NOANSWER</code>.<a id="I_indexterm6_tt967" class="indexterm"></a></p></div><div class="footnotes"><br /><hr width="100" align="left" /><div class="footnote"><p><sup>[<a id="ftn.id4133356" href="#id4133356">84</a>] </sup>Although <code class="literal">Macro</code> seems like a
        general-purpose dialplan subroutine, it has a stack overflow problem
        that means you should not try to nest <code class="literal">Macro</code> calls more than five levels deep. As
        of this writing, we do not know whether the <code class="literal">Macro</code>
        application will be patched for 1.4, or if it will be rewritten for
        future versions. If you plan to do a lot of macros within macros (and
        call complex functions within them), you may run into stability
        problems. You will know you have a problem with just one test call, so
        if your dialplan tests out, you’re good to go. We also recommend that
        you take a look at the <code class="literal">Gosub</code> and
        <code class="literal">Return</code> applications, as a lot of
        macro functionality can be implemented without actually using
        <code class="literal">Macro()</code>. Also, please note that we are not
        suggesting that you don’t use <code class="literal">Macro()</code>. It is
        fantastic and works very well; it just doesn’t nest
        efficiently.</p></div></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="asterisk-CHP-6-SECT-4.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="asterisk-CHP-6.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="asterisk-CHP-6-SECT-6.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Voicemail </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Using the Asterisk Database (AstDB)</td></tr></table></div><div xmlns="" id="svn-footer"><hr /><p>You are reading <em>Asterisk: The Future of Telephony</em> (2nd Edition for Asterisk 1.4), by Jim van Meggelen, Jared Smith, and Leif Madsen.<br />
       This work is licensed under the <a href="http://creativecommons.org/licenses/by-nc-nd/3.0/">Creative Commons Attribution-Noncommercial-No Derivative Works License v3.0</a>.<br />
       To submit comments, corrections, or other contributions to the text, please visit <a href="http://oreilly.com/catalog/9780596510480/">http://www.oreilly.com/</a>.</p></div></body></html>