<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/~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/pages/viewpage.action?pageId=29396202&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/pages/viewpage.action?pageId=29396202&src=email" title="MEDIA? MORE LIKE MEDI-DUH!" style="color: #3b73af; text-decoration: none">MEDIA? MORE LIKE MEDI-DUH!</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"> <p class="diff-context-placeholder" style="margin: 10px 0 0 0; margin-top: 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-1988229788/4732/f543bd9a3bbc12daed85f6f5e5cba84282599932.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-record.py</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">py</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">#!/usr/bin/env python
<span class="diff-html-added" id="added-diff-0" style="font-size: 100%; background-color: #ddfade;">
</span>import ari
import logging
<span class="diff-html-added" id="added-diff-1" style="font-size: 100%; background-color: #ddfade;">import</span> <span class="diff-html-added" id="added-diff-2" style="font-size: 100%; background-color: #ddfade;">time
import os
</span>logging.basicConfig(level=logging.ERROR)
LOGGER = logging.getLogger(__name__)
client = ari.connect('http://<span class="diff-html-removed" id="removed-diff-0" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">localhost</span><span class="diff-html-added" id="added-diff-3" style="font-size: 100%; background-color: #ddfade;">10.24.20.249</span>:8088', 'asterisk', 'asterisk')
<span class="diff-html-added" id="added-diff-4" style="font-size: 100%; background-color: #ddfade;">
</span>def recording_finished(recording, event, channel):
print("Recording of channel {0} completed".format(
channel.json.get('name')))
channel.hangup(<span class="diff-html-removed" id="removed-diff-1" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">channelId=channel.id</span>)
<span class="diff-html-added" id="added-diff-5" style="font-size: 100%; background-color: #ddfade;">
</span>
def stasis_start_cb(channel_obj, event):
channel = channel_obj['channel']
<span class="diff-html-added" id="added-diff-6" style="font-size: 100%; background-color: #ddfade;">channel_name = channel.json.get('name')
mailbox = event.get('args')[0]
path = os.path.join('voicemail', mailbox, str(time.time()))
</span>print("Channel {0} <span class="diff-html-removed" id="removed-diff-2" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">has</span><span class="diff-html-added" id="added-diff-7" style="font-size: 100%; background-color: #ddfade;">leaving</span> <span class="diff-html-removed" id="removed-diff-3" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">entered</span><span class="diff-html-added" id="added-diff-8" style="font-size: 100%; background-color: #ddfade;">voicemail</span> <span class="diff-html-removed" id="removed-diff-4" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">the</span><span class="diff-html-added" id="added-diff-9" style="font-size: 100%; background-color: #ddfade;">for</span> <span class="diff-html-removed" id="removed-diff-5" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">application</span><span class="diff-html-added" id="added-diff-10" style="font-size: 100%; background-color: #ddfade;">{1}</span>".format(<span class="diff-html-added" id="added-diff-11" style="font-size: 100%; background-color: #ddfade;">channel_name,</span> <span class="diff-html-added" id="added-diff-12" style="font-size: 100%; background-color: #ddfade;">mailbox))</span>
<span class="diff-html-added" id="added-diff-13" style="font-size: 100%; background-color: #ddfade;">channel.answer()</span>
<span class="diff-html-removed" id="removed-diff-6" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">channel.json.get('name')))
channel.answer()
recording = channel.record(channelId=channel.id,
</span><span class="diff-html-added" id="added-diff-14" style="font-size: 100%; background-color: #ddfade;"> recording = channel.record(name=path, format='wav', beep=True,
terminateOn='#', ifExists='overwrite')
recording.on_event('RecordingFinished', recording_finished, channel)
client.on_channel_event('StasisStart', stasis_start_cb)
client.run(apps='record-voicemail')</span>
</pre> </td>
</tr>
</tbody>
</table> <h3 id="MEDIA?MORELIKEMEDI-DUH!-Javascript.1" class="diff-block-target diff-block-context" style="margin: 10px 0 0 0; font-size: 16px; line-height: 25px; margin: 30px 0 0 0"> <span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">Javascript</span> </h3>
<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-1988229788/4732/f543bd9a3bbc12daed85f6f5e5cba84282599932.48/_/plugins/servlet/confluence/placeholder/macro-icon?name=code" style="padding-right: 5px; vertical-align: text-bottom;" /> </span>Code Block</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;">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;">vm-record.js</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;">language</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;">js</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;">collapse</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;">true</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"> <pre style="margin: 10px 0 0 0; margin-top: 0">
<span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;"> /*jshint node:true*/
'use strict';
var ari = require('ari-client');
var util = require('util');
var path = require('path');
ari.connect('http://10.24.20.249:8088', 'asterisk', 'asterisk', clientLoaded);
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;
}
startRecording(channel, mailbox);
});
}
function startRecording(channel, mailbox) {
var vm_path = path.join('voicemail/', mailbox, Date.now().toString());
console.log("Channel %s leaving voicemail for %s", channel.name, mailbox);
client.once('RecordingFinished', recordingFinished);
channel.record({name: vm_path, format: 'wav', beep: true, terminateOn: '#'}, function(err, recording) {</span>
<span class="diff-html-added" id="added-diff-15" style="font-size: 100%; background-color: #ddfade;">if</span> <span class="diff-html-added" id="added-diff-16" style="font-size: 100%; background-color: #ddfade;">(err)</span> <span class="diff-html-added" id="added-diff-17" style="font-size: 100%; background-color: #ddfade;">{</span>
<span class="diff-html-removed" id="removed-diff-7" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">name='voicemail/{0}/{1}'.format(channel.json.get('caller').get('number'),
</span><span class="diff-html-added" id="added-diff-18" style="font-size: 100%; background-color: #ddfade;"> throw err;
}
});
function recordingFinished(event, recording) {
console.log("Recording of channel %s completed", channel.name);
channel.hangup();
}
}
client.start('record-voicemail');
}
</span>
</pre> </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;">Each of these scripts starts a Stasis application called </span><code style="font-family: monospace"><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">record-voicemail</span></code><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;"> that takes a single argument, a mailbox into which to record a voicemail. The scripts use this mailbox number to help determine the path on the file system where the recording will reside. Since this is a bare-bones voicemail application, there are no such things as "folders" for voicemail boxes. The path the scripts construct is relative to the folder where recordings are stored and is constructed as "voicemail/{mailbox}/{timestamp}". The use of a timestamp serves as a cheap way to order voicemails by recording time and saves our scripts from having to keep track of how many voicemails exist in each mailbox.</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-1988229788/4732/f543bd9a3bbc12daed85f6f5e5cba84282599932.48/_/images/icons/macrobrowser/dropdown/note.png" style="padding-right: 5px; vertical-align: text-bottom;" /> </span>Note</span></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"> <p style="margin: 10px 0 0 0; margin-top: 0"> <span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">Though the Python and Node.js scripts perform the exact same tasks, it is not recommended to switch between the two at will. This is because Javascript and Python represent Unix timestamps differently: Javascript returns an integer count of milliseconds since the epoch, and Python returns a floating point number representing the seconds and fractions of a second since the epoch. As such, mixing files between these two could cause lexicographical sorting anomalies if you are trying to let the file system sort the recordings by date.</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;">Within Asterisk, the </span><code style="font-family: monospace"><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">record-voicemail</span></code><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;"> application can be invoked however is desired. I set up the following simple extension in my dialplan:</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-1988229788/4732/f543bd9a3bbc12daed85f6f5e5cba84282599932.48/_/images/icons/macrobrowser/dropdown/noformat.png" style="padding-right: 5px; vertical-align: text-bottom;" /> </span>No Format</span></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"> <pre style="margin: 10px 0 0 0; margin-top: 0">
<span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">[default]
exten => _3XX,1,Stasis(record-voicemail, ${EXTEN});</span>
</pre> </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;">This allows for mailboxes 300-399 to exist on the system. Whatever extension is dialed by the user is the mailbox in which the mailbox is stored. Since I use the default </span><code style="font-family: monospace"><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">astspooldir</span></code><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;"> on my system, this means that if I were to dial 305, the voicemail I leave will be stored at, for extample </span><code style="font-family: monospace"><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">/var/spool/asterisk/recording/voicemail/305/1410806204299.wav</span></code><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">.</span> </p> <h2 id="MEDIA?MORELIKEMEDI-DUH!-LiveRecordings" class="diff-block-target diff-block-context" style="margin: 10px 0 0 0; font-size: 20px; font-weight: normal; line-height: 30px; margin: 40px 0 0 0"> <span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">Live Recordings</span> </h2> <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;">In addition to the simple act of recording, ARI also provides the capability to manipulate stored and live recordings via the </span><code style="font-family: monospace"><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">/recordings</span></code><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;"> resource, documented </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;">here</span></a><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">. The following code samples build on the previous samples to allow a user to cancel their current live recording and re-record their message. This makes use of DTMF interception techniques that were introduced on this </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;">page</span></a><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">. When the user presses the '*' key, the current recording is discarded and the user is re-prompted to record their message.</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-1988229788/4732/f543bd9a3bbc12daed85f6f5e5cba84282599932.48/_/plugins/servlet/confluence/placeholder/macro-icon?name=code" style="padding-right: 5px; vertical-align: text-bottom;" /> </span>Code Block</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;">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;">vm-record-retry.py</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;">language</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;">py</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;">collapse</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;">true</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"> <pre style="margin: 10px 0 0 0; margin-top: 0">
<span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">#!/usr/bin/env python
import ari
import logging
import time
import os
logging.basicConfig(level=logging.ERROR)
LOGGER = logging.getLogger(__name__)
client = ari.connect('http://localhost:8088', 'asterisk', 'asterisk')
global DTMF_EVENT
def on_dtmf(channel, event, recording, mailbox):
global DTMF_EVENT
digit = event.get('digit')
if digit == '*':</span>
<span class="diff-html-added" id="added-diff-19" style="font-size: 100%; background-color: #ddfade;">print("Canceling</span> <span class="diff-html-added" id="added-diff-20" style="font-size: 100%; background-color: #ddfade;">recording</span> <span class="diff-html-added" id="added-diff-21" style="font-size: 100%; background-color: #ddfade;">{0}".format(recording.json.get('name')))</span>
<span class="diff-html-added" id="added-diff-22" style="font-size: 100%; background-color: #ddfade;">recording.cancel()</span>
<span class="diff-html-added" id="added-diff-23" style="font-size: 100%; background-color: #ddfade;">DTMF_EVENT.close()</span>
<span class="diff-html-added" id="added-diff-24" style="font-size: 100%; background-color: #ddfade;">start_recording(channel,</span> <span class="diff-html-added" id="added-diff-25" style="font-size: 100%; background-color: #ddfade;">mailbox)</span>
<span class="diff-html-added" id="added-diff-26" style="font-size: 100%; background-color: #ddfade;">if</span> <span class="diff-html-added" id="added-diff-27" style="font-size: 100%; background-color: #ddfade;">digit</span> <span class="diff-html-added" id="added-diff-28" style="font-size: 100%; background-color: #ddfade;">==</span> <span class="diff-html-added" id="added-diff-29" style="font-size: 100%; background-color: #ddfade;">'#':</span>
<span class="diff-html-removed" id="removed-diff-8" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">time.time()),</span><span class="diff-html-added" id="added-diff-30" style="font-size: 100%; background-color: #ddfade;">print("Stopping recording {0}".format(recording.json.get('name')))</span>
<span class="diff-html-added" id="added-diff-31" style="font-size: 100%; background-color: #ddfade;">recording.stop()</span>
<span class="diff-html-added" id="added-diff-32" style="font-size: 100%; background-color: #ddfade;">DTMF_EVENT.close()</span>
<span class="diff-html-added" id="added-diff-33" style="font-size: 100%; background-color: #ddfade;">channel.hangup()</span>
<span class="diff-html-added" id="added-diff-34" style="font-size: 100%; background-color: #ddfade;"> </span>
<span class="diff-html-added" id="added-diff-35" style="font-size: 100%; background-color: #ddfade;">def</span> <span class="diff-html-added" id="added-diff-36" style="font-size: 100%; background-color: #ddfade;">start_recording(channel,</span> <span class="diff-html-removed" id="removed-diff-9" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;"> format='wav', beep=True, terminateOn='#',
</span><span class="diff-html-added" id="added-diff-37" style="font-size: 100%; background-color: #ddfade;">mailbox):
global DTMF_EVENT
path = os.path.join('voicemail', mailbox, str(time.time()))
recording = channel.record(name=path, format='wav', beep=True,</span>
<span class="diff-html-added" id="added-diff-38" style="font-size: 100%; background-color: #ddfade;"> </span>ifExists='overwrite')
<span class="diff-html-removed" id="removed-diff-10" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">recording.</span><span class="diff-html-added" id="added-diff-39" style="font-size: 100%; background-color: #ddfade;">print("Recording voicemail at {0}".format(path))
DTMF_EVENT = channel.</span>on_event('<span class="diff-html-removed" id="removed-diff-11" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">RecordingFinished</span><span class="diff-html-added" id="added-diff-40" style="font-size: 100%; background-color: #ddfade;">ChannelDtmfReceived</span>', <span class="diff-html-added" id="added-diff-41" style="font-size: 100%; background-color: #ddfade;">on_dtmf, </span>recording<span class="diff-html-removed" id="removed-diff-12" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">_finished, channel)
</span><span class="diff-html-added" id="added-diff-42" style="font-size: 100%; background-color: #ddfade;">, mailbox)
def stasis_start_cb(channel_obj, event):
channel = channel_obj['channel']
channel_name = channel.json.get('name')
mailbox = event.get('args')[0]
print("Channel {0} recording voicemail for {1}".format(
channel_name, mailbox))
channel.answer()
start_recording(channel, mailbox)
</span>client.on_channel_event('StasisStart', stasis_start_cb)
client.run(apps='record-voicemail')
</pre> </td>
</tr>
</tbody>
</table> <h3 id="MEDIA?MORELIKEMEDI-DUH!-Javascript.1" class="diff-block-target diff-block-context" style="margin: 10px 0 0 0; font-size: 16px; line-height: 25px; margin: 30px 0 0 0"> <span class="diff-html-removed" id="removed-diff-13" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">Javascript</span> </h3> <span class="diff-html-removed" id="removed-diff-14" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;"> </span>
<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-1988229788/4732/f543bd9a3bbc12daed85f6f5e5cba84282599932.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"><span class="diff-html-added" id="added-diff-43" 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;">vm-record-retry.js</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;">language</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;">js</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;">collapse</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;">true</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"> <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');
ari.connect('http://<span class="diff-html-removed" id="removed-diff-15" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">10.24.20.249</span><span class="diff-html-added" id="added-diff-44" style="font-size: 100%; background-color: #ddfade;">localhost</span>:8088', 'asterisk', 'asterisk', clientLoaded);
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;
}
startRecording(channel, mailbox);
});
}
function startRecording(channel, mailbox) {
var vm_path = path.join('voicemail/', mailbox, Date.now().toString());
console.log("Channel %s leaving voicemail for %s", channel.name, mailbox);
<span class="diff-html-removed" id="removed-diff-16" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">client.once('RecordingFinished', recordingFinished);
</span>channel.record({name: vm_path, format: 'wav', beep: true<span class="diff-html-removed" id="removed-diff-17" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">, terminateOn: '#'</span>}, function(err, recording) {
if (err) {
throw err;
}
<span class="diff-html-removed" id="removed-diff-18" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">})</span><span class="diff-html-added" id="added-diff-45" style="font-size: 100%; background-color: #ddfade;"> channel.on('ChannelDtmfReceived', function dtmfReceived(event, channel) {
var digit = event.digit</span>;
<span class="diff-html-removed" id="removed-diff-19" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">function recordingFinished(event, recording</span><span class="diff-html-added" id="added-diff-46" style="font-size: 100%; background-color: #ddfade;"> if (digit == '*'</span>) {
<span class="diff-html-added" id="added-diff-47" style="font-size: 100%; background-color: #ddfade;"> </span>console.log("<span class="diff-html-removed" id="removed-diff-20" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">Recording</span><span class="diff-html-added" id="added-diff-48" style="font-size: 100%; background-color: #ddfade;">Canceling</span> <span class="diff-html-removed" id="removed-diff-21" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">of channel %s completed", channel</span><span class="diff-html-added" id="added-diff-49" style="font-size: 100%; background-color: #ddfade;">recording", recording.name);
recording.cancel();
channel.removeListener('ChannelDtmfReceived', dtmfReceived);
startRecording(channel, mailbox);
} else if (digit == '#') {
console.log("Stopping recording", recording</span>.name);
<span class="diff-html-added" id="added-diff-50" style="font-size: 100%; background-color: #ddfade;"> recording.stop();
</span>channel.<span class="diff-html-added" id="added-diff-51" style="font-size: 100%; background-color: #ddfade;">removeListener('ChannelDtmfReceived', dtmfReceived);
channel.</span>hangup();
<span class="diff-html-added" id="added-diff-52" style="font-size: 100%; background-color: #ddfade;"> </span>}
<span class="diff-html-added" id="added-diff-53" style="font-size: 100%; background-color: #ddfade;"> </span>}<span class="diff-html-added" id="added-diff-54" style="font-size: 100%; background-color: #ddfade;">);</span>
<span class="diff-html-added" id="added-diff-55" style="font-size: 100%; background-color: #ddfade;"> });
}
</span>client.start('record-voicemail');
}
<span class="diff-html-removed" id="removed-diff-22" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">
</span>
</pre> </td>
</tr>
</tbody>
</table> <p class="diff-block-target diff-block-context" style="margin: 10px 0 0 0"> <span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">In case it isn't clear from the snippets. The above stores voice mails within the recordings directory in </span><code style="font-family: monospace"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">voicemail/{callerIDNumber}/{timestamp}</span></code><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">. For a real voicemail system, you'd want to store them based on mailbox IDs rather than caller ID number, but for the purpose of this toy system we are creating, the given scheme will suffice.</span> </p> <h2 id="MEDIA?MORELIKEMEDI-DUH!-LiveRecordings" class="diff-block-target diff-block-context" style="margin: 10px 0 0 0; font-size: 20px; font-weight: normal; line-height: 30px; margin: 40px 0 0 0"> <span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">Live Recordings</span> </h2> <p class="diff-block-target diff-block-context" style="margin: 10px 0 0 0"> <span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">In addition to the simple act of recording, ARI also provides the capability to manipulate stored and live recordings via the </span><code style="font-family: monospace"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">/recordings</span></code><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;"> resource. The following commands are available for stored recordings:</span> </p>
<div class="table-wrap diff-block-target diff-block-context" 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>
<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"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">Method</span></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"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">Description</span></th>
</tr>
<tr>
<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"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">GET /recordings/stored</span></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"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">Retrieve a listing of all recordings stored on the system</span></td>
</tr>
<tr>
<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"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">GET /recordings/stored/{recordingName}</span></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"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">Retrieve a specific recording stored on the system</span></td>
</tr>
<tr>
<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"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">DELETE /recordings/stored/{recordingName}</span></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"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">Delete a stored recording</span></td>
</tr>
<tr>
<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"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">POST /recordings/stored/{recordingName}/copy</span></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"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">Create a copy of a stored recording</span></td>
</tr>
</tbody>
</table>
</div> <p class="diff-block-target diff-block-context" style="margin: 10px 0 0 0"> <span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">In a voicemail system, users will want to be able to copy and delete their voicemails.</span> </p> <p class="diff-block-target diff-block-context" style="margin: 10px 0 0 0"> <span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;"><Put some code of some sort here...not really sure what I'm going to do here yet></span> </p> <p class="diff-block-target diff-block-context" style="margin: 10px 0 0 0"> <span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">In addition to being able to manipulate stored recordings, ARI also allows for manipulation of live recordings. The following commands are available:</span> </p>
<div class="table-wrap diff-block-target diff-block-context" 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>
<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"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">Method</span></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"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">Description</span></th>
</tr>
<tr>
<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"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">GET /recordings/live/recordingName</span></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"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">Retrieve a live recording with a specific name</span></td>
</tr>
<tr>
<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"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">DELETE /recordings/live/recordingName</span></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"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">Stop a live recording and discard it</span></td>
</tr>
<tr>
<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"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">POST </span><span><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">/recordings/live/recordingName/</span></span><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">stop</span></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"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">Stop a live recording and store it</span></td>
</tr>
<tr>
<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"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">POST </span><span><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">/recordings/live/recordingName/</span></span><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">pause</span></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"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">Temporarily stop a live recording</span></td>
</tr>
<tr>
<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"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">DELETE </span><span><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">/recordings/live/recordingName/</span></span><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">pause</span></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"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">Unpause the live recording</span></td>
</tr>
<tr>
<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"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">POST </span><span><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">/recordings/live/recordingName/</span></span><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">mute</span></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"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">Mute a live recording</span></td>
</tr>
<tr>
<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"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">DELETE </span><span><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">/recordings/live/recordingName/</span></span><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">mute</span></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"><span class="diff-html-removed" style="font-size: 100%; background-color: #ffe7e7; text-decoration: line-through;">Unmute a live recording</span></td>
</tr>
</tbody>
</table>
</div> <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">
<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"></pre> </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;">Instead of listing for a </span><code style="line-height: 1.4285715;; font-family: monospace"><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">RecordingFinished</span></code><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;"> event, we instead listen for </span><code style="line-height: 1.4285715;; font-family: monospace"><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">ChannelDtmfReceived</span></code><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">. This lets us act differently depending on which DTMF digit we receive from the channel. Notice that when we receive a DTMF digit that we care about, we stop listening for DTMF ({{DTMF_EVENT.stop()}} in Python, </span><code style="font-family: monospace"><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">channel.removeListener()</span></code><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;"> in Javascript). This is so that if a user presses the '*' key multiple times while recording, we will not have the </span><code style="font-family: monospace"><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">ChannelDtmfReceived</span></code><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;"> event fire multiple times for a single key press. Since we are having to listen for DTMF events, it also becomes easier for us to detect the '#' key press ourselves and leave off the </span><code style="font-family: monospace"><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">terminateOn</span></code><span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;"> option when recording the audio.</span> </p> <h3 id="MEDIA?MORELIKEMEDI-DUH!-Playingbackrecordings" class="diff-block-target diff-block-context" style="margin: 10px 0 0 0; font-size: 16px; line-height: 25px; margin: 30px 0 0 0"> <span class="diff-html-added" style="font-size: 100%; background-color: #ddfade;">Playing back recordings</span> </h3> <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;">Being able to cancel a voicemail while recording it is somewhat nice. What would be better, though, is if a caller were able to listen to the recorded voicemail and then be able to accept the current recording or discard it and re-record. We can modify the scripts to be able to play the stored voicemail back once the user has finished recording the initial voicemail.</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;">Since DTMF key presses now have different meanings depending on the current state of the call, we will introduce a very simple state machine concept into each of the scripts. Initially, when the call starts, the call will be in a "recording" state. Pressing the '*' key will cancel the current recording and start over. Pressing the '#' key will accept the recording and move to the "review" state. In this state, the recorded voicemail is played back to the caller. If the caller presses '*' during playback, the playback will be stopped and the call will re-enter the "recording" state. If the caller presses the '#' key, then the recording is accepted and the call is ended. If the playback finishes and the caller has not pressed any DTMF yet, then the call moves to the "waiting" state. In this state, the '*' and '#' keys have the same function as in the "review" state, but there is no playback to stop.</span> </p> </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/pages/viewpage.action?pageId=29396202&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/pages/viewpage.action?pageId=29396202&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/pages/viewpage.action?pageId=29396202&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/pages/viewpage.action?pageId=29396202&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=29396202&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=29396202&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>