Skip to content

Commit

Permalink
v17.1.6
Browse files Browse the repository at this point in the history
- Using Babel in Android build to ensure compatibility with Android 7+ (Chrome 51+) webviews

- Fixed and improved hardware acceleration control, lost since migrating NW.js -> Electron

- Minor bug fixes and improvements
  • Loading branch information
EdenwareApps committed Aug 20, 2023
1 parent b8cc1d5 commit c4ace37
Show file tree
Hide file tree
Showing 25 changed files with 1,064 additions and 788 deletions.
12 changes: 12 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"chrome": "51"
}
}
]
]
}
2 changes: 1 addition & 1 deletion config.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<widget android-versionCode="385" id="tv.megacubo.app" version="17.1.5" xmlns="http://www.w3.org/ns/widgets" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<widget android-versionCode="388" id="tv.megacubo.app" version="17.1.6" xmlns="http://www.w3.org/ns/widgets" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<name>Megacubo</name>
<description>
An intuitive, free and open source IPTV player.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "tv.megacubo.app",
"displayName": "Megacubo",
"version": "17.1.5",
"version": "17.1.6",
"description": "A intuitive and multi-language IPTV player.",
"main": "index.js",
"scripts": {
Expand Down
9 changes: 6 additions & 3 deletions www/nodejs-project/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=contain" name="viewport" />
<meta name="color-scheme" content="light" />
<title>Megacubo</title>
<script type="text/javascript">
var frm, q, ptr, config, lang, explorer
if(typeof(window.onerror) != 'function') {
window.onerror = parent.onerror;
}
</script>
<script type="text/javascript" defer src="node_modules/jquery/dist/jquery.min.js"></script>
<script type="text/javascript" defer src="assets/js/libs/jquery.shortcuts.min.js"></script>
<script type="text/javascript" defer src="assets/js/libs/events.js"></script>
Expand All @@ -28,9 +34,6 @@
<link rel="stylesheet" href="node_modules/@fortawesome/fontawesome-free/css/all.min.css" />
<link rel="stylesheet" href="assets/css/index.css" />
<link rel="stylesheet" href="assets/icons/icons.css" />
<script type="text/javascript">
var frm, q, ptr, config, lang, explorer
</script>
</head>
<body>
<div id="main">
Expand Down
9 changes: 4 additions & 5 deletions www/nodejs-project/assets/js/app/app.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
var body = $('body'), content = $('#explorer content'), wrap = document.querySelector('#explorer wrap'), wrapper = $(wrap)

if(typeof(window.onerror) != 'function'){
window.onerror = parent.onerror
}

function parseMomentLocale(content){
let startPos = content.indexOf('moment.defineLocale('), endPos = content.lastIndexOf('return ')
if(startPos != -1 && endPos != -1){
Expand Down Expand Up @@ -477,7 +473,10 @@ function initApp(){
}
})
streamer.on('stop', () => {
if(explorer.modalContainer && explorer.modalContainer.querySelector('#modal-template-option-wait')){
if(explorer.modalContainer && (
explorer.modalContainer.querySelector('#modal-template-option-wait') ||
explorer.modalContainer.querySelector('#modal-template-option-resume')
)){
explorer.endModal()
}
menuPlaying(false)
Expand Down
2 changes: 1 addition & 1 deletion www/nodejs-project/assets/js/app/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -944,7 +944,7 @@ function hexToRGBA(hex, alpha){
const chunkSize = Math.floor((hex.length - 1) / 3)
const hexArr = getChunksFromString(hex.slice(1), chunkSize)
const [r, g, b, a] = hexArr.map(convertHexUnitTo256)
return `rgba(${r}, ${g}, ${b}, ${getAlphafloat(a, alpha)})`
return 'rgba('+ [r, g, b, getAlphafloat(a, alpha)].join(', ') +')'
}

function setupFontDetector(){
Expand Down
12 changes: 6 additions & 6 deletions www/nodejs-project/assets/js/index/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -328,33 +328,33 @@ function fakeUpdateProgress() {
}, 1000);
}

(window.onerror = function (message, file, line, column, errorObj) {
window.onerror = function (message, file, line, column, errorObj) {
let stack = typeof errorObj == 'object' && errorObj !== null && errorObj.stack ? errorObj.stack : traceback();
if (maxAlerts) {
maxAlerts--;
if (file && file.startsWith('blob:http://')) { // ignore hls.js errors
if (file && !file.startsWith('blob:http://')) { // ignore hls.js errors
alert(message + ' ' + file + ':' + line + ' ' + stack);
log(message);
}
}
console.error(errorObj || message, { errorObj, message, file, stack });
return true;
});
}

document.addEventListener('pause', function () {
if (channel) {
if (window.channel) {
channel.post('message', ['suspend']);
}
});

document.addEventListener('resume', function () {
if (channel) {
if (window.channel) {
channel.post('message', ['resume']);
}
});

document.addEventListener('backbutton', function (e) {
if (app) {
if (window.app) {
e.preventDefault();
app.postMessage({ action: 'backbutton' }, location.origin);
}
Expand Down
4 changes: 2 additions & 2 deletions www/nodejs-project/assets/js/index/video.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ class VideoControl extends EventEmitter {
if(!this.suspendStateChangeReporting) this.emit('state', s, err)
}
}
load(src, mimetype, cookie, mediatype){
load(src, mimetype, cookie, mediatype, data){
this.setState('loading')
this.suspendStateChangeReporting = true
this.current && this.current.unload(true)
Expand All @@ -166,7 +166,7 @@ class VideoControl extends EventEmitter {
let m = mimetype.toLowerCase()
if(m.indexOf('mpegurl') != -1){
this.setup('html5h', VideoControlAdapterHTML5HLS)
} else if(m.indexOf('mp2t') != -1 || (src.endsWith('.ts') && mediatype == 'video')){
} else if(m.indexOf('mp2t') != -1 || (src.endsWith('.ts') && mediatype == 'video') || (data && data.mpegts === true)){
this.setup('html5t', VideoControlAdapterHTML5TS)
} else if(m.indexOf('audio/') != -1){
this.setup('html5a', VideoControlAdapterHTML5Audio)
Expand Down
11 changes: 7 additions & 4 deletions www/nodejs-project/assets/js/index/video.ts.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class VideoControlAdapterHTML5TS extends VideoControlAdapterHTML5Video {
this.currentMimetype = mimetype
}
this.mpegts = mpegts.createPlayer({
type: 'mse', // could be mse, mpegts, m2ts, flv
type: 'mse', // could be mse, mpegts, m2ts, flv
url: this.currentSrc,
isLive: type != 'video'
}, {
Expand All @@ -27,10 +27,13 @@ class VideoControlAdapterHTML5TS extends VideoControlAdapterHTML5Video {
})
this.mpegts.attachMediaElement(this.object)
this.errorListener = err => {
console.error('MPEGTS ERROR', err)
const t = this.time()
const t = this.time()
if(t != this.lastErrorTime) {
this.errorsCount = 0
}
this.errorsCount++
if(t != this.lastErrorTime && this.errorsCount >= (t > 0 ? 20 : 3)){
console.error('MPEGTS ERROR', err, this.errorsCount, t != this.lastErrorTime)
if(this.errorsCount >= (t > 0 ? 20 : 3)){
this.emit('error', String(err), true)
this.state = ''
this.emit('state', '')
Expand Down
4 changes: 2 additions & 2 deletions www/nodejs-project/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
height: 100vh;
margin: 0;
padding: 0;
background-color: black;
background-color: #100927;
}
html, body, iframe {
margin: 0;
Expand All @@ -29,7 +29,7 @@
background-image: url(./assets/images/default_icon_white.png);
background-position: center center;
background-repeat: no-repeat;
background-size: 20vh 20vh;
background-size: 25vmin 25vmin;
}
player {
width: 100vw;
Expand Down
33 changes: 19 additions & 14 deletions www/nodejs-project/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -681,33 +681,38 @@ global.ui.on('get-lang-callback', (locale, timezone, ua, online) => {
if(global.cordova) {
global.ui.emit('get-lang')
} else {
let remoteModuleExternal = parseFloat(process.versions.electron) >= 22
const remoteModuleExternal = parseFloat(process.versions.electron) >= 22
remoteModuleExternal && require('@electron/remote/main').initialize()
const { app, BrowserWindow, globalShortcut } = require('electron')
onexit(() => {
app.quit()
})
app.on('window-all-closed', () => {
app.quit()
})
onexit(() => app.quit())
if(remoteModuleExternal){
app.on('browser-window-created', (_, window) => {
require('@electron/remote/main').enable(window.webContents)
})
}

const hwDefaultAccelFlags = `
--use-gl=desktop
--enable-gpu-rasterization
--enable-accelerated-video
--enable-accelerated-video-decode
--enable-accelerated-mjpeg-decode
--enable-native-gpu-memory-buffers
`
let hwAccelFlags = global.config.get('hw-acceleration') || hwDefaultAccelFlags
hwAccelFlags = hwAccelFlags.replace(new RegExp('[\t\n ]+', 'g'), ' ').trim().split(' ').map(s => s.substr(2)).filter(s => s).map(s => s.split('='))
hwAccelFlags.forEach(a => app.commandLine.appendSwitch(...a))

app.commandLine.appendSwitch('no-prefetch')
app.commandLine.appendSwitch('use-gl', 'desktop')
app.commandLine.appendSwitch('disable-http-cache')
app.commandLine.appendSwitch('disable-websql', 'true')
app.commandLine.appendSwitch('enable-gpu-rasterization')
app.commandLine.appendSwitch('enable-accelerated-video')
app.commandLine.appendSwitch('password-store', 'basic')
app.commandLine.appendSwitch('enable-smooth-scrolling')
app.commandLine.appendSwitch('disable-transparency', 'true')
app.commandLine.appendSwitch('disable-site-isolation-trials')
app.commandLine.appendSwitch('enable-accelerated-video-decode')
app.commandLine.appendSwitch('enable-accelerated-mjpeg-decode')
app.commandLine.appendSwitch('enable-native-gpu-memory-buffers')
app.commandLine.appendSwitch('enable-experimental-web-platform-features') // audioTracks support
app.commandLine.appendSwitch('enable-features', 'PlatformHEVCDecoderSupport')
app.commandLine.appendSwitch('disable-features', 'SitePerProcess')
app.commandLine.appendSwitch('disable-features', 'IsolateOrigins,SitePerProcess,NetworkPrediction')
app.whenReady().then(() => {
const window = new BrowserWindow({
titleBarStyle: 'hidden',
Expand Down
106 changes: 44 additions & 62 deletions www/nodejs-project/modules/channels/channels.js
Original file line number Diff line number Diff line change
Expand Up @@ -1644,22 +1644,13 @@ class Channels extends ChannelsKids {
if(!global.lists.activeLists.length){ // one list available on index beyound meta watching list
return [global.lists.manager.noListsEntry()]
}
const namedGroups = {}, isSeries = type == 'series'
let entries = [], groups = await global.lists.groups(type ? [type] : ['series', 'vod'])
const acpolicy = global.config.get('parental-control')
if(acpolicy == 'remove'){
groups = global.lists.parentalControl.filter(groups)
} else if(acpolicy == 'only') {
groups = global.lists.parentalControl.only(groups)
}
groups.forEach(group => {
const isSeries = type == 'series'
let groups = await global.lists.groups(type ? [type] : ['series', 'vod'])
const acpolicy = global.config.get('parental-control')
const groupToEntry = group => {
const name = group.name
const slug = name.toLowerCase().normalize('NFD').replace(new RegExp('[^a-z0-9]', 'g'), '')
if(typeof(namedGroups[slug]) == 'undefined'){
namedGroups[slug] = []
}
const details = group.group.split('/').filter(n => n != name).join(' &middot; ')
namedGroups[slug].push({
return {
name,
details,
type: 'group',
Expand All @@ -1668,59 +1659,50 @@ class Channels extends ChannelsKids {
class: isSeries ? 'entry-cover' : undefined,
fa: isSeries ? 'fas fa-play-circle' : undefined,
renderer: async () => {
let entries = await global.lists.group(group).catch(console.error)
if(Array.isArray(entries)) {
if(acpolicy == 'block'){
entries = global.lists.parentalControl.filter(entries)
}
entries = await global.lists.tools.deepify(entries, {source: group.url})
while(entries.length == 1 && entries[0].type == 'group'){
if(entries[0].entries){
entries = entries[0].entries
} else if(typeof(entries[0].renderer) == 'function') {
entries = await entries[0].renderer(entries[0])
} else if(typeof(entries[0].renderer) == 'string') {
entries = await global.storage.temp.promises.get(entries[0].renderer)
}
}
return entries
return await renderer(group)
}
}
}
const parentalFilter = entries => {
if(acpolicy == 'block'){
entries = global.lists.parentalControl.filter(entries)
} else if(acpolicy == 'remove'){
entries = global.lists.parentalControl.filter(entries)
} else if(acpolicy == 'only') {
entries = global.lists.parentalControl.only(entries)
}
return entries
}
const renderer = async group => {
console.error('GROUP='+ JSON.stringify(group))
let entries = await global.lists.group(group).catch(console.error)
if(Array.isArray(entries)) {
let gentries = (group.entries || []).map(g => groupToEntry(g))
gentries.push(...entries)
while(entries.length == 1){
const entry = entries[0]
if(entry.entries){
entries = entry.entries
} else if(typeof(entry.renderer) == 'function') {
entries = await entry.renderer(entry)
} else if(typeof(entry.renderer) == 'string') {
entries = await global.storage.temp.promises.get(entry.renderer)
} else {
process.nextTick(() => global.explorer.back(null, true))
return []
break
}
}
})
})
Object.keys(namedGroups).forEach(name => {
if(namedGroups[name].length == 1){
entries.push(namedGroups[name][0])
entries = parentalFilter(entries).sortByProp('name')
const deepEntries = await global.lists.tools.deepify(entries, {source: group.url}).catch(console.error)
if(Array.isArray(deepEntries)) {
entries = deepEntries
}
return gentries
} else {
let rname = namedGroups[name][0].name || name
let fa = 'fas fa-box-open'
let icon = namedGroups[name].map(g => g.icon).filter(g => g).shift()
entries.push({
name: rname,
type: 'group',
fa,
icon,
class: isSeries ? 'entry-cover' : undefined,
details: namedGroups[name].details,
renderer: async () => {
const entries = [], already = {}
await Promise.allSettled(namedGroups[name].map(g => g.renderer().then(es => {
es.forEach(e => {
if(typeof(already[e.url]) != 'undefined') return
entries.push(e)
already[e.url] = null
})
})))
return await global.lists.tools.deepify(entries, { minPageCount: 8 })
}
})
process.nextTick(() => global.explorer.back(null, true))
return []
}
})
entries = await global.lists.tools.deepify(entries, { minPageCount: 5 })
return entries
}
return parentalFilter(groups).map(group => groupToEntry(group))
}
async hook(entries, path){
if(!path) {
Expand Down
17 changes: 7 additions & 10 deletions www/nodejs-project/modules/crashlog/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,16 @@ class Crashlog {
return val
}
save(message, file, line, column, errorObj){
console.warn('IDX', message, file, line, column, errorObj)
let stack = errorObj !== undefined && errorObj !== null ? errorObj.stack : traceback()
if(this.maxAlerts){
this.maxAlerts--
alert(message +' '+ file +':'+ line +' '+ stack)
console.error(errorObj || message)
}
app && app.emit('crash', message +' '+ file +':'+ line +' '+ stack)
if(!window.app) return
const stack = errorObj !== undefined && errorObj !== null ? errorObj.stack : traceback()
app.emit('crash', message +' '+ file +':'+ line +' '+ stack)
}
}

var crashlog = new Crashlog()
window.onerror = (...args) => {
crashlog.save(...args)
window.onerror = function (arguments) {
var args = Array.from(arguments)
parent.onerror && parent.onerror.apply(null, args)
crashlog.save(args)
return true
}
Loading

0 comments on commit c4ace37

Please sign in to comment.