<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; }}
</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/~mjordan?src=email" style="color: #3b73af; text-decoration: none"><img id="header-avatar-image" class="image_fix" src="cid:avatar_ce51dcf276530e4a4b00548e2a6d0905" 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">Matt Jordan <strong>created</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/ARI+and+Channels%3A+Simple+Media+Manipulation?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/ARI+and+Channels%3A+Simple+Media+Manipulation?src=email" title="ARI and Channels: Simple Media Manipulation" style="color: #3b73af; text-decoration: none">ARI and Channels: Simple Media Manipulation</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">
<div class="sectionColumnWrapper">
<div class="sectionMacro">
<div class="sectionMacroRow">
<div class="columnMacro" style="width:60%;min-width:60%;max-width:60%;">
<h1 id="ARIandChannels:SimpleMediaManipulation-Simplemediaplayback" 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">Simple media playback</h1>
<p style="margin: 10px 0 0 0">Almost all media is played to a channel using the <code style="font-family: monospace">POST /channels/{channel_id}/play</code> operation. This will do the following:</p>
<ol style="margin: 10px 0 0 0">
<li>Create a new <a href="https://wiki.asterisk.org/wiki/display/AST/Asterisk+12+REST+Data+Models#Asterisk12RESTDataModels-Playback" rel="nofollow" style="color: #3b73af; text-decoration: none"><code style="font-family: monospace">Playback</code></a> object for the channel. If a media operation is currently in progress on the channel, the new <code style="font-family: monospace">Playback</code> object will be queued up for the channel.</li>
<li> <p style="margin: 10px 0 0 0; margin-top: 0">The <code style="font-family: monospace">media</code> URI passed to the <code style="font-family: monospace">play</code> operation will be inspected, and Asterisk will attempt to find the media requested. Currently, the following media schemes are supported:</p>
<div class="table-wrap" style="margin: 10px 0 0 0; overflow-x: auto">
<table class="confluenceTable" style="border-collapse: collapse; border: 1px solid #ddd;; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; color: #333; border-collapse: collapse; margin: 10px 0 0 0; overflow-x: auto; margin-top: 0">
<tbody>
<tr style="margin-left: 60.0px;">
<th class="confluenceTh" style="border: 1px solid #DDD; padding: 5px 7px; min-width: 0.6em; text-align: left; vertical-align: top;background-color: #F0F0F0; font-weight: bold;; border: 1px solid #ddd; padding: 7px 10px; vertical-align: top; text-align: left; background-color: #f0f0f0; font-weight: bold">URI Scheme</th>
<th class="confluenceTh" style="border: 1px solid #DDD; padding: 5px 7px; min-width: 0.6em; text-align: left; vertical-align: top;background-color: #F0F0F0; font-weight: bold;; border: 1px solid #ddd; padding: 7px 10px; vertical-align: top; text-align: left; background-color: #f0f0f0; font-weight: bold">Description</th>
</tr>
<tr style="margin-left: 60.0px;">
<td class="confluenceTd" style="border: 1px solid #DDD; padding: 5px 7px; min-width: 0.6em; text-align: left; vertical-align: top;; padding: 0px; border-collapse: collapse; border: 1px solid #ddd; padding: 7px 10px; vertical-align: top; text-align: left"><code style="font-family: monospace">sound</code></td>
<td class="confluenceTd" style="border: 1px solid #DDD; padding: 5px 7px; min-width: 0.6em; text-align: left; vertical-align: top;; padding: 0px; border-collapse: collapse; border: 1px solid #ddd; padding: 7px 10px; vertical-align: top; text-align: left">A sound file located on the Asterisk system. You can use the <code style="font-family: monospace"><a href="https://wiki.asterisk.org/wiki/display/AST/Asterisk+12+Sounds+REST+API" rel="nofollow" style="color: #3b73af; text-decoration: none">/sounds</a></code> resource to query for available sounds on the system.</td>
</tr>
<tr style="margin-left: 60.0px;">
<td colspan="1" class="confluenceTd" style="border: 1px solid #DDD; padding: 5px 7px; min-width: 0.6em; text-align: left; vertical-align: top;; padding: 0px; border-collapse: collapse; border: 1px solid #ddd; padding: 7px 10px; vertical-align: top; text-align: left"><code style="font-family: monospace">recording</code></td>
<td colspan="1" class="confluenceTd" style="border: 1px solid #DDD; padding: 5px 7px; min-width: 0.6em; text-align: left; vertical-align: top;; padding: 0px; border-collapse: collapse; border: 1px solid #ddd; padding: 7px 10px; vertical-align: top; text-align: left">A <a href="https://wiki.asterisk.org/wiki/display/AST/Asterisk+12+REST+Data+Models#Asterisk12RESTDataModels-StoredRecording" rel="nofollow" style="color: #3b73af; text-decoration: none"><code style="font-family: monospace">StoredRecording</code></a> stored on the Asterisk system. You can use the <a href="https://wiki.asterisk.org/wiki/display/AST/Asterisk+12+Recordings+REST+API" rel="nofollow" style="color: #3b73af; text-decoration: none"><code style="font-family: monospace">/recordings/stored</code></a> resource to query for available <code style="font-family: monospace">StoredRecording</code>s on the system.</td>
</tr>
<tr style="margin-left: 60.0px;">
<td colspan="1" class="confluenceTd" style="border: 1px solid #DDD; padding: 5px 7px; min-width: 0.6em; text-align: left; vertical-align: top;; padding: 0px; border-collapse: collapse; border: 1px solid #ddd; padding: 7px 10px; vertical-align: top; text-align: left"><code style="font-family: monospace">number</code></td>
<td colspan="1" class="confluenceTd" style="border: 1px solid #DDD; padding: 5px 7px; min-width: 0.6em; text-align: left; vertical-align: top;; padding: 0px; border-collapse: collapse; border: 1px solid #ddd; padding: 7px 10px; vertical-align: top; text-align: left">Play back the specified number. This uses the same mechanism as Asterisk's <code style="font-family: monospace"><a href="https://wiki.asterisk.org/wiki/display/AST/SayDigits,+SayNumber,+SayAlpha,+and+SayPhonetic+Applications?src=search" rel="nofollow" style="color: #3b73af; text-decoration: none">Say</a></code> family of applications.</td>
</tr>
<tr style="margin-left: 60.0px;">
<td colspan="1" class="confluenceTd" style="border: 1px solid #DDD; padding: 5px 7px; min-width: 0.6em; text-align: left; vertical-align: top;; padding: 0px; border-collapse: collapse; border: 1px solid #ddd; padding: 7px 10px; vertical-align: top; text-align: left"><code style="font-family: monospace">digits</code></td>
<td colspan="1" class="confluenceTd" style="border: 1px solid #DDD; padding: 5px 7px; min-width: 0.6em; text-align: left; vertical-align: top;; padding: 0px; border-collapse: collapse; border: 1px solid #ddd; padding: 7px 10px; vertical-align: top; text-align: left">Play back the specified digits. This uses the same mechanism as Asterisk's <code style="font-family: monospace"><a href="https://wiki.asterisk.org/wiki/display/AST/SayDigits,+SayNumber,+SayAlpha,+and+SayPhonetic+Applications?src=search" rel="nofollow" style="color: #3b73af; text-decoration: none">Say</a></code> family of applications.</td>
</tr>
<tr style="margin-left: 60.0px;">
<td colspan="1" class="confluenceTd" style="border: 1px solid #DDD; padding: 5px 7px; min-width: 0.6em; text-align: left; vertical-align: top;; padding: 0px; border-collapse: collapse; border: 1px solid #ddd; padding: 7px 10px; vertical-align: top; text-align: left"><code style="font-family: monospace">characters</code></td>
<td colspan="1" class="confluenceTd" style="border: 1px solid #DDD; padding: 5px 7px; min-width: 0.6em; text-align: left; vertical-align: top;; padding: 0px; border-collapse: collapse; border: 1px solid #ddd; padding: 7px 10px; vertical-align: top; text-align: left">Play back the specified characters. This uses the same mechanism as Asterisk's <code style="font-family: monospace"><a href="https://wiki.asterisk.org/wiki/display/AST/SayDigits,+SayNumber,+SayAlpha,+and+SayPhonetic+Applications?src=search" rel="nofollow" style="color: #3b73af; text-decoration: none">Say</a></code> family of applications.</td>
</tr>
<tr style="margin-left: 60.0px;">
<td colspan="1" class="confluenceTd" style="border: 1px solid #DDD; padding: 5px 7px; min-width: 0.6em; text-align: left; vertical-align: top;; padding: 0px; border-collapse: collapse; border: 1px solid #ddd; padding: 7px 10px; vertical-align: top; text-align: left"><code style="font-family: monospace">tone</code></td>
<td colspan="1" class="confluenceTd" style="border: 1px solid #DDD; padding: 5px 7px; min-width: 0.6em; text-align: left; vertical-align: top;; padding: 0px; border-collapse: collapse; border: 1px solid #ddd; padding: 7px 10px; vertical-align: top; text-align: left">Play a particular tone sequence until stopped. This can be used to play locale specific ringing, stutter, busy, congestion, or other tones to a device.</td>
</tr>
</tbody>
</table>
</div> </li>
<li>Once the media operation is started or enqueued, the <code style="font-family: monospace">Playback</code> object will be returned to the caller in the <code style="font-family: monospace">HTTP</code> response to the request. The caller can use that playback object to manipulate the media operation.</li>
</ol>
<p style="margin: 10px 0 0 0"> </p>
</div>
<div class="columnMacro">
<div class="panel" style="border-width: 1px;">
<div class="panelHeader" style="border-bottom-width: 1px;">
<b>On This Page</b>
</div>
<div class="panelContent">
<p style="margin: 10px 0 0 0; margin-top: 0"> <style type="text/css">/**/
div.rbtoc1408639955687 {padding: 0px;}
div.rbtoc1408639955687 ul {list-style: disc;margin-left: 0px;}
div.rbtoc1408639955687 li {margin-left: 0px;padding-left: 0px;}
/**/</style> </p>
<div class="toc-macro rbtoc1408639955687" style="padding: 0px; padding: 0px">
<ul class="toc-indentation" style="margin: 10px 0 0 0; margin-top: 0; list-style: disc; margin-left: 0px; list-style: disc; margin-left: 0px">
<li style="margin-left: 0px; padding-left: 0px; margin-left: 0px; padding-left: 0px"> <a href="#ARIandChannels:SimpleMediaManipulation-Simplemediaplayback" style="color: #3b73af; text-decoration: none">Simple media playback</a>
<ul class="toc-indentation" style="margin: 10px 0 0 0; list-style: disc; margin-left: 0px; list-style: disc; margin-left: 0px">
<li style="margin-left: 0px; padding-left: 0px; margin-left: 0px; padding-left: 0px"> <a href="#ARIandChannels:SimpleMediaManipulation-EarlyMedia" style="color: #3b73af; text-decoration: none">Early Media</a> </li>
</ul> </li>
<li style="margin-left: 0px; padding-left: 0px; margin-left: 0px; padding-left: 0px"> <a href="#ARIandChannels:SimpleMediaManipulation-Example:Playingbacktones" style="color: #3b73af; text-decoration: none">Example: Playing back tones</a>
<ul class="toc-indentation" style="margin: 10px 0 0 0; list-style: disc; margin-left: 0px; list-style: disc; margin-left: 0px">
<li style="margin-left: 0px; padding-left: 0px; margin-left: 0px; padding-left: 0px"> <a href="#ARIandChannels:SimpleMediaManipulation-Dialplan" style="color: #3b73af; text-decoration: none">Dialplan</a> </li>
<li style="margin-left: 0px; padding-left: 0px; margin-left: 0px; padding-left: 0px"> <a href="#ARIandChannels:SimpleMediaManipulation-Python" style="color: #3b73af; text-decoration: none">Python</a>
<ul class="toc-indentation" style="margin: 10px 0 0 0; list-style: disc; margin-left: 0px; list-style: disc; margin-left: 0px">
<li style="margin-left: 0px; padding-left: 0px; margin-left: 0px; padding-left: 0px"> <a href="#ARIandChannels:SimpleMediaManipulation-channel-tones.py" style="color: #3b73af; text-decoration: none">channel-tones.py</a> </li>
<li style="margin-left: 0px; padding-left: 0px; margin-left: 0px; padding-left: 0px"> <a href="#ARIandChannels:SimpleMediaManipulation-channel-tones.pyinaction" style="color: #3b73af; text-decoration: none">channel-tones.py in action</a> </li>
</ul> </li>
<li style="margin-left: 0px; padding-left: 0px; margin-left: 0px; padding-left: 0px"> <a href="#ARIandChannels:SimpleMediaManipulation-JavaScript(Node.js)" style="color: #3b73af; text-decoration: none">JavaScript (Node.js)</a>
<ul class="toc-indentation" style="margin: 10px 0 0 0; list-style: disc; margin-left: 0px; list-style: disc; margin-left: 0px">
<li style="margin-left: 0px; padding-left: 0px; margin-left: 0px; padding-left: 0px"> <a href="#ARIandChannels:SimpleMediaManipulation-channel-tones.js" style="color: #3b73af; text-decoration: none">channel-tones.js</a> </li>
<li style="margin-left: 0px; padding-left: 0px; margin-left: 0px; padding-left: 0px"> <a href="#ARIandChannels:SimpleMediaManipulation-channel-tones.jsinaction" style="color: #3b73af; text-decoration: none">channel-tones.js in action</a> </li>
</ul> </li>
</ul> </li>
<li style="margin-left: 0px; padding-left: 0px; margin-left: 0px; padding-left: 0px"> <a href="#ARIandChannels:SimpleMediaManipulation-Example:Playingbackasoundfile" style="color: #3b73af; text-decoration: none">Example: Playing back a sound file</a>
<ul class="toc-indentation" style="margin: 10px 0 0 0; list-style: disc; margin-left: 0px; list-style: disc; margin-left: 0px">
<li style="margin-left: 0px; padding-left: 0px; margin-left: 0px; padding-left: 0px"> <a href="#ARIandChannels:SimpleMediaManipulation-Dialplan.1" style="color: #3b73af; text-decoration: none">Dialplan</a> </li>
<li style="margin-left: 0px; padding-left: 0px; margin-left: 0px; padding-left: 0px"> <a href="#ARIandChannels:SimpleMediaManipulation-Python.1" style="color: #3b73af; text-decoration: none">Python</a>
<ul class="toc-indentation" style="margin: 10px 0 0 0; list-style: disc; margin-left: 0px; list-style: disc; margin-left: 0px">
<li style="margin-left: 0px; padding-left: 0px; margin-left: 0px; padding-left: 0px"> <a href="#ARIandChannels:SimpleMediaManipulation-channel-playback-monkeys.py" style="color: #3b73af; text-decoration: none">channel-playback-monkeys.py</a> </li>
<li style="margin-left: 0px; padding-left: 0px; margin-left: 0px; padding-left: 0px"> <a href="#ARIandChannels:SimpleMediaManipulation-channel-playback-monkeys.pyinaction" style="color: #3b73af; text-decoration: none">channel-playback-monkeys.py in action</a> </li>
</ul> </li>
<li style="margin-left: 0px; padding-left: 0px; margin-left: 0px; padding-left: 0px"> <a href="#ARIandChannels:SimpleMediaManipulation-JavaScript(Node.js).1" style="color: #3b73af; text-decoration: none">JavaScript (Node.js)</a>
<ul class="toc-indentation" style="margin: 10px 0 0 0; list-style: disc; margin-left: 0px; list-style: disc; margin-left: 0px">
<li style="margin-left: 0px; padding-left: 0px; margin-left: 0px; padding-left: 0px"> <a href="#ARIandChannels:SimpleMediaManipulation-channel-playback-monkeys.js" style="color: #3b73af; text-decoration: none">channel-playback-monkeys.js</a> </li>
<li style="margin-left: 0px; padding-left: 0px; margin-left: 0px; padding-left: 0px"> <a href="#ARIandChannels:SimpleMediaManipulation-channel-playback-monkeys.jsinaction" style="color: #3b73af; text-decoration: none">channel-playback-monkeys.js in action</a> </li>
</ul> </li>
</ul> </li>
</ul>
</div>
<p style="margin: 10px 0 0 0"></p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="aui-message success shadowed information-macro">
<p class="title" style="margin: 10px 0 0 0; margin-top: 0">Specify your own ID!</p>
<span class="aui-icon icon-success">Icon</span>
<div class="message-content">
<p style="margin: 10px 0 0 0; margin-top: 0">It is <strong>highly</strong> recommended that the <code style="font-family: monospace">POST /channels/{channel_id}/play/{playback_id}</code> operation be used instead of the <code style="font-family: monospace">POST /channels/{channel_id}/play</code> variant. Asterisk lives in an asynchronous world - which is the same world you and I live in. Sometimes, if things happen <em>very</em> quickly, you may get notifications over the WebSocket about things you have started before the HTTP response completes!</p>
<p style="margin: 10px 0 0 0">When you specify your own ID, you have the ability to tie information coming from events back to whatever operation you initiated - if you so choose to. If you use the non-ID providing variant, Asterisk will happily generate a UUID for your <code style="font-family: monospace">Playback</code> object - but then it is up to you to deal with whatever information comes back from the WebSocket.</p>
</div>
</div> <h2 id="ARIandChannels:SimpleMediaManipulation-EarlyMedia" style="margin: 10px 0 0 0; font-size: 20px; font-weight: normal; line-height: 30px; margin: 40px 0 0 0">Early Media</h2> <p style="margin: 10px 0 0 0">Generally, before a channel has been answered and transitioned to the Up state, media cannot pass between Asterisk and a device. For example, if Asterisk is placing an outbound call to a device, the device may be ringing but no one has picked up a handset yet! In such circumstances, media cannot be successfully played to the ringing device - after all, who could listen to it?</p> <p style="margin: 10px 0 0 0">However, with inbound calls, Asterisk is the entity that decides when the path of communication between itself and the device is answered - not the user on the other end. This can be useful when answering the channel may trigger billing times or other mechanisms that we don't want to fire yet. This is called "early media". For the channel technologies that support this, ARI and Asterisk will automatically handle sending the correct indications to the ringing phone before sending it media. The same <code style="font-family: monospace">play</code> operation can be used both for "regular" playback of media, as well as for "early media" scenarios.</p> <h1 id="ARIandChannels:SimpleMediaManipulation-Example:Playingbacktones" style="margin: 10px 0 0 0; font-size: 24px; font-weight: normal; line-height: 30px; margin: 40px 0 0 0">Example: Playing back tones</h1> <p style="margin: 10px 0 0 0">This example ARI application will do the following:</p>
<ol style="margin: 10px 0 0 0">
<li>When a channel enters into the Stasis application, it will start a playback of a French ringing tone.</li>
<li>After 8 seconds, the channel will be answered.</li>
<li>After 1 second, the channel will be rudely hung up on - we didn't want to talk to them anyway!</li>
</ol> <h2 id="ARIandChannels:SimpleMediaManipulation-Dialplan" style="margin: 10px 0 0 0; font-size: 20px; font-weight: normal; line-height: 30px; margin: 40px 0 0 0">Dialplan</h2> <p style="margin: 10px 0 0 0">For this example, we need to just drop the channel into Stasis, specifying our application:</p>
<div class="code panel pdl" style="border-width: 1px;">
<div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;">
<b>extensions.conf</b>
</div>
<div class="codeContent panelContent pdl">
<pre class="theme: Confluence; brush: text; gutter: true" style="font-size:12px;; margin: 10px 0 0 0; margin-top: 0">exten => 1000,1,NoOp()
same => n,Stasis(channel-tones)
same => n,Hangup() </pre>
</div>
</div> <h2 id="ARIandChannels:SimpleMediaManipulation-Python" style="margin: 10px 0 0 0; font-size: 20px; font-weight: normal; line-height: 30px; margin: 40px 0 0 0">Python</h2> <p style="margin: 10px 0 0 0">This example will use a very similar structure as the <a href="https://wiki.asterisk.org/wiki/display/%7Emjordan/Draft%3A+ARI+Channels%3A+Channel+State#Draft:ARIChannels:ChannelState-channel-state.py" rel="nofollow" style="color: #3b73af; text-decoration: none"><code style="font-family: monospace">channel-state.py</code></a> example. Instead of performing a <code style="font-family: monospace">ring</code> operation in our <code style="font-family: monospace">StasisStart</code> handler, we'll instead initiate a playback using the <code style="font-family: monospace">playWithId</code> operation on the channel. Note that our URI uses the <code style="font-family: monospace">tone</code> scheme, which supports an optional <code style="font-family: monospace">tonezone</code> parameter. We specify our <code style="font-family: monospace">tonezone</code> as <code style="font-family: monospace">fr</code>, so that we get an elegant French ringing tone. Much like the <code style="font-family: monospace">channel-state.py</code> example, we then use a Python timer to schedule a callback that will answer the channel. Since we care about both the <code style="font-family: monospace">channel</code> and the <code style="font-family: monospace">playback</code> initiated on it, we pass both parameters as <code style="font-family: monospace">*args</code> parameters to the callback function.</p>
<div class="code panel pdl" style="border-width: 1px;">
<div class="codeContent panelContent pdl">
<pre class="first-line: 46; theme: Confluence; brush: py; gutter: true" style="font-size:12px;; margin: 10px 0 0 0; margin-top: 0"> playback_id = str(uuid.uuid4())
playback = channel.playWithId(playbackId=playback_id,
media='tone:ring;tonezone=fr')
timer = threading.Timer(8, answer_channel, [channel, playback])
</pre>
</div>
</div> <p style="margin: 10px 0 0 0">Since this is a media operation and not <em>technically</em> a ringing indication, when we <code style="font-family: monospace">answer</code> the channel, the tone playback will not stop! To stop playing back our French ringing tone, we issue a <code style="font-family: monospace">stop</code> operation on the <code style="font-family: monospace">playback</code> object. This actually maps to a <a href="https://wiki.asterisk.org/wiki/display/AST/Asterisk+12+Playbacks+REST+API#Asterisk12PlaybacksRESTAPI-stop" rel="nofollow" style="color: #3b73af; text-decoration: none"><code style="font-family: monospace">DELETE /playbacks/{playback_id}</code></a> operation.</p>
<div class="code panel pdl" style="border-width: 1px;">
<div class="codeContent panelContent pdl">
<pre class="first-line: 26; theme: Confluence; brush: py; gutter: true" style="font-size:12px;; margin: 10px 0 0 0; margin-top: 0"> def answer_channel(channel, playback):
"""Callback that will actually answer the channel"""
print "Answering channel %s" % channel.json.get('name')
playback.stop()
channel.answer()</pre>
</div>
</div> <p style="margin: 10px 0 0 0">Once answered, we'll schedule another Python timer that will do the actual hanging up of the channel.</p> <h3 id="ARIandChannels:SimpleMediaManipulation-channel-tones.py" style="margin: 10px 0 0 0; font-size: 16px; line-height: 25px; margin: 30px 0 0 0">channel-tones.py</h3> <p style="margin: 10px 0 0 0">The full source code for <code style="font-family: monospace">channel-tones.py</code> is shown below:</p>
<div class="code panel pdl" style="border-width: 1px;">
<div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;">
<b>channel-tones.py</b>
</div>
<div class="codeContent panelContent pdl">
<pre class="theme: Confluence; brush: py; gutter: true" style="font-size:12px;; margin: 10px 0 0 0; margin-top: 0">#!/usr/bin/env python
import ari
import logging
import threading
import uuid
logging.basicConfig(level=logging.ERROR)
client = ari.connect('http://localhost:8088', 'asterisk', 'asterisk')
channel_timers = {}
def stasis_end_cb(channel, ev):
"""Handler for StasisEnd event"""
print "Channel %s just left our application" % channel.json.get('name')
timer = channel_timers.get(channel.id)
if timer:
timer.cancel()
del channel_timers[channel.id]
def stasis_start_cb(channel_obj, ev):
"""Handler for StasisStart event"""
def answer_channel(channel, playback):
"""Callback that will actually answer the channel"""
print "Answering channel %s" % channel.json.get('name')
playback.stop()
channel.answer()
timer = threading.Timer(1, hangup_channel, [channel])
channel_timers[channel.id] = timer
timer.start()
def hangup_channel(channel):
"""Callback that will actually hangup the channel"""
print "Hanging up channel %s" % channel.json.get('name')
channel.hangup()
channel = channel_obj.get('channel')
print "Channel %s has entered the application" % channel.json.get('name')
playback_id = str(uuid.uuid4())
playback = channel.playWithId(playbackId=playback_id,
media='tone:ring;tonezone=fr')
timer = threading.Timer(8, answer_channel, [channel, playback])
channel_timers[channel.id] = timer
timer.start()
client.on_channel_event('StasisStart', stasis_start_cb)
client.on_channel_event('StasisEnd', stasis_end_cb)
client.run(apps='channel-tones')
</pre>
</div>
</div> <h3 id="ARIandChannels:SimpleMediaManipulation-channel-tones.pyinaction" style="margin: 10px 0 0 0; font-size: 16px; line-height: 25px; margin: 30px 0 0 0">channel-tones.py in action</h3> <p style="margin: 10px 0 0 0">The following shows the output of the <code style="font-family: monospace">channel-tones.js</code> script when a <code style="font-family: monospace">PJSIP</code> channel for <code style="font-family: monospace">alice</code> enters the application:</p>
<div class="code panel pdl" style="border-width: 1px;">
<div class="codeContent panelContent pdl">
<pre class="theme: Confluence; brush: java; gutter: false" style="font-size:12px;; margin: 10px 0 0 0; margin-top: 0">Channel PJSIP/alice-00000000 has entered the application
Answering channel PJSIP/alice-00000000
Hanging up channel PJSIP/alice-00000000
Channel PJSIP/alice-00000000 just left our application</pre>
</div>
</div> <h2 id="ARIandChannels:SimpleMediaManipulation-JavaScript(Node.js)" style="margin: 10px 0 0 0; font-size: 20px; font-weight: normal; line-height: 30px; margin: 40px 0 0 0">JavaScript (Node.js)</h2> <p style="margin: 10px 0 0 0">This example will use a very similar structure as the <span class="confluence-link"><code style="font-family: monospace"><span class="confluence-link"><span class="confluence-link"><a href="https://wiki.asterisk.org/wiki/display/%7Emjordan/Draft%3A+ARI+Channels%3A+Channel+State#Draft:ARIChannels:ChannelState-channel-state.js" rel="nofollow" style="color: #3b73af; text-decoration: none">channel-state.js</a></span></span></code></span> example. Instead of performing a <code style="font-family: monospace">ring</code> operation in our <code style="font-family: monospace">StasisStart</code> handler, we'll instead initiate a playback using the <code style="font-family: monospace">play</code> operation on the channel. Note that our URI uses the <code style="font-family: monospace">tone</code> scheme, which supports an optional <code style="font-family: monospace">tonezone</code> parameter. We specify our <code style="font-family: monospace">tonezone</code> as <code style="font-family: monospace">fr</code>, so that we get an elegant French ringing tone. Much like the <code style="font-family: monospace">channel-state.js</code> example, we then use a JavaScript timeout to schedule a callback that will answer the channel.</p>
<div class="code panel pdl" style="border-width: 1px;">
<div class="codeContent panelContent pdl">
<pre class="first-line: 21; theme: Confluence; brush: js; gutter: true" style="font-size:12px;; margin: 10px 0 0 0; margin-top: 0">var playback = client.Playback();
channel.play({media: 'tone:ring;tonezone=fr'},
playback, function(err, newPlayback) {
if (err) {
throw err;
}
});
// answer the channel after 8 seconds
var timer = setTimeout(answer, 8000);
timers[channel.id] = timer;
</pre>
</div>
</div> <p style="margin: 10px 0 0 0">Since this is a media operation and not <em>technically</em> a ringing indication, when we <code style="font-family: monospace">answer</code> the channel, the tone playback will not stop! To stop playing back our French ringing tone, we issue a <code style="font-family: monospace">stop</code> operation on the <code style="font-family: monospace">playback</code> object. This actually maps to a <a href="https://wiki.asterisk.org/wiki/display/AST/Asterisk+12+Playbacks+REST+API#Asterisk12PlaybacksRESTAPI-stop" rel="nofollow" style="color: #3b73af; text-decoration: none"><code style="font-family: monospace">DELETE /playbacks/{playback_id}</code></a> operation. Notice that we use the fact that the answer callback closes on the original channel and playback variables to access them from the callback.</p>
<div class="code panel pdl" style="border-width: 1px;">
<div class="codeContent panelContent pdl">
<pre class="first-line: 33; theme: Confluence; brush: js; gutter: true" style="font-size:12px;; margin: 10px 0 0 0; margin-top: 0">function answer() {
console.log(util.format('Answering channel %s', channel.name));
playback.stop(function(err) {
if (err) {
throw err;
}
});
channel.answer(function(err) {
if (err) {
throw err;
}
});
// hang up the channel in 1 seconds
var timer = setTimeout(hangup, 1000);
timers[channel.id] = timer;
}</pre>
</div>
</div> <p style="margin: 10px 0 0 0">Once answered, we'll schedule another timeout that will do the actual hanging up of the channel.</p> <h3 id="ARIandChannels:SimpleMediaManipulation-channel-tones.js" style="margin: 10px 0 0 0; font-size: 16px; line-height: 25px; margin: 30px 0 0 0">channel-tones.js</h3> <p style="margin: 10px 0 0 0"> <span class="confluence-anchor-link" id="ARIandChannels:SimpleMediaManipulation-channel-tones.js"></span> </p> <p style="margin: 10px 0 0 0">The full source code for <code style="font-family: monospace">channel-tones.js</code> is shown below:</p>
<div class="code panel pdl" style="border-width: 1px;">
<div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;">
<b>channel-tones.js</b>
</div>
<div class="codeContent panelContent pdl">
<pre class="theme: Confluence; brush: js; gutter: true" style="font-size:12px;; margin: 10px 0 0 0; margin-top: 0">/*jshint node: true*/
'use strict';
var ari = require('ari-client');
var util = require('util');
var timers = {};
ari.connect('http://localhost:8088', 'asterisk', 'asterisk', clientLoaded);
// handler for client being loaded
function clientLoaded (err, client) {
if (err) {
throw err;
}
// handler for StasisStart event
function stasisStart(event, channel) {
console.log(util.format(
'Channel %s has entered the application', channel.name));
var playback = client.Playback();
channel.play({media: 'tone:ring;tonezone=fr'},
playback, function(err, newPlayback) {
if (err) {
throw err;
}
});
// answer the channel after 8 seconds
var timer = setTimeout(answer, 8000);
timers[channel.id] = timer;
// callback that will answer the channel
function answer() {
console.log(util.format('Answering channel %s', channel.name));
playback.stop(function(err) {
if (err) {
throw err;
}
});
channel.answer(function(err) {
if (err) {
throw err;
}
});
// hang up the channel in 1 seconds
var timer = setTimeout(hangup, 1000);
timers[channel.id] = timer;
}
// callback that will hangup the channel
function hangup() {
console.log(util.format('Hanging up channel %s', channel.name));
channel.hangup(function(err) {
if (err) {
throw err;
}
});
}
}
// handler for StasisEnd event
function stasisEnd(event, channel) {
console.log(util.format(
'Channel %s just left our application', channel.name));
var timer = timers[channel.id];
if (timer) {
clearTimeout(timer);
delete timers[channel.id];
}
}
client.on('StasisStart', stasisStart);
client.on('StasisEnd', stasisEnd);
client.start('channel-tones');
} </pre>
</div>
</div> <h3 id="ARIandChannels:SimpleMediaManipulation-channel-tones.jsinaction" style="margin: 10px 0 0 0; font-size: 16px; line-height: 25px; margin: 30px 0 0 0">channel-tones.js in action</h3> <p style="margin: 10px 0 0 0">The following shows the output of the <code style="font-family: monospace">channel-tones.js</code> script when a <code style="font-family: monospace">PJSIP</code> channel for <code style="font-family: monospace">alice</code> enters the application:</p> <pre style="margin: 10px 0 0 0">Channel PJSIP/alice-00000000 has entered the application
Answering channel PJSIP/alice-00000000
Hanging up channel PJSIP/alice-00000000
Channel PJSIP/alice-00000000 just left our application</pre> <h1 id="ARIandChannels:SimpleMediaManipulation-Example:Playingbackasoundfile" style="margin: 10px 0 0 0; font-size: 24px; font-weight: normal; line-height: 30px; margin: 40px 0 0 0">Example: Playing back a sound file</h1> <p style="margin: 10px 0 0 0">This example ARI application will do the following:</p>
<ol style="margin: 10px 0 0 0">
<li>When a channel enters the Stasis application, initiate a playback of howler monkeys on the channel. Fly my pretties, FLY!</li>
<li>If the user has not hung up their phone in panic, it will hang up the channel when the howler monkeys return victorious - or rather, when ARI notifies the application that the playback has finished via the <a href="https://wiki.asterisk.org/wiki/display/AST/Asterisk+12+REST+Data+Models#Asterisk12RESTDataModels-PlaybackFinished" rel="nofollow" style="color: #3b73af; text-decoration: none"><code style="font-family: monospace">PlaybackFinished</code></a> event.</li>
</ol> <h2 id="ARIandChannels:SimpleMediaManipulation-Dialplan.1" style="margin: 10px 0 0 0; font-size: 20px; font-weight: normal; line-height: 30px; margin: 40px 0 0 0">Dialplan</h2> <p style="margin: 10px 0 0 0">For this example, we need to just drop the channel into Stasis, specifying our application:</p>
<div class="code panel pdl" style="border-width: 1px;">
<div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;">
<b>extensions.conf</b>
</div>
<div class="codeContent panelContent pdl">
<pre class="theme: Confluence; brush: text; gutter: true" style="font-size:12px;; margin: 10px 0 0 0; margin-top: 0">exten => 1000,1,NoOp()
same => n,Stasis(channel-playback-monkeys)
same => n,Hangup() </pre>
</div>
</div> <h2 id="ARIandChannels:SimpleMediaManipulation-Python.1" style="margin: 10px 0 0 0; font-size: 20px; font-weight: normal; line-height: 30px; margin: 40px 0 0 0">Python</h2> <p style="margin: 10px 0 0 0">Much like the <code style="font-family: monospace"><a href="https://wiki.asterisk.org/wiki/display/%7Emjordan/Draft%3A+ARI+Channels%3A+Performing+a+simple+playback+of+media#Draft:ARIChannels:Performingasimpleplaybackofmedia-channel-tones.py" rel="nofollow" style="color: #3b73af; text-decoration: none">channel-tones.py</a></code> example, we'll start off by initiating a playback on the channel. Instead of specifying a <code style="font-family: monospace">tone</code> scheme, however, we'll specify a scheme of <code style="font-family: monospace">sound</code> with a resource of <code style="font-family: monospace">tt-monkeys</code>. Unlike the tones, this media <em>does</em> have a well defined ending - the end of the sound file! So we'll subscribe for the <code style="font-family: monospace">PlaybackFinished</code> event and tell <code style="font-family: monospace">ari-py</code> to call <code style="font-family: monospace">playback_finished</code> when our monkeys are done attacking.</p>
<div class="code panel pdl" style="border-width: 1px;">
<div class="codeContent panelContent pdl">
<pre class="first-line: 32; theme: Confluence; brush: py; gutter: true" style="font-size:12px;; margin: 10px 0 0 0; margin-top: 0"> playback_id = str(uuid.uuid4())
playback = channel.playWithId(playbackId=playback_id,
media='sound:tt-monkeys')
playback.on_event('PlaybackFinished', playback_finished)</pre>
</div>
</div> <p style="margin: 10px 0 0 0">Unfortunately, <code style="font-family: monospace">ari-py</code> doesn't let us pass arbitrary data to a callback function in the same fashion as a Python timer. Nuts. Luckily, the <code style="font-family: monospace">Playback</code> object has a property, <code style="font-family: monospace">target_uri</code>, that tells us which object it just finished playing to. Using that, we can get the <code style="font-family: monospace">channel</code> object back from Asterisk so we can hang it up.</p>
<div class="code panel pdl" style="border-width: 1px;">
<div class="codeContent panelContent pdl">
<pre class="first-line: 19; theme: Confluence; brush: py; gutter: true" style="font-size:12px;; margin: 10px 0 0 0; margin-top: 0"> def playback_finished(playback, ev):
"""Callback when the monkeys have finished howling"""
target_uri = playback.json.get('target_uri')
channel_id = target_uri.replace('channel:', '')
channel = client.channels.get(channelId=channel_id)
print "Monkeys successfully vanquished %s; hanging them up" % channel.json.get('name')
channel.hangup() </pre>
</div>
</div> <p style="margin: 10px 0 0 0">Note that unlike the <code style="font-family: monospace">channel-tones.py</code> example, this application eschews the use of Python timers and simply responds to ARI events as they happen. This means we don't have to do much in our <code style="font-family: monospace">StasisEnd</code> event, and we have to track less state.</p> <h3 id="ARIandChannels:SimpleMediaManipulation-channel-playback-monkeys.py" style="margin: 10px 0 0 0; font-size: 16px; line-height: 25px; margin: 30px 0 0 0">channel-playback-monkeys.py</h3> <p style="margin: 10px 0 0 0">The full source code for <code style="font-family: monospace">channel-playback-monkeys.py</code> is shown below:</p>
<div class="code panel pdl" style="border-width: 1px;">
<div class="codeContent panelContent pdl">
<pre class="theme: Confluence; brush: py; gutter: true" style="font-size:12px;; margin: 10px 0 0 0; margin-top: 0"> #!/usr/bin/env python
import ari
import logging
import uuid
logging.basicConfig(level=logging.ERROR)
client = ari.connect('http://localhost:8088', 'asterisk', 'asterisk')
def stasis_end_cb(channel, ev):
"""Handler for StasisEnd event"""
print "Channel %s just left our application" % channel.json.get('name')
def stasis_start_cb(channel_obj, ev):
"""Handler for StasisStart event"""
def playback_finished(playback, ev):
"""Callback when the monkeys have finished howling"""
target_uri = playback.json.get('target_uri')
channel_id = target_uri.replace('channel:', '')
channel = client.channels.get(channelId=channel_id)
print "Monkeys successfully vanquished %s; hanging them up" % channel.json.get('name')
channel.hangup()
channel = channel_obj.get('channel')
print "Monkeys! Attack %s!" % channel.json.get('name')
playback_id = str(uuid.uuid4())
playback = channel.playWithId(playbackId=playback_id,
media='sound:tt-monkeys')
playback.on_event('PlaybackFinished', playback_finished)
client.on_channel_event('StasisStart', stasis_start_cb)
client.on_channel_event('StasisEnd', stasis_end_cb)
client.run(apps='channel-playback-monkeys')
</pre>
</div>
</div> <h3 id="ARIandChannels:SimpleMediaManipulation-channel-playback-monkeys.pyinaction" style="margin: 10px 0 0 0; font-size: 16px; line-height: 25px; margin: 30px 0 0 0">channel-playback-monkeys.py in action</h3> <p style="margin: 10px 0 0 0">The following shows the output of the <code style="font-family: monospace">channel-playback-monkeys</code>.py script when a <code style="font-family: monospace">PJSIP</code> channel for <code style="font-family: monospace">alice</code> enters the application:</p>
<div class="code panel pdl" style="border-width: 1px;">
<div class="codeContent panelContent pdl">
<pre class="theme: Confluence; brush: java; gutter: false" style="font-size:12px;; margin: 10px 0 0 0; margin-top: 0">Monkeys! Attack PJSIP/alice-00000000!
Monkeys successfully vanquished PJSIP/alice-00000000; hanging them up
Channel PJSIP/alice-00000000 just left our application</pre>
</div>
</div> <h2 id="ARIandChannels:SimpleMediaManipulation-JavaScript(Node.js).1" style="margin: 10px 0 0 0; font-size: 20px; font-weight: normal; line-height: 30px; margin: 40px 0 0 0">JavaScript (Node.js)</h2> <p style="margin: 10px 0 0 0">Much like the <code style="font-family: monospace"><span class="confluence-link"><a href="#ARIandChannels:SimpleMediaManipulation-channel-tones.js" style="color: #3b73af; text-decoration: none">channel-tones.js</a></span></code> example, we'll start off by initiating a playback on the channel. Instead of specifying a <code style="font-family: monospace">tone</code> scheme, however, we'll specify a scheme of <code style="font-family: monospace">sound</code> with a resource of <code style="font-family: monospace">tt-monkeys</code>. Unlike the tones, this media <em>does</em> have a well defined ending - the end of the sound file! So we'll subscribe for the <code style="font-family: monospace">PlaybackFinished</code> event and tell <code style="font-family: monospace">ari-client</code> to call <code style="font-family: monospace">playbackFinished</code> when our monkeys are done attacking. Notice that we use <code style="font-family: monospace">client.Playback()</code> to generate a playback object with a pre-existing Id so we can scope the PlaybackFinished event to the playback we just created.</p>
<div class="code panel pdl" style="border-width: 1px;">
<div class="codeContent panelContent pdl">
<pre class="first-line: 20; theme: Confluence; brush: js; gutter: true" style="font-size:12px;; margin: 10px 0 0 0; margin-top: 0">var playback = client.Playback();
channel.play({media: 'sound:tt-monkeys'},
playback, function(err, newPlayback) {
if (err) {
throw err;
}
});
playback.on('PlaybackFinished', playbackFinished);</pre>
</div>
</div> <p style="margin: 10px 0 0 0">Notice that we use the fact that the playbackFinished callback closes over the original channel variable to perform a hangup operation using that object directly.</p>
<div class="code panel pdl" style="border-width: 1px;">
<div class="codeContent panelContent pdl">
<pre class="first-line: 29; theme: Confluence; brush: js; gutter: true" style="font-size:12px;; margin: 10px 0 0 0; margin-top: 0">function playbackFinished(event, completedPlayback) {
console.log(util.format(
'Monkeys successfully vanquished %s; hanging them up',
channel.name));
channel.hangup(function(err) {
if (err) {
throw err;
}
});
}</pre>
</div>
</div> <p style="margin: 10px 0 0 0">Note that unlike the <code style="font-family: monospace">channel-tones.js</code> example, this application eschews the use of JavaScript timeouts and simply responds to ARI events as they happen. This means we don't have to do much in our <code style="font-family: monospace">StasisEnd</code> event, and we have to track less state.</p> <h3 id="ARIandChannels:SimpleMediaManipulation-channel-playback-monkeys.js" style="margin: 10px 0 0 0; font-size: 16px; line-height: 25px; margin: 30px 0 0 0">channel-playback-monkeys.js</h3> <p style="margin: 10px 0 0 0">The full source code for <code style="font-family: monospace">channel-playback-monkeys.js</code> is shown below:</p>
<div class="code panel pdl" style="border-width: 1px;">
<div class="codeContent panelContent pdl">
<pre class="theme: Confluence; brush: js; gutter: true" style="font-size:12px;; margin: 10px 0 0 0; margin-top: 0">/*jshint node: true*/
'use strict';
var ari = require('ari-client');
var util = require('util');
ari.connect('http://localhost:8088', 'asterisk', 'asterisk', clientLoaded);
// handler for client being loaded
function clientLoaded (err, client) {
if (err) {
throw err;
}
// handler for StasisStart event
function stasisStart(event, channel) {
console.log(util.format(
'Monkeys! Attack %s!', channel.name));
var playback = client.Playback();
channel.play({media: 'sound:tt-monkeys'},
playback, function(err, newPlayback) {
if (err) {
throw err;
}
});
playback.on('PlaybackFinished', playbackFinished);
function playbackFinished(event, completedPlayback) {
console.log(util.format(
'Monkeys successfully vanquished %s; hanging them up',
channel.name));
channel.hangup(function(err) {
if (err) {
throw err;
}
});
}
}
// handler for StasisEnd event
function stasisEnd(event, channel) {
console.log(util.format(
'Channel %s just left our application', channel.name));
}
client.on('StasisStart', stasisStart);
client.on('StasisEnd', stasisEnd);
client.start('channel-playback-monkeys');
}
</pre>
</div>
</div> <h3 id="ARIandChannels:SimpleMediaManipulation-channel-playback-monkeys.jsinaction" style="margin: 10px 0 0 0; font-size: 16px; line-height: 25px; margin: 30px 0 0 0">channel-playback-monkeys.js in action</h3> <p style="margin: 10px 0 0 0">The following shows the output of the <code style="font-family: monospace">channel-playback-monkeys</code>.js script when a <code style="font-family: monospace">PJSIP</code> channel for <code style="font-family: monospace">alice</code> enters the application:</p>
<div class="code panel pdl" style="border-width: 1px;">
<div class="codeContent panelContent pdl">
<pre class="theme: Confluence; brush: java; gutter: false" style="font-size:12px;; margin: 10px 0 0 0; margin-top: 0">Monkeys! Attack PJSIP/alice-00000000!
Monkeys successfully vanquished PJSIP/alice-00000000; hanging them up
Channel PJSIP/alice-00000000 just left our application</pre>
</div>
</div> </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/ARI+and+Channels%3A+Simple+Media+Manipulation?src=email" title="View page" style="color: #3b73af; text-decoration: none"><img class="actions-pattern-action-icon-image" src="cid:confluence.mail.templates.view.page" alt="View page-icon" title="View page-icon" height="16" width="16" border="0" 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/ARI+and+Channels%3A+Simple+Media+Manipulation?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/ARI+and+Channels%3A+Simple+Media+Manipulation?showComments=true&showCommentArea=true#addcomment" title="Add comment" style="color: #3b73af; text-decoration: none"><img class="actions-pattern-action-icon-image" src="cid:confluence.mail.templates.add.comment" alt="Add comment-icon" title="Add comment-icon" height="16" width="16" border="0" 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/ARI+and+Channels%3A+Simple+Media+Manipulation?showComments=true&showCommentArea=true#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=29395606&src=email" title="Like" style="color: #3b73af; text-decoration: none"><img class="actions-pattern-action-icon-image" src="cid:likes.like" alt="Like-icon" title="Like-icon" height="16" width="16" border="0" 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=29395606&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.4.3</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>