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);
 | |
|     }
 | |
|   };
 | |
| } |