In WordPress with Hello Elementor, Elementor and Elementor Pro I wrote a custom web-based audio player to play live radio stream but it doesnt work on iphone and Mozilla firefox in all devices.
I tried many things but nothing works. When I switch off enhanced protection off it works. Can someone help me?
(function () {
const el = {
'timer': '#timer .elementor-heading-title',
'duration': '#duration .elementor-heading-title',
'loading': '#loading',
'playBtn': '#playBtn',
'pauseBtn': '#pauseBtn',
'backward': '#backward',
'forward': '#forward',
'bar': '#bar',
'progress': '#progress',
'tracker': '#tracker',
'volBar': '#volBar',
'volBarPerc': '#volBarPerc',
'volTracker': '#volTracker',
'mute': '#mute i',
'htmlAudio': '#html-audio',
'live': '#live'
};
const elems = {};
Object.keys(el).forEach((key) => {
elems[key] = document.querySelector(el[key]);
});
/**
* Radio class containing the state of our stations.
* Includes all methods for playing, stopping, etc.
* @param station object with station details ({title, src, howl, ...}).
*/
var Radio = function (station) {
var self = this;
self.station = station;
self.vol = 1;
self.duration = 0;
self.playing = false;
self.loadtime = 0;
setInterval(function () {
var f = self.updateDuration();
}, 1000);
};
Radio.prototype = {
/**
* Play a station.
*/
play: function () {
var self = this;
var sound;
var data = self.station;
// If we already loaded this track, use the current one.
// Otherwise, setup and load a new Howl.
if (data.howl) {
data.howl.play();
} else {
self.newHowl();
self.station.howl.load();
self.station.howl.volume(0, self.sid);
self.sid = self.station.howl.play();
self.station.howl.seek(0, self.sid);
}
self.playing = true;
// Show the pause button.
if (data.howl.state(self.sid) === 'loaded') {
elems.playBtn.style.display = 'none';
elems.pauseBtn.style.display = 'flex';
} else {
elems.loading.style.display = 'flex';
elems.playBtn.style.display = 'none';
elems.pauseBtn.style.display = 'none';
}
},
newHowl: function () {
var self = this;
self.station.howl = new Howl({
src: self.station.src, // + '?dt=' + Date.now().toString(),
html5: true, // A live stream can only be played through HTML5 Audio.
ext: ['mp3'],
format: ['mp3'],
preload: false,
autoplay: true,
onplay: function () {
// Start updating the progress of the track.
requestAnimationFrame(self.step.bind(self));
elems.pauseBtn.style.display = 'flex';
},
onload: function () {
elems.loading.style.display = 'none';
},
onpause: function () {
requestAnimationFrame(self.step.bind(self));
},
onstop: function () {
},
onseek: function () {
// Start updating the progress of the track.
requestAnimationFrame(self.step.bind(self));
}
});
},
updateDuration: function () {
var self = this;
var sound = self.station.howl;
if (!sound) {
return -1;
}
console.log(sound.state(self.sid));
if (sound.state(self.sid) === 'loading') {
self.loadtime++;
}
if (sound.state(self.sid) !== 'loaded') {
elems.loading.style.display = 'flex';
elems.playBtn.style.display = 'none';
elems.pauseBtn.style.display = 'none';
if (sound.state(self.sid) !== 'loading' || self.loadtime > 5) { // || self.duration > 0) {
console.log("new")
self.station.howl.unload(self.sid);
// self.station.howl = null;
//
// self.newHowl();
self.duration = 0;
self.loadtime = 0;
self.station.howl.load();
self.sid = self.station.howl.play();
self.station.howl.volume(0, self.sid);
self.station.howl.seek(0, self.sid);
self.playing = true;
}
return 0;
}
elems.loading.style.display = 'none';
if (self.playing) {
elems.playBtn.style.display = 'none';
elems.pauseBtn.style.display = 'flex';
} else {
elems.playBtn.style.display = 'flex';
elems.pauseBtn.style.display = 'none';
}
self.duration++;
self.station.howl.volume(self.vol, self.sid);
return 1;
},
/**
* Pause the currently playing track.
*/
pause: function () {
var self = this;
// Get the Howl we want to manipulate.
var sound = self.station.howl;
if (!sound) return;
// Puase the sound.
sound.pause(self.sid);
self.playing = false;
// Show the play button.
elems.playBtn.style.display = 'flex';
elems.pauseBtn.style.display = 'none';
},
goLive: function () {
var self = this;
var sound = self.station.howl;
if (!sound) return;
var s = self.duration - 1;
if (s < 0) s = 0;
sound.seek(s, self.sid);
},
jump: function (direction) {
var self = this;
var sound = self.station.howl;
if (!sound) return;
var jump = 10
if (direction === 'backward') {
jump *= -1
}
var newSeek = sound.seek(self.sid) + jump;
if (newSeek < 0) {
newSeek = 0;
}
if (newSeek > self.duration) {
newSeek = self.duration - 1;
if (newSeek < 0) newSeek = 0;
}
if (sound.state() === 'loaded') {
sound.seek(newSeek, self.sid);
}
},
/**
* Stop a station's live stream.
*/
stop: function () {
var self = this;
// Get the Howl we want to manipulate.
var sound = self.station.howl;
if (!sound) return;
// Stop the sound.
if (sound) {
sound.unload(self.sid);
}
},
/**
* Set the volume and update the volume slider display.
* @param {Number} val Volume between 0 and 1.
*/
volume: function (val) {
var self = this;
if (!self.station.howl) return;
// Update the display on the slider.
elems.volBarPerc.style.width = (val * 100) + '%';
elems.volTracker.style.left = (val * 100) + '%';
if (val === 0) {
elems.mute.classList.remove("player-fill-volume");
elems.mute.classList.add("player-fill-mute");
self.volSave = self.station.howl.volume(self.sid);
if (self.volSave < 0.1) self.volSave = 0.1;
} else {
elems.mute.classList.remove("player-fill-mute");
elems.mute.classList.add("player-fill-volume");
}
// Update the global volume (affecting all Howls).
self.station.howl.volume(val, self.sid);
self.vol = val;
},
mute: function () {
var self = this;
if (!self.station.howl) return;
if (self.station.howl.volume(self.sid) === 0) {
self.volume(self.volSave);
} else {
self.volume(0);
}
},
/**
* Seek to a new position in the currently playing track.
* @param {Number} per Percentage through the song to skip.
*/
seek: function (per) {
var self = this;
// Get the Howl we want to manipulate.
var sound = self.station.howl;
if (!sound) return;
// Convert the percent into a seek position.
//if (sound.playing()) {
var newSeek = self.duration * per;
if (self.duration - newSeek < 2) {
newSeek = self.duration - 1;
}
if (newSeek < 0) newSeek = 0;
sound.seek(newSeek, self.sid);
//}
},
/**
* The step called within requestAnimationFrame to update the playback position.
*/
step: function () {
var self = this;
// Get the Howl we want to manipulate.
var sound = self.station.howl;
if (sound) {
var seek = sound.seek(self.sid) || 0;
// if (self.duration > 0){ // && sound.state() === "loaded" && seek <= self.duration) {
// Determine our current seek position.
var perc = ((seek / self.duration) * 100) || 100;
var diff = self.duration - seek;
var timertxt = '';
if (diff < 0) {
seek = self.duration - 1;
if (seek < 0) seek = 0;
sound.seek(seek, self.sid);
perc = 100;
elems.live.classList.add('now');
} else if (diff < 2) {
perc = 100;
elems.live.classList.add('now');
} else {
elems.live.classList.remove('now');
timertxt = '- ' + self.formatTime(Math.round(diff))
}
elems.timer.innerHTML = timertxt;
elems.duration.innerHTML = self.formatTime(Math.round(self.duration));
if (!window.trackerDown) {
elems.progress.style.width = perc.toString() + '%';
elems.tracker.style.left = perc.toString() + '%';
}
// }
}
// If the sound is still playing, continue stepping.
//if (sound.playing()) {
requestAnimationFrame(self.step.bind(self));
//}
},
/**
* Format the time from seconds to M:SS.
* @param {Number} secs Seconds to format.
* @return {String} Formatted time.
*/
formatTime: function (secs) {
var minutes = Math.floor(secs / 60) || 0;
var seconds = (secs - minutes * 60) || 0;
return minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
}
};
window.trackerDown = false;
window.volTrackerDown = false;
window.trackerPerc = 0;
// Setup our new radio and pass in the stations.
var player = new Radio(
{
freq: '100.6',
title: "Nostos Radio",
src: 'https://rdst.win:48051', // + Date.now().toString(), 'https://neos.win:37878/stream?type=.mp3',
howl: null
}
);
// Bind our player controls.
// Main Buttons
elems.playBtn.addEventListener('click', function () {
player.play();
});
elems.pauseBtn.addEventListener('click', function () {
player.pause();
});
elems.live.addEventListener('click', function () {
player.goLive();
});
elems.backward.addEventListener('click', function () {
player.jump('backward');
});
elems.forward.addEventListener('click', function () {
player.jump('forward');
});
// Progress Bar
function getPercent(event, bar) {
let x = event.clientX || event.touches[0].clientX;
let barRect = bar.getBoundingClientRect();
let per;
if (x < barRect.left) {
per = 0;
} else if (x > barRect.left + barRect.width) {
per = 1;
} else {
per = (x - barRect.left) / barRect.width;
}
return per;
}
elems.bar.addEventListener('mousedown', function (event) {
if(!player.station.howl) return;
window.trackerPerc = getPercent(event, elems.bar);
// player.seek(per);
window.trackerDown = true;
elems.progress.style.width = (window.trackerPerc * 100).toString() + '%';
elems.tracker.style.left = (window.trackerPerc * 100).toString() + '%';
});
elems.tracker.addEventListener('mousedown', function () {
if(!player.station.howl) return;
window.trackerDown = true;
elems.progress.style.width = (window.trackerPerc * 100).toString() + '%';
elems.tracker.style.left = (window.trackerPerc * 100).toString() + '%';
});
elems.tracker.addEventListener('touchstart', function () {
if(!player.station.howl) return;
window.trackerDown = true;
elems.progress.style.width = (window.trackerPerc * 100).toString() + '%';
elems.tracker.style.left = (window.trackerPerc * 100).toString() + '%';
});
// Volume
elems.mute.addEventListener('click', function () {
player.mute();
});
// Set up the event listeners to enable dragging of volume slider.
elems.volBar.addEventListener('mousedown', function (event) {
let per = getPercent(event, elems.volBar);
player.volume(per);
window.volTrackerDown = true;
});
elems.volTracker.addEventListener('mousedown', function () {
window.volTrackerDown = true;
});
elems.volTracker.addEventListener('touchstart', function () {
window.volTrackerDown = true;
});
// Move Bars
window.addEventListener('mouseup', function () {
if(!player.station.howl) return;
if (window.trackerDown) {
player.seek(window.trackerPerc);
}
window.trackerDown = false;
window.volTrackerDown = false;
});
window.addEventListener('touchend', function () {
if(!player.station.howl) return;
if (window.trackerDown) {
player.seek(window.trackerPerc);
}
window.trackerDown = false;
window.volTrackerDown = false;
});
var move = function (event) {
if(!player.station.howl) return;
if (window.trackerDown) {
window.trackerPerc = getPercent(event, elems.bar);
elems.progress.style.width = (window.trackerPerc * 100).toString() + '%';
elems.tracker.style.left = (window.trackerPerc * 100).toString() + '%';
// player.seek(per);
}
if (window.volTrackerDown) {
let per = getPercent(event, elems.volBar);
player.volume(per);
}
};
window.addEventListener('mousemove', move);
window.addEventListener('touchmove', move);
})();
</script>