Use RecordRTC or Wami adding audio on execises tool - refs BT#11060

ofaj
Angel Fernando Quiroz Campos 10 years ago
parent 574a044a0c
commit 72cd91d40f
  1. 65
      main/exercice/exercise.class.php
  2. 2
      main/exercice/exercise_show.php
  3. 7
      main/exercice/exercise_submit.php
  4. 209
      main/exercice/oral_expression.class.php
  5. 4
      main/exercice/question.class.php
  6. 98
      main/inc/ajax/nanogong.ajax.php
  7. 28
      main/inc/ajax/wamirecorder.ajax.php
  8. 386
      main/inc/lib/WamiRecorder.php
  9. 34
      main/inc/lib/document.lib.php
  10. 11
      main/inc/lib/events.lib.php
  11. 20
      main/inc/lib/exercise.lib.php
  12. 10
      main/inc/lib/exercise_show_functions.lib.php
  13. 670
      main/inc/lib/nanogong.lib.php
  14. 139
      main/template/default/exercise/oral_expression.tpl

@ -3167,7 +3167,7 @@ class Exercise
$totalScore = 0;
// Destruction of the Question object
unset($objQuestionTmp);
//unset($objQuestionTmp);
// Construction of the Answer object
$objAnswerTmp = new Answer($questionId);
@ -3185,34 +3185,20 @@ class Exercise
$nbrAnswers = 1;
}
$nano = null;
$wamiRecorder = null;
if ($answerType == ORAL_EXPRESSION) {
$exe_info = Event::get_exercise_results_by_attempt($exeId);
$exe_info = isset($exe_info[$exeId]) ? $exe_info[$exeId] : null;
$params = array();
$params['course_id'] = $course_id;
$params['session_id'] = api_get_session_id();
$params['user_id'] = isset($exe_info['exe_user_id'])? $exe_info['exe_user_id'] : api_get_user_id();
$params['exercise_id'] = isset($exe_info['exe_exo_id'])? $exe_info['exe_exo_id'] : $this->id;
$params['question_id'] = $questionId;
$params['exe_id'] = isset($exe_info['exe_id']) ? $exe_info['exe_id'] : $exeId;
$nano = new Nanogong($params);
$wamiRecorder = new WamiRecorder(
api_get_course_int_id(),
$objQuestionTmp->initFile(
api_get_session_id(),
isset($exe_info['exe_user_id']) ? $exe_info['exe_user_id'] : api_get_user_id(),
isset($exe_info['exe_exo_id']) ? $exe_info['exe_exo_id'] : $this->id,
$questionId,
isset($exe_info['exe_id']) ? $exe_info['exe_id'] : $exeId
);
//probably this attempt came in an exercise all question by page
if ($feedback_type == 0) {
$nano->replace_with_real_exe($exeId);
$objQuestionTmp->replaceWithRealExe($exeId);
}
}
@ -3845,10 +3831,11 @@ class Exercise
$query = "SELECT answer, marks FROM ".$TBL_TRACK_ATTEMPT."
WHERE exe_id = '".$exeId."' AND question_id= '".$questionId."'";
$resq = Database::query($query);
$choice = Database::result($resq,0,'answer');
$row = Database::fetch_assoc($resq);
$choice = $row['answer'];
$choice = str_replace('\r\n', '', $choice);
$choice = stripslashes($choice);
$questionScore = Database::result($resq,0,"marks");
$questionScore = $row['marks'];
if ($questionScore==-1) {
$totalScore+=0;
} else {
@ -4195,7 +4182,8 @@ class Exercise
$choice,
0,
0,
$wamiRecorder);
$objQuestionTmp->getFileUrl()
);
//}
} elseif ($answerType == HOT_SPOT) {
//if ($origin != 'learnpath') {
@ -4527,7 +4515,7 @@ class Exercise
$choice,
$exeId,
$questionId,
$wamiRecorder
$objQuestionTmp->getFileUrl()
) . '</td>
</tr>
</table>';
@ -5043,7 +5031,16 @@ class Exercise
Event::saveQuestionAttempt($questionScore, $answer, $quesId, $exeId, 0, $this->id);
} elseif ($answerType == ORAL_EXPRESSION) {
$answer = $choice;
Event::saveQuestionAttempt($questionScore, $answer, $quesId, $exeId, 0, $this->id, $nano);
Event::saveQuestionAttempt(
$questionScore,
$answer,
$quesId,
$exeId,
0,
$this->id,
false,
$objQuestionTmp->getAbsoluteFilePath()
);
} elseif (in_array($answerType, [UNIQUE_ANSWER, UNIQUE_ANSWER_IMAGE, UNIQUE_ANSWER_NO_OPTION])) {
$answer = $choice;
Event::saveQuestionAttempt($questionScore, $answer, $quesId, $exeId, 0, $this->id);
@ -6850,6 +6847,7 @@ class Exercise
$nbrAnswers = $objAnswerTmp->selectNbrAnswers();
$course_id = api_get_course_int_id();
$sessionId = api_get_session_id();
$quiz_question_options = Question::readQuestionOption($questionId, $course_id);
// For "matching" type here, we need something a little bit special
@ -6914,27 +6912,28 @@ class Exercise
$s .= $form->return_form();
} elseif ($answerType == ORAL_EXPRESSION) {
// Add nanogong
if (api_get_setting('document.enable_nanogong') == 'true') {
if (api_get_setting('enable_record_audio') === 'true') {
//@todo pass this as a parameter
global $exercise_stat_info, $exerciseId;
if (!empty($exercise_stat_info)) {
$params = array(
'exercise_id' => $exercise_stat_info['exe_exo_id'],
'exe_id' => $exercise_stat_info['exe_id'],
'question_id' => $questionId
$objQuestionTmp->initFile(
api_get_session_id(),
api_get_user_id(),
$exercise_stat_info['exe_exo_id'],
$exercise_stat_info['exe_id']
);
} else {
$params = array(
'exercise_id' => $exerciseId,
'exe_id' => 'temp_exe',
'question_id' => $questionId
$objQuestionTmp->initFile(
api_get_session_id(),
api_get_user_id(),
$exerciseId,
'temp_exe'
);
}
$nano = new Nanogong($params);
$s .= $nano->show_button();
$s .= $objQuestionTmp->returnRecorder();
}
$form->addElement('html_editor', "choice[".$questionId."]", null, array('id' => "choice[".$questionId."]"), array('ToolbarSet' => 'TestFreeAnswer'));

@ -398,7 +398,6 @@ foreach ($questionList as $questionId) {
$questionScore = $question_result['score'];
$totalScore += $question_result['score'];
} elseif ($answerType == FREE_ANSWER) {
$answer = $str;
$question_result = $objExercise->manage_answer(
$id,
$questionId,
@ -413,7 +412,6 @@ foreach ($questionList as $questionId) {
$questionScore = $question_result['score'];
$totalScore += $question_result['score'];
} elseif ($answerType == ORAL_EXPRESSION) {
$answer = $str;
$question_result = $objExercise->manage_answer(
$id,
$questionId,

@ -63,6 +63,13 @@ $htmlHeadXtra[] = api_get_js('epiclock/renderers/minute/epiclock.minute.js');
$htmlHeadXtra[] = '<link rel="stylesheet" href="' . api_get_path(WEB_LIBRARY_JS_PATH) . 'hotspot/css/hotspot.css">';
$htmlHeadXtra[] = '<script src="' . api_get_path(WEB_LIBRARY_JS_PATH) . 'hotspot/js/hotspot.js"></script>';
if (api_get_setting('enable_record_audio') === 'true') {
$htmlHeadXtra[] = '<script src="' . api_get_path(WEB_LIBRARY_JS_PATH) . 'rtc/RecordRTC.js"></script>';
$htmlHeadXtra[] = '<script src="' . api_get_path(WEB_LIBRARY_PATH) . 'wami-recorder/recorder.js"></script>';
$htmlHeadXtra[] = '<script src="' . api_get_path(WEB_LIBRARY_PATH) . 'wami-recorder/gui.js"></script>';
$htmlHeadXtra[] = '<script type="text/javascript" src="' . api_get_path(WEB_LIBRARY_PATH) . 'swfobject/swfobject.js"></script>';
}
$template = new Template();
// General parameters passed via POST/GET

@ -14,6 +14,16 @@ class OralExpression extends Question
static $typePicture = 'audio_question.png';
static $explanationLangVar = 'OralExpression';
private $sessionId;
private $userId;
private $exerciseId;
private $exeId;
private $storePath;
private $fileName;
private $filePath;
public $available_extensions = array('wav', 'ogg');
/**
* Constructor
*/
@ -76,4 +86,203 @@ class OralExpression extends Question
return $header;
}
/**
* initialize the attributes to generate the file path
* @param $sessionId integer
* @param $userId integer
* @param $exerciseId integer
* @param $exeId integer
*/
public function initFile($sessionId, $userId, $exerciseId, $exeId)
{
$this->sessionId = intval($sessionId);
$this->userId = intval($userId);
$this->exerciseId = 0;
if (!empty($exerciseId)) {
$this->exerciseId = intval($exerciseId);
}
$this->exeId = intval($exeId);
$this->storePath = $this->generateDirectory();
$this->fileName = $this->generateFileName();
$this->filePath = $this->storePath . $this->fileName;
}
/**
* Generate the necessary directory for audios. If them not exists, are created
* @return string
*/
private function generateDirectory()
{
$this->storePath = api_get_path(SYS_COURSE_PATH) . $this->course['path'] . '/exercises/';
if (!is_dir($this->storePath)) {
mkdir($this->storePath);
}
if (!is_dir($this->storePath . $this->sessionId)) {
mkdir($this->storePath . $this->sessionId);
}
if (!empty($this->exerciseId) && !is_dir($this->storePath . $this->sessionId . '/' . $this->exerciseId)) {
mkdir($this->storePath . $this->sessionId . '/' . $this->exerciseId);
}
if (!empty($this->id) && !is_dir($this->storePath . $this->sessionId . '/' . $this->exerciseId . '/' . $this->id)) {
mkdir($this->storePath . $this->sessionId . '/' . $this->exerciseId . '/' . $this->id);
}
if (!empty($this->userId) && !is_dir($this->storePath . $this->sessionId . '/' . $this->exerciseId . '/' . $this->id . '/' . $this->userId)) {
mkdir($this->storePath . $this->sessionId . '/' . $this->exerciseId . '/' . $this->id . '/' . $this->userId);
}
return $this->storePath .= implode(
'/',
array(
$this->sessionId,
$this->exerciseId,
$this->id,
$this->userId
)
) . '/';
}
/**
* Generate the file name
* @return string
*/
private function generateFileName()
{
return implode(
'-',
array(
$this->course['real_id'],
$this->sessionId,
$this->userId,
$this->exerciseId,
$this->id,
$this->exeId
)
);
}
/**
* Generate a relative directory path
* @return string
*/
private function generateRelativeDirectory()
{
return '/exercises/' . implode(
'/',
[$this->sessionId, $this->exerciseId, $this->id, $this->userId]
) . '/';
}
/**
* Return the HTML code to show the RecordRTC/Wami recorder
* @return string
*/
public function returnRecorder()
{
$directory = '/..' . $this->generateRelativeDirectory();
$recordAudioView = new Template('', false, false,false, false, false, false);
$recordAudioView->assign('directory', $directory);
$recordAudioView->assign('user_id', $this->userId);
$recordAudioView->assign('file_name', $this->fileName);
$template = $recordAudioView->get_template('exercise/oral_expression.tpl');
return $recordAudioView->fetch($template);
}
/**
* Get the absolute file path. Return null if the file doesn't exists
* @param bool $loadFromDatabase
* @return string
*/
public function getAbsoluteFilePath($loadFromDatabase = false)
{
$fileName = $this->fileName;
if ($loadFromDatabase) {
$em = Database::getManager();
//Load the real filename just if exists
if (isset($this->exeId, $this->userId, $this->id, $this->sessionId, $this->course['real_id'])) {
$result = $em
->getRepository('ChamiloCoreBundle:TrackEAttempt')
->findOneBy([
'exeId' => $this->exeId,
'userId' => $this->userId,
'questionId' => $this->id,
'sessionId' => $this->sessionId,
'cId' => $this->course['real_id']
]);
if (!$result) {
return null;
}
return $this->storePath . $result->getFilename();
}
}
foreach ($this->available_extensions as $extension) {
if (!is_file($this->storePath . $fileName . ".$extension.$extension")) {
continue;
}
return "{$this->storePath}$fileName.$extension.$extension";
}
return null;
}
/**
* Get the URL for the audio file. Return null if the file doesn't exists
* @return string
*/
public function getFileUrl()
{
$filePath = $this->getAbsoluteFilePath();
if (empty($filePath)) {
return null;
}
return str_replace(
api_get_path(SYS_COURSE_PATH),
api_get_path(WEB_COURSE_PATH),
$filePath
);
}
/**
* Tricky stuff to deal with the feedback = 0 in exercises (all question per page)
* @param $exe_id integer
*/
public function replaceWithRealExe($exe_id)
{
$filename = null;
//ugly fix
foreach ($this->available_extensions as $extension) {
$items = explode('-', $this->fileName);
$items[5] = 'temp_exe';
$filename = implode('-', $items);
if (is_file($this->storePath . $filename . '.' . $extension)) {
$old_name = $this->storePath . $filename . '.' . $extension;
$items = explode('-', $this->fileName);
$items[5] = $exe_id;
$filename = $filename = implode('-', $items);
$new_name = $this->storePath . $filename . '.' . $extension;
rename($old_name, $new_name);
break;
}
}
}
}

@ -1357,7 +1357,7 @@ abstract class Question
*/
public static function get_question_type($type)
{
if ($type == ORAL_EXPRESSION && api_get_setting('enable_nanogong') != 'true') {
if ($type == ORAL_EXPRESSION && api_get_setting('enable_record_audio') !== 'true') {
return null;
}
return self::$questionTypes[$type];
@ -1368,7 +1368,7 @@ abstract class Question
*/
public static function get_question_type_list()
{
if (api_get_setting('enable_nanogong') != 'true') {
if (api_get_setting('enable_record_audio') !== 'true') {
self::$questionTypes[ORAL_EXPRESSION] = null;
unset(self::$questionTypes[ORAL_EXPRESSION]);
}

@ -1,98 +0,0 @@
<?php
/* For licensing terms, see /license.txt */
/**
* Responses to AJAX calls
*/
require_once '../global.inc.php';
//@todo for some reason nanogong doesn't like this variables
$action = $_REQUEST['a'];
unset($_REQUEST['a']);
$js_path = api_get_path(WEB_LIBRARY_PATH).'javascript/';
//Fix in order to add the exe_id
if (isset($_REQUEST['from_htaccess'])) {
if (isset($_REQUEST['file'])) {
$fileinfo = pathinfo($_REQUEST['file']);
$items = explode('-', $fileinfo['filename']);
$_REQUEST['exe_id'] = $items[5];
}
}
$nano = new Nanogong($_REQUEST);
$is_nano = false;
if (isset($_REQUEST['is_nano'])) {
$is_nano = true;
}
switch ($action) {
case 'get_file':
if ($nano->get_param_value('user_id') == api_get_user_id() || api_is_allowed_to_edit()) {
$file_path = $nano->load_filename_if_exists();
if ($file_path) {
$info = pathinfo($file_path);
$user_info = api_get_user_info($nano->params['user_id']);
$name = get_lang('Quiz').'-'.$user_info['firstname'].'-'.$user_info['lastname'].'.'.$info['extension'];
$download = true;
if (isset($_REQUEST['download']) && $_REQUEST['download'] == 0) {
$download = false;
}
DocumentManager::file_send_for_download($file_path, $download);
exit;
}
}
break;
case 'show_audio':
if (!$is_nano) {
echo $nano->return_js($_REQUEST);
}
echo $nano->show_audio_file($is_nano);
break;
case 'delete':
$return = $nano->delete_files();
if ($return == 1) {
//cant' do this because the post that nano send doesnt take into account the session
Display::display_confirmation_message(get_lang('FileDeleted'));
} else {
Display::display_confirmation_message(get_lang('FileNotFound'));
}
break;
case 'show_form':
api_protect_course_script(true);
Display::display_reduced_header();
echo $nano->return_js($_REQUEST);
echo $nano->return_form();
break;
case 'save_file':
// User access same as upload.php
$return = $nano->upload_file($is_nano);
if ($is_nano) {
//nano looks for numbers
if ($return == 1) {
//cant' do this because the post that nano send doesnt take into account the session
echo 1; //Display::display_confirmation_message(get_lang('UplUploadSucceeded'));
} else {
echo 0;
//Display::display_warning_message(get_lang('UplUnableToSaveFileFilteredExtension'));
}
} else {
Display::display_reduced_header();
echo $nano->return_js($_REQUEST);
//normal form
if ($return == 1) {
//cant' do this because the post that nano send doesnt take into account the session
$message = Display::return_message(get_lang('UplUploadSucceeded'), 'confirm');
} else {
$message = Display::return_message(get_lang('UplUnableToSaveFileFilteredExtension'), 'warning');
}
echo $nano->return_form($message);
}
break;
default:
echo '';
}
exit;

@ -1,28 +0,0 @@
<?php
/* For license terms, see /license.txt */
/**
* AJAX Call for wamirecorder
*/
require_once '../global.inc.php';
$action = $_REQUEST['a'];
//$js_path = api_get_path(WEB_LIBRARY_PATH) . 'javascript/';
$courseId = isset($_REQUEST['course_id']) ? $_REQUEST['course_id'] : 0;
$sessionId = isset($_REQUEST['session_id']) ? $_REQUEST['session_id'] : 0;
$userId = isset($_REQUEST['user_id']) ? $_REQUEST['user_id'] : 0;
$exerciseId = isset($_REQUEST['exercise_id']) ? $_REQUEST['exercise_id'] : 0;
$questionId = isset($_REQUEST['question_id']) ? $_REQUEST['question_id'] : 0;
$exeId = isset($_REQUEST['exe_id']) ? $_REQUEST['exe_id'] : 0;
$wamiRecorder = new WamiRecorder($courseId, $sessionId, $userId, $exerciseId, $questionId, $exeId);
switch ($action) {
case 'show_form':
api_protect_course_script(true);
Display::display_reduced_header();
$wamiRecorder->showJS();
$wamiRecorder->showForm();
break;
}

@ -1,386 +0,0 @@
<?php
/* For license terms, see /license.txt */
class WamiRecorder
{
public $courseInfo;
public $userId;
public $exeId;
public $exerciseId;
public $questionId;
public $courseId;
public $sessionId;
public $storePath;
public $fileName;
public $filePath;
public $canEdit;
/**
* WamiRecorder constructor.
* @param int $courseId
* @param int $sessionId
* @param int $userId
* @param int $exerciseId
* @param int $questionId
* @param int $exeId
*/
public function __construct($courseId = 0, $sessionId = 0, $userId = 0, $exerciseId = 0, $questionId = 0, $exeId = 0)
{
if (!empty($courseId)) {
$this->courseId = intval($courseId);
} else {
$this->courseId = api_get_course_int_id();
}
$this->courseInfo = api_get_course_info_by_id($this->courseId);
if (!empty($sessionId)) {
$this->sessionId = intval($sessionId);
} else {
$this->sessionId = api_get_session_id();
}
if (!empty($userId)) {
$this->userId = intval($userId);
} else {
$this->userId = api_get_user_id();
}
$this->exerciseId = 0;
if (!empty($exerciseId)) {
$this->exerciseId = intval($exerciseId);
}
$this->questionId = 0;
if (!empty($questionId)) {
$this->questionId = intval($questionId);
}
$this->canEdit = false;
if (api_is_allowed_to_edit()) {
$this->canEdit = true;
} else {
if ($this->userId == api_get_user_id()) {
$this->canEdit = true;
}
}
$this->exeId = intval($exeId);
$this->storePath = $this->generateDirectory();
$this->fileName = $this->generateFileName();
$this->filePath = $this->storePath . $this->fileName;
}
/**
* Generate the file name
* @return string
*/
private function generateFileName()
{
return implode(
'-',
array(
$this->courseId,
$this->sessionId,
$this->userId,
$this->exerciseId,
$this->questionId,
$this->exeId
)
);
}
/**
* Generate the necessary directory for audios. If them not exists, are created
* @return string
*/
private function generateDirectory()
{
$this->storePath = api_get_path(SYS_COURSE_PATH) . $this->courseInfo['path'] . '/exercises/';
if (!is_dir($this->storePath)) {
mkdir($this->storePath);
}
if (!is_dir($this->storePath . $this->sessionId)) {
mkdir($this->storePath . $this->sessionId);
}
if (!empty($this->exerciseId) && !is_dir($this->storePath . $this->sessionId . '/' . $this->exerciseId)) {
mkdir($this->storePath . $this->sessionId . '/' . $this->exerciseId);
}
if (!empty($this->questionId) && !is_dir($this->storePath . $this->sessionId . '/' . $this->exerciseId . '/' . $this->questionId)) {
mkdir($this->storePath . $this->sessionId . '/' . $this->exerciseId . '/' . $this->questionId);
}
if (!empty($this->userId) && !is_dir($this->storePath . $this->sessionId . '/' . $this->exerciseId . '/' . $this->questionId . '/' . $this->userId)) {
mkdir($this->storePath . $this->sessionId . '/' . $this->exerciseId . '/' . $this->questionId . '/' . $this->userId);
}
return $this->storePath .= implode(
'/',
array(
$this->sessionId,
$this->exerciseId,
$this->questionId,
$this->userId
)
) . '/';
}
/**
* Generate a relative directory path
* @return string
*/
private function generateRelativeDirectory()
{
return implode(
'/',
array(
$this->sessionId,
$this->exerciseId,
$this->questionId,
$this->userId
)
);
}
/**
* Get necessary params for Flash
* @return string
*/
private function getParams()
{
return http_build_query(array(
'course_id' => $this->courseId,
'session_id' => $this->sessionId,
'exercise_id' => $this->exerciseId,
'exe_id' => $this->exeId,
'question_id' => $this->questionId,
'user_id' => $this->userId
));
}
/**
* Print the JavaScript for Wami
*/
public function showJS()
{
$wamidir = '/../exercises/' . $this->generateRelativeDirectory() . '/';
$wamiurlplay = api_get_path(WEB_COURSE_PATH) . api_get_course_path($this->courseInfo['code']) . '/exercises/' . $this->generateRelativeDirectory();
$wamiuserid = $this->userId;
echo '
<!-- swfobject is a commonly used library to embed Flash content https://ajax.googleapis.com/ajax/libs/swfobject/2.2/ -->
<script type="text/javascript" src="' . api_get_path(WEB_LIBRARY_PATH) . 'swfobject/swfobject.js"></script>
<!-- Setup the recorder interface -->
<script type="text/javascript" src="' . api_get_path(WEB_LIBRARY_PATH) . 'wami-recorder/recorder.js"></script>
<!-- GUI code... take it or leave it -->
<script type="text/javascript" src="' . api_get_path(WEB_LIBRARY_PATH) . 'wami-recorder/gui.js"></script>
<script type="text/javascript">
function newNameRecord() {
location.reload(true)
}
function setupRecorder() {
document.getElementById(\'audio_button\').style.display = \'none\';
Wami.setup({
id : \'wami\',
onReady : setupGUI
});
}
function setupGUI() {
var waminame = \'' . $this->fileName . '.wav\';
var waminame_play=waminame;
var gui = new Wami.GUI({
id : \'wami\',
singleButton : true,
recordUrl: \'' . api_get_path(WEB_AJAX_PATH) . 'record_audio_wami.ajax.php?waminame=\' + waminame + \'&wamidir=' . $wamidir . '&wamiuserid=' . $wamiuserid . '\',
playUrl: \'' . $wamiurlplay . '\' + waminame_play,
buttonUrl: \'' . api_get_path(WEB_LIBRARY_PATH) . 'wami-recorder/buttons.png\',
swfUrl: \'' . api_get_path(WEB_LIBRARY_PATH) . 'wami-recorder/Wami.swf\'
});
gui.setPlayEnabled(false);
}
</script>
';
}
/**
* Show the form controls to Wami
*/
public function showForm()
{
echo '
<div id="wami" style="padding-top:10px;"></div>
<div align="center" style="padding-top:150px;">
<form name="form_wami_recorder">
<button type="button" value="" onclick="setupRecorder()" id="audio_button" />' . get_lang('Activate') . '</button>
<button type="button" value="" onclick="newNameRecord()" id="new_name" />' . get_lang('Reload') . '</button>
</form>
</div>
';
}
/**
* Get a HTML button for record answer
* @return string
*/
public function getButton()
{
$params_strings = $this->getParams();
$params_strings .= '&a=show_form';
$html = "
<script>
$(document).on('ready', function () {
$('#btn-record_answer').on('click', function (e) {
e.preventDefault();
var url = '" . api_get_path(WEB_AJAX_PATH) . "wamirecorder.ajax.php?" . $params_strings . "',
iframe = $('<iframe>').attr({
hspace: 0,
src: url,
frameborder: 0,
width: '100%',
height: 400
});
var modalDialog = $('#global-modal').find('.modal-dialog'),
modalTitle = '" . get_lang('RecordAnswer') ."';
modalDialog
.removeClass('modal-lg modal-sm')
.css('width', '500px')
$('#global-modal').find('.modal-title').text(modalTitle);
$('#global-modal').find('.modal-body').html(iframe);
$('#global-modal').modal('show');
});
});
</script>
";
$html .= '<br />'
. Display::toolbarButton(
get_lang('RecordAnswer'),
api_get_path(WEB_AJAX_PATH) . 'wamirecorder.ajax.php?' . $params_strings . http_build_query([
'a' => 'show_form',
'TB_iframe' => 'true',
'data-height' => 400,
'data-width' => 500
]),
'microphone',
'primary',
['id' => 'btn-record_answer']
)
. '<br /><br />' . Display::return_message(get_lang('UseTheMessageBelowToAddSomeComments'));
return $html;
}
/**
* Show the audio file
* @return null|string
*/
public function showAudioFile()
{
$filePath = $this->loadFileIfExists();
if (empty($filePath)) {
return null;
}
$url = $this->getPublicURL();
$params = array(
'url' => $url,
'extension' => 'wav',
'count' => 1
);
$jquery = DocumentManager::generate_jplayer_jquery($params);
$jsPath = api_get_path(WEB_LIBRARY_PATH) . 'javascript/';
$actions = Display::url(Display::return_icon('save.png', get_lang('Download'), array(), ICON_SIZE_SMALL), $url, array('target' => '_blank'));
$html = '<link rel="stylesheet" href="' . $jsPath . 'jquery-jplayer/skins/blue/jplayer.blue.monday.css" type="text/css">';
//$html .= '<link rel="stylesheet" href="' . $jsPath . 'jquery-jplayer/skins/chamilo/jplayer.blue.monday.css" type="text/css">';
$html .= '<script type="text/javascript" src="' . $jsPath . 'jquery-jplayer/jquery.jplayer.min.js"></script>';
$html .= '<div class="nanogong_player"></div>';
$html .= '<br /><div class="action_player">' . $actions . '</div><br /><br /><br />';
$html .= '<script>
$(document).ready( function() {
//Experimental changes to preview mp3, ogg files
' . $jquery . '
});
</script>';
$html .= DocumentManager::generate_media_preview(1, 'advanced');
return $html;
}
/**
* Get the audio file
* @param bool $loadFromDatabase
* @return null|string
*/
public function loadFileIfExists($loadFromDatabase = false)
{
$fileName = $this->fileName . '.wav';
//temp_exe
if ($loadFromDatabase) {
//Load the real filename just if exists
if (isset($this->exeId) && isset($this->userId) && isset($this->questionId) && isset($this->sessionId) && isset($this->courseId)) {
$attempt_table = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
$sql = "SELECT filename FROM $attempt_table
WHERE exe_id = " . $this->exeId . " AND
user_id = " . $this->userId . " AND
question_id = " . $this->questionId . " AND
session_id = " . $this->sessionId . " AND
course_code = '" . $this->courseInfo['code'] . "' LIMIT 1";
$result = Database::query($sql);
$result = Database::fetch_row($result, 'ASSOC');
if (isset($result) && isset($result[0]) && !empty($result[0])) {
$fileName = $result[0];
}
}
}
if (is_file($this->storePath . $fileName)) {
return $this->storePath . $fileName;
}
return null;
}
/**
* Get a public URL
* @return string
*/
public function getPublicURL()
{
$url = api_get_path(WEB_COURSE_PATH) . $this->courseInfo['path'] . '/exercises/';
$url .= $this->generateRelativeDirectory() . '/';
$url .= $this->fileName . '.wav';
return $url;
}
}

@ -5318,7 +5318,7 @@ class DocumentManager
if ($filetype == 'file') {
// Sound preview with jplayer
if (preg_match('/mp3$/i', urldecode($checkExtension)) ||
(preg_match('/wav$/i', urldecode($checkExtension)) && !preg_match('/_chnano_.wav$/i', urldecode($url))) ||
(preg_match('/wav$/i', urldecode($checkExtension))) ||
preg_match('/ogg$/i', urldecode($checkExtension))
) {
return '<span style="float:left" ' . $visibility_class . '>' .
@ -5333,12 +5333,7 @@ class DocumentManager
preg_match('/jpg$/i', urldecode($checkExtension)) ||
preg_match('/jpeg$/i', urldecode($checkExtension)) ||
preg_match('/bmp$/i', urldecode($checkExtension)) ||
preg_match('/svg$/i', urldecode($checkExtension)) ||
(
preg_match('/wav$/i', urldecode($checkExtension)) &&
preg_match('/_chnano_.wav$/i', urldecode($checkExtension)) &&
api_get_setting('enable_nanogong') == 'true'
)
preg_match('/svg$/i', urldecode($checkExtension))
) {
// Simpler version of showinframesmin.php with no headers
$url = 'show_content.php?' . api_get_cidreq() . '&id=' . $document_data['id'];
@ -5388,7 +5383,7 @@ class DocumentManager
if ($filetype == 'file') {
//Sound preview with jplayer
if (preg_match('/mp3$/i', urldecode($checkExtension)) ||
(preg_match('/wav$/i', urldecode($checkExtension)) && !preg_match('/_chnano_.wav$/i', urldecode($url))) ||
(preg_match('/wav$/i', urldecode($checkExtension))) ||
preg_match('/ogg$/i', urldecode($checkExtension))) {
$sound_preview = DocumentManager::generate_media_preview($counter);
@ -5401,12 +5396,7 @@ class DocumentManager
preg_match('/jpg$/i', urldecode($checkExtension)) ||
preg_match('/jpeg$/i', urldecode($checkExtension)) ||
preg_match('/bmp$/i', urldecode($checkExtension)) ||
preg_match('/svg$/i', urldecode($checkExtension)) ||
(
preg_match('/wav$/i', urldecode($checkExtension)) &&
preg_match('/_chnano_.wav$/i', urldecode($checkExtension)) &&
api_get_setting('enable_nanogong') == 'true'
)
preg_match('/svg$/i', urldecode($checkExtension))
) {
$url = 'showinframes.php?' . api_get_cidreq() . '&id=' . $document_data['id'];
return '<a href="' . $url . '" title="' . $tooltip_title_alt . '" ' . $visibility_class . ' style="float:left">' .
@ -5426,7 +5416,7 @@ class DocumentManager
if ($filetype == 'file') {
// Sound preview with jplayer
if (preg_match('/mp3$/i', urldecode($checkExtension)) ||
(preg_match('/wav$/i', urldecode($checkExtension)) && !preg_match('/_chnano_.wav$/i', urldecode($url))) ||
(preg_match('/wav$/i', urldecode($checkExtension))) ||
preg_match('/ogg$/i', urldecode($checkExtension))) {
$sound_preview = DocumentManager::generate_media_preview($counter);
@ -5441,12 +5431,7 @@ class DocumentManager
preg_match('/jpg$/i', urldecode($checkExtension)) ||
preg_match('/jpeg$/i', urldecode($checkExtension)) ||
preg_match('/bmp$/i', urldecode($checkExtension)) ||
preg_match('/svg$/i', urldecode($checkExtension)) ||
(
preg_match('/wav$/i', urldecode($checkExtension)) &&
preg_match('/_chnano_.wav$/i', urldecode($checkExtension)) &&
api_get_setting('enable_nanogong') == 'true'
)
preg_match('/svg$/i', urldecode($checkExtension))
) {
$url = 'showinframes.php?' . api_get_cidreq() . '&id=' . $document_data['id']; //without preview
return '<a href="' . $url . '" title="' . $tooltip_title_alt . '" ' . $visibility_class . ' style="float:left">' .
@ -5479,12 +5464,7 @@ class DocumentManager
if ($type == 'file') {
$icon = choose_image($basename);
if (preg_match('/_chnano_.wav$/i', $basename)) {
$icon = "jplayer_play.png";
$basename = 'wav' . ' ' . '(Nanogong)';
} else {
$basename = substr(strrchr($basename, '.'), 1);
}
$basename = substr(strrchr($basename, '.'), 1);
} else {
if ($path == '/shared_folder') {
$icon = 'folder_users.gif';

@ -406,7 +406,7 @@ class Event
* @param integer Position
* @param integer Exercise ID (from c_quiz)
* @param bool update results?
* @param string Filename (for audio answers - using nanogong)
* @param $fileName string Filename (for audio answers - using nanogong)
* @param integer User ID The user who's going to get this score. Default value of null means "get from context".
* @param integer Course ID (from the "id" column of course table). Default value of null means "get from context".
* @param integer Session ID (from the session table). Default value of null means "get from context".
@ -422,7 +422,7 @@ class Event
$position,
$exercise_id = 0,
$updateResults = false,
$nano = null,
$fileName = null,
$user_id = null,
$course_id = null,
$session_id = null,
@ -479,11 +479,6 @@ class Event
$answer = 0;
}
$file = '';
if (isset($nano)) {
$file = Database::escape_string(basename($nano->load_filename_if_exists(false)));
}
$session_id = api_get_session_id();
if (!empty($question_id) && !empty($exe_id) && !empty($user_id)) {
@ -496,7 +491,7 @@ class Event
'session_id' => $session_id,
'position' => $position,
'tms' => $now,
'filename' => $file,
'filename' => !empty($fileName) ? basename($fileName) : $fileName,
);
// Check if attempt exists.

@ -166,31 +166,27 @@ class ExerciseLib
$s .= $form->returnForm();
} elseif ($answerType == ORAL_EXPRESSION) {
// Add nanog
if (api_get_setting('enable_nanogong') == 'true') {
if (api_get_setting('enable_record_audio') == 'true') {
//@todo pass this as a parameter
global $exercise_stat_info, $exerciseId, $exe_id;
if (!empty($exercise_stat_info)) {
$wamiRecorder = new WamiRecorder(
0,
0,
0,
$objQuestionTmp->initFile(
api_get_session_id(),
api_get_user_id(),
$exercise_stat_info['exe_exo_id'],
$questionId,
$exercise_stat_info['exe_id']
);
} else {
$wamiRecorder = new WamiRecorder(
0,
0,
0,
$objQuestionTmp->initFile(
api_get_session_id(),
api_get_user_id(),
$exerciseId,
$questionId,
'temp_exe'
);
}
echo $wamiRecorder->getButton();
echo $objQuestionTmp->returnRecorder();
}
$form = new FormValidator('free_choice_'.$questionId);

@ -117,10 +117,14 @@ class ExerciseShowFunctions
}
}
public static function display_oral_expression_answer($feedback_type, $answer, $id, $questionId, $nano = null)
public static function display_oral_expression_answer($feedback_type, $answer, $id, $questionId, $fileUrl = null)
{
if (isset($nano)) {
echo $nano->showAudioFile();
if (isset($fileUrl)) {
echo '
<tr>
<td><audio src="' . $fileUrl . '" controls></audio></td>
</tr>
';
}
if (empty($id)) {

@ -1,670 +0,0 @@
<?php
/* For licensing terms, see /license.txt */
/**
* Class Nanogong
*
* Files are saved in the path:
* courses/XXX/exercises/(session_id)/(exercise_id)/(question_id)/(user_id)/
*
* The file name is composed with:
* (course_id)/(session_id)/(user_id)/(exercise_id)/(question_id)/(exe_id).wav|mp3|ogg
*
*
*/
class Nanogong
{
public $filename;
public $store_filename;
public $store_path;
public $params;
public $can_edit = false;
public $course_id;
public $session_id;
public $exercise_id;
public $question_id;
public $user_id;
public $course_info;
/* Files allowed to upload */
public $available_extensions = array('mp3', 'wav', 'ogg');
/**
* @param array $params
*/
public function __construct($params = array())
{
$this->set_parameters($params);
}
/**
* @return bool
*/
public function create_user_folder()
{
//COURSE123/exercises/session_id/exercise_id/question_id/user_id
if (empty($this->store_path)) {
return false;
}
// Trying to create the courses/COURSE123/exercises/ dir just in case.
$directoryPermissions = api_get_permissions_for_new_directories();
if (!is_dir($this->store_path)) {
mkdir($this->store_path, $directoryPermissions);
}
if (!is_dir($this->store_path.$this->session_id)) {
mkdir($this->store_path.$this->session_id, $directoryPermissions);
}
if (!is_dir($this->store_path.$this->session_id.'/'.$this->exercise_id)) {
mkdir($this->store_path.$this->session_id.'/'.$this->exercise_id, $directoryPermissions);
}
if (!is_dir($this->store_path.$this->session_id.'/'.$this->exercise_id.'/'.$this->question_id)
) {
mkdir($this->store_path.$this->session_id.'/'.$this->exercise_id.'/'.$this->question_id, $directoryPermissions);
}
if (!empty($this->user_id) &&
!is_dir($this->store_path.$this->session_id.'/'.$this->exercise_id.'/'.$this->question_id.'/'.$this->user_id)
) {
mkdir($this->store_path.$this->session_id.'/'.$this->exercise_id.'/'.$this->question_id.'/'.$this->user_id, $directoryPermissions);
}
}
/**
* Setting parameters: course id, session id, etc
* @param array
*/
public function set_parameters($params = array())
{
// Setting course id
if (isset($params['course_id'])) {
$this->course_id = intval($params['course_id']);
} else {
$this->course_id = $params['course_id'] = api_get_course_int_id();
}
//Setting course info
if (isset($this->course_id)) {
$this->course_info = api_get_course_info_by_id($this->course_id);
}
//Setting session id
if (isset($params['session_id'])) {
$this->session_id = intval($params['session_id']);
} else {
$this->session_id = $params['session_id'] = api_get_session_id();
}
//Setting user ids
if (isset($params['user_id'])) {
$this->user_id = intval($params['user_id']);
} else {
$this->user_id = $params['user_id'] = api_get_user_id();
}
//Setting user ids
if (isset($params['exercise_id'])) {
$this->exercise_id = intval($params['exercise_id']);
} else {
$this->exercise_id = 0;
}
//Setting user ids
if (isset($params['question_id'])) {
$this->question_id = intval($params['question_id']);
} else {
$this->question_id = 0;
}
$this->can_edit = false;
if (api_is_allowed_to_edit()) {
$this->can_edit = true;
} else {
if ($this->user_id == api_get_user_id()) {
$this->can_edit = true;
}
}
// Settings the params array
$this->params = $params;
$this->store_path = api_get_path(SYS_COURSE_PATH).$this->course_info['path'].'/exercises/';
$this->create_user_folder();
$this->store_path = $this->store_path.implode('/', array($this->session_id, $this->exercise_id, $this->question_id, $this->user_id)).'/';
$this->filename = $this->generate_filename();
$this->store_filename = $this->store_path.$this->filename;
}
/**
* Generates the filename with the next format:
* (course_id)/(session_id)/(user_id)/(exercise_id)/(question_id)/(exe_id)
*
* @return string
*/
public function generate_filename()
{
if (!empty($this->params)) {
//filename
//course_id/session_id/user_id/exercise_id/question_id/exe_id
$filename_array = array(
$this->params['course_id'],
$this->params['session_id'],
$this->params['user_id'],
$this->params['exercise_id'],
$this->params['question_id'],
$this->params['exe_id']
);
return implode('-', $filename_array);
} else {
return api_get_unique_id();
}
}
/**
* Delete audio file
* @return int
*/
public function delete_files()
{
$delete_found = 0;
if ($this->can_edit) {
$file = $this->load_filename_if_exists();
$path_info = pathinfo($file);
foreach ($this->available_extensions as $extension) {
$file_to_delete = $path_info['dirname'].'/'.$path_info['filename'].'.'.$extension;
if (is_file($file_to_delete)) {
unlink($file_to_delete);
$delete_found = 1;
}
}
}
return $delete_found;
}
/**
*
* Tricky stuff to deal with the feedback = 0 in exercises (all question per page)
* @param int $exe_id
*/
public function replace_with_real_exe($exe_id)
{
$filename = null;
//@ugly fix
foreach($this->available_extensions as $extension) {
$items = explode('-', $this->filename);
$items[5] = 'temp_exe';
$filename = implode('-', $items);
if (is_file($this->store_path.$filename.'.'.$extension)) {
$old_name = $this->store_path.$filename.'.'.$extension;
$items = explode('-', $this->filename);
$items[5] = $exe_id;
$filename = $filename = implode('-', $items);
$new_name = $this->store_path.$filename.'.'.$extension;
rename($old_name, $new_name);
break;
}
}
}
/**
* @param bool $load_from_database
* @return null|string
*/
public function load_filename_if_exists($load_from_database = false)
{
$filename = null;
//@ugly fix
foreach($this->available_extensions as $extension) {
if (is_file($this->store_path.$this->filename.'.'.$extension)) {
$filename = $this->filename.'.'.$extension;
break;
}
}
// temp_exe
if ($load_from_database) {
//Load the real filename just if exists
if (isset($this->params['exe_id']) && isset($this->params['user_id']) &&
isset($this->params['question_id']) && isset($this->params['session_id']) && isset($this->params['course_id'])
) {
$attempt_table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
$sql = "SELECT filename FROM $attempt_table
WHERE
exe_id = ".$this->params['exe_id']." AND
user_id = ".$this->params['user_id']." AND
question_id = ".$this->params['question_id']." AND
session_id = ".$this->params['session_id']." AND
course_code = '".$this->course_info['code']."'
LIMIT 1";
$result = Database::query($sql);
$result = Database::fetch_row($result,'ASSOC');
if (isset($result) && isset($result[0]) && !empty($result[0])) {
$filename = $result[0];
}
}
}
if (is_file($this->store_path.$filename)) {
return $this->store_path.$filename;
}
return null;
}
/**
*
* Get the URL of the file
* path courses/XXX/exercises/(session_id)/(exercise_id)/(question_id)/(user_id)/
* @param int $force_download
*
* @return string
*/
public function get_public_url($force_download = 0)
{
$params = $this->get_params();
$filename = basename($this->load_filename_if_exists());
$url = api_get_path(WEB_COURSE_PATH).$this->course_info['path'].'/exercises/'.$params['session_id'].'/'.$params['exercise_id'].'/'.$params['question_id'].'/'.$params['user_id'].'/'.$filename;
return $url;
}
/**
* Uploads the nanogong wav file
* @param bool
*/
public function upload_file($is_nano = false)
{
if (!empty($_FILES)) {
$upload_ok = process_uploaded_file($_FILES['file'], false);
if (!is_uploaded_file($_FILES['file']['tmp_name'])) {
return 0;
}
if ($upload_ok) {
// Check if there is enough space to save the file
if (!DocumentManager::enough_space($_FILES['file']['size'], DocumentManager::get_course_quota())) {
return 0;
}
//first we delete everything before uploading the file
$this->delete_files();
//Reload the filename variable
$file_name = add_ext_on_mime($_FILES['file']['name'], $_FILES['file']['type']);
$file_name = strtolower($file_name);
$file_info = pathinfo($file_name);
if ($is_nano == true) {
$file_info['extension'] = 'wav';
}
$file_name = $this->filename.'.'.$file_info['extension'];
if (in_array($file_info['extension'], $this->available_extensions)) {
if (move_uploaded_file($_FILES['file']['tmp_name'], $this->store_path.$file_name)) {
$this->store_filename = $this->store_path.$file_name;
return 1;
}
}
}
}
return 0;
}
/**
* Show the audio file + a button to download
* @param bool
*/
public function show_audio_file($show_delete_button = false)
{
$html = '';
$file_path = $this->load_filename_if_exists();
if (!empty($file_path)) {
$url = $this->get_public_url(true);
$actions = Display::url(Display::return_icon('save.png', get_lang('Download'), array(), ICON_SIZE_SMALL), $url, array('target'=>'_blank'));
$download_button = Display::url(get_lang('Download'), $url, array('class' =>'btn btn-default'));
if ($show_delete_button) {
$actions .= ' '.Display::url(Display::return_icon('delete.png', get_lang('Delete'), array(), ICON_SIZE_SMALL), "#", array('onclick'=>'delete_file();'));
}
$basename = basename($file_path);
$path_info = pathinfo($basename);
if ($path_info['extension'] == 'wav') {
$html .= '<script>
$(document).ready( function() {
var java_enabled = navigator.javaEnabled();
if (java_enabled) {
$("#nanogong_warning").hide();
$("#nanogong_player_id").show();
} else {
$("#nanogong_warning").show();
$("#nanogong_player_id").hide();
}
});
</script>';
$html .= '<div id="nanogong_player_id" class="nanogong_player_container">';
$html .= '<div class="action_player">'.$actions.'</div>';
$html .= '<div class="nanogong_player">';
$html .= '<applet id="nanogong_player" archive="'.api_get_path(WEB_LIBRARY_PATH).'nanogong/nanogong.jar" code="gong.NanoGong" width="250" height="95" ALIGN="middle">';
$html .= '<param name="ShowRecordButton" value="false" />'; // default true
$html .= '<param name="ShowSaveButton" value="false" />'; //you can save in local computer | (default true)
//echo '<param name="ShowAudioLevel" value="false" />'; // it displays the audiometer | (default true)
$html .= '<param name="ShowTime" value="true" />'; // default false
$html .= '<param name="Color" value="#FFFFFF" />';
$html .= '<param name="ShowSpeedButton" value="false" />';
//echo '<param name="StartTime" value="10.5" />';
//echo '<param name="EndTime" value="65" />';
$html .= '<param name="AudioFormat" value="ImaADPCM" />';// ImaADPCM (more speed), Speex (more compression)|(default Speex)
//$html .= '<param name="AudioFormat" value="Speex" />';// ImaADPCM (more speed), Speex (more compression)|(default Speex)
//Quality for ImaADPCM (low 8000, medium 11025, normal 22050, hight 44100) OR Quality for Speex (low 8000, medium 16000, normal 32000, hight 44100) | (default 44100)
//echo '<param name="SamplingRate" value="32000" />';
//echo '<param name="MaxDuration" value="60" />';
$html .= '<param name="SoundFileURL" value="'.$url.'" />';//load a file |(default "")
$html .= '</applet>';
$html .= '</div>';
$html .= '</div>';
$html .= '<div id="nanogong_warning">'.Display::return_message(get_lang('BrowserDoesNotSupportNanogongPlayer'), 'warning').$download_button.'</div>';
} elseif(in_array($path_info['extension'],array('mp3', 'ogg','wav'))) {
$js_path = api_get_path(WEB_LIBRARY_PATH).'javascript/';
$html .= '<link rel="stylesheet" href="'.$js_path.'jquery-jplayer/skin/blue.monday/css/jplayer.blue.monday.css" type="text/css">';
$html .= '<script type="text/javascript" src="'.$js_path.'jquery-jplayer/jplayer/jquery.jplayer.min.js"></script>';
$html .= '<div class="nanogong_player"></div>';
$html .= '<br /><div class="action_player">'.$actions.'</div><br /><br /><br />';
$params = array(
'url' => $url,
'extension' =>$path_info['extension'],
'count'=> 1
);
$jquery = DocumentManager::generate_jplayer_jquery($params);
$html .= '<script>
$(document).ready( function() {
//Experimental changes to preview mp3, ogg files
'.$jquery.'
});
</script>';
$html .= DocumentManager::generate_media_preview(1, 'advanced');
}
}
return $html;
}
/*
var filename = document.getElementById("audio_title").value+".wav";
var filename = filename.replace(/\s/g, "_");//replace spaces by _
var filename = encodeURIComponent(filename);
var filepath="'.urlencode($filepath).'";
var dir="'.urlencode($dir).'";
var course_code="'.urlencode($course_code).'";
var urlnanogong="'.$url.'?filename="+filename+"&filepath="+filepath+"&dir="+dir+"&course_code="+course_code;
*/
/**
* Returns the nanogong javascript code
* @return string
*/
public function return_js()
{
$params = $this->get_params(true);
$url = api_get_path(WEB_AJAX_PATH).'nanogong.ajax.php?a=save_file&'.$params.'&is_nano=1';
$url_load_file = api_get_path(WEB_AJAX_PATH).'nanogong.ajax.php?a=show_audio&'.$params;
$url_delete = api_get_path(WEB_AJAX_PATH).'nanogong.ajax.php?a=delete&'.$params;
$js = '<script language="javascript">
//lang vars
var lang_no_applet = "'.get_lang('NanogongNoApplet').'";
var lang_record_before_save = "'.get_lang('NanogongRecordBeforeSave').'";
var lang_give_a_title = "'.get_lang('NanogongGiveTitle').'";
var lang_failed_to_submit = "'.get_lang('NanogongFailledToSubmit').'";
var lang_submitted = "'.get_lang('NanogongSubmitted').'";
var lang_deleted = "'.get_lang('Deleted').'";
var is_nano = 0;
function check_gong() {
//var record = document.getElementById("nanogong");
var recorder;
var java_enabled = navigator.javaEnabled()
return java_enabled;
}
function show_simple_upload_form() {
$("#no_nanogong_div").show();
//$("#nanogong_div").hide();
$("#preview").hide();
}
$(document).ready( function() {
$("#no_nanogong_div").hide();
$("#nanogong_div").hide();
var check_js = check_gong();
if (check_js == true) {
$("#nanogong_div").show();
$("#no_nanogong_div").hide();
is_nano = 1;
$(".nanogong_player").show();
} else {
$("#no_nanogong_div").show();
$("#nanogong_div").hide();
$(".nanogong_player").hide();
}
//show always the mp3/ogg upload form (for dev purposes)
//$("#no_nanogong_div").show();
//$("#nanogong_div").hide();
});
function delete_file() {
$.ajax({
url: "'.$url_delete.'",
success:function(data) {
$("#status_warning").hide();
$("#status_ok").hide();
$("#messages").html(data);
$("#messages").show();
$("#preview").hide();
}
});
}
function upload_file() {
$("#form_nanogong_simple").submit();
}
function send_voice() {
$("#status_warning").hide();
$("#status_ok").hide();
$("#messages").hide();
var check_js = check_gong();
var recorder = document.getElementById("nanogong");
if (!recorder || !check_js) {
//alert(lang_no_applet)
$("#status_warning").html(lang_no_applet);
$("#status_warning").show();
//Show form
$("#no_nanogong_div").show();
$("#nanogong_div").hide();
return false;
}
var duration = parseInt(recorder.sendGongRequest("GetMediaDuration", "audio")) || 0;
if (duration <= 0) {
$("#status_warning").html(lang_record_before_save);
$("#status_warning").show();
return false;
}
var applet = document.getElementById("nanogong");
var ret = applet.sendGongRequest("PostToForm", "'.$url.'", "file", "", "temp"); // PostToForm, postURL, inputname, cookie, filename
if (ret == 1) {
$("#status_ok").html(lang_submitted);
$("#status_ok").show();
$.ajax({
url:"'.$url_load_file.'&is_nano="+is_nano,
success: function(data){
$("#preview").html(data);
$("#preview").show();
}
});
} else {
//alert(lang_submitted+"\n"+ret);
$("#status_warning").html(lang_failed_to_submit);
$("#status_warning").show();
}
return false;
}
</script>';
return $js;
}
/**
* Returns the HTML form to upload a nano file or upload a file
* @param string
*/
public function return_form($message = null)
{
$params = $this->get_params(true);
$url = api_get_path(WEB_AJAX_PATH).'nanogong.ajax.php?a=save_file&'.$params;
//check browser support and load form
$array_browser = api_browser_support('check_browser');
$preview_file = $this->show_audio_file(true, true);
$preview_file = Display::div(
$preview_file,
array('id' => 'preview', 'style' => 'text-align:center; padding-left: 25px;')
);
$html = '<center>';
//Use normal upload file
$html .= Display::return_icon('microphone.png', get_lang('PressRecordButton'),'', ICON_SIZE_BIG);
$html .='<br />';
$html .= '<div id="nanogong_div">';
$html .= '<applet id="nanogong" archive="'.api_get_path(WEB_LIBRARY_PATH).'nanogong/nanogong.jar" code="gong.NanoGong" width="250" height="95" align="middle">';
//echo '<param name="ShowRecordButton" value="false" />'; // default true
// echo '<param name="ShowSaveButton" value="false" />'; //you can save in local computer | (default true)
$html .= '<param name="ShowSpeedButton" value="false" />'; // default true
//echo '<param name="ShowAudioLevel" value="false" />'; // it displays the audiometer | (default true)
$html .= '<param name="ShowTime" value="true" />'; // default false
$html .= '<param name="Color" value="#FFFFFF" />'; // default #FFFFFF
//echo '<param name="StartTime" value="10.5" />';
//echo '<param name="EndTime" value="65" />';
$html .= '<param name="AudioFormat" value="ImaADPCM" />';// ImaADPCM (more speed), Speex (more compression)|(default Speex)
//$html .= '<param name="AudioFormat" value="Speex" />';// ImaADPCM (more speed), Speex (more compression)|(default Speex)
//echo '<param name="SamplingRate" value="32000" />';//Quality for ImaADPCM (low 8000, medium 11025, normal 22050, hight 44100) OR Quality for Speex (low 8000, medium 16000, normal 32000, hight 44100) | (default 44100)
//echo '<param name="MaxDuration" value="60" />';
//echo '<param name="SoundFileURL" value="http://somewhere.com/mysoundfile.wav" />';//load a file |(default "")
$html .= '</applet>';
$html .= '<br /><br /><br />';
$html .= '<form name="form_nanogong_advanced">';
$html .= '<input type="hidden" name="is_nano" value="1">';
$html .= '<a href="#" class="btn btn-default" onclick="send_voice()" />'.get_lang('SendRecord').'</a>';
$html .= '</form></div>';
$html .= Display::url(get_lang('ProblemsRecordingUploadYourOwnAudioFile'), 'javascript:void(0)', array('onclick' => 'show_simple_upload_form();'));
$html .= '<br /><br /><div id="no_nanogong_div">';
//$html .= Display::return_message(get_lang('BrowserNotSupportNanogongSend'), 'warning');
$html .= '<form id="form_nanogong_simple" class="form-search" action="'.$url.'" name="form_nanogong" method="POST" enctype="multipart/form-data">';
$html .= '<input type="file" name="file">';
$html .= '<a href="#" class="btn btn-default" onclick="upload_file()" /><em class="fa fa-upload"></em> '.get_lang('UploadFile').'</a>';
$html .= '</form>';
$html .= '</div>';
$html .= '</center>';
$html .= '<div style="display:none" id="status_ok" class="confirmation-message"></div><div style="display:none" id="status_warning" class="warning-message"></div>';
$html .= '<div id="messages">'.$message.'</div>';
$html .= $preview_file;
return $html;
}
/**
* @param bool $return_as_query
* @return bool|string
*/
public function get_params($return_as_query = false)
{
if (empty($this->params)) {
return false;
}
if ($return_as_query) {
return http_build_query($this->params);
}
return $this->params;
}
/**
* @param $attribute
* @return mixed
*/
public function get_param_value($attribute)
{
if (isset($this->params[$attribute])) {
return $this->params[$attribute];
}
}
/**
* Show a button to load the form
* @return string
*/
public function show_button()
{
$params_string = $this->get_params(true);
$url = api_get_path(WEB_AJAX_PATH)
. 'nanogong.ajax.php?a=show_form&'
. $params_string
. '&TB_iframe=true';
$html = Display::url(
get_lang('RecordAnswer'),
$url,
[
'class' => 'btn btn-default ajax',
'data-title' => get_lang('RecordAnswer')
]
);
$html .= '<br /><br />'.Display::return_message(get_lang('UseTheMessageBelowToAddSomeComments'));
return $html;
}
}

@ -0,0 +1,139 @@
<div class="alert alert-warning">
<span class="fa fa-warning fa-fw" aria-hidden="true"></span> {{ 'WamiNeedFilename'|get_lang }}
</div>
<div id="record-audio-recordrtc" class="row text-center">
<form>
<div class="row">
<div class="col-sm-4 col-sm-offset-4">
<div class="form-group">
<span class="fa fa-microphone fa-5x fa-fw" aria-hidden="true"></span>
<span class="sr-only">{{ 'RecordAudio'|get_lang }}</span>
</div>
</div>
<div class="col-sm-12">
<div class="form-groups">
<button class="btn btn-primary" type="button" id="btn-start-record">
<span class="fa fa-circle fa-fw" aria-hidden="true"></span> {{ 'StartRecordingAudio'|get_lang }}
</button>
<button class="btn btn-success" type="button" id="btn-stop-record" disabled>
<span class="fa fa-square fa-fw" aria-hidden="true"></span> {{ 'StopRecordingAudio'|get_lang }}
</button>
</div>
</div>
</div>
</form>
</div>
<div class="row" id="record-audio-wami">
<div class="col-sm-4 col-sm-offset-4 text-center">
<div id="record-audio-wami-container" class="wami-container"></div>
</div>
</div>
<script>
$(document).on('ready', function () {
function useRecordRTC() {
$('#record-audio-recordrtc').show();
var mediaConstraints = {audio: true},
recordRTC = null,
btnStart = $('#btn-start-record'),
btnStop = $('#btn-stop-record');
btnStart.on('click', function () {
navigator.getUserMedia = navigator.getUserMedia ||
navigator.mozGetUserMedia ||
navigator.webkitGetUserMedia;
if (navigator.getUserMedia) {
navigator.getUserMedia(mediaConstraints, successCallback, errorCallback);
} else if (navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia(mediaConstraints)
.then(successCallback).error(errorCallback);
}
function successCallback(stream) {
recordRTC = RecordRTC(stream, {
numberOfAudioChannels: 1,
type: 'audio'
});
recordRTC.startRecording();
btnStop.prop('disabled', false);
btnStart.prop('disabled', true);
}
function errorCallback(error) {
alert(error.message);
}
});
btnStop.on('click', function () {
if (!recordRTC) {
return;
}
recordRTC.stopRecording(function (audioURL) {
var recordedBlob = recordRTC.getBlob(),
fileName = '{{ file_name }}',
fileExtension = '.' + recordedBlob.type.split('/')[1];
var formData = new FormData();
formData.append('audio_blob', recordedBlob, fileName + fileExtension);
formData.append('audio_dir', '{{ directory }}');
$.ajax({
url: '{{ _p.web_ajax }}record_audio_rtc.ajax.php',
data: formData,
processData: false,
contentType: false,
type: 'POST'
});
btnStop.prop('disabled', true);
btnStart.prop('disabled', false);
});
});
}
function useWami() {
$('#record-audio-wami').show();
Wami.setup({
id: "record-audio-wami-container",
onReady: setupGUI,
swfUrl: '{{ _p.web_lib }}wami-recorder/Wami.swf'
});
function setupGUI() {
var gui = new Wami.GUI({
id: 'record-audio-wami-container',
singleButton: true,
recordUrl: '{{ _p.web_ajax }}record_audio_wami.ajax.php?' + $.param({
waminame: '{{ file_name }}.wav',
wamidir: '{{ directory }}',
wamiuserid: {{ user_id }}
}),
buttonUrl: '{{ _p.web_lib }}wami-recorder/buttons.png',
buttonNoUrl: '{{ _p.web_img }}blank.gif'
}
);
gui.setPlayEnabled(false);
}
}
$('#record-audio-recordrtc, #record-audio-wami').hide();
var webRTCIsEnabled = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.getUserMedia ||
navigator.mediaDevices.getUserMedia;
if (webRTCIsEnabled) {
useRecordRTC();
return;
}
useWami();
});
</script>
Loading…
Cancel
Save