Move transcoder to separate file.

Transcode VM messages to get WAV instead of WAV49.
Fix sound set handling and transcode PCMA to WAV.
agranig/1_0_subfix
Andreas Granig 12 years ago
parent da4170c2a6
commit b194556431

@ -7,8 +7,8 @@ BEGIN { extends 'Catalyst::Controller'; }
use NGCP::Panel::Form::SoundSet;
use NGCP::Panel::Form::SoundFile;
use File::Type;
use IPC::System::Simple qw/capturex/;
use NGCP::Panel::Utils::XMLDispatcher;
use NGCP::Panel::Utils::Sounds;
sub auto :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRole(reseller) {
my ($self, $c) = @_;
@ -133,13 +133,13 @@ sub handles_list :Chained('base') :PathPart('handles') :CaptureArgs(0) {
as => [ 'groupname', 'handlename', 'handleid', 'filename', 'loopplay', 'codec'],
alias => 'groups',
from => [
{ groups => 'voip_sound_groups' },
{ groups => 'provisioning.voip_sound_groups' },
[
{ handles => 'voip_sound_handles', -join_type=>'left'},
{ handles => 'provisioning.voip_sound_handles', -join_type=>'left'},
{ 'groups.id' => 'handles.group_id'},
],
[
{ files => 'voip_sound_files', -join_type => 'left'},
{ files => 'provisioning.voip_sound_files', -join_type => 'left'},
{ 'handles.id' => { '=' => \'files.handle_id'}, 'files.set_id' => $c->stash->{set_result}->id},
],
],
@ -231,7 +231,7 @@ sub handles_edit :Chained('handles_base') :PathPart('edit') {
}
try {
$soundfile = $self->_transcode_sound_file(
$soundfile = NGCP::Panel::Utils::Sounds::transcode_file(
$upload->tempname, 'WAV', $target_codec);
} catch ($error) {
$c->flash(messages => [{type => 'error', text => 'Transcode of audio file failed!'}]);
@ -243,7 +243,7 @@ sub handles_edit :Chained('handles_base') :PathPart('edit') {
$file_result->update({
filename => $filename,
data => $soundfile,
codec => 'WAV',
codec => $target_codec,
});
}
@ -272,43 +272,29 @@ sub handles_delete :Chained('handles_base') :PathPart('delete') {
sub handles_download :Chained('handles_base') :PathPart('download') :Args(0) {
my ($self, $c) = @_;
my %codec_mapping = (WAV => 'audio/x-wav');
my $file_result = $c->stash->{file_result};
$c->response->header ('Content-Disposition' => 'attachment; filename="' . $file_result->filename . '"');
$c->response->content_type(
$codec_mapping{$file_result->codec} // 'application/octet-stream'); #'
$c->response->body($file_result->data);
}
sub _transcode_sound_file {
my ($self, $tmpfile, $source_codec, $target_codec) = @_;
my $out;
my @conv_args;
## quite snappy, but breaks SOAP (sigpipe's) and the catalyst devel server
## need instead to redirect like below
given ($target_codec) {
when ('PCMA') {
@conv_args = ($tmpfile, qw/--type raw --bits 8 --channels 1 -A - rate 8k/);
}
when ('WAV') {
if ($source_codec eq 'PCMA') {
# this can actually only come from inside
# certain files will be stored as PCMA (for handles with name "music_on_hold")
@conv_args = ( qw/-A --rate 8k --channels 1 --type raw/, $tmpfile, "--type", "wav", "-");
}
else {
@conv_args = ($tmpfile, qw/--type wav --bits 16 - rate 8k/);
}
my $file = $c->stash->{file_result};
my $filename = $file->filename;
$filename =~ s/\.\w+$/.wav/;
my $data;
say ">>>>>>>>>>>>>>>>> download ".$file->filename." with codec ".$file->codec;
if($file->codec ne 'WAV') {
try {
$data = NGCP::Panel::Utils::Sounds::transcode_data(
$file->data, $file->codec, 'WAV');
} catch ($error) {
$c->flash(messages => [{type => 'error', text => 'Transcode of audio file failed!'}]);
$c->log->info("Transcode failed: $error");
$c->response->redirect($c->stash->{handles_base_uri});
return;
}
} else {
$data = $file->data;
}
$out = capturex([0], "/usr/bin/sox", @conv_args);
return $out;
$c->response->header ('Content-Disposition' => 'attachment; filename="' . $filename . '"');
$c->response->content_type('audio/x-wav'); #'
$c->response->body($data);
}
sub _clear_audio_cache {
@ -435,16 +421,6 @@ L<NGCP::Panel::Form::SoundFile>.
Delete the Sound File determined by L</base>.
=head2 _transcode_sound_file
Transcodes the given sound file specified by a (temporary) filename.
This is ported from ossbss/lib/Sipwise/Provisioning/Voip.pm
For $target_codec 'PCMA' returns is RAW 8bit, 8kHz PCMA.
For $target_codec 'WAV' returns is WAV 16bit, 8kHz.
Will die if transcoding doesn't work.
=head2 _clear_audio_cache
Ported from ossbss.

@ -1356,11 +1356,22 @@ sub play_voicemail :Chained('voicemail') :PathPart('play') :Args(0) {
my ($self, $c) = @_;
my $file = $c->stash->{voicemail};
my $recording = $file->recording;
my $data;
try {
$data= NGCP::Panel::Utils::Sounds::transcode_data(
$recording, 'WAV', 'WAV');
} catch ($error) {
$c->flash(messages => [{type => 'error', text => 'Transcode of audio file failed!'}]);
$c->log->info("Transcode failed: $error");
$c->response->redirect($c->uri_for_action('/subscriber/details', [$c->req->captures->[0]]));
return;
}
# TODO: doesn't properly play wav49!
$c->response->header('Content-Disposition' => 'attachment; filename="'.$file->msgnum.'.wav"');
$c->response->content_type('audio/x-wav');
$c->response->body($file->recording);
$c->response->body($data);
}
sub delete_voicemail :Chained('voicemail') :PathPart('delete') :Args(0) {

@ -0,0 +1,52 @@
package NGCP::Panel::Utils::Sounds;
use strict;
use warnings;
use Sipwise::Base;
use IPC::System::Simple qw/capturex/;
use File::Temp qw/tempfile/;
sub transcode_file {
my ($tmpfile, $source_codec, $target_codec) = @_;
my $out;
my @conv_args;
## quite snappy, but breaks SOAP (sigpipe's) and the catalyst devel server
## need instead to redirect like below
given ($target_codec) {
when ('PCMA') {
@conv_args = ($tmpfile, qw/--type raw --bits 8 --channels 1 -e a-law - rate 8k/);
}
when ('WAV') {
if ($source_codec eq 'PCMA') {
# this can actually only come from inside
# certain files will be stored as PCMA (for handles with name "music_on_hold")
@conv_args = ( qw/-A --rate 8k --channels 1 --type raw/, $tmpfile, "--type", "wav", "-");
}
else {
@conv_args = ($tmpfile, qw/--type wav --bits 16 - rate 8k/);
}
}
}
$out = capturex([0], "/usr/bin/sox", @conv_args);
return $out;
}
sub transcode_data {
my ($data, $source_codec, $target_codec) = @_;
my ($fh, $filename) = tempfile;
print $fh $data;
close $fh;
my $out = transcode_file($filename, $source_codec, $target_codec);
unlink $filename;
return $out;
}
1;
# vim: set tabstop=4 expandtab:

@ -56,8 +56,8 @@ $(document).ready(function() {
var html = '' +
'<div class="sw_actions pull-right">';
[% FOR button IN helper.dt_buttons -%]
[% confirm_delete = 'data-confirm="Delete"' IF button.name == "Delete" -%]
[% confirm_delete = 'data-confirm="Terminate"' IF button.name == "Terminate" -%]
[% confirm_delete = button.name == "Delete" ? 'data-confirm="Delete"' : '' -%]
[% confirm_delete = button.name == "Terminate" ? 'data-confirm="Terminate"' : confirm_delete -%]
[% IF button.condition -%]
if([% button.condition %]) {
[% END -%]

@ -1,6 +1,6 @@
[% site_config.title = 'Manage Sound Set ' _ set_result.name -%]
<a href="[% c.uri_for() %]">&lt; Back</a>
<a class="btn btn-large btn-primary" href="[% c.uri_for() %]"><i class="icon-arrow-left"></i> Back</a>
[% IF messages -%]
<div class="row">
@ -25,34 +25,21 @@
<thead>
<tr>
[% # one for description -%]
<th></th>
<th>Name</th>
<th>Filename</th>
<th>Loop</th>
[% # one for actions -%]
<th class="span3"></th>
<th></th>
</tr>
</thead>
<tbody>
[% FOREACH r IN group.value %]
<tr class="sw_action_row">
<td>
<a href="#" onclick="$.msgbox(
'[% r.description.squote | html %]',
{
type:'info',
buttons:[
{type:'cancel',value:'Close'}
]
}); return false;"><i class="icon-question-sign"></i></a>
</td>
<td>
[% r.get_column("handlename") %]
</td>
<td>
<a href="[% c.uri_for_action('/sound/handles_download', [c.req.captures.0, r.get_column('handleid')]) %]">
[% r.get_column("filename") %]
</a>
</td>
<td>
<input type="checkbox" disabled="disabled" [% r.get_column('loopplay') ? 'checked="checked"' : '' %]>
@ -60,7 +47,10 @@
<td>
<div class="sw_actions pull-right">
<a class="btn btn-small btn-primary" href="[% handles_base_uri _ "/" _ r.get_column("handleid") _ "/edit" %]"><i class="icon-edit"></i> Upload</a>
[% IF r.get_column("filename").size -%]
<a class="btn btn-small btn-secondary" data-confirm="Delete" href="[% handles_base_uri _ "/" _ r.get_column("handleid") _ "/delete" %]"><i class="icon-edit"></i> Delete</a>
<a class="btn btn-small btn-tertiary" href="[% c.uri_for_action('/sound/handles_download', [c.req.captures.0, r.get_column('handleid')]) %]"><i class="icon-play"></i> Play</a>
[% END -%]
</div>
</td>
</tr>

@ -12,10 +12,6 @@
helper.form_object = form;
helper.ajax_uri = c.uri_for_action( "/sound/ajax" );
helper.extra_buttons = [
[ 'Files', 'handles'],
];
helper.dt_buttons = [
{ name = 'Edit', uri = "/sound/'+full[\"id\"]+'/edit", class = 'btn-small btn-primary', icon = 'icon-edit' },
{ name = 'Delete', uri = "/sound/'+full[\"id\"]+'/delete", class = 'btn-small btn-secondary', icon = 'icon-trash' },

Loading…
Cancel
Save