<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">(function (window, undefined) {
	'use strict';
	var jsFW = function jsFW(elements) {
		return {
			elements: elements,
			addClass: function addClass(classes) {
				let selectors = elements.length ? elements : [elements];
				selectors.forEach(function(el) {
					classes.split(" ").forEach(function(className) {
						el.classList.add(className);
					});
				});
			},
			removeClass: function removeClass(classes) {
				let selectors = elements.length ? elements : [elements];
				selectors.forEach(function(el) {
					classes.split(" ").forEach(function(className) {
						el.classList.remove(className);
					});
				});
			},
			toggleClass: function removeClass(classes) {
				let selectors = elements.length ? elements : [elements];
				selectors.forEach(function(el) {
					classes.split(" ").forEach(function(className) {
						el.classList.toggle(className);
					});
				});
			},
			extendObj: function extendObj(source, properties) {
				var response = {}, property;
				for(property in source){
					if(properties.hasOwnProperty(property)) {
						if( (typeof source[property] === "object" || typeof source[property] === 'function') &amp;&amp; (source[property] !== null) ) {
							// it's Object go deeply
							response[property] = this.extendObj(source[property], properties[property]);
						} else {
							// It's value, set it
							response[property] = properties[property];
						}
					} else {
						// properties not have this property, get source value
						response[property] = source[property];
					}
				}
				return response;
			},
			/* BUILD DOM */
			buildDOM: function buildDOM(container, DOM) {
				// Prepare arguments
				if(!DOM) {
					DOM = container;
					container = elements;
				}
				let element;
				// Prepare each nod
				DOM.forEach(function(node) {
					// Crete Node
					switch(node.nodeName) {
						case 'svg':
						case 'circle':
						case 'polygon':
						case 'path':
						case 'rect':
							element = document.createElementNS("http://www.w3.org/2000/svg", node.nodeName);
							break;
						case 'text':
							element = document.createTextNode(node.textNode);
							break;
						default:
							element = document.createElement(node.nodeName);
							break;
					}
					// If has Clases
					if(node.class) {
						node.class.split(" ").forEach(function(className) {
							element.classList.add(className);
						});
					}
					// If has Attributes
					if(node.attributes) {
						for(var attributeName in node.attributes) {
							if(node.attributes.hasOwnProperty(attributeName)) {
								element.setAttribute(attributeName, node.attributes[attributeName]);
							}
						}
					}
					// If has Style
					if(node.css) {
						for(var property in node.css) {
							if(node.css.hasOwnProperty(property)) {
							element.style[property] = node.css[property];
							}
						}
					}
					// If has TextNode
					if(node.textNode) {
						element.innerText = node.textNode;
					}
					// If has Children
					if(node.children) {
						buildDOM(element, node.children);
					}
					container.append(element);
				});
			},
			imgLoader: function(data) {

				let downloadingImage = new Image();
				downloadingImage.src = data.img;

				downloadingImage.onload = function() {
					let image = this;
					data.onLoad(image.src);
				};
			}
		};
	};

	var gPlayers = [];

	var gPlayer = function(options) {
		let defaultOptions = {
			container: null,
			skin: 'dark',
			playlist: null,
			albumArtist: null,
			albumCover: null,
			songsVisible: null,
			showPlaylist: false,
			volume: 1,
			cover: true,
			repeat: true,
			shuffle: true,
			debug: false,
			style: {
				player: {
					background: '#F6C90E',
					artist: '#3A4750',
					title: '#303841',
					cover: '#3A4750',
					coverLoaderCircle: '#303841',
					coverLoader: '#F6C90E',
					seek: '#3A4750',
					progress: '#EEEEEE',
					timestamps: '#3A4750',
					buttons: {
						normal: '#3A4750',
						hover: '#EEE',
						active: '#EEE'
					}
				},
				playlist: {
					scroll: {
						background: '#3A4750',
						rail: '#303841',
						scrollbar: '#F6C90E'
					},
					normal: {
						background: '#303841',
						separator: '#3A4750',
						color: '#EEE'
					},
					hover: {
						background: '#3A4750',
						separator: '#303841',
						color: '#F6C90E'
					},
					active: {
						background: '#F6C90E',
						separator: '#F6C90E',
						color: '#303841'
					}
				}
			},
			translate: {
				buttons: {
					download: 'Download',
					buy: 'Buy',
					repeatToggle: 'Repeat',
					shuffleToggle: 'Shuffle',
					volumeToggle: 'Volume',
					playlistToggle: 'Show/Hide Playlist',
					next: 'Next Song',
					playback: 'Play/Pause',
					prev: 'Prev Song'
				},
				playlist: {
					noAtist: 'Unknown',
					noTitle: 'Unnamed'
				}
			}
		},
		_this = this, settings, elements = [], playerHTML, playerIcons, playerButtons;

		settings = jsFW().extendObj(defaultOptions, options);
		this.id = settings.container;
		this.skin = settings.skin;
		this.playlist = settings.playlist;
		// Create Audio
		this.audio = new Audio();
		this.audio.preload = 'metadata';
		this.audio.volume = 0;
		// Add to List of Players
		gPlayers[this.id] = this.audio;

		this.state = {
			autoplay: false,
			seeking: false,
			volumeSeeking: false,
			repeat: false,
			shuffle: false,
			playlistToggle: false,
			volumeToggle: false,
			isMobile: detectMobile(),
			coverVissible: false
		};

		this.Events = null;

		this.currentSong = 0;
		this.currentTime = 0;
		this.volume = settings.volume;

		elements.wrapper = document.getElementById(settings.container);

		/* PLAYER ICONS */
		playerIcons = {
			playback: {
				play: 'M1,1 10,5.5 10,14.5 1,19z M10,5.5 19,10 19,10 10,14.5z',
				pause: 'M1,1 5,1 5,19 1,19z M15,1 19,1 19,19 15,19z'
			},
			prev: 'M1,10 9,1 9,19z M10,10 19,1 19,19z',
			next: 'M1,1 10,10 1,19z M11,1 19,10 11,19z',
			repeat: 'M18.5 10c-.8 0-1.5.7-1.5 1.5v3H6.9V13a1 1 0 0 0-.5-.9 1 1 0 0 0-1 0l-4.9 3c-.3.2-.5.6-.5.9s.2.7.5.9l4.9 3 .5.1.5-.1c.3-.2.5-.5.5-.9v-1.5h11.6c.8 0 1.5-.7 1.5-1.5v-4.5c0-.8-.7-1.5-1.5-1.5zM1.5 11c.8 0 1.5-.7 1.5-1.5v-4h10V7c0 .4.2.7.5.9l.5.1.5-.1 5-3c.3-.2.5-.5.5-.9s-.2-.7-.5-.9l-5-3a1 1 0 0 0-1 0 1 1 0 0 0-.5.9v1.5H1.5C.7 2.5 0 3.2 0 4v5.5c0 .8.7 1.5 1.5 1.5z',
			shuffle: 'M.4.4C-.1 1-.1 2 .4 2.6L6.8 9l2.1-2.1L2.6.4C2-.1 1-.1.4.4zm18.9 11.8c-.4-.2-.8-.1-1.1.2l-1.9 1.9-3.2-3.2-2.1 2.1 3.2 3.2-1.9 1.9c-.3.3-.4.7-.2 1.1s.5.6.9.6h6c.6 0 1-.4 1-1v-6c-.1-.3-.3-.7-.7-.8zM19 0h-6c-.4 0-.8.2-.9.6-.2.4-.1.8.2 1.1l1.9 1.9L.4 17.4c-.6.6-.6 1.5 0 2.1.3.4.7.5 1.1.5s.8-.1 1.1-.4L16.4 5.8l1.9 1.9c.2.2.4.3.7.3l.4-.1c.4-.1.6-.5.6-.9V1c0-.6-.4-1-1-1z',
			volume: 'M9.4,0.1C9-0.1,8.6,0,8.3,0.3L3.6,5H1C0.4,5,0,5.4,0,6v8c0,0.6,0.4,1,1,1h2.6l4.7,4.7C8.5,19.9,8.7,20,9,20c0.1,0,0.3,0,0.4-0.1C9.8,19.8,10,19.4,10,19V1C10,0.6,9.8,0.2,9.4,0.1z M14,15c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.3-1,0.1-1.4c0,0,1.7-1.5,1.7-3.3c0-1.7-1.7-3.2-1.7-3.3c-0.4-0.4-0.4-1-0.1-1.4c0.4-0.4,1-0.4,1.4-0.1C14.8,5.3,17,7.4,17,10c0,2.6-2.2,4.7-2.3,4.7C14.5,14.9,14.2,15,14,15z M15.8,17.5c-0.4,0-0.7-0.2-0.9-0.6c-0.2-0.5,0-1.1,0.5-1.3c0.1,0,2.6-1.3,2.6-5.6c0-3.5-2.8-5.7-2.8-5.7c-0.4-0.3-0.5-1-0.2-1.4c0.3-0.4,1-0.5,1.4-0.2C16.6,2.8,20,5.6,20,10c0,5.6-3.6,7.3-3.8,7.4C16.1,17.5,15.9,17.5,15.8,17.5z',
			playlist: {
				openned: 'M2.4151,1 19,17.5849 17.5849,19 1,2.4151z M10,9 10,9 10,11 10,11z M1,17.5637 17.6637,1 19,2.4363 2.4636,19z',
				closed: 'M1,2 19,2 19,4 1,4z M1,9 19,9 19,11 1,11z M1,16 19,16 19,18 1,18z'
			},
			download: '&lt;svg viewBox="0 0 20 20"&gt;&lt;path d="M1,10 1,19 19,19 19,10 M10,1 10,12 M8,11 12,11 10,14z"&gt;&lt;/path&gt;&lt;/svg&gt;',
			buy: '&lt;svg viewBox="0 0 20 20"&gt;&lt;path d="M11,1 11,7 M9,7 13,7 11,10z M1,5 3,5 5,13 18,13 19,8 M6,17 a2,2 0 1,1 4,0 a2,2 0 1,1 -4,0 M13,17 a2,2 0 1,1 4,0 a2,2 0 1,1 -4,0"&gt;&lt;/path&gt;&lt;/svg&gt;'
		};

		/* PLAYER BUTTONS */
		playerButtons = {
			playback: {
				nodeName: 'svg',
				attributes: { viewBox: '0 0 20 20' },
				children: [{
					nodeName: "path",
					attributes: { d: playerIcons.playback.play }
				}]
			},
			prev: {
				nodeName: 'svg',
				attributes: { viewBox: '0 0 20 20' },
				children: [{
					nodeName: "path",
					attributes: { d: playerIcons.prev }
				}]
			},
			next: {
				nodeName: 'svg',
				attributes: { viewBox: '0 0 20 20' },
				children: [{
					nodeName: "path",
					attributes: { d: playerIcons.next }
				}]
			},
			repeatToggle: {
				nodeName: 'svg',
				attributes: { viewBox: '0 0 20 20' },
				children: [{
					nodeName: "path",
					attributes: { d: playerIcons.repeat }
				}]
			},
			shuffleToggle: {
				nodeName: 'svg',
				attributes: { viewBox: '0 0 20 20' },
				children: [{
					nodeName: "path",
					attributes: { d: playerIcons.shuffle }
				}]
			},
			playlistToggle: {
				nodeName: 'svg',
				attributes: { viewBox: '0 0 20 20' },
				children: [{
					nodeName: "path",
					attributes: { d: playerIcons.playlist.closed }
				}]
			},
			volumeToggle: {
				nodeName: 'svg',
				attributes: { viewBox: '0 0 20 20' },
				children: [{
					nodeName: "path",
					attributes: { d: playerIcons.volume }
				}]
			},
		};

		/* PLAYER HTML */
		playerHTML = {
			player: [{
				nodeName: 'div',
				class: 'gp-player-wrapper',
				children: [{
					nodeName: 'div',
					class: 'gp-player-left-side',
					children: [{
						nodeName: 'div',
						class: 'gp-player-cover-wrapper',
						children: [{
							nodeName: 'img',
							class: 'gp-player-cover-blurred'
						}, {
							nodeName: 'img',
							class: 'gp-player-cover'
						}]
					}]
				}, {
					nodeName: 'div',
					class: 'gp-player-right-side',
					children: [{
						nodeName: 'div',
						class: 'gp-player-song-info',
						children: [{
							nodeName: 'div',
							class: 'gp-player-song-title',
							children: [{
								nodeName: 'span'
							}]
						}, {
							nodeName: 'div',
							class: 'gp-player-song-artist',
							children: [{
								nodeName: 'span'
							}]
						}]
					}, {
						nodeName: 'div',
						class: 'gp-player-seek-wrapper',
						children: [{
							nodeName: 'div',
							class: 'gp-player-seek',
							children: [{
								nodeName: 'div',
								class: 'gp-player-buffered'
							}, {
								nodeName: 'div',
								class: 'gp-player-progress'
							}, {
								nodeName: 'div',
								class: 'gp-player-loader',
								children: [{
									nodeName: 'span'
								}, {
									nodeName: 'span'
								}, {
									nodeName: 'span'
								}]
							}]
						}, {
							nodeName: 'div',
							class: 'gp-player-timestamps',
							children: [{
								nodeName: 'div',
								class: 'gp-player-currenttime',
								textNode: '00:00'
							}, {
								nodeName: 'div',
								class: 'gp-player-duration',
								textNode: '00:00'
							}]
						}]
					}, {
						nodeName: 'div',
						class: 'gp-player-controls-wrapper',
						children: [{
							nodeName: 'div',
							class: 'gp-player-controls-left-side',
							children: [{
								nodeName: 'div',
								class: 'gp-button gp-player-control gp-playback',
								children: [playerButtons.playback],
								attributes: {
									title: settings.translate.buttons.playback
								}
							}, {
								nodeName: 'div',
								class: 'gp-button gp-player-control gp-prev',
								children: [playerButtons.prev],
								attributes: {
									title: settings.translate.buttons.prev
								}
							}, {
								nodeName: 'div',
								class: 'gp-button gp-player-control gp-repeat-toggle',
								children: [playerButtons.repeatToggle],
								attributes: {
									title: settings.translate.buttons.repeatToggle
								}
							}, {
								nodeName: 'div',
								class: 'gp-button gp-player-control gp-next',
								children: [playerButtons.next],
								attributes: {
									title: settings.translate.buttons.next
								}
							}, {
								nodeName: 'div',
								class: 'gp-button gp-player-control gp-shuffle-toggle',
								children: [playerButtons.shuffleToggle],
								attributes: {
									title: settings.translate.buttons.shuffleToggle
								}
							}, {
								nodeName: 'div',
								class: 'gp-button gp-player-control gp-volume-toggle',
								children: [playerButtons.volumeToggle],
								attributes: {
									title: settings.translate.buttons.volumeToggle
								}
							}, {
								nodeName: 'div',
								class: 'gp-player-volume-seek-wrapper',
								children: [{
									nodeName: 'div',
									class: 'gp-player-volume-seek',
									children: [{
										nodeName: 'div',
										class: 'gp-player-volume-value'
									}]
								}]
							}]
						}, {
							nodeName: 'div',
							class: 'gp-player-controls-right-side',
							children: [{
								nodeName: 'div',
								class: 'gp-button gp-player-control gp-playlist-toggle',
								children: [playerButtons.playlistToggle],
								attributes: {
									title: settings.translate.buttons.playlistToggle
								}
							}]
						}]
					}]
				}]
			}, {
				nodeName: 'div',
				class: 'gp-playlist-wrapper',
				children: [{
					nodeName: 'ul',
					class: 'gp-playlist'
				}]
			}],
			/* Playlist Template */
			playlist: '&lt;li class="gp-playlist-item"&gt;&lt;div class="gp-playlist-marker"&gt;&lt;div class="gp-playlist-bar"&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="gp-playlist-song" title="{artist} - {title}"&gt;&lt;span&gt;{artist}&lt;/span&gt; - {title}&lt;/div&gt;{download}{buy}&lt;/li&gt;',
			/* Style CSS */
			style: [{
				selector: '.gp-player-wrapper',
				properties: {
					background: settings.style.player.background
				}
			}, {
				selector: ['.gp-player-cover-wrapper', '.gp-player-particles-wrapper'],
				properties: {
					background: settings.style.player.cover
				}
			}, {
				selector: '.gp-player-cover-wrapper:before',
				properties: {
					borderColor: settings.style.player.coverLoaderCircle
				}
			}, {
				selector: '.gp-player-cover-wrapper:after',
				properties: {
					borderTopColor: settings.style.player.coverLoader
				}
			}, {
				selector: '.gp-player-song-title',
				properties: {
					color: settings.style.player.title
				}
			}, {
				selector: '.gp-player-song-artist',
				properties: {
					color: settings.style.player.artist
				}
			}, {
				selector: ['.gp-player-loader', '.gp-player-seek', '.gp-player-volume-seek'],
				properties: {
					background: settings.style.player.seek
				}
			}, {
				selector: ['.gp-player-loader span', '.gp-player-buffered',  '.gp-player-progress', '.gp-player-volume-value'],
				properties: {
					background: settings.style.player.progress
				}
			}, {
				selector: '.gp-player-timestamps',
				properties: {
					color: settings.style.player.timestamps
				}
			}, {
				selector: '.gp-button svg',
				properties: {
					fill: settings.style.player.buttons.normal,
					stroke: settings.style.player.buttons.normal
				}
			}, {
				selector: '.gp-button:hover svg',
				properties: {
					fill: settings.style.player.buttons.hover,
					stroke: settings.style.player.buttons.hover
				}
			}, {
				selector: ['.gp-button:active svg', '.gp-button.active svg'],
				properties: {
					fill: settings.style.player.buttons.active,
					stroke: settings.style.player.buttons.active
				}
			}, {
				selector: '.gp-playlist-item',
				properties: {
					background: settings.style.playlist.normal.background,
					borderBottomColor: settings.style.playlist.normal.separator,
					color: settings.style.playlist.normal.color
				}
			}, {
				selector: '.gp-playlist-item:hover',
				properties: {
					background: settings.style.playlist.hover.background,
					borderBottomColor: settings.style.playlist.hover.separator,
					color: settings.style.playlist.hover.color
				}
			}, {
				selector: '.gp-playlist-item.active',
				properties: {
					background: settings.style.playlist.active.background,
					borderBottomColor: settings.style.playlist.active.separator,
					color: settings.style.playlist.active.color
				}
			}, {
				selector: ['.gp-playlist-item .gp-playlist-bar:before', '.gp-playlist-item .gp-playlist-bar:after', '.gp-playlist-item .gp-playlist-bar'],
				properties: {
					background: settings.style.playlist.normal.color
				}
			}, {
				selector: ['.gp-playlist-item:hover .gp-playlist-bar:before', '.gp-playlist-item:hover .gp-playlist-bar:after', '.gp-playlist-item:hover .gp-playlist-bar'],
				properties: {
					background: settings.style.playlist.hover.color
				}
			}, {
				selector: ['.gp-playlist-item.active .gp-playlist-bar:before', '.gp-playlist-item.active .gp-playlist-bar:after', '.gp-playlist-item.active .gp-playlist-bar'],
				properties: {
					background: settings.style.playlist.active.color
				}
			}, {
				selector: ['.gp-playlist-item .gp-playlist-song-buy svg', '.gp-playlist-item .gp-playlist-song-download svg'],
				properties: {
					stroke: settings.style.playlist.normal.color
				}
			}, {
				selector: ['.gp-playlist-item:hover .gp-playlist-song-buy svg', '.gp-playlist-item:hover .gp-playlist-song-download svg'],
				properties: {
					stroke: settings.style.playlist.hover.color
				}
			}, {
				selector: ['.gp-playlist-item.active .gp-playlist-song-buy svg', '.gp-playlist-item.active .gp-playlist-song-download svg'],
				properties: {
					stroke: settings.style.playlist.active.color
				}
			}, {
				selector: '.gp-playlist-wrapper',
				properties: {
					background: settings.style.playlist.scroll.background
				}
			}, {
				selector: '.gp-playlist::-webkit-scrollbar-track',
				properties: {
					background: settings.style.playlist.scroll.rail
				}
			}, {
				selector: '.gp-playlist::-webkit-scrollbar-thumb',
				properties: {
					background: settings.style.playlist.scroll.scrollbar
				}
			}, {
				selector: '.gp-playlist',
				properties: {
					scrollbarColor: settings.style.playlist.scroll.scrollbar + ' ' + settings.style.playlist.scroll.rail
				}
			}]
		};

		this.buildPlayer = function() {
			let styleCss = '',
					head = document.head || document.getElementsByTagName('head')[0],
					styleTag = document.getElementById('gp-styles');

			// Add Class
			jsFW(elements.wrapper).addClass('gp-player ' + this.skin);
			// Create Player
			jsFW(elements.wrapper).buildDOM(playerHTML.player);
			// Create Playlist
			let playlist = elements.wrapper.querySelector('.gp-playlist');
			this.playlist.forEach(function(item) {
				let artist, title, download, buy, playlistItem;
				// Prepare Artist and Titles
				artist = item.artist ? item.artist : settings.translate.playlist.noAtist;
				title = item.title ? item.title : settings.translate.playlist.noTitle;
				// Prepare Download and Buy
				download = item.download ? '&lt;a href="' + item.download + '" target="_blank" class="gp-playlist-song-download" title="' + settings.translate.buttons.download + '"&gt;' + playerIcons.download + '&lt;/a&gt;' : "";
				buy = item.buy ? '&lt;a href="' + item.buy + '" target="_blank" class="gp-playlist-song-buy" title="' + settings.translate.buttons.buy + '"&gt;' + playerIcons.buy + '&lt;/a&gt;' : "";
				// Create Playlist Item
				playlistItem = playerHTML.playlist.replace(/\{artist\}/g, artist).replace(/\{title\}/g, title).replace('{download}', download).replace('{buy}', buy);
				// Add Playlist Item to Playlist
				playlist.insertAdjacentHTML('beforeend', playlistItem);
			});
			// Create Styles
			if (!styleTag) {
				styleTag = document.createElement('style');
				styleTag.id = 'gp-styles';
				head.appendChild(styleTag);
				styleTag.setAttribute('type', 'text/css');
			}
			// Generate Styles
			playerHTML.style.forEach(function(item) {
				let cssSelector = [];
				// Selector
				if(Array.isArray(item.selector)) {
					item.selector.forEach(function(name, index) {
						cssSelector[index] = '#' + _this.id + '.custom ' + item.selector[index];
					});
				} else {
					cssSelector = '#' + _this.id + '.custom ' + item.selector;
				}
				styleCss += cssSelector + ' {\n';
				for(var property in item.properties) {
					if(item.properties.hasOwnProperty(property)) {
						styleCss += property.replace(/[A-Z]/g, function (m) { return "-" + m.toLowerCase(); }) + ': ' + item.properties[property] + ';\n'; 
					}
				}
				styleCss += '}\n';
			});
			// Add Styles
			styleTag.appendChild(document.createTextNode(styleCss));
		};

		this.prepareControls = function() {
			elements.coverBlurred = elements.wrapper.querySelector('.gp-player-cover-blurred');
			elements.cover = elements.wrapper.querySelector('.gp-player-cover');
			elements.artist = elements.wrapper.querySelector('.gp-player-song-artist span');
			elements.title = elements.wrapper.querySelector('.gp-player-song-title span');
			elements.seek = elements.wrapper.querySelector('.gp-player-seek');
			elements.buffered = elements.wrapper.querySelector('.gp-player-buffered');
			elements.progress = elements.wrapper.querySelector('.gp-player-progress');
			elements.currentTime = elements.wrapper.querySelector('.gp-player-currenttime');
			elements.duration = elements.wrapper.querySelector('.gp-player-duration');
			elements.prev = elements.wrapper.querySelector('.gp-prev');
			elements.playback = elements.wrapper.querySelector('.gp-playback');
			elements.next = elements.wrapper.querySelector('.gp-next');
			elements.shuffleToggle = elements.wrapper.querySelector('.gp-shuffle-toggle');
			elements.repeatToggle = elements.wrapper.querySelector('.gp-repeat-toggle');
			elements.playlistToggle = elements.wrapper.querySelector('.gp-playlist-toggle');
			elements.volumeToggle = elements.wrapper.querySelector('.gp-volume-toggle');
			elements.volumeSeek = elements.wrapper.querySelector('.gp-player-volume-seek-wrapper');
			elements.volumeValue = elements.wrapper.querySelector('.gp-player-volume-value');
			elements.playlistWrapper = elements.wrapper.querySelector('.gp-playlist-wrapper');
			elements.playlist = elements.wrapper.querySelector('.gp-playlist');
			elements.playlistItem = elements.wrapper.querySelectorAll('.gp-playlist-item');

			// Prepare Settings
			// Scroll
			if(settings.songsVisible !== null &amp;&amp; this.playlist.length &gt; settings.songsVisible) {
				// Max height by amount visible song * 40
				elements.playlistWrapper.style.maxHeight = 40 * settings.songsVisible + "px";
			}
			// If less than 2 songs: hide repeat, shuffle, next and prev
			if(this.playlist.length === 1) {
				elements.repeatToggle.style.display = 'none';
				elements.shuffleToggle.style.display = 'none';
				elements.next.style.display = 'none';
				elements.prev.style.display = 'none';
			} else {
				// IF ENABLED PLAYLIST SHOW
				if(settings.showPlaylist) {
					this.playlistToggle();
				}
				// IF DESABLED REPEAT
				if(!settings.repeat) {
					elements.repeatToggle.style.display = "none";
				}
				// IF DISABLED SHUFFLE
				if(!settings.shuffle) {
					elements.shuffleToggle.style.display = "none";
				}
			}
			// If it's Mobile
			if(this.state.isMobile) {
				elements.volumeToggle.style.display = "none";
				elements.volumeSeek.style.display = "none";
			}
			// IF DISABLED COVER
			if(!settings.cover) {
				elements.wrapper.style.padding = '20px 0';
				elements.wrapper.querySelector('.gp-player-left-side').remove();
			}
		};

		// Add EVENTS
		this._addEventListener = function() {
			/* AUDIO */
			let audioEvents = ['abort', 'canplay', 'canplaythrough', 'durationchange', 'emptied', 'ended', 'error', 'loadeddata', 'loadedmetadata', 'loadstart', 'pause', 'play', 'playing', 'progress', 'ratechange', 'seeked', 'seeking', 'stalled', 'suspend', 'timeupdate', 'volumechange', 'waiting'];
			// Add all audio events
			audioEvents.forEach(function(event) {
				_this.audio.addEventListener(event, _this[event]);
			});

			/* BUTTONS */
			// Playback
			elements.playback.addEventListener('click', this.playback);
			// Previous Song
			elements.prev.addEventListener('click', this.prevSong);
			// Next Song
			elements.next.addEventListener('click', this.nextSong);
			// Volume Toggle
			elements.volumeToggle.addEventListener('click', this.volumeToggle);
			// Repeat Toggle
			elements.repeatToggle.addEventListener('click', this.repeatToggle);
			// Shuffle Toggle
			elements.shuffleToggle.addEventListener('click', this.shuffleToggle);
			// Playlist Toggle
			elements.playlistToggle.addEventListener('click', this.playlistToggle);

			// Playlist's Items Events
			elements.playlistItem.forEach(function(item) {
				let download = item.querySelector('.apb-song-download'),
						buy = item.querySelector('.apb-song-buy');

				// SELECT SONG FROM PLAYLIST
				item.addEventListener('click', function() {
					// If New Index
					if(_this.currentSong != Array.from(elements.playlistItem).indexOf(item)) {
						_this.currentSong = Array.from(elements.playlistItem).indexOf(item);
						_this.state.autoplay = true;
						_this.switchSong();
					}
				});
				// PREVENT DOWNLOAD CLICK
				if(download) {
					download.addEventListener('click', function(event) {
						event.stopPropagation();
					});
				}
				// PREVENT BUY CLICK
				if(buy) {
					buy.addEventListener('click', function(event) {
						event.stopPropagation();
					});
				}
			});

			// SEKING
			if(this.state.isMobile) {
				elements.seek.addEventListener('touchstart', _this.seekingStart, false);
			} else {
				elements.seek.addEventListener('mousedown', _this.seekingStart, false);
				elements.volumeSeek.addEventListener('mousedown', _this.volumeSeekingStart, false);
			}
		};

		this.reloadCover = function() {
			let keyframesIn = [{ opacity: 1 }, { opacity: 0}],
					keyframeOut = [{ opacity: 0 }, { opacity: 1}],
					animationProperties = {
						duration: 500,
						delay: 0,
						easing: 'linear',
						fill: 'forwards'
					};
			// Have album cover or cover
			if(settings.albumCover || _this.playlist[_this.currentSong].cover) {
				// If Vissible Cover Hide it
				if(_this.state.coverVissible) {
					elements.cover.animate(keyframesIn, animationProperties);
					elements.coverBlurred.animate(keyframesIn, animationProperties);
				}
				jsFW(elements.cover).imgLoader({
					img: settings.albumCover ? settings.albumCover : _this.playlist[_this.currentSong].cover,
					onLoad: function(img) {
						// Fix Animation time
						setTimeout(function() {
							// Update SRC
							elements.cover.src = img;
							elements.coverBlurred.src = img;
							elements.cover.animate(keyframeOut, animationProperties);
							elements.coverBlurred.animate(keyframeOut, animationProperties);
							_this.state.coverVissible = true;
						}, animationProperties.duration);
					}
				});
			}
		};

		this.switchSongAnimation = function() {
			let keyframesIn = [{ transform: 'translateY(0)' }, { transform: 'translateY(-25px)'}],
					keyframeOut = [{ transform: 'translateY(25px)' }, { transform: 'translateY(0px)'}],
					animationProperties = {
						duration: 250,
						delay: 0,
						easing: 'cubic-bezier(0.55, 0, 1, 0.45)',
						fill: 'forwards'
					};

			// If Cover For all album, just show it
			if(settings.albumCover) {
				// If no cover set it
				if(elements.cover.src === "") {
					jsFW(elements.cover).imgLoader({
						img: settings.albumCover,
						onLoad: function(img) {
							let keyframeOut = [{ opacity: 0 }, { opacity: 1}],
									animationProperties = {
										duration: 500,
										delay: 0,
										easing: 'linear',
										fill: 'forwards'
									};
							// Update SRC
							elements.cover.src = img;
							elements.coverBlurred.src = img;
							// Animate
							elements.cover.animate(keyframeOut, animationProperties);
							elements.coverBlurred.animate(keyframeOut, animationProperties);
							_this.state.coverVissible = true;
						}
					});
				}
			} else {
				// Change Cover
				if(settings.cover) {
					this.reloadCover();
				}
			}
			// Title
			elements.title.animate(keyframesIn, animationProperties).onfinish = function() {
				elements.title.textContent = _this.playlist[_this.currentSong].title ? _this.playlist[_this.currentSong].title : settings.translate.playlist.noTitle;
				elements.title.title = _this.playlist[_this.currentSong].title ? _this.playlist[_this.currentSong].title : settings.translate.playlist.noTitle;
				animationProperties.easing = 'cubic-bezier(0, 0.55, 0.45, 1)';
				elements.title.animate(keyframeOut, animationProperties);
			};

			// Artist
			animationProperties.delay = 100;
			animationProperties.easing = 'cubic-bezier(0.55, 0, 1, 0.45)';
			elements.artist.animate(keyframesIn, animationProperties).onfinish = function() {
				elements.artist.textContent = settings.albumArtist ? settings.albumArtist : _this.playlist[_this.currentSong].artist ? _this.playlist[_this.currentSong].artist : settings.translate.playlist.noAtist;
				elements.artist.title = settings.albumArtist ? settings.albumArtist : _this.playlist[_this.currentSong].artist ? _this.playlist[_this.currentSong].artist : settings.translate.playlist.noAtist;
				animationProperties.easing = 'cubic-bezier(0, 0.55, 0.45, 1)';
				elements.artist.animate(keyframeOut, animationProperties);
			};

			// Remove class "active and playing" from all playlist items
			jsFW(elements.playlistItem[_this.currentSong]).removeClass('active playing');
			// Select Item in Playlist
			jsFW(elements.playlistItem[_this.currentSong]).addClass('active');
		};

		this.init =  function() {
			// Build Player
			this.buildPlayer();
			// Prepare Controls
			this.prepareControls();
			// Add Events
			this._addEventListener();
			// Load Firtst Song
			this.audio.src = this.playlist[this.currentSong].source;
			this.audio.load();
			this.audio.volume = this.volume;
			// Prepare Song Info
			this.switchSongAnimation();
		};

		// Set Player Event
		this.setEvent = function(event) {
			if(_this.Events !== event) {
				_this.Events = event;
				if(settings.debug) {
					console.log(event);
				}
			}
			switch(_this.Events) {
				case 'abort':
					console.log('audio load aborted');
					break;
			}
		};

		/* AUDIO EVENTS */
		// Abort
		this.abort = function() {
			_this.setEvent('abort');
		};

		// Canplay
		this.canplay = function() {
			_this.setEvent('canplay');
			// Remove Loading State
			jsFW(elements.wrapper).removeClass('loading');
		};

		// Canplaythrough
		this.canplaythrough = function() {
			_this.setEvent('canplaythrough');
			// Remove Loading State
			jsFW(elements.wrapper).removeClass('loading');
			// If autoplay
			if(_this.state.autoplay) {
				_this.audio.play();
			}
		};

		// Durationchange
		this.durationchange = function() {
			_this.setEvent('durationchange');
			_this.getDuration();
		};

		// Emptied
		this.emptied = function() {
			_this.setEvent('emptied');
		};

		// Ended
		this.ended = function() {
			_this.setEvent('ended');
			// Play Next
			_this.nextSong();
		};

		// Error
		this.error = function() {
			_this.setEvent('error');
			switch(_this.audio.error.code) {
				case 1:
					console.log('The user canceled the audio.');
					break;
				case 2:
					console.log('A network error occurred while fetching the audio.');
					break;
				case 3:
					console.log('An error occurred while decoding the audio.');
					break;
				case 4:
					console.log('The audio is missing or is in a format not supported by your browser.');
					break;
				default:
					console.log('An unknown error occurred.');
					break;
			}
		};

		// Loaded data
		this.loadeddata = function() {
			_this.setEvent('loadeddata');
		};

		// Loaded metadata
		this.loadedmetadata = function() {
			_this.setEvent('loadedmetadata');
			_this.getDuration();
		};

		// Load Start
		this.loadstart = function() {
			_this.setEvent('loadstart');
			// Add Loading State
			jsFW(elements.wrapper).addClass('loading');
		};

		// Pause
		this.pause = function() {
			_this.setEvent('pause');
			// Remove HL 'playing' from Playlist
			jsFW(elements.playlistItem).removeClass('playing');
			// Button State
			jsFW(elements.playback).removeClass('active');
			elements.playback.querySelector('path').setAttribute('d', playerIcons.playback.play);
		};

		// Play
		this.play = function() {
			_this.setEvent('play');
			// STOP OTHERS PLAYERS
			Object.keys(gPlayers).forEach(function(player) {
				if (player !== _this.id) {
					gPlayers[player].pause();
				}
			});
			// Highlight Playing Song in Playlist
			jsFW(elements.playlistItem[_this.currentSong]).addClass('playing');
			// Button State
			jsFW(elements.playback).addClass('active');
			elements.playback.querySelector('path').setAttribute('d', playerIcons.playback.pause);
		};

		// Playing
		this.playing = function() {
			_this.setEvent('playing');
			// Remove Loading State
			jsFW(elements.wrapper).removeClass('loading');
		};

		// Progress
		this.progress = function() {
			let audio = _this.audio, duration = audio.duration, progress = 0;
			_this.setEvent('progress');
			if(audio.buffered.length) {
				progress = audio.buffered.end(audio.buffered.length - 1) / duration;
				elements.buffered.style.width = progress * 100 + "%";
				if(progress == 1) {
					elements.buffered.style.opacity = 0;
				} else {
					elements.buffered.style.opacity = 0.25;
				}
			}
		};

		// Rate Change
		this.ratechange = function() {
			_this.setEvent('ratechange');
		};

		// Seeked
		this.seeked = function() {
			_this.setEvent('seeked');
			jsFW(elements.wrapper).removeClass('loading');
		};

		// Seeking
		this.seeking = function() {
			_this.setEvent('seeking');
			jsFW(elements.wrapper).addClass('loading');
		};

		// Staled
		this.stalled = function() {
			_this.setEvent('stalled');
		};

		// Suspend
		this.suspend = function() {
			_this.setEvent('suspend');
		};

		// TimeUpdate
		this.timeupdate = function() {
			_this.setEvent('timeupdate');
			if(!_this.state.seeking) {
				// Set Current Time
				_this.currentTime = _this.audio.currentTime;
				// Get Percents
				let percent = (_this.currentTime / _this.audio.duration) * 100;
				// Set value for seek progress
				elements.progress.style.width = percent + '%';
				// Set Curent Time in Player
				elements.currentTime.textContent = formatTime(_this.audio.currentTime);
				_this.progress();
			}
		};

		// Volume Change
		this.volumechange = function() {
			_this.setEvent('volumechange');
			elements.volumeValue.style.width = _this.audio.volume * 100 + 'px';
		};

		// Waiting
		this.waiting = function() {
			_this.setEvent('waiting');
			// Add Loading State
			jsFW(elements.wrapper).addClass('loading');
		};


		/* PLAYER FUNCTIONS */
		// Playback
		this.playback = function() {
			if(_this.audio.paused) {
				_this.audio.play();
				_this.state.autoplay = true;
			} else {
				_this.audio.pause();
				_this.state.autoplay = false;
			}
		};

		// Prev song
		this.prevSong = function() {
			// If Shuffle Mode is On
			if(_this.state.shuffle) {
				// Get first index from Order List
				_this.currentSong = _this.orderList[0];
				// If has Items Just Slice, else Get New Order List
				if(_this.orderList.length &gt; 1) {
					_this.orderList.splice(0, 1);
				} else {
					_this.orderList = getOrderList();
				}
				// Switch song
				_this.switchSong();
			} else {
				// Shuffle Mode is Off
				// If Not First Item
				if(_this.currentSong - 1 &gt;= 0) {
					_this.currentSong--;
					_this.switchSong();
				} else {
					// If Repeat Mode is On
					if(_this.state.repeat) {
						_this.currentSong = _this.playlist.length - 1;
						_this.switchSong();
					} else {
						// If Repead is Off
						_this.audio.pause();
						_this.audio.currentTime = 0;
						_this.state.autoplay = false;
					}
				}
			}
		};

		// Next song
		this.nextSong = function() {
			// If Shuffle Mode is On
			if(_this.state.shuffle) {
				// Get first index from Order List
				_this.currentSong = _this.orderList[0];
				// If has Items Just Slice, else Get New Order List
				if(_this.orderList.length &gt; 1) {
					_this.orderList.splice(0, 1);
				} else {
					_this.orderList = getOrderList();
				}
				// Switch song
				_this.switchSong();
			} else {
				// Shuffle Mode is Off
				// If Not Last Item
				if(_this.currentSong + 1 &lt; _this.playlist.length) {
					_this.currentSong++;
					_this.switchSong();
				} else {
					// If Last Item
					// If Repeat Mode is On
					if(_this.state.repeat) {
						_this.currentSong = 0;
						_this.switchSong();
					} else {
						// If Repead is Off
						_this.audio.pause();
						_this.audio.currentTime = 0;
						_this.state.autoplay = false;
					}
				}
			}
		};

		// Repeat Toggle
		this.repeatToggle = function() {
			// Toggle State
			_this.state.repeat = !_this.state.repeat;
			jsFW(elements.repeatToggle).toggleClass('active');
		};

		// Shuffle Toggle
		this.shuffleToggle = function() {
			// Toggle State
			_this.state.shuffle = !_this.state.shuffle;
			jsFW(elements.shuffleToggle).toggleClass('active');
			_this.orderList = (_this.state.shuffle) ? getOrderList() : null;
		};

		// Volume Toggle
		this.volumeToggle = function() {
			// Toggle State
			_this.state.volumeToggle = !_this.state.volumeToggle;
			if(_this.state.volumeToggle) {
				jsFW(elements.volumeToggle).addClass('active');
			} else {
				jsFW(elements.volumeToggle).removeClass('active');
			}
		};

		// Playlist Toggle
		this.playlistToggle = function() {
			let playlistHeight = 0;
			// Toggle State
			_this.state.playlistToggle = !_this.state.playlistToggle;
			// Toggle Classes
			jsFW(elements.playlistToggle).toggleClass('active');
			jsFW(elements.wrapper).toggleClass('playlist-openned');

			// Show or Hide Playlist
			if(_this.state.playlistToggle) {
				// Button Icons Change
				elements.playlistToggle.querySelector('path').setAttribute('d', playerIcons.playlist.openned);
				// IF SCROLL
				if(_this.playlist.length &gt; settings.songsVisible &amp;&amp; settings.songsVisible !== null) {
					playlistHeight = settings.songsVisible * 40 + 'px';
					jsFW(elements.playlistWrapper).addClass('scroll');
				} else {
					playlistHeight = _this.playlist.length * 40 + 'px';
				}
			} else {
				// Button Icons Change
				elements.playlistToggle.querySelector('path').setAttribute('d', playerIcons.playlist.closed);
			}
			// Set Height
			elements.playlistWrapper.style.height = playlistHeight;
		};

		// Seeking
		this.seekingStart = function(event) {
			event.preventDefault();
			if(_this.state.isMobile) {
				_this.state.seeking = true;
				_this.seekingTo(event); // In no move, set value from start
				window.addEventListener('touchmove', _this.seekingTo, false);
				window.addEventListener('touchend', _this.seekingFinish, false);
			} else {
				if(event.button === 0) {
					_this.state.seeking = true;
					_this.seekingTo(event); // In no move, set value from start
					document.documentElement.addEventListener('mousemove', _this.seekingTo, false);
					document.documentElement.addEventListener('mouseup', _this.seekingFinish, false);
				}
			}
		};

		this.seekingTo = function(event) {
			if(_this.state.seeking) {
				let bound = elements.seek.getBoundingClientRect(),
						clientX = event.clientX ? event.clientX : event.touches[0].clientX,
						percent = (clientX - bound.left) / bound.width;
				// Fix percent
				percent = percent &gt; 1 ? 1 : percent &lt; 0 ? 0 : percent;

				elements.progress.style.width = percent * 100 + "%";
				_this.currentTime = _this.audio.duration * percent;
				elements.currentTime.textContent = formatTime(_this.currentTime);
			}
		};

		this.seekingFinish = function() {
			if(_this.state.isMobile) {
				window.removeEventListener('touchmove', _this.seekingTo, false);
				window.removeEventListener('touchend', _this.seekingFinish, false);
			} else {
				document.documentElement.removeEventListener('mousemove', _this.seekingTo, false);
				document.documentElement.removeEventListener('mouseup', _this.seekingFinish, false);
			}
			_this.state.seeking = false;
			_this.audio.currentTime = _this.currentTime;
		};

		// Volume Seeking
		this.volumeSeekingStart = function(event) {
			event.preventDefault();
			if(event.button === 0) {
				_this.state.volumeSeeking = true;
				_this.volumeSeekingTo(event); // In no move, set value from start
				document.documentElement.addEventListener('mousemove', _this.volumeSeekingTo, false);
				document.documentElement.addEventListener('mouseup', _this.volumeSeekingFinish, false);
			}
		};

		this.volumeSeekingTo = function(event) {
			if(_this.state.volumeSeeking) {
				let bound = elements.volumeSeek.getBoundingClientRect(),
						clientX = event.clientX,
						percent = (clientX - bound.left) / bound.width;
				// Fix Percent
				percent = percent &gt; 1 ? 1 : percent &lt; 0 ? 0 : percent;
				_this.audio.volume = percent;
			}
		};

		this.volumeSeekingFinish = function() {
			document.documentElement.removeEventListener('mousemove', _this.volumeSeekingTo, false);
			document.documentElement.removeEventListener('mouseup', _this.volumeSeekingFinish, false);
			_this.state.volumeSeeking = false;
		};

		this.switchSong = function() {
			let scrollDistance = 0;
			// RESET PROGRESS
			_this.audio.pause();
			_this.audio.currentTime = 0;
			// Load Song
			_this.audio.src = _this.playlist[_this.currentSong].source;
			_this.audio.load();
			// Remove class "playing" from all playlist items
			jsFW(elements.playlistItem).removeClass('active playing');
			// Add class "active" to current song
			jsFW(elements.playlistItem[_this.currentSong]).addClass('active');
			// AUTOSCROLL
			if(settings.songsVisible != null &amp;&amp; _this.playlist.length &gt; settings.songsVisible) {
				if(_this.currentSong + 1 &gt;= settings.songsVisible) {
					scrollDistance = 40 * (_this.currentSong - settings.songsVisible + 1);
				} else {
					scrollDistance = 0;
				}
				// Scroll To
				elements.playlist.scrollTo({
					top: scrollDistance,
					behavior: "smooth"
				});
			}
			_this.switchSongAnimation();
		};
		
		// Get Duration
		this.getDuration = function() {
			elements.duration.textContent = formatTime(_this.audio.duration);
		};

		/* Utilities */
		// Format Time
		function formatTime(secs) {
			var hours, minutes, seconds, sec_num;
			sec_num = parseInt(secs, 10);
			hours   = Math.floor(sec_num / 3600);
			minutes = Math.floor(sec_num / 60) % 60;
			seconds = sec_num % 60;

			return [hours, minutes, seconds].map(function (v) { return v &lt; 10 ? "0" + v : v; }).filter(function (v, i) { return v !== "00" || i &gt; 0; }).join(":");
		}

		// Get Oreder List
		 function getOrderList() {
			let array = [], i, j, temp = null;
			// create array of nums from 0 to playlist length
			for(i = 0; i &lt; _this.playlist.length; i++) {
				if(i !== _this.currentSong) {
					array.push(i);
				}
			}
			// shuffle array and return
			for(i = array.length - 1; i &gt; 0; i--) {
				j = Math.floor(Math.random() * (i + 1));
				temp = array[i];
				array[i] = array[j];
				array[j] = temp;
			}
			return array;
		}

		// Detect Mobile
		function detectMobile() {
			var toMatch = [/Android/i, /webOS/i, /iPhone/i, /iPad/i, /iPod/i, /BlackBerry/i, /Windows Phone/i];
			return toMatch.some(function(toMatchItem) {
				return navigator.userAgent.match(toMatchItem);
			});
		}
		
		// Random Integer
		function getRandomInt(min, max) {
			min = Math.ceil(min);
			max = Math.floor(max);
			return Math.floor(Math.random() * (max - min + 1)) + min;
		}

		this.init();
	};

	window.gPlayer = gPlayer;

})(window);</pre></body></html>