<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" /> 
<base href="https://wiki.asterisk.org/wiki" /> 
<title>Message Title</title>  
<style type="text/css">@media only screen and (max-device-width: 480px) {.mobile-only {
        width: auto !important;
        height: auto !important;
        overflow: visible !important;
        line-height: normal !important;
        font-size: inherit !important;
        mso-hide: all;
}

.desktop-only {
        display: none !important;
}

/* iPhone 3GS fix for unwanted 20px right margin */
body { min-width: 100% !important; padding: 0; margin: 0; }

#center-content-table { max-width: none; !important; }
#header-pattern-container { padding: 10px 10px 10px 10px !important; line-height: 20px !important; }
#header-avatar-image-container { padding-right: 8px !important; }
#email-content-container { padding: 0 !important; }
.mobile-expand { border-radius: 0 !important; border-left: 0 !important; border-right: 0 !important; padding-left: 26px !important;}
.mobile-resize-text { font-size: 16px !important; line-height: 22px !important; }
#page-title-pattern-header { font-size: 20px !important; line-height: 28px !important; }
#page-title-pattern-icon-image-container-cell { padding-top: 7px !important; }
#inline-user-pattern { display: block !important; }
#inline-user-pattern-avatar { padding-top: 3px !important; }
.contextual-area-pattern { border-bottom: 1px solid #ccc !important; padding: 15px 10px 0 10px !important;}
.users-involved-pattern-column-table { width: 100% !important;  }
.users-involved-pattern-avatar-table-cell { padding: 3px 5px 5px 0 !important; }
.users-involved-pattern-column-container { padding-right: 0 !important; }
.contextual-excerpt-pattern, #users-involved-pattern { border: 0 !important; }

/** Aui Typography upsized for mobile **/
#content-excerpt-pattern-container, #contextual-excerpt-pattern-text-container { font-size: 16px !important; line-height: 22px !important; }
#content-excerpt-pattern-container h1, #contextual-excerpt-pattern-text-container h1 { font-size: 24px !important; line-height: 28px !important; }
#content-excerpt-pattern-container h2, #contextual-excerpt-pattern-text-container h2 { font-size: 20px !important; line-height: 28px !important; }
#content-excerpt-pattern-container h3, #contextual-excerpt-pattern-text-container h3 { font-size: 18px !important; line-height: 24px !important; }
#content-excerpt-pattern-container h4, #contextual-excerpt-pattern-text-container h4 { font-size: 16px !important; line-height: 22px !important; }
#content-excerpt-pattern-container h5, #contextual-excerpt-pattern-text-container h5 { font-size: 14px !important; line-height: 20px !important; }
#content-excerpt-pattern-container h6, #contextual-excerpt-pattern-text-container h6 { font-size: 14px !important; line-height: 20px !important; }
.user-mention { line-height: 18px !important; }
/** Aui Typography end **/

/* Show appropriate footer logo on mobile, display links vertically */
#footer-pattern { padding: 15px 10px !important; }
#footer-pattern-logo-desktop-container { padding: 0 !important; }
#footer-pattern-logo-desktop { width: 0 !important; height: 0 !important; }
#footer-pattern-logo-mobile {
    padding-top: 10px !important;
    width: 30px !important;
    height: 27px !important;
    display: inline !important;
}
#footer-pattern-text {
    display: block !important;
}
#footer-pattern-links-container { line-height: 0 !important;}
.footer-pattern-links.mobile-resize-text,
.footer-pattern-links.mobile-resize-text,
#footer-pattern-text.mobile-resize-text,
#footer-pattern-links-container.no-footer-links {
    font-size: 14px !important;
    line-height: 20px !important;
}
.footer-link { display: block !important; }
#footer-pattern-links-container table { display: inline-block !important; float: none !important; }
#footer-pattern-links-container, #footer-pattern-text { text-align: center !important; }
#footer-pattern-links { padding-bottom: 5px !important; }

/** Team Calendar overrides, these should be removed when notifications are updated in Team Calendars. For now CSS
    overrides are being used because the structure of the content can't change without rereleasing the plugin */
