'use strict'; /*@ Ox.AudioPlayer Generic Audio Player @*/ Ox.AudioPlayer = function(options, self) { self = self || {}; var that = Ox.Element({}, self) .defaults({ audio: [], muted: false, paused: false, position: 0, repeat: 0, shuffle: false, time: 'elapsed', track: 0, volume: 1, width: 512 }) .options(options || {}) .update({ audio: function() { self.options.position = -1; self.options.track = -1; that.options({ paused: true, position: 0, track: 0 }); }, muted: function() { self.options.muted = !self.options.muted; toggleMuted(); }, paused: function() { self.options.paused = !self.options.paused; togglePaused(); }, position: function() { setPosition(self.options.position); }, repeat: function() { setRepeat(self.options.repeat); }, shuffle: function() { self.options.shuffle = !self.options.shuffle; toggleShuffle(); }, time: function() { self.options.time = self.options.time == 'elapsed' ? 'remaining' : 'elapsed'; toggleTime(); }, track: function() { setTrack(self.options.track); }, volume: function() { setVolume(self.options.volume); }, width: setSizes }) .addClass('OxAudioPlayer') .css({width: self.options.width + 'px'}) .bindEvent({ key_0: toggleMuted, key_equal: function() { setVolume(Ox.min(self.options.volume + 0.1, 1)); }, key_minus: function() { setVolume(Ox.max(self.options.volume - 0.1, 0)); }, key_space: togglePaused }); self.tracks = self.options.audio.length; self.volume = self.options.muted ? 1 : self.options.volume; self.$listButton = Ox.MenuButton({ items: self.options.audio.slice( Math.max(self.options.track - 10, 0), Math.min(self.options.track + 11, self.tracks) ).map(function(track, index) { index += Math.max(self.options.track - 10, 0); return { id: index.toString(), title: formatTrack(track), checked: index == self.options.track }; }), maxWidth: 256, overlap: 'left', title: 'select', type: 'image' }) .addClass('OxListButton') .appendTo(that); self.$shuffleButton = Ox.Button( Ox.extend({overlap: 'left', type: 'image'}, getButtonOptions('shuffle')) ) .addClass('OxShuffleButton') .bindEvent({ click: toggleShuffle }) .appendTo(that); self.$repeatButton = Ox.Button( Ox.extend({overlap: 'left', type: 'image'}, getButtonOptions('repeat')) ) .addClass('OxRepeatButton') .bindEvent({ click: function() { setRepeat( self.options.repeat == 0 ? -1 : self.options.repeat == -1 ? 1 : 0 ); } }) .appendTo(that); self.$trackLabel = Ox.Label({ textAlign: 'center', title: '', }) .addClass('OxTrackLabel') .appendTo(that); self.$playButtons = Ox.ButtonGroup({ buttons: [ { id: 'current', title: 'playPrevious', tooltip: Ox._('Play Current Track') }, Ox.extend({id: 'play'}, getButtonOptions('play')), { id: 'next', title: 'playNext', tooltip: Ox._('Play Next Track') } ], overlap: 'right', type: 'image', }) .addClass('OxPlayButtons') .bindEvent({ click: function(data) { if (data.id == 'current') { setPosition(0); } else if (data.id == 'play') { togglePaused(); } else if (data.id == 'next') { playNext(); } } }) .appendTo(that); self.$positionLabel = Ox.Label({ textAlign: 'center', title: '00:00:00', tooltip: Ox._('Show Remaining Time'), width: 80 }) .addClass('OxPositionLabel') .bindEvent({ anyclick: toggleTime }) .appendTo(that); self.$positionSlider = Ox.Range({ changeOnDrag: true, max: 1, min: 0, step: 0.0000001, }) .addClass('OxPositionSlider') .bindEvent({ change: function(data) { setPosition(data.value * self.duration); } }) .appendTo(that); self.$muteButton = Ox.Button({ overlap: 'right', title: 'mute', tooltip: Ox._('Mute'), type: 'image' }) .addClass('OxMuteButton') .bindEvent({ click: toggleMuted }) .appendTo(that); self.$volumeLabel = Ox.Label({ textAlign: 'center', title: '  100%', width: 46 }) .addClass('OxVolumeLabel') .bindEvent({ anyclick: function() { setVolume(1); } }) .appendTo(that); self.$volumeSlider = Ox.Range({ changeOnDrag: true, max: 1, min: 0, size: 116, step: 0.01, value: self.options.volume, }) .addClass('OxVolumeSlider') .bindEvent({ change: function(data) { setVolume(data.value); } }) .appendTo(that); self.$audio = Ox.AudioElement({ src: self.options.audio[self.options.track].file }) .bindEvent({ ended: function() { playNext(); }, loadedmetadata: function(data) { self.duration = data.duration; } }) .appendTo(that); setTrack(self.options.track); function formatTrack(data) { return [ data.name, data.artist, data.album, data.year ].join(' · '); } function getButtonOptions(id) { var options; if (id == 'mute') { options = self.options.muted || self.options.volume == 0 ? {title: 'unmute', tooltip: Ox._('Unmute')} : self.options.volume < 1/3 ? {title: 'volumeUp', tooltip: Ox._('Mute')} : self.options.volume < 2/3 ? {title: 'volumeDown', tooltip: Ox._('Mute')} : {title: 'mute', tooltip: Ox._('Mute')}; } else if (id == 'play') { options = self.options.paused ? {title: 'play', tooltip: Ox._('Play')} : {title: 'pause', tooltip: Ox._('Pause')}; } else if (id == 'repeat') { options = self.options.repeat == 0 ? {title: 'repeatNone', tooltip: Ox._('Repeat All')} : self.options.repeat == -1 ? {title: 'repeatAll', tooltip: Ox._('Repeat One')} : {title: 'repeatOne', tooltip: Ox._('Repeat None')}; } else if (id == 'shuffle') { options = self.options.shuffle ? {title: 'shuffleAll', tooltip: Ox._('Don\'t Shuffle')} : {title: 'shuffleNone', tooltip: Ox._('Shuffle')}; } return options; } function getNextTrack() { return self.options.repeat == 1 ? self.options.track : self.options.track < self.tracks - 1 ? self.options.track + 1 : self.options.repeat == -1 ? 0 : null; } function playing() { self.options.position = self.$audio.currentTime(); setPosition(self.options.position, 'audio') that.triggerEvent('playing', {position: self.options.position}); } function playNext() { var track = getNextTrack(); if (track === null) { // ... } else { setTrack(track); } } function setPosition(position, from) { self.options.position = position; if (from != 'audio') { self.$audio.currentTime(position); } self.$positionSlider.options({ value: position / self.duration }); setTime(); } function setRepeat(repeat) { self.options.repeat = repeat; self.$repeatButton.options(getButtonOptions('repeat')); } function setSizes() { that.css({width: self.options.width + 'px'}); self.$trackLabel.options({width: self.options.width - 46}); self.$positionSlider.options({size: self.options.width - 262}); self.$positionLabel.css({left: self.options.width - 232 + 'px'}); self.$volumeLabel.css({left: self.options.width - 46 + 'px'}) } function setTime() { self.$positionLabel.options({ title: Ox.formatDuration( self.options.time == 'elapsed' ? self.options.position : self.options.audio[self.options.track].duration - self.options.position ) }); } function setTrack(track) { self.options.track = track; self.$trackLabel.options({ title: formatTrack(self.options.audio[track]) }); self.$audio.options({src: self.options.audio[self.options.track].file}); !self.options.paused && self.$audio.play(); that.triggerEvent('track', {track: self.options.track}); } function setVolume(volume) { self.options.volume = volume; if (volume > 0) { self.volume = volume; } self.$audio.volume(volume); self.$muteButton.options(getButtonOptions('mute')); self.$volumeSlider.options({value: volume}); self.$volumeLabel.options({ title: '  ' + Math.round(volume * 100) + '%' }); } function toggleMuted() { self.options.muted = !self.options.muted; setVolume(self.options.muted ? 0 : self.volume); } function togglePaused() { self.options.paused = !self.options.paused; self.$playButtons.buttonOptions('play', getButtonOptions('play')); if (self.options.paused) { self.$audio.pause(); clearInterval(self.playInterval); } else { self.$audio.play(); self.playInterval = setInterval(playing, 100); } that.triggerEvent('paused', {paused: self.options.paused}); } function toggleShuffle() { self.options.shuffle = !self.options.shuffle; self.$shuffleButton.options(getButtonOptions('shuffle')) } function toggleTime() { self.options.time = self.options.time == 'remaining' ? 'elapsed' : 'remaining'; setTime(); } return that; };