/* * WPaudio v3.1 (http://wpaudio.com) * by Todd Iceton (todd@wpaudio.com) * * Modified January 2012 by Wendy Cholbi (wendy@cholbi.com) * with code gleaned from the WordPress.org support forums: * * http://bit.ly/y6UArf (WP user rahul286) * http://bit.ly/w2vG0H (WP user waffl) * http://bit.ly/xTnQWm (WP user Ursula (aka WP Gal)) * * Converts an mp3 link to a simple player styled by HTML & CSS, powered by HTML5 with SoundManager2 Flash fallback * * Copyright 2010 Todd Iceton (email: todd@wpaudio.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * Player CSS */ _wpaudio.css = { inline: { '.wpaudio-container': { display: 'inline-block', 'font-family': 'Sans-serif', 'line-height': 1, '*display': 'inline', zoom: 1 }, '.wpaudio-container a': { color: _wpaudio.style.link_color, 'text-decoration': 'none' }, '.wpaudio-container .wpaudio': { 'font-family': _wpaudio.style.text_font, 'font-size': _wpaudio.style.text_size, 'font-weight': _wpaudio.style.text_weight, 'letter-spacing': _wpaudio.style.text_letter_spacing }, '.wpaudio-play': { margin: '0 5px 0 0', width: '14px', height: '13px', background: '#ccc', 'vertical-align': 'baseline' }, '.wpaudio-slide': { display: 'none' }, '.wpaudio-bar': { position: 'relative', margin: '2px 0 0 19px', height: '5px', 'font-size': '1px', background: _wpaudio.style.bar_base_bg }, '.wpaudio-bar-playable': { position: 'absolute', top: 0, left: 0, right: '100%', height: '5px', 'z-index': 11, background: _wpaudio.style.bar_load_bg }, '.wpaudio-bar-position': { position: 'absolute', top: 0, left: 0, right: '100%', height: '5px', 'z-index': 12, background: _wpaudio.style.bar_position_bg }, '.wpaudio-bar-click': { position: 'absolute', top: 0, left: 0, right: 0, width: '100%', height: '5px', 'z-index': 13, cursor: 'pointer' }, '.wpaudio-meta': { margin: '3px 0 0 19px', 'font-size': '11px', color: _wpaudio.style.sub_color }, '.wpaudio-download': { float: 'right' } }, head: { '.wpaudio-container a:visited': { color: _wpaudio.style.link_color }, '.wpaudio-container a:hover': { color: _wpaudio.style.link_hover_color } } }; /* * Append CSS to head */ (function(){ /*var css = '.wpaudio-container {display:inline-block; zoom:1; *display:inline; line-height: 1; font-family: Sans-serif; font-size: 18px; line-height: 1;}' + '.wpaudio-container a, .wpaudio-container a:visited {color: #06c; text-decoration: none;}' + '.wpaudio-container a:hover {color: #03a;}' + '.wpaudio-play {margin: 0 5px 0 0; border: 0; width: 14px; height: 13px; background: #666; vertical-align: baseline;}' + '.wpaudio-slide {display: none;}' + '.wpaudio-bar {position: relative; margin: 2px 0 0 19px; height: 5px; font-size: 1px; background: #eee;}' + '.wpaudio-bar-playable {position: absolute; top: 0; left: 0; right: 100%; height: 5px; z-index: 11; background: #ccc;}' + '.wpaudio-bar-position {position: absolute; top: 0; left: 0; right: 100%; height: 5px; z-index: 12; background: #06c;}' + '.wpaudio-bar-click {position: absolute; top: 0; left: 0; right: 0; width: 100%; height: 5px; z-index: 12; cursor: pointer;}' + '.wpaudio-meta {margin: 3px 0 0 19px; font-size: 11px; color: #888;}' + '.wpaudio-download {float: right;}';*/ var css = ''; jQuery.each( jQuery.extend( {}, _wpaudio.css.inline, _wpaudio.css.head ), function ( css_group, css_rules ) { css += css_group + '{'; jQuery.each( css_rules, function ( css_item, css_value ) { css += css_item + ':' + css_value + ';'; }); // Zero margin, border, and padding if they're not specified if ( !css_rules.margin ) { css += 'margin:0;'; } if ( !css_rules.border ) { css += 'border:0;'; } if ( !css_rules.padding ) { css += 'padding:0;'; } css += '}'; }); jQuery('head').append(''); }()); /* * WPaudio common parent that will be appended to the mp3 link * * All interaction happens through this object, which calls the child players' control methods. * This takes care of click event listening and link decoration. */ function Wpaudio (elem) { this.elem = elem; var player; this.player = player; var getUrl = function () { return _wpaudio.enc[elem.id] ? _wpaudio.enc[elem.id] : elem.href; }; this.getUrl = getUrl; var isPlaying = function () { return player.isPlaying(); }; this.isPlaying = isPlaying; var play = function () { // Pause all playing players before starting this one jQuery('.wpaudio-playing').each(function(i,v){ v.wpaudio.pause(); }); player.play(); // Mark as playing and slide down jQuery(elem).addClass('wpaudio-playing').parent().find('.wpaudio-slide:hidden').slideDown(); }; this.play = play; var pause = function () { player.pause(); jQuery(elem).removeClass('wpaudio-playing'); }; this.pause = pause; var seek = function ( percent ) { if ( !isPlaying() ) { play(); } player.seek(percent); }; this.seek = seek; // Update button image, progress bars, time var updateDisplay = function () { // Get info from player var info = player.getInfo(); // Set button image based on play/pause (check current and change if necessary) var button_url = (info.is_playing) ? _wpaudio.url + '/wpaudio-pause.png' : _wpaudio.url + '/wpaudio-play.png'; if ( button_url !== jQuery(elem).children('.wpaudio-play').attr('src') ) { jQuery(elem).children('.wpaudio-play').attr( 'src', button_url ); } // Set bar positions jQuery(elem).parent().find('.wpaudio-bar-position').css({ left: String((info.playable_start/info.duration) || 0) + '%', width: String((info.position - info.playable_start) / info.duration * 100 || 0) + '%' }); jQuery(elem).parent().find('.wpaudio-bar-playable').css({ left: String((info.playable_start/info.duration) || 0) + '%', width: String((info.playable_end - info.playable_start) / info.duration * 100 || 0) + '%' }); // Set time var min = Math.floor(info.position / 60); var sec = Math.floor(info.position % 60); var time_string = min + ':'; if ( sec < 10 ) { time_string += '0'; // Add leading 0 to seconds if necessary } time_string += sec; jQuery(elem).parent().find('.wpaudio-position').text(time_string); }; this.updateDisplay = updateDisplay; // Define the slider HTML so the next bit doesn't get too messy var slider = '
' + '
' + '
' + '
' + '
' + '
' + '
' + String( jQuery(elem).hasClass('wpaudio-nodl') ? '' : 'Download' ) + '
' + '
' + '
'; // Toggle play/pause on click and style the player jQuery(elem).click(function(){ if ( isPlaying() ) { pause(); } else { play(); } jQuery(this).blur(); return false; }).prepend('').wrap('').after(slider); // Fix slide width for IE -- in a timeout b/c Chrome shits otherwise jQuery(elem).parent().children('.wpaudio-slide').width(jQuery(elem).width()); // Click bar to seek jQuery(elem).parent().find('.wpaudio-bar-click').mouseup(function (e) { if ( e.pageX ) { var percent = ( e.pageX - jQuery(this).offset().left ) / jQuery(this).width(); seek(percent); } }); // Initialize the player player = new this.Player(this); } /* * HTML5 player * * This contains controls and event handling for the native player */ function WpaudioHTML5 (parent) { var player = document.createElement('audio'); this.player = player; this.parent = parent; player.src = parent.getUrl(); player.volume = 1; player.preload = "none"; jQuery(player).bind('play pause ended timeupdate progress canplaythrough', parent.updateDisplay); var isPlaying = function () { return !player.paused; }; this.isPlaying = isPlaying; var getInfo = function () { var pos, dur, start, end; try { pos = player.currentTime; dur = player.duration; start = player.buffered.start(0); end = player.buffered.end(0); } catch (e) { pos = 0; dur = 0; start = 0; end = 0; } return { is_playing: isPlaying(), position: pos, duration: dur, playable_start: start, playable_end: end }; }; this.getInfo = getInfo; var play = function () { player.play(); }; this.play = play; this.pause = function () { player.pause(); }; this.seek = function ( fraction ) { player.currentTime = player.duration * fraction; }; return this; } /* * SoundManager2 player * * This contains controls and event handling for the Flash player */ function WpaudioSM2 (par) { var that = this, player, parent; this.player = player; this.parent = parent; this.parent = par; this.player = soundManager.createSound({ id: (par.elem.id && jQuery('#' + par.elem.id).length === 1) ? par.elem.id : 'wpaudio-' + String(Math.random()).split('.')[1] + String((new Date()).getTime()), url: par.getUrl(), onplay: par.updateDisplay, onresume: par.updateDisplay, onpause: par.updateDisplay, onfinish: par.updateDisplay, whileplaying: par.updateDisplay, whileloading: par.updateDisplay, volume: 100 }); var isPlaying = function () { return !(that.player.paused || that.player.playState === 0); }; this.isPlaying = isPlaying; var getInfo = function () { return { is_playing: isPlaying(), position: that.player.position / 1000 || 0, duration: (((that.player.bytesLoaded == that.player.bytesTotal) ? that.player.duration : that.player.durationEstimate) / 1000) || 0, playable_start: 0, playable_end: ((that.player.bytesLoaded / that.player.bytesTotal) * that.player.duration) / 1000 || 0 }; }; this.getInfo = getInfo; var play = function () { that.player.togglePause(); }; this.play = play; this.pause = function () { that.player.togglePause(); }; this.seek = function ( fraction ) { if ( !isPlaying() ) { play(); } that.player.setPosition(((that.player.bytesLoaded == that.player.bytesTotal) ? that.player.duration : that.player.durationEstimate) * fraction); }; return this; } /* * WPaudio ready * * When WPaudio is loaded, style and autoplay. Consider moving autoplay to the Wpaudio object (play if autoplay and no .wpaudio-playing). */ function wpaudioReady () { // Apply CSS jQuery.each( _wpaudio.css.inline, function ( css_group, css_rules ) { jQuery( css_group ).css( css_rules ); // Zero margin, border, and padding if they're not specified if ( !css_rules.margin ) { jQuery( css_group ).css('margin', 0); } if ( !css_rules.border ) { jQuery( css_group ).css('border', 0); } if ( !css_rules.padding ) { jQuery( css_group ).css('padding', 0); } }); // Autoplay if ( jQuery('.wpaudio-autoplay:first').length ) { jQuery('.wpaudio-autoplay:first')[0].wpaudio.play(); } } /* * Initialize WPaudio players * * Detect HTML5 support, set WPaudio player to either HTML5 or SM2, and initialize WPaudio players */ jQuery(document).ready(function(){ var wpaudio_selector = '.wpaudio, .wpaudio-autoplay'; // Handle all mp3 links if selected if ( _wpaudio.convert_mp3_links ) { jQuery('a[href$=".mp3"]').addClass('wpaudio'); } // Detect HTML5 var _wpaudio_html5 = document.createElement('audio'); if (!!(_wpaudio_html5.canPlayType && _wpaudio_html5.canPlayType('audio/mpeg;').replace(/no/, ''))) { Wpaudio.prototype.Player = WpaudioHTML5; jQuery(wpaudio_selector).each(function(i,v){ v.wpaudio = new Wpaudio(v); }); wpaudioReady(); } // SoundManager2 fallback else { if ( typeof soundManager !== 'object' ) { jQuery.getScript( _wpaudio.url + '/sm2/soundmanager2-nodebug-jsmin.js', function () { if ( typeof soundManager === 'object' ) { soundManager.debugMode = false; soundManager.url = _wpaudio.url + '/sm2/'; soundManager.nullURL = 'about:blank'; //_wpaudio.url + '/sm2/null.mp3'; soundManager.useHighPerformance = true; soundManager.useFastPolling = false; soundManager.waitForWindowLoad = false; soundManager.onready(function(){ jQuery(wpaudio_selector).each(function(i,v){ v.wpaudio = new Wpaudio(v); }); wpaudioReady(); }); } }); } Wpaudio.prototype.Player = WpaudioSM2; } }); // Preload play + pause images -- play first! (function(){ var play = new Image(), pause = new Image(); play.src = _wpaudio.url + '/wpaudio-play.png'; jQuery( play ).load(function () { pause.src = _wpaudio.url + '/wpaudio-pause.png'; }); }());