From cf51a862e7f0e26c6c1ac31082b75ae3a66987dc Mon Sep 17 00:00:00 2001 From: fusionate Date: Fri, 9 Feb 2024 13:14:22 -0700 Subject: [PATCH] CDR: Audio waveform generation integration. --- app/xml_cdr/waveform.php | 126 +++++++++++++++++++++++++++++++++++++++ app/xml_cdr/xml_cdr.php | 2 +- 2 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 app/xml_cdr/waveform.php diff --git a/app/xml_cdr/waveform.php b/app/xml_cdr/waveform.php new file mode 100644 index 0000000000..7704241fcd --- /dev/null +++ b/app/xml_cdr/waveform.php @@ -0,0 +1,126 @@ + + Portions created by the Initial Developer are Copyright (C) 2024 + the Initial Developer. All Rights Reserved. + + Contributor(s): + Mark J Crane +*/ + +//includes files + require_once dirname(__DIR__, 2) . "/resources/require.php"; + require_once "resources/check_auth.php"; + require_once "resources/classes/waveform.php"; + + use maximal\audio\Waveform; + +//check permisions + if (permission_exists('xml_cdr_recording_play')) { + //access granted + } + else { + echo "access denied"; + exit; + } + +//create the waveform file + if (is_uuid($_GET['id'])) { + + //get call recording details from database + $sql = "select call_recording_name, call_recording_path "; + if (!empty($_SESSION['call_recordings']['storage_type']['text']) && $_SESSION['call_recordings']['storage_type']['text'] == 'base64' && !empty($row['call_recording_base64'])) { + $sql = ", call_recording_base64 "; + } + $sql .= "from view_call_recordings "; + $sql .= "where call_recording_uuid = :call_recording_uuid "; + $parameters['call_recording_uuid'] = $_GET['id']; + $database = new database; + $row = $database->select($sql, $parameters, 'row'); + if (is_array($row) && @sizeof($row) != 0) { + $call_recording_name = $row['call_recording_name']; + $call_recording_path = $row['call_recording_path']; + if (!empty($_SESSION['call_recordings']['storage_type']['text']) && $_SESSION['call_recordings']['storage_type']['text'] == 'base64' && !empty($row['call_recording_base64'])) { + file_put_contents($call_recording_path.'/'.$call_recording_name, base64_decode($row['call_recording_base64'])); + } + } + unset($sql, $parameters); + + //build full path + $full_recording_path = $call_recording_path.'/'.$call_recording_name; + + //stream waveform file + if ($full_recording_path != '/' && file_exists($full_recording_path)) { + + //temporary waveform image filename + $temp_filename = 'waveform_'.$_GET['id'].'_'.rand(0000,9999).'.png'; + + //create temporary waveform image, if doesn't exist + if (file_exists($temp_filename)) { + $wf = true; + } + else { + //create temporary waveform image + $waveform = new Waveform($full_recording_path); + Waveform::$linesPerPixel = 1; // default: 8 + Waveform::$samplesPerLine = 512; // default: 512 + Waveform::$colorA = !empty($_SESSION['theme']['audio_player_waveform_color_a_leg']['text']) ? color_to_rgba_array($_SESSION['theme']['audio_player_waveform_color_a_leg']['text']) : [32,134,37,0.6]; // array rgba, left (a-leg) wave color + Waveform::$colorB = !empty($_SESSION['theme']['audio_player_waveform_color_b_leg']['text']) ? color_to_rgba_array($_SESSION['theme']['audio_player_waveform_color_b_leg']['text']) : [0,125,232,0.6]; // array rgba, right (b-leg) wave color + Waveform::$backgroundColor = !empty($_SESSION['theme']['audio_player_waveform_color_background']['text']) ? color_to_rgba_array($_SESSION['theme']['audio_player_waveform_color_background']['text']) : [0,0,0,0]; // array rgba, default: transparent + Waveform::$axisColor = !empty($_SESSION['theme']['audio_player_waveform_color_axis']['text']) ? color_to_rgba_array($_SESSION['theme']['audio_player_waveform_color_axis']['text']) : [0,0,0,0.3]; // array rgba + Waveform::$singlePhase = empty($_SESSION['theme']['audio_player_waveform_single_phase']['boolean']) || $_SESSION['theme']['audio_player_waveform_single_phase']['boolean'] !== 'true' ? false : true; // positive phase only - left (a-leg) top, right (b-leg) bottom + Waveform::$singleAxis = empty($_SESSION['theme']['audio_player_waveform_single_axis']['boolean']) || $_SESSION['theme']['audio_player_waveform_single_axis']['boolean'] !== 'false' ? true : false; // combine channels into single axis + $height = !empty($_SESSION['theme']['audio_player_waveform_height']['text']) && is_numeric(str_replace('px','',$_SESSION['theme']['audio_player_waveform_height']['text'])) ? 2.2 * (int) str_replace('px','',$_SESSION['theme']['audio_player_waveform_height']['text']) : null; + $wf = $waveform->getWaveform($temp_filename, 1600, $height ?? 180); // input: png filename returns boolean true/false, or 'base64' returns base64 string + } + + //stream image to browser + if ($wf === true && file_exists($temp_filename)) { + + ob_clean(); + $fd = fopen($temp_filename, 'rb'); + header("Content-Type: application/force-download"); + header("Content-Type: application/octet-stream"); + header("Content-Type: application/download"); + header("Content-Description: File Transfer"); + header("Content-Type: image/png"); + header('Content-Disposition: attachment; filename="'.$temp_filename.'"'); + header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1 + header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past + header("Content-Length: ".filesize($temp_filename)); + ob_clean(); + + fpassthru($fd); + + } + + } + + //if base64, remove temp recording file + if (!empty($_SESSION['call_recordings']['storage_type']['text']) && $_SESSION['call_recordings']['storage_type']['text'] == 'base64' && !empty($row['call_recording_base64'])) { + @unlink($full_recording_path); + } + unset($row); + + //delete temp waveform image + @unlink($temp_filename); + + } + +?> \ No newline at end of file diff --git a/app/xml_cdr/xml_cdr.php b/app/xml_cdr/xml_cdr.php index 7ee486fbac..b63f8ffbf7 100644 --- a/app/xml_cdr/xml_cdr.php +++ b/app/xml_cdr/xml_cdr.php @@ -772,7 +772,7 @@ //recording playback if (permission_exists('xml_cdr_recording_play')) { - $content .= "\n"; + $content .= "\n"; $content .= "\n"; // dummy row to maintain alternating background color } if (permission_exists('xml_cdr_details')) {