Projects (GanjooRazor -> DivanRazor, GanjoorService.sln -> DivanService.sln), files, folders, classes, namespaces, settings, API routes (/api/divan) and DB tables (Divan*). External addresses (ganjoor.net, github.com/ganjoor) unchanged. Migrations renamed consistently (no pending model changes); requires a fresh database. Upstream RUNNING_LOCALLY/SEMANTIC_SEARCH docs archived unmodified under docs/. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
310 lines
17 KiB
Plaintext
310 lines
17 KiB
Plaintext
@page
|
|
@model DivanRazor.Pages.AudioClipModel
|
|
@using DNTPersianUtils.Core
|
|
@{
|
|
Layout = null;
|
|
}
|
|
|
|
<!DOCTYPE html>
|
|
<html lang="ur-PK" dir="rtl">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<meta name="robots" content="noindex, nofollow" />
|
|
<title>
|
|
دیوان » نمایش خوانش
|
|
</title>
|
|
<link href="~/dist/skin/pink.flag/css/jplayer.pink.flag.min.css" rel="stylesheet" type="text/css" />
|
|
<link href="~/css/p8.css" asp-append-version="true" rel="stylesheet" type="text/css" />
|
|
<partial name="_DivanHead" />
|
|
<link rel="shortcut icon" href="/favicon.ico?version=1" type="image/x-icon" />
|
|
<link rel="search" type="application/opensearchdescription+xml" title="دیوان" href="/search.xml" />
|
|
<script>
|
|
function wpopen(macagna) {
|
|
window.open(macagna, '_blank', 'width=600,height=700,scrollbars=yes,status=yes');
|
|
}
|
|
</script>
|
|
</head>
|
|
<body>
|
|
@if (!string.IsNullOrEmpty(Model.LastError))
|
|
{
|
|
<p>@Model.LastError</p>
|
|
}
|
|
else
|
|
{
|
|
<div style="width:95%;max-width:500px;min-width:380px;margin:auto">
|
|
<div id="jp_container_1" class="jp-video jp-video-270p">
|
|
<div class="jp-type-playlist">
|
|
<div id="jquery_jplayer_1" class="jp-jplayer"></div>
|
|
<div id="textcnt" style="display:table;width:100%;height:400px;vertical-align: bottom;background-image: url('https://source.unsplash.com/500x400/?flowers');color:white">
|
|
<div id="title1" style="display: table-row">
|
|
<p style="width:100%;height:25%;text-align:center;vertical-align: middle;font-family: 'Vazirmatn';display: table-cell;font-size: 1.5em;text-shadow: 2px 2px 4px white;">
|
|
@Model.Poem.Category.Poet.Nickname
|
|
</p>
|
|
</div>
|
|
<div id="title2" style="display: table-row">
|
|
<p style="width:100%;height:25%;text-align:center;vertical-align: middle;font-family: 'Vazirmatn';display: table-cell;font-size: 1.5em;text-shadow: 2px 2px 4px white;">
|
|
@for (int i = 1; i < Model.Poem.Category.Cat.Ancestors.Count; i++)
|
|
{
|
|
<text>
|
|
@Model.Poem.Category.Cat.Ancestors.ElementAt(i).Title »
|
|
</text>
|
|
|
|
}
|
|
@Model.Poem.Category.Cat.Title
|
|
</p>
|
|
</div>
|
|
<div id="title3" style="display: table-row">
|
|
<p style="width:100%;height:25%;text-align:center;vertical-align: middle;font-family: 'Vazirmatn';display: table-cell;font-size: 1.5em;text-shadow: 2px 2px 4px white;">
|
|
@Model.Recitation.AudioTitle
|
|
</p>
|
|
</div>
|
|
<div id="title4" style="display: table-row">
|
|
<p style="width:100%;height:25%;text-align:center;vertical-align: middle;font-family: 'Vazirmatn';display: table-cell;font-size: 1em;text-shadow: 2px 2px 4px white;">
|
|
به خوانش @Model.Recitation.AudioArtist
|
|
</p>
|
|
</div>
|
|
|
|
<div id="verse1div" style="display: table-row;visibility: hidden;">
|
|
<div style="width:100%;height:50%;text-align:center;vertical-align: bottom;font-family: 'Vazirmatn';display: table-cell;font-size: 1.5em;text-shadow: 2px 2px 4px white;">
|
|
<p id="verse1" style="width:80%;margin:auto;background-color:rgba(0, 0, 0, .4);margin-bottom:5px">
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="verse2div" style="display: table-row;visibility: hidden">
|
|
<div style="width:100%;height:50%;text-align:center;vertical-align: top;font-family: 'Vazirmatn';display: table-cell;font-size: 1.5em;text-shadow: 2px 2px 4px white;">
|
|
<p id="verse2" style="width:80%;margin:auto;background-color:rgba(0, 0, 0, .4);margin-top:5px">
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div id="normaldiv" style="display: table-row;visibility: hidden">
|
|
<div style="width:100%;height:100%;text-align:center;vertical-align: middle;font-family: 'Vazirmatn';display: table-cell;font-size: 1.5em;text-shadow: 2px 2px 4px white;">
|
|
<p id="normal" style="width:80%;margin:auto;background-color:rgba(0, 0, 0, .4);">
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
</div>
|
|
<div class="jp-gui">
|
|
<div class="jp-video-play">
|
|
<button class="jp-video-play-icon" tabindex="0">پخش</button>
|
|
</div>
|
|
<div class="jp-interface">
|
|
<div class="jp-progress">
|
|
<div class="jp-seek-bar">
|
|
<div class="jp-play-bar"></div>
|
|
</div>
|
|
</div>
|
|
<div class="jp-current-time"> </div>
|
|
<div class="jp-duration"> </div>
|
|
<div class="jp-controls-holder">
|
|
<div class="jp-controls">
|
|
<button class="jp-previous" tabindex="0">قبلی</button>
|
|
<button class="jp-play" tabindex="0">پخش</button>
|
|
<button class="jp-next" tabindex="0">بعدی</button>
|
|
<button class="jp-stop" tabindex="0">توقف</button>
|
|
</div>
|
|
<div class="jp-volume-controls">
|
|
<button class="jp-mute" tabindex="0">بیصدا</button>
|
|
<button class="jp-volume-max" tabindex="0">حداکثر صدا</button>
|
|
<div class="jp-volume-bar">
|
|
<div class="jp-volume-bar-value"></div>
|
|
</div>
|
|
</div>
|
|
<div class="jp-toggles">
|
|
<button class="jp-repeat" tabindex="0">تکرار</button>
|
|
</div>
|
|
</div>
|
|
<div class="jp-details">
|
|
<div class="jp-title"> </div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="jp-playlist">
|
|
<ul>
|
|
<!-- The method Playlist.displayPlaylist() uses this unordered list -->
|
|
<li> </li>
|
|
</ul>
|
|
</div>
|
|
<div class="jp-no-solution">
|
|
<span>نیاز به بروزآوری</span>
|
|
جهت خوانش شعر شما یا باید از مرورگر جدیدی همچون <a href="http://getfirefox.com/">فایرفاکس</a> استفاده کنید یا افزونه <a href="http://get.adobe.com/flashplayer/" target="_blank">فلش</a> مرورگرتان را بروزآوری کنید.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<p style="font-family: 'Vazirmatn';font-size: 0.8em;color:darkgray">
|
|
تصویر پسزمینهٔ خوانش یک تصویر تصادفی از سایت <a href="https://unsplash.com/" target="_blank">unsplash.com</a> است و ارتباطی با محتوای شعر ندارد.
|
|
</p>
|
|
|
|
|
|
<p style="font-family: 'Vazirmatn';font-size: 1em">
|
|
فایل صوتی متناظر را میتوانید در قالب mp3 از <a href="@Model.Recitation.Mp3Url" download>این نشانی</a> (اندازه @Html.Raw($"{(Model.Recitation.Mp3SizeInBytes / (1024.0 * 1024.0)):0.00}".ToPersianNumbers()) مگابایت) دریافت کنید.
|
|
</p>
|
|
|
|
<p style="font-family: 'Vazirmatn';font-size: 1em">
|
|
جهت دریافت خوانش با استفاده از دیوان رومیزی این مطلب را مطالعه بفرمایید. امکان ساخت کلیپهای ویدیویی از خوانشها با استفاده از خوانشگر دیوان رومیزی وجود دارد. جهت مشارکت در خوانش اشعار این صفحه و ویدیوهای آموزشی آن را ببینید.
|
|
</p>
|
|
|
|
<script src="~/lib/jquery/dist/jquery.min.js"></script>
|
|
<script src="~/js/bk.js" asp-append-version="true"></script>
|
|
<script src="~/js/jplayersupport.js"></script>
|
|
<script src="~/js/vaabd.js?version=10"></script>
|
|
<script src="~/dist/jplayer/jquery.jplayer.min.js"></script>
|
|
<script src="~/dist/add-on/jplayer.playlist.min.js"></script>
|
|
<script>
|
|
@* Verse text is untrusted (user-submitted content, sanitized for storage but not for
|
|
safe embedding inside a <script> block) - it must never be spliced into a JS string
|
|
literal via @Html.Raw as it was here before, since a verse containing a stray "'" or
|
|
"</script>" would break out of the string. JsonSerializer.Serialize both quotes the
|
|
value correctly and HTML/JS-escapes '<', '>' and '&' by default, so the whole array
|
|
can be assigned directly and stays inert as data. *@
|
|
var verses = @Html.Raw(System.Text.Json.JsonSerializer.Serialize(Model.Poem.Verses.Select(v => v.Text)));
|
|
|
|
@Html.Raw($" var normaltext = { (Model.Poem.Verses.Where(v => v.VersePosition == RMuseum.Models.Divan.VersePosition.Paragraph).Any() ? "true" : "false") }")
|
|
|
|
function prepareclip(xmlfilename, poemtitle, auartist, oggurl, mp3url, verseArray) {
|
|
var verseStart = [];
|
|
var verseEnd = [];
|
|
var verseIndex = [];
|
|
var nLastHighlight = -1;
|
|
var vCount = 0;
|
|
|
|
audioxmlfiles[0] = xmlfilename;
|
|
|
|
|
|
var jlist = new jPlayerPlaylist({
|
|
jPlayer: "#jquery_jplayer_1",
|
|
cssSelectorAncestor: "#jp_container_1"
|
|
}, [
|
|
{
|
|
title: poemtitle,
|
|
artist: auartist,
|
|
mp3: mp3url
|
|
},
|
|
],
|
|
{
|
|
setmedia: function(event) {
|
|
|
|
$.ajax({
|
|
type: "GET",
|
|
url: audioxmlfiles[jlist.current],
|
|
dataType: "xml",
|
|
success: function(xml) {
|
|
var nOneSecondBugFix = 2000;
|
|
$(xml).find('OneSecondBugFix').each(function() {
|
|
nOneSecondBugFix = parseInt($(xml).find('OneSecondBugFix').text());
|
|
});
|
|
var v = 0;
|
|
$(xml).find('SyncInfo').each(function() {
|
|
verseStart[v] = parseInt($(this).find('AudioMiliseconds').text()) / nOneSecondBugFix;
|
|
verseIndex[v] = parseInt($(this).find('VerseOrder').text());
|
|
if (v > 0)
|
|
verseEnd[v - 1] = verseStart[v];
|
|
v++;
|
|
});
|
|
v--;
|
|
if (v > 1)
|
|
verseEnd[v] = verseStart[v] + 2 * (verseEnd[v - 1] - verseStart[v - 1]);
|
|
vCount = v;
|
|
}
|
|
});
|
|
|
|
|
|
},
|
|
|
|
timeupdate: function(event) { // 4Hz
|
|
var curTime = event.jPlayer.status.currentTime;
|
|
if (curTime > 0) {
|
|
if (normaltext == true) {
|
|
for (i = 0; i <= vCount; i++) {
|
|
if (curTime >= verseStart[i] && curTime <= verseEnd[i]) {
|
|
|
|
|
|
if (nLastHighlight != verseIndex[i]) {
|
|
|
|
$('#title1').hide();
|
|
$('#title2').hide();
|
|
$('#title3').hide();
|
|
$('#title4').hide();
|
|
$('#normal').text(verseArray[verseIndex[i]]);
|
|
$('#verse1div').css("visibility", "hidden");
|
|
$('#verse2div').css("visibility", "hidden");
|
|
$('#verse1div').hide();
|
|
$('#verse2div').hide();
|
|
$('#normaldiv').css("visibility", "visible");
|
|
|
|
}
|
|
nLastHighlight = verseIndex[i];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for (i = 0; i <= vCount; i += 2) {
|
|
if (curTime >= verseStart[i] && curTime <= verseEnd[i]) {
|
|
|
|
|
|
if (nLastHighlight != verseIndex[i]) {
|
|
|
|
$('#title1').hide();
|
|
$('#title2').hide();
|
|
$('#title3').hide();
|
|
$('#title4').hide();
|
|
$('#verse1').text(verseArray[verseIndex[i]]);
|
|
$('#verse2').text(verseArray[verseIndex[i] + 1]);
|
|
$('#normaldiv').css("visibility", "hidden");
|
|
$('#normaldiv').hide();
|
|
$('#verse1div').css("visibility", "visible");
|
|
$('#verse2div').css("visibility", "visible");
|
|
}
|
|
nLastHighlight = verseIndex[i];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
},
|
|
ended: function(event) { // 4Hz
|
|
|
|
},
|
|
swfPath: "dist/jplayer",
|
|
supplied: "mp3",
|
|
wmode: "window",
|
|
useStateClassSkin: true,
|
|
autoBlur: false,
|
|
smoothPlayBar: true,
|
|
keyEnabled: true,
|
|
remainingDuration: true,
|
|
toggleDuration: true
|
|
});
|
|
|
|
return jlist;
|
|
|
|
}
|
|
|
|
|
|
//<![CDATA[
|
|
$(document).ready(function() {
|
|
|
|
prepareclip('@Html.Raw($"{DivanRazor.APIRoot.InternetUrl}/api/audio/file/{Model.Recitation.Id}.xml")', '@Model.Recitation.AudioTitle',
|
|
'به خوانش @Model.Recitation.AudioArtist', '', '@Model.Recitation.Mp3Url', verses);
|
|
|
|
|
|
});
|
|
//]]>
|
|
</script>
|
|
|
|
@if (ViewData["TrackingScript"] != null && !string.IsNullOrEmpty(ViewData["TrackingScript"].ToString()))
|
|
{
|
|
@Html.Raw(ViewData["TrackingScript"])
|
|
}
|
|
}
|
|
|
|
</body>
|
|
</html> |