<?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 => 101,1,Dial(${JOHN},10) exten => 101,n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail) exten => 101,n(unavail),Voicemail(101@default,u) exten => 101,n,Hangup() exten => 101,n(busy),VoiceMail(101@default,b) exten => 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 => s,1,Dial(${JOHN},10) exten => s,n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail) exten => s,n(unavail),Voicemail(101@default,u) exten => s,n,Hangup() exten => s,n(busy),VoiceMail(101@default,b) exten => 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 => 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 => s,1,Dial(${JOHN},10) exten => s,n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail) exten => s,n(unavail),Voicemail(${MACRO_EXTEN}@default,u) exten => s,n,Hangup() exten => s,n(busy),VoiceMail(${MACRO_EXTEN}@default,b) exten => 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 => s,1,Dial(${ARG1},10) exten => s,n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail) exten => s,n(unavail),Voicemail(${MCARO_EXTEN}@default,u) exten => s,n,Hangup() exten => s,n(busy),VoiceMail(${MCARO_EXTEN}@default,b) exten => 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 => 101,1,Macro(voicemail,${JOHN}) exten => 102,1,Macro(voicemail,${JANE}) exten => 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 => s,1,Dial(${ARG1},20) exten => s,n,Goto(s-${DIALSTATUS},1) exten => s-NOANSWER,1,Voicemail(${MACRO_EXTEN},u) exten => s-NOANSWER,n,Goto(incoming,s,1) exten => s-BUSY,1,Voicemail(${MACRO_EXTEN},b) exten => s-BUSY,n,Goto(incoming,s,1) exten => _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>