SAAS-712: UI Improvements
This commit is contained in:
parent
f6d5b34cca
commit
23bf866211
13 changed files with 81 additions and 50 deletions
12
airtime_mvc/application/views/scripts/player/customize.phtml
Normal file
12
airtime_mvc/application/views/scripts/player/customize.phtml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<div class="ui-widget ui-widget-content block-shadow simple-formblock embed-player-form clearfix padded-strong ">
|
||||
|
||||
<?php $baseUrl = Application_Common_OsPath::getBaseDir(); ?>
|
||||
|
||||
<form method="post" id="player_form" enctype="multipart/form-data">
|
||||
<h2 style="float:left"><?php echo _("Embeddable Player") ?></h2>
|
||||
<div style="clear:both"></div>
|
||||
<?php echo $this->errorMsg; ?>
|
||||
<?php echo $this->form; ?>
|
||||
|
||||
</form>
|
||||
</div>
|
294
airtime_mvc/application/views/scripts/player/index.phtml
Normal file
294
airtime_mvc/application/views/scripts/player/index.phtml
Normal file
|
@ -0,0 +1,294 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
<link rel="stylesheet" href="<?php echo $this->css?>" type="text/css">
|
||||
<script src="<?php echo $this->mrp_js?>" type="text/javascript"></script>
|
||||
<script src="<?php echo $this->jquery?>" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
var MAX_MOBILE_SCREEN_WIDTH = 760;
|
||||
|
||||
// We are creating a custom player object that acts as a wrapper
|
||||
// around the player object we get from Muses. We are doing this
|
||||
// for a couple reasons:
|
||||
//
|
||||
// 1. It will be easier to swap out Muses for a different player engine
|
||||
// in the future - if we ever decide to do that.
|
||||
// 2. We had to add in some custom behaviour depending on the player
|
||||
// customizations and whether or not the player is in Flash or HTML5
|
||||
// mode.
|
||||
var MusesPlayer = function() {
|
||||
this.mobileDetect = this.mobileDetect();
|
||||
this.playerMode = "<?php echo $this->playerMode ?>";
|
||||
this.flashDetect = FlashDetect.versionAtLeast(10, 1) ? true : false;
|
||||
this.settings = {
|
||||
'volume': 100,
|
||||
'jsevents': true,
|
||||
'autoplay': false,
|
||||
'buffering': 0,
|
||||
'title': 'test',
|
||||
'bgcolor': '#FFFFFF',
|
||||
'skin': 'mcclean',
|
||||
'width': 180,
|
||||
'height': 60
|
||||
};
|
||||
|
||||
if (this.playerMode == "manual") {
|
||||
this.settings.url = "<?php echo $this->streamURL ?>";
|
||||
this.settings.codec = "<?php echo $this->codec ?>";
|
||||
} else if (this.playerMode == "auto") {
|
||||
this.availableMobileStreamQueue = <?php echo $this->availableMobileStreams?>;
|
||||
this.availableDesktopStreamQueue = <?php echo $this->availableDesktopStreams?>;
|
||||
var stream = this.getNextAvailableStream();
|
||||
this.settings.url = stream["url"];
|
||||
this.settings.codec = stream["codec"];
|
||||
}
|
||||
|
||||
// Create the Muses player object
|
||||
MRP.insert(this.settings);
|
||||
|
||||
$("p.station_name").html(htmlEscape("<?php echo $this->station_name?>"));
|
||||
|
||||
attachStreamMetadataToPlayer();
|
||||
|
||||
// detects events in HTML5 mode
|
||||
if (!this.flashDetect) {
|
||||
|
||||
MRP.html.audio.addEventListener('error', function failed(e) {
|
||||
console.log("HTML error");
|
||||
var stream = musesPlayer.getNextAvailableStream();
|
||||
var audio = $(MRP.html.audio);
|
||||
audio.src = stream["url"];
|
||||
audio[0].load();
|
||||
audio[0].play();
|
||||
}, true);
|
||||
|
||||
MRP.html.audio.addEventListener('pause', function paused(e) {
|
||||
//this is when pause happens
|
||||
console.log("HTML paused");
|
||||
//src = MRP.html.audio.src;
|
||||
//MRP.html.audio.src = "";
|
||||
}, true);
|
||||
}
|
||||
};
|
||||
|
||||
MusesPlayer.prototype.mobileDetect = function() {
|
||||
return (screen.width <= MAX_MOBILE_SCREEN_WIDTH);
|
||||
}
|
||||
|
||||
// This function is called if an error occurs while a client is
|
||||
// attempting to connect to a stream (An error would occur if
|
||||
// the streams listener count has been maxed out or if the stream is down).
|
||||
// It checks if the client is a mobile device or not and returns the next
|
||||
// best available stream.
|
||||
MusesPlayer.prototype.getNextAvailableStream = function() {
|
||||
if (this.mobileDetect && this.availableMobileStreamQueue.length > 0) {
|
||||
return this.getNextAvailableMobileStream();
|
||||
}
|
||||
|
||||
if (!this.mobileDetect && this.availableDesktopStreamQueue.length > 0) {
|
||||
return this.getNextAvailableDesktopStream();
|
||||
}
|
||||
|
||||
// If we get to this point there are no available streams for the
|
||||
// type of device the client has connected with so just return
|
||||
// the next available stream - first we'll try the desktop streams
|
||||
var desktopStream = this.getNextAvailableDesktopStream();
|
||||
if (desktopStream) {
|
||||
return desktopStream;
|
||||
} else {
|
||||
return this.getNextAvailableMobileStream();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Gets and returns the next available mobile stream from the queue,
|
||||
// but adds it back to the end of the queue to be recycled.
|
||||
MusesPlayer.prototype.getNextAvailableMobileStream = function() {
|
||||
var stream = this.availableMobileStreamQueue.shift();
|
||||
//add to end of queue
|
||||
this.availableMobileStreamQueue.push(stream);
|
||||
return stream;
|
||||
}
|
||||
|
||||
// Gets and returns the next available desktop stream from the queue,
|
||||
// but adds it back to the end of the queue to be recycled.
|
||||
MusesPlayer.prototype.getNextAvailableDesktopStream = function() {
|
||||
var stream = this.availableDesktopStreamQueue.shift();
|
||||
//add to end of queue
|
||||
this.availableDesktopStreamQueue.push(stream);
|
||||
return stream;
|
||||
}
|
||||
|
||||
MusesPlayer.prototype.play = function() {
|
||||
this.flashDetect ? MRP.play() : musesHTMLPlayClick();;
|
||||
togglePlayStopButton();
|
||||
};
|
||||
|
||||
MusesPlayer.prototype.stop = function() {
|
||||
this.flashDetect ? MRP.stop() : musesHTMLStopClick();
|
||||
togglePlayStopButton();
|
||||
};
|
||||
|
||||
MusesPlayer.prototype.setURL = function(url) {
|
||||
console.log("setURL");
|
||||
MRP.setUrl(url);
|
||||
};
|
||||
|
||||
// detects errors in FLASH mode
|
||||
function musesCallback(event,value) {
|
||||
switch (event) {
|
||||
case "ioError":
|
||||
// connection limit reached or problem connecting to stream
|
||||
if (value === "0") {
|
||||
var stream = musesPlayer.getNextAvailableStream();
|
||||
musesPlayer.setURL(stream["url"]);
|
||||
musesPlayer.play();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Triggers the play function on the Muses player object in HTML5 mode
|
||||
function musesHTMLPlayClick() {
|
||||
/*if (MRP.html === undefined) {
|
||||
console.log("inserting player");
|
||||
MRP.insert(musesPlayer.settings);
|
||||
}*/
|
||||
MRP.html.audio.src = MRP.html.src;
|
||||
|
||||
MRP.html.audio.play();
|
||||
}
|
||||
|
||||
// Triggers the stop function on the Muses player object in HTML5 mode
|
||||
// NOTE: The HTML5 audio element doesn't have stop functionality. It
|
||||
// can only be paused.
|
||||
function musesHTMLStopClick() {
|
||||
MRP.html.audio.pause();
|
||||
//delete MRP.html;
|
||||
}
|
||||
|
||||
function togglePlayStopButton() {
|
||||
document.getElementById("play_button").classList.toggle("hide_button");
|
||||
document.getElementById("stop_button").classList.toggle("hide_button");
|
||||
}
|
||||
|
||||
// default how often to fetch metadata to 20 seconds
|
||||
var time_to_next_track_starts = 20000;
|
||||
|
||||
// Fetches the streams metadata from the Airtime live-info API
|
||||
// and attaches it to the player UI.
|
||||
//
|
||||
// The metadata is fetched when the current track is about to end.
|
||||
function attachStreamMetadataToPlayer(){
|
||||
$.ajax({url: "<?php echo $this->metadata_api_url?>",
|
||||
data: {type:"interval",limit:"5"},
|
||||
dataType: "jsonp",
|
||||
success: function(data) {
|
||||
|
||||
if (data.current === null) {
|
||||
$("p.now_playing").html("Offline");
|
||||
} else {
|
||||
var artist = data.current.name.split(" - ")[0];
|
||||
var track = data.current.name.split(" - ")[1];
|
||||
$("p.now_playing").html(artist + "<span>" + track + "</span>");
|
||||
|
||||
var current_track_end_time = new Date(data.current.ends);
|
||||
var current_time = new Date();
|
||||
//convert current_time to UTC to match the timezone of time_to_next_track_starts
|
||||
current_time = new Date(current_time.getTime() + current_time.getTimezoneOffset() * 60 * 1000);
|
||||
//TODO stop the first settimeout from executing!!
|
||||
time_to_next_track_starts = current_track_end_time - current_time;
|
||||
//console.log((time_to_next_track_starts/1000)/60);
|
||||
// maybe we should set time_to_next_track_starts to
|
||||
// (10 || 20 || etc.) minutes if its greater than that
|
||||
// in case of on-the-fly schedule changes
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (data.next === null) {
|
||||
$("ul.schedule_list").find("li").html("Nothing scheduled");
|
||||
} else {
|
||||
$("ul.schedule_list").find("li").html(data.next.name);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
setTimeout(attachStreamMetadataToPlayer, time_to_next_track_starts);
|
||||
}
|
||||
|
||||
function htmlEscape(str) {
|
||||
return String(str)
|
||||
.replace(/&/g, '&')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>');
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style type="text/css">
|
||||
/*
|
||||
We have to have the default Muses skin displayed on the page or else
|
||||
the player will not work. Setting the display to none and hidden does
|
||||
not work. It has to be "visible" on the page. As a hacky work around we
|
||||
set the height and width to 1px so users will not see it.
|
||||
*/
|
||||
#muses_skin{width:1px; height:1px; overflow-x: hidden; overflow-y: hidden;}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="airtime_player">
|
||||
|
||||
<div class="airtime_header">
|
||||
<p class="station_name">fff</p>
|
||||
</div>
|
||||
|
||||
<div class="airtime_box">
|
||||
|
||||
<div class="airtime_button">
|
||||
<span id="play_button" class="play_button" onclick="musesPlayer.play()"></span>
|
||||
<span id="stop_button" class="stop_button hide_button" onclick="musesPlayer.stop()"></span>
|
||||
</div>
|
||||
<p class="now_playing"></p>
|
||||
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<div class="airtime_volume">
|
||||
|
||||
<div class="volume_control">
|
||||
<span class="mute"></span>
|
||||
</div>
|
||||
|
||||
<div class="airtime_volume_bar">
|
||||
<div class="airtime_volume_bar_value" style="width: 80%;"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
-->
|
||||
<div style="clear:both"></div>
|
||||
|
||||
<div class="airtime_schedule">
|
||||
<p class="airtime_next">Next</p>
|
||||
<ul class="schedule_list">
|
||||
<li></li>
|
||||
</ul>
|
||||
</div>
|
||||
<a class="airtime_pro" target="_blank" href="https://www.airtime.pro/">Powered by Airtime Pro<span class="airtime_pro_logo"></span></a>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="muses_skin">
|
||||
<script type="text/javascript">
|
||||
var musesPlayer = new MusesPlayer();
|
||||
</script>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue