TT#5953 Implement wav conversion to the GSM for the voicemail greetings

Change-Id: I425c7cd66bb9ce38cadbbf4804738a47d9942383
changes/22/10622/4
Irina Peshinskaya 9 years ago
parent 49c092a7d9
commit dbd63c2181

@ -81,7 +81,7 @@ sub create_item {
my ($self, $c, $resource, $form, $process_extras) = @_;
my $dir = NGCP::Panel::Utils::Subscriber::get_subscriber_voicemail_directory( c => $c, subscriber => $c->stash->{checked}->{subscriber}, dir => $resource->{dir} );
my $item = $c->stash->{checked}->{voicemail_subscriber}->voicemail_spools->create({
'recording' => $resource->{greetingfile}->slurp,
'recording' => ${$process_extras->{binary_ref}},
'dir' => $dir,
'origtime' => time(),#just to make inflate possible. Really we don't need this value
'mailboxcontext' => 'default',

@ -29,10 +29,12 @@ sub update_item_model{
my($self, $c, $item, $old_resource, $resource, $form, $process_extras) = @_;
my $dir = NGCP::Panel::Utils::Subscriber::get_subscriber_voicemail_directory(c => $c, subscriber => $c->stash->{checked}->{subscriber}, dir => $resource->{dir} );
$item->update({
'recording' => $resource->{greetingfile}->slurp,
'dir' => $dir,
'origtime' => time(),#just to make inflate possible. Really we don't need this value
'recording' => ${$process_extras->{binary_ref}},
'dir' => $dir,
'mailboxuser' => $c->stash->{checked}->{subscriber}->uuid,
'origtime' => time(),#just to make inflate possible. Really we don't need this value
});
#we need to return subscriber id, so item can be used for further update
#We can't just add field to the item object, so we need to reselect it

@ -8,7 +8,6 @@ use JSON qw(decode_json encode_json);
use URI::Escape qw(uri_unescape);
use Data::Dumper;
use MIME::Base64 qw(encode_base64url decode_base64url);
use File::Type;
use NGCP::Panel::Utils::Navigation;
use NGCP::Panel::Utils::Contract;
@ -3043,17 +3042,28 @@ sub edit_voicebox :Chained('base') :PathPart('preferences/voicebox/edit') :Args(
return;
}
}elsif($posted){
my $ft = File::Type->new();
my $greetingfile = delete $form->values->{'greetingfile'};
my $mime_type = $ft->mime_type($greetingfile);
if(('edit' eq $action) &&('audio/x-wav' ne $mime_type && 'application/octet-stream' ne $mime_type)){
die('Wrong mime-type '.$mime_type.' for the voicemail greeting. Must be a audio file in the "wav" format');
my $greeting_converted_ref;
try {
NGCP::Panel::Utils::Subscriber::convert_voicemailgreeting(
c => $c,
upload => $greetingfile,
filepath => $greetingfile->tempname,
converted_data_ref => \$greeting_converted_ref );
} catch($e) {
NGCP::Panel::Utils::Message::error(
c => $c,
log => $e,
desc => $c->loc($e),
);
NGCP::Panel::Utils::Navigation::back_or($c,
$c->uri_for_action('/subscriber/preferences', [$c->req->captures->[0]]), 1);
return;
}
if($form->validated) {
if('edit' eq $action){
$vm_user->voicemail_spools->update_or_create({
'recording' => $greetingfile->slurp,
'recording' => $$greeting_converted_ref,
'dir' => $dir,
'origtime' => time(),#just to make inflate possible. Really we don't need this value
'mailboxcontext' => 'default',
@ -3097,7 +3107,7 @@ sub edit_voicebox :Chained('base') :PathPart('preferences/voicebox/edit') :Args(
NGCP::Panel::Utils::Message::error(
c => $c,
error => $e,
desc => $c->loc('Failed to update voicemail setting'),
desc => $c->loc('Failed to update voicemail setting.'),
);
NGCP::Panel::Utils::Navigation::back_or($c,
$c->uri_for_action('/subscriber/preferences', [$c->req->captures->[0]]));

@ -62,8 +62,31 @@ sub get_form {
return (NGCP::Panel::Form::Voicemail::GreetingAPI->new, ['subscriber_id'] );
}
sub process_hal_resource{
my $self = shift;
my ($c, $item, $resource, $form) = @_;
$resource->{dir} = NGCP::Panel::Utils::Subscriber::get_subscriber_voicemail_type(c => $c, dir => $resource->{dir} );
return $resource;
}
sub process_form_resource{
my($self, $c, $item, $old_resource, $resource, $form, $process_extras) = @_;
try{
NGCP::Panel::Utils::Subscriber::convert_voicemailgreeting(
c => $c,
upload => $resource->{greetingfile},
converted_data_ref => \$process_extras->{binary_ref},
);
} catch($e) {
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, $e);
return;
}
return 1;
}
sub check_resource{
my($self, $c, $item, $old_resource, $resource, $form) = @_;
my($self, $c, $item, $old_resource, $resource, $form, $process_extras) = @_;
#TODO: Move subscriber checking to some checking collections
my $subscriber_rs = $c->model('DB')->resultset('voip_subscribers')->search({
@ -108,7 +131,7 @@ sub check_resource{
}
sub check_duplicate{
my($self, $c, $item, $old_resource, $resource, $form) = @_;
my($self, $c, $item, $old_resource, $resource, $form, $process_extras) = @_;
my $rs = $self->item_rs($c);
@ -132,11 +155,6 @@ sub check_duplicate{
# return $res;
#}
sub process_hal_resource{
my $self = shift;
my ($c, $item, $resource, $form) = @_;
$resource->{dir} = NGCP::Panel::Utils::Subscriber::get_subscriber_voicemail_type(c => $c, dir => $resource->{dir} );
return $resource;
}
1;
# vim: set tabstop=4 expandtab:

@ -15,6 +15,7 @@ use NGCP::Panel::Utils::Events;
use UUID qw/generate unparse/;
use JSON qw/decode_json encode_json/;
use IPC::System::Simple qw/capturex/;
use File::Slurp qw/read_file/;
my %LOCK = (
0, 'none',
@ -1493,6 +1494,7 @@ sub update_voicemail_number {
return;
}
sub vmnotify{
my (%params) = @_;
@ -1518,6 +1520,7 @@ sub vmnotify{
$c->log->debug("cmd=".join(" ", @cmd)."; output=$output;");
return;
}
sub mark_voicemail_read{
my (%params) = @_;
@ -1528,6 +1531,7 @@ sub mark_voicemail_read{
$voicemail->update({ dir => $dir });
return;
}
sub get_subscriber_voicemail_directory{
my (%params) = @_;
@ -1536,6 +1540,7 @@ sub get_subscriber_voicemail_directory{
my $dir = $params{dir};
return "/var/spool/asterisk/voicemail/default/".$subscriber->uuid."/$dir";
}
sub get_subscriber_voicemail_type{
my (%params) = @_;
@ -1544,6 +1549,46 @@ sub get_subscriber_voicemail_type{
$dir =~s/.*?\/([^\/]+)$/$1/gis;
return $dir;
}
sub convert_voicemailgreeting{
my (%params) = @_;
my $c = $params{c};
my $upload = $params{upload};
my $converted_data_ref = $params{converted_data_ref};
if(!$upload->size){
die('Uploaded greeting file is empty.');
}
$c->log->debug("type=".$upload->type."; size=".$upload->size."; filename=".$upload->filename.";");
my $filepath = $upload->tempname;
my $filepath_converted = $filepath;
$filepath_converted =~s/\.([^\.]+)$/\.converted.$1/;
#my $ft = File::Type->new();
#my $greetingfile = delete $form->values->{'greetingfile'};
#my $mime_type = $ft->mime_type($greetingfile);
#if(('edit' eq $action) &&('audio/x-wav' ne $mime_type && 'application/octet-stream' ne $mime_type)){
# die('Wrong mime-type '.$mime_type.' for the voicemail greeting. Must be a audio file in the "wav" format');
# return;
#}
my @cmd = ( $filepath, '-e', 'gsm', '-b', '16', '-r', '8000', '-c', '1', $filepath_converted);
my $output = '';
$c->log->debug("cmd=".join(" ", 'sox', @cmd));
eval {
$output = capturex('sox', @cmd);
};
$c->log->debug("cmd=".join(" ", 'sox', @cmd)."; output=$output; \$\@=".($@?$@:'').';');
if($output || $@){
die('Wrong file format for the voicemail greeting. Must be a audio file in the "wav" format with "gsm" encoding.');
}
my $data = read_file($filepath_converted, {binmode => ':raw'},);
if(!length($data)){
die('Empty greeting file after conversion to GSM encoding.');
}
${$params{converted_data_ref}} = \$data;
}
sub number_as_string{
my ($number_row, %params) = @_;
return 'HASH' eq ref $number_row
@ -1610,6 +1655,7 @@ sub create_cf_destination{
});
}
}
sub get_subscriber_pbx_status{
my($c, $subscriber) = @_;
if($c->config->{features}->{cloudpbx}) {

@ -7,7 +7,9 @@ use JSON;
use Test::More;
use Data::Dumper;
use File::Basename;
use File::Slurp qw/read_file/;
use File::Slurp qw/read_file write_file/;
use File::Temp;
use NGCP::Panel::Utils::Generic qw(:all);
#init test_machine
my $fake_data = Test::FakeData->new;
@ -36,26 +38,74 @@ $test_machine->methods->{item}->{allowed} = {map {$_ => 1} qw(GET HEAD OPT
#$test_machine->form_data_item( sub {$_[0]->{json}->{dir} = $dir;} );
$test_machine->form_data_item();
my ($res,$content,$req);
my $greeting = $test_machine->check_create_correct( 1 )->[0];
ok(is_int($greeting->{content}->{id}), "Check id presence after creation.");
ok(is_int($greeting->{content}->{subscriber_id}), "Check subscriber_id presence after creation.");
is($greeting->{content}->{subscriber_id}, $test_machine->DATA_ITEM->{json}->{subscriber_id}, "Check subscriber_id after creation.");
ok($greeting->{content}->{dir} =~/^(?:unavail|busy)$/, "Check dir after creation.");
is($greeting->{content}->{dir}, $test_machine->DATA_ITEM->{json}->{dir}, "Check dir after creation #2.");
my $req = $test_machine->get_request_get($greeting->{location});
$req->header('Accept' => 'audio/x-wav');
my ($res) = $test_machine->request_get(undef, $req);
$test_machine->http_code_msg(200, "check download ", $res);
is($res->filename, "voicemail_".$greeting->{content}->{dir}."_".$greeting->{content}->{subscriber_id}.".wav","Check downloaded file name.");
$res = $test_machine->request_get($greeting->{location}, undef, {
'Accept' => 'audio/x-wav',
});
$test_machine->http_code_msg(200, "check download voicemail greeting", $res);
my $expected_downloaded_name = "voicemail_".$greeting->{content}->{dir}."_".$greeting->{content}->{subscriber_id}.".wav";
is($res->filename, $expected_downloaded_name ,"Check downloaded file name: $expected_downloaded_name .");
ok(length($res->content)>0,"Check length of the downloaded file > 0 :".length($res->content));
my $uploaded_path = $test_machine->DATA_ITEM_STORE->{greetingfile}->[0];
my $sent_file_content_ref = read_file($test_machine->DATA_ITEM_STORE->{greetingfile}->[0], binmode => ':raw');
my $dir = File::Temp->newdir(undef, CLEANUP => 0);
my $tempdir = $dir->dirname;
my $downloaded_path = $tempdir.'/'.$expected_downloaded_name;
write_file( $downloaded_path , {binmode => ':raw'}, $res->content);
my $soxi_output = `soxi -e $downloaded_path`;
$soxi_output=~s/\n//g;
is(length($res->content), length($sent_file_content_ref),"Check length of the downloaded file");
if(ok($soxi_output =~/GSM/, "Check that we converted wav to GSM encoding:".$soxi_output)){
my $soxi_output_original = `soxi -e $uploaded_path`;
$soxi_output_original=~s/\n//g;
if(ok($soxi_output_original ne $soxi_output, "Check that we used non GSM encoded wav from the start")){
diag("Time to test uploading of the wav file with GSM encoding");
$test_machine->DATA_ITEM->{json}->{dir} = 'busy';
($res,$content,$req) = $test_machine->request_put( [
'json' => JSON::to_json($test_machine->DATA_ITEM->{json}),
greetingfile => [ $downloaded_path ],
] );
$test_machine->http_code_msg(200, "check download voicemail greeting after put", $res, $content);
ok(is_int($content->{id}),"Check id presence after editing.");
ok(is_int($content->{subscriber_id}),"Check subscriber_id presence after editing.");
is($content->{dir}, 'busy', "Check dir after editing.");
is($content->{subscriber_id}, $greeting->{content}->{subscriber_id}, "Check subscriber_id after editing.");
$test_machine->check_get2put( {
'data_cb' => sub {
$_[0] = {
'json' => JSON::to_json($_[0]),
'greetingfile' => $test_machine->DATA_ITEM_STORE->{greetingfile}
};
$uploaded_path = $downloaded_path;
$test_machine->http_code_msg(200, "check update voicemail greeting with put. We used GSM file $downloaded_path.", $res);
my $uploaded_content = read_file($downloaded_path, binmode => ':raw');
my $res_download = $test_machine->request_get($greeting->{location}, undef, {
'Accept' => 'audio/x-wav',
});
$test_machine->http_code_msg(200, "check download voicemail greeting after put", $res);
is(length($res_download->content), length($uploaded_content),"Check length of the downloaded file: ".length($uploaded_content)."<=>".length($res_download->content));
}
} );
}
{
diag("Check empty file:");
#btw - other vriant of tha put data - closer to stored. will be changed by Collection::encode_content
my ($res_put_empty,$content_put_empty) = $test_machine->request_put( {
%{$test_machine->DATA_ITEM_STORE},
greetingfile => [ dirname($0).'/resources/empty.wav' ],
} );
$test_machine->http_code_msg(422, "check response code on put empty file", $res_put_empty, $content_put_empty);
diag("Check dirty file:");
#btw - other vriant of tha put data - closer to stored. will be changed by Collection::encode_content
($res_put_empty,$content_put_empty) = $test_machine->request_put( {
%{$test_machine->DATA_ITEM_STORE},
greetingfile => [ dirname($0).'/resources/empty.wav' ],
} );
$test_machine->http_code_msg(422, "check response code on put empty file", $res_put_empty, $content_put_empty);
}
$test_machine->check_bundle();
$test_machine->check_item_delete($greeting->{location});

@ -486,6 +486,15 @@ sub encode_content{
if($content){
if( $json_types{$type} && (('HASH' eq ref $content) ||('ARRAY' eq ref $content)) ){
return JSON::to_json($content);
}elsif('multipart/form-data' eq $type
&& 'HASH' eq ref $content
&& $content->{json}
&& (('HASH' eq ref $content->{json}) || ( 'ARRAY' eq ref $content->{json} ) )
){
$content->{json} = JSON::to_json($content->{json});
return [
%{$content},
];
}
}
#print "2. content=$content;\n\n";
@ -524,9 +533,13 @@ sub request_process{
return ($res,$rescontent,$req);
}
sub get_request_get{
my($self, $uri) = @_;
my($self, $uri, $headers) = @_;
$headers ||= {};
$uri = $self->normalize_uri($uri);
my $req = HTTP::Request->new('GET', $uri);
foreach my $key (keys %$headers){
$req->header($key => $headers->{$key});
}
return $req ;
}
sub get_request_put{
@ -635,9 +648,9 @@ sub request_delete{
}
sub request_get{
my($self,$uri,$req) = @_;
my($self,$uri,$req,$headers) = @_;
$uri = $self->normalize_uri($uri);
$req //= $self->get_request_get($uri);
$req //= $self->get_request_get($uri,$headers);
my $res = $self->request($req);
my $content = $self->get_response_content($res);
return wantarray ? ($res, $content, $req) : $res;

Loading…
Cancel
Save