364 lines
9.0 KiB
JavaScript
364 lines
9.0 KiB
JavaScript
var playlist = WaveformPlaylist.init({
|
|
container: document.getElementById("playlist"),
|
|
timescale: true,
|
|
state: 'select',
|
|
samplesPerPixel: 16384,
|
|
zoomLevels: [2048, 4096, 8192, 16384],
|
|
|
|
controls: {
|
|
show: true,
|
|
width: 150,
|
|
widgets: {
|
|
stereoPan: false,
|
|
}
|
|
},
|
|
waveHeight: 80,
|
|
});
|
|
|
|
function onFinishedLoading() {
|
|
//initialize the WAV exporter.
|
|
playlist.initExporter();
|
|
|
|
const tracks = playlist.tracks;
|
|
for (var i = 0; i < tracks.length; i++) {
|
|
playlist.collapseTrack(tracks[i], {collapsed: true});
|
|
}
|
|
|
|
const highlight = window.location.hash.split('#').filter(Boolean);
|
|
for(var i = 0; i < highlight.length; i++) {
|
|
const guid = highlight[i];
|
|
|
|
for (var j = 0; j < tracks.length; j++) {
|
|
if (tracks[j].name == guid) {
|
|
tracks[j].setWaveOutlineColor('#d1e7dd');
|
|
}
|
|
}
|
|
|
|
for (var j = 0; j < g_chats.length; j++) {
|
|
if (g_chats[j].player_guid == guid) {
|
|
chatRows[j].classList.add("table-active");
|
|
}
|
|
}
|
|
}
|
|
|
|
playlist.drawRequest();
|
|
}
|
|
|
|
function collapseTrack(guid, collapse) {
|
|
const tracks = playlist.tracks;
|
|
for (var i = 0; i < tracks.length; i++) {
|
|
if (guid === null || tracks[i].name == guid) {
|
|
playlist.collapseTrack(tracks[i], {collapsed: collapse});
|
|
if (guid != null) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function updateTrackInfo(guid, info) {
|
|
const tracks = playlist.tracks;
|
|
for (var i = 0; i < tracks.length; i++) {
|
|
if (guid === null || tracks[i].name == guid) {
|
|
tracks[i].setInfo(info);
|
|
if (guid != null) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
var ee = playlist.getEventEmitter();
|
|
var $container = $("body");
|
|
var $time = $container.find(".audio-pos");
|
|
var $time_ = $container.find(".audio-pos-2");
|
|
|
|
var audioPos = 0;
|
|
|
|
function clockFormat(seconds, decimals) {
|
|
var hours,
|
|
minutes,
|
|
secs,
|
|
result;
|
|
|
|
hours = parseInt(seconds / 3600, 10) % 24;
|
|
minutes = parseInt(seconds / 60, 10) % 60;
|
|
secs = seconds % 60;
|
|
secs = secs.toFixed(decimals);
|
|
|
|
result = (hours < 10 ? "0" + hours : hours) + ":" + (minutes < 10 ? "0" + minutes : minutes) + ":" + (secs < 10 ? "0" + secs : secs);
|
|
|
|
return result;
|
|
}
|
|
|
|
var lastChunkIdx = 0;
|
|
var lastUpdateTime = 0;
|
|
function updateTime(time) {
|
|
$time.html(clockFormat(time, 3));
|
|
audioPos = time;
|
|
|
|
if (time < lastUpdateTime) {
|
|
lastChunkIdx = 0;
|
|
}
|
|
|
|
var tick = time / g_session.tickinterval;
|
|
var silenceTicks = 0;
|
|
for (; lastChunkIdx < g_session.silence_chunks.length; lastChunkIdx++) {
|
|
var chunk = g_session.silence_chunks[lastChunkIdx];
|
|
if (tick > chunk[0]) {
|
|
silenceTicks = chunk[1];
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
tick += silenceTicks;
|
|
var tickedTime = tick * g_session.tickinterval;
|
|
$time_.html(clockFormat(tickedTime, 3));
|
|
|
|
lastUpdateTime = time;
|
|
if (lastChunkIdx > 0) {
|
|
lastChunkIdx -= 1;
|
|
}
|
|
|
|
onTick(tick, tickedTime);
|
|
}
|
|
updateTime(audioPos);
|
|
|
|
function onEvent(idx, event) {
|
|
var update = 0;
|
|
if (event.event == "player_connect") {
|
|
collapseTrack(event.player_guid, false);
|
|
updateTrackInfo(event.player_guid, event.data.name);
|
|
update += 1;
|
|
}
|
|
else if (event.event == "player_disconnect") {
|
|
collapseTrack(event.player_guid, true);
|
|
update += 1;
|
|
}
|
|
else if (event.event == "player_changename") {
|
|
updateTrackInfo(event.player_guid, event.data.newname);
|
|
update += 1;
|
|
}
|
|
return update;
|
|
}
|
|
|
|
var chatBox = $("div#chat");
|
|
var chatRows = $("div#chat>table>tbody").children();
|
|
var lastPrimaryRow = undefined;
|
|
function onChat(idx, chat) {
|
|
if (idx == lastPrimaryRow) {
|
|
return 0;
|
|
}
|
|
|
|
if (lastPrimaryRow != undefined) {
|
|
chatRows[lastPrimaryRow].classList.remove("table-primary");
|
|
}
|
|
|
|
chatRows[idx].classList.add("table-primary");
|
|
if (autoScrollChat) {
|
|
chatRows[idx].scrollIntoViewIfNeeded();
|
|
}
|
|
|
|
lastPrimaryRow = idx;
|
|
return 1;
|
|
}
|
|
|
|
var lastTick = undefined;
|
|
var lastChatIdx = 0;
|
|
var lastEventIdx = 0;
|
|
function onTick(tick, time) {
|
|
var update = 0;
|
|
if (tick == lastTick) {
|
|
return;
|
|
}
|
|
|
|
if (tick < lastTick) {
|
|
lastChatIdx = 0;
|
|
lastEventIdx = 0;
|
|
}
|
|
|
|
for (; lastEventIdx < g_events.length; lastEventIdx++) {
|
|
const event = g_events[lastEventIdx];
|
|
if (tick > event.tick) {
|
|
update += onEvent(lastEventIdx, event);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
if (lastEventIdx > 0) {
|
|
lastEventIdx -= 1;
|
|
}
|
|
|
|
for (; lastChatIdx < g_chats.length; lastChatIdx++) {
|
|
const chat = g_chats[lastChatIdx];
|
|
if (tick < chat.tick) {
|
|
if (lastChatIdx > 0) {
|
|
lastChatIdx -= 1;
|
|
}
|
|
update += onChat(lastChatIdx, chat);
|
|
break;
|
|
}
|
|
}
|
|
|
|
lastTick = tick;
|
|
|
|
if (update) {
|
|
playlist.drawRequest();
|
|
}
|
|
}
|
|
|
|
function gameTimeToAudio(tick) {
|
|
tick += 1;
|
|
var silenceTicks = 0;
|
|
for (var i = 0; i < g_session.silence_chunks.length; i++) {
|
|
const chunk = g_session.silence_chunks[i];
|
|
if ((tick - chunk[1]) > chunk[0]) {
|
|
silenceTicks = chunk[1];
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return (tick - silenceTicks) * g_session.tickinterval;
|
|
}
|
|
|
|
function jumpToGameTick(tick) {
|
|
var audioTime = gameTimeToAudio(tick);
|
|
playlist.seek(audioTime);
|
|
playlist.drawRequest();
|
|
updateTime(audioTime);
|
|
}
|
|
|
|
$container.on("click", ".btn-play", function() {
|
|
ee.emit("play");
|
|
});
|
|
|
|
$container.on("click", ".btn-pause", function() {
|
|
isLooping = false;
|
|
ee.emit("pause");
|
|
});
|
|
|
|
$container.on("click", ".btn-stop", function() {
|
|
isLooping = false;
|
|
ee.emit("stop");
|
|
});
|
|
|
|
$container.on("click", ".btn-rewind", function() {
|
|
isLooping = false;
|
|
ee.emit("rewind");
|
|
});
|
|
|
|
$container.on("click", ".btn-fast-forward", function() {
|
|
isLooping = false;
|
|
ee.emit("fastforward");
|
|
});
|
|
|
|
// zoom buttons
|
|
$container.on("click", ".btn-zoom-in", function() {
|
|
ee.emit("zoomin");
|
|
});
|
|
|
|
$container.on("click", ".btn-zoom-out", function() {
|
|
ee.emit("zoomout");
|
|
});
|
|
|
|
// download
|
|
var downloadUrl = undefined;
|
|
var downloadName = undefined;
|
|
$container.on("click", ".btn-download", function () {
|
|
if (downloadName) {
|
|
return;
|
|
}
|
|
|
|
downloadName = g_session.demoname;
|
|
if (playlist.isSegmentSelection()) {
|
|
const segment = playlist.getTimeSelection();
|
|
downloadName += "-" + clockFormat(segment.start).replaceAll(':', '-') + "_" + clockFormat(segment.end).replaceAll(':', '-');
|
|
}
|
|
downloadName += ".wav";
|
|
|
|
ee.emit('startaudiorendering', 'wav');
|
|
});
|
|
|
|
ee.on('audiorenderingfinished', function (type, data) {
|
|
if (type != 'wav') {
|
|
return;
|
|
}
|
|
if (downloadUrl) {
|
|
window.URL.revokeObjectURL(downloadUrl);
|
|
}
|
|
|
|
downloadUrl = window.URL.createObjectURL(data);
|
|
|
|
const tempLink = document.createElement('a');
|
|
tempLink.style.display = 'none';
|
|
tempLink.href = downloadUrl;
|
|
tempLink.setAttribute('download', downloadName);
|
|
document.body.appendChild(tempLink);
|
|
tempLink.click();
|
|
document.body.removeChild(tempLink);
|
|
|
|
downloadName = undefined;
|
|
});
|
|
|
|
|
|
$container.on("input change", ".master-gain", function(e){
|
|
ee.emit("mastervolumechange", e.target.value);
|
|
});
|
|
$container.find(".master-gain").change();
|
|
|
|
var autoScrollVoice = false;
|
|
$container.on("change", "#autoscroll_voice", function(e){
|
|
autoScrollVoice = $(e.target).is(':checked');
|
|
ee.emit("automaticscroll", autoScrollVoice);
|
|
});
|
|
$container.find("#autoscroll_voice").change();
|
|
|
|
var autoScrollChat = false;
|
|
$container.on("change", "#autoscroll_chat", function(e){
|
|
autoScrollChat = $(e.target).is(':checked');
|
|
});
|
|
$container.find("#autoscroll_chat").change();
|
|
|
|
ee.on("timeupdate", updateTime);
|
|
|
|
|
|
function getParent(el) {
|
|
var parent = el.parentNode;
|
|
|
|
if (parent === document) {
|
|
return document;
|
|
} else if (parent.offsetHeight < parent.scrollHeight || parent.offsetWidth < parent.scrollWidth) {
|
|
return parent;
|
|
} else {
|
|
return getParent(parent);
|
|
}
|
|
}
|
|
if (!Element.prototype.scrollIntoViewIfNeeded) {
|
|
Element.prototype.scrollIntoViewIfNeeded = function (centerIfNeeded) {
|
|
centerIfNeeded = arguments.length === 0 ? true : !!centerIfNeeded;
|
|
|
|
var parent = getParent(this),
|
|
parentComputedStyle = window.getComputedStyle(parent, null),
|
|
parentBorderTopWidth = parseInt(parentComputedStyle.getPropertyValue('border-top-width')),
|
|
parentBorderLeftWidth = parseInt(parentComputedStyle.getPropertyValue('border-left-width')),
|
|
overTop = this.offsetTop - parent.offsetTop < parent.scrollTop,
|
|
overBottom = (this.offsetTop - parent.offsetTop + this.clientHeight - parentBorderTopWidth) > (parent.scrollTop + parent.clientHeight),
|
|
overLeft = this.offsetLeft - parent.offsetLeft < parent.scrollLeft,
|
|
overRight = (this.offsetLeft - parent.offsetLeft + this.clientWidth - parentBorderLeftWidth) > (parent.scrollLeft + parent.clientWidth),
|
|
alignWithTop = overTop && !overBottom;
|
|
|
|
if ((overTop || overBottom) && centerIfNeeded) {
|
|
parent.scrollTop = this.offsetTop - parent.offsetTop - parent.clientHeight / 2 - parentBorderTopWidth + this.clientHeight / 2;
|
|
}
|
|
|
|
if ((overLeft || overRight) && centerIfNeeded) {
|
|
parent.scrollLeft = this.offsetLeft - parent.offsetLeft - parent.clientWidth / 2 - parentBorderLeftWidth + this.clientWidth / 2;
|
|
}
|
|
|
|
if ((overTop || overBottom || overLeft || overRight) && !centerIfNeeded) {
|
|
this.scrollIntoView(alignWithTop);
|
|
}
|
|
};
|
|
} |