PageSourceSearch

https://teamfm.nl/wp-content/plugins/qtmplayer/assets/js/qtmplayer.js?ver=PR.8.5

js teamfm.nl collected 2026-09-24 13:13:12 UTC 50,860 bytes, 1,677 lines download raw bytes

1/** @license
2 *
3 * ProRadio Music Player: JavaScript player with audio analyzer
4 * ----------------------------------------------
5 * http://proradio.com/
6 *
7 * Copyright (c) 2020-2021, ProRadio / Igor Nardo. All rights reserved.
8 * This software cna be used only within our products. It can't be edited or modified for reuse under other projects.
9 * Cannot be re-sold or embedded in other products for sale.
10 *
11 */
12
13
14// IMPORTANT: THE FOLLOWING IS NOT A COMMENT! IT IS JAVASCIPT IMPORTING! DO NOT DELETE
15// ===================================================================================
16// @codekit-prepend "../components/raphael/raphael.min.js"
17// @codekit-prepend "../soundmanager/script/soundmanager2-nodebug-jsmin.js"
18// @codekit-prepend "qtmplayer-smpo.js"
19// @codekit-prepend "qtmplayer-radiofeed.js"
20
21// Not required			codekit-prepend "qtmplayer-webapiplayer.js" 
22
23(function($){
24	
25	var qtPlayDebug = $('#qtmplayer').data('qtmplayer-debugger');
26	var qtAnalyzer  = $('#qtmplayer').data('analyzer'); // disable webaudio
27	var qtInitialized = false;
28	var qtPlayIsAllowed = false;
29	var qtShowPlayer  = $('#qtmplayer').data('showplayer'); // disable webaudio
30
31
32	if( /MSIE|Edge|Trident/i.test(navigator.userAgent) || ( navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Chrome') == -1 ) ){
33		qtAnalyzer = 0;
34	}
35
36	function qtMplayer_filename(path){
37		path = path.substring(path.lastIndexOf("/")+ 1);
38		return (path.match(/[^.]+(\.[^?#]+)?/) || [])[0];
39	}
40
41	// since 3.0.2 moved browser detection to mobile
42	var qtMplayerisMobile = false;
43	if( /MSIE|Edge|Trident/i.test(navigator.userAgent) 
44		|| ( 
45			navigator.userAgent.indexOf('Safari') != -1 
46			&& 
47			navigator.userAgent.indexOf('Chrome') == -1 
48			) 
49		){
50		qtMplayerisMobile = true;
51	}
52	if( /iPad/i.test(navigator.userAgent) ){
53		qtMplayerisMobile = true;
54	}
55	if( /iPhone/i.test(navigator.userAgent) ){
56		qtMplayerisMobile = true;
57	}
58	if (screen.width <= 1119){ 
59		qtMplayerisMobile = true;
60	}
61	if(true === qtMplayerisMobile){
62		qtAnalyzer = 0;
63	}
64
65
66	$.qtMplayerGlobalSongData = {
67		title: false,
68		artist: false,
69		thumbnail: false
70	};
71
72	$.qtMplayerPlaylistCue = {
73		minicue: false,
74		tadv: false,
75		init: function(){
76			$.qtMplayerPlaylistCue.destroy();
77			var item, offset, width,left,
78				minicue, det;;
79			item = $("li.qtmplayer-played");
80			if(item.length > 0){
81				offset = item.offset().left;
82				width =  item.width();
83				left = 0;
84				item.append('<div id="qtMplayerPlaylistTrack" class="qtmplayer-playlist__track"><span id="qtMplayerPlaylistTrackAdv" data-qtmplayer-trackadv class="qtmplayer-track-adv qtmplayer-content-accent"></span>
84<span id="qtMplayerPlaylistMinicue" class="qtmplayer-playlist-minicue"></span></div>');
85				$.qtMplayerPlaylistCue.minicue = $("#qtMplayerPlaylistMinicue");
86				$.qtMplayerPlaylistCue.tadv = $("#qtMplayerPlaylistTrackAdv");
87				det = $("#qtMplayerPlaylistTrack");
88				det.off("mousemove").off("click");
89				det.on("mousemove", function(e){
90					left = e.clientX - offset;
91					$.qtMplayerPlaylistCue.minicue.css({
92						'left': left,
93						'transition': 'left 0.1s'
94					});
95				});
96				det.on("click", function(e){
97					$.qtPlayerObj.uniPlayer.seek((e.clientX - offset) / width * 100);
98				});
99			}
100		},
101		update:function(p){
102			if($.qtMplayerPlaylistCue.tadv){
103				$.qtMplayerPlaylistCue.tadv.css({"width": p+'%'});
104			}
105			if($.qtMplayerPlaylistCue.minicue){
106				// $.qtMplayerPlaylistCue.minicue.css({"left": p+'%'});
107			}
108		},
109		destroy: function(){
110			$("#qtMplayerPlaylistTrack").remove();
111		}
112	};
113
114	/**
115	 * ===========================================================================
116	 * Circle for podcast
117	 * @type {Object}
118	 * ===========================================================================
119	 */
120	$.qtRaphaelCircle = {
121		container: $(".qtmplayer-circularplayer"),
122		findXY: function(obj) {
123			var curleft = 0, curtop = 0;
124			do {
125				curleft += obj.offsetLeft;
126				curtop += obj.offsetTop;
127			} while (!!(obj = obj.offsetParent));
128			return [curleft,curtop];
129		},
130		getScrollLeft: function() {
131			return ($('body').scrollLeft+document.documentElement.scrollLeft);
132		},
133		getScrollTop: function() {
134			return ($('body').scrollTop+document.documentElement.scrollTop);
135		},
136		init: function(){
137
138			if ( typeof $ !== 'undefined' &&  $.qtPlayerObj && $.qtPlayerObj.songdata && $.qtPlayerObj.songdata.type === 'radio') {
139  				return;
140			}
141
142			var RC = $.qtRaphaelCircle,
143				rcontainer = $("#qtdonut"),
144				
145				cH = rcontainer.height(),
146				cW = rcontainer.width(),
147				R = cH / 2;
148			RC.destroy();
149			rcontainer.find("svg").remove();
150			RC.R = R;
151			var archtype = new Raphael("qtdonut", cW, cH);
152			archtype.customAttributes.arc = function (xloc, yloc, value, total, R) {
153				var alpha = 360 / total * value,
154					a = (90 - alpha) * Math.PI / 180,
155					x = xloc + R * Math.cos(a),
156					y = yloc - R * Math.sin(a),
157					path;
158				if (total === value) {
159					path = [
160						["M", xloc, yloc - R],
161						["A", R, R, 0, 1, 1, xloc, yloc - R]
162					];
163				} else {
164					path = [
165						["M", xloc, yloc - R],
166						["A", R, R, 0, +(alpha > 180), 1, x, y]
167					];
168				}
169				return {
170					path: path
171				};
172			};
173			var my_arc = archtype.path().attr({
174				"stroke": "#fff",
175				"stroke-width": '22px',
176				arc: [0, 0, 0, 0, 0]
177			});
178			RC.arc = my_arc;
179			RC.container = rcontainer;
180			var	uA = navigator.userAgent,
181				isOpera = (uA.match(/opera/i)),
182				isChrome = (uA.match(/chrome/i)),
183				isTouchDevice = (uA.match(/ipad|iphone/i)),
184				fullCircle = (isOpera||isChrome?359.9:360),
185				angle, offl, offt,
186				dx,dy,coords, perc;
187
188			rcontainer.on('click','svg',function(e){
189				e = e?e:window.event;
190				if (isTouchDevice && e.touches) {
191					e = e.touches[0];
192				}
193				if (e.pageX || e.pageY) {
194					coords = [e.pageX,e.pageY];
195				} else if (e.clientX || e.clientY) {
196					coords = [e.clientX+RC.getScrollLeft(),e.clientY+RC.getScrollTop()];
197				}
198				offl = rcontainer.offset().left;
199				offt = rcontainer.offset().top - $(window).scrollTop() ;
200				dx = e.clientX -  (offl + (cW / 2));
201				dy = e.clientY -  (offt + (cH / 2));
202				angle = Math.floor(fullCircle-(  (Math.atan2(dx,dy) * 180/Math.PI )  +180));
203				perc = angle/fullCircle * 100;
204				$.qtPlayerObj.uniPlayer.seek(perc);
205			});
206			rcontainer.addClass("active");
207		},
208		update: function(p){
209
210			if ( typeof $ !== 'undefined' &&  $.qtPlayerObj && $.qtPlayerObj.songdata && $.qtPlayerObj.songdata.type === 'radio') {
211  				return;
212			}
213
214
215
216			var RC = $.qtRaphaelCircle,
217				R = RC.R;
218			if(typeof(p) === 'undefined' || typeof(RC.arc) === 'undefined' ){
219				return;
220			}
221			if(isNaN(p)){
222				return;
223			}
224			RC.arc.animate({
225				arc: [R, R, p*100, 100, R]
226			}, 2, "ease");
227		},
228		destroy: function(){
229			var RC = $.qtRaphaelCircle;
230
231			if(typeof(RC.arc) !== 'undefined'){
232				RC.arc.remove();
233				RC.container.removeClass('active');
234			}
235			if(typeof(RC.container) !== 'undefined'){
236				RC.container.removeClass('active');
237			}
238		}
239	};
240
241
242
243	/**
244	 * =============================================================================================================================================
245	 * /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
246	 * =============================================================================================================================================
247	 * 
248	 * Player Object
249	 * This is the main interface controller
250	 * 
251	 * =============================================================================================================================================
252	 * /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
253	 * =============================================================================================================================================
254	 * */
255	$.qtPlayerObj = {
256		isSoundApi: false,
257		playing: false,
258		hasDoneAutoplay: false,
259		masterVolume:  $('#qtmplayer').data('qtmplayer-startvol'),//100,
260		ProRadioUserManagerIntegration: {
261			shouldBlock: function( songdata ){
262				if('undefined' == typeof($.ProRadioUserManager)){
263					return;
264				}
265				if( 'undefined' === typeof( songdata ) ){
266					songdata = $.qtPlayerObj.songdata;
267				}
268				var prum = $.ProRadioUserManager;
269				var blocking = $.qtPlayerObj.songdata.blocking;
270				
271				if( undefined !== blocking ){
272					console.log( blocking );
273					prum.fn.modal.openModal(prum, blocking);
274					return true;
275				} 
276				return false;
277			}
278		},
279		/**
280		 * =============================================================================================================================================
281		 * /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
282		 * 
283		 * UNIPLAYER
284		 * Audio engine controller
285		 * 
286		 * =============================================================================================================================================
287		 * */
288		uniPlayer: {
289			btnPlay: $("[data-qtmplayer-playbtn]"), //btnPlay: $("#qtmplayerPlay"),
290			canMoove: true,
291			pause: function(){
292				// qtmplayer-radiofeed.js
293				$.qtPlayerObj.playing = false;
294				if('object' === typeof($.qtmplayerRadioFeedObj)){ // check if the file is loaded
295					$.qtmplayerRadioFeedObj.fn.stopFeed();
296				}
297				$.qtPlayerObj.interface.justStop();
298				if( 'radio' === $.qtPlayerObj.songdata.type ){
299					// With this, after pausing from the bar, music can't restart
300					$.qtPlayerObj.songdata.file_hold = $.qtPlayerObj.songdata.file; // Store stream in a temorary object
301					$.qtPlayerObj.songdata.file = 'file_hold'; // replace stream with a string to block it
302					$.qtPlayerObj.interface.doSpinner(false);
303					if($.qtPlayerObj.isSoundApi === true){
304						$.qtWebApiPlayer.stop();
305					} else {
306						$.qtSMPO.smStop();
307					}
308
309				} else {
310					if($.qtPlayerObj.isSoundApi === true){
311						$.qtWebApiPlayer.pause();
312					} else {
313						$.qtSMPO.smPause();
314					}
315				}
316			},
317			webapiPlay: function(){
318				$.qtWebApiPlayer.play($.qtPlayerObj.songdata.file);
319			},
320			radioFeedCallback:function( feedImageUrl ){
321				var fallback = $.qtPlayerObj.imgCover.attr('data-fallback');
322				if(undefined !== feedImageUrl){
323					$.qtPlayerObj.imgCover.attr( 'src', feedImageUrl ).show();
324				} else {
325					if(fallback) {
326						$.qtPlayerObj.imgCover.attr('src', fallback).show();
327					} else {
328						$.qtPlayerObj.imgCover.hide();
329					}
330				}
331			},
332			play: function(){
333
334				if('function' == typeof($.qtmplayerRadioFeedObj.fn.updateMediaData)){
335					// console.log('Play update;');
336					$.qtmplayerRadioFeedObj.fn.updateMediaData();
337				}
338
339
340				if ($.qtPlayerObj.uniPlayer.btnPlay.find("i.material-icons").html() === 'pause') {
341					return;
342				}
343				if(qtInitialized && qtPlayIsAllowed){
344					$.qtPlayerObj.uniPlayer.btnPlay.find("i.material-icons").html("pause");
345					if($.qtPlayerObj.isSoundApi === true){
346						$.qtWebApiPlayer.play($.qtPlayerObj.songdata.file);
347					} else {
348						if( 'radio' === $.qtPlayerObj.songdata.type && 'file_hold' === $.qtPlayerObj.songdata.file ){
349							$.qtPlayerObj.songdata.file = $.qtPlayerObj.songdata.file_hold;
350							// FIX-2021-06-16_01 - set volume fix after change track
351							// fix issue when after pause the feed doesn't restart
352							$.qtmplayerRadioFeedObj.fn.pushFeed( $.qtPlayerObj.songdata );
353
354						}
355						
356						// console.log( $.qtPlayerObj.songdata );
357						if('undefined' !== typeof($.qtMplayerStats)){
358							$.qtMplayerStats.sendHit( $.qtPlayerObj.songdata );
359						}
360						console.log( $.qtPlayerObj.songdata );
361						$.qtSMPO.smPause();
362						$.qtSMPO.smPlay();
363					}
364					// FIX-2021-06-16_02 - set volume fix after change track
365					setTimeout(
366						function(){
367							if($.qtPlayerObj.masterVolume !== 100){
368								var mvol = $.qtPlayerObj.masterVolume;
369								$.qtPlayerObj.uniPlayer.setVolume( mvol );
370								$("[data-qtmplayer-vball]").css({'top': 100 - mvol});
371								$("[data-qtmplayer-vfill]").css({'height':mvol+'%'});
372							}
373						}, 300
374					);
375					$.qtPlayerObj.playing = true;
376				}
377			},
378			seek: function(p){ // p = percentage
379				if(isNaN(p)){
380					return;
381				}
382				p = parseFloat(p);
383				if(p > 100){
384					p = 100;
385				}
386				if($.qtPlayerObj.isSoundApi === true){
387					$.qtWebApiPlayer.seek(p);
388				} else {
389					$.qtSMPO.smSeek(p);
390				}
391			},
392			seekTime: function(t){
393				if(t === '00:00'){
394					t = '00:00:00';
395				}
396				if($.qtPlayerObj.isSoundApi === true){
397					$.qtWebApiPlayer.seekTime(t);
398				} else {
399					$.qtSMPO.smSeekTime(t);
400				}
401			},
402			setVolume: function(v){
403				// console.log(v);
404				$.qtPlayerObj.masterVolume = v;
405				if($.qtPlayerObj.isSoundApi === true){
406					$.qtWebApiPlayer.setvolume(v / 100);
407				} else {
408					$.qtSMPO.sm.setVolume(v);
409				}
410			}
411		},
412
413
414		/**
415		 * =============================================================================================================================================
416		 * /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
417		 * 
418		 * Player Object
419		 * This is the main interface controller
420		 * @function interface
421		 * 
422		 * =============================================================================================================================================
423		 * */
424		interface: {
425			window: $(window),
426			body: $("body"),
427			htmlAndbody: $('html,body'),
428			player: $('#qtmplayer'),
429			controls: $('#qtmplayer-controls'),
430			qtmplayer: $('#qtmplayer-playlistcontainer'),
431			playlist: $("#qtmplayer-playlist ul"),
432			grooveadv:  $('#qtMplayerTadv'), // music cue
433			buffer:  $('#qtMplayerBuffer'), // buffer
434			progWave:  $('#qtMplayerprogWave'), // buffer
435			advance: $("#qtMplayerTadv"),
436			btnPlay: $("[data-qtmplayer-playbtn]"), // $("#qtmplayerPlay"),
437			control: $("#qtmplayerTrackControl"),
438			minicue: $("#qtMplayerMiniCue"),
439			minicueT: $("#qtMplayerPlaylistTrackMinicue"),
440			trackAdvance: $("#qtmplayerTrackAdv"),
441			time: $("#qtmplayerTime"),
442			autoplay: $('#qtmplayer').data('autoplay'),
443			artwork: $('#qtmplayer').data('artwork'),
444			dragging: false,
445			vdragging: false,
446			debug: function(msg){
447				$("#qtmplayerDebug").prepend(msg+'<br>');
448			},
449
450			// Sync all buttons that target the same stream/file
451			syncButtonsByFile: function(file, state, scope){
452				var p = $.qtPlayerObj,
453					i = p.interface;
454
455				if(!file || !state){ return; }
456
457				// Normalize paused-radio placeholder
458				if(file === 'file_hold' && p.songdata && p.songdata.file_hold){
459					file = p.songdata.file_hold;
460				}
461
462				var $root = scope ? $(scope) : i.body;
463
464				// Fast path: attribute-equals selector (escape double quotes only)
465				var safe = (''+file).replace(/"/g,'\\"');
466				var $btns = $root.find('.qtmplayer-play-btn[data-qtmplayer-file="' + safe + '"]');
467				if(!$btns.length){ return; }
468
469				i.switchicon($btns.find('i.material-icons'), state);
470
471				// Keep trackitem played class consistent
472				$btns.each(function(){
473					var $it = $(this).closest('.qtmplayer-trackitem');
474					if(!$it.length){ return; }
475					if(state === 'pause'){ $it.addClass('qtmplayer-played'); }
476					else { $it.removeClass('qtmplayer-played'); }
477				});
478			},
479
480
481			
482			preloadTrack: function(qtmpid){
483				var p = $.qtPlayerObj,
484					i = p.interface;
485				p.interface.doSpinner(true);
486
487				// Since 3.9.4 preload custom track // still in alpha (incomplete function)
488				var firstTrack = "li:first-child";
489				// if( false !== qtmpid ){
490				// 	console.log(qtmpid) ;
491				// 	firstTrack = 'li[data-qtmplayer-qtmpid="'+qtmpid+'"]';
492				// }
493
494				i.playlist.find(firstTrack + " .qtmplayer-play-btn").each(function(i,c){
495					var trk = $(c),
496						q = 'qtmplayer-';
497
498					p.songdata = {};
499					$.each(trk.data() , function(i,c){
500						var newKey = i.replace("qtmplayer", "").toLowerCase();
501						p.songdata[newKey] = c;
502					});
503
504
505					$('.qtmplayer-played').removeClass('qtmplayer-played');
506					trk.closest(".qtmplayer-trackitem").addClass("qtmplayer-played");
507					var c = $.qtPlayerObj.interface.controls,
508						ot = false;
509					if(qtShowPlayer){
510						p.interface.showhide();
511					}
512
513
514					if(p.interface.deployTrack()){
515						if(p.interface.autoplay){
516							setTimeout(
517								p.uniPlayer.play, 
518								2200
519							);
520						}
521					}
522				});
523			},
524
525			isMobile: function(){
526				return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) || $(window).width() < 1170 ;
527			},
528
529			deployTrack: function(autoplay){
530				var o = $.qtPlayerObj,
531					i = o.interface,
532					hd = i.controls,
533					dt = o.songdata,
534					mp = i.qtmplayer,
535					durtime = $("#qtmplayerDuration"),
536					cartlink,
537					cartbt = hd.find('.qtmplayer__cart'),
538					cur_url = window.location.href,
539					wc_params = '',
540					wc_classes = '',
541					params, // for URL
542					params_str; // for URL
543				if(dt.file == ''){
544					return;
545				}
546				if(true === qtMplayerisMobile && $.qtPlayerObj.songdata.file_mobile && screen.width <= 1119 ){
547					$.qtPlayerObj.songdata.file = $.qtPlayerObj.songdata.file_mobile;
548				}
549				i.doSpinner(true);
550				if(false == qtInitialized){
551					setTimeout(
552						i.doSpinner, 
553						1000
554					);
555				}
556				$.qtPlayerObj.interface.waveformAdvance = false;
557
558				if( 'radio' === dt.type ){
559					i.minicue.hide();
560					i.buffer.hide();
561					i.trackAdvance.hide();
562					durtime.hide();
563					i.control.addClass('qtmplayer-is-radio');
564					$('#qtmplayerTrackControl canvas').remove();
565					if( $.qtmplayerRadioFeedObj ){
566						$.qtPlayerObj.songdata.callBack = false;
567						if( $.qtPlayerObj.interface.artwork ){
568							$.qtPlayerObj.imgCover = $.qtPlayerObj.interface.controls.find('.qtmplayer__cover img');
569							var original = $.qtPlayerObj.imgCover.attr('src');
570							if( original ){
571								$.qtPlayerObj.imgCover.attr('data-fallback', original);
572							}
573							$.qtPlayerObj.interface.controls.find('.qtmplayer__cover img').attr('data-fallback', original);
574							$.qtPlayerObj.songdata.callBack = $.qtPlayerObj.uniPlayer.radioFeedCallback;
575						}
576						$.qtmplayerRadioFeedObj.fn.pushFeed( $.qtPlayerObj.songdata );
577					}
578				} else {
579					i.control.removeClass('qtmplayer-is-radio');
580					if( $.qtmplayerRadioFeedObj ){
581						$.qtmplayerRadioFeedObj.fn.stopFeed();
582					}
583					i.minicue.show();
584					i.buffer.show();
585					i.trackAdvance.show();
586					durtime.show();
587					if( false === i.isMobile() ){
588						var comp = new RegExp(location.host);
589						try {
590							if(comp.test( dt.file ) && 'function' === typeof(qtDrawAudio)){
591								qtDrawAudio(dt.file);
592								$.qtPlayerObj.interface.waveformAdvance = $('#qtwaveformClone');
593							} else {
594								$('#qtmplayerTrackControl canvas').remove();
595							}
596						} catch(e){
597							console.log(e);
598						}
599					}
600				}
601				if(dt.buylink == '' || dt.buylink == 'undefined' || typeof(dt.buylink) === 'undefined'){
602					cartbt.css({'opacity':0, 'pointer-events': 'none'});
603				} else {
604					cartbt.css({'opacity':1, 'pointer-events': 'initial'});
605				}
606				$('.qtmplayer__actions .added_to_cart.wc-forward').remove();
607
608				if( dt.link !== ''){
609					hd.find('.qtmplayer__title').html('<a href="'+dt.link+'"><strong>'+dt.title+'</strong></a> ');
610				} else {
611					hd.find('.qtmplayer__title').html(dt.title);
612				}
613				hd.find('.qtmplayer__artist').text(dt.artist);
614				if(typeof( dt.album ) !== 'undefined' && dt.album !== ''){
615					hd.find('.qtmplayer__title').append('['+dt.album+']');
616					$.qtMplayerGlobalSongData.album = dt.album;
617				}
618				hd.find('.qtmplayer__cover').attr("href", dt.link);
619				$.qtMplayerGlobalSongData.title = dt.title;
620				$.qtMplayerGlobalSongData.artist = dt.artist;
621				if( dt.cover ){
622					$.qtMplayerGlobalSongData.thumbnail = dt.cover;
623				} else {
624					$.qtMplayerGlobalSongData.thumbnail = false;
625				}
626
627				// WooCommerce support added
628				cartbt.addClass('qtmplayer__disabled');
629				cartbt.off('click');
630				if (typeof dt.buylink === 'string' && dt.buylink.trim() !== '') {
631					cartbt.removeClass('qtmplayer__disabled');
632					// WooCommerce
633					cartlink = dt.buylink;
634					if('undefined' !== typeof( dt.buylink )) { 
635						dt.buylink = dt.buylink.toString(); 
636						if (dt.buylink.match(/^-?\d+$/)) { // is a numeric ID
637							params = { "add-to-cart":dt.buylink };
638							params_str = jQuery.param( params );
639							if(cur_url.indexOf('?') != -1) {
640								cartlink = cur_url+"&"+params_str;
641							}else{
642								cartlink = cur_url+"?"+params_str;
643							}
644							// Extra cart classes and attrs
645							wc_classes = ' product_type_simple add_to_cart_button ajax_add_to_cart ';
646							cartbt.attr("href", cartlink).attr('data-quantity','1').attr('data-product_id', dt.buylink).addClass(wc_classes).show();
647						} else {
648							cartbt.attr("href", dt.buylink).removeClass('product_type_simple').removeClass('add_to_cart_button').removeClass('ajax_add_to_cart').show();
649						}
650
651						// PR.6.3.0
652						// If link is another domain, add target _blank, or remove it
653						try {
654					        // Use window.location.origin as base so relative URLs are valid too
655					        var linkUrl = new URL(cartlink, window.location.origin);
656					        if (linkUrl.host === window.location.host && ! $('body').hasClass('qtmplayer--page-popup')) {
657					            cartbt.attr('target', '');
658					        } else {
659					            cartbt.attr('target', '_blank');
660					        }
661					    } catch (e) {
662					        // If URL is invalid, just avoid breaking the player
663					        cartbt.attr('target', '');
664					    }
665					}
666					if(dt.icon == 'download') {
667						dt.icon = 'file_download';
668					} 
669					cartbt.show();
670				} else {
671					cartbt.hide();
672					cartbt.removeClass('product_type_simple').removeClass('add_to_cart_button').removeClass('ajax_add_to_cart');
673				}
674
675				cartbt.find('i').html(dt.icon);
676				i.advance.width(0);
677				if( false !== i.waveformAdvance && "undefined" !== typeof(i.waveformAdvance) ){
678					i.waveformAdvance.css({
679						"clip-path": "polygon(0 0, 0% 0, 0% 100%, 0% 100%)"
680					});
681				}
682				i.buffer.width(0);
683				if(dt.cover !== '' && dt.cover !== undefined){
684					mp.find('.qtmplayer__album img').attr("src", dt.cover).show();
685					hd.find('.qtmplayer__cover img').attr("src", dt.cover).show();
686					hd.find('.qtmplayer__bgimg').css({"background-image": 'url('+dt.cover+')' });
687				} else {
688					mp.find('.qtmplayer__album img').hide();
689					hd.find('.qtmplayer__cover img').hide();
690					hd.find('.qtmplayer__bgimg').css({"background-image": 'none' });
691				}
692				mp.find('.qtmplayer-albumlink').attr("href",dt.link);
693				if(qtShowPlayer){
694					i.showhide();
695				}
696				i.btnPlayClick();
697				i.playTrack();
698				if(autoplay){
699					o.uniPlayer.play();
700				}
701				return true;
702			},
703			btnPlaySetup: function(dt){
704				var state = 'pause', 
705					o = $.qtPlayerObj,
706					i = o.interface,
707					b = i.btnPlay,
708					p = o.uniPlayer;
709
710				b.off("click");
711				b.on("click", function(e){
712					e.preventDefault();
713					state = b.find("i").html();
714					if(state === 'pause'){
715						$(".qtmplayer-played .qtmplayer-play-btn").click();
716					} else {
717						$('#qtmplayer-playlist li:first-child').find(".qtmplayer-play-btn").click();
718					}
719				});
720			},
721			/**
722			 * Questa funzione è probabilmente inutile adesso
723			 */
724			btnPlayClick: function(){
725
726				var state = 'pause', 
727					o = $.qtPlayerObj,
728					i = o.interface,
729					b = i.btnPlay,
730					p = o.uniPlayer;
731
732				var currentFile = (p.songdata && p.songdata.file) ? p.songdata.file : '';
733				if(currentFile === 'file_hold' && p.songdata && p.songdata.file_hold){
734					currentFile = p.songdata.file_hold;
735				}
736				b.off("click");
737				b.on("click", function(e){
738					e.preventDefault();
739					// state = b.find("i").html();
740					state = b.find("i.material-icons").html();
741					if(state === 'pause'){
742						p.pause();
743					} else {
744						if(false == qtInitialized){
745							i.doSpinner(true);
746							i.initializeAudio();
747							if( true === $.qtPlayerObj.ProRadioUserManagerIntegration.shouldBlock() ){
748								i.doSpinner(false);
749								return;
750							}
751							qtPlayIsAllowed = true;
752							setTimeout(
753								p.play, 
754								200
755							);
756						} else {
757							if( true === $.qtPlayerObj.ProRadioUserManagerIntegration.shouldBlock() ){
758								i.doSpinner(false);
759								return;
760							}
761							qtPlayIsAllowed = true;
762							p.play();
763						}
764					}
765					return true;
766				});
767			},
768			getCurrentFile: function(){
769				var p = $.qtPlayerObj, f = (p.songdata && p.songdata.file) ? p.songdata.file : '';
770				if(f === 'file_hold' && p.songdata && p.songdata.file_hold){ f = p.songdata.file_hold; }
771				return f || '';
772			},
773			playTrack: function(){
774				var p = $.qtPlayerObj,
775					i = p.interface,
776					u = p.uniPlayer;
777				if( i.resumeRadio ){
778					clearTimeout(i.resumeRadio);
779				}
780
781				// Sync all per-track buttons when toggling playback from the main bar button
782				i.body.off('click.proradioSyncBar', '#qtmplayerPlay').on('click.proradioSyncBar', '#qtmplayerPlay', function(){
783					setTimeout(function(){
784						console.log('Sync play');
785						var f = i.getCurrentFile ? i.getCurrentFile() : ((p.songdata && p.songdata.file) ? p.songdata.file : '');
786						if(!f){ return; }
787						i.syncButtonsByFile(f, (p.playing === true ? 'pause' : 'play'));
788					}, 350);
789				});
790
791
792				i.body.off("click", ".qtmplayer-play-btn");
793				i.body.on("click", ".qtmplayer-play-btn", function(e){
794					e.preventDefault();		
795					qtPlayIsAllowed = true;
796					i.doSpinner(true);
797					var tr = $(this),
798						item = tr.closest(".qtmplayer-trackitem"),
799						isDonut = item.hasClass("qtmplayer-donut"),
800						icon = tr.find("i"),
801						clickedsong = tr.attr('data-qtmplayer-file'),
802						playedclass = "qtmplayer-played",
803						playedtrack = i.body.find("."+playedclass),
804						iplay =  "dripicons-media-play",
805						ipause = "dripicons-media-pause";
806					if(item.hasClass(playedclass) && tr.find('i').html() === 'pause'){
807						// old
808						// i.switchicon(icon, 'play');
809						// item.removeClass(playedclass);
810						// i.switchicon(playedtrack.find('.qtmplayer-play-btn i.material-icons'), 'play');
811					
812						i.syncButtonsByFile(clickedsong, 'play'); // new
813					
814						u.pause();
815						e.stopPropagation();
816						return;
817					} else {
818						// Check if is the same track. If yes pause, if not stop the first play the second
819						// update 2019 05 22
820
821						// if(clickedsong === p.songdata.file) { // old
822						if(clickedsong === i.getCurrentFile()){
823							if(playedtrack.length > 0){
824
825								if(p.uniPlayer.btnPlay.find("i.material-icons").html() === 'pause'){
826									
827									// playedtrack.removeClass(playedclass); // old
828									// i.switchicon(playedtrack.find('.qtmplayer-play-btn i.material-icons'), 'play'); // old
829									i.syncButtonsByFile(clickedsong, 'play'); // new
830									u.pause();
831									e.stopPropagation();
832									return;
833								} else {
834									u.pause();
835									// i.switchicon(playedtrack.find('.qtmplayer-play-btn i.material-icons'), 'play'); // old
836									// playedtrack.removeClass(playedclass); // old
837									i.syncButtonsByFile(clickedsong, 'play'); // new
838								}
839
840							}
841						} else {
842							// i.switchicon(playedtrack.find('.qtmplayer-play-btn i.material-icons'), 'play'); // old
843							// playedtrack.removeClass(playedclass); // old
844
845							i.syncButtonsByFile(i.getCurrentFile(), 'play'); // new
846
847							i.justStop();
848							u.pause();
849						}
850					
851
852						if( undefined === tr.data("qtmplayer-type") ){
853							tr.data("qtmplayer-type", 'track');
854						}
855
856
857						// 2019 12 29 new faster remapping of data
858						p.songdata = {};
859						
860						$.each(tr.data() , function(i,c){
861							var newKey = i.replace("qtmplayer", "").toLowerCase();
862							p.songdata[newKey] = c;
863						});
864						i.deployTrack();
865						if( true === $.qtPlayerObj.ProRadioUserManagerIntegration.shouldBlock() ){
866							return;
867						}
868						i.seekBtn();
869						// i.switchicon(icon, 'pause'); // old
870						// item.addClass(playedclass); // old
871						i.syncButtonsByFile(clickedsong, 'pause');
872						if($("#qtdonut").length > 0){
873							$("#qtdonut").removeAttr("id");
874						}
875
876
877						if(isDonut){
878							item.attr("id", "qtdonut");
879							$.qtMplayerPlaylistCue.destroy();
880
881							if( 'track' === p.songdata.type){ 
882								$.qtRaphaelCircle.init();
883							}
884						} else {
885							if( 'track' === p.songdata.type){
886								$.qtMplayerPlaylistCue.init();
887							}
888						}
889						// safe initialization
890						if(false == qtInitialized){
891							i.initializeAudio();
892							i.doSpinner(true);
893							setTimeout(
894								u.play, 
895								2200
896							);
897						} else {
898							u.play();
899						}
900					}
901					e.stopPropagation();
902				});
903			},
904			
905			switchicon: function(i, state) {
906				if(state === 'play'){
907					i.html('play_arrow');
908				} else if (state === 'pause') {
909					i.html('pause');
910				}
911			},
912			progressUpdate: function(perc){ // buffered
913				var i = $.qtPlayerObj.interface,
914					p = perc * 100;
915				i.buffer.css({width: p+'%'});
916				i.minicue.addClass('actvd');
917				
918			},
919			timeupdate: function(perc, time){
920				var i = $.qtPlayerObj.interface,
921					p = perc * 100;
922				i.advance.css({
923					width: (p)+'%',
924					'transition':'width 0.3s',
925				});
926				if(false !== i.waveformAdvance && "undefined" !== typeof( i.waveformAdvance ) ){
927					i.waveformAdvance.css({
928						'transition':'clip-path 0.3s',
929						"clip-path": "polygon(0 0, "+(p)+"% 0, "+(p)+"% 100%, 0% 100%)"
930					});
931				}
932				i.time.html(time);
933				if(perc > 0.001){
934					i.doSpinner();
935					setTimeout(
936						i.doSpinner, 
937						300
938					);
939				}
940				if($('#qtMplayerprogWave')){
941					$('#qtMplayerprogWave').css({width: (p)+'%'});
942				}
943				if(i.dragging === false) {
944					i.minicue.css({
945						'transition':'left 0.3s',
946						"left": (p)+'%'
947					});
948				}
949			},
950			seekBtn: function(){
951				var o = $.qtPlayerObj,
952					i = o.interface,
953					c = i.control,
954					m = i.minicue,
955					ol = c.offset().left,
956					w = c.outerWidth(),
957					t = (o.songdata.type == 'radio') ? 'radio' : 'track',
958					l,
959					active = false,
960					currentX, currentY, initialX, initialY,
961					xOffset = 0;
962					yOffset = 0;
963					dragItem = m;
964				c.off("touchstart").off("touchend").off('touchmove').off('mousedown').off('mouseup').off('mouseleave').off('mousemove');
965				if(t === 'radio') {
966					m.css({'left': 0});
967				} else {
968					c.on("touchstart", dragStart);
969					c.on("touchend", dragEnd);
970					c.on("touchmove", drag);
971					c.on("mousedown", dragStart);
972					c.on("mouseup", dragEnd);
973					c.on("mouseleave", dragEnd);
974					c.on("mousemove", drag);
975					function dragStart(e) {
976						i.dragging = true; 
977						active = true;
978						m.addClass('qtmplayer-touch');
979					}
980					function dragEnd(e) {
981						i.dragging = false;
982						active = false;
983						m.removeClass('qtmplayer-touch');
984					}
985					function drag(e) {
986						ol = c.offset().left;
987						w = c.outerWidth();
988						if (e.type === "touchmove") {
989							l = e.originalEvent.touches[0].pageX - ol;
990						} else {
991							l = e.clientX - ol;
992						}
993						if(active){
994							relocate(l);
995						}
996					}
997					function relocate(l){
998						var p = l / w;
999						if( p < 0 || p > 99.9 ){
1000							return;
1001						}
1002						m.css({'left': l});
1003						o.uniPlayer.seek(p * 100);
1004					}
1005				}
1006			},	
1007			appendAlbum: function(){
1008				var p = $.qtPlayerObj,
1009					i = p.interface,
1010					c = i.controls,
1011					cartlink,
1012					cur_url = window.location.href,
1013					wc_params = '',
1014					wc_classes = '',
1015					params, // for URL
1016					params_str, // for URL
1017					ot = false, // timeout
1018					notif = $('[data-qtmplayerNotif]');
1019					i.body.on("click", "[data-qtmplayer-addrelease]", function(e){
1020					e.preventDefault();
1021					var that = $(this),
1022						url = that.data("qtmplayer-addrelease"),
1023						playnow = that.data("playnow"),
1024						latestAdded = 'qtmplayer-latestadded';
1025					if(that.data("qtmplayer-addrelease") == '0'  || that.hasClass("disabled")){
1026						return;
1027					}
1028					$.getJSON(url, function( data ) {
1029						var newitem,
1030							special_action,
1031							tn = data.length;
1032						$.each( data, function( key, val ) {
1033							// WooCommerce
1034							cartlink = val.buylink;
1035							if (val.buylink.match(/^-?\d+$/)) { // is a numeric ID
1036								params = { "add-to-cart":val.buylink };
1037								params_str = jQuery.param( params );
1038								if( cur_url) {
1039									if( cur_url.indexOf("?")>= 0 ) {
1040										cartlink = cur_url+"&"+params_str;
1041									}else{
1042										cartlink = cur_url+"?"+params_str;
1043									}
1044								}
1045								// Extra cart classes and attrs
1046								wc_classes = ' product_type_simple add_to_cart_button ajax_add_to_cart ';
1047								wc_params = ' data-quantity="1" data-product_id="'+ val.buylink +'" ';
1048							}
1049							special_action = '<i class="material-icons">'+val.icon+'</i>';
1050							if( typeof(val.price) !== 'undefined'){
1051								if (val.price !== ''){
1052									special_action = '<span class="qtmplayer-price qtmplayer-btn qtmplayer-btn-xs qtmplayer-btn-primary">'+val.price+'</span>';
1053								}
1054							}
1055							newitem = '<li class="qtmplayer-trackitem dynamic">';
1056							if(val.cover !== ''){
1057								newitem += '<img src="'+val.cover+'">';
1058							}
1059							newitem += '<span class="qtmplayer-play qtmplayer-link-sec qtmplayer-play-btn '+latestAdded+'" data-qtmplayer-type="track" data-qtmplayer-cover="'+val.cover+'" data-qtmplayer-price="'+val.price+'" data-qtmplayer-file="'+val.file+'" data-qtmplayer-title="'+val.title+'"'+'data-qtmplayer-artist="'+val.artist+'"'+'data-qtmplayer-album="'+val.album+'" data-qtmplayer-link="'+val.link+'" data-qtmplayer-buylink="'+val.buylink+'" data-qtmplayer-icon="'+val.icon+'"><i class="material-icons">play_arrow</i></span><p>	<span class="qtmplayer-tit">'+val.title+'</span><br>	<span class="qtmplayer-art">'+val.artist+'</span></p><a href="'+cartlink+'" '+wc_params+' class="qtmplayer-cart '+ wc_classes +'" target="_blank">'+special_action+'</a></li>';
1060							i.playlist.append(newitem);
1061							if(0 === key && playnow){
1062								$.qtPlayerObj.interface.justStop();
1063								$.qtPlayerObj.uniPlayer.pause();
1064								p.songdata = val;
1065								$("."+latestAdded).click();
1066							}
1067							latestAdded = '';
1068						});
1069						i.showhide();
1070						if(that.data("clickonce") === 1){
1071							that.hide();
1072							
1073							$(that.data("notificate")).addClass("active");
1074
1075						} else {
1076							that.addClass('disabled');
1077							
1078						}
1079						notif.addClass("wait").delay(1500).promise().done(function(){
1080							notif.removeClass("wait");
1081						});
1082						// Disable the functionality
1083						that.attr("data-qtmplayer-addrelease", '0');
1084					});
1085				});
1086			},
1087			showhide: function(){
1088				var c = $.qtPlayerObj.interface.controls;
1089				c.addClass('open');
1090				ot = setTimeout(function() {
1091					c.removeClass('open');
1092					clearTimeout(ot);
1093				}, 4000);
1094			},
1095			prevNext: function(){
1096				$.qtPlayerObj.interface.controls.on("click",".qtmplayer__prev, .qtmplayer__next", function(e){
1097					e.preventDefault();
1098					var t = $(this), b;
1099					$.qtPlayerObj.interface.doSpinner(true);
1100					if(t.data("control") === "prev"){
1101						b = $(".qtmplayer-played").prev();
1102					} else {
1103						b = $(".qtmplayer-played").next();
1104					}
1105					b.find(".qtmplayer-play-btn").click();
1106				});
1107			},
1108			doSpinner: function(state, content){
1109				var notif = $('[data-qtmplayerNotif]');
1110				if( content ){
1111					notif.html(content);
1112				} else {
1113					notif.html('');
1114				}
1115				if( true === state ){ 
1116					notif.addClass("active qtmplayer-spinner"); 
1117				} else {
1118					notif.removeClass("active").removeClass("qtmplayer-spinner"); 
1119				}
1120			},
1121			resumeRadio: false,
1122			_wasRadioPlayingOnOffline: false,
1123			resumeAttempts: 0,
1124			resumeMaxAttempts: 5,
1125			next: function(){
1126				var i = $.qtPlayerObj.interface,
1127					p  = $.qtPlayerObj,
1128					current = $(".qtmplayer-played"),
1129					nt = $(".qtmplayer-played").next();
1130
1131				// 20251209 - Radio resume if connection lost
1132				 // NEW: for radio streams, retry same channel instead of going to next track
1133			    if ( i.player.data('qtmplayer-reconnect') && 'radio' === $.qtPlayerObj.songdata.type  ) {
1134			    	console.log ( 'resume attempts: ' + i.resumeAttempts );
1135			    	console.log( i.player.data('qtmplayer-bufferinglabel') );
1136			        if ( current.length ) {
1137			        	if( i.resumeAttempts < i.resumeMaxAttempts ){
1138				        	i.justStop();
1139				            i.doSpinner(true,  "⌀"); // preload mode
1140				            setTimeout(function () {
1141					            i.doSpinner(true, "⌀");
1142					        }, 350);
1143				            $('.qtmplayer__title').html(  i.player.data('qtmplayer-bufferinglabel') );
1144				            $('.qtmplayer__artist').html( '' );
1145				            if( i.resumeRadio ){
1146				            	clearTimeout(i.resumeRadio);
1147				            }
1148				            i.resumeRadio = setTimeout(function () {
1149				            	console.log('Restart Radio');
1150				                current.find(".qtmplayer-play-btn").click();
1151				                i.resumeAttempts += 1;
1152				            }, 7000);
1153				        } else {
1154				        	i.resumeAttempts = 0;
1155				        	i.justStop();
1156				        	i.doSpinner(false);
1157							$('.qtmplayer__title').html(  i.player.data('qtmplayer-bufferingfail') );
1158							$('.qtmplayer__artist').html( '' );
1159							return;
1160				        }
1161			        } else {
1162			        	console.log( 'Current length FALSE' );
1163			        }
1164			        return;
1165			    }
1166				// Classic output	
1167				var playedParent = $(".qtmplayer-played").closest(".proradio-chart-track");
1168				if(playedParent.length){
1169					var nextChartTrack = playedParent.next(".proradio-chart-track").find('.collapsible-header');
1170					if(nextChartTrack.length){
1171						nextChartTrack.click();
1172						nt = playedParent.next(".proradio-chart-track").find(".qtmplayer-trackitem");
1173					}
1174				}
1175				if(nt !== undefined){
1176					if(nt.length > 0){
1177						nt.find(".qtmplayer-play-btn").click();
1178					} else {
1179						i.justStop();
1180					}
1181				} else {
1182					i.justStop();
1183				}
1184			},			
1185			justStop: function(){
1186				$.qtPlayerObj.interface.switchicon($(".qtmplayer-played .qtmplayer-play-btn i.material-icons"), 'play');
1187				$.qtPlayerObj.uniPlayer.btnPlay.find("i.material-icons").html("play_arrow");
1188			},
1189			skipCue: function(){
1190				var o = $.qtPlayerObj,
1191					i = o.interface
1192					b = i.btnPlay,
1193					p = o.uniPlayer;
1194				i.body.on('click', '[data-qtplayercue]',function(){
1195					var t = $(this),
1196						k = t.data('qttrackurl'),
1197						c = t.data('qtplayercue');
1198
1199					if("undefined" === typeof( o.songdata.type )) {
1200						return;
1201					}
1202					if(o.songdata.file === k) {
1203						if( $.qtPlayerObj.playing ) {
1204							o.uniPlayer.seekTime(c);
1205						} else {
1206							if(false == qtInitialized){
1207								i.doSpinner(true);
1208								i.initializeAudio();
1209								qtPlayIsAllowed = true;
1210								setTimeout(
1211									p.play, 
1212									200
1213								);
1214							} else {
1215								qtPlayIsAllowed = true;
1216								p.play();
1217							}
1218						}
1219					} else {
1220						console.log('Not this track');
1221					}
1222				});
1223			},
1224			volBtn: function(){
1225				var o = $.qtPlayerObj,
1226					i = o.interface,
1227					c = $("[data-qtmplayer-vcontrol]");
1228				if( 0 === c.length ){ return; }
1229				var	ol = c.offset().top,
1230					w = c.outerHeight(),
1231					ct = $("[data-qtmplayer-vtrack]"), // cue
1232					f = $("[data-qtmplayer-vfill]"), // fill
1233					m = $("[data-qtmplayer-vball]"), // fill
1234					off = c.offset().top,
1235					h =  c.height(),
1236					vi = $('[data-qtmplayer-vicon]'),
1237					t, // top
1238					p = 100, // percentage
1239					tp = 100, // volume before muting to unmute
1240					d; // delta
1241				c.on("touchstart", vdragStart);
1242				c.on("touchend", vdragEnd);
1243				c.on("touchmove", vdrag);
1244				c.on("mousedown", vdragStart);
1245				c.on("mouseup", vdragEnd);
1246				c.on("mouseleave", vdragEnd);
1247				c.on("mousemove", vdrag);
1248				var vactive = false;
1249				var vcurrentX;
1250				var vcurrentY;
1251				var vinitialX;
1252				var vinitialY;
1253				var vxOffset = 0;
1254				var vyOffset = 0;
1255				var vdragItem = m;
1256				function vdragStart(e) {
1257					i.vdragging = true; 
1258					vactive = true;
1259					m.addClass('qtmplayer-touch');
1260				}
1261				function vdragEnd(e) {
1262					i.vdragging = false;
1263					vactive = false;
1264					m.removeClass('qtmplayer-touch');
1265				}
1266				function vdrag(e) {
1267					off = c.offset().top - $(window).scrollTop();
1268					if(vactive){
1269						ol = c.offset().top;
1270						w = c.outerHeight();
1271						if (e.type === "touchmove") {
1272							l = off - e.originalEvent.touches[0].pageY;
1273						} else {
1274							l = off - e.clientY;
1275						}
1276						vrelocate(100 - Math.abs(l) );
1277					}
1278
1279
1280				}
1281				function vrelocate(l){
1282					if(l < 0 ){
1283						l = 0;
1284					}
1285					if(l > 95 ){
1286						l = 100;
1287					}
1288					m.css({'top': 100 -l});
1289					p = l;
1290					f.css({'height':p+'%'});
1291					$.qtPlayerObj.uniPlayer.setVolume(p);
1292
1293					$('[data-proradio-volumeslider]').val(p)
1294
1295					var vi = $('[data-qtmplayer-vicon]');
1296					if(p > 1){
1297						if(p < 50){
1298							vi.html('volume_down');
1299						} else {
1300							vi.html('volume_up');
1301						}
1302					} else {
1303						vi.html('volume_off');
1304					}
1305				}
1306				$('body').on('click','[data-qtmplayer-vicon]', function(e){
1307					e.preventDefault();
1308					
1309					if(p > 1){
1310						tp = p;
1311						vrelocate(0);
1312					} else {
1313						vrelocate(tp);
1314					}
1315					e.stopPropagation();
1316				});
1317				// Boot setup start volume
1318				var mvol = $.qtPlayerObj.masterVolume;
1319				if(mvol !== 100){					
1320					$.qtPlayerObj.uniPlayer.setVolume( mvol );
1321					vrelocate(mvol);
1322				}
1323			},
1324			setDuration: function(text){
1325				if(text === 'NaN:NaN' || text === '00:00'){
1326					$("#qtmplayerDuration").html();
1327					return;
1328				}
1329				$("#qtmplayerDuration").html(text);
1330			},
1331			bufferStart: function(){
1332				
1333				$("#qtmplayerDuration").html('...');
1334				$("#qtmplayer-buffer").show();
1335				$('#qtMplayerMiniCue,  #qtMplayerTadv').animate({'opacity':1}, 'fast' ).css({'pointer-events': 'none'});
1336			},
1337			bufferEnd: function(){
1338				$("#qtmplayer-buffer").hide();
1339				var returnAlive = setTimeout(function(){
1340					$('#qtMplayerMiniCue, #qtMplayerTadv').css({'pointer-events': 'all'});
1341				}, 300);
1342				
1343			},
1344			screenResize: function(){
1345				var resizeTimer,
1346					o = $.qtPlayerObj,
1347					i = o.interface,
1348					w = i.window,
1349					ww = w.width(),
1350					wh = w.height();
1351				w.on('resize', function() {
1352					clearTimeout(resizeTimer);
1353					resizeTimer = setTimeout(function() {
1354						if (w.width() !== ww || w.height() !== wh) {
1355							i.seekBtn();
1356							$.qtMplayerPlaylistCue.init();
1357						}
1358						
1359					}, 100);
1360				});
1361			},
1362			initializeAudio: function() {
1363				var o = $.qtPlayerObj,
1364				i = o.interface;
1365				i.doSpinner(true);
1366				if(qtAnalyzer){
1367					var hasAudioContext = false;
1368					try {
1369						hasAudioContext = window.AudioContext || window.webkitAudioContext;
1370					} catch(e) {
1371						if($.qtSMPO.init()){
1372							qtInitialized = true;
1373							return true;
1374						};
1375					}
1376					if(hasAudioContext !== false){
1377						o.isSoundApi = true;
1378						if($.qtWebApiPlayer.init()){
1379							qtInitialized = true;
1380							return true;
1381						}
1382					}
1383				} else {
1384					if($.qtSMPO.init()){
1385						qtInitialized = true;
1386						return true;
1387					};
1388				}
1389			},
1390			resumeAudioOld: function(){
1391				var o = $.qtPlayerObj,
1392					i = o.interface;
1393				i.initializeAudio(); // Appply new fixes
1394				qtPlayIsAllowed = true;
1395				if(i.autoplay){
1396					setTimeout(
1397						o.uniPlayer.play, 
1398						2200
1399					);
1400					
1401				}
1402				document.removeEventListener("click", i.resumeAudio);
1403			},
1404			resumeAudio: function(){
1405				// this seems to break the player by creating sometimes a parallel audio instance
1406				// return;
1407
1408				var o = $.qtPlayerObj,
1409					i = o.interface;
1410				i.log("resumeAudio A");
1411				i.initializeAudio(); // Appply new fixes
1412				qtPlayIsAllowed = true;
1413				if(i.autoplay){
1414					i.log("resumeAudio B");
1415					setTimeout(
1416						function(){ 
1417							i.btnPlay.click(); 
1418							i.log("resumeAudio A1");
1419							setTimeout(
1420								function(){ 
1421									i.log("resumeAudio AB");
1422									if(false === i.isMobile()){
1423										i.log("resumeAudio AB 0");
1424									} else {
1425										i.btnPlay.click();
1426										i.log("resumeAudio AB 1");
1427									}
1428								},
1429								10
1430							);
1431						},
1432						2200
1433					);					
1434				}
1435				i.log("resumeAudio C");
1436				document.removeEventListener("click", i.resumeAudio);
1437			
1438
1439			},
1440			triucco: function(){
1441				var b = $('body'),
1442					i = $.qtPlayerObj.interface,
1443					t; 
1444				$('#qtmusicplayer').addClass('qt-mplayer-mobile');
1445				i.initializeAudio(); 
1446				i.resumeAudio();
1447				b.addClass("qt-mplayer-enabled");
1448				i.log('mobile player enabled');
1449				setTimeout(
1450					function(){
1451						i.doSpinner();
1452					}, 
1453					1200
1454				);
1455				
1456			},
1457			log: function(m){
1458				var c = $("#qtmPlayerDebugger");
1459				if(c.length > 0){
1460					c.append(m+'<br>');
1461				}
1462			},
1463
1464		},
1465		initPlayer: function(){
1466			if(qtPlayDebug){
1467				$('#qtmplayer-playlist').append('<div class="qtmplayer__debugger" id="qtmPlayerDebugger"><h5>Player Debug</h5></div>');
1468			}
1469			if($('.qtmplayer__controllayer_noky').length > 0){
1470				$('.qtmplayer__controllayer_noky').animate({opacity: 0.6},2000);
1471				return;
1472			}
1473			var o = $.qtPlayerObj,
1474				i = o.interface,
1475				c = i.controls,
1476				b = i.body,
1477				ot; 
1478			o.songdata = {};
1479			b.addClass("qtmplayer-enabled");
1480			$(document).on("click", "[data-playlistopen]", function(){
1481				b.toggleClass("qtmplayer-openplaylist");
1482			});
1483			b.on("click", "[data-playeropen]", function(){
1484				b.toggleClass("qtmplayer-open");
1485			});
1486			c.find('.qtmplayer__cover').html('<img src="">');
1487			i.qtmplayer.find('.qtmplayer__album').prepend('<img src="">');
1488
1489			if( qtMplayerisMobile ){
1490				i.triucco();
1491
1492			} 	else {
1493				b.addClass("qt-mplayer-enabled");
1494			}
1495
1496			i.preloadTrack(false);
1497			i.prevNext();
1498			i.appendAlbum();
1499			i.seekBtn();
1500			i.volBtn();
1501			i.bufferEnd();
1502			i.skipCue();
1503			i.screenResize();
1504			c.mouseenter(function(){
1505				c.addClass('open');
1506				i.seekBtn();
1507				clearTimeout(ot);
1508			}).mouseleave(function(){				
1509				ot = setTimeout(function() {
1510					c.removeClass('open');
1511				}, c.data('hidetimeout'));
1512			});
1513
1514			$('body').one('click', function(e) {
1515
1516				if(  $(window).width() >= 1280 ){
1517					
1518					
1519					// console.log('Autoplay test2');
1520					var target = $(e.target).closest('a');
1521					if(target){
1522						// not('.qtmplayer__play, .qtmplayer-play, .proradio-btn--playmenu')
1523						if(target.hasClass('qtmplayer__play') || target.hasClass('qtmplayer-play') || target.hasClass('proradio-btn--playmenu')){
1524							return;
1525						}
1526					}
1527					var closest = $(e.target).closest('a');
1528					if(closest){
1529						if(closest.hasClass('qtmplayer__play') || closest.hasClass('qtmplayer-play') || closest.hasClass('proradio-btn--playmenu')){
1530						 		return;
1531						}
1532					}
1533					// console.log( $(e.target).closest('a').attr('class') );
1534					if( $.qtPlayerObj.hasDoneAutoplay === false && $.qtPlayerObj.interface.autoplay ){
1535					    setTimeout(function(){
1536					    	console.log('%c Pro.Radio player - do Autoplay! ', 'background: #030303; color: #bada55');
1537					    	$('#qtmplayerPlay').click();
1538					    	$.qtPlayerObj.hasDoneAutoplay = false;
1539					    }, 500);
1540					}
1541				}
1542			});
1543
1544			$('body').on('change', '[data-proradio-volumeslider]', function() {
1545				let mvol = $(this).val();
1546				$.qtPlayerObj.uniPlayer.setVolume( mvol );
1547
1548				$("[data-qtmplayer-vball]").css({'top': 100 - mvol});
1549				$("[data-qtmplayer-vfill]").css({'height':mvol+'%'});
1550			});
1551			$('[data-proradio-volumeslider]').val( $.qtPlayerObj.masterVolume );
1552			
1553
1554			window.onresize = function(){
1555			    if($('body').hasClass('qtmplayer--page-popup')){
1556			    	window.resizeTo(380,560);
1557			    }
1558			}
1559		},
1560	};
1561
1562	// Browser online/offline → radio resume helper
1563	if ( typeof window !== 'undefined' && window.addEventListener ) {
1564
1565	    // When the browser goes offline
1566	    window.addEventListener('offline', function () {
1567	        var p = $.qtPlayerObj,
1568	            i = p.interface;
1569
1570	        if (
1571	            p &&
1572	            p.playing &&
1573	            p.songdata &&
1574	            p.songdata.type === 'radio'
1575	        ) {
1576	            // Remember that a radio was playing when we lost connection
1577	            i._wasRadioPlayingOnOffline = true;
1578
1579	            // UI feedback
1580	            i.justStop();
1581	            i.doSpinner(true, 'Connection lost, reconnecting...');
1582	        }
1583	    });
1584
1585	    // When the browser comes back online
1586	    window.addEventListener('online', function () {
1587	        var p = $.qtPlayerObj,
1588	            i = p.interface;
1589
1590	        if (
1591	            p &&
1592	            i._wasRadioPlayingOnOffline
1593	        ) {
1594	            // Reset flag
1595	            i._wasRadioPlayingOnOffline = false;
1596
1597	            // Push into your existing radio resume logic in next()
1598	            i.next();
1599	        }
1600	    });
1601	}
1602
1603
1604	$(window).on('qtAjaxpageLoadEnd', function(){
1605		// If player is paused and we open a channel page, load the channel first
1606		if( $('.proradio-infoajax') ){
1607			if( $('.proradio-infoajax').data('proradio-posttype') == 'radiochannel' ){
1608				var pageId =  $('.proradio-infoajax').data('proradio-pageid');
1609				if( $.qtPlayerObj.playing == false ){
1610					if( $('*[data-qtmplayer-qtmpid="'+ pageId +'"]') ){
1611						$('*[data-qtmplayer-qtmpid="'+ pageId +'"]').click();
1612					}
1613				}
1614			}
1615		}
1616		// set volume 
1617		$('[data-proradio-volumeslider]').val( $.qtPlayerObj.masterVolume );
1618	});
1619
1620
1621	$(document).ready(function() {
1622		if(0 === $('#qtmplayer-playlist li').length ){
1623			return;
1624		}
1625		$.qtPlayerObj.initPlayer();
1626	});
1627
1628
1629})(jQuery);
1630
1631
1632/* Sync play/pause icons for channel buttons after AJAX page swap (qtmplayer.js uses $.qtPlayerObj.playing + $.qtPlayerObj.songdata.*). :contentReference[oaicite:0]{index=0} */
1633(function($){
1634	"use strict";
1635
1636	// Call this after your AJAX DOM swap completes
1637	window.proradio_sync_qtmplayer_buttons = function(scope){
1638		var p = $.qtPlayerObj;
1639		if(!p || !p.interface || !p.interface.switchicon){ return; }
1640
1641		var $root = scope ? $(scope) : $('body');
1642
1643		// Only sync when actually playing (your requirement)
1644		if(p.playing !== true){ return; }
1645
1646		// Current loaded stream URL (radio pause logic can set file='file_hold')
1647		var currentUrl = (p.songdata && p.songdata.file) ? p.songdata.file : '';
1648		if(currentUrl === 'file_hold' && p.songdata && p.songdata.file_hold){ currentUrl = p.songdata.file_hold; }
1649		if(!currentUrl){ return; }
1650
1651		// Sync all play buttons in the newly loaded page
1652		$root.find('.qtmplayer-play-btn[data-qtmplayer-file]').each(function(){
1653			var $btn = $(this);
1654			var btnUrl = $btn.attr('data-qtmplayer-file') || '';
1655			var $icon = $btn.find('i.material-icons');
1656			if(!$icon.length){ return; }
1657
1658			if(btnUrl === currentUrl){
1659				p.interface.switchicon($icon, 'pause');
1660				var $ti = $btn.closest('.qtmplayer-trackitem');
1661				if($ti.length){ $ti.addClass('qtmplayer-played'); }
1662			} else {
1663				p.interface.switchicon($icon, 'play');
1664				var $ti2 = $btn.closest('.qtmplayer-trackitem');
1665				if($ti2.length){ $ti2.removeClass('qtmplayer-played'); }
1666			}
1667		});
1668	};
1669
1670	// If you want it automatically on the existing event:
1671	$(window).on('qtAjaxpageLoadEnd', function(){
1672		window.proradio_sync_qtmplayer_buttons(document.body);
1673	});
1674
1675})(jQuery);
1676
1677

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.