diff --git a/lib/NGCP/Panel/Controller/Sound.pm b/lib/NGCP/Panel/Controller/Sound.pm index 6d0a16846c..f88afa3512 100644 --- a/lib/NGCP/Panel/Controller/Sound.pm +++ b/lib/NGCP/Panel/Controller/Sound.pm @@ -8,7 +8,10 @@ use NGCP::Panel::Form::Sound::AdminSet; use NGCP::Panel::Form::Sound::ResellerSet; use NGCP::Panel::Form::Sound::CustomerSet; use NGCP::Panel::Form::Sound::File; +use NGCP::Panel::Form::Sound::LoadDefault; use File::Type; +use File::Slurp; +use File::Basename; use NGCP::Panel::Utils::XMLDispatcher; use NGCP::Panel::Utils::Sounds; use NGCP::Panel::Utils::Navigation; @@ -88,7 +91,7 @@ sub contract_sets_list :Chained('/') :PathPart('sound/contract') :CaptureArgs(1) if($c->user->roles eq "subscriberadmin" && $c->user->account_id != $contract_id) { NGCP::Panel::Utils::Message->error( c => $c, - error => "access violatio, subscriberadmin ".$c->user->uuid." with contract id ".$c->user->account_id." tries to access foreign contract id $contract_id", + error => "access violation, subscriberadmin ".$c->user->uuid." with contract id ".$c->user->account_id." tries to access foreign contract id $contract_id", desc => $c->loc('Invalid contract id found'), ); NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/sound')); @@ -444,8 +447,8 @@ sub handles_list :Chained('base') :PathPart('handles') :CaptureArgs(0) { my $handles_rs = $c->model('DB')->resultset('voip_sound_groups') ->search({ },{ - select => ['groups.name', \'handles.name', \'handles.id', 'files.filename', 'files.loopplay', 'files.codec'], - as => [ 'groupname', 'handlename', 'handleid', 'filename', 'loopplay', 'codec'], + select => ['groups.name', \'handles.name', \'handles.id', 'files.filename', 'files.loopplay', 'files.codec', 'files.id'], + as => [ 'groupname', 'handlename', 'handleid', 'filename', 'loopplay', 'codec', 'fileid'], alias => 'groups', from => [ { groups => 'provisioning.voip_sound_groups' }, @@ -465,7 +468,7 @@ sub handles_list :Chained('base') :PathPart('handles') :CaptureArgs(0) { 'groups.name' => { '-in' => [qw/pbx music_on_hold digits/] } }); } else { - $handles_rs = $handles_rs->search({ 'groups.name' => { '!=' => 'pbx' } }); + #$handles_rs = $handles_rs->search({ 'groups.name' => { '!=' => 'pbx' } }); } unless($c->config->{features}->{cloudpbx}) { @@ -592,7 +595,7 @@ sub handles_edit :Chained('handles_base') :PathPart('edit') { } last SWITCH; }; - /^(pbx|music_on_hold)$/ && do { + /^(pbx|music_on_hold|voucher_recharge|play_balance|conference|digits)$/ && do { my $service; try { if(!$file_result->set->contract_id) { @@ -726,102 +729,142 @@ sub handles_download :Chained('handles_base') :PathPart('download') :Args(0) { return; } +sub handles_load_default :Chained('handles_list') :PathPart('loaddefault') :Args(0) { + my ($self, $c) = @_; + my $posted = ($c->request->method eq 'POST'); + my $form = NGCP::Panel::Form::Sound::LoadDefault->new; + $form->process( + posted => $posted, + params => $c->request->params, + item => {}, + ); + NGCP::Panel::Utils::Navigation::check_form_buttons( + c => $c, + form => $form, + fields => {}, + back_uri => $c->req->uri, + ); + + if($posted && $form->validated) { + my $lang = $form->params->{language}; + my $base = "/var/lib/ngcp-soundsets"; + my $set_id = $c->stash->{set_result}->id; + try { + my $schema = $c->model('DB'); + $schema->txn_do(sub { + foreach my $h($c->stash->{handles_rs}->all) { + my $hname = $h->get_column("handlename"); + my @paths = ( + "$base/system/$lang/$hname.wav", + "$base/customer/$lang/$hname.wav", + "/var/lib/asterisk/sounds/$lang/digits/$hname.wav", + ); + my $path; + foreach my $p(@paths) { + if(-f $p) { + $path = $p; + last; + } + } + next unless(defined $path); + + my $handle_id = $h->get_column("handleid"); + my $file_id = $h->get_column("fileid"); + my $fres; + my $fname = basename($path); + if(defined $file_id) { + if($form->params->{override}) { + $c->log->debug("override $path as $hname for existing id $file_id"); + my $data; + if(!$c->stash->{set_result}->contract_id && + grep {/^$hname$/} (qw/music_on_hold/)) { + + $fname =~ s/\.wav$/.pcma/; + $data = NGCP::Panel::Utils::Sounds::transcode_file( + $path, 'WAV', 'PCMA'); + } else { + $data = read_file($path); + } -__PACKAGE__->meta->make_immutable; - -1; - -__END__ - -=head1 NAME - -NGCP::Panel::Controller::Sound - Manage Sounds - -=head1 DESCRIPTION - -Show/Edit/Create/Delete Sound Sets. - -Show/Upload Sound Files in Sound Sets. - -=head1 METHODS - -=head2 auto - -Grants access to admin and reseller role. - -=head2 sets_list - -Basis for provisioning.voip_sound_sets. -Provides sets_rs in stash. - -=head2 root - -Display Sound Sets through F template. - -=head2 ajax - -Get provisioning.voip_sound_sets from db and output them as JSON. -The format is meant for parsing with datatables. - -=head2 base - -Fetch a provisioning.voip_sound_sets row from the database by its id. -The resultset is exported to stash as "set_result". - -=head2 edit - -Show a modal to edit the Sound Set determined by L using the form -L. - -=head2 delete - -Delete the Sound Set determined by L. - -=head2 create - -Show modal to create a new Sound Set using the form -L. - -=head2 handles_list - -Basis for provisioning.voip_sound_handles grouped by voip_sound_groups with -the actual data in voip_sound_files. -Stashes: - * handles_base_uri: To show L - * files_rs: Resultset of voip_sound_files in the current voip_sound_group - * sound_groups: Hashref of sound_goups with handles JOIN files inside - (used in the template F) - -=head2 handles_root - -Display Sound Files through F template accordion -grouped by sound_groups. - -=head2 handles_base - -Fetch a provisioning.voip_sound_files row from the database by the id -of the according voip_sound_handle. Create a new one if it doesn't exist but -do not immediately update the db. -The ResultClass is exported to stash as "file_result". - -=head2 handles_edit - -Show a modal to upload a file or set/unset loopplay using the form -L. - -=head2 handles_delete + $fres = $schema->resultset('voip_sound_files')->find($file_id); + $fres->update({ + filename => $fname, + data => $data, + loopplay => $form->params->{loopplay} ? 1 : 0, + }); + } else { + $c->log->debug("skip $path as $hname exists via id $file_id and override is not set"); + } + } else { + $c->log->debug("inserting $path as $hname with new id"); + + my $codec = 'WAV'; + my $data; + if(!$c->stash->{set_result}->contract_id && + grep {/^$hname$/} (qw/music_on_hold/)) { + + $fname =~ s/\.wav$/.pcma/; + $codec = 'PCMA'; + $data = NGCP::Panel::Utils::Sounds::transcode_file( + $path, 'WAV', $codec); + } else { + $data = read_file($path); + } -Delete the Sound File determined by L. + $fres = $schema->resultset('voip_sound_files') + ->create({ + filename => $fname, + data => $data, + handle_id => $handle_id, + set_id => $set_id, + loopplay => $form->params->{loopplay} ? 1 : 0, + codec => $codec, + }); + } -=head1 AUTHOR + SWITCH: for ($fres->handle->group->name) { + /^calling_card$/ && do { + NGCP::Panel::Utils::Sems::clear_audio_cache($c, "appserver", $fres->set_id, $fres->handle->name); + last SWITCH; + }; + /^(pbx|music_on_hold|voucher_recharge|play_balance|conference|digits)$/ && do { + my $service; + if(!$fres->set->contract_id && $_ ne "pbx") { + # app server doesn't know about pbx sets, skip them + $service = "appserver"; + NGCP::Panel::Utils::Sems::clear_audio_cache($c, $service, $fres->set_id, $fres->handle->name); + } else { + $service = "pbx"; + NGCP::Panel::Utils::Sems::clear_audio_cache($c, $service, $fres->set_id, $fres->handle->name); + } + last SWITCH; + }; + } + } + }); + NGCP::Panel::Utils::Message->info( + c => $c, + desc => $c->loc('Sound set successfully loaded with default files.'), + ); + } catch($e) { + NGCP::Panel::Utils::Message->error( + c => $c, + error => $e, + desc => $c->loc('Failed to load default sound files.'), + ); + } + NGCP::Panel::Utils::Navigation::back_or($c, $c->stash->{handles_base_uri}); + return; + } -Gerhard Jungwirth C<< >> + $c->stash(form => $form); + $c->stash(edit_default_flag => 1); + return; +} -=head1 LICENSE -This library is free software. You can redistribute it and/or modify -it under the same terms as Perl itself. +__PACKAGE__->meta->make_immutable; -=cut +1; # vim: set tabstop=4 expandtab: diff --git a/lib/NGCP/Panel/Form/Sound/LoadDefault.pm b/lib/NGCP/Panel/Form/Sound/LoadDefault.pm new file mode 100644 index 0000000000..1da777cd01 --- /dev/null +++ b/lib/NGCP/Panel/Form/Sound/LoadDefault.pm @@ -0,0 +1,82 @@ +package NGCP::Panel::Form::Sound::LoadDefault; + +use HTML::FormHandler::Moose; +extends 'HTML::FormHandler'; +use Moose::Util::TypeConstraints; +use File::Find::Rule; + +use HTML::FormHandler::Widget::Block::Bootstrap; + +has '+widget_wrapper' => ( default => 'Bootstrap' ); +has_field 'submitid' => ( type => 'Hidden' ); +sub build_render_list {[qw/submitid fields actions/]} +sub build_form_element_class {[qw(form-horizontal)]} + +has_field 'language' => ( + type => 'Select', + label => 'Language', + options_method => \&build_langs, + default => 'en', + required => 1, + element_attr => { + rel => ['tooltip'], + title => ['The language of the default sound files.'] + }, +); + +sub build_langs { + my ($self) = @_; + + my @options = (); + my @dirs = File::Find::Rule + ->directory + ->maxdepth(1) + ->not(File::Find::Rule->new->name(qr/^\.\.?$/)) + ->in('/var/lib/ngcp-soundsets/system'); + + @options = map { $_ =~ s/^.+\///; { label => $_, value => $_ } } @dirs; + + return \@options; +} + + +has_field 'loopplay' => ( + type => 'Boolean', + label => 'Play in Loop', + element_attr => { + rel => ['tooltip'], + title => ['Whether to play files in a loop where applicable.'] + }, +); + +has_field 'override' => ( + type => 'Boolean', + label => 'Replace existing', + element_attr => { + rel => ['tooltip'], + title => ['Replace existing sound files in set by default files.'] + }, +); + +has_field 'save' => ( + type => 'Submit', + value => 'Save', + element_class => [qw/btn btn-primary/], + label => '', +); + +has_block 'fields' => ( + tag => 'div', + class => [qw/modal-body/], + render_list => [qw/language loopplay override/], +); + +has_block 'actions' => ( + tag => 'div', + class => [qw/modal-footer/], + render_list => [qw/save/], +); + +1; + +# vim: set tabstop=4 expandtab: diff --git a/share/templates/sound/handles_list.tt b/share/templates/sound/handles_list.tt index 8eab4e2b62..5010a1d90a 100644 --- a/share/templates/sound/handles_list.tt +++ b/share/templates/sound/handles_list.tt @@ -1,6 +1,11 @@ [% site_config.title = c.loc('Manage Sound Set [_1]', set_result.name) -%] - [% c.loc('Back') %] + [% back_created = 1 -%] [% IF messages -%] @@ -68,15 +73,15 @@ [% END %] -[% IF edit_flag -%] - -[% +[% IF edit_flag || edit_default_flag; PROCESS "helpers/modal.tt"; modal_header(m.create_flag=0, - m.name = file_result.handle.name ); + m.name = edit_default_flag ? c.loc('Default Files') : file_result.handle.name ); translate_form(form).render; modal_footer(); + END; -%] +[% IF edit_flag || edit_default_flag -%]