lrkmusic-ytpro 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bgplay.js +186 -108
- package/package.json +2 -2
- package/script.js +1534 -1524
package/bgplay.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
/***** lrkmusic-ytpro bgplay *****
|
|
2
2
|
Author: Satya Prakash
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1.0
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
if (typeof MediaMetadata === 'undefined') {
|
|
7
|
-
window.MediaMetadata = class {
|
|
8
|
-
constructor(data = {}) {
|
|
9
|
-
this.title = data.title || '';
|
|
10
|
-
this.artist = data.artist || '';
|
|
11
|
-
this.album = data.album || '';
|
|
12
|
-
this.artwork = data.artwork || [];
|
|
13
|
-
}
|
|
14
|
-
};
|
|
7
|
+
window.MediaMetadata = class {
|
|
8
|
+
constructor(data = {}) {
|
|
9
|
+
this.title = data.title || '';
|
|
10
|
+
this.artist = data.artist || '';
|
|
11
|
+
this.album = data.album || '';
|
|
12
|
+
this.artwork = data.artwork || [];
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
15
|
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -19,79 +19,78 @@ this.artwork = data.artwork || [];
|
|
|
19
19
|
|
|
20
20
|
if (!('mediaSession' in navigator)) {
|
|
21
21
|
|
|
22
|
-
window.handlers = {};
|
|
23
|
-
window.serviceRunning=false;
|
|
24
|
-
|
|
22
|
+
window.handlers = {};
|
|
23
|
+
window.serviceRunning = false;
|
|
25
24
|
|
|
26
25
|
|
|
27
26
|
|
|
28
|
-
let _state = 'none';
|
|
29
|
-
let _metadata = null;
|
|
30
27
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
configurable: true
|
|
34
|
-
});
|
|
28
|
+
let _state = 'none';
|
|
29
|
+
let _metadata = null;
|
|
35
30
|
|
|
36
|
-
Object.defineProperty(navigator
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
set(value) {
|
|
41
|
-
//console.log("metadata set:", value);
|
|
42
|
-
bgPlay(value);
|
|
43
|
-
_metadata = value;
|
|
44
|
-
},
|
|
45
|
-
configurable: true
|
|
46
|
-
});
|
|
31
|
+
Object.defineProperty(navigator, 'mediaSession', {
|
|
32
|
+
value: {},
|
|
33
|
+
configurable: true
|
|
34
|
+
});
|
|
47
35
|
|
|
36
|
+
Object.defineProperty(navigator.mediaSession, 'metadata', {
|
|
37
|
+
get() {
|
|
38
|
+
return _metadata;
|
|
39
|
+
},
|
|
40
|
+
set(value) {
|
|
41
|
+
//console.log("metadata set:", value);
|
|
42
|
+
bgPlay(value);
|
|
43
|
+
_metadata = value;
|
|
44
|
+
},
|
|
45
|
+
configurable: true
|
|
46
|
+
});
|
|
48
47
|
|
|
49
48
|
|
|
50
49
|
|
|
51
|
-
navigator.mediaSession.setActionHandler = (action, handler) => {
|
|
52
50
|
|
|
53
|
-
|
|
54
|
-
handlers[action] = handler;
|
|
55
|
-
}
|
|
51
|
+
navigator.mediaSession.setActionHandler = (action, handler) => {
|
|
56
52
|
|
|
57
|
-
|
|
53
|
+
if (typeof handler === 'function') {
|
|
54
|
+
handlers[action] = handler;
|
|
55
|
+
}
|
|
58
56
|
|
|
57
|
+
//console.log(action,handler)
|
|
59
58
|
|
|
60
|
-
};
|
|
61
59
|
|
|
60
|
+
};
|
|
62
61
|
|
|
63
62
|
|
|
64
63
|
|
|
65
64
|
|
|
66
65
|
|
|
67
|
-
Object.defineProperty(navigator.mediaSession, 'playbackState', {
|
|
68
|
-
get() {
|
|
69
|
-
return _state;
|
|
70
|
-
},
|
|
71
|
-
set(value) {
|
|
66
|
+
Object.defineProperty(navigator.mediaSession, 'playbackState', {
|
|
67
|
+
get() {
|
|
68
|
+
return _state;
|
|
69
|
+
},
|
|
70
|
+
set(value) {
|
|
72
71
|
|
|
73
|
-
//console.log("Custom playbackState set to:", value);
|
|
72
|
+
//console.log("Custom playbackState set to:", value);
|
|
74
73
|
|
|
75
74
|
|
|
76
|
-
_state = value;
|
|
75
|
+
_state = value;
|
|
77
76
|
|
|
78
77
|
|
|
79
|
-
var ytproAud = getMediaElement();
|
|
78
|
+
var ytproAud = getMediaElement();
|
|
80
79
|
|
|
81
|
-
if (value === 'playing' && ytproAud) {
|
|
82
|
-
setTimeout(()=>{Android.bgPlay(ytproAud.currentTime*1000);},100);
|
|
83
|
-
} else if (value === 'paused' && (pauseAllowed || PIPause) && ytproAud) {
|
|
84
|
-
setTimeout(()=>{Android.bgPause(ytproAud.currentTime*1000);},100);
|
|
85
|
-
}
|
|
86
|
-
// Do NOT call bgStop() when user goes back to home – keep video running like YouTube app.
|
|
87
|
-
// Service stops only when YouTube screen is closed (app onDestroy) or user stops from notification.
|
|
88
|
-
// Removed: else if(value === "none" && !on watch/shorts){ Android.bgStop(); serviceRunning=false; }
|
|
80
|
+
if (value === 'playing' && ytproAud) {
|
|
81
|
+
setTimeout(() => { Android.bgPlay(ytproAud.currentTime * 1000); }, 100);
|
|
82
|
+
} else if (value === 'paused' && (pauseAllowed || PIPause) && ytproAud) {
|
|
83
|
+
setTimeout(() => { Android.bgPause(ytproAud.currentTime * 1000); }, 100);
|
|
84
|
+
}
|
|
85
|
+
// Do NOT call bgStop() when user goes back to home – keep video running like YouTube app.
|
|
86
|
+
// Service stops only when YouTube screen is closed (app onDestroy) or user stops from notification.
|
|
87
|
+
// Removed: else if(value === "none" && !on watch/shorts){ Android.bgStop(); serviceRunning=false; }
|
|
89
88
|
|
|
90
89
|
|
|
91
90
|
|
|
92
|
-
},
|
|
93
|
-
configurable: true
|
|
94
|
-
});
|
|
91
|
+
},
|
|
92
|
+
configurable: true
|
|
93
|
+
});
|
|
95
94
|
|
|
96
95
|
|
|
97
96
|
|
|
@@ -101,7 +100,7 @@ configurable: true
|
|
|
101
100
|
try {
|
|
102
101
|
var origSet = navigator.mediaSession.setActionHandler;
|
|
103
102
|
if (origSet) {
|
|
104
|
-
navigator.mediaSession.setActionHandler = function(action, handler) {
|
|
103
|
+
navigator.mediaSession.setActionHandler = function (action, handler) {
|
|
105
104
|
if (typeof handler === 'function') window.handlers[action] = handler;
|
|
106
105
|
return origSet.call(navigator.mediaSession, action, handler);
|
|
107
106
|
};
|
|
@@ -111,14 +110,93 @@ configurable: true
|
|
|
111
110
|
var origMetaSet = desc.set;
|
|
112
111
|
Object.defineProperty(navigator.mediaSession, 'metadata', {
|
|
113
112
|
get: desc.get,
|
|
114
|
-
set: function(v) { origMetaSet.call(navigator.mediaSession, v); bgPlay(v); },
|
|
113
|
+
set: function (v) { origMetaSet.call(navigator.mediaSession, v); bgPlay(v); },
|
|
115
114
|
configurable: true, enumerable: desc.enumerable
|
|
116
115
|
});
|
|
117
116
|
}
|
|
118
|
-
} catch (e) {}
|
|
117
|
+
} catch (e) { }
|
|
119
118
|
}
|
|
120
119
|
|
|
121
120
|
|
|
121
|
+
/*=========================================================
|
|
122
|
+
FIX 1: Visibilitychange auto-resume guard
|
|
123
|
+
When screen locks / app goes to background, YouTube's
|
|
124
|
+
player pauses. We detect this and force-resume playback.
|
|
125
|
+
=========================================================*/
|
|
126
|
+
document.addEventListener('visibilitychange', function () {
|
|
127
|
+
if (document.hidden && window.serviceRunning) {
|
|
128
|
+
// Set pauseAllowed false so pause override blocks YouTube's auto-pause
|
|
129
|
+
window.pauseAllowed = false;
|
|
130
|
+
var el = getMediaElement();
|
|
131
|
+
if (el && !el.ended) {
|
|
132
|
+
// Multiple retries because YouTube tries to pause at different timings
|
|
133
|
+
setTimeout(function () { try { el.play().catch(function () { }); } catch (e) { } }, 300);
|
|
134
|
+
setTimeout(function () { try { el.play().catch(function () { }); } catch (e) { } }, 800);
|
|
135
|
+
setTimeout(function () { try { el.play().catch(function () { }); } catch (e) { } }, 1500);
|
|
136
|
+
setTimeout(function () { try { el.play().catch(function () { }); } catch (e) { } }, 3000);
|
|
137
|
+
}
|
|
138
|
+
} else if (!document.hidden) {
|
|
139
|
+
// Page visible again — allow normal pause behavior
|
|
140
|
+
window.pauseAllowed = true;
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
/*=========================================================
|
|
146
|
+
FIX 2: Background auto-play-next on video ended
|
|
147
|
+
Uses JS-level handlers.nexttrack() instead of DOM clicks
|
|
148
|
+
so it works reliably when screen is locked / bg.
|
|
149
|
+
=========================================================*/
|
|
150
|
+
function setupBgAutoPlayNext() {
|
|
151
|
+
var el = getMediaElement();
|
|
152
|
+
if (el && !el._bgAutoNextSetup) {
|
|
153
|
+
el._bgAutoNextSetup = true;
|
|
154
|
+
el.addEventListener('ended', function () {
|
|
155
|
+
// Only auto-next if we're on a watch/shorts/music page
|
|
156
|
+
var href = window.location.href;
|
|
157
|
+
if (!(href.indexOf("youtube.com/watch") > -1 || href.indexOf("youtube.com/shorts") > -1 || href.indexOf("music.youtube.com") > -1)) return;
|
|
158
|
+
|
|
159
|
+
if (handlers && typeof handlers.nexttrack === 'function') {
|
|
160
|
+
setTimeout(function () { handlers.nexttrack(); }, 500);
|
|
161
|
+
} else {
|
|
162
|
+
// Fallback: try clicking next button via DOM
|
|
163
|
+
setTimeout(function () {
|
|
164
|
+
try {
|
|
165
|
+
var nextBtn = document.querySelector('[aria-label*="Next"]') ||
|
|
166
|
+
document.querySelector('button[aria-label*="Next"]') ||
|
|
167
|
+
document.querySelector('.ytp-next-button');
|
|
168
|
+
if (nextBtn) nextBtn.click();
|
|
169
|
+
} catch (e) { }
|
|
170
|
+
}, 500);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Re-setup on mutations (new video element created)
|
|
177
|
+
if (typeof MutationObserver !== 'undefined') {
|
|
178
|
+
var _bgNextObserver = new MutationObserver(function () { setupBgAutoPlayNext(); });
|
|
179
|
+
_bgNextObserver.observe(document.documentElement, { childList: true, subtree: true });
|
|
180
|
+
}
|
|
181
|
+
// Also try immediately
|
|
182
|
+
setTimeout(setupBgAutoPlayNext, 2000);
|
|
183
|
+
setTimeout(setupBgAutoPlayNext, 5000);
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
/*=========================================================
|
|
187
|
+
FIX 3: Watchdog timer — re-play if unexpectedly paused
|
|
188
|
+
Catches edge cases where notifications, SMS, or other
|
|
189
|
+
audio focus events cause the WebView media to pause.
|
|
190
|
+
Only active when bg service is running.
|
|
191
|
+
=========================================================*/
|
|
192
|
+
setInterval(function () {
|
|
193
|
+
if (window.serviceRunning && !window.pauseAllowed && !window.PIPause) {
|
|
194
|
+
var el = getMediaElement();
|
|
195
|
+
if (el && el.paused && !el.ended && el.readyState >= 2) {
|
|
196
|
+
try { el.play().catch(function () { }); } catch (e) { }
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}, 3000);
|
|
122
200
|
|
|
123
201
|
|
|
124
202
|
|
|
@@ -129,50 +207,50 @@ function getMediaElement() {
|
|
|
129
207
|
return el || null;
|
|
130
208
|
}
|
|
131
209
|
|
|
132
|
-
async function bgPlay(info){
|
|
210
|
+
async function bgPlay(info) {
|
|
133
211
|
|
|
134
212
|
|
|
135
|
-
if(!(window.location.href.indexOf("youtube.com/watch") > -1 || window.location.href.indexOf("youtube.com/shorts") > -1 || window.location.href.indexOf("music.youtube.com") > -1
|
|
213
|
+
if (!(window.location.href.indexOf("youtube.com/watch") > -1 || window.location.href.indexOf("youtube.com/shorts") > -1 || window.location.href.indexOf("music.youtube.com") > -1)) return;
|
|
136
214
|
|
|
137
215
|
|
|
138
|
-
if(!info) return;
|
|
216
|
+
if (!info) return;
|
|
139
217
|
|
|
140
218
|
|
|
141
|
-
var ytproAud = getMediaElement();
|
|
219
|
+
var ytproAud = getMediaElement();
|
|
142
220
|
|
|
143
221
|
|
|
144
|
-
if(!ytproAud) return;
|
|
222
|
+
if (!ytproAud) return;
|
|
145
223
|
|
|
146
224
|
|
|
147
|
-
var iconBase64="iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=";
|
|
225
|
+
var iconBase64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=";
|
|
148
226
|
|
|
149
227
|
|
|
150
|
-
var img = new Image();
|
|
151
|
-
img.crossOrigin="anonymous";
|
|
152
|
-
img.src=info?.artwork?.[0]?.src;
|
|
228
|
+
var img = new Image();
|
|
229
|
+
img.crossOrigin = "anonymous";
|
|
230
|
+
img.src = info?.artwork?.[0]?.src;
|
|
153
231
|
|
|
154
232
|
|
|
155
|
-
var canvas = document.createElement('canvas');
|
|
156
|
-
canvas.style.width = "1600px";
|
|
157
|
-
canvas.style.height = "900px";
|
|
158
|
-
canvas.style.background="black";
|
|
159
|
-
var context = canvas.getContext('2d');
|
|
233
|
+
var canvas = document.createElement('canvas');
|
|
234
|
+
canvas.style.width = "1600px";
|
|
235
|
+
canvas.style.height = "900px";
|
|
236
|
+
canvas.style.background = "black";
|
|
237
|
+
var context = canvas.getContext('2d');
|
|
160
238
|
|
|
161
|
-
canvas.width = 160;
|
|
162
|
-
canvas.height
|
|
239
|
+
canvas.width = 160;
|
|
240
|
+
canvas.height = 90;
|
|
163
241
|
|
|
164
|
-
//var z=performance.now();
|
|
242
|
+
//var z=performance.now();
|
|
165
243
|
|
|
166
244
|
|
|
167
|
-
await new Promise((res,rej)=>{
|
|
168
|
-
img.onload=()=>res();
|
|
169
|
-
});
|
|
245
|
+
await new Promise((res, rej) => {
|
|
246
|
+
img.onload = () => res();
|
|
247
|
+
});
|
|
170
248
|
|
|
171
249
|
|
|
172
|
-
try{
|
|
173
|
-
context.drawImage(img, 0,0
|
|
174
|
-
iconBase64 = canvas.toDataURL('image/png',1.0);
|
|
175
|
-
}catch{}
|
|
250
|
+
try {
|
|
251
|
+
context.drawImage(img, 0, 0, 160, 90);
|
|
252
|
+
iconBase64 = canvas.toDataURL('image/png', 1.0);
|
|
253
|
+
} catch { }
|
|
176
254
|
|
|
177
255
|
|
|
178
256
|
|
|
@@ -185,15 +263,15 @@ iconBase64 = canvas.toDataURL('image/png',1.0);
|
|
|
185
263
|
|
|
186
264
|
|
|
187
265
|
|
|
188
|
-
if(window.serviceRunning){
|
|
189
|
-
setTimeout(()=>{Android.bgUpdate(iconBase64.replace("data:image/png;base64,", ""),info.title,info.artist,ytproAud.duration*1000);},50);
|
|
190
|
-
setTimeout(()=>{Android.bgPlay(ytproAud.currentTime*1000);},100);
|
|
191
|
-
}
|
|
192
|
-
else{
|
|
193
|
-
window.serviceRunning=true;
|
|
194
|
-
setTimeout(()=>{Android.bgStart(iconBase64.replace("data:image/png;base64,", ""),info.title,info.artist,ytproAud.duration*1000);},50);
|
|
195
|
-
setTimeout(()=>{Android.bgPlay(ytproAud.currentTime*1000);},100);
|
|
196
|
-
}
|
|
266
|
+
if (window.serviceRunning) {
|
|
267
|
+
setTimeout(() => { Android.bgUpdate(iconBase64.replace("data:image/png;base64,", ""), info.title, info.artist, ytproAud.duration * 1000); }, 50);
|
|
268
|
+
setTimeout(() => { Android.bgPlay(ytproAud.currentTime * 1000); }, 100);
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
window.serviceRunning = true;
|
|
272
|
+
setTimeout(() => { Android.bgStart(iconBase64.replace("data:image/png;base64,", ""), info.title, info.artist, ytproAud.duration * 1000); }, 50);
|
|
273
|
+
setTimeout(() => { Android.bgPlay(ytproAud.currentTime * 1000); }, 100);
|
|
274
|
+
}
|
|
197
275
|
|
|
198
276
|
|
|
199
277
|
|
|
@@ -225,32 +303,32 @@ setTimeout(()=>{Android.bgPlay(ytproAud.currentTime*1000);},100);
|
|
|
225
303
|
|
|
226
304
|
|
|
227
305
|
/*When user hits the notification*/
|
|
228
|
-
function seekTo(t){
|
|
229
|
-
handlers.seekto({ seekTime: t/1000 });
|
|
306
|
+
function seekTo(t) {
|
|
307
|
+
handlers.seekto({ seekTime: t / 1000 });
|
|
230
308
|
}
|
|
231
309
|
|
|
232
310
|
/*Daamm , its play*/
|
|
233
|
-
function playVideo(){
|
|
311
|
+
function playVideo() {
|
|
234
312
|
|
|
235
313
|
|
|
236
|
-
if(!pauseAllowed){
|
|
237
|
-
window.PIPause = false;
|
|
238
|
-
navigator.mediaSession.playbackState = 'playing';
|
|
239
|
-
}
|
|
314
|
+
if (!pauseAllowed) {
|
|
315
|
+
window.PIPause = false;
|
|
316
|
+
navigator.mediaSession.playbackState = 'playing';
|
|
317
|
+
}
|
|
240
318
|
|
|
241
|
-
handlers.play();
|
|
319
|
+
handlers.play();
|
|
242
320
|
}
|
|
243
321
|
|
|
244
322
|
/*Daamm , its pause*/
|
|
245
|
-
function pauseVideo(){
|
|
323
|
+
function pauseVideo() {
|
|
246
324
|
|
|
247
325
|
|
|
248
326
|
|
|
249
|
-
if(!pauseAllowed){
|
|
250
|
-
window.PIPause=true;
|
|
251
|
-
navigator.mediaSession.playbackState = 'paused';
|
|
252
|
-
}
|
|
253
|
-
handlers.pause();
|
|
327
|
+
if (!pauseAllowed) {
|
|
328
|
+
window.PIPause = true;
|
|
329
|
+
navigator.mediaSession.playbackState = 'paused';
|
|
330
|
+
}
|
|
331
|
+
handlers.pause();
|
|
254
332
|
|
|
255
333
|
|
|
256
334
|
|
|
@@ -260,14 +338,14 @@ handlers.pause();
|
|
|
260
338
|
|
|
261
339
|
|
|
262
340
|
/*Alexa , play da next song*/
|
|
263
|
-
async function playNext(){
|
|
264
|
-
handlers.nexttrack();
|
|
341
|
+
async function playNext() {
|
|
342
|
+
handlers.nexttrack();
|
|
265
343
|
}
|
|
266
344
|
|
|
267
345
|
|
|
268
346
|
|
|
269
347
|
|
|
270
348
|
/*Alexa , play the f**ng song once again */
|
|
271
|
-
function playPrev(){
|
|
272
|
-
handlers.previoustrack();
|
|
349
|
+
function playPrev() {
|
|
350
|
+
handlers.previoustrack();
|
|
273
351
|
}
|
package/package.json
CHANGED