From 6c732f90e80bc6f13c6e50d6d9ddb66560b51e8e Mon Sep 17 00:00:00 2001 From: NH Gooi Date: Wed, 25 Sep 2024 17:30:15 +0200 Subject: [PATCH] Wavesurfer voor audio file player --- app/Http/Controllers/RadioController.php | 2 +- app/Http/Controllers/StreamController.php | 17 +- public/js/wavesurfer.min.js | 1 + resources/views/layouts/master.blade.php | 2 +- resources/views/listen.blade.php | 11 +- resources/views/podcastitem.blade.php | 3 +- resources/views/widgets/audioplayer.blade.php | 171 ++++++++++++------ 7 files changed, 138 insertions(+), 69 deletions(-) create mode 100644 public/js/wavesurfer.min.js diff --git a/app/Http/Controllers/RadioController.php b/app/Http/Controllers/RadioController.php index ba2087cf..b08ecf5c 100644 --- a/app/Http/Controllers/RadioController.php +++ b/app/Http/Controllers/RadioController.php @@ -95,7 +95,7 @@ class RadioController extends Controller { $programs = []; $now = new \DateTimeImmutable('2 minutes ago'); - $page = (int)$request->get('pagina', 1); + $page = (int)$request->get('pagina', 1); $apiResult = $this->API('programma/schema/recent?pagina=' . (int)max(1, $page) . '&aantal=12'); foreach($apiResult->schedule as $item) { if(!$item->program->nonstop && !$item->program->rerun) { diff --git a/app/Http/Controllers/StreamController.php b/app/Http/Controllers/StreamController.php index 841cf341..8c1317ea 100644 --- a/app/Http/Controllers/StreamController.php +++ b/app/Http/Controllers/StreamController.php @@ -14,6 +14,8 @@ class StreamController extends Controller return view('listen', [ 'source' => self::$STREAM_URL . 'mp3live', 'title' => 'Luister live', + 'lengte' => 0, + 'waveform' => null, 'content' => 'de live-uitzending van NH Gooi.', 'isStream' => true ]); } @@ -53,13 +55,20 @@ class StreamController extends Controller 'source' => $this->API_URL . 'podcast/stream/' . $apiResult->url, 'title' => $podcast->title, 'content' => $podcast->title, + 'lengte' => $podcast->duration / 1000, + 'waveform' => $podcast->waveform, 'isStream' => false, 'canDownload' => $this->API_URL . 'podcast/download/' . $apiResult->url ]); } public function program(Request $request, $year, $month, $day, $hour, $duration, $offset = 0) { $date = (new \DateTimeImmutable())->setDate($year, $month, $day)->setTime($hour, 0, 0); - $current = $date->add(\DateInterval::createFromDateString($offset . ' hours')); + $current = $date->add(\DateInterval::createFromDateString($offset . ' hours')); + + $programma = $this->API("programma/details/" . $current->Format("Y/m/d/H")); + if(!$programma->is_beschikbaar) { + return view('listen', ['notAvailable' => true]); + } $hours = []; for($i = 0; $i < $duration; $i++) { @@ -69,10 +78,12 @@ class StreamController extends Controller } return view('listen', [ - 'source' => $this->API_URL . 'programma/stream/' . $current->format('Y/m/d/H') . '/1', + 'source' => $this->API_URL . 'programma/stream/' . $current->format('Y/m/d/H'), 'tabs' => $hours, 'title' => 'Uitzending terugluisteren', - 'content' => 'de uitzending van ' . $current->format('d-m-Y, H') . ':00 uur', + 'lengte' => $programma->waveform->length, + 'waveform' => $programma->waveform, + 'content' => $programma->programma->name . ' van ' . $current->format('d-m-Y, H') . ':00 uur', 'isStream' => false, 'canDownload' => false ]); } diff --git a/public/js/wavesurfer.min.js b/public/js/wavesurfer.min.js new file mode 100644 index 00000000..86acd1f2 --- /dev/null +++ b/public/js/wavesurfer.min.js @@ -0,0 +1 @@ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).WaveSurfer=e()}(this,(function(){"use strict";function t(t,e,i,n){return new(i||(i=Promise))((function(s,r){function o(t){try{h(n.next(t))}catch(t){r(t)}}function a(t){try{h(n.throw(t))}catch(t){r(t)}}function h(t){var e;t.done?s(t.value):(e=t.value,e instanceof i?e:new i((function(t){t(e)}))).then(o,a)}h((n=n.apply(t,e||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;class e{constructor(){this.listeners={}}on(t,e,i){if(this.listeners[t]||(this.listeners[t]=new Set),this.listeners[t].add(e),null==i?void 0:i.once){const i=()=>{this.un(t,i),this.un(t,e)};return this.on(t,i),i}return()=>this.un(t,e)}un(t,e){var i;null===(i=this.listeners[t])||void 0===i||i.delete(e)}once(t,e){return this.on(t,e,{once:!0})}unAll(){this.listeners={}}emit(t,...e){this.listeners[t]&&this.listeners[t].forEach((t=>t(...e)))}}const i={decode:function(e,i){return t(this,void 0,void 0,(function*(){const t=new AudioContext({sampleRate:i});return t.decodeAudioData(e).finally((()=>t.close()))}))},createBuffer:function(t,e){return"number"==typeof t[0]&&(t=[t]),function(t){const e=t[0];if(e.some((t=>t>1||t<-1))){const i=e.length;let n=0;for(let t=0;tn&&(n=i)}for(const e of t)for(let t=0;tnull==t?void 0:t[e],copyFromChannel:AudioBuffer.prototype.copyFromChannel,copyToChannel:AudioBuffer.prototype.copyToChannel}}};function n(t,e){const i=e.xmlns?document.createElementNS(e.xmlns,t):document.createElement(t);for(const[t,s]of Object.entries(e))if("children"===t)for(const[t,s]of Object.entries(e))"string"==typeof s?i.appendChild(document.createTextNode(s)):i.appendChild(n(t,s));else"style"===t?Object.assign(i.style,s):"textContent"===t?i.textContent=s:i.setAttribute(t,s.toString());return i}function s(t,e,i){const s=n(t,e||{});return null==i||i.appendChild(s),s}var r=Object.freeze({__proto__:null,createElement:s,default:s});const o={fetchBlob:function(e,i,n){return t(this,void 0,void 0,(function*(){const s=yield fetch(e,n);if(s.status>=400)throw new Error(`Failed to fetch ${e}: ${s.status} (${s.statusText})`);return function(e,i){t(this,void 0,void 0,(function*(){if(!e.body||!e.headers)return;const n=e.body.getReader(),s=Number(e.headers.get("Content-Length"))||0;let r=0;const o=e=>t(this,void 0,void 0,(function*(){r+=(null==e?void 0:e.length)||0;const t=Math.round(r/s*100);i(t)})),a=()=>t(this,void 0,void 0,(function*(){let t;try{t=yield n.read()}catch(t){return}t.done||(o(t.value),yield a())}));a()}))}(s.clone(),i),s.blob()}))}};class a extends e{constructor(t){super(),this.isExternalMedia=!1,t.media?(this.media=t.media,this.isExternalMedia=!0):this.media=document.createElement("audio"),t.mediaControls&&(this.media.controls=!0),t.autoplay&&(this.media.autoplay=!0),null!=t.playbackRate&&this.onMediaEvent("canplay",(()=>{null!=t.playbackRate&&(this.media.playbackRate=t.playbackRate)}),{once:!0})}onMediaEvent(t,e,i){return this.media.addEventListener(t,e,i),()=>this.media.removeEventListener(t,e,i)}getSrc(){return this.media.currentSrc||this.media.src||""}revokeSrc(){const t=this.getSrc();t.startsWith("blob:")&&URL.revokeObjectURL(t)}canPlayType(t){return""!==this.media.canPlayType(t)}setSrc(t,e){if(this.getSrc()===t)return;this.revokeSrc();const i=e instanceof Blob&&this.canPlayType(e.type)?URL.createObjectURL(e):t;this.media.src=i}destroy(){this.media.pause(),this.isExternalMedia||(this.media.remove(),this.revokeSrc(),this.media.src="",this.media.load())}setMediaElement(t){this.media=t}play(){return t(this,void 0,void 0,(function*(){return this.media.play()}))}pause(){this.media.pause()}isPlaying(){return!this.media.paused&&!this.media.ended}setTime(t){this.media.currentTime=t}getDuration(){return this.media.duration}getCurrentTime(){return this.media.currentTime}getVolume(){return this.media.volume}setVolume(t){this.media.volume=t}getMuted(){return this.media.muted}setMuted(t){this.media.muted=t}getPlaybackRate(){return this.media.playbackRate}isSeeking(){return this.media.seeking}setPlaybackRate(t,e){null!=e&&(this.media.preservesPitch=e),this.media.playbackRate=t}getMediaElement(){return this.media}setSinkId(t){return this.media.setSinkId(t)}}class h extends e{constructor(t,e){super(),this.timeouts=[],this.isScrollable=!1,this.audioData=null,this.resizeObserver=null,this.lastContainerWidth=0,this.isDragging=!1,this.subscriptions=[],this.subscriptions=[],this.options=t;const i=this.parentFromOptionsContainer(t.container);this.parent=i;const[n,s]=this.initHtml();i.appendChild(n),this.container=n,this.scrollContainer=s.querySelector(".scroll"),this.wrapper=s.querySelector(".wrapper"),this.canvasWrapper=s.querySelector(".canvases"),this.progressWrapper=s.querySelector(".progress"),this.cursor=s.querySelector(".cursor"),e&&s.appendChild(e),this.initEvents()}parentFromOptionsContainer(t){let e;if("string"==typeof t?e=document.querySelector(t):t instanceof HTMLElement&&(e=t),!e)throw new Error("Container not found");return e}initEvents(){const t=t=>{const e=this.wrapper.getBoundingClientRect(),i=t.clientX-e.left,n=t.clientY-e.top;return[i/e.width,n/e.height]};this.wrapper.addEventListener("click",(e=>{const[i,n]=t(e);this.emit("click",i,n)})),this.wrapper.addEventListener("dblclick",(e=>{const[i,n]=t(e);this.emit("dblclick",i,n)})),!0!==this.options.dragToSeek&&"object"!=typeof this.options.dragToSeek||this.initDrag(),this.scrollContainer.addEventListener("scroll",(()=>{const{scrollLeft:t,scrollWidth:e,clientWidth:i}=this.scrollContainer,n=t/e,s=(t+i)/e;this.emit("scroll",n,s)}));const e=this.createDelay(100);this.resizeObserver=new ResizeObserver((()=>{e().then((()=>this.onContainerResize())).catch((()=>{}))})),this.resizeObserver.observe(this.scrollContainer)}onContainerResize(){const t=this.parent.clientWidth;t===this.lastContainerWidth&&"auto"!==this.options.height||(this.lastContainerWidth=t,this.reRender())}initDrag(){this.subscriptions.push(function(t,e,i,n,s=3,r=0,o=100){if(!t)return()=>{};const a=matchMedia("(pointer: coarse)").matches;let h=()=>{};const l=l=>{if(l.button!==r)return;l.preventDefault(),l.stopPropagation();let d=l.clientX,c=l.clientY,u=!1;const p=Date.now(),m=n=>{if(n.preventDefault(),n.stopPropagation(),a&&Date.now()-ps||Math.abs(m)>s){const n=t.getBoundingClientRect(),{left:s,top:o}=n;u||(null==i||i(d-s,c-o),u=!0),e(l,m,r-s,h-o),d=r,c=h}},f=e=>{if(u){const i=e.clientX,s=e.clientY,r=t.getBoundingClientRect(),{left:o,top:a}=r;null==n||n(i-o,s-a)}h()},g=t=>{t.relatedTarget&&t.relatedTarget!==document.documentElement||f(t)},v=t=>{u&&(t.stopPropagation(),t.preventDefault())},b=t=>{u&&t.preventDefault()};document.addEventListener("pointermove",m),document.addEventListener("pointerup",f),document.addEventListener("pointerout",g),document.addEventListener("pointercancel",g),document.addEventListener("touchmove",b,{passive:!1}),document.addEventListener("click",v,{capture:!0}),h=()=>{document.removeEventListener("pointermove",m),document.removeEventListener("pointerup",f),document.removeEventListener("pointerout",g),document.removeEventListener("pointercancel",g),document.removeEventListener("touchmove",b),setTimeout((()=>{document.removeEventListener("click",v,{capture:!0})}),10)}};return t.addEventListener("pointerdown",l),()=>{h(),t.removeEventListener("pointerdown",l)}}(this.wrapper,((t,e,i)=>{this.emit("drag",Math.max(0,Math.min(1,i/this.wrapper.getBoundingClientRect().width)))}),(t=>{this.isDragging=!0,this.emit("dragstart",Math.max(0,Math.min(1,t/this.wrapper.getBoundingClientRect().width)))}),(t=>{this.isDragging=!1,this.emit("dragend",Math.max(0,Math.min(1,t/this.wrapper.getBoundingClientRect().width)))})))}getHeight(t,e){var i;const n=(null===(i=this.audioData)||void 0===i?void 0:i.numberOfChannels)||1;if(null==t)return 128;if(!isNaN(Number(t)))return Number(t);if("auto"===t){const t=this.parent.clientHeight||128;return(null==e?void 0:e.every((t=>!t.overlay)))?t/n:t}return 128}initHtml(){const t=document.createElement("div"),e=t.attachShadow({mode:"open"});return e.innerHTML=`\n \n\n
\n
\n
\n
\n
\n
\n
\n `,[t,e]}setOptions(t){if(this.options.container!==t.container){const e=this.parentFromOptionsContainer(t.container);e.appendChild(this.container),this.parent=e}!0!==t.dragToSeek&&"object"!=typeof this.options.dragToSeek||this.initDrag(),this.options=t,this.reRender()}getWrapper(){return this.wrapper}getScroll(){return this.scrollContainer.scrollLeft}setScroll(t){this.scrollContainer.scrollLeft=t}setScrollPercentage(t){const{scrollWidth:e}=this.scrollContainer,i=e*t;this.setScroll(i)}destroy(){var t;this.subscriptions.forEach((t=>t())),this.container.remove(),null===(t=this.resizeObserver)||void 0===t||t.disconnect()}createDelay(t=10){let e,i;const n=()=>{e&&clearTimeout(e),i&&i()};return this.timeouts.push(n),()=>new Promise(((s,r)=>{n(),i=r,e=setTimeout((()=>{e=void 0,i=void 0,s()}),t)}))}convertColorValues(t){if(!Array.isArray(t))return t||"";if(t.length<2)return t[0]||"";const e=document.createElement("canvas"),i=e.getContext("2d"),n=e.height*(window.devicePixelRatio||1),s=i.createLinearGradient(0,0,0,n),r=1/(t.length-1);return t.forEach(((t,e)=>{const i=e*r;s.addColorStop(i,t)})),s}renderBarWaveform(t,e,i,n){const s=t[0],r=t[1]||t[0],o=s.length,{width:a,height:h}=i.canvas,l=h/2,d=window.devicePixelRatio||1,c=e.barWidth?e.barWidth*d:1,u=e.barGap?e.barGap*d:e.barWidth?c/2:0,p=e.barRadius||0,m=a/(c+u)/o,f=p&&"roundRect"in i?"roundRect":"rect";i.beginPath();let g=0,v=0,b=0;for(let t=0;t<=o;t++){const o=Math.round(t*m);if(o>g){const t=Math.round(v*l*n),s=t+Math.round(b*l*n)||1;let r=l-t;"top"===e.barAlign?r=0:"bottom"===e.barAlign&&(r=h-s),i[f](g*(c+u),r,c,s,p),g=o,v=0,b=0}const a=Math.abs(s[t]||0),d=Math.abs(r[t]||0);a>v&&(v=a),d>b&&(b=d)}i.fill(),i.closePath()}renderLineWaveform(t,e,i,n){const s=e=>{const s=t[e]||t[0],r=s.length,{height:o}=i.canvas,a=o/2,h=i.canvas.width/r;i.moveTo(0,a);let l=0,d=0;for(let t=0;t<=r;t++){const r=Math.round(t*h);if(r>l){const t=a+(Math.round(d*a*n)||1)*(0===e?-1:1);i.lineTo(l,t),l=r,d=0}const o=Math.abs(s[t]||0);o>d&&(d=o)}i.lineTo(l,a)};i.beginPath(),s(0),s(1),i.fill(),i.closePath()}renderWaveform(t,e,i){if(i.fillStyle=this.convertColorValues(e.waveColor),e.renderFunction)return void e.renderFunction(t,i);let n=e.barHeight||1;if(e.normalize){const e=Array.from(t[0]).reduce(((t,e)=>Math.max(t,Math.abs(e))),0);n=e?1/e:1}e.barWidth||e.barGap||e.barAlign?this.renderBarWaveform(t,e,i,n):this.renderLineWaveform(t,e,i,n)}renderSingleCanvas(t,e,i,n,s,r,o){const a=window.devicePixelRatio||1,h=document.createElement("canvas");h.width=Math.round(i*a),h.height=Math.round(n*a),h.style.width=`${i}px`,h.style.height=`${n}px`,h.style.left=`${Math.round(s)}px`,r.appendChild(h);const l=h.getContext("2d");if(this.renderWaveform(t,e,l),h.width>0&&h.height>0){const t=h.cloneNode(),i=t.getContext("2d");i.drawImage(h,0,0),i.globalCompositeOperation="source-in",i.fillStyle=this.convertColorValues(e.progressColor),i.fillRect(0,0,h.width,h.height),o.appendChild(t)}}renderMultiCanvas(e,i,n,s,r,o){return t(this,void 0,void 0,(function*(){const a=window.devicePixelRatio||1,l=n/a;let d=Math.min(h.MAX_CANVAS_WIDTH,this.scrollContainer.clientWidth);if(i.barWidth||i.barGap){const t=i.barWidth||.5,e=t+(i.barGap||t/2);d%e!=0&&(d=Math.floor(d/e)*e)}const c=t=>{const n=t*d,a=Math.min(l-n,d),h=e.map((t=>{const e=Math.floor(n/l*t.length),i=Math.floor((n+a)/l*t.length);return t.slice(e,i)}));this.renderSingleCanvas(h,i,a,s,n,r,o)},u=Math.ceil(l/d);if(1===u)return void c(0);const p=this.scrollContainer.scrollLeft/l,m=Math.floor(p*u);c(m),c(m+1),yield Promise.all([(()=>t(this,void 0,void 0,(function*(){const t=this.createDelay();for(let e=m-1;e>=0;e--)yield t(),c(e)})))(),(()=>t(this,void 0,void 0,(function*(){const t=this.createDelay();for(let e=m+2;e0&&(o.style.marginTop=`-${a}px`),this.canvasWrapper.style.minHeight=`${a}px`,this.canvasWrapper.appendChild(o);const h=o.cloneNode();this.progressWrapper.appendChild(h),yield this.renderMultiCanvas(e,r,n,a,o,h)}))}render(e){return t(this,void 0,void 0,(function*(){this.timeouts.forEach((t=>t())),this.timeouts=[],this.canvasWrapper.innerHTML="",this.progressWrapper.innerHTML="",null!=this.options.width&&(this.scrollContainer.style.width="number"==typeof this.options.width?`${this.options.width}px`:this.options.width);const t=window.devicePixelRatio||1,i=this.scrollContainer.clientWidth,n=Math.ceil(e.duration*(this.options.minPxPerSec||0));this.isScrollable=n>i;const s=this.options.fillParent&&!this.isScrollable,r=(s?i:n)*t;this.wrapper.style.width=s?"100%":`${n}px`,this.scrollContainer.style.overflowX=this.isScrollable?"auto":"hidden",this.scrollContainer.classList.toggle("noScrollbar",!!this.options.hideScrollbar),this.cursor.style.backgroundColor=`${this.options.cursorColor||this.options.progressColor}`,this.cursor.style.width=`${this.options.cursorWidth}px`,this.audioData=e,this.emit("render");try{if(this.options.splitChannels)yield Promise.all(Array.from({length:e.numberOfChannels}).map(((t,i)=>{var n;const s=Object.assign(Object.assign({},this.options),null===(n=this.options.splitChannels)||void 0===n?void 0:n[i]);return this.renderChannel([e.getChannelData(i)],s,r,i)})));else{const t=[e.getChannelData(0)];e.numberOfChannels>1&&t.push(e.getChannelData(1)),yield this.renderChannel(t,this.options,r,0)}}catch(t){return}this.emit("rendered")}))}reRender(){if(!this.audioData)return;const{scrollWidth:t}=this.scrollContainer,{right:e}=this.progressWrapper.getBoundingClientRect();if(this.render(this.audioData),this.isScrollable&&t!==this.scrollContainer.scrollWidth){const{right:t}=this.progressWrapper.getBoundingClientRect();let i=t-e;i*=2,i=i<0?Math.floor(i):Math.ceil(i),i/=2,this.scrollContainer.scrollLeft+=i}}zoom(t){this.options.minPxPerSec=t,this.reRender()}scrollIntoView(t,e=!1){const{scrollLeft:i,scrollWidth:n,clientWidth:s}=this.scrollContainer,r=t*n,o=i,a=i+s,h=s/2;if(this.isDragging){const t=30;r+t>a?this.scrollContainer.scrollLeft+=t:r-ta)&&(this.scrollContainer.scrollLeft=r-(this.options.autoCenter?h:0));const t=r-i-h;e&&this.options.autoCenter&&t>0&&(this.scrollContainer.scrollLeft+=Math.min(t,10))}{const t=this.scrollContainer.scrollLeft,e=t/n,i=(t+s)/n;this.emit("scroll",e,i)}}renderProgress(t,e){if(isNaN(t))return;const i=100*t;this.canvasWrapper.style.clipPath=`polygon(${i}% 0, 100% 0, 100% 100%, ${i}% 100%)`,this.progressWrapper.style.width=`${i}%`,this.cursor.style.left=`${i}%`,this.cursor.style.transform=`translateX(-${100===Math.round(i)?this.options.cursorWidth:0}px)`,this.isScrollable&&this.options.autoScroll&&this.scrollIntoView(t,e)}exportImage(e,i,n){return t(this,void 0,void 0,(function*(){const t=this.canvasWrapper.querySelectorAll("canvas");if(!t.length)throw new Error("No waveform data");if("dataURL"===n){const n=Array.from(t).map((t=>t.toDataURL(e,i)));return Promise.resolve(n)}return Promise.all(Array.from(t).map((t=>new Promise(((n,s)=>{t.toBlob((t=>{t?n(t):s(new Error("Could not export image"))}),e,i)})))))}))}}h.MAX_CANVAS_WIDTH=4e3;class l extends e{constructor(){super(...arguments),this.unsubscribe=()=>{}}start(){this.unsubscribe=this.on("tick",(()=>{requestAnimationFrame((()=>{this.emit("tick")}))})),this.emit("tick")}stop(){this.unsubscribe()}destroy(){this.unsubscribe()}}class d extends e{constructor(t=new AudioContext){super(),this.bufferNode=null,this.playStartTime=0,this.playedDuration=0,this._muted=!1,this._playbackRate=1,this._duration=void 0,this.buffer=null,this.currentSrc="",this.paused=!0,this.crossOrigin=null,this.seeking=!1,this.autoplay=!1,this.addEventListener=this.on,this.removeEventListener=this.un,this.audioContext=t,this.gainNode=this.audioContext.createGain(),this.gainNode.connect(this.audioContext.destination)}load(){return t(this,void 0,void 0,(function*(){}))}get src(){return this.currentSrc}set src(t){if(this.currentSrc=t,this._duration=void 0,!t)return this.buffer=null,void this.emit("emptied");fetch(t).then((e=>{if(e.status>=400)throw new Error(`Failed to fetch ${t}: ${e.status} (${e.statusText})`);return e.arrayBuffer()})).then((e=>this.currentSrc!==t?null:this.audioContext.decodeAudioData(e))).then((e=>{this.currentSrc===t&&(this.buffer=e,this.emit("loadedmetadata"),this.emit("canplay"),this.autoplay&&this.play())}))}_play(){var t;if(!this.paused)return;this.paused=!1,null===(t=this.bufferNode)||void 0===t||t.disconnect(),this.bufferNode=this.audioContext.createBufferSource(),this.buffer&&(this.bufferNode.buffer=this.buffer),this.bufferNode.playbackRate.value=this._playbackRate,this.bufferNode.connect(this.gainNode);let e=this.playedDuration*this._playbackRate;e>=this.duration&&(e=0,this.playedDuration=0),this.bufferNode.start(this.audioContext.currentTime,e),this.playStartTime=this.audioContext.currentTime,this.bufferNode.onended=()=>{this.currentTime>=this.duration&&(this.pause(),this.emit("ended"))}}_pause(){var t;this.paused=!0,null===(t=this.bufferNode)||void 0===t||t.stop(),this.playedDuration+=this.audioContext.currentTime-this.playStartTime}play(){return t(this,void 0,void 0,(function*(){this.paused&&(this._play(),this.emit("play"))}))}pause(){this.paused||(this._pause(),this.emit("pause"))}stopAt(t){var e,i;const n=t-this.currentTime;null===(e=this.bufferNode)||void 0===e||e.stop(this.audioContext.currentTime+n),null===(i=this.bufferNode)||void 0===i||i.addEventListener("ended",(()=>{this.bufferNode=null,this.pause()}),{once:!0})}setSinkId(e){return t(this,void 0,void 0,(function*(){return this.audioContext.setSinkId(e)}))}get playbackRate(){return this._playbackRate}set playbackRate(t){this._playbackRate=t,this.bufferNode&&(this.bufferNode.playbackRate.value=t)}get currentTime(){return(this.paused?this.playedDuration:this.playedDuration+(this.audioContext.currentTime-this.playStartTime))*this._playbackRate}set currentTime(t){const e=!this.paused;e&&this._pause(),this.playedDuration=t/this._playbackRate,e&&this._play(),this.emit("seeking"),this.emit("timeupdate")}get duration(){var t,e;return null!==(t=this._duration)&&void 0!==t?t:(null===(e=this.buffer)||void 0===e?void 0:e.duration)||0}set duration(t){this._duration=t}get volume(){return this.gainNode.gain.value}set volume(t){this.gainNode.gain.value=t,this.emit("volumechange")}get muted(){return this._muted}set muted(t){this._muted!==t&&(this._muted=t,this._muted?this.gainNode.disconnect():this.gainNode.connect(this.audioContext.destination))}canPlayType(t){return/^(audio|video)\//.test(t)}getGainNode(){return this.gainNode}getChannelData(){const t=[];if(!this.buffer)return t;const e=this.buffer.numberOfChannels;for(let i=0;i{this.emit("init");const{peaks:t,duration:e}=this.options;(n||t&&e)&&this.load(n,t,e).catch((()=>null))}))}updateProgress(t=this.getCurrentTime()){return this.renderer.renderProgress(t/this.getDuration(),this.isPlaying()),t}initTimerEvents(){this.subscriptions.push(this.timer.on("tick",(()=>{if(!this.isSeeking()){const t=this.updateProgress();this.emit("timeupdate",t),this.emit("audioprocess",t)}})))}initPlayerEvents(){this.isPlaying()&&(this.emit("play"),this.timer.start()),this.mediaSubscriptions.push(this.onMediaEvent("timeupdate",(()=>{const t=this.updateProgress();this.emit("timeupdate",t)})),this.onMediaEvent("play",(()=>{this.emit("play"),this.timer.start()})),this.onMediaEvent("pause",(()=>{this.emit("pause"),this.timer.stop()})),this.onMediaEvent("emptied",(()=>{this.timer.stop()})),this.onMediaEvent("ended",(()=>{this.emit("finish")})),this.onMediaEvent("seeking",(()=>{this.emit("seeking",this.getCurrentTime())})),this.onMediaEvent("error",(t=>{this.emit("error",t.error)})))}initRendererEvents(){this.subscriptions.push(this.renderer.on("click",((t,e)=>{this.options.interact&&(this.seekTo(t),this.emit("interaction",t*this.getDuration()),this.emit("click",t,e))})),this.renderer.on("dblclick",((t,e)=>{this.emit("dblclick",t,e)})),this.renderer.on("scroll",((t,e)=>{const i=this.getDuration();this.emit("scroll",t*i,e*i)})),this.renderer.on("render",(()=>{this.emit("redraw")})),this.renderer.on("rendered",(()=>{this.emit("redrawcomplete")})),this.renderer.on("dragstart",(t=>{this.emit("dragstart",t)})),this.renderer.on("dragend",(t=>{this.emit("dragend",t)})));{let t;this.subscriptions.push(this.renderer.on("drag",(e=>{if(!this.options.interact)return;let i;this.renderer.renderProgress(e),clearTimeout(t),this.isPlaying()?i=0:!0===this.options.dragToSeek?i=200:"object"==typeof this.options.dragToSeek&&void 0!==this.options.dragToSeek&&(i=this.options.dragToSeek.debounceTime),t=setTimeout((()=>{this.seekTo(e)}),i),this.emit("interaction",e*this.getDuration()),this.emit("drag",e)})))}}initPlugins(){var t;(null===(t=this.options.plugins)||void 0===t?void 0:t.length)&&this.options.plugins.forEach((t=>{this.registerPlugin(t)}))}unsubscribePlayerEvents(){this.mediaSubscriptions.forEach((t=>t())),this.mediaSubscriptions=[]}setOptions(t){this.options=Object.assign({},this.options,t),this.renderer.setOptions(this.options),t.audioRate&&this.setPlaybackRate(t.audioRate),null!=t.mediaControls&&(this.getMediaElement().controls=t.mediaControls)}registerPlugin(t){return t._init(this),this.plugins.push(t),this.subscriptions.push(t.once("destroy",(()=>{this.plugins=this.plugins.filter((e=>e!==t))}))),t}getWrapper(){return this.renderer.getWrapper()}getScroll(){return this.renderer.getScroll()}setScroll(t){return this.renderer.setScroll(t)}setScrollTime(t){const e=t/this.getDuration();this.renderer.setScrollPercentage(e)}getActivePlugins(){return this.plugins}loadAudio(e,n,s,r){return t(this,void 0,void 0,(function*(){var t;if(this.emit("load",e),!this.options.media&&this.isPlaying()&&this.pause(),this.decodedData=null,!n&&!s){const i=this.options.fetchParams||{};window.AbortController&&!i.signal&&(this.abortController=new AbortController,i.signal=null===(t=this.abortController)||void 0===t?void 0:t.signal);const s=t=>this.emit("loading",t);n=yield o.fetchBlob(e,s,i)}this.setSrc(e,n);const a=r||this.getDuration()||(yield new Promise((t=>{this.onMediaEvent("loadedmetadata",(()=>t(this.getDuration())),{once:!0})})));if(!e&&!n){const t=this.getMediaElement();t instanceof d&&(t.duration=a)}if(s)this.decodedData=i.createBuffer(s,a||0);else if(n){const t=yield n.arrayBuffer();this.decodedData=yield i.decode(t,this.options.sampleRate)}this.decodedData&&(this.emit("decode",this.getDuration()),this.renderer.render(this.decodedData)),this.emit("ready",this.getDuration())}))}load(e,i,n){return t(this,void 0,void 0,(function*(){try{return yield this.loadAudio(e,void 0,i,n)}catch(t){throw this.emit("error",t),t}}))}loadBlob(e,i,n){return t(this,void 0,void 0,(function*(){try{return yield this.loadAudio("blob",e,i,n)}catch(t){throw this.emit("error",t),t}}))}zoom(t){if(!this.decodedData)throw new Error("No audio loaded");this.renderer.zoom(t),this.emit("zoom",t)}getDecodedData(){return this.decodedData}exportPeaks({channels:t=2,maxLength:e=8e3,precision:i=1e4}={}){if(!this.decodedData)throw new Error("The audio has not been decoded yet");const n=Math.min(t,this.decodedData.numberOfChannels),s=[];for(let t=0;tMath.abs(s)&&(s=i)}r.push(Math.round(s*i)/i)}s.push(r)}return s}getDuration(){let t=super.getDuration()||0;return 0!==t&&t!==1/0||!this.decodedData||(t=this.decodedData.duration),t}toggleInteraction(t){this.options.interact=t}setTime(t){super.setTime(t),this.updateProgress(t),this.emit("timeupdate",t)}seekTo(t){const e=this.getDuration()*t;this.setTime(e)}playPause(){return t(this,void 0,void 0,(function*(){return this.isPlaying()?this.pause():this.play()}))}stop(){this.pause(),this.setTime(0)}skip(t){this.setTime(this.getCurrentTime()+t)}empty(){this.load("",[[0]],.001)}setMediaElement(t){this.unsubscribePlayerEvents(),super.setMediaElement(t),this.initPlayerEvents()}exportImage(){return t(this,arguments,void 0,(function*(t="image/png",e=1,i="dataURL"){return this.renderer.exportImage(t,e,i)}))}destroy(){var t;this.emit("destroy"),null===(t=this.abortController)||void 0===t||t.abort(),this.plugins.forEach((t=>t.destroy())),this.subscriptions.forEach((t=>t())),this.unsubscribePlayerEvents(),this.timer.destroy(),this.renderer.destroy(),super.destroy()}}return u.BasePlugin=class extends e{constructor(t){super(),this.subscriptions=[],this.options=t}onInit(){}_init(t){this.wavesurfer=t,this.onInit()}destroy(){this.emit("destroy"),this.subscriptions.forEach((t=>t()))}},u.dom=r,u})); diff --git a/resources/views/layouts/master.blade.php b/resources/views/layouts/master.blade.php index 3ddb356d..8f7f4876 100644 --- a/resources/views/layouts/master.blade.php +++ b/resources/views/layouts/master.blade.php @@ -203,7 +203,7 @@ function openPlayerInNewScreen() { $(".player").click(function (e) { e.preventDefault(); - window.open($(this).attr('href'), '_player', 'width=550,height=500,titlebar,close'); + window.open($(this).attr('href'), '_player', 'width=550,height=600,titlebar,close'); return false; }); } diff --git a/resources/views/listen.blade.php b/resources/views/listen.blade.php index 60b5d8f1..df61e50d 100644 --- a/resources/views/listen.blade.php +++ b/resources/views/listen.blade.php @@ -4,8 +4,8 @@ Venster sluiten - @if(false && $isStream) -

Wegens een technisch probleem is NH Gooi momenteel niet via Internet te beluisteren. Onze excuses voor het + @if(isset($notAvailable) && $notAvailable) +

Helaas is de door u gekozen audio momenteel niet via Internet te beluisteren. Onze excuses voor het ongemak.

In Hilversum, Huizen en de BEL-gemeenten zijn wij te ontvangen op 92.0 FM of 105.1 FM.

@else @@ -41,9 +41,10 @@ --}} @include('widgets.audioplayer', [ - 'source' =>str_replace("stream", "download", $source), - 'lengte' => 0, - 'waveform' => [] + 'source' => $source, + 'isStream' => $isStream, + 'lengte' => $lengte, + 'waveform' => $waveform ])

diff --git a/resources/views/podcastitem.blade.php b/resources/views/podcastitem.blade.php index 722f774a..9d008889 100644 --- a/resources/views/podcastitem.blade.php +++ b/resources/views/podcastitem.blade.php @@ -113,6 +113,7 @@
@include("widgets.audioplayer", [ + 'isStream' => false, 'source' => $streamUrl, 'lengte' => $podcast->duration / 1000, 'waveform' => $podcast->waveform @@ -122,7 +123,7 @@ Download fragment - + Luister in nieuw venster
diff --git a/resources/views/widgets/audioplayer.blade.php b/resources/views/widgets/audioplayer.blade.php index 20eca206..d24d247d 100644 --- a/resources/views/widgets/audioplayer.blade.php +++ b/resources/views/widgets/audioplayer.blade.php @@ -1,31 +1,23 @@
- {{-- - -
- @if( $lengte > 60) - {{ floor($lengte / 60) }} minuten en {{ floor(($lengte % 60)) }} seconden - @else - {{ $lengte }} seconden - @endif -
- --}} - + @if(!$isStream)
0:00
0:00
+ @endif
- + onchange="setVolume( this.value )" />
+ @if(!$isStream) - + @if(!$isStream) + @endif
+@if($isStream) + + + + + +@else + +@endif + \ No newline at end of file