.mail-calendar-container .day-header + table tr td:first-child {
    vertical-align: top !important;
    padding-top: 5px !important;
}}
@media (min-width: 900px) {#center-content-table { width: 900px; }}
@media all {#outlook a {padding:0;} /* Force Outlook to provide a "view in browser" menu link. */
/* Prevent Webkit and Windows Mobile platforms from changing default font sizes.*/
body{-webkit-text-size-adjust:100%; -ms-text-size-adjust:100%;}
.ExternalClass {width:100%;} /* Force Hotmail to display emails at full width */
#background-table {margin:0; padding:0; width:100% !important; }
/* Needed to override highlighting on date and time links in iOS */
.grey a {color: #707070; text-decoration: none; }/* These styles are appended to the head element of a notification in order to prevent Apple Mail and similar
   clients from underlining the due dates with a blue hyperlink */
/* a lozenge outside an inline task should always be #333, lozenges inside an inline task should be
   colored according to their upcoming due dates, a completed task date lozenge or deleted task date
   lozenge should always be #707070 */
.date-time-lozenge a {color: #333333; text-decoration: none; }
.inline-task-text-container .date-time-lozenge.date-upcoming a {color: #DF6F00; text-decoration: none; }
.inline-task-text-container .date-time-lozenge.date-past a {color: #D04437; text-decoration: none; }
.inline-task-text-container.content-deleted-color .date-time-lozenge a,
.inline-task-text-container.checked .date-time-lozenge a {
    color: #707070; text-decoration: none;
}}
</style> 
</head>
<body>
<table id="background-table" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333; background-color: #f5f5f5"> 
<tbody> 
<tr> 
<td id="header-pattern-container" style="padding: 0px; border-collapse: collapse; padding: 10px 20px"> 
<table id="header-pattern" cellspacing="0" cellpadding="0" border="0" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<tbody> 
<tr> 
<td id="header-avatar-image-container" valign="top" style="padding: 0px; border-collapse: collapse; vertical-align: top; width: 32px; padding-right: 9px"><a href="https://wiki.asterisk.org/wiki/display/~mmichelson?src=email" style="color: #3b73af; text-decoration: none"><img id="header-avatar-image" class="image_fix" src="cid:avatar_99ed0aa29d6f204db4785296f8170422" height="32" width="32" border="0" style="border-radius: 3px; vertical-align: top" /></a></td>
<td id="header-text-container" valign="middle" style="padding: 0px; border-collapse: collapse; vertical-align: middle; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; mso-line-height-rule: exactly; mso-text-raise: 1px">Mark Michelson <strong>edited</strong> a page</td> 
</tr> 
</tbody> 
</table> </td> 
</tr> 
<!-- End Header pattern --> 
<tr> 
<td id="email-content-container" style="padding: 0px; border-collapse: collapse; padding: 0 20px"> 
<table id="email-content-table" cellspacing="0" cellpadding="0" border="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333; border-spacing: 0; border-collapse: separate"> 
<tbody> 
<tr> 
<td class="email-content-rounded-top mobile-expand" style="padding: 0px; border-collapse: collapse; color: #fff; padding: 0 15px 0 16px; height: 15px; background-color: #fff; border-left: 1px solid #ccc; border-top: 1px solid #ccc; border-right: 1px solid #ccc; border-bottom: 0; border-top-right-radius: 5px; border-top-left-radius: 5px"> </td> 
</tr> 
<tr> 
<td class="email-content-main mobile-expand" style="padding: 0px; border-collapse: collapse; border-left: 1px solid #ccc; border-right: 1px solid #ccc; border-top: 0; border-bottom: 0; padding: 0 15px 15px 16px; background-color: #fff"> 
<table id="page-title-pattern" cellspacing="0" cellpadding="0" border="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<tbody> 
<tr> 
<td id="page-title-pattern-icon-image-container" valign="top" style="padding: 0px; border-collapse: collapse; width: 16px; vertical-align: top"> 
<table cellspacing="0" cellpadding="0" border="0" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<tbody> 
<tr> 
<td id="page-title-pattern-icon-image-container-cell" style="padding: 0px; border-collapse: collapse; width: 16px; padding: 9px 8px 0px 0px; mso-text-raise: 5px; mso-line-height-rule: exactly"><a href="https://wiki.asterisk.org/wiki/display/AST/Part+2%3A+Playbacks?src=email" title="page icon" style="vertical-align: top;; color: #3b73af; text-decoration: none"><img style="vertical-align: top; display: block;" src="cid:page-icon" alt="page icon" title="page icon" height="16" width="16" border="0" /></a></td> 
</tr> 
</tbody> 
</table> </td>
<td style="vertical-align: top;; padding: 0px; border-collapse: collapse; padding-right: 5px; font-size: 20px; line-height: 30px; mso-line-height-rule: exactly" id="page-title-pattern-header-container"><span id="page-title-pattern-header" style="font-family: Arial, sans-serif; padding: 0; font-size: 20px; line-height: 30px; mso-text-raise: 2px; mso-line-height-rule: exactly; vertical-align: middle"><a href="https://wiki.asterisk.org/wiki/display/AST/Part+2%3A+Playbacks?src=email" title="Part 2: Playbacks" style="color: #3b73af; text-decoration: none">Part 2: Playbacks</a></span></td> 
</tr> 
</tbody> 
</table> </td> 
</tr> 
<tr> 
<td class="email-content-main mobile-expand" style="padding: 0px; border-collapse: collapse; border-left: 1px solid #ccc; border-right: 1px solid #ccc; border-top: 0; border-bottom: 0; padding: 0 15px 15px 16px; background-color: #fff"> 
<table class="content-excerpt-pattern" cellspacing="0" cellpadding="0" border="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; mso-line-height-rule: exactly; mso-text-raise: 1px"> 
<tbody> 
<tr> 
<td class="content-excerpt-pattern-container mobile-resize-text " style="padding: 0px; border-collapse: collapse; padding: 0 0 0 24px"> 
<table class="diff-macro diff-block-target diff-block-context" style="background-color: #f0f0f0;border: 1px solid #dddddd;margin: 10px 1px;padding: 0 2px 2px;width: 100%;; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<thead> 
<tr> 
<th class="diff-macro-title" style="background-color: transparent; text-align: left; font-weight: normal;padding: 5px;"><span class="icon macro-placeholder-icon" style="background-color: ;line-height: 20px;"><img src="https://wiki.asterisk.org/wiki/s/en_GB/5635/60fd2eb45debbf4ede2b669f4c9b96b4ce40a937.48/_/images/icons/macrobrowser/dropdown/section.png" style="padding-right: 5px; vertical-align: text-bottom;" /> </span>Section</th> 
</tr> 
</thead> 
<tbody> 
<tr> 
<td class="diff-macro-body" style="background-color: #fff;border: 1px solid #dddddd;padding: 10px;; padding: 0px; border-collapse: collapse"> 
<table class="diff-macro" style="background-color: #f0f0f0;border: 1px solid #dddddd;margin: 10px 1px;padding: 0 2px 2px;width: 100%;; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<thead> 
<tr> 
<th class="diff-macro-title" style="background-color: transparent; text-align: left; font-weight: normal;padding: 5px;"><span class="icon macro-placeholder-icon" style="background-color: ;line-height: 20px;"><img src="https://wiki.asterisk.org/wiki/s/en_GB/5635/60fd2eb45debbf4ede2b669f4c9b96b4ce40a937.48/_/images/icons/macrobrowser/dropdown/column.png" style="padding-right: 5px; vertical-align: text-bottom;" /> </span>Column</th> 
</tr> 
</thead> 
<tbody> 
<tr> 
<td class="diff-macro-body" style="background-color: #fff;border: 1px solid #dddddd;padding: 10px;; padding: 0px; border-collapse: collapse"> <h1 id="Part2:Playbacks-Queryingforsounds" style="margin: 10px 0 0 0; margin-top: 0; font-size: 24px; font-weight: normal; line-height: 30px; margin: 40px 0 0 0; margin-top: 0"> <span class="diff-html-changed" id="changed-diff-0" style="background-color: #d6f0ff;">Querying for sounds</span> </h1> <p style="margin: 10px 0 0 0">In our voice mail application we have been creating, we have learned the ins and outs of creating and manipulating live and stored recordings. Let's make the voice mail application more user-friendly now by adding some playbacks of installed sounds. The voice mail application has some nice capabilities, but it is not very user-friendly yet. Let's modify the current application to play a greeting to the user when they call into the application. This is the updated state machine:</p> <p style="text-align: center;; margin: 10px 0 0 0"></p> 
<table class="diff-macro bodyless" style="background-color: #f0f0f0;border: 1px solid #dddddd;margin: 10px 1px;padding: 0 2px 2px;width: 100%;margin: 5px 0; padding: 0; width: auto;; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<thead> 
<tr> 
<th class="diff-macro-title" style="background-color: transparent; text-align: left; font-weight: normal;padding: 5px;"><span class="icon macro-placeholder-icon" style="background-color: ;line-height: 20px;"><img src="https://wiki.asterisk.org/wiki/s/en_GB/5635/60fd2eb45debbf4ede2b669f4c9b96b4ce40a937.48/_/plugins/servlet/confluence/placeholder/macro-icon?name=gliffy" style="padding-right: 5px; vertical-align: text-bottom;" /> </span>Gliffy Diagram</th> 
</tr> 
</thead> 
<tbody> 
<tr> 
<td class="diff-macro-properties" style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;padding: 0; border: 1px solid #dddddd;; padding: 0px; border-collapse: collapse"> 
<table style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<tbody> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse"></td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse"></td> 
</tr> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">name</td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">vm-full</td> 
</tr> 
</tbody> 
</table> </td> 
</tr> 
</tbody> 
</table> <p style="margin: 10px 0 0 0"></p> </td> 
</tr> 
</tbody> 
</table> 
<table class="diff-macro" style="background-color: #f0f0f0;border: 1px solid #dddddd;margin: 10px 1px;padding: 0 2px 2px;width: 100%;; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<thead> 
<tr> 
<th class="diff-macro-title" style="background-color: transparent; text-align: left; font-weight: normal;padding: 5px;"><span class="icon macro-placeholder-icon" style="background-color: ;line-height: 20px;"><img src="https://wiki.asterisk.org/wiki/s/en_GB/5635/60fd2eb45debbf4ede2b669f4c9b96b4ce40a937.48/_/images/icons/macrobrowser/dropdown/column.png" style="padding-right: 5px; vertical-align: text-bottom;" /> </span>Column</th> 
</tr> 
</thead> 
<tbody> 
<tr> 
<td class="diff-macro-body" style="background-color: #fff;border: 1px solid #dddddd;padding: 10px;; padding: 0px; border-collapse: collapse"> 
<table class="diff-macro" style="background-color: #f0f0f0;border: 1px solid #dddddd;margin: 10px 1px;padding: 0 2px 2px;width: 100%;; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<thead> 
<tr> 
<th class="diff-macro-title" style="background-color: transparent; text-align: left; font-weight: normal;padding: 5px;"><span class="icon macro-placeholder-icon" style="background-color: ;line-height: 20px;"><img src="https://wiki.asterisk.org/wiki/s/en_GB/5635/60fd2eb45debbf4ede2b669f4c9b96b4ce40a937.48/_/images/icons/macrobrowser/dropdown/panel.png" style="padding-right: 5px; vertical-align: text-bottom;" /> </span>Panel</th> 
</tr> 
</thead> 
<tbody> 
<tr> 
<td class="diff-macro-properties" style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;padding: 0; border: 1px solid #dddddd;; padding: 0px; border-collapse: collapse"> 
<table style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<tbody> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">title</td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">On this Page</td> 
</tr> 
</tbody> 
</table> </td> 
</tr> 
</tbody> 
<tbody> 
<tr> 
<td class="diff-macro-body" style="background-color: #fff;border: 1px solid #dddddd;padding: 10px;; padding: 0px; border-collapse: collapse"> <p style="margin: 10px 0 0 0; margin-top: 0"></p> 
<table class="diff-macro bodyless" style="background-color: #f0f0f0;border: 1px solid #dddddd;margin: 10px 1px;padding: 0 2px 2px;width: 100%;margin: 5px 0; padding: 0; width: auto;; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<thead> 
<tr> 
<th class="diff-macro-title" style="background-color: transparent; text-align: left; font-weight: normal;padding: 5px;"><span class="icon macro-placeholder-icon" style="background-color: ;line-height: 20px;"><img src="https://wiki.asterisk.org/wiki/s/en_GB/5635/60fd2eb45debbf4ede2b669f4c9b96b4ce40a937.48/_/images/icons/macrobrowser/dropdown/toc.png" style="padding-right: 5px; vertical-align: text-bottom;" /> </span>Table of Contents</th> 
</tr> 
</thead> 
<tbody> 
<tr> 
<td class="diff-macro-properties" style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;padding: 0; border: 1px solid #dddddd;; padding: 0px; border-collapse: collapse"> 
<table style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<tbody> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">maxLevel</td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">2</td> 
</tr> 
</tbody> 
</table> </td> 
</tr> 
</tbody> 
</table> <p style="margin: 10px 0 0 0"></p> </td> 
</tr> 
</tbody> 
</table> </td> 
</tr> 
</tbody> 
</table> </td> 
</tr> 
</tbody> 
</table> <p class="diff-block-target" style="margin: 10px 0 0 0"> <span class="diff-html-removed" id="removed-diff-0" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">Information on playing a sound file on a channel can be found here. To make this </span><span class="diff-html-added" id="added-diff-0" style="font-size: 100%; background-color: #ddfade;">To make the new "greeting" state </span>more interesting, we are going to add some safety to this state by ensuring that the sound we want to play is installed on the system. The <a class="confluence-link unresolved" href="#" style="color: #3b73af; text-decoration: none"><code style="font-family: monospace"><span class="diff-html-changed" id="changed-diff-1" style="background-color: #d6f0ff;">/</span></code></a><span class="diff-html-removed" id="removed-diff-1" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">playbacks</span><a class="confluence-link unresolved" href="#" style="color: #3b73af; text-decoration: none"><code style="font-family: monospace"><span class="diff-html-added" id="added-diff-1" style="font-size: 100%; background-color: #ddfade;">sounds</span></code></a> resource in ARI provides methods to list the sounds installed on the system, as well as the ability to get specific sound files.</p> <p class="diff-block-target" style="margin: 10px 0 0 0">Asterisk searches for sounds in the <code style="font-family: monospace">/sounds/</code> subdirectory of the configured <code style="font-family: monospace">astdatadir</code> option in <code style="font-family: monospace">asterisk.conf</code>. By default, Asterisk will search for sounds in <code style="font-family: monospace">/var/lib/asterisk/sounds</code>. When Asterisk starts up, it indexes the installed sounds and keeps an in-data representation of <span class="diff-html-removed" id="removed-diff-2" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">the installed sounds</span><span class="diff-html-added" id="added-diff-2" style="font-size: 100%; background-color: #ddfade;">those sound files</span>. When an ARI application asks Asterisk for details about a specific sound or for a list of sounds on the system, Asterisk consults its in-memory index instead of searching the file system directly. This <span class="diff-html-removed" id="removed-diff-3" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">means that if you add sound files to the sounds directory after Asterisk has started, then your ARI application will not be able to retrieve details about the newly-added sound. This can be remedied by running the Asterisk </span><span class="diff-html-added" id="added-diff-3" style="font-size: 100%; background-color: #ddfade;">has some trade-offs. When querying for sound information, this in-memory indexing makes the operations much faster. On the other hand, it also means that Asterisk has to be "poked" to re-index the sounds if new sounds are added to the file system after Asterisk is running.  The Asterisk </span>CLI command "module reload sounds" <span class="diff-html-added" id="added-diff-4" style="font-size: 100%; background-color: #ddfade;">provides a means of having Asterisk re-index the sounds on the system so that they are available to ARI</span>.</p> <p class="diff-block-context" style="margin: 10px 0 0 0">For our greeting, we will play the built-in sound "vm-intro". Here is the code for our new state:</p> <p class="diff-context-placeholder" style="margin: 10px 0 0 0">...</p> 
<table class="diff-macro diff-block-context" style="background-color: #f0f0f0;border: 1px solid #dddddd;margin: 10px 1px;padding: 0 2px 2px;width: 100%;; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<thead> 
<tr> 
<th class="diff-macro-title" style="background-color: transparent; text-align: left; font-weight: normal;padding: 5px;"><span class="icon macro-placeholder-icon" style="background-color: ;line-height: 20px;"><img src="https://wiki.asterisk.org/wiki/s/en_GB/5635/60fd2eb45debbf4ede2b669f4c9b96b4ce40a937.48/_/plugins/servlet/confluence/placeholder/macro-icon?name=code" style="padding-right: 5px; vertical-align: text-bottom;" /> </span>Code Block</th> 
</tr> 
</thead> 
<tbody> 
<tr> 
<td class="diff-macro-properties" style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;padding: 0; border: 1px solid #dddddd;; padding: 0px; border-collapse: collapse"> 
<table style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<tbody> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">title</td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">greeting_state.js</td> 
</tr> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">language</td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">js</td> 
</tr> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">collapse</td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">true</td> 
</tr> 
</tbody> 
</table> </td> 
</tr> 
</tbody> 
<tbody> 
<tr> 
<td class="diff-macro-body" style="background-color: #fff;border: 1px solid #dddddd;padding: 10px;; padding: 0px; border-collapse: collapse"> <pre style="margin: 10px 0 0 0; margin-top: 0">var Event = require('./event');

function sounds_installed(client) {
    client.sounds.get({soundId: 'vm-intro'}, function(err) {
        if (err) {
            console.log("Required sound 'vm-intro' not installed. Aborting");
            throw err;
        }
    });
}

var GreetingState = function(call) {
    this.state_name = "greeting";
    this.call = call;
    sounds_installed(call.client);
}

GreetingState.prototype.enter = function() {
    var self = this;
    var playback = self.call.client.Playback();
    console.log("Entering greeting state");
    self.call.channel.on("ChannelHangupRequest", on_hangup);
    self.call.channel.on("ChannelDtmfReceived", on_dtmf);
    self.call.client.on("PlaybackFinished", on_playback_finished);
    self.call.channel.play({media: 'sound:vm-intro'}, playback);

    function cleanup() {
        self.call.channel.removeListener('ChannelHangupRequest', on_hangup);
        self.call.channel.removeListener('ChannelDtmfReceived', on_dtmf);
        self.call.client.removeListener('PlaybackFinished', on_playback_finished);
    }

    function on_hangup(event, channel) {
        console.log("Abandoning voicemail recording on hangup");
        cleanup();
        self.call.state_machine.change_state(Event.HANGUP);
    }

    function on_playback_finished(event) {
        if (playback && playback.id === event.playback.id) {
            cleanup();
            self.call.state_machine.change_state(Event.PLAYBACK_COMPLETE);
        }
    }

    function on_dtmf(event, channel) {
        switch (event.digit) {
        case '#':
            console.log("Skipping greeting");
            playback.stop();
            //Let on_playback_finished take care of state change
        }
    }
}

module.exports = GreetingState;</pre> </td> 
</tr> 
</tbody> 
</table> <p class="diff-block-target" style="margin: 10px 0 0 0"> <span class="diff-html-added" id="added-diff-5" style="font-size: 100%; background-color: #ddfade;">The </span><code style="font-family: monospace"><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">sounds.get()</span></code><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;"> method employed here allows for a single sound to be retrieved based on input parameters. Here, we simply specify the name of the recording we want to ensure that it exists in some form on the system. </span>By checking for the sound's existence in the initialization of <code style="font-family: monospace">GreetingState</code>, we can abort the call early if the sound is not installed.</p> <p class="diff-context-placeholder" style="margin: 10px 0 0 0">...</p> 
<table class="diff-macro diff-block-target diff-block-context" style="background-color: #f0f0f0;border: 1px solid #dddddd;margin: 10px 1px;padding: 0 2px 2px;width: 100%;; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<thead> 
<tr> 
<th class="diff-macro-title" style="background-color: transparent; text-align: left; font-weight: normal;padding: 5px;"><span class="icon macro-placeholder-icon" style="background-color: ;line-height: 20px;"><img src="https://wiki.asterisk.org/wiki/s/en_GB/5635/60fd2eb45debbf4ede2b669f4c9b96b4ce40a937.48/_/images/icons/macrobrowser/dropdown/panel.png" style="padding-right: 5px; vertical-align: text-bottom;" /> </span>Panel</th> 
</tr> 
</thead> 
<tbody> 
<tr> 
<td class="diff-macro-properties" style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;padding: 0; border: 1px solid #dddddd;; padding: 0px; border-collapse: collapse"> 
<table style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<tbody> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">bgColor</td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">silver</td> 
</tr> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">titleBGColor</td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">seagreen</td> 
</tr> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">borderStyle</td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">solid</td> 
</tr> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">title</td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">Reader Exercise <span class="diff-html-removed" id="removed-diff-4" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">5</span><span class="diff-html-added" id="added-diff-6" style="font-size: 100%; background-color: #ddfade;">1</span></td> 
</tr> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">titleColor</td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">black</td> 
</tr> 
</tbody> 
</table> </td> 
</tr> 
</tbody> 
<tbody> 
<tr> 
<td class="diff-macro-body" style="background-color: #fff;border: 1px solid #dddddd;padding: 10px;; padding: 0px; border-collapse: collapse"> <p style="margin: 10px 0 0 0; margin-top: 0">Our current implementation of <code style="font-family: monospace">GreetingState</code> does not take language into consideration. The <code style="font-family: monospace">sounds_installed</code> method checks for the existence of the sound file, but it does not ensure that we have the sound file in the language of the channel that is in our application.</p> <p style="margin: 10px 0 0 0">For this exercise, modify <code style="font-family: monospace">sounds_installed()</code> to also check if the retrieved sound exists in the language of the calling channel. The channel's language can be retrieved using the <code style="font-family: monospace">getChannelVar()</code> method on a channel to retrieve the value of variable "CHANNEL(language)". The sound returned by <code style="font-family: monospace">sounds.get()</code> contains an array of <code style="font-family: monospace">FormatLang</code> objects that are a pair of format and language strings. If the sound exists, but not in the channel's language, then throw an exception.</p> </td> 
</tr> 
</tbody> 
</table> <h1 id="Part2:Playbacks-Controllingplaybacks" class="diff-block-target diff-block-context" style="margin: 10px 0 0 0; font-size: 24px; font-weight: normal; line-height: 30px; margin: 40px 0 0 0"> <span class="diff-html-changed" id="changed-diff-2" style="background-color: #d6f0ff;">Controlling playbacks</span> </h1> <p class="diff-block-target diff-block-context" style="margin: 10px 0 0 0"> <span class="diff-html-removed" id="removed-diff-5" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">We've seen playbacks get stopped</span><span class="diff-html-added" id="added-diff-7" style="font-size: 100%; background-color: #ddfade;">So far in our voice mail application, we have stopped playbacks</span>, but there are a lot more interesting operations that can be done on <span class="diff-html-removed" id="removed-diff-6" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">playbacks</span><span class="diff-html-added" id="added-diff-8" style="font-size: 100%; background-color: #ddfade;">them</span>, such as reversing and fast-forwarding them. Within the context of recording a voicemail, these operations are pretty useless, so we will shift our focus now to the other side of voicemail: listening to recorded voicemails.</p> <p class="diff-block-target" style="margin: 10px 0 0 0">For this, we will write a new application. This new application will allow a caller to listen to the voicemails that are stored in a specific mailbox. When the caller <span class="diff-html-removed" id="removed-diff-7" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">calls in</span><span class="diff-html-added" id="added-diff-9" style="font-size: 100%; background-color: #ddfade;">enters the application</span>, a prompt is played to the caller saying which message number the caller is hearing. When the message number finishes playing (or if the caller interrupts the playback with '#'), then the caller hears the specified message in the voicemail box. While listening to the voicemail, the caller can do several things:</p> <p class="diff-context-placeholder" style="margin: 10px 0 0 0">...</p> <p class="diff-block-target" style="margin: 10px 0 0 0">This means defining a brand new state machine. To start with, we'll define <span class="diff-html-removed" id="removed-diff-8" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">a </span>three new states. The "preamble" state is <span class="diff-html-removed" id="removed-diff-9" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">a state </span><span class="diff-html-added" id="added-diff-10" style="font-size: 100%; background-color: #ddfade;">the initial state of the state machine, </span>where the current message number is played back to the listener. The "listening" state is where <span class="diff-html-removed" id="removed-diff-10" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">the  </span><span class="diff-html-added" id="added-diff-11" style="font-size: 100%; background-color: #ddfade;">the </span>voice mail message is played back to the listener. The "empty" state is where no more messages remain in the mailbox. Here is the state machine we will be using:</p> <p style="text-align: center;; margin: 10px 0 0 0" class="diff-block-context"></p> 
<table class="diff-macro bodyless" style="background-color: #f0f0f0;border: 1px solid #dddddd;margin: 10px 1px;padding: 0 2px 2px;width: 100%;margin: 5px 0; padding: 0; width: auto;; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<thead> 
<tr> 
<th class="diff-macro-title" style="background-color: transparent; text-align: left; font-weight: normal;padding: 5px;"><span class="icon macro-placeholder-icon" style="background-color: ;line-height: 20px;"><img src="https://wiki.asterisk.org/wiki/s/en_GB/5635/60fd2eb45debbf4ede2b669f4c9b96b4ce40a937.48/_/plugins/servlet/confluence/placeholder/macro-icon?name=gliffy" style="padding-right: 5px; vertical-align: text-bottom;" /> </span>Gliffy Diagram</th> 
</tr> 
</thead> 
<tbody> 
<tr> 
<td class="diff-macro-properties" style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;padding: 0; border: 1px solid #dddddd;; padding: 0px; border-collapse: collapse"> 
<table style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<tbody> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse"></td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse"></td> 
</tr> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">name</td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">vm-listen</td> 
</tr> 
</tbody> 
</table> </td> 
</tr> 
</tbody> 
</table> <p style="margin: 10px 0 0 0"></p> <p class="diff-block-target" style="margin: 10px 0 0 0">Notice that <span class="diff-html-added" id="added-diff-12" style="font-size: 100%; background-color: #ddfade;">while in the listening state, </span>DMTF '4', '6', and '*' all change the state to the preamble state. This is so that the new message number can be played back to the caller before the next message is heard. Also notice that the preamble state is responsible for determining if the state should change to empty. This keeps the logic in the listening state more straight-forward since it is already having to deal with a lot of DTMF events. It also gracefully handles the case where a caller calls into the application when the caller has no voicemail messages.</p> <p class="diff-context-placeholder" style="margin: 10px 0 0 0">...</p> 
<table class="diff-macro diff-block-context" style="background-color: #f0f0f0;border: 1px solid #dddddd;margin: 10px 1px;padding: 0 2px 2px;width: 100%;; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<thead> 
<tr> 
<th class="diff-macro-title" style="background-color: transparent; text-align: left; font-weight: normal;padding: 5px;"><span class="icon macro-placeholder-icon" style="background-color: ;line-height: 20px;"><img src="https://wiki.asterisk.org/wiki/s/en_GB/5635/60fd2eb45debbf4ede2b669f4c9b96b4ce40a937.48/_/plugins/servlet/confluence/placeholder/macro-icon?name=code" style="padding-right: 5px; vertical-align: text-bottom;" /> </span>Code Block</th> 
</tr> 
</thead> 
<tbody> 
<tr> 
<td class="diff-macro-properties" style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;padding: 0; border: 1px solid #dddddd;; padding: 0px; border-collapse: collapse"> 
<table style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<tbody> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">title</td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">vm-playback.js</td> 
</tr> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">language</td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">js</td> 
</tr> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">collapse</td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">true</td> 
</tr> 
</tbody> 
</table> </td> 
</tr> 
</tbody> 
<tbody> 
<tr> 
<td class="diff-macro-body" style="background-color: #fff;border: 1px solid #dddddd;padding: 10px;; padding: 0px; border-collapse: collapse"> <pre style="margin: 10px 0 0 0; margin-top: 0">/*jshint node:true*/
'use strict';
 
var ari = require('ari-client');
var util = require('util');
var path = require('path');

var Event = require('./event');
var StateMachine = require('./state_machine');
var EndingState = require('./ending_state');
var HungUpState = require('./hungup_state');
var PreambleState = require('./preamble_state');
var EmptyState = require('./empty_state');
var ListeningState = require('./listening_state');

ari.connect('http://10.24.20.249:8088', 'asterisk', 'asterisk', clientLoaded);

var VoiceMailCall = function(ari_client, channel, mailbox) {
    var self = this;
    self.client = ari_client;
    self.channel = channel;
    self.current_voicemail = 0;
    self.voicemails = [];
    ari_client.recordings.listStored(function (err, recordings) {
        var vm_number = 1;
        var regex = new RegExp('^voicemail/' + mailbox);
        for (var i = 0; i < recordings.length; i++) {
            var rec_name = recordings[i].name;
            if (rec_name.search(regex) != -1) {
                console.log("Found voicemail", rec_name);
                self.voicemails.push({'number': vm_number, 'file': rec_name});
                vm_number++;
            }
        }

        self.setup_state_machine();
    });
}

VoiceMailCall.prototype.setup_state_machine = function() {
    var hungup_state = new HungUpState(this);
    var ending_state = new EndingState(this);
    var listening_state = new ListeningState(this);
    var preamble_state = new PreambleState(this);
    var empty_state = new EmptyState(this);
    this.state_machine = new StateMachine(this);
    this.state_machine.add_transition(listening_state, Event.DTMF_4, preamble_state);
    this.state_machine.add_transition(listening_state, Event.DTMF_6, preamble_state);
    this.state_machine.add_transition(listening_state, Event.HANGUP, hungup_state);
    this.state_machine.add_transition(listening_state, Event.DTMF_OCTOTHORPE, ending_state);
    this.state_machine.add_transition(listening_state, Event.DTMF_STAR, preamble_state);
    this.state_machine.add_transition(preamble_state, Event.DTMF_OCTOTHORPE, listening_state);
    this.state_machine.add_transition(preamble_state, Event.PLAYBACK_COMPLETE, listening_state);
    this.state_machine.add_transition(preamble_state, Event.MAILBOX_EMPTY, empty_state);
    this.state_machine.add_transition(preamble_state, Event.HANGUP, hungup_state);
    this.state_machine.add_transition(empty_state, Event.HANGUP, hungup_state);
    this.state_machine.add_transition(empty_state, Event.PLAYBACK_COMPLETE, ending_state);
    this.state_machine.start(preamble_state);
}

VoiceMailCall.prototype.next_message = function() {
    this.current_voicemail++;
    if (this.current_voicemail === this.voicemails.length) {
        this.current_voicemail = 0;
    }
}

VoiceMailCall.prototype.previous_message = function() {
    this.current_voicemail--;
    if (this.current_voicemail < 0) {
        this.current_voicemail = this.voicemails.length - 1;
    }
}

VoiceMailCall.prototype.delete_message = function() {
    this.voicemails.splice(this.current_voicemail, 1);
    if (this.current_voicemail === this.voicemails.length) {
        this.current_voicemail = 0;
    }
}

VoiceMailCall.prototype.get_current_voicemail_number = function() {
    return this.voicemails[this.current_voicemail]['number'];
}

VoiceMailCall.prototype.get_current_voicemail_file = function() {
    return this.voicemails[this.current_voicemail]['file'];
}

VoiceMailCall.prototype.mailbox_empty = function() {
    return this.voicemails.length === 0;
}

function clientLoaded(err, client) {
    if (err) {
        throw err;
    }
    client.on('StasisStart', stasisStart);
    function stasisStart(event, channel) {
        var mailbox = event.args[0]
        channel.answer(function(err) {
            if (err) {
                throw err;
            }
            new VoiceMailCall(client, channel, mailbox);
        });
    }
    client.start(process.argv[2]);
}</pre> </td> 
</tr> 
</tbody> 
</table> <p class="diff-block-target" style="margin: 10px 0 0 0"> <span class="diff-html-removed" id="removed-diff-11" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;"> </span> </p> <p class="diff-block-target diff-block-context" style="margin: 10px 0 0 0">Quite a bit of this is similar to what we were using <span class="diff-html-removed" id="removed-diff-12" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">for </span><code style="font-family: monospace"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">vm-call.py</span></code><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;"> previously. Aside from the new states, which will be introduced later, the real </span><span class="diff-html-added" id="added-diff-13" style="font-size: 100%; background-color: #ddfade;">for our voice mail recording application. The biggest </span>difference here is <span class="diff-html-removed" id="removed-diff-13" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">the new set of methods on the </span><code style="font-family: monospace"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">VoiceMailCall</span></code><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">.</span><span class="diff-html-added" id="added-diff-14" style="font-size: 100%; background-color: #ddfade;">that the call has many more methods defined since playing back voice mails is more complicated than recording a single one.</span> </p> <p class="diff-block-target diff-block-context" style="margin: 10px 0 0 0"> <span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">Now that we have the state machine defined and the application written, let's actually write the required new states. </span>First of the new states is the "preamble" state.</p> <p class="diff-context-placeholder" style="margin: 10px 0 0 0">...</p> <p class="diff-block-target" style="margin: 10px 0 0 0"> <code style="font-family: monospace">PreambleState</code> should look similar to the <code style="font-family: monospace">GreetingState</code> introduced previously <span class="diff-html-added" id="added-diff-15" style="font-size: 100%; background-color: #ddfade;">on this page</span>. The biggest difference is that the code is structured to play multiple sound files instead of just a single one. Note that it is acceptable to call <code style="font-family: monospace">channel.play()</code><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;"> </span><span class="diff-html-removed" id="removed-diff-14" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">multiple times consecutively </span><span class="diff-html-added" id="added-diff-16" style="font-size: 100%; background-color: #ddfade;">while a playback is playing on a channel in order </span>to queue <span class="diff-html-removed" id="removed-diff-15" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">playbacks on </span>a <span class="diff-html-removed" id="removed-diff-16" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">channel. However</span><span class="diff-html-added" id="added-diff-17" style="font-size: 100%; background-color: #ddfade;">second playback. For our application though</span>, we have elected to play the second sound only after the first has completed. <span class="diff-html-removed" id="removed-diff-17" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">This is to make it </span><span class="diff-html-added" id="added-diff-18" style="font-size: 100%; background-color: #ddfade;">The reason for this is that if there is only a single active playback at any given time, then it becomes </span>easier to clean up <span class="diff-html-removed" id="removed-diff-18" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">after ourself when it is time to change states</span><span class="diff-html-added" id="added-diff-19" style="font-size: 100%; background-color: #ddfade;">the current state when an event occurs that causes a state change</span>.</p> <p class="diff-block-context" style="margin: 10px 0 0 0">Next, here is the "empty" state code:</p> <p class="diff-context-placeholder" style="margin: 10px 0 0 0">...</p> 
<table class="diff-macro diff-block-context" style="background-color: #f0f0f0;border: 1px solid #dddddd;margin: 10px 1px;padding: 0 2px 2px;width: 100%;; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<thead> 
<tr> 
<th class="diff-macro-title" style="background-color: transparent; text-align: left; font-weight: normal;padding: 5px;"><span class="icon macro-placeholder-icon" style="background-color: ;line-height: 20px;"><img src="https://wiki.asterisk.org/wiki/s/en_GB/5635/60fd2eb45debbf4ede2b669f4c9b96b4ce40a937.48/_/plugins/servlet/confluence/placeholder/macro-icon?name=code" style="padding-right: 5px; vertical-align: text-bottom;" /> </span>Code Block</th> 
</tr> 
</thead> 
<tbody> 
<tr> 
<td class="diff-macro-properties" style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;padding: 0; border: 1px solid #dddddd;; padding: 0px; border-collapse: collapse"> 
<table style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<tbody> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">title</td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">empty_state.js</td> 
</tr> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">language</td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">js</td> 
</tr> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">collapse</td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">true</td> 
</tr> 
</tbody> 
</table> </td> 
</tr> 
</tbody> 
<tbody> 
<tr> 
<td class="diff-macro-body" style="background-color: #fff;border: 1px solid #dddddd;padding: 10px;; padding: 0px; border-collapse: collapse"> <pre style="margin: 10px 0 0 0; margin-top: 0">var Event = require('./event');

function sounds_installed(client) {
    client.sounds.get({soundId: 'vm-nomore'}, function(err) {
        if (err) {
            console.log("Required sound 'vm-nomore' not installed. Aborting");
            throw err;
        }
    });
}

var EmptyState = function(call) {
    this.state_name = "empty";
    this.call = call;
}

EmptyState.prototype.enter = function() {
    var self = this;
    console.log("Entering empty state");
    playback = self.call.client.Playback();
    self.call.channel.on("ChannelHangup", on_hangup);
    self.call.client.on("PlaybackFinished", on_playback_finished);
    self.call.channel.play({media: 'sound:vm-nomore'}, playback);

    function cleanup() {
        self.call.channel.removeListener('ChannelHangupRequest', on_hangup);
        self.call.channel.removeListener('PlaybackFinished', on_playback_finished);
        if (playback) {
            playback.stop();
        }
    }

    function on_hangup(event, channel) {
        playback = null;
        cleanup();
        self.call.state_machine.change_state(Event.HANGUP);
    }

    function on_playback_finished(event) {
        if (playback && playback.id === event.playback.id) {
            playback = null;
            cleanup();
            self.call.state_machine.change_state(Event.PLAYBACK_COMPLETE);
        }
    }
}

module.exports = EmptyState;</pre> </td> 
</tr> 
</tbody> 
</table> <p class="diff-block-target" style="margin: 10px 0 0 0"> <span class="diff-html-removed" id="removed-diff-19" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">And finally, here is </span><span class="diff-html-added" id="added-diff-20" style="font-size: 100%; background-color: #ddfade;">This state does not introduce anything we haven't seen already, so let's move on to </span>the "listening" state code:</p> <p class="diff-context-placeholder" style="margin: 10px 0 0 0">...</p> <p class="diff-block-target diff-block-context" style="margin: 10px 0 0 0"> <code style="font-family: monospace">ListeningState</code> is where we introduce new playback control concepts. <span class="diff-html-removed" id="removed-diff-20" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">The </span><code style="font-family: monospace"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">control()</span></code><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;"> method on playbacks allows for the current playback to be manipulated in various ways. All </span><span class="diff-html-added" id="added-diff-21" style="font-size: 100%; background-color: #ddfade;">Playbacks have their controlling operations wrapped in a single method, </span><code style="font-family: monospace"><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">control()</span></code><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">, rather than having lots of separate operations. All control </span>operations (reverse, pause, unpause, forward, and restart) are demonstrated <span class="diff-html-removed" id="removed-diff-21" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">here.</span><span class="diff-html-added" id="added-diff-22" style="font-size: 100%; background-color: #ddfade;">by this state.</span> </p> 
<table class="diff-macro diff-html-added diff-block-target diff-block-context" style="background-color: #f0f0f0;border: 1px solid #dddddd;margin: 10px 1px;padding: 0 2px 2px;width: 100%;background-color: #ddfade;border-color: #93c49f;; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<thead> 
<tr> 
<th class="diff-macro-title" style="background-color: transparent; text-align: left; font-weight: normal;padding: 5px;"><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;"><span class="icon macro-placeholder-icon" style="background-color: ;line-height: 20px;"><img src="https://wiki.asterisk.org/wiki/s/en_GB/5635/60fd2eb45debbf4ede2b669f4c9b96b4ce40a937.48/_/images/icons/macrobrowser/dropdown/panel.png" style="padding-right: 5px; vertical-align: text-bottom;" /> </span>Panel</span></th> 
</tr> 
</thead> 
<tbody> 
<tr> 
<td class="diff-macro-properties" style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;padding: 0; border: 1px solid #dddddd;; padding: 0px; border-collapse: collapse"> 
<table style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<tbody> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse"><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">bgColor</span></td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse"><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">silver</span></td> 
</tr> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse"><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">titleBGColor</span></td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse"><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">seagreen</span></td> 
</tr> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse"><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">borderStyle</span></td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse"><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">solid</span></td> 
</tr> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse"><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">title</span></td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse"><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">Reader Exercise 2</span></td> 
</tr> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse"><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">titleColor</span></td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse"><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">black</span></td> 
</tr> 
</tbody> 
</table> </td> 
</tr> 
</tbody> 
<tbody> 
<tr> 
<td class="diff-macro-body" style="background-color: #fff;border: 1px solid #dddddd;padding: 10px;; padding: 0px; border-collapse: collapse"> <p style="margin: 10px 0 0 0; margin-top: 0"> <span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">You may have noticed while exploring the playbacks API that the </span><code style="font-family: monospace"><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">control()</span></code><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;"> method takes no parameters other than the operation. This means that certain properties of operations are determined when the playback is started on the channel.</span> </p> <p style="margin: 10px 0 0 0"> <span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">For this exercise, modify the </span><code style="font-family: monospace"><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">ListeningState</span></code><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;"> so that DTMF '1' and '3' reverse or forward the playback by 5000 milliseconds instead of the default 3000 milliseconds.</span> </p> </td> 
</tr> 
</tbody> 
</table> <p class="diff-block-target diff-block-context" style="margin: 10px 0 0 0"> <span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;"> </span> </p> <h1 id="Part2:Playbacks-Playbacksonbridges" class="diff-block-target diff-block-context" style="margin: 10px 0 0 0; font-size: 24px; font-weight: normal; line-height: 30px; margin: 40px 0 0 0"> <span class="diff-html-changed" id="changed-diff-3" style="background-color: #d6f0ff;">Playbacks on bridges</span> </h1> <p class="diff-block-target diff-block-context" style="margin: 10px 0 0 0">Just as channels allow for playbacks to be performed on them, bridges also have the capacity to have sounds, recordings, tones, numbers, etc. played back on them. The difference is is that all participants in the bridge will hear the playback instead of just <span class="diff-html-removed" id="removed-diff-22" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">the </span><span class="diff-html-added" id="added-diff-23" style="font-size: 100%; background-color: #ddfade;">a </span>single channel. In bridging situations, it can be useful to play certain sounds to an entire bridge (e.g. Telling participants the call is being recorded), but it can also be useful to play sounds to specific participants (e.g. Telling a caller he has joined a conference bridge). A playback on a bridge can be stopped or controlled exactly the same as a playback on a channel.</p> 
<table class="diff-macro diff-block-target" style="background-color: #f0f0f0;border: 1px solid #dddddd;margin: 10px 1px;padding: 0 2px 2px;width: 100%;; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<thead> 
<tr> 
<th class="diff-macro-title" style="background-color: transparent; text-align: left; font-weight: normal;padding: 5px;"><span class="icon macro-placeholder-icon" style="background-color: ;line-height: 20px;"><img src="https://wiki.asterisk.org/wiki/s/en_GB/5635/60fd2eb45debbf4ede2b669f4c9b96b4ce40a937.48/_/images/icons/macrobrowser/dropdown/panel.png" style="padding-right: 5px; vertical-align: text-bottom;" /> </span>Panel</th> 
</tr> 
</thead> 
<tbody> 
<tr> 
<td class="diff-macro-properties" style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;padding: 0; border: 1px solid #dddddd;; padding: 0px; border-collapse: collapse"> 
<table style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<tbody> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">bgColor</td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">silver</td> 
</tr> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">titleBGColor</td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">seagreen</td> 
</tr> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">borderStyle</td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">solid</td> 
</tr> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">title</td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">Reader Exercise <span class="diff-html-removed" id="removed-diff-23" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">6</span><span class="diff-html-added" id="added-diff-24" style="font-size: 100%; background-color: #ddfade;">3</span></td> 
</tr> 
<tr> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">titleColor</td> 
<td style="background-color: #fafafa; padding: 0 0 0 5px; font-size: 12px; text-align: left;; padding: 0px; border-collapse: collapse">black</td> 
</tr> 
</tbody> 
</table> </td> 
</tr> 
</tbody> 
<tbody> 
<tr> 
<td class="diff-macro-body" style="background-color: #fff;border: 1px solid #dddddd;padding: 10px;; padding: 0px; border-collapse: collapse"> <p style="margin: 10px 0 0 0; margin-top: 0">If you've read through the Recording and Playbacks pages, then you should have a good grasp on the operations available, as well as a decent state machine implementation. <span class="diff-html-removed" id="removed-diff-24" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">Instead </span><span class="diff-html-added" id="added-diff-25" style="font-size: 100%; background-color: #ddfade;">For our final exercise, instead </span>of adding onto the existing voice mail applications, create a new application that uses <span class="diff-html-added" id="added-diff-26" style="font-size: 100%; background-color: #ddfade;">some of </span>the recording and playback operations that you have learned about.</p> <p style="margin: 10px 0 0 0">You will be creating a rudimentary call queue application. The queue application will have two types of participants: agents and callers. Agents and callers call into the same Stasis application and are distinguished based on arguments to the Stasis application (e.g. A caller might call Stasis(queue,caller) and an agent might call Stasis(queue,agent) from the dialplan).</p> 
<ul style="margin: 10px 0 0 0"> 
<li>When an agent calls into the Stasis application, the agent is placed into an agent queue. 
<ul style="margin: 10px 0 0 0; margin-top: 0"> 
<li>While in the agent queue, the agent should hear music on hold. Information about how to play music on hold to a channel can be found here.</li> 
</ul> </li> 
<li>When a caller calls into the Stasis application, the caller is placed into a caller queue. 
<ul style="margin: 10px 0 0 0; margin-top: 0"> 
<li>While in the caller queue, the caller should hear music on hold.</li> 
<li>Every 30 seconds, the caller should hear an announcement. If the caller is at the front of the queue, the "queue-youarenext" sound should play. If the caller is not at the front of the queue, then the caller should hear the "queue-thereare" sound, then the number of callers ahead in the queue, then the "queue-callswaiting" sound.</li> 
</ul> </li> 
<li>If there is a caller in the caller queue and an agent in the agent queue, then the caller and agent at the front of their respective queues are removed and placed into a bridge with each other. <span class="diff-html-added" id="added-diff-27" style="font-size: 100%; background-color: #ddfade;">For more information on bridging channels, see </span><a class="confluence-link unresolved" href="#" style="color: #3b73af; text-decoration: none"><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">this page</span></a><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">. </span>If this happens while a caller has a sound file playing, then this should cause the sound file to immediately stop playing in order to bridge the call.</li> 
<li>Once bridged, the agent can perform the following: 
<ul style="margin: 10px 0 0 0; margin-top: 0"> 
<li>Pressing '0' should start recording the bridge. Upon recording the bridge, the caller should hear a beep sound.</li> 
<li>Pressing '5' while the call is being recorded should pause the recording. Pressing '5' a second time should unpause the recording.</li> 
<li>Pressing '7' while the call is being recorded should stop the recording.</li> 
<li>Pressing '9' while the call is being recorded should discard the recording.</li> 
<li>Pressing '#' at any time (whether the call is being recorded or not) should end the call, causing the agent to be placed into the back of the agent queue and the caller to be hung up.</li> 
<li>If the agent hangs up, then the caller should also be hung up.</li> 
</ul> </li> 
<li>Once bridged, if the caller hangs up, then the agent should be placed into the back of the agent queue.</li> 
</ul> <p style="margin: 10px 0 0 0">Best of luck!</p> </td> 
</tr> 
</tbody> 
</table> </td> 
</tr> 
</tbody> 
</table> </td> 
</tr> 
<tr> 
<td class="email-content-main mobile-expand action-padding last-row-padding" style="padding: 0px; border-collapse: collapse; border-left: 1px solid #ccc; border-right: 1px solid #ccc; border-top: 0; border-bottom: 0; padding: 0 15px 15px 16px; background-color: #fff; padding-bottom: 10px; padding-bottom: 10px"> 
<table id="actions-pattern" cellspacing="0" cellpadding="0" border="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; mso-line-height-rule: exactly; mso-text-raise: 1px"> 
<tbody> 
<tr> 
<td id="actions-pattern-container" valign="middle" style="padding: 0px; border-collapse: collapse; padding: 15px 0 0 24px; vertical-align: middle"> 
<table align="left" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<tbody> 
<tr> 
<td class="actions-pattern-action-icon-container" style="padding: 0px; border-collapse: collapse; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; mso-line-height-rule: exactly; mso-text-raise: 0px; vertical-align: middle"><a href="https://wiki.asterisk.org/wiki/display/AST/Part+2%3A+Playbacks?src=email" title="View page Icon" style="color: #3b73af; text-decoration: none"><img class="actions-pattern-action-icon-image" height="16" width="16" border="0" title="View page Icon" src="cid:com.atlassian.confluence.plugins.confluence-email-resources%3Aview-page-email-adg-footer-item%3Aicon" alt="View page Icon" style="vertical-align: middle" /></a></td>
<td class="actions-pattern-action-text-container" style="padding: 0px; border-collapse: collapse; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; mso-line-height-rule: exactly; mso-text-raise: 4px; padding-left: 5px; white-space: nowrap"><a href="https://wiki.asterisk.org/wiki/display/AST/Part+2%3A+Playbacks?src=email" title="View page" style="color: #3b73af; text-decoration: none">View page</a></td>
<td class="actions-pattern-action-bull" style="padding: 0px; border-collapse: collapse; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; mso-line-height-rule: exactly; mso-text-raise: 4px; color: #999; padding: 0 5px">•</td> 
</tr> 
</tbody> 
</table> 
<table align="left" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<tbody> 
<tr> 
<td class="actions-pattern-action-icon-container" style="padding: 0px; border-collapse: collapse; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; mso-line-height-rule: exactly; mso-text-raise: 0px; vertical-align: middle"><a href="https://wiki.asterisk.org/wiki/display/AST/Part+2%3A+Playbacks?showComments=true&showCommentArea=true&src=email#addcomment" title="Add comment Icon" style="color: #3b73af; text-decoration: none"><img class="actions-pattern-action-icon-image" height="16" width="16" border="0" title="Add comment Icon" src="cid:com.atlassian.confluence.plugins.confluence-email-resources%3Aadd-comment-to-content-email-adg-footer-item%3Aicon" alt="Add comment Icon" style="vertical-align: middle" /></a></td>
<td class="actions-pattern-action-text-container" style="padding: 0px; border-collapse: collapse; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; mso-line-height-rule: exactly; mso-text-raise: 4px; padding-left: 5px; white-space: nowrap"><a href="https://wiki.asterisk.org/wiki/display/AST/Part+2%3A+Playbacks?showComments=true&showCommentArea=true&src=email#addcomment" title="Add comment" style="color: #3b73af; text-decoration: none">Add comment</a></td>
<td class="actions-pattern-action-bull" style="padding: 0px; border-collapse: collapse; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; mso-line-height-rule: exactly; mso-text-raise: 4px; color: #999; padding: 0 5px">•</td> 
</tr> 
</tbody> 
</table> 
<table style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<tbody> 
<tr> 
<td class="actions-pattern-action-icon-container" style="padding: 0px; border-collapse: collapse; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; mso-line-height-rule: exactly; mso-text-raise: 0px; vertical-align: middle"><a href="https://wiki.asterisk.org/wiki/plugins/likes/like.action?contentId=30277828&src=email" title="Like Icon" style="color: #3b73af; text-decoration: none"><img class="actions-pattern-action-icon-image" height="16" width="16" border="0" title="Like Icon" src="cid:com.atlassian.confluence.plugins.confluence-like%3Aview-email-adg-content-item%3Aicon" alt="Like Icon" style="vertical-align: middle" /></a></td>
<td class="actions-pattern-action-text-container" style="padding: 0px; border-collapse: collapse; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; mso-line-height-rule: exactly; mso-text-raise: 4px; padding-left: 5px; white-space: nowrap"><a href="https://wiki.asterisk.org/wiki/plugins/likes/like.action?contentId=30277828&src=email" title="Like" style="color: #3b73af; text-decoration: none">Like</a></td> 
</tr> 
</tbody> 
</table> </td> 
</tr> 
</tbody> 
</table> </td> 
</tr> 
<tr> 
<td class="email-content-rounded-bottom mobile-expand" style="padding: 0px; border-collapse: collapse; color: #fff; height: 5px; line-height: 5px; padding: 0 15px 0 16px; background-color: #fff; border-bottom-right-radius: 5px; border-bottom-left-radius: 5px; border-top: 0; border-left: 1px solid #ccc; border-bottom: 1px solid #ccc; border-right: 1px solid #ccc; mso-line-height-rule: exactly"> </td> 
</tr> 
</tbody> 
</table> </td> 
</tr> 
<tr> 
<td id="footer-pattern" style="padding: 0px; border-collapse: collapse; padding: 12px 20px"> 
<table id="footer-pattern-container" cellspacing="0" cellpadding="0" border="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333"> 
<tbody> 
<tr> 
<td id="footer-pattern-links-container" width="100%" style="padding: 0px; border-collapse: collapse; color: #999; font-size: 12px; line-height: 18px; font-family: Arial, sans-serif; mso-line-height-rule: exactly; mso-text-raise: 2px"> 
<table align="left" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333; font-size: 12px; line-height: 18px; font-family: Arial, sans-serif; mso-line-height-rule: exactly; mso-text-raise: 2px"> 
<tbody> 
<tr> 
<td class="footer-pattern-links mobile-resize-text" style="padding: 0px; border-collapse: collapse"><a href="https://wiki.asterisk.org/wiki/users/removespacenotification.action?spaceKey=AST&src=email" title="" style="color: #3b73af; text-decoration: none">Stop watching space</a></td>
<td class="footer-pattern-links-bull" style="padding: 0px; border-collapse: collapse; padding: 0 5px; color: #999">•</td> 
</tr> 
</tbody> 
</table> 
<table style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333; font-size: 12px; line-height: 18px; font-family: Arial, sans-serif; mso-line-height-rule: exactly; mso-text-raise: 2px"> 
<tbody> 
<tr> 
<td class="footer-pattern-links mobile-resize-text" style="padding: 0px; border-collapse: collapse"><a href="https://wiki.asterisk.org/wiki/users/editmyemailsettings.action?src=email" title="" style="color: #3b73af; text-decoration: none">Manage notifications</a></td> 
</tr> 
</tbody> 
</table> </td> 
</tr> 
<tr> 
<td id="footer-pattern-text" class="mobile-resize-text" width="100%" style="padding: 0px; border-collapse: collapse; color: #999; font-size: 12px; line-height: 18px; font-family: Arial, sans-serif; mso-line-height-rule: exactly; mso-text-raise: 2px; display: none">This message was sent by Atlassian Confluence 5.6.1</td> 
</tr> 
</tbody> 
</table> </td> 
</tr> 
</tbody> 
</table> 
<table id="sealed-section" border="0" cellpadding="0" cellspacing="0" width="0" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333; display: none"> 
<tbody> 
<tr> 
<td style="padding: 0px; border-collapse: collapse; border: 0; font-size: 0px; line-height: 0; mso-line-height-rule: exactly"></td> 
</tr> 
</tbody> 
</table>
</body>
</html>