12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143 |
- /*
- Amplitude.js
- Version: 2.2
- */
- var Amplitude = (function () {
- /*
- |--------------------------------------------------------------------------
- | Initializers
- |--------------------------------------------------------------------------
- | When the document is ready, Amplitude goes through and finds the elements
- | that should have event listeners and binds them. Next it will set up all
- | of the song time visualizations. These visualizations simply show the
- | proportion of the song time that has elapsed with respect to the container
- | element. These are NOT the visualizations for audio frequencies that are
- | artistic. It's a div that fills with another div representing the song time.
- */
- document.onreadystatechange = function () {
- if( document.readyState == "complete" ){
- privateInitializeEventHandlers();
- privateInitializeSongTimeVisualizations();
- }
- }
- /*
- |--------------------------------------------------------------------------
- | Module Variables
- |--------------------------------------------------------------------------
- | These variables make Amplitude run. The config is the most important
- | containing active settings and parameters. The Web Audio API variables
- | for visualizations are below.
- */
- /*--------------------------------------------------------------------------
- The config JSON is the global settings for ALL of Amplitude functions.
- This is global and contains all of the user preferences. The default
- settings are set, and the user overwrites them when they initialize
- Amplitude.
- --------------------------------------------------------------------------*/
- var config = {
- /*
- The audio element we will be using to handle all of the audio. This
- is the javascript version of the HTML5 audio element.
- */
- active_song: new Audio(),
- /*
- JSON object that contains the active metadata for the song.
- */
- active_metadata: {},
- /*
- String to hold the active album name. Used to check and see if the
- album changed and run the album changed callback.
- */
- active_album: '',
- /*
- Contains the index of the actively playing song.
- */
- active_index: 0,
- /*
- Set to true to autoplay the song
- */
- autoplay: false,
- /*
- Used to determine if the album has changed and run the callback if it
- has.
- */
- album_change: false,
- /*
- The user can set dynamic_mode to true and dynamic mode will be enabled
- allowing the user to pass a JSON representation of a song when they
- want to play it and utilize the Amplitude events to control it. The
- user also doesn't have to config songs to use dynamic mode.
- */
- dynamic_mode: false,
- /*
- The user can pass a JSON object with a key => value store of callbacks
- to be run at certain events.
- */
- callbacks: {},
- /*
- Object containing all of the songs the user has passed to Amplitude
- to use.
- */
- songs: {},
- /*
- When repeat is on, when the song ends the song will replay itself.
- */
- repeat: false,
- /*
- When shuffled, this gets populated with the songs the user provided
- in a random order.
- */
- shuffle_list: {},
- /*
- When shuffled is turned on this gets set to true so when traversing
- through songs Amplitude knows whether or not to use the songs object
- or the shuffle_list.
- */
- shuffle_on: false,
- /*
- When shuffled, this index is used to let Amplitude know where it's
- at when traversing.
- */
- shuffle_active_index: 0,
- /*
- The user can set default album art to be displayed if the song they
- set doesn't contain album art.
- */
- default_album_art: '',
- /*
- When set to true, Amplitude will print to the console any errors
- that it runs into providing helpful feedback to the user.
- */
- debug: false,
- /*
- When Amplitude finishes initializing, this is set to true. When set
- to true, Amplitude cannot be initialized again preventing double
- event handlers.
- */
- initialized: false,
- /*
- By default this is true, but if the user wanted to hard code elements
- with song data, they could set this to false and Amplitude wouldn't
- edit the now playing information in elements.
- */
- handle_song_elements: true,
- /*
- The user can set the initial volume to a number between 0 and 1
- overridding a default of .5.
- */
- volume: .5,
- /*
- This is set on mute so that when a user un-mutes Amplitude knows
- what to restore the volume to.
- */
- pre_mute_volume: .5,
- /*
- This is an integer between 1 and 100 for how much the volume should
- increase when the user presses a volume up button.
- */
- volume_increment: 5,
- /*
- This is an integer between 1 and 100 for how much the volume should
- decrease when the user presses a volume down button.
- */
- volume_decrement: 5,
- /*
- To use visualizations with Amplitude, the user will set this to true.
- It is assumed that the user has thoroughly tested thier songs and have
- a back up plan in place if the browser doesn't support the Web Audio API.
- By doing this, we bypass a lot of unforseen errors with auto binding
- the web audio API to songs that don't need visualizations.
- */
- use_visualizations: false,
- /*
- Handles all of the user registered visualizations if the user chooses
- to use visualizations in their design.
- */
- visualizations: new Array(),
- /*
- Is set to the active visualization so Amplitude can detect changes
- per song if necessary.
- */
- active_visualization: '',
- /*
- Holds the information the user defined about the current visualization,
- such as preferences.
- */
- current_visualization: {},
- /*
- When the visualization is started, this is set to true.
- */
- visualization_started: false,
- /*
- If the browser doesn't support visualizations, the user can provide
- a back up. 'nothing' is the default which removes the visualization
- element from the document. 'album-art' has Amplitude inject the now
- playing album art into the element that would have contained the
- visualization.
- */
- visualization_backup: '',
- /*
- When using SoundCloud, the user will have to provide their API Client
- ID
- */
- soundcloud_client: '',
- /*
- The user can set this to true and Amplitude will use the album art
- for the song returned from the Soundcloud API
- */
- soundcloud_use_art: false,
- /*
- Used on config to count how many songs are from soundcloud and
- compare it to how many are ready for when to move to the rest
- of the configuration.
- */
- soundcloud_song_count: 0,
- /*
- Used on config to count how many songs are ready so when we get
- all of the data from the SoundCloud API that we need this should
- match the SoundCloud song count meaning we can move to the rest
- of the config.
- */
- soundcloud_songs_ready: 0,
- /*--------------------------------------------------------------------------
- These are web audio API variables. They connect the web audio
- api to the audio source allowing for visualization extensions.
- These variables are public and to be used for extensions.
- Initializes the variables if they are available.
- --------------------------------------------------------------------------*/
- context: '',
- analyser: '',
- source: ''
- };
- /*--------------------------------------------------------------------------
- Used with SoundCloud to copy over the user config and add
- extra data so it doesn't interfere with the actual user
- config.
- --------------------------------------------------------------------------*/
- var temp_user_config = {};
-
- /*
- |--------------------------------------------------------------------------
- | PUBLIC METHODS
- |--------------------------------------------------------------------------
- | These methods are available to the developer. They allow the developer
- | to change certain attributes if needed and configure the library.
- */
- /*--------------------------------------------------------------------------
- The main init function. The user will call this through
- Amplitude.init({}) and pass in their settings.
-
- Public Accessor: Amplitude.init( user_config_json );
- @param user_config A JSON object of user defined values that help
- configure and initialize AmplitudeJS.
- --------------------------------------------------------------------------*/
- function publicInit( user_config ){
- /*
- Checks to see if Amplitude has been initialized.
- If it hasn't then we can initialize AmplitudeJS.
- The reason we check is so the same event handler
- isn't bound twice to the same element.
- */
- if( !config.initialized ){
- /*
- Initializes debugging right away so we can use it for the rest
- of the configuration.
- */
- config.debug = ( user_config.debug != undefined ? user_config.debug : false );
- /*
- Checks for dynamic mode right away. This will determine whether
- not having songs is a critical error or not since dynamic mode
- allows you to play songs by passing them in dynamically.
- */
- config.dynamic_mode = ( user_config.dynamic_mode != undefined ? user_config.dynamic_mode : false );
-
- /*
- To use visualizations with Amplitude, the user will have to explicitly state
- that their player uses visualizations. Reason being is that the AudioContext
- and other filters can really mess up functionality if the user is not prepared
- to have them operate on their audio element. If set to true, then the
- AudioContext and the other necessary elements will be bound for the Web Audio API
- to handle the visualization processing.
- */
- config.use_visualizations = ( user_config.use_visualizations != undefined ? user_config.use_visualizations : false );
-
- /*
- If the browser supports it and the user wants to use
- visualizations, then they can run visualizations. If
- the browser does not support the Web Audio API and the
- user has debug turned on, write to the console.
- */
- if( window.AudioContext && config.use_visualizations ){
- config.context = new AudioContext();
- config.analyser = config.context.createAnalyser();
- config.source = config.context.createMediaElementSource( config.active_song );
- config.source.connect( config.analyser );
-
- config.analyser.connect( config.context.destination );
- config.active_song.crossOrigin = "anonymous";
- }else{
- if( !window.AudioContext ){
- privateWriteDebugMessage( 'This browser does not support the Web Audio API' );
- }
- }
- /*
- The first step in setting up Amplitude is copying over all of
- the song objects that the user wants to use.
- */
- var ready = false;
- /*
- This copies over all of the user defined songs and adds them
- to the amplitude config.
- First check is to see if Amplitude is in Dynamic Mode which
- means that the user will be selecting sending songs dynamically
- and using a global control set to control the functionality.
- This is the ONLY scenario that doesn't require song(s) object.
- */
- if( !user_config.dynamic_mode ){
- /*
- Checks to see if the user defined any songs.
- If there are no song definitions, then it's
- a critical error since Amplitude needs that to
- run.
- */
- if( user_config.songs ){
- /*
- Makes sure the songs length is not 0, meaning
- that there is at least 1 song.
- */
- if( user_config.songs.length != 0 ){
- /*
- Copies over the user defined songs. and prepares
- Amplitude for the rest of the configuration.
- */
- config.songs = user_config.songs;
- ready = true;
- }else{
- privateWriteDebugMessage( 'Please add some songs, to your songs object!' );
- }
- }else{
- privateWriteDebugMessage( 'Please provide a songs object for AmplitudeJS to run!' );
- }
- }else{
- /*
- We are ready to copy over the rest of the information
- since we are in dynamic mode.
- */
- ready = true;
- }
-
- /*
- When the preliminary config is ready, we are rady to proceed.
- */
- if( ready ){
- /*
- Copies over the soundcloud information to the global config
- which will determine where we go from there.
- */
- config.soundcloud_client = ( user_config.soundcloud_client != undefined ? user_config.soundcloud_client : '' );
- config.soundcloud_use_art = ( user_config.soundcloud_use_art != undefined ? user_config.soundcloud_use_art : '' );
-
- /*
- If the user provides a soundcloud client then we assume that
- there are URLs in their songs that will reference SoundcCloud.
- We then copy over the user config they provided to the
- temp_user_config so we don't mess up the global or their configs
- and load the soundcloud information.
- */
- if( config.soundcloud_client != '' ){
- temp_user_config = user_config;
- /*
- Load up SoundCloud for use with AmplitudeJS.
- */
- privateLoadSoundcloud();
- }else{
- /*
- The user is not using Soundcloud with Amplitude at this point
- so we just finish the configuration with the users's preferences.
- */
- privateSetConfig( user_config );
- }
- }
- }
- }
- /*--------------------------------------------------------------------------
- Allows the user to turn on debugging.
-
- Public Accessor: Amplitude.setDebug( bool );
-
- @param BOOL state Turns debugging on and off.
- --------------------------------------------------------------------------*/
- function publicSetDebug( state ){
- /*
- Sets the global config debug on or off.
- */
- config.debug = state;
- }
- /*--------------------------------------------------------------------------
- Returns the active song meta data for the user to do what is
- needed.
-
- Public Accessor: Amplitude.getActiveSongMetadata();
-
- @returns JSON Object with the active song information
- --------------------------------------------------------------------------*/
- function publicGetActiveSongMetadata(){
- return config.active_metadata;
- }
- /*--------------------------------------------------------------------------
- Registers a visualization and sets that visualization's
- preferences. When creating a visualization, you can set certain
- preferences that the user can overwrite similar to Amplitude.
- Public Accessor: Amplitude.registerVisualization( visualization, preferences )
- @param visualzation A visualization object that gets registered
- with Amplitude
- @param preferences A JSON object of preferences relating to the
- visualization
- --------------------------------------------------------------------------*/
- function publicRegisterVisualization( visualization, preferences ){
- /*
- Adds the visualization to the global config so it knows
- it can be used when playing songs.
- getID is a public function for getting a visualization's id.
- It becomes the key to access the visualization.
- */
- config.visualizations[ visualization.getID ] = visualization;
-
- /*
- If defined, set the visualization preferences.
- setPreferences is a public function for connecting
- to a user defined visualization.
- */
- if( preferences != undefined ){
- visualization.setPreferences( preferences );
- }
- }
- /*--------------------------------------------------------------------------
- Changes the active visualization. Could be called from a
- user defined dropdown or whatever way the user wants to change a
- visualization dynamically.
-
- Public Accessor: Amplitude.changeVisualization( visualization )
- @param string visualization The name of the visualization
- that should be used.
- --------------------------------------------------------------------------*/
- function publicChangeActiveVisualization( visualization ){
- /*
- First we stop the active visualization. If the visualization
- is set up correctly, it should halt all callbacks, and clear
- the amplitude-visualization element.
- */
- privateStopVisualization();
- /*
- Next we set the active visualization in the config.
- */
- config.active_visualization = visualization;
- /*
- We then start the visualization hooks again. This should
- insert itself into the amplitude-visualization element
- and bind the proper hooks.
- */
- privateStartVisualization();
- }
- /*--------------------------------------------------------------------------
- Checks to see if the current browser is capable of running
- visualizations. If the AudioContext is available, then the browser
- can play the visualization.
-
- Public Accessor: Amplitude.visualizationCapable()
-
- @returns BOOL true if the browser can play the visualization and false
- if the browser cannot.
- --------------------------------------------------------------------------*/
- function publicVisualizationCapable(){
- if ( !window.AudioContext ) {
- return false;
- }else{
- return true;
- }
- }
- /*--------------------------------------------------------------------------
- Returns a song in the songs array at that index
-
- Public Accessor: Amplitude.getSongByIndex( song_index )
- @param int index The integer for the index of the
- song in the songs array.
- @returns JSON representation for the song at a specific index.
- --------------------------------------------------------------------------*/
- function publicGetSongByIndex( index ){
- return config.songs[index];
- }
- /*--------------------------------------------------------------------------
- Adds a song to the end of the config array. This will allow Amplitude
- to play the song in a playlist type setting.
-
- Public Accessor: Amplitude.addSong( song_json )
- @param song JSON representation of a song.
- @returns int New index of the song.
- --------------------------------------------------------------------------*/
- function publicAddSong( song ){
- config.songs.push( song );
- return config.songs.length - 1;
- }
- /*--------------------------------------------------------------------------
- When you pass a song object it plays that song right awawy. It sets
- the active song in the config to the song you pass in and synchronizes
- the visuals.
-
- Public Accessor: Amplitude.playNow( song_json )
- @param song JSON representation of a song.
- --------------------------------------------------------------------------*/
- function publicPlayNow( song ){
- /*
- Makes sure the song object has a URL associated with it
- or there will be nothing to play.
- */
- if( song.url ){
- config.active_song.src = song.url;
- config.active_metadata = song;
- config.active_album = song.album;
- }else{
- privateWriteDebugMessage('The song needs to have a URL!');
- }
-
- /*
- Sets the main song control status visual
- */
- privateChangePlayPauseState('playing');
- /*
- Calls the song change method that configures everything necessary for
- Amplitude when the song changes.
- */
- privateAfterSongChanges();
- }
- /*--------------------------------------------------------------------------
- Allows the user to play whatever the active song is directly
- through Javascript. Normally ALL of Amplitude functions that access
- the core features are called through event handlers. However when in
- dynamic mode is enabled, you will need to call this directly.
- WARNING: Accessible ONLY if dynmaic mode is turned on.
- Public Accessor: Amplitude.play();
- --------------------------------------------------------------------------*/
- function publicPlay(){
- if( config.dynamic_mode ){
- privatePlay();
- }
- }
- /*--------------------------------------------------------------------------
- Allows the user to pause whatever the active song is directly
- through Javascript. Normally ALL of Amplitude functions that access
- the core features are called through event handlers. However when in
- dynamic mode is enabled, you will need to call this directly.
- WARNING: Accessible ONLY if dynmaic mode is turned on.
- Public Accessor: Amplitude.pause();
- --------------------------------------------------------------------------*/
- function publicPause(){
- if( config.dynamic_mode ){
- privatePause();
- }
- }
- function publicGetAnalyser(){
- return config.analyser;
- }
- /*
- |--------------------------------------------------------------------------
- | INITIALIZATION FUNCTIONS
- |--------------------------------------------------------------------------
- | CALLED ON INITIALIZATION
- |
- | These functions are called on initialization and configure the base
- | functionality for Amplitude. They init event handlers and set up the
- | song time visualizations.
- */
- /*--------------------------------------------------------------------------
- Binds all AmplitudeJS event handlers to their respective elements.
- This is a special function that is ONLY called once the document
- is initialized. If it is called more than once than more than one
- event handler will be bound to an individual element causing chaos.
- If the navigator is a mobile device, the event bound for user
- interaction is 'touchstart', otherwise it is 'click' for the majority
- of the AmplitudeJS elements.
- The 'input' interaction is used for the HTML5 Range song sliders.
- The events 'timeupdate' and 'ended' are bound to the javascript
- audio element.
- --------------------------------------------------------------------------*/
- function privateInitializeEventHandlers(){
- /*
- On time update for the audio element, update visual displays that
- represent the time on either a visualized element or time display.
- */
- config.active_song.addEventListener('timeupdate', privateUpdateTime );
- /*
- When the audio element has ended playing, we handle the song
- ending. In a single song or multiple modular song instance,
- this just synchronizes the visuals for time and song time
- visualization, but for a playlist it determines whether
- it should play the next song or not.
- */
- config.active_song.addEventListener('ended', privateHandleSongEnded );
- /*
- Binds handlers for play classes
- */
- var play_classes = document.getElementsByClassName("amplitude-play");
- for( var i = 0; i < play_classes.length; i++ ){
- if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
- play_classes[i].addEventListener('touchstart', privatePlayClickHandle );
- }else{
- play_classes[i].addEventListener('click', privatePlayClickHandle );
- }
- }
- /*
- Binds handlers for pause classes
- */
- var pause_classes = document.getElementsByClassName("amplitude-pause");
- for( var i = 0; i < pause_classes.length; i++ ){
- if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
- pause_classes[i].addEventListener('touchstart', privatePauseClickHandle );
- }else{
- pause_classes[i].addEventListener('click', privatePauseClickHandle );
- }
- }
- /*
- Binds handlers for stop classes
- */
- var stop_classes = document.getElementsByClassName("amplitude-stop");
- for( var i = 0; i < stop_classes.length; i++ ){
- if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
- stop_classes[i].addEventListener('touchstart', privateStopClickHandle );
- }else{
- stop_classes[i].addEventListener('click', privateStopClickHandle );
- }
- }
- /*
- Binds handlers for play/pause classes
- */
- var play_pause_classes = document.getElementsByClassName("amplitude-play-pause");
- for( var i = 0; i < play_pause_classes.length; i++ ){
- if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
- play_pause_classes[i].addEventListener('touchstart', privatePlayPauseClickHandle );
- }else{
- play_pause_classes[i].addEventListener('click', privatePlayPauseClickHandle );
- }
- }
- /*
- Binds handlers for mute classes
- WARNING: If iOS, we don't do anything because iOS does not allow the
- volume to be adjusted through anything except the buttons on the side of
- the device.
- */
- var mute_classes = document.getElementsByClassName("amplitude-mute");
- for( var i = 0; i < mute_classes.length; i++ ){
- if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
- /*
- Checks for an iOS device and displays an error message if debugging
- is turned on.
- */
- if( /iPhone|iPad|iPod/i.test(navigator.userAgent) ) {
- privateWriteDebugMessage( 'iOS does NOT allow volume to be set through javascript: https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html#//apple_ref/doc/uid/TP40009523-CH5-SW4' );
- }else{
- mute_classes[i].addEventListener('touchstart', privateMuteClickHandle );
- }
- }else{
- mute_classes[i].addEventListener('click', privateMuteClickHandle );
- }
- }
- /*
- Binds handlers for volume up classes
- WARNING: If iOS, we don't do anything because iOS does not allow the
- volume to be adjusted through anything except the buttons on the side of
- the device.
- */
- var volume_up_classes = document.getElementsByClassName("amplitude-volume-up");
- for( var i = 0; i < volume_up_classes.length; i++ ){
- if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
- /*
- Checks for an iOS device and displays an error message if debugging
- is turned on.
- */
- if( /iPhone|iPad|iPod/i.test(navigator.userAgent) ) {
- privateWriteDebugMessage( 'iOS does NOT allow volume to be set through javascript: https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html#//apple_ref/doc/uid/TP40009523-CH5-SW4' );
- }else{
- volume_up_classes[i].addEventListener('touchstart', privateVolumeUpClickHandle );
- }
- }else{
- volume_up_classes[i].addEventListener('click', privateVolumeUpClickHandle );
- }
- }
- /*
- Binds handlers for volume down classes
- WARNING: If iOS, we don't do anything because iOS does not allow the
- volume to be adjusted through anything except the buttons on the side of
- the device.
- */
- var volume_down_classes = document.getElementsByClassName("amplitude-volume-down");
-
- for( var i = 0; i < volume_down_classes.length; i++ ){
- if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
- /*
- Checks for an iOS device and displays an error message if debugging
- is turned on.
- */
- if( /iPhone|iPad|iPod/i.test(navigator.userAgent) ) {
- privateWriteDebugMessage( 'iOS does NOT allow volume to be set through javascript: https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html#//apple_ref/doc/uid/TP40009523-CH5-SW4' );
- }else{
- volume_down_classes[i].addEventListener('touchstart', privateVolumeDownClickHandle );
- }
- }else{
- volume_down_classes[i].addEventListener('click', privateVolumeDownClickHandle );
- }
- }
- /*
- Binds handlers for song slider classes. The song sliders are HTML 5
- Range Elements. This event fires everytime a slider has changed.
- */
- var song_sliders = document.getElementsByClassName("amplitude-song-slider");
- for( var i = 0; i < song_sliders.length; i++ ){
- song_sliders[i].addEventListener('input', privateSongStatusBarInputHandle );
- }
- /*
- Binds handlers for volume slider classes. The volume sliders are HTML 5
- Range Elements. This event fires everytime a slider has changed.
- WARNING: If iOS, we don't do anything because iOS does not allow the
- volume to be adjusted through anything except the buttons on the side of
- the device.
- */
- var volume_sliders = document.getElementsByClassName("amplitude-volume-slider");
- for( var i = 0; i < volume_sliders.length; i++ ){
- /*
- Checks for an iOS device and displays an error message if debugging
- is turned on.
- */
- if( /iPhone|iPad|iPod/i.test(navigator.userAgent) ) {
- privateWriteDebugMessage( 'iOS does NOT allow volume to be set through javascript: https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html#//apple_ref/doc/uid/TP40009523-CH5-SW4' );
- }else{
- volume_sliders[i].addEventListener('input', privateVolumeInputHandle );
- }
- }
- /*
- Binds handlers for next button classes.
- */
- var next_classes = document.getElementsByClassName("amplitude-next");
- for( var i = 0; i < next_classes.length; i++ ){
- if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
- next_classes[i].addEventListener('touchstart', privateNextClickHandle );
- }else{
- next_classes[i].addEventListener('click', privateNextClickHandle );
- }
- }
- /*
- Binds handlers for previous button classes.
- */
- var prev_classes = document.getElementsByClassName("amplitude-prev");
- for( var i = 0; i < prev_classes.length; i++ ){
- if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
- prev_classes[i].addEventListener('touchstart', privatePrevClickHandle );
- }else{
- prev_classes[i].addEventListener('click', privatePrevClickHandle );
- }
- }
- /*
- Binds handlers for shuffle button classes.
- */
- var shuffle_classes = document.getElementsByClassName("amplitude-shuffle");
- for( var i = 0; i < shuffle_classes.length; i++ ){
- shuffle_classes[i].classList.remove('amplitude-shuffle-on');
- shuffle_classes[i].classList.add('amplitude-shuffle-off');
- if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
- shuffle_classes[i].addEventListener('touchstart', privateShuffleClickHandle );
- }else{
- shuffle_classes[i].addEventListener('click', privateShuffleClickHandle );
- }
- }
- /*
- Binds handlers for repeat button classes.
- */
- var repeat_classes = document.getElementsByClassName("amplitude-repeat");
- for( var i = 0; i < repeat_classes.length; i++ ){
- repeat_classes[i].classList.remove('amplitude-repeat-on');
- repeat_classes[i].classList.add('amplitude-repeat-off');
- if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
- repeat_classes[i].addEventListener('touchstart', privateRepeatClickHandle );
- }else{
- repeat_classes[i].addEventListener('click', privateRepeatClickHandle );
- }
- }
- }
- /*--------------------------------------------------------------------------
- Sets up all of the song time visualizations. This is the only time
- that AmplitudeJS will add an element to the page. AmplitudeJS will
- add an element inside of the song time visualization element that will
- expand proportionally to the amount of time elapsed on the active
- audio, thus visualizing the song time. This element is NOT user
- interactive. To have the user scrub the time, they will have to
- style and implement a song time slider with an HTML 5 Range Element.
- --------------------------------------------------------------------------*/
- function privateInitializeSongTimeVisualizations(){
- /*
- Sets up song time visualizations
- */
- var song_time_visualizations = document.getElementsByClassName("amplitude-song-time-visualization");
- /*
- Iterates through all of the amplitude-song-time-visualization
- elements adding a new div with a class of
- 'amplitude-song-time-visualization-status' that will expand
- inside of the 'amplitude-song-time-visualization' element.
- */
- for( var i = 0; i < song_time_visualizations.length; i++ ){
- /*
- Creates new element
- */
- var status = document.createElement('div');
- /*
- Adds class and attributes
- */
- status.classList.add('amplitude-song-time-visualization-status');
- status.setAttribute( 'style', 'width: 0px' );
- /*
- Appends the element as a child element.
- */
- song_time_visualizations[i].appendChild( status );
- }
- }
- /*
- |--------------------------------------------------------------------------
- | EVENT HANDLER FUNCTIONS
- |--------------------------------------------------------------------------
- | These functions handle the events that we bound to each element and
- | prepare for a function to be called. For example, if a click is on a song
- | that doens't equal the index of the active song, it sets the active song
- | to be what is needed and then play is called. These kind of act
- | like filters/middleware.
- */
- /*--------------------------------------------------------------------------
- HANDLER FOR: 'amplitude-play-pause';
- Handles a click on a play/pause element. This element toggles
- functionality based on the state of the song.
- TODO: Clean up this function and break out into helper functions
- --------------------------------------------------------------------------*/
- function privatePlayPauseClickHandle(){
- /*
- If there are multiple play/pause buttons on the screen,
- you can have them assigned to an individual song.
- With the amplitude-song-index attribute, you can assign
- the play buttons a song to play out of the songs array.
- */
- var playing_song_index = this.getAttribute('amplitude-song-index');
- /*
- If there is a new song to be played. Since this handler
- handles ALL events on a play-pause element, we have
- to check to see if there is a song that is being
- played already and the user clicked a different element
- of the same type that is supposed to play a new song.
- */
- if( privateCheckNewSong( playing_song_index) ){
- privateChangeSong( playing_song_index );
- /*
- Sets all song status and play/pause button visuals
- to sync with the newly played song.
- */
- privateSetPlayPauseButtonsToPause();
- privateResetSongStatusSliders();
- privateChangePlayPauseState('playing');
-
- /*
- Starts the song visualization if there is one.
- */
- privateStartVisualization();
- privatePlay();
- }else{
- if( config.active_song.paused ){
-
- privateChangePlayPauseState('playing');
- /*
- Starts the song visualization if there is one.
- */
- privateStartVisualization();
- privatePlay( this.getAttribute('amplitude-song-index') );
- }else{
- privateChangePlayPauseState('paused');
- privatePause();
- }
- }
- }
- /*--------------------------------------------------------------------------
- HANDLER FOR: 'amplitude-play'
- Handles a click on a play element.
- TODO: Check to see if we should start the visualizations and run the
- play or check to see if the song clicked is not new and paused before
- we run those otherwise it might cause an error like re-starting the
- song if play is clicked twice.
- --------------------------------------------------------------------------*/
- function privatePlayClickHandle(){
- /*
- Gets the attribute for song index so we can check if
- there is a need to change the song. In some scenarios
- there might be multiple play classes on the page. In that
- case it is possible the user could click a different play
- class and change the song.
- */
- var playing_song_index = this.getAttribute('amplitude-song-index');
- /*
- We set the new song if the user clicked a song with a different
- index. If it's the same as what's playing then we don't set anything.
- If it's different we reset all song sliders.
- */
- if( privateCheckNewSong( playing_song_index ) ){
- privateChangeSong( playing_song_index );
- privateResetSongStatusSliders();
- }
- /*
- Start the visualizations for the song.
- */
- privateStartVisualization();
-
- /*
- Play the song through the core play function.
- */
- privatePlay();
- }
- /*--------------------------------------------------------------------------
- HANDLER FOR: 'amplitude-pause'
- Handles a click on a pause element.
- TODO: Check to see that the pause element has an index and if that
- index matches the current song being played. If it's different then
- we should disable it? If the user clicks on song-index=1 pause and
- song-index=2 is being played, is it right to pause?
- --------------------------------------------------------------------------*/
- function privatePauseClickHandle(){
- /*
- Calls the core function for pause
- */
- privatePause();
- }
- /*--------------------------------------------------------------------------
- HANDLER FOR: 'amplitude-stop'
- Handles a click on a stop element.
- --------------------------------------------------------------------------*/
- function privateStopClickHandle(){
- /*
- Calls the helper function to stop
- the visualization.
- */
- privateStopVisualization();
- /*
- Calls the core function for stop
- */
- privateStop();
- }
- /*--------------------------------------------------------------------------
- HANDLER FOR: 'amplitude-mute'
- Handles a click on a mute element.
- TODO: Add a class if muted to this element of amplitude-mute. That way
- the designer can style the element if amplitude is muted like the typical
- volume with a line through it.
- TODO: Standardize the privateSetVolume parameter so it doesn't need
- to be converted by the privateSetVolume function. Right now it converts
- up then down again which makes no sense.
- --------------------------------------------------------------------------*/
- function privateMuteClickHandle(){
- /*
- If the current volume in the config is 0, we set the volume to the
- pre_mute level. This means that the audio is already muted and
- needs to be restored to the pre_mute level.
-
- Otherwise, we set pre_mute volume to the current volume
- and set the config volume to 0, muting the audio.
- */
- if( config.volume == 0 ){
- config.volume = config.pre_mute_volume;
- }else{
- config.pre_mute_volume = config.volume;
- config.volume = 0;
- }
- /*
- Calls the core function to set the volume to the computed value
- based on the user's intent.
- */
- privateSetVolume( config.volume * 100 );
- /*
- Syncs the volume sliders so the visuals align up with the functionality.
- If the volume is at 0, then the sliders should represent that so the user
- has the right starting point.
- */
- privateSyncVolumeSliders();
- }
- /*--------------------------------------------------------------------------
- HANDLER FOR: 'amplitude-volume-up'
- Handles a click on a volume up element.
- TODO: Standardize the privateSetVolume parameter so it doesn't need
- to be converted by the privateSetVolume function. Right now it converts
- up then down again which makes no sense.
- --------------------------------------------------------------------------*/
- function privateVolumeUpClickHandle(){
- /*
- The volume range is from 0 to 1 for an audio element. We make this
- a base of 100 for ease of working with.
- If the new value is less than 100, we use the new calculated
- value which gets converted to the proper unit for the audio element.
- If the new value is greater than 100, we set the volume to 1 which
- is the max for the audio element.
- */
- if( ( ( config.volume * 100 ) + config.volume_increment ) <= 100 ){
- config.volume = config.volume + ( config.volume_increment / 100 );
- }else{
- config.volume = 1;
- }
- /*
- Calls the core function to set the volume to the computed value
- based on the user's intent.
- */
- privateSetVolume( config.volume * 100 );
- /*
- Syncs the volume sliders so the visuals align up with the functionality.
- If the volume is at 0, then the sliders should represent that so the user
- has the right starting point.
- */
- privateSyncVolumeSliders();
- }
- /*--------------------------------------------------------------------------
- HANDLER FOR: 'amplitude-volume-down'
- Handles a click on a volume down element.
- TODO: Standardize the privateSetVolume parameter so it doesn't need
- to be converted by the privateSetVolume function. Right now it converts
- up then down again which makes no sense.
- --------------------------------------------------------------------------*/
- function privateVolumeDownClickHandle(){
- /*
- The volume range is from 0 to 1 for an audio element. We make this
- a base of 100 for ease of working with.
- If the new value is less than 0, we use the new calculated
- value which gets converted to the proper unit for the audio element.
- If the new value is greater than 0, we set the volume to 0 which
- is the min for the audio element.
- */
- if( ( ( config.volume * 100 ) - config.volume_decrement ) > 0 ){
- config.volume = config.volume - ( config.volume_decrement / 100 );
- }else{
- config.volume = 0;
- }
- /*
- Calls the core function to set the volume to the computed value
- based on the user's intent.
- */
- privateSetVolume( config.volume * 100 );
- /*
- Syncs the volume sliders so the visuals align up with the functionality.
- If the volume is at 0, then the sliders should represent that so the user
- has the right starting point.
- */
- privateSyncVolumeSliders();
- }
- /*--------------------------------------------------------------------------
- HANDLER FOR: 'amplitude-volume-slider'
- Handles an input change for a volume slider.
- TODO: Standardize the privateSetVolume parameter so it doesn't need
- to be converted by the privateSetVolume function. Right now it converts
- up then down again which makes no sense.
- --------------------------------------------------------------------------*/
- function privateVolumeInputHandle(){
- /*
- The range slider has a range of 1 to 100 so we get the value and
- convert it to a range of 0 to 1 and set the volume.
- */
- config.volume = ( this.value / 100 );
- /*
- Calls the core function to set the volume to the computed value
- based on the user's intent.
- */
- privateSetVolume( this.value );
- /*
- Syncs the volume sliders so the visuals align up with the functionality.
- If the volume is at 0, then the sliders should represent that so the user
- has the right starting point.
- */
- privateSyncVolumeSliders();
- }
- /*--------------------------------------------------------------------------
- HANDLER FOR: 'amplitude-song-slider'
- Handles an input change for a song slider.
- TODO: Make an attribute that allows for multiple main song sliders
- allowing the active playing song to be scrubbed from multiple locations
- on the page and is always in sync.
- --------------------------------------------------------------------------*/
- function privateSongStatusBarInputHandle(){
- /*
- We only adjust the time if the song is playing. It wouldn't make
- sense if we adjusted the time while it was paused.
- */
- if( !config.active_song.paused ){
- /*
- We first check if the song slider is the only one on the page.
- If it is, we can safely assume that the slider is synced with
- the song's progression and adjust the song.
- */
- if( this.getAttribute('amplitude-singular-song-slider') ){
- privateSetSongLocation( this.value );
- }
- /*
- If the song slider has a song index, we check to see if it matches
- the active song index. If it does, then adjust the song location.
- We do this so we can have multiple Amplitude players on the same page
- and have the slider relate to the song playing.
- */
- if( this.getAttribute('amplitude-song-index') == config.active_index ){
- privateSetSongLocation( this.value );
- }
- }
- }
- /*--------------------------------------------------------------------------
- HANDLER FOR: 'amplitude-next'
- Handles a click for the next song.
- --------------------------------------------------------------------------*/
- function privateNextClickHandle(){
- /*
- Runs the before_next callback for the user to hook into.
- */
- privateRunCallback('before_next');
- /*
- Stop active song since we are moving to the next song.
- */
- privateStop();
- /*
- First we check if shuffle is on. If it is we use the shuffle array
- to select the next song. Otherwise, we go with the standard song
- array.
- Loop around songs array if at the end. We need to check if the next
- song is within array. Otherwise we reset it to 0.
- Set new song
- */
- if( config.shuffle_on ){
- if( parseInt( config.shuffle_active_index ) + 1 < config.shuffle_list.length ){
- /*
- Gets the new index in the shuffle array for the song we need.
- */
- var newIndex = parseInt( config.shuffle_active_index ) + 1;
- /*
- Check new album
- */
- privateCheckNewAlbum( config.suffle_list[ newIndex ].album );
-
- /*
- Sets the new song information in the config, so everything
- is ready to be changed.
- */
- privateSetActiveSongInformation( newIndex, config.shuffle_on );
- /*
- Checks to see if there is a new album to be played. If there
- is we fire the after_album_change callback which allows the
- developer to handler album changes which could also mean multiple
- playlists.
- */
- if( config.album_change ){
- privateRunCallback('after_album_change');
- config.album_change = false;
- }
- /*
- Sets the new shuffle active index to be used in the shuffled songs object.
- */
- config.shuffle_active_index = newIndex;
- }else{
- /*
- Check new album
- */
- privateCheckNewAlbum( config.suffle_list[0].album );
- /*
- Sets the new song information in the config, so everything
- is ready to be changed.
- */
- privateSetActiveSongInformation( 0, config.shuffle_on );
- /*
- Checks to see if there is a new album to be played. If there
- is we fire the after_album_change callback which allows the
- developer to handler album changes which could also mean multiple
- playlists.
- */
- if( config.album_change ){
- privateRunCallback('after_album_change');
- config.album_change = false;
- }
- /*
- Sets the new shuffle active index to be used in the shuffled songs object.
- */
- config.shuffle_active_index = 0;
- }
- }else{
- if( parseInt(config.active_index) + 1 < config.songs.length ){
- var newIndex = parseInt( config.active_index ) + 1;
- /*
- Check new album
- */
- privateCheckNewAlbum( config.songs[newIndex].album );
- /*
- Sets the new song information in the config, so everything
- is ready to be changed.
- */
- privateSetActiveSongInformation( newIndex, config.shuffle_on );
- /*
- Checks to see if there is a new album to be played. If there
- is we fire the after_album_change callback which allows the
- developer to handler album changes which could also mean multiple
- playlists.
- */
- if( config.album_change ){
- privateRunCallback('after_album_change');
- config.album_change = false;
- }
- /*
- Sets the new active index to be used with the songs object
- */
- config.active_index = newIndex;
- }else{
- /*
- Check new album
- */
- privateCheckNewAlbum( config.songs[0].album );
-
- /*
- Sets the new song information in the config, so everything
- is ready to be changed.
- */
- privateSetActiveSongInformation( 0, config.shuffle_on );
- /*
- Checks to see if there is a new album to be played. If there
- is we fire the after_album_change callback which allows the
- developer to handler album changes which could also mean multiple
- playlists.
- */
- if( config.album_change ){
- privateRunCallback('after_album_change');
- config.album_change = false;
- }
- /*
- Sets the new active index to be used with the songs object
- */
- config.active_index = 0;
- }
- }
-
- /*
- Sets the main song control status to be in sync with the current state
- of the song.
- */
- privateChangePlayPauseState( 'playing' );
- /*
- Runs the song change method to sync everything necessary.
- */
- privateAfterSongChanges();
- /*
- Fires the after_next callback for users to hook into.
- */
- privateRunCallback('after_next');
- }
- /*--------------------------------------------------------------------------
- HANDLER FOR: 'amplitude-prev'
- Handles a click for the previous song.
- --------------------------------------------------------------------------*/
- function privatePrevClickHandle(){
- /*
- Runs the before_prev callback for the user to hook into.
- */
- privateRunCallback('before_prev');
-
- /*
- Stop active song since we are moving to the previous song.
- */
- privateStop();
- /*
- First we check if shuffle is on. If it is we use the shuffle array to
- select the previous song. Otherwise, we go with the sandard song array.
- Loop around songs array if at the beginning. We need to check if the next
- song is within array. Otherwise we reset it to the end of the songs.
- Set new song
- */
- if( config.shuffle_on ){
- if( ( parseInt( config.shuffle_active_index ) - 1 ) >= 0 ){
- /*
- Gets the new index in the shuffle array for the song we need.
- */
- var newIndex = parseInt( config.shuffle_active_index ) - 1;
- /*
- Check new album
- */
- privateCheckNewAlbum( config.suffle_list[ newIndex ].album );
- /*
- Sets the new song information in the config, so everything
- is ready to be changed.
- */
- privateSetActiveSongInformation( newIndex, config.shuffle_on );
- /*
- Checks to see if there is a new album to be played. If there
- is we fire the after_album_change callback which allows the
- developer to handler album changes which could also mean multiple
- playlists.
- */
- if( config.album_change ){
- privateRunCallback('after_album_change');
- config.album_change = false;
- }
- /*
- Sets the new shuffle active index to be used in the shuffled songs object.
- */
- config.shuffle_active_index = newIndex;
- }else{
- /*
- Gets the new index in the shuffle array for the song we need.
- */
- var newIndex = parseInt( config.shuffle_list.length - 1 );
- /*
- Check new album
- */
- privateCheckNewAlbum( config.suffle_list[ newIndex ].album );
-
- /*
- Sets the new song information in the config, so everything
- is ready to be changed.
- */
- privateSetActiveSongInformation( newIndex, config.shuffle_on );
- /*
- Checks to see if there is a new album to be played. If there
- is we fire the after_album_change callback which allows the
- developer to handler album changes which could also mean multiple
- playlists.
- */
- if( config.album_change ){
- privateRunCallback('after_album_change');
- config.album_change = false;
- }
- /*
- Sets the new shuffle active index to be used in the shuffled songs object.
- */
- config.shuffle_active_index = newIndex;
- }
- }else{
- if( ( parseInt( config.active_index ) - 1 ) >= 0 ){
- var newIndex = parseInt( parseInt(config.active_index) - 1 );
- /*
- Check new album
- */
- privateCheckNewAlbum( config.songs[ newIndex ].album );
-
- /*
- Sets the new song information in the config, so everything
- is ready to be changed.
- */
- privateSetActiveSongInformation( newIndex, config.shuffle_on );
- /*
- Checks to see if there is a new album to be played. If there
- is we fire the after_album_change callback which allows the
- developer to handler album changes which could also mean multiple
- playlists.
- */
- if( config.album_change ){
- privateRunCallback('after_album_change');
- config.album_change = false;
- }
- /*
- Sets the new active index to be used with the songs object
- */
- config.active_index = newIndex;
- }else{
- var newIndex = config.songs.length - 1;
- /*
- Check new album
- */
- privateCheckNewAlbum( config.songs[ newIndex ].album );
-
- /*
- Sets the new song information in the config, so everything
- is ready to be changed.
- */
- privateSetActiveSongInformation( newIndex, config.shuffle_on );
- /*
- Checks to see if there is a new album to be played. If there
- is we fire the after_album_change callback which allows the
- developer to handler album changes which could also mean multiple
- playlists.
- */
- if( config.album_change ){
- privateRunCallback('after_album_change');
- config.album_change = false;
- }
- /*
- Sets the new active index to be used with the songs object
- */
- config.active_index = newIndex;
- }
- }
-
- /*
- Sets the main song control status to be in sync with the current state
- of the song.
- */
- privateChangePlayPauseState( 'playing' );
-
-
- /*
- Runs the song change method to sync everything necessary.
- */
- privateAfterSongChanges();
- /*
- Fires the after_prev callback for users to hook into.
- */
- privateRunCallback('after_prev');
- }
- /*--------------------------------------------------------------------------
- HANDLER FOR: 'ended' on main audio element.
- When the song has ended, this method gets called.
- If it's a one song instance, then we don't do anything.
- If there are multiple songs, we check if shuffle is on
- or if we should use the original songs array. Then we set
- the next song and play it.
- --------------------------------------------------------------------------*/
- function privateHandleSongEnded(){
- /*
- Checks to see if repeat is on. If it's on, then we re-play the
- current song. Otherwise we begin the process of playing the
- next song in the list whether it's shuffle or regular list or
- single song.
- */
- if( config.repeat ){
- /*
- Confirms stop of the active song
- */
- privateStop();
- /*
- Without changing the index, just prepares the
- next song to play.
- */
- privateAfterSongChanges();
- }else{
- /*
- Checks to see if there is more than one song.
- */
- if( config.songs.length > 1 ){
- /*
- Stops the active song
- */
- privateStop();
- /*
- Checks to see if shuffle mode is turned on.
- */
- if( config.shuffle_on ){
- /*
- Loop around shuffle array if at the end. We need to check if the next
- song is within array. Otherwise we reset it to 0.
- Set new song
- */
- if( parseInt( config.shuffle_active_index) + 1 < config.shuffle_list.length ){
- var newIndex = parseInt( config.shuffle_active_index) + 1;
- /*
- Sets the active song information.
- */
- privateSetActiveSongInformation( newIndex, config.shuffle_on );
- config.shuffle_active_index = parseInt(config.shuffle_active_index) + 1;
- }else{
- /*
- Sets the active song information to the beginning of the
- shuffle list
- */
- privateSetActiveSongInformation( 0, config.shuffle_on );
- config.shuffle_active_index = 0;
- }
- }else{
- /*
- Loop around songs array if at the end. We need to check if the next
- song is within array. Otherwise we reset it to 0.
- Sets new song
- */
- if( parseInt(config.active_index) + 1 < config.songs.length ){
- var newIndex = parseInt( config.active_index ) + 1;
- /*
- Sets the active song information
- */
- privateSetActiveSongInformation( newIndex, config.shuffle_on );
- config.active_index = parseInt(config.active_index) + 1;
- }else{
- /*
- Sets the active song information to the beginning of the
- songs list
- */
- privateSetActiveSongInformation( 0, config.shuffle_on );
- config.active_index = 0;
- }
- }
- /*
- Runs the song change function.
- */
- privateAfterSongChanges();
- }else{
- /*
- If there is nothing coming up, pause the play
- button and sync the current times. This will set the play pause
- buttons to paused (stopped) state and the current times to
- 0:00
- */
- privateSetPlayPauseButtonsToPause();
- privateSyncCurrentTimes();
- }
- }
- /*
- Fire song ended event handler.
- */
- privateRunCallback('after_song_ended');
- }
- /*--------------------------------------------------------------------------
- HANDLER FOR: 'timeupdate' on main audio element.
- Everytime the active audio time updates, this function is called.
- It will update the visual display for everything related to the time
- and location compared to the duration of the song.
- TODO: Change all querySelector functions to querySelectorAll functions
- --------------------------------------------------------------------------*/
- function privateUpdateTime(){
- /*
- Gets the current time of the song in seconds and minutes.
- */
- var current_seconds = ( Math.floor( config.active_song.currentTime % 60 ) < 10 ? '0' : '' ) +
- Math.floor( config.active_song.currentTime % 60 );
- var current_minutes = Math.floor( config.active_song.currentTime / 60 );
- /*
- Gets the current song's duration in seconds and minutes.
- */
- var song_duration_seconds = ( Math.floor( config.active_song.duration % 60 ) < 10 ? '0' : '' ) +
- Math.floor( config.active_song.duration % 60 );
- var song_duration_minutes = Math.floor( config.active_song.duration / 60 );
-
- /*
- Finds the current slider that represents the active song's time.
- If there is only one song slider, than that's the one we adjust
- to represent the song's current time, otherwise we find the one
- with the same song index as the active song.
- */
- var current_slider = '';
- if( document.querySelector('[amplitude-singular-song-slider="true"]') ){
- current_slider = document.querySelector('[amplitude-singular-song-slider="true"]');
- }else{
- current_slider = document.querySelector('input[amplitude-song-index="'+config.active_index+'"]');
- }
- /*
- When we find the right visualization, we set the value to the percentage of
- completion only if the song isn't live. Since it's 'infinite' if
- it's a live source, it wouldn't make sense to update the time
- display.
- */
- if( !config.active_metadata.live ){
- /*
- Finds the current song time visualization. If there is only one
- song time visualization, then that's the one we adjust to represent
- the current song time's visualization. Otherwise we find the one
- with the same song index as the active song.
- */
- if( document.querySelectorAll('[amplitude-single-song-time-visualization="true"]').length > 0 ){
- current_song_time_visualization = document.querySelectorAll('[amplitude-single-song-time-visualization="true"]');
- for( var i = 0; i < current_song_time_visualization.length; i++ ){
- var current_song_time_visualization_status = current_song_time_visualization[i].querySelectorAll('.amplitude-song-time-visualization-status');
- var visualization_width = current_song_time_visualization[i].offsetWidth;
- current_song_time_visualization_status[0].setAttribute('style', 'width:' +( visualization_width * ( config.active_song.currentTime / config.active_song.duration ) ) + 'px');
- }
- }
- if( document.querySelectorAll('.amplitude-song-time-visualization[amplitude-song-index="'+config.active_index+'"]').length > 0 ){
- current_song_time_visualization = document.querySelectorAll('.amplitude-song-time-visualization[amplitude-song-index="'+config.active_index+'"]');
-
- for( var i = 0; i < current_song_time_visualization.length; i++ ){
- var current_song_time_visualization_status = current_song_time_visualization[i].querySelectorAll('.amplitude-song-time-visualization-status');
- var visualization_width = current_song_time_visualization[i].offsetWidth;
- current_song_time_visualization_status[0].setAttribute('style', 'width:' +( visualization_width * ( config.active_song.currentTime / config.active_song.duration ) ) + 'px');
- }
- }
- }
- /*
- Looks for an element with attributes that define which part of
- the time should be inserted into the html. If there is a singlular
- display, we update the singular. If there are multiple, we only do
- the first one on the query, it wouldn't make sense to do all of them.
- */
- if( document.querySelectorAll('[amplitude-single-current-minutes="true"]').length > 0 ){
- var mainCurrentMinuteSelectors = document.querySelectorAll('[amplitude-single-current-minutes="true"]');
- for( var i = 0; i < mainCurrentMinuteSelectors.length; i++ ){
- mainCurrentMinuteSelectors[i].innerHTML = current_minutes;
- }
- }
- if( document.querySelectorAll('.amplitude-current-minutes[amplitude-song-index="'+config.active_index+'"]').length > 0 ){
- var currentMinuteSelectors = document.querySelectorAll('.amplitude-current-minutes[amplitude-song-index="'+config.active_index+'"]');
- for( var i = 0; i < currentMinuteSelectors.length; i++ ){
- currentMinuteSelectors[i].innerHTML = current_minutes;
- }
- }
- if( document.querySelectorAll('[amplitude-single-current-seconds="true"]').length > 0 ){
- var mainCurrentSecondSelectors = document.querySelectorAll('[amplitude-single-current-seconds="true"]');
- for( var i = 0; i < mainCurrentSecondSelectors.length; i++ ){
- mainCurrentSecondSelectors[i].innerHTML = current_seconds;
- }
- }
- if( document.querySelectorAll('.amplitude-current-seconds[amplitude-song-index="'+config.active_index+'"]').length > 0 ){
- var currentSecondSelectors = document.querySelectorAll('.amplitude-current-seconds[amplitude-song-index="'+config.active_index+'"]');
- for( var i = 0; i < currentSecondSelectors.length; i++ ){
- currentSecondSelectors[i].innerHTML = current_seconds;
- }
- }
-
- if( !config.active_metadata.live ){
- if( document.querySelectorAll('[amplitude-single-duration-minutes="true"]').length > 0 ){
- var mainDurationMinuteSelectors = document.querySelectorAll('[amplitude-single-duration-minutes="true"]');
- for( var i = 0; i < mainDurationMinuteSelectors.length; i++ ){
- mainDurationMinuteSelectors[i].innerHTML = song_duration_minutes;
- }
- }
- if( document.querySelectorAll('.amplitude-duration-minutes[amplitude-song-index="'+config.active_index+'"]').length > 0 ){
- var durationMinuteSelectors = document.querySelectorAll('.amplitude-duration-minutes[amplitude-song-index="'+config.active_index+'"]');
- for( var i = 0; i < durationMinuteSelectors.length; i++ ){
- durationMinuteSelectors[i].innerHTML = song_duration_minutes;
- }
- }
- if( document.querySelectorAll('[amplitude-single-duration-seconds="true"]').length > 0 ){
- var mainDurationSecondSelectors = document.querySelectorAll('[amplitude-single-duration-seconds="true"]');
- for( var i = 0; i < mainDurationSecondSelectors.length; i++ ){
- mainDurationSecondSelectors[i].innerHTML = song_duration_seconds;
- }
- }
- if( document.querySelectorAll('.amplitude-duration-seconds[amplitude-song-index="'+config.active_index+'"]').length > 0 ){
- var durationSecondSelectors = document.querySelectorAll('.amplitude-duration-seconds[amplitude-song-index="'+config.active_index+'"]');
- for( var i = 0; i < durationSecondSelectors.length; i++ ){
- durationSecondSelectors[i].innerHTML = song_duration_seconds;
- }
- }
- }
- /*
- When we find the right slider, we set the value to the percentage of
- completion only if the song isn't live. Since it's 'infinite' if
- it's a live source, it wouldn't make sense to update the time
- display.
- */
- if( !config.active_metadata.live && current_slider ){
- if( config.active_metadata.duration != undefined ){
- current_slider.value = ( ( config.active_song.currentTime / config.active_metadata.duration ) * 1000 ) * 100;
- }else{
- current_slider.value = ( config.active_song.currentTime / config.active_song.duration ) * 100;
- }
- }
- }
- /*--------------------------------------------------------------------------
- HANDLER FOR: 'amplitude-shuffle'
- Handles a click for the shuffle element.
- --------------------------------------------------------------------------*/
- function privateShuffleClickHandle(){
- /*
- If the shuffle is already on, then swe turn it off
- and clear out the existing shuffle list. We also
- restore the active index back to 0.
- */
- if( config.shuffle_on ){
- config.shuffle_on = false;
- config.shuffle_list = {};
- config.shuffle_active_index = 0;
- }else{
- /*
- If the shuffle is not on then we turn on shuffle
- and re-shuffle the songs.
- */
- config.shuffle_on = true;
- privateShuffleSongs();
- }
- /*
- We then sync the visual shuffle button so it has the proper
- class representing the state of the shuffle functionality.
- */
- privateSyncVisualShuffle();
- }
- /*--------------------------------------------------------------------------
- HANDLER FOR: 'amplitude-repeat'
- Handles a click for the repeat element.
- --------------------------------------------------------------------------*/
- function privateRepeatClickHandle(){
- /*
- If repeat is on, we turn it off. Othwerwise we turn repeat on.
- */
- if( config.repeat ){
- config.repeat = false;
- }else{
- config.repeat = true;
- }
- privateSyncVisualRepeat();
- }
- /*
- |--------------------------------------------------------------------------
- | HELPER FUNCTIONS
- |--------------------------------------------------------------------------
- | For the sake of code clarity, these functions perform helper tasks
- | assisting the logical functions with what they need such as setting
- | the proper song index after an event has occured.
- */
- /*--------------------------------------------------------------------------
- Finishes the initalization of the config. Takes all of the user defined
- parameters and makes sure they override the defaults. The important
- config information is assigned in the publicInit() function.
- This function can be called from 2 different locations:
- 1. Right away on init after the important settings are defined.
- 2. After all of the Soundcloud URLs are resolved properly and
- soundcloud is configured. We will need the proper URLs from Soundcloud
- to stream through Amplitude so we get those right away before we
- set the information and the active song
- @param user_config JSON representation of the user's settings when
- they init Amplitude.
- TODO: In all functions that call privateSetActiveSongInformation, have
- the active_index set there as well.
- TODO: Make sure that if the user sends a start_song that it's an integer
- and nothing else. Debug if NOT an integer.
- TODO: Make the user enter a volume between 0 and 100. It's a little
- easier sounding.
- TODO: Make sure the user enters a volume increment or decrement between
- 1 and 100 to ensure something happens when they click the increment
- or decrement button.
- --------------------------------------------------------------------------*/
- function privateSetConfig( user_config ){
- /*
- If Amplitude is not in dynamic mode, we determine what the
- start song should be. Dynamic mode doesn't have any songs on
- config because the user will be sending them to Amplitude
- dynamically.
- */
- if( !config.dynamic_mode ){
- /*
- If the user provides a starting song index then we set
- the active song information to the song at that index.
- */
- if( user_config.start_song != undefined ){
- privateSetActiveSongInformation( user_config.start_song, false );
- /*
- TODO: REMOVE Sets the user defined index.
- */
- config.active_index = user_config.start_song;
- }else{
- privateSetActiveSongInformation( 0, false );
- /*
- TODO: REMOVE Sets the active index to the first song.
- */
- config.active_index = 0;
- }
- }
- /*
- If live is not defined, assume it is false. The reason for
- this definition is if we play/pause we disconnect
- and re-connect to the stream so we don't fill up our cache
- with unused audio and we aren't playing outdated audio upon
- resume.
- */
- if( config.active_metadata.live == undefined ){
- config.active_metadata.live = false;
- }
- /*
- If the user wants the song to be pre-loaded for instant
- playback, they set it to true. By default it's set to just
- load the metadata.
- */
- config.active_song.preload = ( user_config.preload != undefined ? user_config.preload : "metadata" );
-
- /*
- Initializes the user defined callbacks. This should be a JSON
- object that contains a key->value store of the callback name
- and the name of the function the user needs to call.
- */
- config.callbacks = ( user_config.callbacks != undefined ? user_config.callbacks : {} );
- /*
- The user can define a starting volume in a range of 0-1 with
- 0 being muted and 1 being the loudest. After the config is set
- Amplitude sets the active song's volume to the volume defined
- by the user.
- */
- config.volume = ( user_config.volume != undefined ? user_config.volume : .5 );
- config.active_song.volume = config.volume;
- /*
- The user can set the volume increment and decrement values between 1 and 100
- for when the volume up or down button is pressed. The default is an increase
- or decrease of 5.
- */
- config.volume_increment = ( user_config.volume_increment != undefined ? user_config.volume_increment : 5 );
- config.volume_decrement = ( user_config.volume_decrement != undefined ? user_config.volume_decrement : 5 );
- /*
- The user can turn off Amplitude handling the song elements (putting the meta data into
- certain fields when the song is playing or changed). This would be if the user wanted
- to hard code this information which would probably be most popular in single song
- instances.
- */
- config.handle_song_elements = ( user_config.handle_song_elements != undefined ? user_config.handle_song_elements : true );
- /*
- If the user defines default album art, this image will display if the active
- song doesn't have album art defined.
- */
- config.default_album_art = ( user_config.default_album_art != undefined ? user_config.default_album_art : '' );
-
- /*
- The user can define a visualization backup to use if they are using
- visualizations (song visualizations not song time visualizations) and the
- browser doesn't support it. This can be "nothing" meaning that the
- visualization element is removed otherwise it can be the album art
- of the song being played.
- */
- config.visualization_backup = ( user_config.visualization_backup != undefined ? user_config.visualization_backup : 'nothing' );
- /*
- Sets initialized to true, so the user can't re-initialize
- and mess everything up.
- */
- config.initialized = true;
- /*
- Since the user can define a start volume, we want our volume
- sliders to sync with the user defined start value.
- */
- privateSyncVolumeSliders();
- /*
- Sets up the player if the browser doesn't have the audio context
- */
- privateSyncNoAudioContext();
- /*
- Set all of the current time elements to 0:00 upon initialization
- */
- privateSyncCurrentTimes();
- /*
- Syncs all of the song status sliders so the user can't set the
- HTML 5 range element to be something invalid on load like half
- way through the song by default.
- */
- privateResetSongStatusSliders();
- privateCheckSongVisualization();
- /*
- Initialize the visual elements for the song if the user
- wants Amplitude to handle the changes. This is new
- compared to previous versions where Amplitude automatically
- handled the song elements.
- */
- if( config.handle_song_elements ){
- privateDisplaySongMetadata();
- }
- /*
- Removes any classes set by the user so any inconsistencies
- with start song and actual song are displayed correctly.
- */
- privateSyncVisualPlayingContainers();
- /*
- Sets the active song container for the song that will be
- played. This adds a class to an element containing the
- visual representation of the active song .
- */
- privateSetActiveContainer();
- /*
- Sets the temporary user conifg back to empty. We are done
- using it.
- */
- temp_user_config = {};
- /*
- Run after init callback
- */
- privateRunCallback("after_init");
- /*
- If the user turns on autoplay the song will play automatically.
- */
- if( user_config.autoplay ){
- /*
- Gets the attribute for song index so we can check if
- there is a need to change the song. In some scenarios
- there might be multiple play classes on the page. In that
- case it is possible the user could click a different play
- class and change the song.
- */
- var playing_song_index = config.start_song;
- /*
- We set the new song if the user clicked a song with a different
- index. If it's the same as what's playing then we don't set anything.
- If it's different we reset all song sliders.
- */
- if( privateCheckNewSong( playing_song_index ) ){
- privateChangeSong( playing_song_index );
- privateResetSongStatusSliders();
- }
- /*
- Start the visualizations for the song.
- */
- privateStartVisualization();
-
- /*
- If there are any play pause buttons we need
- to sync them to playing for auto play.
- */
- privateChangePlayPauseState('playing');
- /*
- Play the song through the core play function.
- */
- privatePlay();
- }
- }
- /*--------------------------------------------------------------------------
- Handles the back up functionality for visualizations. This happens
- if there is no AudioContext available or the song is live.
- The two settings are:
- 1. "nothing" DEFAULT. It will remove the visualization element from the
- page.
- 2. "album-art" Instead of the visualization, the element that would have
- container for the visualization will instead display the album
- art for the now playing song.
- TODO: Make sure this is only run if the user is using visualizations
- in their design.
- TODO: Change querySelector to querySelectorAll once again justifying
- the use of a global query all function for visual syncing.
- --------------------------------------------------------------------------*/
- function privateHandleVisualizationBackup(){
- switch( config.visualization_backup ){
- /*
- Removes the visualization element from the page.
- */
- case "nothing":
-
- if( document.getElementById('amplitude-visualization') ){
- document.getElementById('amplitude-visualization').remove();
- }
- break;
- /*
- Sets up the old visualization element to contain the
- album art.
- */
- case "album-art":
- /*
- Gets the old visualizationelement.
- */
- var old_visualization = document.getElementById('amplitude-visualization');
- /*
- If there is a visualization element then we proceed.
- */
- if( old_visualization ){
- /*
- Gets the parent node to append the inner node to containing
- the album art.
- */
- var parent_old_visualization = old_visualization.parentNode;
- var new_album_art = document.createElement('img');
- /*
- Sets the attribute to be the song infor for the cover
- art on the new element. Also apply the class 'amplitude-album-art'
- */
- new_album_art.setAttribute('amplitude-song-info', 'cover');
- new_album_art.setAttribute('class', 'amplitude-album-art');
- /*
- TODO: is this the right place to do this? Shouldn't this happen
- AFTER we replace the visualization?
- */
- if( document.querySelector('[amplitude-song-info="cover"]') ){
- if( config.active_metadata.cover_art_url != undefined){
- new_album_art.setAttribute( 'src', config.active_metadata.cover_art_url );
- document.querySelector('[amplitude-song-info="cover"]').setAttribute('src', config.active_metadata.cover_art_url);
- }else if( config.default_album_art != '' ){
- new_album_art.setAttribute( 'src', config.default_album_art );
- }else{
- new_album_art.setAttribute( 'src', '' );
- }
- }
- parent_old_visualization.replaceChild( new_album_art, old_visualization );
- }
- break;
- }
- }
- /*--------------------------------------------------------------------------
- Sets information relating to the active song.
- --------------------------------------------------------------------------*/
- function privateSetActiveSongInformation( index, shuffle ){
- if( shuffle ){
- /*
- If the current state is in shuffle mode, we set the
- active song to the song at the index in the shuffle list.
- Amplitude will also grab specific meta data from the song
- in the shuffle list and set the attributes in the config
- accordingly.
- */
- config.active_song.src = config.shuffle_list[index].url;
- config.active_metadata = config.shuffle_list[index];
- config.active_album = config.shuffle_list[index].album;
- }else{
- /*
- If the current state is not in shuffle mode, we will
- grab the index from the songs array and set the active
- song to the source of that song. Amplitude will also
- grab certain attributes from the song and use them
- in the config accordingly.
- */
- config.active_song.src = config.songs[index].url;
- config.active_metadata = config.songs[index];
- config.active_album = config.songs[index].album;
- }
- }
-
- /*--------------------------------------------------------------------------
- Writes out debug message to the console if enabled.
- @param string message The string that gets printed to
- alert the user of a debugging error.
- --------------------------------------------------------------------------*/
- function privateWriteDebugMessage( message ){
- if( config.debug ){
- console.log( message );
- }
- }
- /*--------------------------------------------------------------------------
- Checks to see if a new song should be prepared for playing
- @param int new_song_index The integer index of the song
- that will be played.
- --------------------------------------------------------------------------*/
- function privateCheckNewSong( new_song_index ){
- /*
- If the new song index is null, then nothing was defined,
- so we assume it's in a single song scenario or a main control click
- and we don't need to worry about changing the song. If there was an
- index defined and the index and active_index are different then we
- adjust the song.
- */
- if( new_song_index != null && ( new_song_index != config.active_index ) ){
- return true;
- }else{
- return false;
- }
- }
- /*--------------------------------------------------------------------------
- Gets Amplitude ready for a song change. Syncs elements and runs
- necessary callbacks.
- @param int new_song_index The integer index of the song
- that will be played.
- --------------------------------------------------------------------------*/
- function privateChangeSong( new_song_index ){
- /*
- Stops the currently playing song.
- */
- privateStop();
- /*
- Checks to see if the new song is a different album.
- */
- privateCheckNewAlbum( config.songs[new_song_index].album );
- /*
- Changes the active song index that is being played.
- */
- config.active_index = new_song_index;
- /*
- Sets the active song information for the new song that will
- be played.
- */
- privateSetActiveSongInformation( new_song_index, config.shuffle_on );
- if( config.album_change ){
- privateRunCallback('after_album_change');
- config.album_change = false;
- }
-
- /*
- If it's a new song and the user wants amplitude to handle
- the song elements, we need to set the information for
- the song.
- */
- if( config.handle_song_elements ){
- privateDisplaySongMetadata();
- }
- /*
- We set the current times to 0:00 when song changes
- so all of the pages players will be synchronized.
- */
- privateSyncCurrentTimes();
- privateCheckSongVisualization();
- privateSetActiveContainer();
- }
- /*--------------------------------------------------------------------------
- Checks to see if a new album is playing. This allows for
- multiple albums to be initialized on the same page.
- Through CSS you can show and hide albums and simulate
- multiple playlists. This method is called after there is a for
- sure change to see if the next song's album is different than
- the song that will soon to be previous' album.
- @param string new_album The string of the new album
- to see if it has changed.
- TODO: Research if we should return true/false instead of setting the
- config.
- TODO: Makes sure the song actually has an album before running.
- --------------------------------------------------------------------------*/
- function privateCheckNewAlbum( new_album ){
- /*
- If the new album isn't the same as the
- active album, we set the change to true
- and run the before_album_change callback.
- */
- if( config.active_album != new_album ){
- config.album_change = true;
- privateRunCallback('before_album_change');
- }
- }
- /*--------------------------------------------------------------------------
- Called when a song changes. Synchronizes everything necessary on
- the page to handle the song change.
- TODO: Check to see if using visualizations.
- --------------------------------------------------------------------------*/
- function privateAfterSongChanges(){
- /*
- After the new song is set, we see if we need to change
- the visualization. If it's different, we need to start
- the new one.
- */
- if( privateCheckSongVisualization() ){
- privateStartVisualization();
- }
- /*
- After the new song is set, Amplitude will update the
- visual elements containing information about the
- new song if the user wants Amplitude to.
- */
- if( config.handle_song_elements ){
- privateDisplaySongMetadata();
- }
- /*
- Sync song status sliders. Sets them back to 0 because
- when the song is changing there won't be any songs currently
- playing.
- */
- privateResetSongStatusSliders();
- /*
- We set the current times to 0:00 when song changes
- so all of the page's players will be synchronized.
- */
- privateSyncCurrentTimes();
- /*
- Remove class from all containers
- */
- privateSyncVisualPlayingContainers();
- /*
- Set new active song container by applying a class
- to the visual element containing the visual representation
- of the song that is actively playing.
- */
- privateSetActiveContainer();
- /*
- Plays the new song.
- */
- privatePlay();
- }
- /*--------------------------------------------------------------------------
- Shuffles songs.
- Based off of: http://www.codinghorror.com/blog/2007/12/the-danger-of-naivete.html
- --------------------------------------------------------------------------*/
- function privateShuffleSongs(){
- var shuffle_temp = new Array( config.songs.length );
- for( i = 0; i < config.songs.length; i++ ){
- shuffle_temp[i] = config.songs[i];
- }
- for( i = config.songs.length - 1; i > 0; i-- ){
- rand_num = Math.floor( ( Math.random() * config.songs.length ) + 1 );
- privateShuffleSwap( shuffle_temp, i, rand_num - 1 );
- }
- config.shuffle_list = shuffle_temp;
- }
- /*--------------------------------------------------------------------------
- Swaps and randomizes the song shuffle.
- @param JSON shuffle_list The list of songs that is going to
- be shuffled
- @param int original The original index of the song in the
- songs array.
- @param int random The randomized index that will be the
- new index of the song in the shuffle array.
- --------------------------------------------------------------------------*/
- function privateShuffleSwap( shuffle_list, original, random ){
- var temp = shuffle_list[ original ];
- shuffle_list[ original ] = shuffle_list[ random ];
- shuffle_list[ random ] = temp;
- }
- /*--------------------------------------------------------------------------
- Runs callback for specific function
- @param string The name of the call back. Also used as the index that
- the user can use in the callback array to define their callback method.
- --------------------------------------------------------------------------*/
- function privateRunCallback( callback_name ){
- if( config.callbacks[callback_name] ){
- var callback_function = window[ config.callbacks[ callback_name ] ];
- callback_function();
- }
- }
- /*--------------------------------------------------------------------------
- If there is a visualization specifically for a song, we set that
- as the active visualization. Only if one is specified, otherwise
- nothing changes and we continue using the active visualization.
- @returns BOOL Returns true if there is a specific visualization for
- the song.
- --------------------------------------------------------------------------*/
- function privateCheckSongVisualization(){
- var changed = false;
- /*
- Checks to see if the song actually has a specific visualization
- defined.
- */
- if( config.active_metadata.visualization ){
-
- /*
- If the visualization is different and there is an active
- visualization. We must stop the active visualization
- before setting the new one.
- */
- if( config.active_metadata.visualization != config.active_visualization && config.active_visualization != '' ){
- privateStopVisualization();
-
- /*
- Set the visualization changed to true
- so we return the status change.
- */
- changed = true;
- /*
- Sets the active visualization to the new
- visualization that the song uses.
- */
- config.active_visualization = config.active_metadata.visualization;
- }
- }
- /*
- Returns the status of the new song visualization.
- If there is a change it returns true and we will
- have to start the the visualization.
- */
- return changed;
- }
- /*--------------------------------------------------------------------------
- Sets the visual elements containg the active song
- metadata
- --------------------------------------------------------------------------*/
- function privateDisplaySongMetadata(){
- /*
- Sets all elements that will contain the active song's name metadata
- */
- if( document.querySelectorAll('[amplitude-song-info="name"]') ){
- var metaNames = document.querySelectorAll('[amplitude-song-info="name"]');
- for( i = 0; i < metaNames.length; i++ ){
- metaNames[i].innerHTML = config.active_metadata.name;
- }
- }
- /*
- Sets all elements that will contain the active song's artist metadata
- */
- if( document.querySelectorAll('[amplitude-song-info="artist"]') ){
- var metaArtist = document.querySelectorAll('[amplitude-song-info="artist"]');
- for( i = 0; i < metaArtist.length; i++ ){
- metaArtist[i].innerHTML = config.active_metadata.artist;
- }
- }
- /*
- Sets all elements that will contain the active song's album metadata
- */
- if( document.querySelectorAll('[amplitude-song-info="album"]') ){
- var metaAlbum = document.querySelectorAll('[amplitude-song-info="album"]');
- for( i = 0; i < metaAlbum.length; i++ ){
- metaAlbum[i].innerHTML = config.active_metadata.album;
- }
- }
- /*
- Sets all elements that will contain the active song's cover art metadata
- */
- if( document.querySelectorAll('[amplitude-song-info="cover"]') ){
- var coverImages = document.querySelectorAll('[amplitude-song-info="cover"]');
- for( i = 0; i < coverImages.length; i++ ){
- /*
- Checks to see if first, the song has a defined cover art and uses
- that. If it does NOT have defined cover art, checks to see if there
- is a default. Otherwise it just sets the src to '';
- */
- if( config.active_metadata.cover_art_url != undefined){
- coverImages[i].setAttribute('src', config.active_metadata.cover_art_url);
- }else if( config.default_album_art != '' ){
- coverImages[i].setAttribute('src', config.default_album_art);
- }else{
- coverImages[i].setAttribute('src', '');
- }
- }
-
- }
- /*
- Station information for live streams
- */
- /*
- Sets all of the elements that will contain the live stream's call sign metadata
- */
- if( document.querySelectorAll('[amplitude-song-info="call-sign"]') ){
- var metaCallSign = document.querySelectorAll('[amplitude-song-info="call-sign"]');
- for( i = 0; i < metaCallSign.length; i++ ){
- metaCallSign[i].innerHTML = config.active_metadata.call_sign;
- }
- }
- /*
- Sets all of the elements that will contain the live stream's station name metadata
- */
- if( document.querySelectorAll('[amplitude-song-info="station-name"]') ){
- var metaStationName = document.querySelectorAll('[amplitude-song-info="station-name"]');
- for( i = 0; i < metaStationName.length; i++ ){
- metaStationName[i].innerHTML = config.active_metadata.station_name;
- }
- }
- /*
- Sets all of the elements that will contain the live stream's location metadata
- */
- if( document.querySelectorAll('[amplitude-song-info="location"]') ){
- var metaStationLocation = document.querySelectorAll('[amplitude-song-info="location"]');
- for( i = 0; i < metaStationLocation.length; i++ ){
- metaStationLocation[i].innerHTML = config.active_metadata.location;
- }
- }
- /*
- Sets all of the elements that will contain the live stream's frequency metadata
- */
- if( document.querySelectorAll('[amplitude-song-info="frequency"]') ){
- var metaStationFrequency = document.querySelectorAll('[amplitude-song-info="frequency"]');
- for( i = 0; i < metaStationFrequency.length; i++ ){
- metaStationFrequency[i].innerHTML = config.active_metadata.frequency;
- }
- }
- /*
- Sets all of the elements that will contain the live stream's station art metadata
- TODO: Rename coverImages to stationArtImages
- */
- if( document.querySelectorAll('[amplitude-song-info="station-art"]') ){
- var coverImages = document.querySelectorAll('[amplitude-song-info="station-art"]');
- /*
- Checks to see if first, the song has a defined station art and uses
- that. If it does NOT have defined station art, checks to see if there
- is a default. Otherwise it just sets the src to '';
- */
- for( i = 0; i < coverImages.length; i++ ){
- if( config.active_metadata.cover_art_url != undefined){
- coverImages[i].setAttribute('src', config.active_metadata.station_art_url);
- }else if( config.default_album_art != '' ){
- coverImages[i].setAttribute('src', config.default_album_art);
- }else{
- coverImages[i].setAttribute('src', '');
- }
- }
-
- }
- }
- /*--------------------------------------------------------------------------
- Applies the class 'amplitude-active-song-container' to the element
- containing visual information regarding the active song.
- TODO: Make sure that when shuffling, this changes accordingly.
- --------------------------------------------------------------------------*/
- function privateSetActiveContainer(){
- var songContainers = document.getElementsByClassName('amplitude-song-container');
- /*
- Removes all of the active song containrs.
- */
- for( i = 0; i < songContainers.length; i++ ){
- songContainers[i].classList.remove('amplitude-active-song-container');
- }
- /*
- Finds the active index and adds the active song container to the element
- that represents the song at the index.
- */
- if( document.querySelectorAll('.amplitude-song-container[amplitude-song-index="'+config.active_index+'"]') ){
- var songContainers = document.querySelectorAll('.amplitude-song-container[amplitude-song-index="'+config.active_index+'"]');
- for( i = 0; i < songContainers.length; i++ ){
- songContainers[i].classList.add('amplitude-active-song-container');
- }
- }
- }
- /*--------------------------------------------------------------------------
- Calls the start method on the active visualization.
- --------------------------------------------------------------------------*/
- function privateStartVisualization(){
- /*
- If the visualization is not started, and there are visualizations
- ready to be activated, we check to see if the user defined a
- starting visualization. If there is a starting visualization,
- then we start that one, otherwise we grab the first visualization
- defined and start that one.
- */
- if( !config.visualization_started && Object.keys(config.visualizations).length > 0){
- if( config.active_visualization != '' ){
- config.visualizations[config.active_visualization].startVisualization(config.active_song);
- config.current_visualization = config.visualizations[config.active_visualization];
- }else{
- for(first_visualization in config.visualizations);
- config.visualizations[first_visualization].startVisualization(config.active_song);
- config.current_visualization = config.visualizations[first_visualization];
- }
- config.visualization_started = true;
- }
- }
- /*--------------------------------------------------------------------------
- Calls the stop method of the active visualization.
- If the visualization is started, we stop it.
- --------------------------------------------------------------------------*/
- function privateStopVisualization(){
- if( config.visualization_started && Object.keys(config.visualizations).length > 0){
- config.current_visualization.stopVisualization();
- config.visualization_started = false;
- }
- }
- /*
- |--------------------------------------------------------------------------
- | SOUNDCLOUD SPECIFIC HELPERS
- |--------------------------------------------------------------------------
- | These helpers wrap around the basic functions of the Soundcloud API
- | and get the information we need from SoundCloud to make the songs
- | streamable through Amplitude
- */
- /*--------------------------------------------------------------------------
- Loads the soundcloud SDK for use with Amplitude so the user doesn't have
- to load it themselves.
- With help from: http://stackoverflow.com/questions/950087/include-a-javascript-file-in-another-javascript-file
- --------------------------------------------------------------------------*/
- function privateLoadSoundcloud(){
- var head = document.getElementsByTagName('head')[0];
- var script = document.createElement('script');
- script.type = 'text/javascript';
- /*
- URL to the remote soundcloud SDK
- */
- script.src = 'https://connect.soundcloud.com/sdk.js';
- script.onreadystatechange = privateInitSoundcloud;
- script.onload = privateInitSoundcloud;
- head.appendChild( script );
- }
- /*--------------------------------------------------------------------------
- Initializes soundcloud with the key provided.
- --------------------------------------------------------------------------*/
- function privateInitSoundcloud(){
- /*
- Calls the SoundCloud initialize function
- from their API and sends it the client_id
- that the user passed in.
- */
- SC.initialize({
- client_id: config.soundcloud_client
- });
- /*
- Gets the streamable URLs to run through Amplitue. This is
- VERY important since Amplitude can't stream the copy and pasted
- link from the SoundCloud page, but can resolve the streaming
- URLs from the link.
- */
- privateGetSoundcloudStreamableURLs();
- }
- /*--------------------------------------------------------------------------
- Gets the streamable URL from the URL provided for
- all of the soundcloud links. This will loop through
- and set all of the information for the soundcloud
- urls.
- --------------------------------------------------------------------------*/
- function privateGetSoundcloudStreamableURLs(){
- var soundcloud_regex = /^https?:\/\/(soundcloud.com|snd.sc)\/(.*)$/;
-
- for( var i = 0; i < config.songs.length; i++ ){
- /*
- If the URL matches soundcloud, we grab
- that url and get the streamable link
- if there is one.
- */
- if( config.songs[i].url.match( soundcloud_regex ) ){
- config.soundcloud_song_count++;
- privateSoundcloudResolveStreamable(config.songs[i].url, i);
- }
- }
- }
- /*--------------------------------------------------------------------------
- Due to Soundcloud SDK being asynchronous, we need to scope the
- index of the song in another function. The privateGetSoundcloudStreamableURLs
- function does the actual iteration and scoping.
- --------------------------------------------------------------------------*/
- function privateSoundcloudResolveStreamable(url, index){
- SC.get('/resolve/?url='+url, function( sound ){
- /*
- If streamable we get the url and bind the client ID to the end
- so Amplitude can just stream the song normally. We then overwrite
- the url the user provided with the streamable URL.
- */
- if( sound.streamable ){
- config.songs[index].url = sound.stream_url+'?client_id='+config.soundcloud_client;
- /*
- If the user want's to use soundcloud art, we overwrite the
- cover_art_url with the soundcloud artwork url.
- */
- if( config.soundcloud_use_art ){
- config.songs[index].cover_art_url = sound.artwork_url;
- }
- /*
- Grab the extra metadata from soundcloud and bind it to the
- song. The user can get this through the public function:
- getActiveSongMetadata
- */
- config.songs[index].soundcloud_data = sound;
- }else{
- /*
- If not streamable, then we print a message to the user stating
- that the song with name X and artist X is not streamable. This
- gets printed ONLY if they have debug turned on.
- */
- privateWriteDebugMessage( config.songs[index].name +' by '+config.songs[index].artist +' is not streamable by the Soundcloud API' );
- }
- /*
- Increments the song ready counter.
- */
- config.soundcloud_songs_ready++;
- /*
- When all songs are accounted for, then amplitude is ready
- to rock and we set the rest of the config.
- */
- if( config.soundcloud_songs_ready == config.soundcloud_song_count ){
- privateSetConfig( temp_user_config );
- }
- });
- }
-
- /*
- |--------------------------------------------------------------------------
- | VISUAL SYNCHRONIZATION METHODS
- |--------------------------------------------------------------------------
- | These methods keep the screen in sync. For example if there are multiple
- | play/pause buttons and a song changes, we need to set all of the other
- | play/pause buttons to paused state.
- |
- */
- /*--------------------------------------------------------------------------
- Sets all of the play/pause buttons to the not playing state. The
- click handler will set the actual playing button to the playing state.
- --------------------------------------------------------------------------*/
- function privateSetPlayPauseButtonsToPause(){
- var play_pause_classes = document.getElementsByClassName("amplitude-play-pause");
- /*
- Iterates over all of the play pause classes removing
- the playing class and adding the paused class.
- */
- for( var i = 0; i < play_pause_classes.length; i++ ){
- play_pause_classes[i].classList.add('amplitude-paused');
- play_pause_classes[i].classList.remove('amplitude-playing');
- }
- }
- /*--------------------------------------------------------------------------
- Changes the play pause state for all classes that need it. This
- iterates through all of the amplitude-play-pause classes for the
- active index and all of the amplitude-main-play-puase attributes
- making sure everything stays in sync.
- --------------------------------------------------------------------------*/
- function privateChangePlayPauseState( state ){
- /*
- If the state is playing we set all of the classes accordingly.
- */
- if( state == 'playing' ){
- if( document.querySelectorAll('.amplitude-play-pause[amplitude-song-index="'+config.active_index+'"]').length > 0 ){
- var currentPlayPauseControls = document.querySelectorAll('.amplitude-play-pause[amplitude-song-index="'+config.active_index+'"]');
-
- /*
- Iterates over all of the play pause controls adding the
- 'amplitude-playing' classes and removing the 'amplitude-paused'
- classes.
- */
- for( var i = 0; i < currentPlayPauseControls.length; i++ ){
- currentPlayPauseControls[i].classList.add('amplitude-playing');
- currentPlayPauseControls[i].classList.remove('amplitude-paused');
- }
- }
- /*
- Sets the main song control statuses to playing by removing the
- 'amplitude-paused' class and adding the 'amplitude-playing' class.
- */
- if( document.querySelectorAll('[amplitude-main-play-pause="true"]').length > 0 ){
- var mainControls = document.querySelectorAll('[amplitude-main-play-pause="true"]');
- for( var i = 0; i < mainControls.length; i++ ){
- mainControls[i].classList.add('amplitude-playing');
- mainControls[i].classList.remove('amplitude-paused');
- }
- }
- }
- /*
- If the state is paused, we set all of the classes accordingly.
- */
- if( state == 'paused' ){
- if( document.querySelectorAll('.amplitude-play-pause[amplitude-song-index="'+config.active_index+'"]').length > 0 ){
- var currentPlayPauseControls = document.querySelectorAll('.amplitude-play-pause[amplitude-song-index="'+config.active_index+'"]');
-
- /*
- Iterates over all of the play pause controls adding the
- 'amplitude-paused' classes and removing the 'amplitude-playing'
- classes.
- */
- for( var i = 0; i < currentPlayPauseControls.length; i++ ){
- currentPlayPauseControls[i].classList.remove('amplitude-playing');
- currentPlayPauseControls[i].classList.add('amplitude-paused');
- }
- }
- /*
- Sets the main song control statuses to paused by removing the
- 'amplitude-playing' class and adding the 'amplitude-paused' class.
- */
- if( document.querySelectorAll('[amplitude-main-play-pause="true"]').length > 0 ){
- var mainControls = document.querySelectorAll('[amplitude-main-play-pause="true"]');
- for( var i = 0; i < mainControls.length; i++ ){
- mainControls[i].classList.add('amplitude-paused');
- mainControls[i].classList.remove('amplitude-playing');
- }
- }
- }
- }
- /*--------------------------------------------------------------------------
- Sets all of the song status sliders to 0, the time update event
- handler will adjust the one that represents the current song
- that is playing.
- --------------------------------------------------------------------------*/
- function privateResetSongStatusSliders(){
- var amplitude_song_sliders = document.getElementsByClassName("amplitude-song-slider");
- /*
- Iterate over all of the song sliders and sets them to
- 0 essentially resetting them.
- */
- for( var i = 0; i < amplitude_song_sliders.length; i++ ){
- amplitude_song_sliders[i].value = 0;
- }
- }
- /*--------------------------------------------------------------------------
- Sets all of the volume sliders to the active song's volume.
- --------------------------------------------------------------------------*/
- function privateSyncVolumeSliders(){
- var amplitude_volume_sliders = document.getElementsByClassName("amplitude-volume-slider");
- /*
- Iterates over all of the volume sliders for the song, setting the value
- to the config value.
- */
- for( var i = 0; i < amplitude_volume_sliders.length; i++ ){
- amplitude_volume_sliders[i].value = config.active_song.volume * 100;
- }
- }
- /*--------------------------------------------------------------------------
- Handles the situation if there is no audio context
- available
- --------------------------------------------------------------------------*/
- function privateSyncNoAudioContext(){
- if( !window.AudioContext ){
- privateHandleVisualizationBackup();
- }
- }
- /*--------------------------------------------------------------------------
- Syncs the current time displays so you can have multiple song time
- displays. When a song changes, we need the current minutes and seconds
- to go to 0:00
- --------------------------------------------------------------------------*/
- function privateSyncCurrentTimes(){
- var current_minute_times = document.getElementsByClassName("amplitude-current-minutes");
- for( var i = 0; i < current_minute_times.length; i++ ){
- current_minute_times[i].innerHTML = '0';
- }
- var current_second_times = document.getElementsByClassName("amplitude-current-seconds");
- for( var i = 0; i < current_second_times.length; i++ ){
- current_second_times[i].innerHTML = '00';
- }
- }
- /*--------------------------------------------------------------------------
- For visual playing containers, we find all containers that
- have a class of 'amplitude-song-container' and remove all of
- the additional 'amplitude-active-song-container' classes.
- When a new song is activated, it will find the parameter
- 'amplitude-song-index' and the class of 'amplitude-song-container'
- and give it the additional class 'amplitude-active-song-container'.
- --------------------------------------------------------------------------*/
- function privateSyncVisualPlayingContainers(){
- var visual_playing_containers = document.getElementsByClassName("amplitude-song-container");
- for( var i = 0; i < visual_playing_containers.length; i++ ){
- visual_playing_containers[i].classList.remove('amplitude-active-song-container');
- }
- }
- /*--------------------------------------------------------------------------
- Sets shuffle on for all of the shuffle buttons. Users
- can apply styles to the amplitude-shuffle-on and
- amplitude-shuffle-off classes. They represent the state
- of the playlist.
- --------------------------------------------------------------------------*/
- function privateSyncVisualShuffle(){
- var shuffle_classes = document.getElementsByClassName("amplitude-shuffle");
- for( var i = 0; i < shuffle_classes.length; i++ ){
- if( config.shuffle_on ){
- shuffle_classes[i].classList.add('amplitude-shuffle-on');
- shuffle_classes[i].classList.remove('amplitude-shuffle-off');
- }else{
- shuffle_classes[i].classList.remove('amplitude-shuffle-on');
- shuffle_classes[i].classList.add('amplitude-shuffle-off');
- }
- }
- }
- /*--------------------------------------------------------------------------
- Sets repeat on for all of the repeat buttons. Users
- can apply styles to the amplitude-repeat-on and
- amplitude-repeat-off classes. They represent the state
- of the player.
- --------------------------------------------------------------------------*/
- function privateSyncVisualRepeat(){
- var repeat_classes = document.getElementsByClassName("amplitude-repeat");
- for( var i = 0; i < repeat_classes.length; i++ ){
- if( config.repeat ){
- repeat_classes[i].classList.add('amplitude-repeat-on');
- repeat_classes[i].classList.remove('amplitude-repeat-off');
- }else{
- repeat_classes[i].classList.remove('amplitude-repeat-on');
- repeat_classes[i].classList.add('amplitude-repeat-off');
- }
- }
- }
- /*
- |--------------------------------------------------------------------------
- | CORE FUNCTIONAL METHODS
- |--------------------------------------------------------------------------
- | Interacts directly with native functions of the Audio element. Logic
- | leading up to these methods are handled by click handlers which call
- | helpers and visual synchronizers. These are the core functions of AmplitudeJS.
- | Every other function that leads to these prepare the information to be
- | acted upon by these functions.
- */
- /*--------------------------------------------------------------------------
- Plays the active song. If the current song is live, it reconnects
- the stream before playing.
- --------------------------------------------------------------------------*/
- function privatePlay(){
- privateRunCallback('before_play');
- if( config.active_metadata.live ){
- privateReconnectStream();
- }
- config.active_song.play();
- privateRunCallback('after_play');
- }
- /*--------------------------------------------------------------------------
- Pauses the active song. If it's live, it disconnects the stream.
- --------------------------------------------------------------------------*/
- function privatePause(){
- config.active_song.pause();
-
- if( config.active_metadata.live ){
- privateDisconnectStream();
- }
- }
- /*--------------------------------------------------------------------------
- Stops the active song by setting the current song time to 0.
- When the user resumes, it will be from the beginning.
- If it's a live stream it disconnects.
- */
- function privateStop(){
- privateRunCallback('before_stop');
- config.active_song.currentTime = 0;
- config.active_song.pause();
- if( config.active_metadata.live ){
- privateDisconnectStream();
- }
- privateRunCallback('after_stop');
- }
- /*--------------------------------------------------------------------------
- Sets the song volume.
- @param int volume_level A number between 1 and 100 as a percentage of
- min to max for a volume level.
- --------------------------------------------------------------------------*/
- function privateSetVolume( volume_level ){
- config.active_song.volume = volume_level / 100;
- }
- /*--------------------------------------------------------------------------
- Sets the song percentage. If it's a live song, we ignore this because
- we can't skip ahead. This is an issue if you have a playlist with
- a live source.
- @param int song_percentage A number between 1 and 100 as a percentage of
- song completion.
- --------------------------------------------------------------------------*/
- function privateSetSongLocation( song_percentage ){
- if( !config.active_metadata.live ){
- config.active_song.currentTime = ( config.active_song.duration ) * ( song_percentage / 100 );
- }
- }
- /*--------------------------------------------------------------------------
- Disconnects the live stream
- --------------------------------------------------------------------------*/
- function privateDisconnectStream(){
- config.active_song.src = '';
- config.active_song.load();
- }
- /*--------------------------------------------------------------------------
- Reconnects the live stream
- --------------------------------------------------------------------------*/
- function privateReconnectStream(){
- config.active_song.src = config.active_metadata.url;
- config.active_song.load();
- }
- /*
- Defines which methods and variables are public.
- */
- return {
- init: publicInit,
- setDebug: publicSetDebug,
- getActiveSongMetadata: publicGetActiveSongMetadata,
- getSongByIndex: publicGetSongByIndex,
- playNow: publicPlayNow,
- play: publicPlay,
- pause: publicPause,
- registerVisualization: publicRegisterVisualization,
- visualizationCapable: publicVisualizationCapable,
- changeVisualization: publicChangeActiveVisualization,
- addSong: publicAddSong,
- analyser: publicGetAnalyser,
- active: config.active_song
- };
- })();
|