From d70f23346f62df5a48cd08872b5c2a169d24d08b Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Fri, 5 Jan 2024 11:15:13 +0200 Subject: [PATCH 001/183] [Added] Full crypto info support --- lib/python/Components/Converter/CryptoInfo.py | 71 +++++++++++++++++++ lib/python/Tools/GetEcmInfo.py | 4 ++ 2 files changed, 75 insertions(+) diff --git a/lib/python/Components/Converter/CryptoInfo.py b/lib/python/Components/Converter/CryptoInfo.py index b07e5989b46..ac87d8e42ff 100644 --- a/lib/python/Components/Converter/CryptoInfo.py +++ b/lib/python/Components/Converter/CryptoInfo.py @@ -2,6 +2,7 @@ from Components.Converter.Poll import Poll from Components.Element import cached from Components.config import config +from enigma import iServiceInformation from Tools.GetEcmInfo import GetEcmInfo @@ -30,6 +31,76 @@ def getText(self): self.visible = True if self.type == "VerboseInfo": data = self.ecmdata.getEcmData()[0] + elif self.type == "FullInfo": + textvalue = "" + server = "" + service = self.source.service + if service: + info = service and service.info() + if info: + try: + if info.getInfoObject(iServiceInformation.sCAIDs): + ecm_info = self.ecmdata.getInfoRaw() + if ecm_info: + # caid + caid = "%0.4X" % int(ecm_info.get('caid', ecm_info.get('CAID', '0')),16) + #pid + pid = "%0.4X" % int(ecm_info.get('pid', ecm_info.get('ECM PID', '0')),16) + # oscam + prov = "%0.6X" % int(ecm_info.get('provid', ecm_info.get('prov', ecm_info.get('Provider', '0'))),16) + + if ecm_info.get("ecm time", "").find("msec") > -1: + ecm_time = ecm_info.get("ecm time", "") + else: + ecm_time = ecm_info.get("ecm time", "").replace(".","").lstrip("0") + " msec" + + #from (oscam) + from_item = ecm_info.get("from", "") + from_splitted = from_item.split(":") + #protocol + protocol = ecm_info.get("protocol", "") + # server + server = from_splitted[0].strip() + #port + port = from_splitted[1].strip() if len(from_splitted) > 1 else "" + # source + if from_splitted[0].strip() == "local": + source = "sci" + else: + source = "net" + # hops + hops = ecm_info.get("hops", "") + #system + system = ecm_info.get("system", "") + #provider + provider = ecm_info.get("provider", "") + # reader + reader = ecm_info.get("reader", "") + if source == "emu": + textvalue = "%s - %s (Caid: %s, Prov: %s,)" % (source, caid, caid, prov) + #new oscam ecm.info with port parametr + elif reader != "" and source == "net" and port != "": + textvalue = "%s - Caid: %s, Prov: %s, Reader: %s, %s (%s:%s) - %s" % (source, caid, prov, reader, protocol, server, port, ecm_time.replace('msec','ms')) + elif reader != "" and source == "net": + textvalue = "%s - Caid: %s, Prov: %s, Reader: %s, %s (%s) - %s" % (source, caid, prov, reader, protocol, server, ecm_time.replace('msec','ms')) + elif reader != "" and source != "net": + textvalue = "%s - Caid: %s, Prov: %s, Reader: %s, %s (local) - %s" % (source, caid, prov, reader, protocol, ecm_time.replace('msec','ms')) + elif server == "" and port == "" and protocol != "": + textvalue = "%s - Caid: %s, Prov: %s, %s - %s" % (source, caid, prov, protocol, ecm_time.replace('msec','ms')) + elif server == "" and port == "" and protocol == "": + textvalue = "%s - Caid: %s - %s, Prov: %s" % (source, prov, caid, ecm_time.replace('msec','ms')) + else: + try: + textvalue = "%s - Caid: %s, Prov: %s, %s (%s:%s) - %s" % (source, caid, prov, protocol, server, port, ecm_time.replace('msec','ms')) + except: + pass + else: + textvalue = "No parse cannot emu" + else: + textvalue = "Free-to-air" + except: + pass + return textvalue else: data = self.ecmdata.getInfo(self.type) return data diff --git a/lib/python/Tools/GetEcmInfo.py b/lib/python/Tools/GetEcmInfo.py index 9a0b84da78a..bd98145e2cb 100644 --- a/lib/python/Tools/GetEcmInfo.py +++ b/lib/python/Tools/GetEcmInfo.py @@ -56,6 +56,10 @@ def getEcmData(self): def getInfo(self, member, ifempty=''): self.pollEcmData() return str(info.get(member, ifempty)) + + def getInfoRaw(self): + self.pollEcmData() + return info def getText(self): global ecm From a74b95de6ab474c5e0949416ac5c00200e7d91e0 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Fri, 5 Jan 2024 09:29:36 +0000 Subject: [PATCH 002/183] PEP8 double aggressive E225 ~ E228 and E231 --- lib/python/Components/Converter/CryptoInfo.py | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/python/Components/Converter/CryptoInfo.py b/lib/python/Components/Converter/CryptoInfo.py index ac87d8e42ff..130b2db5ee2 100644 --- a/lib/python/Components/Converter/CryptoInfo.py +++ b/lib/python/Components/Converter/CryptoInfo.py @@ -43,16 +43,16 @@ def getText(self): ecm_info = self.ecmdata.getInfoRaw() if ecm_info: # caid - caid = "%0.4X" % int(ecm_info.get('caid', ecm_info.get('CAID', '0')),16) + caid = "%0.4X" % int(ecm_info.get('caid', ecm_info.get('CAID', '0')), 16) #pid - pid = "%0.4X" % int(ecm_info.get('pid', ecm_info.get('ECM PID', '0')),16) + pid = "%0.4X" % int(ecm_info.get('pid', ecm_info.get('ECM PID', '0')), 16) # oscam - prov = "%0.6X" % int(ecm_info.get('provid', ecm_info.get('prov', ecm_info.get('Provider', '0'))),16) + prov = "%0.6X" % int(ecm_info.get('provid', ecm_info.get('prov', ecm_info.get('Provider', '0'))), 16) if ecm_info.get("ecm time", "").find("msec") > -1: ecm_time = ecm_info.get("ecm time", "") else: - ecm_time = ecm_info.get("ecm time", "").replace(".","").lstrip("0") + " msec" + ecm_time = ecm_info.get("ecm time", "").replace(".", "").lstrip("0") + " msec" #from (oscam) from_item = ecm_info.get("from", "") @@ -80,18 +80,18 @@ def getText(self): textvalue = "%s - %s (Caid: %s, Prov: %s,)" % (source, caid, caid, prov) #new oscam ecm.info with port parametr elif reader != "" and source == "net" and port != "": - textvalue = "%s - Caid: %s, Prov: %s, Reader: %s, %s (%s:%s) - %s" % (source, caid, prov, reader, protocol, server, port, ecm_time.replace('msec','ms')) + textvalue = "%s - Caid: %s, Prov: %s, Reader: %s, %s (%s:%s) - %s" % (source, caid, prov, reader, protocol, server, port, ecm_time.replace('msec', 'ms')) elif reader != "" and source == "net": - textvalue = "%s - Caid: %s, Prov: %s, Reader: %s, %s (%s) - %s" % (source, caid, prov, reader, protocol, server, ecm_time.replace('msec','ms')) + textvalue = "%s - Caid: %s, Prov: %s, Reader: %s, %s (%s) - %s" % (source, caid, prov, reader, protocol, server, ecm_time.replace('msec', 'ms')) elif reader != "" and source != "net": - textvalue = "%s - Caid: %s, Prov: %s, Reader: %s, %s (local) - %s" % (source, caid, prov, reader, protocol, ecm_time.replace('msec','ms')) + textvalue = "%s - Caid: %s, Prov: %s, Reader: %s, %s (local) - %s" % (source, caid, prov, reader, protocol, ecm_time.replace('msec', 'ms')) elif server == "" and port == "" and protocol != "": - textvalue = "%s - Caid: %s, Prov: %s, %s - %s" % (source, caid, prov, protocol, ecm_time.replace('msec','ms')) + textvalue = "%s - Caid: %s, Prov: %s, %s - %s" % (source, caid, prov, protocol, ecm_time.replace('msec', 'ms')) elif server == "" and port == "" and protocol == "": - textvalue = "%s - Caid: %s - %s, Prov: %s" % (source, prov, caid, ecm_time.replace('msec','ms')) + textvalue = "%s - Caid: %s - %s, Prov: %s" % (source, prov, caid, ecm_time.replace('msec', 'ms')) else: try: - textvalue = "%s - Caid: %s, Prov: %s, %s (%s:%s) - %s" % (source, caid, prov, protocol, server, port, ecm_time.replace('msec','ms')) + textvalue = "%s - Caid: %s, Prov: %s, %s (%s:%s) - %s" % (source, caid, prov, protocol, server, port, ecm_time.replace('msec', 'ms')) except: pass else: From 47e59dfe4bf7345683379491bae24336b0e392be Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Fri, 5 Jan 2024 09:29:56 +0000 Subject: [PATCH 003/183] PEP8 double aggressive W291 ~ W293 and W391 --- lib/python/Components/Converter/CryptoInfo.py | 12 ++++++------ lib/python/Tools/GetEcmInfo.py | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/python/Components/Converter/CryptoInfo.py b/lib/python/Components/Converter/CryptoInfo.py index 130b2db5ee2..b8fbf994cdb 100644 --- a/lib/python/Components/Converter/CryptoInfo.py +++ b/lib/python/Components/Converter/CryptoInfo.py @@ -53,7 +53,7 @@ def getText(self): ecm_time = ecm_info.get("ecm time", "") else: ecm_time = ecm_info.get("ecm time", "").replace(".", "").lstrip("0") + " msec" - + #from (oscam) from_item = ecm_info.get("from", "") from_splitted = from_item.split(":") @@ -79,15 +79,15 @@ def getText(self): if source == "emu": textvalue = "%s - %s (Caid: %s, Prov: %s,)" % (source, caid, caid, prov) #new oscam ecm.info with port parametr - elif reader != "" and source == "net" and port != "": + elif reader != "" and source == "net" and port != "": textvalue = "%s - Caid: %s, Prov: %s, Reader: %s, %s (%s:%s) - %s" % (source, caid, prov, reader, protocol, server, port, ecm_time.replace('msec', 'ms')) - elif reader != "" and source == "net": + elif reader != "" and source == "net": textvalue = "%s - Caid: %s, Prov: %s, Reader: %s, %s (%s) - %s" % (source, caid, prov, reader, protocol, server, ecm_time.replace('msec', 'ms')) - elif reader != "" and source != "net": + elif reader != "" and source != "net": textvalue = "%s - Caid: %s, Prov: %s, Reader: %s, %s (local) - %s" % (source, caid, prov, reader, protocol, ecm_time.replace('msec', 'ms')) - elif server == "" and port == "" and protocol != "": + elif server == "" and port == "" and protocol != "": textvalue = "%s - Caid: %s, Prov: %s, %s - %s" % (source, caid, prov, protocol, ecm_time.replace('msec', 'ms')) - elif server == "" and port == "" and protocol == "": + elif server == "" and port == "" and protocol == "": textvalue = "%s - Caid: %s - %s, Prov: %s" % (source, prov, caid, ecm_time.replace('msec', 'ms')) else: try: diff --git a/lib/python/Tools/GetEcmInfo.py b/lib/python/Tools/GetEcmInfo.py index bd98145e2cb..cba5b33fa2a 100644 --- a/lib/python/Tools/GetEcmInfo.py +++ b/lib/python/Tools/GetEcmInfo.py @@ -56,7 +56,7 @@ def getEcmData(self): def getInfo(self, member, ifempty=''): self.pollEcmData() return str(info.get(member, ifempty)) - + def getInfoRaw(self): self.pollEcmData() return info From a06d064c006bb16e425167c6723f2ec7f58fbd4d Mon Sep 17 00:00:00 2001 From: Littlesat Date: Thu, 4 Jan 2024 17:27:45 +0100 Subject: [PATCH 004/183] Simplify some BoxInfo related code Returning a value from a dict when the key does not exist with a default value can be done in one line with the get function --- lib/python/Components/SystemInfo.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/python/Components/SystemInfo.py b/lib/python/Components/SystemInfo.py index 21ba0d6c116..147d9cb48a3 100644 --- a/lib/python/Components/SystemInfo.py +++ b/lib/python/Components/SystemInfo.py @@ -54,9 +54,7 @@ def getItemsList(self): return sorted(list(self.boxInfo.keys())) def getItem(self, item, default=None): - if item in self.boxInfo: - return self.boxInfo[item] - return default + return self.boxInfo.get(item, default) def setItem(self, item, value, immutable=False, forceOverride=False): if item in self.immutableList and not forceOverride: From a416dc96f9e261cd9a6d501cf079d63c4d2e9be0 Mon Sep 17 00:00:00 2001 From: Huevos Date: Sat, 6 Jan 2024 12:26:04 +0100 Subject: [PATCH 005/183] [ServiceList] protect against possible BSoD "config.recording" attribute is not initialised in VuRecovery mode. This is a temporary solution. --- lib/python/Components/ServiceList.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/python/Components/ServiceList.py b/lib/python/Components/ServiceList.py index 253abe28dd2..2dc470132a5 100644 --- a/lib/python/Components/ServiceList.py +++ b/lib/python/Components/ServiceList.py @@ -67,7 +67,10 @@ def __init__(self, serviceList): pic = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "icons/ico_altref-fs8.png")) pic and self.l.setPixmap(self.l.picBackup, pic) - self.l.setAlternativeRecordMatching(config.recording.record_icon_match.value == "Sref only") + try: # "config.recording" not available in VuRecovery mode + self.l.setAlternativeRecordMatching(config.recording.record_icon_match.value == "Sref only") + except AttributeError: + pass self.root = None self.mode = self.MODE_NORMAL From 5553f7e90ec5c8eaf51aaabfdeb795c0e7803e4c Mon Sep 17 00:00:00 2001 From: openvix-build Date: Sat, 6 Jan 2024 11:35:56 +0000 Subject: [PATCH 006/183] openvix: developer 6.4.011.011 --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index 7f92e91db61..1f9d4a577e8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1228,3 +1228,4 @@ openvix: developer 6.4.011.007 openvix: developer 6.4.011.008 openvix: developer 6.4.011.009 openvix: developer 6.4.011.010 +openvix: developer 6.4.011.011 From acaf0668bad900ec76feeda419fcb45f0e45a7fe Mon Sep 17 00:00:00 2001 From: Huevos Date: Sat, 6 Jan 2024 14:49:17 +0100 Subject: [PATCH 007/183] [VuWizard] do not strip vix plugin --- lib/python/Screens/VuWizard.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/python/Screens/VuWizard.py b/lib/python/Screens/VuWizard.py index cd942efafda..3cf0b1ec291 100644 --- a/lib/python/Screens/VuWizard.py +++ b/lib/python/Screens/VuWizard.py @@ -43,6 +43,10 @@ "enigma2-locale", ] +patterns_skip = [ + "enigma2-plugin-systemplugins-vix", +] + STARTUP = "kernel=/zImage root=/dev/%s rootsubdir=linuxrootfs0" % SystemInfo["mtdrootfs"] # /STARTUP STARTUP_RECOVERY = "kernel=/zImage root=/dev/%s rootsubdir=linuxrootfs0" % SystemInfo["mtdrootfs"] # /STARTUP_RECOVERY STARTUP_1 = "kernel=/linuxrootfs1/zImage root=/dev/%s rootsubdir=linuxrootfs1" % SystemInfo["mtdrootfs"] # /STARTUP_1 @@ -165,6 +169,8 @@ def readOpkg(self, result, retval, extra_args): opkg_installed_list = result.split("\n") # python list installed elements # print("[VuWizard] opkg_installed_list", opkg_installed_list) for opkg_element in opkg_installed_list: # element e.g. opkg_status aio-grab - 1.0+git116+30847a1-r0 + if bool([x for x in patterns_skip if x in opkg_element]): + continue if bool([x for x in patterns if x in opkg_element]): parts = opkg_element.strip().split() # print("[VuWizard]1 parts, parts0", parts, " ", parts[0]) From e0ba77c0189b4d5c964231150f6da0fb3ff5fdd3 Mon Sep 17 00:00:00 2001 From: openvix-build Date: Sat, 6 Jan 2024 13:50:45 +0000 Subject: [PATCH 008/183] openvix: developer 6.4.011.012 --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index 1f9d4a577e8..3f87c5cac54 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1229,3 +1229,4 @@ openvix: developer 6.4.011.008 openvix: developer 6.4.011.009 openvix: developer 6.4.011.010 openvix: developer 6.4.011.011 +openvix: developer 6.4.011.012 From 2e7a6fe8d5f6f3b6a7b30eb83ed783cc2ef7de91 Mon Sep 17 00:00:00 2001 From: Orlandoxx <95180049+Orlandoxx@users.noreply.github.com> Date: Sat, 6 Jan 2024 16:57:03 +0200 Subject: [PATCH 009/183] Updated Finnish (fi.po) translation. Added missing ImageManager.py translations. --- po/fi.po | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 121 insertions(+), 2 deletions(-) diff --git a/po/fi.po b/po/fi.po index 1059311cad3..97fe06ee777 100644 --- a/po/fi.po +++ b/po/fi.po @@ -5,7 +5,7 @@ msgstr "" "Project-Id-Version: enigma2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-12-27 23:35+0000\n" -"PO-Revision-Date: 2024-01-02 19:16+0200\n" +"PO-Revision-Date: 2024-01-06 16:28+0200\n" "Last-Translator: Orlandox\n" "Language-Team: timoj/Kojo/Samzam/Orlandox\n" "Language: fi\n" @@ -13543,7 +13543,7 @@ msgstr "" "Suomenkielinen käännös: timoj, Kojo, Samzam, Orlandox\n" "\n" "Ylläpito : Orlandox\n" -"02.01.2024\n" +"06.01.2024\n" "http://www.huoltovalikko.com" msgid "TS file is too large for ISO9660 level 1!" @@ -19189,3 +19189,122 @@ msgstr "Itse luodun imagen URL" msgid "If you are running your own build server and want to download your own images directly into ImageManager you can link to the URL of your JSON index. Don't forget to add '%s' where the box name should be inserted into the url. If you need help with implementing this please ask on the forum." msgstr "Jos käytät omaa koontipalvelinta ja haluat ladata omat imagesi suoraan Imagen Hallinnointiin, voit linkittää JSON-hakemistosi URL-osoitteeseen. Älä unohda lisätä '%s', johon boksin nimi tulee lisätä URL-osoitteeseen. Jos tarvitset apua tämän toteuttamisessa, kysy foorumilta." + +msgid "slot%s %s - %s (current image)" +msgstr "paikka%s %s - %s (nykyinen image)" + +msgid "slot%s %s - %s" +msgstr "paikka%s %s - %s" + +msgid "ImageManager - %s - cannot flash eMMC slot from sd card slot." +msgstr "Imagen hallinnointi - %s - eMMC-paikkaa ei voi flashata SD-kortin paikasta." + +msgid "ImageManager - no HDD unable to backup Vu Multiboot eMMC slots" +msgstr "Imagen hallinnointi - ei HDD:tä, joten ei pysty varmuuskopioimaan Vu Multiboot eMMC -paikkoja" + +msgid "FULL IMAGE BACKUP" +msgstr "IMAGEN TÄYSVARMISTUS" + +msgid "A full image backup can be created at any time." +msgstr "Imagen täysvarmistus voidaan luoda milloin tahansa." + +msgid "The backup creates a snapshot of the image exactly as it is at the current instant." +msgstr "Varmuuskopio luo tilannekuvan imagesta täsmälleen sellaisena kuin se on kyseisellä hetkellä." + +msgid "It allows making changes to the box with the knowledge that the box can be safely reverted back to a previous known working state." +msgstr "Se mahdollistaa muutosten tekemisen boksiin tietäen, että boksi voidaan turvallisesti palauttaa aiempaan tunnetusti toimivaan tilaan." + +msgid "To make an image backup select GREEN from Image Manager main screen." +msgstr "Jos haluat tehdä imagen varmuuskopion, valitse Imagen hallinnoinnin päänäytöstä VIHREÄ." + +msgid "IMAGE DOWNLOADS" +msgstr "IMAGEN LATAUKSET" + +msgid "Image Manager allows downloading images from OpenViX image server and from a range of other distros." +msgstr "Imagen hallinnointi mahdollistaa imagen lataamisen OpenViX-imagepalvelimelta ja useista muista jakeluista." + +msgid "To be able to download any image local storage must already be configured, HDD, USB or SD, and also be selected as the 'Backup location' in Image Manager setup menu." +msgstr "Imagen lataaminen edellyttää, että paikallinen tallennustila on jo määritetty, HDD, USB tai SD, ja se on myös valittava 'Varmuuskopion sijainti' paikaksi Imagen hallinnan asetusvalikosta." + +msgid "To start a download select YELLOW from Image Manager main screen, then select the distro, and finally which image to download." +msgstr "Aloita lataus valitsemalla KELTAINEN Imagen hallinnoinnin päänäytöstä, valitse sitten kirjasto ja lopuksi ladattava image." + +msgid "The image will then be downloaded to the 'Backup location'." +msgstr "Image ladataan sitten paikkaan 'Varmuuskopion sijainti." + +msgid "Please note, images are large, generally over 100 MB so downloading over a slow or unstable connection is prohibitive." +msgstr "Huomaa, että imaget ovat suuria, yleensä yli 100 Mt, joten lataaminen hitaalla tai epävakaalla yhteydellä on kohtuutonta." + +msgid "Also, instead to downloading, it is possible to send an image to the 'Backup location' by FTP." +msgstr "Lataamisen sijasta on myös mahdollista lähettää image FTP:n kautta 'Varmuuskopion sijainti' paikkaan." + +msgid "FLASHING" +msgstr "FLASHAUS" + +msgid "Before flashing an image 'Automatic settings backup' should be enabled in Image Manager setup menu." +msgstr "Ennen imagen flashausta, 'Automaattinen asetusten varmuuskopiointi' tulee ottaa käyttöön Imagen hallinnoinnin asetusvalikossa." + +msgid "This will make a backup of the current settings and plugins which can be used later when setting up the new image in the First Install Wizard." +msgstr "Tämä tekee varmuuskopion nykyisistä asetuksista ja laajennuksista, joita voidaan käyttää myöhemmin, kun määrität uuden imagen ohjatussa ensimmäisessä asennustoiminnossa." + +msgid "To flash an image first select it from the list of images in the Image Manager main screen (the image will need to have already been downloaded) and then press BLUE." +msgstr "Jos haluat flashata imagen, valitse se ensin Imagen hallinnoinnin päänäytön imageluettelosta (imagen on oltava jo ladattu) ja paina sitten SINISTÄ." + +msgid "After confirming, an automatic backup will be made and then the image will be flashed." +msgstr "Vahvistuksen jälkeen tehdään automaattinen asetusten varmuuskopiointi, jonka jälkeen image flashataan." + +msgid "Upon completion the receiver will reboot and display the First Install Wizard." +msgstr "Kun se on valmis, vastaanotin käynnistyy uudelleen ja näyttää ohjatun ensimmäisen asennustoiminnon." + +msgid "From here the settings backup and plugins can be restored just by selecting that option." +msgstr "Täältä voit palauttaa asetusten varmuuskopion ja laajennukset valitsemalla vain kyseisen vaihtoehdon." + +msgid "RECOVERY MODE" +msgstr "PALAUTUSTILA" + +msgid "This only applies to a handful of Vu+ 4K models." +msgstr "Tämä koskee vain muutamia Vu+ 4K -malleja." + +msgid "Backups of the RECOVERY image will contain a copy of all the client images." +msgstr "PALAUTUS-imagen varmuuskopiot sisältävät kopion kaikista klientti-imageista." + +msgid "When flashing from the recovery image it is possible to flash it to the recovery slot." +msgstr "Kun flashataan palautus-imagesta, on se mahdollista flashata palautuspaikkaan." + +msgid "The new image will overwrite the previous one including any client images that were also configured, so care needs to be taken to make any full image backups (including client images) before overwriting the recovery image." +msgstr "Uusi image korvaa edellisen, mukaan lukien kaikki klientti-imaget, jotka oli myös määritetty, joten on huolehdittava kaikkien imagejen varmuuskopioiden tekemisestä (mukaan lukien klientti-imaget) ennen palautus-imagen ylikirjoittamista." + +#, python-format +msgid "" +"Error creating backup folder:\n" +"%s: %s" +msgstr "" +"Virhe luotaessa varmuuskopiokansiota:\n" +"%s: %s" + +msgid " Press 'Menu' to select a storage device - none available" +msgstr " Paina 'MENU' valitaksesi tallennuslaitteen - ei yhtään saatavilla" + +msgid "Are you sure you want to overwrite the Recovery image?" +msgstr "Haluatko varmasti korvata palautusimagen?" + +msgid "This change will overwrite all eMMC slots." +msgstr "Tämä muutos korvaa kaikki eMMC-paikat." + +msgid "We advise flashing the new image to a regular MultiBoot slot and restoring a settings backup." +msgstr "Suosittelemme flashaamaan uuden imagen tavalliseen MultiBoot-paikkaan ja palauttamaan asetusten varmuuskopion." + +msgid "Select 'Flash regular slot' to flash a regular MultiBoot slot or select 'Overwrite Recovery' to overwrite the Recovery image." +msgstr "Valitse 'Flashaa tavallinen paikka' flashataksesi tavallisen MultiBoot-paikan tai valitse 'Korvaa palautusimage' korvataksesi palautusimagen." + +msgid "Flash regular slot" +msgstr "Flashaa tavallinen paikka" + +msgid "Overwrite Recovery" +msgstr "Korvaa palautusimage" + +msgid "Do you want to backup eMMC slots? This will add from 1 -> 5 minutes per eMMC slot" +msgstr "Haluatko varmuuskopioida eMMC-paikat? Tämä lisää 1 - 5 minuuttia eMMC-paikkaa kohden" + +msgid "Copy eMMC slots confirmation" +msgstr "eMMC-paikkojen kopioinnin vahvistus" From 3ca1707d1ef055645a9b998d90ec47e01a4ba4c3 Mon Sep 17 00:00:00 2001 From: Orlandoxx <95180049+Orlandoxx@users.noreply.github.com> Date: Sun, 7 Jan 2024 14:14:21 +0200 Subject: [PATCH 010/183] Updated fi.po Better translation. --- po/fi.po | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/po/fi.po b/po/fi.po index 97fe06ee777..f23a9aeabb4 100644 --- a/po/fi.po +++ b/po/fi.po @@ -5,7 +5,7 @@ msgstr "" "Project-Id-Version: enigma2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-12-27 23:35+0000\n" -"PO-Revision-Date: 2024-01-06 16:28+0200\n" +"PO-Revision-Date: 2024-01-07 14:10+0200\n" "Last-Translator: Orlandox\n" "Language-Team: timoj/Kojo/Samzam/Orlandox\n" "Language: fi\n" @@ -13543,7 +13543,7 @@ msgstr "" "Suomenkielinen käännös: timoj, Kojo, Samzam, Orlandox\n" "\n" "Ylläpito : Orlandox\n" -"06.01.2024\n" +"07.01.2024\n" "http://www.huoltovalikko.com" msgid "TS file is too large for ISO9660 level 1!" @@ -19203,10 +19203,10 @@ msgid "ImageManager - no HDD unable to backup Vu Multiboot eMMC slots" msgstr "Imagen hallinnointi - ei HDD:tä, joten ei pysty varmuuskopioimaan Vu Multiboot eMMC -paikkoja" msgid "FULL IMAGE BACKUP" -msgstr "IMAGEN TÄYSVARMISTUS" +msgstr "KOKO IMAGEN VARMUUSKOPIOINTI" msgid "A full image backup can be created at any time." -msgstr "Imagen täysvarmistus voidaan luoda milloin tahansa." +msgstr "Koko imagen varmuuskopiointi voidaan luoda milloin tahansa." msgid "The backup creates a snapshot of the image exactly as it is at the current instant." msgstr "Varmuuskopio luo tilannekuvan imagesta täsmälleen sellaisena kuin se on kyseisellä hetkellä." @@ -19230,7 +19230,7 @@ msgid "To start a download select YELLOW from Image Manager main screen, then se msgstr "Aloita lataus valitsemalla KELTAINEN Imagen hallinnoinnin päänäytöstä, valitse sitten kirjasto ja lopuksi ladattava image." msgid "The image will then be downloaded to the 'Backup location'." -msgstr "Image ladataan sitten paikkaan 'Varmuuskopion sijainti." +msgstr "Image ladataan sitten paikkaan 'Varmuuskopion sijainti'." msgid "Please note, images are large, generally over 100 MB so downloading over a slow or unstable connection is prohibitive." msgstr "Huomaa, että imaget ovat suuria, yleensä yli 100 Mt, joten lataaminen hitaalla tai epävakaalla yhteydellä on kohtuutonta." From fd1a77915e2e6d883c3f578588d6bd2df4373afb Mon Sep 17 00:00:00 2001 From: Huevos Date: Mon, 8 Jan 2024 22:39:59 +0100 Subject: [PATCH 011/183] [Multiboot] ensure join on str items --- lib/python/Tools/Multiboot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/python/Tools/Multiboot.py b/lib/python/Tools/Multiboot.py index d866c109be6..901d7f153a7 100644 --- a/lib/python/Tools/Multiboot.py +++ b/lib/python/Tools/Multiboot.py @@ -219,7 +219,7 @@ def createInfo(slot, imagedir="/"): BuildVer = BoxInfo.getItem("imagebuild") BuildDate = VerDate(imagedir) BuildDev = str(BoxInfo.getItem("imagedevbuild")).zfill(3) if BuildType != "rel" else "" - return " ".join([x for x in (Creator, BuildImgVersion, BuildType, BuildVer, BuildDev, "(%s)" % BuildDate) if x]) + return " ".join([str(x) for x in (Creator, BuildImgVersion, BuildType, BuildVer, BuildDev, "(%s)" % BuildDate) if x]) def VerDate(imagedir): @@ -230,7 +230,7 @@ def VerDate(imagedir): if fileExists(path.join(imagedir, "usr/share/bootlogo.mvi")): date3 = datetime.fromtimestamp(stat(path.join(imagedir, "usr/share/bootlogo.mvi")).st_mtime).strftime("%Y-%m-%d") print("[multiboot][VerDate]1 date1, date2, date3", date1, " ", date2, " ", date3) - date = max(date1, date2, date3) + date = max(date1, date2, date3) # this is comparing strings print("[multiboot][VerDate]2 date = %s" % date) date = datetime.strptime(date, '%Y-%m-%d').strftime("%d-%m-%Y") return date From 0ea3658fe7ab1f8d58c0b3ef8b22a20859aa79b3 Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Tue, 9 Jan 2024 16:17:54 +0200 Subject: [PATCH 012/183] [Added] scale to fit functionality for SVG images --- lib/gdi/epng.cpp | 69 +++++++++++++++++++++------------- lib/gdi/epng.h | 2 +- lib/python/Tools/LoadPixmap.py | 4 +- 3 files changed, 46 insertions(+), 29 deletions(-) diff --git a/lib/gdi/epng.cpp b/lib/gdi/epng.cpp index e5da0b666cd..e5531d8538f 100644 --- a/lib/gdi/epng.cpp +++ b/lib/gdi/epng.cpp @@ -368,7 +368,7 @@ static int savePNGto(FILE *fp, gPixmap *pixmap) return 0; } -int loadSVG(ePtr &result, const char *filename, int cached, int width, int height, float scale) +int loadSVG(ePtr &result, const char *filename, int cached, int width, int height, float scale, int keepAspect) { result = nullptr; int size = 0; @@ -400,34 +400,51 @@ int loadSVG(ePtr &result, const char *filename, int cached, int width, return 0; } - if (height > 0) - yscale = ((double) height) / image->height; + if (width > 0 && height > 0 && keepAspect) { + double sourceWidth = image->width; + double sourceHeight = image->height; + double ratio = sourceWidth / sourceHeight; + double widthScale = 0, heightScale = 0; + if (sourceWidth > 0) + widthScale = (double)width / sourceWidth; + if (sourceHeight > 0) + heightScale = (double)height / sourceHeight; + + double scale = std::min(widthScale, heightScale); + yscale = scale; + xscale = scale; + width = (int)(image->width * xscale); + height = (int)(image->height * scale); + } else { + if (height > 0) + yscale = ((double) height) / image->height; - if (width > 0) - { - xscale = ((double) width) / image->width; - if (height <= 0) + if (width > 0) { - yscale = xscale; - height = (int)(image->height * yscale); + xscale = ((double) width) / image->width; + if (height <= 0) + { + yscale = xscale; + height = (int)(image->height * yscale); + } + } + else if (height > 0) + { + xscale = yscale; + width = (int)(image->width * xscale); + } + else if (scale > 0) + { + xscale = (double) scale; + yscale = (double) scale; + width = (int)(image->width * scale); + height = (int)(image->height * scale); + } + else + { + width = (int)image->width; + height = (int)image->height; } - } - else if (height > 0) - { - xscale = yscale; - width = (int)(image->width * xscale); - } - else if (scale > 0) - { - xscale = (double) scale; - yscale = (double) scale; - width = (int)(image->width * scale); - height = (int)(image->height * scale); - } - else - { - width = (int)image->width; - height = (int)image->height; } result = new gPixmap(width, height, 32, cached ? PixmapCache::PixmapDisposed : NULL, -1); diff --git a/lib/gdi/epng.h b/lib/gdi/epng.h index 7cd844b2598..ff54904ca60 100644 --- a/lib/gdi/epng.h +++ b/lib/gdi/epng.h @@ -6,7 +6,7 @@ SWIG_VOID(int) loadPNG(ePtr &SWIG_OUTPUT, const char *filename, int accel = 0, int cached = 1); SWIG_VOID(int) loadJPG(ePtr &SWIG_OUTPUT, const char *filename, int cached = 0); SWIG_VOID(int) loadJPG(ePtr &SWIG_OUTPUT, const char *filename, ePtr alpha, int cached = 0); -SWIG_VOID(int) loadSVG(ePtr &SWIG_OUTPUT, const char *filename, int cached = 1, int width = 0, int height = 0, float scale = 0); +SWIG_VOID(int) loadSVG(ePtr &SWIG_OUTPUT, const char *filename, int cached = 1, int width = 0, int height = 0, float scale = 0, int keepAspect = 0); SWIG_VOID(int) loadImage(ePtr &SWIG_OUTPUT, const char *filename, int accel = 0, int width = 0, int height = 0, int cached = -1, float scale = 0); int savePNG(const char *filename, gPixmap *pixmap); diff --git a/lib/python/Tools/LoadPixmap.py b/lib/python/Tools/LoadPixmap.py index 9e5e679376a..306e396eb97 100644 --- a/lib/python/Tools/LoadPixmap.py +++ b/lib/python/Tools/LoadPixmap.py @@ -4,7 +4,7 @@ # If cached is not supplied, LoadPixmap defaults to caching PNGs and not caching JPGs # Split alpha channel JPGs are never cached as the C++ layer's caching is based on # a single file per image in the cache -def LoadPixmap(path, desktop=None, cached=None, width=0, height=0): +def LoadPixmap(path, desktop=None, cached=None, width=0, height=0, scaletoFit=0): if path[-4:] == ".png": # cache unless caller explicity requests to not cache ptr = loadPNG(path, 0, 0 if cached is False else 1) @@ -15,7 +15,7 @@ def LoadPixmap(path, desktop=None, cached=None, width=0, height=0): from skin import parameters, getSkinFactor # imported here to avoid circular import autoscale = int(parameters.get("AutoscaleSVG", -1)) # skin_default only == -1, disabled == 0 or enabled == 1 scale = height == 0 and (autoscale == -1 and "/skin_default/" in path or autoscale == 1) and getSkinFactor() or 0 - ptr = loadSVG(path, 0 if cached is False else 1, width, height, scale) + ptr = loadSVG(path, 0 if cached is False else 1, width, height, scale, scaletoFit) elif path[-1:] == ".": # caching mechanism isn't suitable for multi file images, so it's explicitly disabled alpha = loadPNG(path + "a.png", 0, 0) From 857eeb09dcdbe07c18c38408256c387f954d82ed Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Tue, 9 Jan 2024 21:04:34 +0200 Subject: [PATCH 013/183] [Fixed] missing subservices display in case of SR service --- lib/python/Components/Converter/ServiceInfo.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/python/Components/Converter/ServiceInfo.py b/lib/python/Components/Converter/ServiceInfo.py index 8c6f505c28f..8de932d67d6 100644 --- a/lib/python/Components/Converter/ServiceInfo.py +++ b/lib/python/Components/Converter/ServiceInfo.py @@ -4,6 +4,7 @@ from Components.Element import cached from Components.Converter.Poll import Poll from Components.Converter.VAudioInfo import StdAudioDesc +from Components.config import config from Tools.Transponder import ConvertToHumanReadable WIDESCREEN = [3, 4, 7, 8, 0xB, 0xC, 0xF, 0x10] @@ -213,7 +214,12 @@ def getBoolean(self): elif self.type == self.IS_CRYPTED: return info.getInfo(iServiceInformation.sIsCrypted) == 1 elif self.type == self.SUBSERVICES_AVAILABLE: - return hasActiveSubservicesForCurrentChannel(':'.join(info.getInfoString(iServiceInformation.sServiceref).split(':')[:11])) + sRef = info.getInfoString(iServiceInformation.sServiceref) + sr_url = "http://%s:%s/" % (config.misc.softcam_streamrelay_url.getHTML(), config.misc.softcam_streamrelay_port.value) + splittedRef = sRef.split(sr_url.replace(":", "%3a")) + if len(splittedRef) > 1: + sRef = splittedRef[1].split(":")[0].replace("%3a", ":") + return hasActiveSubservicesForCurrentChannel(sRef) elif self.type == self.HAS_HBBTV: return info.getInfoString(iServiceInformation.sHBBTVUrl) != "" elif self.type == self.AUDIOTRACKS_AVAILABLE: From e6633ec5e93c748555cc645e668c3ca7f8394b24 Mon Sep 17 00:00:00 2001 From: Huevos Date: Tue, 9 Jan 2024 20:52:30 +0100 Subject: [PATCH 014/183] [SystemInfo] add a comment --- lib/python/Components/SystemInfo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/Components/SystemInfo.py b/lib/python/Components/SystemInfo.py index 147d9cb48a3..98fd0a974fc 100644 --- a/lib/python/Components/SystemInfo.py +++ b/lib/python/Components/SystemInfo.py @@ -48,7 +48,7 @@ def getEnigmaInfoList(self): return sorted(self.immutableList) def getEnigmaConfList(self): # not used by us - return [] + return [] # return an empty list because we do not import a file called "enigma.conf" def getItemsList(self): return sorted(list(self.boxInfo.keys())) From 656f0831a537904e0365a25ea671b67883ced643 Mon Sep 17 00:00:00 2001 From: Huevos Date: Tue, 9 Jan 2024 21:04:37 +0100 Subject: [PATCH 015/183] [MultiBoot] Use SystemInfo to to send variables to the About screen --- lib/python/Screens/About.py | 4 ++-- lib/python/Tools/Multiboot.py | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/python/Screens/About.py b/lib/python/Screens/About.py index 3401bd80f15..9ea58ece9b7 100644 --- a/lib/python/Screens/About.py +++ b/lib/python/Screens/About.py @@ -109,8 +109,8 @@ def populate(self): if fileHas("/proc/cmdline", "rootsubdir=linuxrootfs0"): AboutText += _("Boot Device: \tRecovery Slot\n") else: - if SystemInfo["mtdbootfs"] != "" and " " not in SystemInfo["mtdbootfs"]: - AboutText += _("Boot Device:\t%s%s\n") % (VuPlustxt, SystemInfo["mtdbootfs"]) + if "BootDevice" in SystemInfo and SystemInfo["BootDevice"]: + AboutText += _("Boot Device:\t%s%s\n") % (VuPlustxt, SystemInfo["BootDevice"]) if SystemInfo["HasH9SD"]: if "rootfstype=ext4" in open("/sys/firmware/devicetree/base/chosen/bootargs", "r").read(): diff --git a/lib/python/Tools/Multiboot.py b/lib/python/Tools/Multiboot.py index 901d7f153a7..da96583d575 100644 --- a/lib/python/Tools/Multiboot.py +++ b/lib/python/Tools/Multiboot.py @@ -26,9 +26,9 @@ def getMultibootslots(): slotname = "" SystemInfo["MultiBootSlot"] = None SystemInfo["VuUUIDSlot"] = "" + SystemInfo["BootDevice"] = "" UUID = "" UUIDnum = 0 - BoxInfo = BoxInfoRunningInstance tmp.dir = tempfile.mkdtemp(prefix="getMultibootslots") tmpname = tmp.dir MbootList = MbootList2 if fileHas("/proc/cmdline", "kexec=1") else MbootList1 @@ -44,7 +44,7 @@ def getMultibootslots(): SystemInfo["MBbootdevice"] = device device2 = device.rsplit("/", 1)[1] print("[Multiboot][[getMultibootslots]1 Bootdevice found: %s" % device2) - BoxInfo.setItem("mtdbootfs", device2, forceOverride=True) + SystemInfo["BootDevice"] = device2 for file in glob.glob(path.join(tmpname, "STARTUP_*")): print("[multiboot*****] [getMultibootslots]2 tmpname = %s" % (tmpname)) print("[multiboot] [getMultibootslots]4 file = ", file) @@ -177,12 +177,12 @@ def GetImagelist(Recovery=None): if path.isfile(path.join(imagedir, "usr/bin/enigma2")): # print("[multiboot] [GetImagelist]1 Slot = %s imagedir = %s" % (slot, imagedir)) if path.isfile(path.join(imagedir, "usr/lib/enigma.info")): - print("[multiboot] [BoxInfo] using BoxInfo") + print("[multiboot] [GetImagelist] using enigma.info") BuildVersion = createInfo(slot, imagedir=imagedir) - # print("[multiboot] [BoxInfo] slot=%s, BuildVersion=%s" % (slot, BuildVersion)) + # print("[multiboot] [GetImagelist] slot=%s, BuildVersion=%s" % (slot, BuildVersion)) else: - # print("[multiboot] [BoxInfo] using BoxBranding") - print("[multiboot] [GetImagelist] 2 slot = %s imagedir = %s" % (slot, imagedir)) + # print("[multiboot] [GetImagelist] using BoxBranding") + print("[multiboot] [GetImagelist]2 slot = %s imagedir = %s" % (slot, imagedir)) Creator = open("%s/etc/issue" % imagedir).readlines()[-2].capitalize().strip()[:-6] print("[multiboot] [GetImagelist] Creator = %s imagedir = %s" % (Creator, imagedir)) if fileHas("/proc/cmdline", "kexec=1") and path.isfile(path.join(imagedir, "etc/vtiversion.info")): From 2ffd0a72c5371651ebd13dd4ca5538400177d570 Mon Sep 17 00:00:00 2001 From: Huevos Date: Tue, 9 Jan 2024 21:16:47 +0100 Subject: [PATCH 016/183] [BoxInfo] remove forceOverride --- lib/python/Components/SystemInfo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/Components/SystemInfo.py b/lib/python/Components/SystemInfo.py index 98fd0a974fc..0238156d218 100644 --- a/lib/python/Components/SystemInfo.py +++ b/lib/python/Components/SystemInfo.py @@ -56,7 +56,7 @@ def getItemsList(self): def getItem(self, item, default=None): return self.boxInfo.get(item, default) - def setItem(self, item, value, immutable=False, forceOverride=False): + def setItem(self, item, value, immutable=False): if item in self.immutableList and not forceOverride: print("[BoxInfo] Error: Item '%s' is immutable and can not be %s!" % (item, "changed" if item in self.boxInfo else "added")) return False From 4d57b7311fa81d092df601002f50c851d4ebe8e1 Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Tue, 9 Jan 2024 20:33:23 +0200 Subject: [PATCH 017/183] [Fixed] copile error on PLi --- lib/gdi/epng.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/gdi/epng.cpp b/lib/gdi/epng.cpp index e5531d8538f..470b3c94bce 100644 --- a/lib/gdi/epng.cpp +++ b/lib/gdi/epng.cpp @@ -403,7 +403,6 @@ int loadSVG(ePtr &result, const char *filename, int cached, int width, if (width > 0 && height > 0 && keepAspect) { double sourceWidth = image->width; double sourceHeight = image->height; - double ratio = sourceWidth / sourceHeight; double widthScale = 0, heightScale = 0; if (sourceWidth > 0) widthScale = (double)width / sourceWidth; From e6db86d292cb2f36e74454bed20a7b78a2859b6f Mon Sep 17 00:00:00 2001 From: Huevos Date: Tue, 9 Jan 2024 23:13:43 +0100 Subject: [PATCH 018/183] [BoxInfo] missing from last commit --- lib/python/Components/SystemInfo.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/python/Components/SystemInfo.py b/lib/python/Components/SystemInfo.py index 0238156d218..e118c077fb5 100644 --- a/lib/python/Components/SystemInfo.py +++ b/lib/python/Components/SystemInfo.py @@ -57,7 +57,7 @@ def getItem(self, item, default=None): return self.boxInfo.get(item, default) def setItem(self, item, value, immutable=False): - if item in self.immutableList and not forceOverride: + if item in self.immutableList: print("[BoxInfo] Error: Item '%s' is immutable and can not be %s!" % (item, "changed" if item in self.boxInfo else "added")) return False if immutable and item not in self.immutableList: @@ -65,8 +65,8 @@ def setItem(self, item, value, immutable=False): self.boxInfo[item] = value return True - def deleteItem(self, item, forceOverride=False): - if item in self.immutableList and not forceOverride: + def deleteItem(self, item): + if item in self.immutableList: print("[BoxInfo] Error: Item '%s' is immutable and can not be deleted!" % item) elif item in self.boxInfo: del self.boxInfo[item] From 752963b2760a1c5c38d418c93a5e0902a40808a5 Mon Sep 17 00:00:00 2001 From: Huevos Date: Wed, 10 Jan 2024 01:48:55 +0100 Subject: [PATCH 019/183] [BoxInfo] simplify processValue --- lib/python/Components/SystemInfo.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lib/python/Components/SystemInfo.py b/lib/python/Components/SystemInfo.py index e118c077fb5..38e3a9b7dbc 100644 --- a/lib/python/Components/SystemInfo.py +++ b/lib/python/Components/SystemInfo.py @@ -33,12 +33,6 @@ def __init__(self, root=""): print("[BoxInfo] ERROR: %s is not available! The system is unlikely to boot or operate correctly." % file) def processValue(self, value): - if value.upper() in ("FALSE", "NO", "OFF", "DISABLED"): - return False - elif value.upper() in ("TRUE", "YES", "ON", "ENABLED"): - return True - elif value.upper() == "NONE": - return None try: return literal_eval(value) except: From 0b52f6adcbd740709864be58fe4f35d19c8305fe Mon Sep 17 00:00:00 2001 From: Huevos Date: Wed, 10 Jan 2024 01:54:46 +0100 Subject: [PATCH 020/183] [SystemInfo] add SystemInfomation class This is an extension of the dict class and is to prevent core variables being overwritten from SystemInfo. Currently for testing only. Follows idea and pattern from openatv. --- lib/python/Components/SystemInfo.py | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/lib/python/Components/SystemInfo.py b/lib/python/Components/SystemInfo.py index 38e3a9b7dbc..62f89ef7f42 100644 --- a/lib/python/Components/SystemInfo.py +++ b/lib/python/Components/SystemInfo.py @@ -71,7 +71,30 @@ def deleteItem(self, item): BoxInfo = BoxInformation() -SystemInfo = BoxInfo.boxInfo +class SystemInformation(dict): + def __getitem__(self, item): + return BoxInfo.boxInfo[item] + + def __setitem__(self, item, value): + BoxInfo.setItem(item, value, immutable=False) + + def __delitem__(self, item): + BoxInfo.deleteItem(item) + + def get(self, item, default=None): + return BoxInfo.boxInfo.get(item, default) + + def __prohibited(self, *args, **kws): + print("[SystemInfo] operation not permitted") + + clear = __prohibited + update = __prohibited + setdefault = __prohibited + pop = __prohibited + popitem = __prohibited + + +SystemInfo = SystemInformation() ARCHITECTURE = BoxInfo.getItem("architecture") From d612ff974dd08ca231ad917d47ad0a18c543db08 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Wed, 10 Jan 2024 00:56:53 +0000 Subject: [PATCH 021/183] PEP8 double aggressive W291 ~ W293 and W391 --- lib/python/Components/SystemInfo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/Components/SystemInfo.py b/lib/python/Components/SystemInfo.py index 62f89ef7f42..4c9efc0ed5e 100644 --- a/lib/python/Components/SystemInfo.py +++ b/lib/python/Components/SystemInfo.py @@ -86,7 +86,7 @@ def get(self, item, default=None): def __prohibited(self, *args, **kws): print("[SystemInfo] operation not permitted") - + clear = __prohibited update = __prohibited setdefault = __prohibited From f3698d816aec236d12b527fc5d1118c44bf7a60c Mon Sep 17 00:00:00 2001 From: openvix-build Date: Wed, 10 Jan 2024 09:56:17 +0000 Subject: [PATCH 022/183] openvix: developer 6.4.012.001 --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index 3f87c5cac54..ef884233c09 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1230,3 +1230,4 @@ openvix: developer 6.4.011.009 openvix: developer 6.4.011.010 openvix: developer 6.4.011.011 openvix: developer 6.4.011.012 +openvix: developer 6.4.012.001 From 6f7e2d4d15af862bdd8ec0ba4fe542e6a323c811 Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Thu, 11 Jan 2024 00:04:30 +0200 Subject: [PATCH 023/183] [Added] HAlignment for svg when scale to fit is enabled --- lib/gdi/epng.cpp | 13 +++++++++---- lib/gdi/epng.h | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/gdi/epng.cpp b/lib/gdi/epng.cpp index 470b3c94bce..bb156bc7aa4 100644 --- a/lib/gdi/epng.cpp +++ b/lib/gdi/epng.cpp @@ -368,7 +368,7 @@ static int savePNGto(FILE *fp, gPixmap *pixmap) return 0; } -int loadSVG(ePtr &result, const char *filename, int cached, int width, int height, float scale, int keepAspect) +int loadSVG(ePtr &result, const char *filename, int cached, int width, int height, float scale, int keepAspect, int align) { result = nullptr; int size = 0; @@ -388,6 +388,8 @@ int loadSVG(ePtr &result, const char *filename, int cached, int width, NSVGrasterizer *rast = nullptr; double xscale = 1.0; double yscale = 1.0; + double tx = 0.0; + double ty = 0.0; image = nsvgParseFromFile(filename, "px", 96.0); if (image == nullptr) @@ -412,8 +414,11 @@ int loadSVG(ePtr &result, const char *filename, int cached, int width, double scale = std::min(widthScale, heightScale); yscale = scale; xscale = scale; - width = (int)(image->width * xscale); - height = (int)(image->height * scale); + int new_width = (int)(image->width * xscale); + int new_height = (int)(image->height * scale); + if (align == 2) tx = width - new_width; // Right alignment + else if (align == 4) tx = (int)(((double)(width - new_width))/2); // Center alignment + ty = (int)(((double)(height - new_height))/2); } else { if (height > 0) yscale = ((double) height) / image->height; @@ -456,7 +461,7 @@ int loadSVG(ePtr &result, const char *filename, int cached, int width, eDebug("[ePNG] loadSVG %s %dx%d from %dx%d", filename, width, height, (int)image->width, (int)image->height); // Rasterizes SVG image, returns RGBA image (non-premultiplied alpha) - nsvgRasterizeFull(rast, image, 0, 0, xscale, yscale, (unsigned char*)result->surface->data, width, height, width * 4, 1); + nsvgRasterizeFull(rast, image, tx, ty, xscale, yscale, (unsigned char*)result->surface->data, width, height, width * 4, 1); if (cached) PixmapCache::Set(cachefile, result); diff --git a/lib/gdi/epng.h b/lib/gdi/epng.h index ff54904ca60..22d4d49750e 100644 --- a/lib/gdi/epng.h +++ b/lib/gdi/epng.h @@ -6,7 +6,7 @@ SWIG_VOID(int) loadPNG(ePtr &SWIG_OUTPUT, const char *filename, int accel = 0, int cached = 1); SWIG_VOID(int) loadJPG(ePtr &SWIG_OUTPUT, const char *filename, int cached = 0); SWIG_VOID(int) loadJPG(ePtr &SWIG_OUTPUT, const char *filename, ePtr alpha, int cached = 0); -SWIG_VOID(int) loadSVG(ePtr &SWIG_OUTPUT, const char *filename, int cached = 1, int width = 0, int height = 0, float scale = 0, int keepAspect = 0); +SWIG_VOID(int) loadSVG(ePtr &SWIG_OUTPUT, const char *filename, int cached = 1, int width = 0, int height = 0, float scale = 0, int keepAspect = 0, int align = 0); SWIG_VOID(int) loadImage(ePtr &SWIG_OUTPUT, const char *filename, int accel = 0, int width = 0, int height = 0, int cached = -1, float scale = 0); int savePNG(const char *filename, gPixmap *pixmap); From 55cf7169f89652bc90645ec2aecdc4a19eefbf79 Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Thu, 11 Jan 2024 00:08:13 +0200 Subject: [PATCH 024/183] [Added] missing python implementation --- lib/python/Tools/LoadPixmap.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/python/Tools/LoadPixmap.py b/lib/python/Tools/LoadPixmap.py index 306e396eb97..552a914791d 100644 --- a/lib/python/Tools/LoadPixmap.py +++ b/lib/python/Tools/LoadPixmap.py @@ -4,7 +4,7 @@ # If cached is not supplied, LoadPixmap defaults to caching PNGs and not caching JPGs # Split alpha channel JPGs are never cached as the C++ layer's caching is based on # a single file per image in the cache -def LoadPixmap(path, desktop=None, cached=None, width=0, height=0, scaletoFit=0): +def LoadPixmap(path, desktop=None, cached=None, width=0, height=0, scaletoFit=0, align=4): #align = 1: LEFT, 2: RIGHT, 4: CENTER if path[-4:] == ".png": # cache unless caller explicity requests to not cache ptr = loadPNG(path, 0, 0 if cached is False else 1) @@ -15,7 +15,7 @@ def LoadPixmap(path, desktop=None, cached=None, width=0, height=0, scaletoFit=0) from skin import parameters, getSkinFactor # imported here to avoid circular import autoscale = int(parameters.get("AutoscaleSVG", -1)) # skin_default only == -1, disabled == 0 or enabled == 1 scale = height == 0 and (autoscale == -1 and "/skin_default/" in path or autoscale == 1) and getSkinFactor() or 0 - ptr = loadSVG(path, 0 if cached is False else 1, width, height, scale, scaletoFit) + ptr = loadSVG(path, 0 if cached is False else 1, width, height, scale, scaletoFit, align) elif path[-1:] == ".": # caching mechanism isn't suitable for multi file images, so it's explicitly disabled alpha = loadPNG(path + "a.png", 0, 0) From 265b49451b896c955dea6bf375402f2324f1412b Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Thu, 11 Jan 2024 00:35:34 +0200 Subject: [PATCH 025/183] [Added] same extensions like loadSVG to loadImage --- lib/gdi/epng.cpp | 4 ++-- lib/gdi/epng.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/gdi/epng.cpp b/lib/gdi/epng.cpp index bb156bc7aa4..449ccc9c14e 100644 --- a/lib/gdi/epng.cpp +++ b/lib/gdi/epng.cpp @@ -472,12 +472,12 @@ int loadSVG(ePtr &result, const char *filename, int cached, int width, return 0; } -int loadImage(ePtr &result, const char *filename, int accel, int width, int height, int cached, float scale) +int loadImage(ePtr &result, const char *filename, int accel, int width, int height, int cached, float scale, int keepAspect, int align) { if (endsWith(filename, ".png")) return loadPNG(result, filename, accel, cached == -1 ? 1 : cached); else if (endsWith(filename, ".svg")) - return loadSVG(result, filename, cached == -1 ? 1 : cached, width, height, scale); + return loadSVG(result, filename, cached == -1 ? 1 : cached, width, height, scale, keepAspect, align); else if (endsWith(filename, ".jpg")) return loadJPG(result, filename, cached == -1 ? 0 : cached); diff --git a/lib/gdi/epng.h b/lib/gdi/epng.h index 22d4d49750e..8e123fc1ce2 100644 --- a/lib/gdi/epng.h +++ b/lib/gdi/epng.h @@ -8,7 +8,7 @@ SWIG_VOID(int) loadJPG(ePtr &SWIG_OUTPUT, const char *filename, int cac SWIG_VOID(int) loadJPG(ePtr &SWIG_OUTPUT, const char *filename, ePtr alpha, int cached = 0); SWIG_VOID(int) loadSVG(ePtr &SWIG_OUTPUT, const char *filename, int cached = 1, int width = 0, int height = 0, float scale = 0, int keepAspect = 0, int align = 0); -SWIG_VOID(int) loadImage(ePtr &SWIG_OUTPUT, const char *filename, int accel = 0, int width = 0, int height = 0, int cached = -1, float scale = 0); +SWIG_VOID(int) loadImage(ePtr &SWIG_OUTPUT, const char *filename, int accel = 0, int width = 0, int height = 0, int cached = -1, float scale = 0, int keepAspect = 0, int align = 0); int savePNG(const char *filename, gPixmap *pixmap); #endif From 46515550281385361a79f7622a368c5053b3532b Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Thu, 11 Jan 2024 00:40:36 +0200 Subject: [PATCH 026/183] [Updated] Used existing enums --- lib/python/Tools/LoadPixmap.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/python/Tools/LoadPixmap.py b/lib/python/Tools/LoadPixmap.py index 552a914791d..c46e9b9612d 100644 --- a/lib/python/Tools/LoadPixmap.py +++ b/lib/python/Tools/LoadPixmap.py @@ -1,10 +1,10 @@ -from enigma import loadPNG, loadJPG, loadSVG +from enigma import loadPNG, loadJPG, loadSVG, RT_HALIGN_CENTER # If cached is not supplied, LoadPixmap defaults to caching PNGs and not caching JPGs # Split alpha channel JPGs are never cached as the C++ layer's caching is based on # a single file per image in the cache -def LoadPixmap(path, desktop=None, cached=None, width=0, height=0, scaletoFit=0, align=4): #align = 1: LEFT, 2: RIGHT, 4: CENTER +def LoadPixmap(path, desktop=None, cached=None, width=0, height=0, scaletoFit=0, align=RT_HALIGN_CENTER): if path[-4:] == ".png": # cache unless caller explicity requests to not cache ptr = loadPNG(path, 0, 0 if cached is False else 1) From 458146230ba45ce169cd351fe29104d2e3129b35 Mon Sep 17 00:00:00 2001 From: Rob van der Does Date: Thu, 11 Jan 2024 15:35:52 +0100 Subject: [PATCH 027/183] [Translations] Update Dutch (NL) translation. --- po/nl.po | 49 +++++++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/po/nl.po b/po/nl.po index accbfb69fbb..4d62cee7fc3 100644 --- a/po/nl.po +++ b/po/nl.po @@ -3,8 +3,8 @@ msgid "" msgstr "" "Project-Id-Version: ViX\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-12-14 12:09+0000\n" -"PO-Revision-Date: 2023-12-15 11:16+0100\n" +"POT-Creation-Date: 2024-01-10 10:06+0000\n" +"PO-Revision-Date: 2024-01-11 15:34+0100\n" "Last-Translator: Rob van der Does \n" "Language-Team: Andy Blackburn, Rob van der Does\n" "Language: nl\n" @@ -13,7 +13,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Poedit-SourceCharset: iso-8859-15\n" -"X-Generator: Poedit 3.4.1\n" +"X-Generator: Poedit 3.4.2\n" #, python-format msgid "" @@ -3734,14 +3734,14 @@ msgstr "Bepaal hoelang oude info in de EPG zichtbaar moet blijven. Nuttig als u msgid "Configure how recording filenames are constructed." msgstr "Stel in hoe de namen van opnames worden samengesteld." -msgid "Configure if and how crypto icons will be shown in the channel selection list." -msgstr "Stel in of en hoe de crypto-iconen moeten worden getoond." +msgid "Configure if and how crypto icons will be shown in the channel selection list (left alignment only available in single line mode)." +msgstr "Stel in of en hoe de crypto-iconen moeten worden getoond (links alleen beschikbaar in de één regel modus)." -msgid "Configure if and how service type icons will be shown." -msgstr "Stel in of en hoe de servicetype-iconen worden getoond." +msgid "Configure if and how service type icons will be shown (left alignment only available in single line mode)." +msgstr "Stel in of en hoe de servicetype-iconen worden getoond (links alleen beschikbaar in de één regel modus)." -msgid "Configure if and how the record indicator will be shown in the channel selection list." -msgstr "Stel in of en hoe de opname-indicatie in de kanaallijst wordt getoond." +msgid "Configure if and how the record indicator will be shown in the channel selection list (left alignment only available in single line mode)." +msgstr "Stel in of en hoe de opname-indicatie in de kanaallijst wordt getoond (links alleen beschikbaar in de één regel modus)." msgid "Configure if and how wide the service name column will be shown in the channel selection list." msgstr "Stel in of en hoe breed de kanaalnaam moeten worden getoond in de kanaallijst." @@ -8093,8 +8093,8 @@ msgstr "Lebanon" msgid "Left" msgstr "Links" -msgid "Left from servicename" -msgstr "Links van kanaalnaam" +msgid "Left from servicename (only available in single line mode)" +msgstr "Links van kanaalnaam (alleen beschikbaar in de één regel modus)" msgid "Left long" msgstr "Lang-links" @@ -10023,8 +10023,8 @@ msgstr "Percentage" msgid "Percentage left" msgstr "Percentage links" -msgid "Percentage right" -msgstr "Percentage rechts" +msgid "Percentage right (only available in single line mode)" +msgstr "Percentage rechts (alleen beschikbaar in de één regel modus)" msgid "Perform a complete image backup before updating." msgstr "Maak een imageback-up alvorens te updaten." @@ -10818,8 +10818,8 @@ msgstr "Voortgang" msgid "Progress bar left" msgstr "Voortgangsbalk links" -msgid "Progress bar right" -msgstr "Voortgangsbalk rechts" +msgid "Progress bar right (only available in single line mode)" +msgstr "Voortgangsbalk rechts (alleen beschikbaar in de één regel modus)" msgid "Prominent" msgstr "Prominent" @@ -12874,8 +12874,8 @@ msgstr "Stel de tijd in waarop de timer moet starten." msgid "Set the time the timer must stop." msgstr "Stel de tijd in waarop de timer stopt." -msgid "Set the type of the progress indication in the channel selection screen." -msgstr "Bepaal teh type voortgangsindicator dat u wilt gebruiken in de kanaallijst." +msgid "Set the type of the progress indication in the channel selection screen (right alignment only available in single line mode)." +msgstr "Bepaal het type voortgangsindicator dat u wil gebruiken in de kanaallijst (rechts alleen beschikbaar in de één regel modus)." msgid "Set to the desired primetime." msgstr "Stel de gewenste primetime in." @@ -18358,6 +18358,9 @@ msgstr "waar" msgid "two lines" msgstr "twee regels" +msgid "two lines+next event" +msgstr "twee regels + volgende programma" + msgid "type" msgstr "type" @@ -19009,6 +19012,9 @@ msgstr "| aparte lijst van voorvoegsels die u van namen wil verwijderen, geschei #~ msgid "Last update: %s" #~ msgstr "Laatste update: %s" +#~ msgid "Left from servicename" +#~ msgstr "Links van kanaalnaam" + #~ msgid "Manage extensions" #~ msgstr "Beheer van extensies" @@ -19079,6 +19085,9 @@ msgstr "| aparte lijst van voorvoegsels die u van namen wil verwijderen, geschei #~ msgid "Packet manager" #~ msgstr "Pakketbeheer" +#~ msgid "Percentage right" +#~ msgstr "Percentage rechts" + #~ msgid "Perform a settings backup, making a backup before updating is strongly advised." #~ msgstr "Maak een settingsback-up; het maken van een back-up alvorens te updaten wordt sterk geadviseerd." @@ -19128,6 +19137,9 @@ msgstr "| aparte lijst van voorvoegsels die u van namen wil verwijderen, geschei #~ msgid "Process" #~ msgstr "Proces" +#~ msgid "Progress bar right" +#~ msgstr "Voortgangsbalk rechts" + #~ msgid "Query before backup starts" #~ msgstr "Vraag alvorens back-up te starten" @@ -19582,8 +19594,5 @@ msgstr "| aparte lijst van voorvoegsels die u van namen wil verwijderen, geschei #~ msgid "start directory" #~ msgstr "startmap" -#~ msgid "two lines and next event" -#~ msgstr "twee regels en volgende programma" - #~ msgid "updates available." #~ msgstr "updates beschikbaar." From ba10b516474d235937cf109e5bb9f92c13d67740 Mon Sep 17 00:00:00 2001 From: Huevos Date: Fri, 12 Jan 2024 12:48:09 +0100 Subject: [PATCH 028/183] [PackageManager] add --- .../SystemPlugins/ViX/PackageManager.py | 380 ++++++++++++++++++ .../SystemPlugins/ViX/images/installable.png | Bin 0 -> 986 bytes .../SystemPlugins/ViX/images/installed.png | Bin 0 -> 2055 bytes .../SystemPlugins/ViX/images/remove.png | Bin 0 -> 2201 bytes .../SystemPlugins/ViX/images/upgrade.png | Bin 0 -> 2603 bytes .../SystemPlugins/ViX/images/upgradeable.png | Bin 0 -> 2055 bytes lib/python/Plugins/SystemPlugins/ViX/ui.py | 5 + 7 files changed, 385 insertions(+) create mode 100644 lib/python/Plugins/SystemPlugins/ViX/PackageManager.py create mode 100644 lib/python/Plugins/SystemPlugins/ViX/images/installable.png create mode 100644 lib/python/Plugins/SystemPlugins/ViX/images/installed.png create mode 100644 lib/python/Plugins/SystemPlugins/ViX/images/remove.png create mode 100644 lib/python/Plugins/SystemPlugins/ViX/images/upgrade.png create mode 100644 lib/python/Plugins/SystemPlugins/ViX/images/upgradeable.png diff --git a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py new file mode 100644 index 00000000000..66a40c3a462 --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py @@ -0,0 +1,380 @@ +import os +import time +import pickle + +from enigma import eRCInput, getPrevAsciiCode + +from Components.Console import Console +from Components.Ipkg import IpkgComponent +from Components.Sources.List import List +from Components.ActionMap import NumberActionMap +from Components.PluginComponent import plugins +from Components.Sources.StaticText import StaticText + +from Screens.Ipkg import Ipkg +from Screens.MessageBox import MessageBox +from Screens.Screen import Screen +from Screens.Standby import TryQuitMainloop + +from Tools.Directories import resolveFilename, SCOPE_PLUGINS, SCOPE_CURRENT_PLUGIN, SCOPE_CURRENT_SKIN +from Tools.LoadPixmap import LoadPixmap +from Tools.NumericalTextInput import NumericalTextInput + + +def write_cache(cache_file, cache_data): + try: + path = os.path.dirname(cache_file) + if not os.path.isdir(path): + os.mkdir(path) + pickle.dump(cache_data, open(cache_file, "wb"), -1) + except Exception as ex: + print("Failed to write cache data to %s:" % cache_file, ex) + + +def valid_cache(cache_file, cache_ttl): + try: + mtime = os.stat(cache_file)[os.stat.ST_MTIME] + except: + return 0 + curr_time = time.time() + if (curr_time - mtime) > cache_ttl: + return 0 + else: + return 1 + + +def load_cache(cache_file): + return pickle.load(open(cache_file, "rb")) + + +class PackageManager(Screen, NumericalTextInput): + skin = [""" + + + + + + + + {"template": [ + MultiContentEntryText(pos = (%d, %d), size = (%d, %d), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name + MultiContentEntryText(pos = (%d, %d), size = (%d, %d), font=1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the description + MultiContentEntryPixmapAlphaBlend(pos = (%d, %d), size = (%d, %d), png = 4, flags=BT_SCALE), # index 4 is the status pixmap + MultiContentEntryPixmapAlphaBlend(pos = (%d, %d), size = (%d, %d), png = 5), # index 4 is the div pixmap + ], + "fonts": [gFont("Regular", %d),gFont("Regular", %d)], + "itemHeight": %d + } + + + """, + 530, 420, # Screen + 0, 0, 140, 40, # colours + 140, 0, 140, 40, + 0, 0, 140, 40, 20, + 140, 0, 140, 40, 20, + 5, 50, 520, 365, # list + 5, 1, 440, 28, # template + 5, 26, 440, 20, + 445, 2, 48, 48, + 5, 50, 510, 2, + 22, 14, # font + 52, #itemHeight + ] + + + # TODO, skin scale + + def __init__(self, session): + Screen.__init__(self, session) + NumericalTextInput.__init__(self) + self.setTitle(_("Package manager")) + + self.setUseableChars("1234567890abcdefghijklmnopqrstuvwxyz") + + self["shortcuts"] = NumberActionMap(["SetupActions", "InputAsciiActions"], + { + "ok": self.go, + "cancel": self.exit, + "save": self.reload, + "gotAsciiCode": self.keyGotAscii, + "1": self.keyNumberGlobal, + "2": self.keyNumberGlobal, + "3": self.keyNumberGlobal, + "4": self.keyNumberGlobal, + "5": self.keyNumberGlobal, + "6": self.keyNumberGlobal, + "7": self.keyNumberGlobal, + "8": self.keyNumberGlobal, + "9": self.keyNumberGlobal, + "0": self.keyNumberGlobal + }, -1) + + self.list = [] + self.statuslist = [] + self["list"] = List(self.list) + self["key_red"] = StaticText(_("Close")) + self["key_green"] = StaticText(_("Refresh list")) + + self.imagePath = "%s/images/" % os.path.dirname(os.path.realpath(__file__)) + self.list_updating = True + self.packetlist = [] + self.installed_packetlist = {} + self.upgradeable_packages = {} + self.Console = Console() + self.cmdList = [] + self.cachelist = [] + self.cache_ttl = 86400 #600 is default, 0 disables, Seconds cache is considered valid (24h should be ok for caching opkgs) + self.cache_file = "/etc/enigma2/packetmanager.cache" #Path to cache directory + self.oktext = _("\nAfter pressing OK, please wait!") + self.unwanted_extensions = ("-dbg", "-dev", "-doc", "-staticdev", "-src", "busybox") + + self.ipkg = IpkgComponent() + self.ipkg.addCallback(self.ipkgCallback) + self.onLayoutFinish.append(self.rebuildList) + + rcinput = eRCInput.getInstance() + rcinput.setKeyboardMode(rcinput.kmAscii) + + def keyNumberGlobal(self, val): + key = self.getKey(val) + if key is not None: + keyvalue = key.encode("utf-8") + if len(keyvalue) == 1: + self.setNextIdx(keyvalue[0]) + + def keyGotAscii(self): + keyvalue = chr(getPrevAsciiCode()).encode("utf-8") + if len(keyvalue) == 1: + self.setNextIdx(keyvalue[0]) + + def setNextIdx(self, char): + if char in ("0", "1", "a"): + self["list"].setIndex(0) + else: + idx = self.getNextIdx(char) + if idx and idx <= self["list"].count: + self["list"].setIndex(idx) + + def getNextIdx(self, char): + for idx, i in enumerate(self["list"].list): + if i[0] and (i[0][0] == char): + return idx + + def exit(self): + self.ipkg.stop() + if self.Console is not None: + self.Console.killAll() + rcinput = eRCInput.getInstance() + rcinput.setKeyboardMode(rcinput.kmNone) + self.close() + + def reload(self): + if os.path.exists(self.cache_file): + os.unlink(self.cache_file) + self.list_updating = True + self.rebuildList() + + def setStatus(self, status=None): + if status: + self.statuslist = [] + divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "div-h.png")) + if status == "update": + statuspng = LoadPixmap(cached=True, path=self.imagePath + "upgrade.png") + self.statuslist.append((_("Package list update"), "", _("Downloading a new packet list. Please wait..."), "", statuspng, divpng)) + self["list"].setList(self.statuslist) + elif status == "error": + statuspng = LoadPixmap(cached=True, path=self.imagePath + "remove.png") + self.statuslist.append((_("Error"), "", _("An error occurred while downloading the packetlist. Please try again."), "", statuspng, divpng)) + self["list"].setList(self.statuslist) + + def rebuildList(self): + self.setStatus("update") + self.inv_cache = 0 + self.vc = valid_cache(self.cache_file, self.cache_ttl) + if self.cache_ttl > 0 and self.vc != 0: + try: + self.buildPacketList() + except: + self.inv_cache = 1 + if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0: + self.run = 0 + self.ipkg.startCmd(IpkgComponent.CMD_UPDATE) + + def go(self, returnValue=None): + cur = self["list"].getCurrent() + if cur: + status = cur[3] + package = cur[0] + self.cmdList = [] + if status == "installed": + self.cmdList.append((IpkgComponent.CMD_REMOVE, {"package": package})) + if len(self.cmdList): + self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n") + package + "\n" + self.oktext) + elif status == "upgradeable": + self.cmdList.append((IpkgComponent.CMD_INSTALL, {"package": package})) + if len(self.cmdList): + self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to update the package:\n") + package + "\n" + self.oktext) + elif status == "installable": + self.cmdList.append((IpkgComponent.CMD_INSTALL, {"package": package})) + if len(self.cmdList): + self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n") + package + "\n" + self.oktext) + + def runRemove(self, result): + if result: + self.session.openWithCallback(self.runRemoveFinished, Ipkg, cmdList=self.cmdList) + + def runRemoveFinished(self): + self.session.openWithCallback(self.RemoveReboot, MessageBox, _("Removal has completed.") + "\n" + _("Do you want to reboot your receiver?"), MessageBox.TYPE_YESNO) + + def RemoveReboot(self, result): + if result is None: + return + if not result: + cur = self["list"].getCurrent() + if cur: + item = self["list"].getIndex() + self.list[item] = self.buildEntryComponent(cur[0], cur[1], cur[2], "installable") + self.cachelist[item] = [cur[0], cur[1], cur[2], "installable"] + self["list"].setList(self.list) + write_cache(self.cache_file, self.cachelist) + self.reloadPluginlist() + if result: + self.session.open(TryQuitMainloop, retvalue=3) + + def runUpgrade(self, result): + if result: + self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList=self.cmdList) + + def runUpgradeFinished(self): + self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Update has completed.") + "\n" + _("Do you want to reboot your receiver?"), MessageBox.TYPE_YESNO) + + def UpgradeReboot(self, result): + if result is None: + return + if not result: + cur = self["list"].getCurrent() + if cur: + item = self["list"].getIndex() + self.list[item] = self.buildEntryComponent(cur[0], cur[1], cur[2], "installed") + self.cachelist[item] = [cur[0], cur[1], cur[2], "installed"] + self["list"].setList(self.list) + write_cache(self.cache_file, self.cachelist) + self.reloadPluginlist() + if result: + self.session.open(TryQuitMainloop, retvalue=3) + + def ipkgCallback(self, event, param): + if event == IpkgComponent.EVENT_ERROR: + self.list_updating = False + self.setStatus("error") + elif event == IpkgComponent.EVENT_DONE: + if self.list_updating: + self.list_updating = False + if not self.Console: + self.Console = Console() + cmd = self.ipkg.ipkg + " list" + self.Console.ePopen(cmd, self.OpkgList_Finished) + pass + + def OpkgList_Finished(self, result, retval, extra_args=None): + if result: + self.packetlist = [] + last_name = "" + for x in result.splitlines(): + if " - " in x: + tokens = x.split(" - ") + name = tokens[0].strip() + if name and not any(name.endswith(x) for x in self.unwanted_extensions): + l = len(tokens) + version = l > 1 and tokens[1].strip() or "" + descr = l > 2 and tokens[2].strip() or "" + if name == last_name: + continue + last_name = name + self.packetlist.append([name, version, descr]) + elif len(self.packetlist) > 0: + # no " - " in the text, assume that this is the description + # therefore add this text to the last packet description + last_packet = self.packetlist[-1] + last_packet[2] = last_packet[2] + x + self.packetlist[:-1] + last_packet + + if not self.Console: + self.Console = Console() + cmd = self.ipkg.ipkg + " list_installed" + self.Console.ePopen(cmd, self.OpkgListInstalled_Finished) + + def OpkgListInstalled_Finished(self, result, retval, extra_args=None): + if result: + self.installed_packetlist = {} + for x in result.splitlines(): + tokens = x.split(" - ") + name = tokens[0].strip() + if not any(name.endswith(x) for x in self.unwanted_extensions): + l = len(tokens) + version = l > 1 and tokens[1].strip() or "" + self.installed_packetlist[name] = version + if not self.Console: + self.Console = Console() + cmd = "opkg list-upgradable" + self.Console.ePopen(cmd, self.OpkgListUpgradeable_Finished) + + def OpkgListUpgradeable_Finished(self, result, retval, extra_args=None): + if result: + self.upgradeable_packages = {} + for x in result.splitlines(): + tokens = x.split(" - ") + name = tokens[0].strip() + if not any(name.endswith(x) for x in self.unwanted_extensions): + l = len(tokens) + version = l > 2 and tokens[2].strip() or "" + self.upgradeable_packages[name] = version + self.buildPacketList() + + def buildEntryComponent(self, name, version, description, state): + divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "div-h.png")) + if not description: + description = "No description available." + if state == "installed": + installedpng = LoadPixmap(cached=True, path=self.imagePath + "installed.png") + return ((name, version, _(description), state, installedpng, divpng)) + elif state == "upgradeable": + upgradeablepng = LoadPixmap(cached=True, path=self.imagePath + "upgradeable.png") + return ((name, version, _(description), state, upgradeablepng, divpng)) + else: + installablepng = LoadPixmap(cached=True, path=self.imagePath + "installable.png") + return ((name, version, _(description), state, installablepng, divpng)) + + def buildPacketList(self): + self.list = [] + self.cachelist = [] + if self.cache_ttl > 0 and self.vc != 0: + print("Loading packagelist cache from ", self.cache_file) + try: + self.cachelist = load_cache(self.cache_file) + if len(self.cachelist) > 0: + for x in self.cachelist: + self.list.append(self.buildEntryComponent(x[0], x[1], x[2], x[3])) + self["list"].setList(self.list) + except: + self.inv_cache = 1 + + if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0: + print("rebuilding fresh package list") + for x in self.packetlist: + status = "" + if x[0] in self.installed_packetlist: + if x[0] in self.upgradeable_packages: + status = "upgradeable" + else: + status = "installed" + else: + status = "installable" + self.list.append(self.buildEntryComponent(x[0], x[1], x[2], status)) + self.cachelist.append([x[0], x[1], x[2], status]) + write_cache(self.cache_file, self.cachelist) + self["list"].setList(self.list) + + def reloadPluginlist(self): + plugins.readPluginList(resolveFilename(SCOPE_PLUGINS)) \ No newline at end of file diff --git a/lib/python/Plugins/SystemPlugins/ViX/images/installable.png b/lib/python/Plugins/SystemPlugins/ViX/images/installable.png new file mode 100644 index 0000000000000000000000000000000000000000..f52b66c25b69d78239d595fd59df2d9f5199f583 GIT binary patch literal 986 zcmV<0110>4P)3kf!tJ2inC>yT(u5)4g8=YjqCDOo4M69}2b zctoI721dYOCc>`v0hVbjr!&=HF9r}u6>%Uj5vGJnVW2ce4VE4;nXE}L70^f1OEhFiVH#4Q|UY9 z6m3&0ZDmmj!+>(eAmq0@8LLXLRY)1Ju$VsK%d4%FbF6OBgz0d{aAMuxZYQBLlbCj3+}Hzwf}Oz(D}>7hz4Oqft74G zs)r^)(K0BJLNG$U!Qgio@qSqPvJeCU+KsJa)nN8O&c@i(tieEy8!WqqxU6u)UoS9X zxy@GXP4Aq|Ay-I8%Mc*rMocLQO*TTUsVfbQJ7_I%AO1~iGr|}XUpxsY08mDZw5G&V zBH8w8Ejaha+FhQG6)7>0zBHtPMxc=f?|3kg8!Od!B?BvVSOXW()nJAtZ2t9W7 z&*7GyTTgFZWaHykyJrgJJOw<%n15dF+v82VzGb%_I&-u#x9XP=&YxrL&v(xE-K&h> z0%QAnRw~ij;_fDEc6@Rhb$=FsOp6n6e|>J-3uXHL+Wnuw-`t|JV6JZ~zW@LL07*qo IM6N<$g1!{a2mk;8 literal 0 HcmV?d00001 diff --git a/lib/python/Plugins/SystemPlugins/ViX/images/installed.png b/lib/python/Plugins/SystemPlugins/ViX/images/installed.png new file mode 100644 index 0000000000000000000000000000000000000000..479088db9cbf128df9192b93e6cea3955c1f6ffe GIT binary patch literal 2055 zcmd^A`9IW&AO0X$n_c&@k|aVzQ6q{RgF%*YG-9@KA3LLoSz>bES90fw1~Vkb8b`v0 zklRS(7!sK^m~xD3HjK~u{vF@v^?KgV>-pjN?RmYQWLq0^q0_&f1^_?^W?>3HQLX<` zfam0*J_|Mj01sem?EpQoAP54YF@WepKsf_AhvCwy=2ndZ6x;y?Hy+g>e(e-tSR0_| z1t@s|itfBuBLwvFB%lR=iZ7t-aRw4DX`Co@GyFVeQ5G7f;#$R};m>^)%YXeO_(<>u z?u`CpacHtEyimsS>3N$pH4pL`J)F?(FcBlXs7aK#S+sjXmK|4?{%eQC*&m+(t&9M`S5^mS03ZS4Y=sVH?!F zUz+7HZHSyZk=@2mTJJ`+IHvVnaxYTzELQg`*ZQOU8n#l?uLOdtHP4;971n&yKi>pj zr=Bvc6ZA?qv>r}m-g;bPn$+n^=2)ck+7-^&WRKWn4|_MTu(eAbMT4&CE&36S1~IKh z@$F{m-6k=OR$2X)8SgFA-r40-><|(>f4w)a{1l4AmJw}wx*3a)Qw6C^Jus#O8#$=8r zBhu~$HX++riLSYZq`73@7nbhDI+&VkIYaIlO}_oC;kDx`8sRN!iM`jtTBW0Vy@| z9%ft9!OV5A{WHgR4J>7Xgwdl5%V6v_*tH7|GQsQ(5V;Kov%%Dp=EG;yrvQKpz`S@mgA{kAG$_de43hG=ApxZ_`__(Ed=i)MJoTwu=ZBI+ zA2h|)Nno&~!mE$u6T0~WxBKmwZ79$ad71khz`ioX+Vvwmo<`Q{A_*HIt-A-*nFC|` z9fd#r*A`JL8b6GD^f%=*%=_u`=JN7S{yDXu7+fkGerT&X4+!LJ4-V`?gIS3?92U}4 zK76N0-@S)U$c{v9;`jDth^iKlV99VCw?bBh?D6INLmA2+m7EOGp2%erCp7=!;!dj! zUG+|`iBLd7iFGb}nMCm(Q=AB#!jkhl4MJ)FhjKmc`*{1`{KM`e?IXWT_`J|LyYIsM z>?Y(pn+;a0T1T;D!bF*W@4dHHJ92$2^?REbmm-IPHld)b~^Rg8Tzv458z#n&-V z-=Y#X(4z9!@`X0Q8JuifPrJ%d8FUB#1uMP7e3!Hm@1V?N?V;FqtPDnZcaBF#<_$Mm?kUK z2CbDEw(T4{`fa8hg+{qRI(ma3S*dbUU9CoQ1Fy9iLxsAMLq;j1zc^Mo)z;0nIpC91 zarYJZ!i_W?*$KkVUH#wQN#GKMid7x2%7fFRP#X(qkwR04bGSggGDX zQGI2)fJt4C%3AomkhHsCQf_aa)n0J& zPEh>%avbj1oOUrmV1GrDWOLxUqt8bZEf{FBD#Xare)_~0$=P^loJ3%R{7mPK!kSHh z)TpvhI%8$|W-6t#8802F?A1tfrH=(};g()WAr2?;m27xz)&{I&XMR>2AD-OE7GVQh o0q$;sq+a&sL&IB$c93TaqCHvj^S?Tsh?7MJU{D*=I%8DKe`?c{LjV8( literal 0 HcmV?d00001 diff --git a/lib/python/Plugins/SystemPlugins/ViX/images/remove.png b/lib/python/Plugins/SystemPlugins/ViX/images/remove.png new file mode 100644 index 0000000000000000000000000000000000000000..28b29c05532d9623cc6fb145bbbe4a7413f98661 GIT binary patch literal 2201 zcmd^>`9IT-1IOQUd?;6<`h18sN6CF36|pRvD~%+#k82s4B<*9;;S6b#RfZ_dB0egl z!;v|1ggM3xi^}GVMvU$K@%=l#ugBx{dOe=MzkYaSxVbvW>{i+h0Due%X^-A%!~a=Q zbSDE@yJ`VI6mWC)Klzi=&W-bdm+2kjn)2#sF$b05lR}_(E30 zSKaEenEo9A7PQZ)9#9VjG(!RPzvWJn04rz<0pwR|ZOW|w77 z;FZyjp{`ll!LOu`U6HpVC?ake;+jroFIy*%8TjVyLnR+@PE&Tf1M|$)^nG+JjAZS1 zQ^n)1ns=TFuF3>khA!K%O=|Icz;L-yrxjeFizzjTD6zO&h0JH$;$Iralw0AePY~Xm zDdpIwHwC@fcFOt`RJMHI0&<2|R=Jq>xO!sGdPM!-XxXp(zWr7`hicy5p9hqD+8pA-p+?$)H``sbB9F8 z%)jD_m0x{#csCO`x|Q=ySjiE5C>t}X;hM1p#T;SnqOgq%R({!fqiu5@5X9qYt*-(wI|D{`2*E*VqP9@QSvxLJmnwUb0 z_)?ZsJce~M0~4ZoR^h->x{(o4KT8*?>m>=xmozeybaoo#K?YqZvEz7F!*5o?l2z65 z!u_nRfTGyzn_uF;#0#fjBB0A&p+r%YZO4FIt4>{{AJ-INKG~Xm>6f6);$_sshHLNo z88$k_*nnuvCSi)ru5S3+xOC{@tEhR&BfmcsLRIgTdoIuJwm3y{EN=H7RpSmCSaieA zETSogU{^n{CeghNHv@m^6@GbYx=oggTYW4q{en^WCc49=jL6jZBr#5X?=b7eN=&QU z=TBgG$;=7PHw8p|c!iP;m@7H*v_lC{50d4NJ}#{sA^(`guFn^$5h~@knk%H8M-EpT zJ{k28wU=9O2nbzOsUJd^nUsw6zkR<24Nn?CsVQ`vd!6GX^pIey@42NUKI3d;+)mp| z7eo7o-?`cyqyp?x;s%h7Zlt>+H_xcV+2)%WDqcCk1jv#QXeWT{f(GLNfJ}pP@lYU4`(I43 z{WNHup(HKry>M}(d2wSg>rrI+U3cu|lH=hDTjNeMils!u5+gsf&b98xDyapHu@Am6 zytAKIpc2PSqMEm&Ewy#--TKGPa$u?XtkXUz{jD;kNN+f5w(m_bz3&AV=RHg4^);J| zfA2>LOHEKHGV_VC_Mw}5&L3&RnL4wONS}G_LlfbUga2A~woG&rLqel(V>`!;MQrBw zc)g^Fp941jIlnHWP+rjZ#Y-9Yweo_3JSwh1u2FF~5eK7oJk!)iig^9#>ZI{k%~MO) z96ydk3<+p$h}%+XZL-yQyNKyxs(n$HcvTWM%44d*wGSeOtA=j{n<$a;RMoV*sT#KB zYjOSV%t_u5@>0%MhTfoQ;xE?y^js(Y1*>}+s+eyb@v2Nzur==bb*%?o_M(AVRx~#a zKvR51?t2P5WoDFm-}yZ;n>ZF)Z)$?^Egj9t7`v@*(qHcMv|wE?o~Ypq{fAUPO9L^-K0u)m2P}`Uu7N)Br?zt;70X z1*}kq!$l*Cv&LZzTOApFYw)d-ky`~CJ`y60ssI2 literal 0 HcmV?d00001 diff --git a/lib/python/Plugins/SystemPlugins/ViX/images/upgrade.png b/lib/python/Plugins/SystemPlugins/ViX/images/upgrade.png new file mode 100644 index 0000000000000000000000000000000000000000..860d3f1360270c67e922bb720b9af58520c354dd GIT binary patch literal 2603 zcmd^=i9geg1INFH#}Qq4a^$8AdvY}Kw47UQm{5+DJ0i@r4H3ETqmeOWVQR@@jvRB} z3N<&mLn!2U^u*-X^LP9{uh-}E`3v5kPolZm4MBc!egFUjQAoJu?^gTIyqv$&X_~JF z06;&?O>ZL>j|#v1s#NtTeAIYRKe`@~)TVElAJV*U9oB7<-X7ltxkvnn&g|2*D6uXc z-8yc=#Ppiw^b5j*)pd!Md8~Vk&#*_;vNoBniSLTW?B;gZU90RQ`Ya&lEG>sm?)VYa zyW!LH?TS@7`Qt9ai#f0#D5FhM(un)SPKP3MF)t^@#Jnx>Ee~5)4KTEOsVwb><+y@T z+ti`%@5P$_G_!{tp1H$-qFcrAmb!NI`f);7?+;zmEaqxM5{tckG#vMKP5~V9bV%}y zL8#=d)aRo|ijL%}r9-f5zA3f=hR%aIz126NkOqye*f~@#qiW`3JWHfp^Lmw$)ax#c zl!14=P~2aCr#fX#LA{DQR~NnOzXW6sAl+-^6>!7__Fq>LgbKNV5O^!F!Lz*PNhL_Q4ua@hu^}S+SVbdB-IThv zzgyI?3W&ttdtT&SI*h`#!H_vz8tLOZ<908{GwK%g9imo_U6AB8O<($DSYp5%IS&%+ zl7ExDxvy;s+PRu-S+bY@VS~^)C4ZMBE)z7smQ%aaknxHI#^eI>ZnjC3pqEpy;4%e8 zJb|`kX_7}`cLiLhckB$KW58eCS*1r7@Xv^3#4Hb_H#S5O~ zF?B$Qfc9t#D0>@KGeB%|N5@nFU=ImI4Al9ll1ea#T4~nMqT$^-;KIE-1gdipO9nd+ z$a|@4g%L|T(uzOe5<4{XDfcPkG8$<`Q{}%ASW&q79}h=(OS4w&#|T-MYFfc=l(Z}d~{jeywH=Ehr2F%EnP<9?e&B8(Pamy z*m!}jmW(%>vvu_mj4t^foYJ*a`duPf#)log;&_VPJEqyCd9|baPm82lJy1{>{)%FP z)d6E8O4?V0=LaDPUb~*o1=`bL#X(Gad31q`w@fsjY1)K`f=b-ErF89Vvh}QMmA%4_ zb^;}P!EfIuWd zc~n9}k4SIw_J}h#2IUxqcRiYm52V$WK2N_m!|kWD1a+Joxqc$PDv?nO9+Iow+o9cT zJ{imw(DxWzCs8=~0;jbGcoKxx{#I#E_S4RfxqQ$@&RyRn0o6U$cEB}l8VZgSEc3s?i9yRwN}JC=_RYi z4y8a|0WrTzrMEeIQd$R7Yep;E!~^hlN>_dPmv(p^Oaf;OT8$y9c^OIiI4zq`L4tL; zeH8?kEPe}-B`6F%+RSk>vMWXgKigto;^u;2y>kFjn3vxt*tV$;Aq*wxx ztg(agigzltAD4I{toMyp$uRPbyv|X?rgP%^}Q_C=^2kx;t=(O2cR6$P5%DE*PwfK zBvFJ?;{vsw4+d*oPxmh8J9*OK0w#;`C~=aTCt`h+h)v#j;mES@o_T7FpB&%LC-D2q zY4<&N@N!5Z>J%hXRgWZl7FMXN2!cOQfD(<}U&O&;4b^Kw%3_oPmsb^o0lGtw2gUaKwO$jKuL$6KnO9;!}Y}M^V2t5vtEaO z(g-Vazc?4AL@Lzr^bC{x(BA=>%*xy;la+rgL(A;V|NaQG!t6FT+I7vC>3i({x+qaL zbvZ`sEcTVecJ^HJHCweO()fjG_+rzr`Iz_=ZB5k-9pWo0Z%|CurgLaNTQv`mJ+R+a zVKM2QouLywF{8?Xfp04AHR?4joI?mDJLd{%y&hB1@%|OPFV{)^y1WK_%W?2(f5Gq7 z(s&A(woa+6c#h4Pog8jqw&*#1=r4Si#YbN3pIa~j=706JPl&E07~9*=@G~yBeYgSK z?z_6erL02FV_kgmm8~AZowQWnY7|HLC;Q=dl!>kO0QddOFTk-RMfP8bITRuCn%5Te Q_w@lNgckt7Dd)G)%id6Vk5lkK zAw&uc9>AfB;kpuh=33~Pt5|{S@e&S|GERkZ4$m}wYj|~{&Kksuny3D0lckC-)d{E+ zHhCmwopI5pMam)9sNhg9Wlqf>ZxGdPmp&k97%XZ33$lM{{l8;xz@tRSMQdS`bNu7ERn-R$!7P;?i^C_Nf z2j10GKiv4u4C1ZqeyjWsmM=!^OD2((RCmIXW7Ui!ZW2{X3nA@d+Lj-V9-~sqeDa!1 zGn)d4+la87sP0vh3W|ijwQ~jeZz`BDxc0bd*p)DjEN+YF{*<){dK0O4vP!P_$N09A z)o)q8{s!j0r@UzIvWb6GIZunk<2|#V82Ec&a8EUTZ^!qP-3YUTYp8ms29fAPR!KIo z<*_d(o@Km?#xIsA-jK;?47*pL9ad-7L4Q#{ljBpa-Mdo|SR)bDELSjLKJ-03c~~la zNF`@PJEPhBEj=) zU^qY)9|($oEQj}F#vm(z&5j1aJP>RFe*z!_4l<2FhUbSdA2#E0Q)39Y2Vrez4h>#mwfvR3gk|C=2tDowoh~@ z0$k)6B>bM0AYJ!LgSByIsKaTYPdq1HEHU(Ac!0W%IUH9U92#Wng*FAJU@WRwdaTC5 zASB#F5{)wUMJl52=zOg_ec#>a^NUloqRZ4I=wt+B00~9kb3I9Zz2Zj_06+k&jfL$A z{+9*V9&*W?{DoE%gu!j&A@q@@l0E4U_lAk=p*zf5kkf`pD9$~3tQ_-(4h~yMKE*N z7|~v|ndUSeNg}o!|2V+5WnQ+`S|`d;?)#li&-jJDP#^R2c)Eqe_OA>2n~z7?At!$( z-89i9qSlYYij{_Qwh-4mV!0Vv-FB@O!O#RHHbrZtd&_NQ@h%O%Q_mIiB>eUELkwfE z?ho5KCi~ab8hm$o)9-K1zI7XTE$$r1ir5pbE?50i{-60I%iv?Azi91sn7*!K1AQ`k z#HCe|bLl$CudKJP3#&2r<$Zry5A`o?rD``;+Vx~ONvnH#vSwt*LV}4B`29=S2({ju zvyw9aUh?>;fAx@GhZT0bOU|j{qa6o-UwpL!z|q;MAzo$!A6f zT`ahWgUebn&A+#P*+e}uO3ZA+AdqzO@*449ZT1g#XB!v4t`1~6yK-b*S==_UFf+%+ zajYrY;p7~)bHqjwTo&d*EXa!El3;r*oh??uKsq>uV9q=B6iEqUOygQ#ku3krOHyp- zw;$_0=U)*X9G8wx*NgUXDh8mvK+0MmW|qbNoSbKw8PcU2ZW7{X-KI$ec*QfQ z#HX#9IpN-{K8Ln&QXDCK=NJ2fJ;qKqDR_TlZ%>z-X^8xCuGoI6G3hI+QlB}L3qV$$%Ima zPx|jaPLoH^`wx|8In>3rM{n)_#LMXNH6}dm*nT0(?o3e-nVtO_dH4`p$lCopQ-tAa zwJ28eauO)$DwciTyy7*0uSVByFHI2-=eBhI*q3dyDAx8E*ET)Nn~wD-Yw4#uo6UWk z9jx)#$(m!7(7i^R1skSDd-5fXYLsQ$%4`VpD_HI2Hrr z2ngm0vqop!~av@aN&nk6ym1U$X5o@ne|D{m+q%>;Mp2ZJy nC%sH8DoTW$zVQa7=>q^pQ%>hZ*0?{MG&*2nWPzwNbWQjlf>xYl literal 0 HcmV?d00001 diff --git a/lib/python/Plugins/SystemPlugins/ViX/ui.py b/lib/python/Plugins/SystemPlugins/ViX/ui.py index f7cee81dcd1..fffac38c1d5 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/ui.py +++ b/lib/python/Plugins/SystemPlugins/ViX/ui.py @@ -61,6 +61,8 @@ def __init__(self, session, args=0): self.list.append(("mount-manager", _("Mount manager"), _("Manage your devices mount points."), None)) self.list.append(("script-runner", _("Script runner"), _("Run your shell scripts."), None)) self.list.append(("swap-manager", _("SWAP manager"), _("Create and Manage your SWAP files."), None)) + if config.usage.setup_level.index > 1: # expert+ + self.list.append(("package-manager", _("Package manager"), _("Advanced management of software packages."), None)) if SystemInfo["HasH9SD"]: self.list.append(("H9SDcard manager", _("H9SDcard Manager"), _("Move Nand root to SD card"), None)) self["menu"] = List(self.list) @@ -139,6 +141,9 @@ def go(self, num=None): elif currentEntry == "swap-manager": from .SwapManager import VIXSwap self.session.open(VIXSwap) + elif currentEntry == "package-manager": + from .PackageManager import PackageManager + self.session.open(PackageManager) def closeRecursive(self): self.close(True) From 007390aab54b1a0d070d0533ce6b9c46a00ce07b Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Fri, 12 Jan 2024 11:50:11 +0000 Subject: [PATCH 029/183] PEP8 double aggressive E225 ~ E228 and E231 --- .../Plugins/SystemPlugins/ViX/PackageManager.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py index 66a40c3a462..57c1baeaf30 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py +++ b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py @@ -68,18 +68,18 @@ class PackageManager(Screen, NumericalTextInput): """, - 530, 420, # Screen - 0, 0, 140, 40, # colours + 530, 420, # Screen + 0, 0, 140, 40, # colours 140, 0, 140, 40, 0, 0, 140, 40, 20, 140, 0, 140, 40, 20, - 5, 50, 520, 365, # list - 5, 1, 440, 28, # template + 5, 50, 520, 365, # list + 5, 1, 440, 28, # template 5, 26, 440, 20, 445, 2, 48, 48, 5, 50, 510, 2, - 22, 14, # font - 52, #itemHeight + 22, 14, # font + 52, # itemHeight ] @@ -125,7 +125,7 @@ def __init__(self, session): self.cmdList = [] self.cachelist = [] self.cache_ttl = 86400 #600 is default, 0 disables, Seconds cache is considered valid (24h should be ok for caching opkgs) - self.cache_file = "/etc/enigma2/packetmanager.cache" #Path to cache directory + self.cache_file = "/etc/enigma2/packetmanager.cache" # Path to cache directory self.oktext = _("\nAfter pressing OK, please wait!") self.unwanted_extensions = ("-dbg", "-dev", "-doc", "-staticdev", "-src", "busybox") From d81eb4e63d5c7baec5f439273f6a6cfaddf14145 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Fri, 12 Jan 2024 11:50:21 +0000 Subject: [PATCH 030/183] PEP8 double aggressive E301 ~ E306 --- lib/python/Plugins/SystemPlugins/ViX/PackageManager.py | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py index 57c1baeaf30..898f8e801bf 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py +++ b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py @@ -82,7 +82,6 @@ class PackageManager(Screen, NumericalTextInput): 52, # itemHeight ] - # TODO, skin scale def __init__(self, session): From dfc0ed8278f1f4ebd0d901d27cf358ba8788ea33 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Fri, 12 Jan 2024 11:50:32 +0000 Subject: [PATCH 031/183] PEP8 double aggressive W291 ~ W293 and W391 --- lib/python/Plugins/SystemPlugins/ViX/PackageManager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py index 898f8e801bf..c42c707ad8a 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py +++ b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py @@ -81,7 +81,7 @@ class PackageManager(Screen, NumericalTextInput): 22, 14, # font 52, # itemHeight ] - + # TODO, skin scale def __init__(self, session): @@ -376,4 +376,4 @@ def buildPacketList(self): self["list"].setList(self.list) def reloadPluginlist(self): - plugins.readPluginList(resolveFilename(SCOPE_PLUGINS)) \ No newline at end of file + plugins.readPluginList(resolveFilename(SCOPE_PLUGINS)) From 3e5d3defbaceb21f1bbe62cff85228dd913a1f10 Mon Sep 17 00:00:00 2001 From: Orlandoxx <95180049+Orlandoxx@users.noreply.github.com> Date: Sat, 13 Jan 2024 15:20:59 +0200 Subject: [PATCH 032/183] Updated Finnish (fi.po) translation. Added new 'Package Manager' translations. --- po/fi.po | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/po/fi.po b/po/fi.po index f23a9aeabb4..d5779b91f17 100644 --- a/po/fi.po +++ b/po/fi.po @@ -5,7 +5,7 @@ msgstr "" "Project-Id-Version: enigma2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-12-27 23:35+0000\n" -"PO-Revision-Date: 2024-01-07 14:10+0200\n" +"PO-Revision-Date: 2024-01-13 15:19+0200\n" "Last-Translator: Orlandox\n" "Language-Team: timoj/Kojo/Samzam/Orlandox\n" "Language: fi\n" @@ -2172,7 +2172,7 @@ msgid "An empty filename is illegal." msgstr "Tyhjä nimi ei ole sallittu." msgid "An error occurred while downloading the packetlist. Please try again." -msgstr "Tapahtui virhe pakettiluetteloa ladattaessa. Yritä uudestaan." +msgstr "Tapahtui virhe pakettilistaa ladattaessa. Yritä uudestaan." msgid "An unknown error occurred!" msgstr "Tuntematon virhe!" @@ -13543,7 +13543,7 @@ msgstr "" "Suomenkielinen käännös: timoj, Kojo, Samzam, Orlandox\n" "\n" "Ylläpito : Orlandox\n" -"07.01.2024\n" +"13.01.2024\n" "http://www.huoltovalikko.com" msgid "TS file is too large for ISO9660 level 1!" @@ -19308,3 +19308,21 @@ msgstr "Haluatko varmuuskopioida eMMC-paikat? Tämä lisää 1 - 5 minuuttia eMM msgid "Copy eMMC slots confirmation" msgstr "eMMC-paikkojen kopioinnin vahvistus" + +msgid "Package manager" +msgstr "Ohjelmistopaketin hallinnointi" + +msgid "Refresh list" +msgstr "Päivitä lista" + +msgid "Downloading a new packet list. Please wait..." +msgstr "Ladataan uutta pakettilistaa. Odota..." + +msgid "Removal has completed." +msgstr "Poistaminen on valmis." + +msgid "Update has completed." +msgstr "Päivitys on valmis." + +msgid "Advanced management of software packages." +msgstr "Ohjelmistopakettien edistynyt hallinnointi." From 1c648d7c2f4cace7c16feaf0422d057dd8cea140 Mon Sep 17 00:00:00 2001 From: openvix-build Date: Sun, 14 Jan 2024 22:53:03 +0000 Subject: [PATCH 033/183] openvix: developer 6.4.012.002 --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index ef884233c09..f22e87a6aed 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1231,3 +1231,4 @@ openvix: developer 6.4.011.010 openvix: developer 6.4.011.011 openvix: developer 6.4.011.012 openvix: developer 6.4.012.001 +openvix: developer 6.4.012.002 From 466eaf170c6698fb59f6afb0dcfdfe9f37a360f7 Mon Sep 17 00:00:00 2001 From: Huevos Date: Mon, 15 Jan 2024 01:24:24 +0100 Subject: [PATCH 034/183] [PackageManager] remove comment --- lib/python/Plugins/SystemPlugins/ViX/PackageManager.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py index c42c707ad8a..64553a424ca 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py +++ b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py @@ -82,8 +82,6 @@ class PackageManager(Screen, NumericalTextInput): 52, # itemHeight ] - # TODO, skin scale - def __init__(self, session): Screen.__init__(self, session) NumericalTextInput.__init__(self) From b4fd236ff3ad04dda79552015d5a05468c68a016 Mon Sep 17 00:00:00 2001 From: Huevos Date: Mon, 15 Jan 2024 01:06:45 +0100 Subject: [PATCH 035/183] [SoftwareUpdate] make package list viewable --- lib/python/Screens/SoftwareUpdate.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/python/Screens/SoftwareUpdate.py b/lib/python/Screens/SoftwareUpdate.py index ea408bb8cde..112f146877f 100644 --- a/lib/python/Screens/SoftwareUpdate.py +++ b/lib/python/Screens/SoftwareUpdate.py @@ -17,7 +17,9 @@ from Components.OnlineUpdateCheck import feedsstatuscheck, kernelMismatch, statusMessage from Screens.ParentalControlSetup import ProtectedScreen from Screens.Screen import Screen +from Screens.TextBox import TextBox from Screens.Standby import TryQuitMainloop +from Tools.BoundFunction import boundFunction from Tools.Directories import isPluginInstalled ocram = '' @@ -285,6 +287,7 @@ def ipkgCallback(self, event, param): if not config.softwareupdate.autoimagebackup.value and config.imagemanager.backuplocation.value: choices.append((_("Perform a full image backup"), "imagebackup")) choices.append((_("Update channel list only"), "channels")) + choices.append((_("Show packages to be updated"), "showlist")) choices.append((_("Cancel"), "")) self["actions"].setEnabled(True) upgrademessage = self.session.openWithCallback(self.startActualUpgrade, UpdateChoices, text=message, list=choices, skin_name="SoftwareUpdateChoices", var=self.trafficLight) @@ -362,6 +365,9 @@ def startActualUpgrade(self, answer): self["actions"].setEnabled(True) upgrademessage = self.session.openWithCallback(self.startActualUpgrade, UpdateChoices, text=message, list=choices, skin_name="SoftwareUpdateChoices", var=self.trafficLight) upgrademessage.setTitle(self.getTitle()) + elif answer[1] == "showlist": + text = "\n".join([x[0] for x in sorted(self.ipkg.getFetchedList(), key=lambda d: d[0])]) + self.session.openWithCallback(boundFunction(self.ipkgCallback, IpkgComponent.EVENT_DONE, None), TextBox, text, _("Packages to update"), True) elif answer[1] == "changes": self.session.openWithCallback(self.startActualUpgrade, SoftwareUpdateChanges) elif answer[1] == "backup": From 3864e02351329c6de21115620a6985ca714b1bde Mon Sep 17 00:00:00 2001 From: Orlandoxx <95180049+Orlandoxx@users.noreply.github.com> Date: Mon, 15 Jan 2024 07:52:42 +0200 Subject: [PATCH 036/183] Updated Finnish (fi.po) translation. Added more 'package manager' translations. --- po/fi.po | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/po/fi.po b/po/fi.po index d5779b91f17..98428626c25 100644 --- a/po/fi.po +++ b/po/fi.po @@ -5,7 +5,7 @@ msgstr "" "Project-Id-Version: enigma2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-12-27 23:35+0000\n" -"PO-Revision-Date: 2024-01-13 15:19+0200\n" +"PO-Revision-Date: 2024-01-15 06:58+0200\n" "Last-Translator: Orlandox\n" "Language-Team: timoj/Kojo/Samzam/Orlandox\n" "Language: fi\n" @@ -13543,7 +13543,7 @@ msgstr "" "Suomenkielinen käännös: timoj, Kojo, Samzam, Orlandox\n" "\n" "Ylläpito : Orlandox\n" -"13.01.2024\n" +"--- 15.01.2024 ---\n" "http://www.huoltovalikko.com" msgid "TS file is too large for ISO9660 level 1!" @@ -19326,3 +19326,9 @@ msgstr "Päivitys on valmis." msgid "Advanced management of software packages." msgstr "Ohjelmistopakettien edistynyt hallinnointi." + +msgid "Show packages to be updated" +msgstr "Näytä päivitettävät ohjelmistopaketit" + +msgid "Packages to update" +msgstr "Päivitettävät ohjelmistopaketit" From 4ee7ffb69a155008d7cbeadb2a2d1dce23d0bec4 Mon Sep 17 00:00:00 2001 From: Huevos Date: Mon, 15 Jan 2024 12:49:41 +0100 Subject: [PATCH 037/183] [PackageManager] update location --- lib/python/Plugins/SystemPlugins/ViX/plugin.py | 14 +++++++++++++- lib/python/Plugins/SystemPlugins/ViX/ui.py | 5 ----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/lib/python/Plugins/SystemPlugins/ViX/plugin.py b/lib/python/Plugins/SystemPlugins/ViX/plugin.py index b0353113d59..5d815ccf885 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/plugin.py +++ b/lib/python/Plugins/SystemPlugins/ViX/plugin.py @@ -105,6 +105,17 @@ def SoftcamSetup(menuid): return [] +def PackageManagerMenu(session, **kwargs): + from .PackageManager import PackageManager + session.open(PackageManager) + + +def PackageManagerSetup(menuid): + if config.usage.setup_level.index > 1 and menuid == "softwareupdatemenu": + return [(_("Package Manager"), PackageManagerMenu, "packagemanager", 1005)] + return [] + + def BackupManager(session): from .BackupManager import VIXBackupManager return VIXBackupManager(session) @@ -193,7 +204,8 @@ def Plugins(**kwargs): plist = [ PluginDescriptor(where=PluginDescriptor.WHERE_MENU, needsRestart=False, fnc=startSetup), PluginDescriptor(name=_("ViX Image Management"), where=PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=UpgradeMain), - PluginDescriptor(where=PluginDescriptor.WHERE_MENU, fnc=SoftcamSetup)] + PluginDescriptor(where=PluginDescriptor.WHERE_MENU, fnc=SoftcamSetup), + PluginDescriptor(where=PluginDescriptor.WHERE_MENU, fnc=PackageManagerSetup)] if config.softcammanager.showinextensions.value: plist.append(PluginDescriptor(name=_("Softcam manager"), where=PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=SoftcamMenu)) if config.scriptrunner.showinextensions.value: diff --git a/lib/python/Plugins/SystemPlugins/ViX/ui.py b/lib/python/Plugins/SystemPlugins/ViX/ui.py index fffac38c1d5..f7cee81dcd1 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/ui.py +++ b/lib/python/Plugins/SystemPlugins/ViX/ui.py @@ -61,8 +61,6 @@ def __init__(self, session, args=0): self.list.append(("mount-manager", _("Mount manager"), _("Manage your devices mount points."), None)) self.list.append(("script-runner", _("Script runner"), _("Run your shell scripts."), None)) self.list.append(("swap-manager", _("SWAP manager"), _("Create and Manage your SWAP files."), None)) - if config.usage.setup_level.index > 1: # expert+ - self.list.append(("package-manager", _("Package manager"), _("Advanced management of software packages."), None)) if SystemInfo["HasH9SD"]: self.list.append(("H9SDcard manager", _("H9SDcard Manager"), _("Move Nand root to SD card"), None)) self["menu"] = List(self.list) @@ -141,9 +139,6 @@ def go(self, num=None): elif currentEntry == "swap-manager": from .SwapManager import VIXSwap self.session.open(VIXSwap) - elif currentEntry == "package-manager": - from .PackageManager import PackageManager - self.session.open(PackageManager) def closeRecursive(self): self.close(True) From 7562b83fe223c266ae958aa753bb96adae6f5df3 Mon Sep 17 00:00:00 2001 From: openvix-build Date: Mon, 15 Jan 2024 12:07:24 +0000 Subject: [PATCH 038/183] openvix: developer 6.4.012.003 --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index f22e87a6aed..c7ce05d7d73 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1232,3 +1232,4 @@ openvix: developer 6.4.011.011 openvix: developer 6.4.011.012 openvix: developer 6.4.012.001 openvix: developer 6.4.012.002 +openvix: developer 6.4.012.003 From 570f83c848c1d11aa6bc2729d519275ac825e01b Mon Sep 17 00:00:00 2001 From: Orlandoxx <95180049+Orlandoxx@users.noreply.github.com> Date: Mon, 15 Jan 2024 17:48:50 +0200 Subject: [PATCH 039/183] Updated Finnish (fi.po) translation. Changes to Package Manager. --- po/fi.po | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/po/fi.po b/po/fi.po index 98428626c25..73c0d413a7c 100644 --- a/po/fi.po +++ b/po/fi.po @@ -5,7 +5,7 @@ msgstr "" "Project-Id-Version: enigma2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-12-27 23:35+0000\n" -"PO-Revision-Date: 2024-01-15 06:58+0200\n" +"PO-Revision-Date: 2024-01-15 17:42+0200\n" "Last-Translator: Orlandox\n" "Language-Team: timoj/Kojo/Samzam/Orlandox\n" "Language: fi\n" @@ -19310,7 +19310,10 @@ msgid "Copy eMMC slots confirmation" msgstr "eMMC-paikkojen kopioinnin vahvistus" msgid "Package manager" -msgstr "Ohjelmistopaketin hallinnointi" +msgstr "Ohjelmistopakettien hallinnointi" + +msgid "Package Manager" +msgstr "Ohjelmistopakettien hallinnointi" msgid "Refresh list" msgstr "Päivitä lista" @@ -19324,9 +19327,6 @@ msgstr "Poistaminen on valmis." msgid "Update has completed." msgstr "Päivitys on valmis." -msgid "Advanced management of software packages." -msgstr "Ohjelmistopakettien edistynyt hallinnointi." - msgid "Show packages to be updated" msgstr "Näytä päivitettävät ohjelmistopaketit" From d64ef6679ea1c63e29e965ee6a69c52acbe04216 Mon Sep 17 00:00:00 2001 From: Huevos Date: Tue, 16 Jan 2024 13:19:35 +0100 Subject: [PATCH 040/183] [InfoBar] when opening MovieSelection skip calling timeshiftEnabled() Needs further testing. --- lib/python/Screens/InfoBar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/Screens/InfoBar.py b/lib/python/Screens/InfoBar.py index 3432b569c39..b847b1f59a5 100644 --- a/lib/python/Screens/InfoBar.py +++ b/lib/python/Screens/InfoBar.py @@ -212,7 +212,7 @@ def showMovies(self, defaultRef=None): self.lastservice = self.session.nav.getCurrentlyPlayingServiceOrGroup() if self.lastservice and ':0:/' in self.lastservice.toString(): self.lastservice = enigma.eServiceReference(config.movielist.curentlyplayingservice.value) - self.session.openWithCallback(self.movieSelected, Screens.MovieSelection.MovieSelection, defaultRef or enigma.eServiceReference(config.usage.last_movie_played.value), timeshiftEnabled=self.timeshiftEnabled()) + self.session.openWithCallback(self.movieSelected, Screens.MovieSelection.MovieSelection, defaultRef or enigma.eServiceReference(config.usage.last_movie_played.value)) # , timeshiftEnabled=self.timeshiftEnabled()) # skip running stat here for no reason def movieSelected(self, service): ref = self.lastservice From d036b7527254ee8f2194510c5e4028215fbb20d5 Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Sat, 13 Jan 2024 13:42:01 +0200 Subject: [PATCH 041/183] [Added] Possibility SelectionList to be controlled from skin per widget --- lib/python/Components/SelectionList.py | 36 +++++++++++++++++++------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/lib/python/Components/SelectionList.py b/lib/python/Components/SelectionList.py index af8ae747fa8..fc12f5eeaf3 100644 --- a/lib/python/Components/SelectionList.py +++ b/lib/python/Components/SelectionList.py @@ -9,8 +9,8 @@ selectionoffpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "icons/lock_off.png")) -def SelectionEntryComponent(description, value, index, selected): - dx, dy, dw, dh = parameters.get("SelectionListDescr", applySkinFactor(25, 5, 650, 30)) +def SelectionEntryComponent(description, value, index, selected, selectionListDescr=parameters.get("SelectionListDescr", applySkinFactor(25, 3, 650, 30))): + dx, dy, dw, dh = selectionListDescr res = [ (description, value, index, selected), (eListboxPythonMultiContent.TYPE_TEXT, dx, dy, dw, dh, 0, RT_HALIGN_LEFT, description) @@ -30,16 +30,17 @@ def __init__(self, list=None, enableWrapAround=False): font = fonts.get("SelectionList", applySkinFactor("Regular", 20, 30)) self.l.setFont(0, gFont(font[0], font[1])) self.l.setItemHeight(font[2]) + self.selectionListDescr = parameters.get("SelectionListDescr", applySkinFactor(25, 3, 650, 30)) def addSelection(self, description, value, index, selected=True): - self.list.append(SelectionEntryComponent(description, value, index, selected)) + self.list.append(SelectionEntryComponent(description, value, index, selected, self.selectionListDescr)) self.setList(self.list) def toggleSelection(self): - if len(self.list) > 0: + if len(self.list): idx = self.getSelectedIndex() item = self.list[idx][0] - self.list[idx] = SelectionEntryComponent(item[0], item[1], item[2], not item[3]) + self.list[idx] = SelectionEntryComponent(item[0], item[1], item[2], not item[3], self.selectionListDescr) self.setList(self.list) def getSelectionsList(self): @@ -48,7 +49,7 @@ def getSelectionsList(self): def toggleAllSelection(self): for idx, item in enumerate(self.list): item = self.list[idx][0] - self.list[idx] = SelectionEntryComponent(item[0], item[1], item[2], not item[3]) + self.list[idx] = SelectionEntryComponent(item[0], item[1], item[2], not item[3], self.selectionListDescr) self.setList(self.list) def removeSelection(self, item): @@ -62,7 +63,7 @@ def toggleItemSelection(self, item): for idx, i in enumerate(self.list): if i[0][0:3] == item[0:3]: item = self.list[idx][0] - self.list[idx] = SelectionEntryComponent(item[0], item[1], item[2], not item[3]) + self.list[idx] = SelectionEntryComponent(item[0], item[1], item[2], not item[3], self.selectionListDescr) self.setList(self.list) return @@ -75,5 +76,22 @@ def sort(self, sortType=False, flag=False): self.list.sort(key=lambda x: x[0][sortType], reverse=flag) self.setList(self.list) - def len(self): - return len(self.list) + def applySkin(self, desktop, parent): + + def selectionListDescr(value): + self.selectionListDescr = map(int, value.split(",")) + + for (attrib, value) in self.skinAttributes[:]: + try: + locals().get(attrib)(value) + except: + pass + else: + self.skinAttributes.remove((attrib, value)) + + # recreate the list with the new parameters parsed from skin + for x in range(len(self.list)): + description, value, index, selected = self.list[x][0] + self.list[x] = SelectionEntryComponent(description, value, index, selected, self.selectionListDescr) + self.setList(self.list) + return MenuList.applySkin(self, desktop, parent) From 2f161654e96bf1656286d1841bb7474e7190d2d7 Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Sat, 13 Jan 2024 14:10:40 +0200 Subject: [PATCH 042/183] [Fixed] Exception in selection in SelectionList --- lib/python/Components/SelectionList.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/Components/SelectionList.py b/lib/python/Components/SelectionList.py index fc12f5eeaf3..b5f1bcaef92 100644 --- a/lib/python/Components/SelectionList.py +++ b/lib/python/Components/SelectionList.py @@ -79,7 +79,7 @@ def sort(self, sortType=False, flag=False): def applySkin(self, desktop, parent): def selectionListDescr(value): - self.selectionListDescr = map(int, value.split(",")) + self.selectionListDescr = list(map(int, value.split(","))) for (attrib, value) in self.skinAttributes[:]: try: From ce7e54b630e744f831ff1a918ca8055ce2e5da4e Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Wed, 17 Jan 2024 13:23:56 +0200 Subject: [PATCH 043/183] [Fixed] some function definitions and checks --- lib/python/Components/SelectionList.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/python/Components/SelectionList.py b/lib/python/Components/SelectionList.py index b5f1bcaef92..e712c2a53ed 100644 --- a/lib/python/Components/SelectionList.py +++ b/lib/python/Components/SelectionList.py @@ -9,8 +9,8 @@ selectionoffpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "icons/lock_off.png")) -def SelectionEntryComponent(description, value, index, selected, selectionListDescr=parameters.get("SelectionListDescr", applySkinFactor(25, 3, 650, 30))): - dx, dy, dw, dh = selectionListDescr +def SelectionEntryComponent(description, value, index, selected, selectionListDescr=None): + dx, dy, dw, dh = parameters.get("SelectionListDescr", applySkinFactor(25, 3, 650, 30)) if selectionListDescr is None else selectionListDescr res = [ (description, value, index, selected), (eListboxPythonMultiContent.TYPE_TEXT, dx, dy, dw, dh, 0, RT_HALIGN_LEFT, description) @@ -37,7 +37,7 @@ def addSelection(self, description, value, index, selected=True): self.setList(self.list) def toggleSelection(self): - if len(self.list): + if self.list: idx = self.getSelectedIndex() item = self.list[idx][0] self.list[idx] = SelectionEntryComponent(item[0], item[1], item[2], not item[3], self.selectionListDescr) From e92798decd03602cc7ec1f7b88e293c2b9558bc0 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Wed, 17 Jan 2024 11:28:10 +0000 Subject: [PATCH 044/183] PEP8 double aggressive W291 ~ W293 and W391 --- lib/python/Components/SelectionList.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/Components/SelectionList.py b/lib/python/Components/SelectionList.py index e712c2a53ed..6cfeb3eac11 100644 --- a/lib/python/Components/SelectionList.py +++ b/lib/python/Components/SelectionList.py @@ -88,7 +88,7 @@ def selectionListDescr(value): pass else: self.skinAttributes.remove((attrib, value)) - + # recreate the list with the new parameters parsed from skin for x in range(len(self.list)): description, value, index, selected = self.list[x][0] From 9685b8c2b92b8b00c5815fa9f8af144569bcd980 Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Wed, 17 Jan 2024 13:38:21 +0200 Subject: [PATCH 045/183] [Added] Native rounded corners rendering and border support for widgets *** Feature and code based on https://github.com/openatv/enigma2/commit/96719cad359d945ed69554b51362b5a2aa2f9348. Thanks to @jbleyel --- lib/gdi/Makefile.inc | 2 + lib/gdi/drawing.cpp | 2043 ++++++++++++++++++++++++++++++++++++ lib/gdi/drawing.h | 67 ++ lib/gdi/gpixmap.cpp | 1219 ++++++++++++++++++++- lib/gdi/gpixmap.h | 139 ++- lib/gdi/grc.cpp | 440 +++++--- lib/gdi/grc.h | 127 ++- lib/gui/ewidget.cpp | 90 +- lib/gui/ewidget.h | 36 + lib/gui/ewidgetdesktop.cpp | 6 +- lib/gui/ewidgetdesktop.h | 2 +- lib/gui/ewindow.cpp | 7 + lib/gui/ewindow.h | 1 + lib/python/skin.py | 34 +- 14 files changed, 4042 insertions(+), 171 deletions(-) create mode 100644 lib/gdi/drawing.cpp create mode 100644 lib/gdi/drawing.h diff --git a/lib/gdi/Makefile.inc b/lib/gdi/Makefile.inc index 4a3f49fe9d0..3644a8aee6e 100644 --- a/lib/gdi/Makefile.inc +++ b/lib/gdi/Makefile.inc @@ -6,6 +6,7 @@ gdi_libenigma_gdi_a_SOURCES = \ gdi/accel.cpp \ gdi/bcm.cpp \ gdi/compositing.cpp \ + gdi/drawing.cpp \ gdi/epng.cpp \ gdi/erect.cpp \ gdi/fb.cpp \ @@ -27,6 +28,7 @@ gdiincludedir = $(pkgincludedir)/lib/gdi gdiinclude_HEADERS = \ gdi/accel.h \ gdi/compositing.h \ + gdi/drawing.h \ gdi/epng.h \ gdi/epoint.h \ gdi/erect.h \ diff --git a/lib/gdi/drawing.cpp b/lib/gdi/drawing.cpp new file mode 100644 index 00000000000..aa97f6ce696 --- /dev/null +++ b/lib/gdi/drawing.cpp @@ -0,0 +1,2043 @@ +/* +Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License + +Copyright (c) 2023-2024 openATV + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +1. Non-Commercial Use: You may not use the Software or any derivative works + for commercial purposes without obtaining explicit permission from the + copyright holder. +2. Share Alike: If you distribute or publicly perform the Software or any + derivative works, you must do so under the same license terms, and you + must make the source code of any derivative works available to the + public. +3. Attribution: You must give appropriate credit to the original author(s) + of the Software by including a prominent notice in your derivative works. +THE SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, +ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more details about the CC BY-NC-SA 4.0 License, please visit: +https://creativecommons.org/licenses/by-nc-sa/4.0/ +*/ + +#include +#include + +uint32_t *createGradientBuffer3(int graSize, const std::vector &colors) +{ + uint32_t *gradientBuf = (uint32_t *)malloc(graSize * sizeof(uint32_t)); + + uint32_t start_col = colors.at(0).argb(); + uint32_t mid_col = colors.at(1).argb(); + uint32_t end_col = colors.at(2).argb(); + + start_col ^= 0xFF000000; + mid_col ^= 0xFF000000; + end_col ^= 0xFF000000; + + uint8_t start_a = (uint8_t)((start_col & 0xFF000000) >> 24); + uint8_t start_r = (uint8_t)((start_col & 0x00FF0000) >> 16); + uint8_t start_g = (uint8_t)((start_col & 0x0000FF00) >> 8); + uint8_t start_b = (uint8_t)(start_col & 0x000000FF); + + uint8_t mid_a = (uint8_t)((mid_col & 0xFF000000) >> 24); + uint8_t mid_r = (uint8_t)((mid_col & 0x00FF0000) >> 16); + uint8_t mid_g = (uint8_t)((mid_col & 0x0000FF00) >> 8); + uint8_t mid_b = (uint8_t)(mid_col & 0x000000FF); + + uint8_t end_a = (uint8_t)((end_col & 0xFF000000) >> 24); + uint8_t end_r = (uint8_t)((end_col & 0x00FF0000) >> 16); + uint8_t end_g = (uint8_t)((end_col & 0x0000FF00) >> 8); + uint8_t end_b = (uint8_t)(end_col & 0x000000FF); + + float steps = (float)graSize; + float aStep1 = (float)(mid_a - start_a) / (steps / 2); + float rStep1 = (float)(mid_r - start_r) / (steps / 2); + float gStep1 = (float)(mid_g - start_g) / (steps / 2); + float bStep1 = (float)(mid_b - start_b) / (steps / 2); + + float aStep2 = (float)(end_a - mid_a) / (steps / 2); + float rStep2 = (float)(end_r - mid_r) / (steps / 2); + float gStep2 = (float)(end_g - mid_g) / (steps / 2); + float bStep2 = (float)(end_b - mid_b) / (steps / 2); + + if (gradientBuf != NULL) + { + for (int x = 0; x < graSize; x++) + { + uint8_t a, r, g, b; + if (x < graSize / 2) + { + a = (uint8_t)(start_a + aStep1 * x); + r = (uint8_t)(start_r + rStep1 * x); + g = (uint8_t)(start_g + gStep1 * x); + b = (uint8_t)(start_b + bStep1 * x); + } + else + { + a = (uint8_t)(mid_a + aStep2 * (x - graSize / 2)); + r = (uint8_t)(mid_r + rStep2 * (x - graSize / 2)); + g = (uint8_t)(mid_g + gStep2 * (x - graSize / 2)); + b = (uint8_t)(mid_b + bStep2 * (x - graSize / 2)); + } + gradientBuf[x] = (((uint32_t)a << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | (uint32_t)b); + } + } + return gradientBuf; +} + +uint32_t *createGradientBuffer2(int graSize, const gRGB &startColor, const gRGB &endColor) +{ + uint32_t *gradientBuf = (uint32_t *)malloc(graSize * sizeof(uint32_t)); + + uint32_t start_col = startColor.argb(); + start_col ^= 0xFF000000; + + uint32_t end_col = endColor.argb(); + end_col ^= 0xFF000000; + + uint8_t start_a = (uint8_t)((start_col & 0xFF000000) >> 24); + uint8_t start_r = (uint8_t)((start_col & 0x00FF0000) >> 16); + uint8_t start_g = (uint8_t)((start_col & 0x0000FF00) >> 8); + uint8_t start_b = (uint8_t)(start_col & 0x000000FF); + + uint8_t end_a = (uint8_t)((end_col & 0xFF000000) >> 24); + uint8_t end_r = (uint8_t)((end_col & 0x00FF0000) >> 16); + uint8_t end_g = (uint8_t)((end_col & 0x0000FF00) >> 8); + uint8_t end_b = (uint8_t)(end_col & 0x000000FF); + + float steps = (float)graSize; + float aStep = (float)(end_a - start_a) / steps; + float rStep = (float)(end_r - start_r) / steps; + float gStep = (float)(end_g - start_g) / steps; + float bStep = (float)(end_b - start_b) / steps; + + if (gradientBuf != nullptr) + { + for (int x = 0; x < graSize; x++) + { + uint8_t a = (uint8_t)(start_a + aStep * x); + uint8_t r = (uint8_t)(start_r + rStep * x); + uint8_t g = (uint8_t)(start_g + gStep * x); + uint8_t b = (uint8_t)(start_b + bStep * x); + gradientBuf[x] = ((uint32_t)a << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | (uint32_t)b; + } + } + return gradientBuf; +} + +static void blendPixelRounded(uint32_t *dst, const uint32_t *src, const double alpha) +{ + if (!((*src) & 0xFF000000)) + return; + + uint8_t r = (*src >> 24) & 0xFF; + uint8_t g = (*src >> 16) & 0xFF; + uint8_t b = (*src >> 8) & 0xFF; + uint8_t a = (*src >> 0) & 0xFF; + + // Apply alpha blending + uint8_t newR = r * alpha; + uint8_t newG = g * alpha; + uint8_t newB = b * alpha; + uint8_t newA = a * alpha; + + // Combine the new color with the existing pixel color using alpha blending + uint8_t oldR = (*dst >> 24) & 0xFF; + uint8_t oldG = (*dst >> 16) & 0xFF; + uint8_t oldB = (*dst >> 8) & 0xFF; + uint8_t oldA = (*dst >> 0) & 0xFF; + + uint8_t finalR = newR + oldR * (1 - alpha); + uint8_t finalG = newG + oldG * (1 - alpha); + uint8_t finalB = newB + oldB * (1 - alpha); + uint8_t finalA = newA + oldA * (1 - alpha); + + *dst = (finalR << 24) | (finalG << 16) | (finalB << 8) | finalA; +} + +void drawAngleTl(gUnmanagedSurface *surface, const uint32_t *src, const eRect &area, uint8_t direction, const eRect &cornerRect, const CornerData &cornerData) +{ + double alpha = 1.0; + int dx = 0, dy = 0, squared_dst = 0; + const std::unordered_map &radiusData = cornerData.RadiusData; + const int aLeft = area.left(); + const int aTop = area.top(); + const int rLeft = cornerRect.left(); + const int rRight = cornerRect.right(); + const int rTop = cornerRect.top(); + const int rBottom = cornerRect.bottom(); + for (int y = rTop; y < rBottom; y++) + { + int yInOriginalArea = y - aTop; + uint32_t *dst = (uint32_t *)(((uint8_t *)surface->data) + y * surface->stride + rLeft * surface->bypp); + + for (int x = rLeft; x < rRight; x++) + { + int xInOriginalArea = x - aLeft; + dx = cornerData.topLeftCornerRadius - xInOriginalArea - 1 + cornerData.borderWidth; + dy = cornerData.topLeftCornerRadius - yInOriginalArea - 1 + cornerData.borderWidth; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.topLeftCornerDRadius) + { + const uint32_t *s = src + (direction == 1 ? yInOriginalArea : xInOriginalArea); + *dst = *s; + ++dst; + continue; + } + else if (squared_dst < cornerData.topLeftCornerSRadius) + { + const uint32_t *s = src + (direction == 1 ? yInOriginalArea : xInOriginalArea); + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, s, alpha); + } + ++dst; + } + } +} + +void drawAngleTr(gUnmanagedSurface *surface, const uint32_t *src, const eRect &area, uint8_t direction, const eRect &cornerRect, const CornerData &cornerData) +{ + double alpha = 1.0; + int dx = 0, dy = 0, squared_dst = 0; + const std::unordered_map &radiusData = cornerData.RadiusData; + const int aLeft = area.left(); + const int aTop = area.top(); + const int rLeft = cornerRect.left(); + const int rRight = cornerRect.right(); + const int rTop = cornerRect.top(); + const int rBottom = cornerRect.bottom(); + for (int y = rTop; y < rBottom; y++) + { + int yInOriginalArea = y - aTop; + uint32_t *dst = (uint32_t *)(((uint8_t *)surface->data) + y * surface->stride + rLeft * surface->bypp); + + for (int x = rLeft; x < rRight; x++) + { + int xInOriginalArea = x - aLeft; + dx = xInOriginalArea - cornerData.w_topRightCornerRadius; + dy = cornerData.topRightCornerRadius - yInOriginalArea - 1 + cornerData.borderWidth; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.topRightCornerDRadius) + { + const uint32_t *s = src + (direction == 1 ? yInOriginalArea : xInOriginalArea); + *dst = *s; + ++dst; + continue; + } + else if (squared_dst < cornerData.topRightCornerSRadius) + { + const uint32_t *s = src + (direction == 1 ? yInOriginalArea : xInOriginalArea); + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, s, alpha); + } + ++dst; + } + } +} + +void drawAngleBl(gUnmanagedSurface *surface, const uint32_t *src, const eRect &area, uint8_t direction, const eRect &cornerRect, const CornerData &cornerData) +{ + double alpha = 1.0; + int dx = 0, dy = 0, squared_dst = 0; + const std::unordered_map &radiusData = cornerData.RadiusData; + const int aLeft = area.left(); + const int aTop = area.top(); + const int rLeft = cornerRect.left(); + const int rRight = cornerRect.right(); + const int rTop = cornerRect.top(); + const int rBottom = cornerRect.bottom(); + for (int y = rTop; y < rBottom; y++) + { + int yInOriginalArea = y - aTop; + uint32_t *dst = (uint32_t *)(((uint8_t *)surface->data) + y * surface->stride + rLeft * surface->bypp); + + for (int x = rLeft; x < rRight; x++) + { + int xInOriginalArea = x - aLeft; + dx = cornerData.bottomLeftCornerRadius - xInOriginalArea - 1 + cornerData.borderWidth; + dy = yInOriginalArea - cornerData.h_bottomLeftCornerRadius; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.bottomLeftCornerDRadius) + { + const uint32_t *s = src + (direction == 1 ? yInOriginalArea : xInOriginalArea); + *dst = *s; + ++dst; + continue; + } + else if (squared_dst < cornerData.bottomLeftCornerSRadius) + { + const uint32_t *s = src + (direction == 1 ? yInOriginalArea : xInOriginalArea); + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, s, alpha); + } + ++dst; + } + } +} + +void drawAngleBr(gUnmanagedSurface *surface, const uint32_t *src, const eRect &area, uint8_t direction, const eRect &cornerRect, const CornerData &cornerData) +{ + double alpha = 1.0; + int dx = 0, dy = 0, squared_dst = 0; + const std::unordered_map &radiusData = cornerData.RadiusData; + const int aLeft = area.left(); + const int aTop = area.top(); + const int rLeft = cornerRect.left(); + const int rRight = cornerRect.right(); + const int rTop = cornerRect.top(); + const int rBottom = cornerRect.bottom(); + for (int y = rTop; y < rBottom; y++) + { + int yInOriginalArea = y - aTop; + uint32_t *dst = (uint32_t *)(((uint8_t *)surface->data) + y * surface->stride + rLeft * surface->bypp); + + for (int x = rLeft; x < rRight; x++) + { + int xInOriginalArea = x - aLeft; + dx = xInOriginalArea - cornerData.w_bottomRightCornerRadius; + dy = yInOriginalArea - cornerData.h_bottomRightCornerRadius; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.bottomRightCornerDRadius) + { + const uint32_t *s = src + (direction == 1 ? yInOriginalArea : xInOriginalArea); + *dst = *s; + ++dst; + continue; + } + else if (squared_dst < cornerData.bottomRightCornerSRadius) + { + const uint32_t *s = src + (direction == 1 ? yInOriginalArea : xInOriginalArea); + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, s, alpha); + } + ++dst; + } + } +} + +void drawAngle32Tl(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag) +{ + double alpha = 1.0; + int dx = 0, dy = 0, squared_dst = 0; + const std::unordered_map &radiusData = cornerData.RadiusData; + const int aLeft = area.left(); + const int aTop = area.top(); + const int rLeft = cornerRect.left(); + const int rRight = cornerRect.right(); + const int rTop = cornerRect.top(); + const int rBottom = cornerRect.bottom(); + uint32_t *srcptr = (uint32_t *)pixmap.surface->data; + uint32_t *dstptr = (uint32_t *)surface->data; + + srcptr += (rLeft - aLeft) + (rTop - aTop) * pixmap.surface->stride / 4; + dstptr += rLeft + rTop * surface->stride / 4; + if (flag & gPixmap::blitAlphaTest) + { + for (int y = rTop; y < rBottom; y++) + { + int yInOriginalArea = y - aTop; + uint32_t *src = srcptr; + uint32_t *dst = dstptr; + + for (int x = rLeft; x < rRight; x++) + { + int xInOriginalArea = x - aLeft; + dx = cornerData.topLeftCornerRadius - xInOriginalArea - 1 + cornerData.borderWidth; + dy = cornerData.topLeftCornerRadius - yInOriginalArea - 1 + cornerData.borderWidth; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.topLeftCornerDRadius) + { + if (!((*src) & 0xFF000000)) + { + src++; + dst++; + } + else + *dst++ = *src++; + continue; + } + else if (squared_dst < cornerData.topLeftCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, src, alpha); + } + ++dst; + ++src; + } + srcptr = (uint32_t *)((uint8_t *)srcptr + pixmap.surface->stride); + dstptr = (uint32_t *)((uint8_t *)dstptr + surface->stride); + } + } + else if (flag & gPixmap::blitAlphaBlend) + { + for (int y = rTop; y < rBottom; y++) + { + int yInOriginalArea = y - aTop; + uint32_t *src = srcptr; + uint32_t *dst = dstptr; + + for (int x = rLeft; x < rRight; x++) + { + int xInOriginalArea = x - aLeft; + dx = cornerData.topLeftCornerRadius - xInOriginalArea - 1 + cornerData.borderWidth; + dy = cornerData.topLeftCornerRadius - yInOriginalArea - 1 + cornerData.borderWidth; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.topLeftCornerDRadius) + { + gRGB *gSrc = (gRGB *)src; + gRGB *gDst = (gRGB *)dst; + gDst->b += (((gSrc->b - gDst->b) * gSrc->a) >> 8); + gDst->g += (((gSrc->g - gDst->g) * gSrc->a) >> 8); + gDst->r += (((gSrc->r - gDst->r) * gSrc->a) >> 8); + gDst->a += (((0xFF - gDst->a) * gSrc->a) >> 8); + src++; + dst++; + continue; + } + else if (squared_dst < cornerData.topLeftCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, src, alpha); + } + ++dst; + ++src; + } + srcptr = (uint32_t *)((uint8_t *)srcptr + pixmap.surface->stride); + dstptr = (uint32_t *)((uint8_t *)dstptr + surface->stride); + } + } + else + { + for (int y = rTop; y < rBottom; y++) + { + int yInOriginalArea = y - aTop; + uint32_t *src = srcptr; + uint32_t *dst = dstptr; + + for (int x = rLeft; x < rRight; x++) + { + int xInOriginalArea = x - aLeft; + dx = cornerData.topLeftCornerRadius - xInOriginalArea - 1 + cornerData.borderWidth; + dy = cornerData.topLeftCornerRadius - yInOriginalArea - 1 + cornerData.borderWidth; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.topLeftCornerDRadius) + { + *dst++ = *src++; + continue; + } + else if (squared_dst < cornerData.topLeftCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, src, alpha); + } + ++dst; + ++src; + } + srcptr = (uint32_t *)((uint8_t *)srcptr + pixmap.surface->stride); + dstptr = (uint32_t *)((uint8_t *)dstptr + surface->stride); + } + } +} + +void drawAngle32Tr(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag) +{ + double alpha = 1.0; + int dx = 0, dy = 0, squared_dst = 0; + const std::unordered_map &radiusData = cornerData.RadiusData; + const int aLeft = area.left(); + const int aTop = area.top(); + const int rLeft = cornerRect.left(); + const int rRight = cornerRect.right(); + const int rTop = cornerRect.top(); + const int rBottom = cornerRect.bottom(); + uint32_t *srcptr = (uint32_t *)pixmap.surface->data; + uint32_t *dstptr = (uint32_t *)surface->data; + + srcptr += (rLeft - aLeft) + (rTop - aTop) * pixmap.surface->stride / 4; + dstptr += rLeft + rTop * surface->stride / 4; + if (flag & gPixmap::blitAlphaTest) + { + for (int y = rTop; y < rBottom; y++) + { + int yInOriginalArea = y - aTop; + uint32_t *src = srcptr; + uint32_t *dst = dstptr; + + for (int x = rLeft; x < rRight; x++) + { + int xInOriginalArea = x - aLeft; + dx = xInOriginalArea - cornerData.w_topRightCornerRadius; + dy = cornerData.topRightCornerRadius - yInOriginalArea - 1 + cornerData.borderWidth; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.topRightCornerDRadius) + { + if (!((*src) & 0xFF000000)) + { + src++; + dst++; + } + else + *dst++ = *src++; + continue; + } + else if (squared_dst < cornerData.topRightCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, src, alpha); + } + ++dst; + ++src; + } + srcptr = (uint32_t *)((uint8_t *)srcptr + pixmap.surface->stride); + dstptr = (uint32_t *)((uint8_t *)dstptr + surface->stride); + } + } + else if (flag & gPixmap::blitAlphaBlend) + { + for (int y = rTop; y < rBottom; y++) + { + int yInOriginalArea = y - aTop; + uint32_t *src = srcptr; + uint32_t *dst = dstptr; + + for (int x = rLeft; x < rRight; x++) + { + int xInOriginalArea = x - aLeft; + dx = xInOriginalArea - cornerData.w_topRightCornerRadius; + dy = cornerData.topRightCornerRadius - yInOriginalArea - 1 + cornerData.borderWidth; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.topRightCornerDRadius) + { + gRGB *gSrc = (gRGB *)src; + gRGB *gDst = (gRGB *)dst; + gDst->b += (((gSrc->b - gDst->b) * gSrc->a) >> 8); + gDst->g += (((gSrc->g - gDst->g) * gSrc->a) >> 8); + gDst->r += (((gSrc->r - gDst->r) * gSrc->a) >> 8); + gDst->a += (((0xFF - gDst->a) * gSrc->a) >> 8); + src++; + dst++; + continue; + } + else if (squared_dst < cornerData.topRightCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, src, alpha); + } + ++dst; + ++src; + } + srcptr = (uint32_t *)((uint8_t *)srcptr + pixmap.surface->stride); + dstptr = (uint32_t *)((uint8_t *)dstptr + surface->stride); + } + } + else + { + for (int y = rTop; y < rBottom; y++) + { + int yInOriginalArea = y - aTop; + uint32_t *src = srcptr; + uint32_t *dst = dstptr; + + for (int x = rLeft; x < rRight; x++) + { + int xInOriginalArea = x - aLeft; + dx = xInOriginalArea - cornerData.w_topRightCornerRadius; + dy = cornerData.topRightCornerRadius - yInOriginalArea - 1 + cornerData.borderWidth; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.topRightCornerDRadius) + { + *dst++ = *src++; + continue; + } + else if (squared_dst < cornerData.topRightCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, src, alpha); + } + ++dst; + ++src; + } + srcptr = (uint32_t *)((uint8_t *)srcptr + pixmap.surface->stride); + dstptr = (uint32_t *)((uint8_t *)dstptr + surface->stride); + } + } +} + +void drawAngle32Bl(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag) +{ + double alpha = 1.0; + int dx = 0, dy = 0, squared_dst = 0; + const std::unordered_map &radiusData = cornerData.RadiusData; + const int aLeft = area.left(); + const int aTop = area.top(); + const int rLeft = cornerRect.left(); + const int rRight = cornerRect.right(); + const int rTop = cornerRect.top(); + const int rBottom = cornerRect.bottom(); + uint32_t *srcptr = (uint32_t *)pixmap.surface->data; + uint32_t *dstptr = (uint32_t *)surface->data; + + srcptr += (rLeft - aLeft) + (rTop - aTop) * pixmap.surface->stride / 4; + dstptr += rLeft + rTop * surface->stride / 4; + if (flag & gPixmap::blitAlphaTest) + { + for (int y = rTop; y < rBottom; y++) + { + int yInOriginalArea = y - aTop; + uint32_t *src = srcptr; + uint32_t *dst = dstptr; + + for (int x = rLeft; x < rRight; x++) + { + int xInOriginalArea = x - aLeft; + dx = cornerData.bottomLeftCornerRadius - xInOriginalArea - 1 + cornerData.borderWidth; + dy = yInOriginalArea - cornerData.h_bottomLeftCornerRadius; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.bottomLeftCornerDRadius) + { + if (!((*src) & 0xFF000000)) + { + src++; + dst++; + } + else + *dst++ = *src++; + continue; + } + else if (squared_dst < cornerData.bottomLeftCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, src, alpha); + } + ++dst; + ++src; + } + srcptr = (uint32_t *)((uint8_t *)srcptr + pixmap.surface->stride); + dstptr = (uint32_t *)((uint8_t *)dstptr + surface->stride); + } + } + else if (flag & gPixmap::blitAlphaBlend) + { + for (int y = rTop; y < rBottom; y++) + { + int yInOriginalArea = y - aTop; + uint32_t *src = srcptr; + uint32_t *dst = dstptr; + + for (int x = rLeft; x < rRight; x++) + { + int xInOriginalArea = x - aLeft; + dx = cornerData.bottomLeftCornerRadius - xInOriginalArea - 1 + cornerData.borderWidth; + dy = yInOriginalArea - cornerData.h_bottomLeftCornerRadius; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.bottomLeftCornerDRadius) + { + gRGB *gSrc = (gRGB *)src; + gRGB *gDst = (gRGB *)dst; + gDst->b += (((gSrc->b - gDst->b) * gSrc->a) >> 8); + gDst->g += (((gSrc->g - gDst->g) * gSrc->a) >> 8); + gDst->r += (((gSrc->r - gDst->r) * gSrc->a) >> 8); + gDst->a += (((0xFF - gDst->a) * gSrc->a) >> 8); + src++; + dst++; + continue; + } + else if (squared_dst < cornerData.bottomLeftCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, src, alpha); + } + ++dst; + ++src; + } + srcptr = (uint32_t *)((uint8_t *)srcptr + pixmap.surface->stride); + dstptr = (uint32_t *)((uint8_t *)dstptr + surface->stride); + } + } + else + { + for (int y = rTop; y < rBottom; y++) + { + int yInOriginalArea = y - aTop; + uint32_t *src = srcptr; + uint32_t *dst = dstptr; + + for (int x = rLeft; x < rRight; x++) + { + int xInOriginalArea = x - aLeft; + dx = cornerData.bottomLeftCornerRadius - xInOriginalArea - 1 + cornerData.borderWidth; + dy = yInOriginalArea - cornerData.h_bottomLeftCornerRadius; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.bottomLeftCornerDRadius) + { + *dst++ = *src++; + continue; + } + else if (squared_dst < cornerData.bottomLeftCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, src, alpha); + } + ++dst; + ++src; + } + srcptr = (uint32_t *)((uint8_t *)srcptr + pixmap.surface->stride); + dstptr = (uint32_t *)((uint8_t *)dstptr + surface->stride); + } + } +} + +void drawAngle32Br(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag) +{ + double alpha = 1.0; + int dx = 0, dy = 0, squared_dst = 0; + const std::unordered_map &radiusData = cornerData.RadiusData; + const int aLeft = area.left(); + const int aTop = area.top(); + const int rLeft = cornerRect.left(); + const int rRight = cornerRect.right(); + const int rTop = cornerRect.top(); + const int rBottom = cornerRect.bottom(); + uint32_t *srcptr = (uint32_t *)pixmap.surface->data; + uint32_t *dstptr = (uint32_t *)surface->data; + + srcptr += (rLeft - aLeft) + (rTop - aTop) * pixmap.surface->stride / 4; + dstptr += rLeft + rTop * surface->stride / 4; + if (flag & gPixmap::blitAlphaTest) + { + for (int y = rTop; y < rBottom; y++) + { + int yInOriginalArea = y - aTop; + uint32_t *src = srcptr; + uint32_t *dst = dstptr; + + for (int x = rLeft; x < rRight; x++) + { + int xInOriginalArea = x - aLeft; + dx = xInOriginalArea - cornerData.w_bottomRightCornerRadius; + dy = yInOriginalArea - cornerData.h_bottomRightCornerRadius; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.bottomRightCornerDRadius) + { + if (!((*src) & 0xFF000000)) + { + src++; + dst++; + } + else + *dst++ = *src++; + continue; + } + else if (squared_dst < cornerData.bottomRightCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, src, alpha); + } + ++dst; + ++src; + } + srcptr = (uint32_t *)((uint8_t *)srcptr + pixmap.surface->stride); + dstptr = (uint32_t *)((uint8_t *)dstptr + surface->stride); + } + } + else if (flag & gPixmap::blitAlphaBlend) + { + for (int y = rTop; y < rBottom; y++) + { + int yInOriginalArea = y - aTop; + uint32_t *src = srcptr; + uint32_t *dst = dstptr; + + for (int x = rLeft; x < rRight; x++) + { + int xInOriginalArea = x - aLeft; + dx = xInOriginalArea - cornerData.w_bottomRightCornerRadius; + dy = yInOriginalArea - cornerData.h_bottomRightCornerRadius; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.bottomRightCornerDRadius) + { + gRGB *gSrc = (gRGB *)src; + gRGB *gDst = (gRGB *)dst; + gDst->b += (((gSrc->b - gDst->b) * gSrc->a) >> 8); + gDst->g += (((gSrc->g - gDst->g) * gSrc->a) >> 8); + gDst->r += (((gSrc->r - gDst->r) * gSrc->a) >> 8); + gDst->a += (((0xFF - gDst->a) * gSrc->a) >> 8); + src++; + dst++; + continue; + } + else if (squared_dst < cornerData.bottomRightCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, src, alpha); + } + ++dst; + ++src; + } + srcptr = (uint32_t *)((uint8_t *)srcptr + pixmap.surface->stride); + dstptr = (uint32_t *)((uint8_t *)dstptr + surface->stride); + } + } + else + { + for (int y = rTop; y < rBottom; y++) + { + int yInOriginalArea = y - aTop; + uint32_t *src = srcptr; + uint32_t *dst = dstptr; + + for (int x = rLeft; x < rRight; x++) + { + int xInOriginalArea = x - aLeft; + dx = xInOriginalArea - cornerData.w_bottomRightCornerRadius; + dy = yInOriginalArea - cornerData.h_bottomRightCornerRadius; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.bottomRightCornerDRadius) + { + *dst++ = *src++; + continue; + } + else if (squared_dst < cornerData.bottomRightCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, src, alpha); + } + ++dst; + ++src; + } + srcptr = (uint32_t *)((uint8_t *)srcptr + pixmap.surface->stride); + dstptr = (uint32_t *)((uint8_t *)dstptr + surface->stride); + } + } +} + +void drawAngle32ScaledTl(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag) +{ + double alpha = 1.0; + int dx = 0, dy = 0, squared_dst = 0; + const std::unordered_map &radiusData = cornerData.RadiusData; + const int src_bypp = pixmap.surface->bypp; + const int dst_bypp = surface->bypp; + const int src_stride = pixmap.surface->stride; + const int dst_stride = surface->stride; + const float scaleX = (float)pixmap.size().width() / (float)area.width(); + const float scaleY = (float)pixmap.size().height() / (float)area.height(); + const int aLeft = area.left(); + const int aTop = area.top(); + const int rLeft = cornerRect.left(); + const int rRight = cornerRect.right(); + const int rTop = cornerRect.top(); + const int rBottom = cornerRect.bottom(); + uint8_t *dst_row = (uint8_t *)surface->data + rLeft * dst_bypp + rTop * dst_stride; + + if (flag & gPixmap::blitAlphaTest) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)pixmap.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + int yInOriginalArea = y - aTop; + + for (int x = rLeft; x < rRight; ++x) + { + int xInOriginalArea = x - aLeft; + int src_x = (int)((x - aLeft) * scaleX); + const uint32_t *src = (const uint32_t *)(src_row + src_x * src_bypp); + dx = cornerData.topLeftCornerRadius - xInOriginalArea - 1 + cornerData.borderWidth; + dy = cornerData.topLeftCornerRadius - yInOriginalArea - 1 + cornerData.borderWidth; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.topLeftCornerDRadius) + { + if (*src & 0x80000000) + *dst = *src; + dst++; + continue; + } + else if (squared_dst < cornerData.topLeftCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, src, alpha); + } + dst++; + } + dst_row += dst_stride; + } + } + else if (flag & gPixmap::blitAlphaBlend) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)pixmap.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + int yInOriginalArea = y - aTop; + + for (int x = rLeft; x < rRight; ++x) + { + int xInOriginalArea = x - aLeft; + int src_x = (int)((x - aLeft) * scaleX); + const uint32_t *src = (const uint32_t *)(src_row + src_x * src_bypp); + dx = cornerData.topLeftCornerRadius - xInOriginalArea - 1 + cornerData.borderWidth; + dy = cornerData.topLeftCornerRadius - yInOriginalArea - 1 + cornerData.borderWidth; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.topLeftCornerDRadius) + { + const gRGB *src = (gRGB *)(src_row + src_x * src_bypp); + gRGB *gDst = (gRGB *)dst; + gDst->b += (((src->b - gDst->b) * src->a) >> 8); + gDst->g += (((src->g - gDst->g) * src->a) >> 8); + gDst->r += (((src->r - gDst->r) * src->a) >> 8); + gDst->a += (((0xFF - gDst->a) * src->a) >> 8); + dst++; + continue; + } + else if (squared_dst < cornerData.topLeftCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, src, alpha); + } + dst++; + } + dst_row += dst_stride; + } + } + else + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)pixmap.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + int yInOriginalArea = y - aTop; + + for (int x = rLeft; x < rRight; ++x) + { + int xInOriginalArea = x - aLeft; + int src_x = (int)((x - aLeft) * scaleX); + const uint32_t *src = (const uint32_t *)(src_row + src_x * src_bypp); + dx = cornerData.topLeftCornerRadius - xInOriginalArea - 1 + cornerData.borderWidth; + dy = cornerData.topLeftCornerRadius - yInOriginalArea - 1 + cornerData.borderWidth; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.topLeftCornerDRadius) + { + *dst = *src; + dst++; + continue; + } + else if (squared_dst < cornerData.topLeftCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, src, alpha); + } + dst++; + } + dst_row += dst_stride; + } + } +} + +void drawAngle32ScaledTr(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag) +{ + double alpha = 1.0; + int dx = 0, dy = 0, squared_dst = 0; + const std::unordered_map &radiusData = cornerData.RadiusData; + const int src_bypp = pixmap.surface->bypp; + const int dst_bypp = surface->bypp; + const int src_stride = pixmap.surface->stride; + const int dst_stride = surface->stride; + const float scaleX = (float)pixmap.size().width() / (float)area.width(); + const float scaleY = (float)pixmap.size().height() / (float)area.height(); + const int aLeft = area.left(); + const int aTop = area.top(); + const int rLeft = cornerRect.left(); + const int rRight = cornerRect.right(); + const int rTop = cornerRect.top(); + const int rBottom = cornerRect.bottom(); + uint8_t *dst_row = (uint8_t *)surface->data + rLeft * dst_bypp + rTop * dst_stride; + + if (flag & gPixmap::blitAlphaTest) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)pixmap.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + int yInOriginalArea = y - aTop; + + for (int x = rLeft; x < rRight; ++x) + { + int xInOriginalArea = x - aLeft; + int src_x = (int)((x - aLeft) * scaleX); + const uint32_t *src = (const uint32_t *)(src_row + src_x * src_bypp); + dx = xInOriginalArea - cornerData.w_topRightCornerRadius; + dy = cornerData.topRightCornerRadius - yInOriginalArea - 1 + cornerData.borderWidth; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.topRightCornerDRadius) + { + if (*src & 0x80000000) + *dst = *src; + dst++; + continue; + } + else if (squared_dst < cornerData.topRightCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, src, alpha); + } + dst++; + } + dst_row += dst_stride; + } + } + else if (flag & gPixmap::blitAlphaBlend) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)pixmap.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + int yInOriginalArea = y - aTop; + + for (int x = rLeft; x < rRight; ++x) + { + int xInOriginalArea = x - aLeft; + int src_x = (int)((x - aLeft) * scaleX); + const uint32_t *src = (const uint32_t *)(src_row + src_x * src_bypp); + dx = xInOriginalArea - cornerData.w_topRightCornerRadius; + dy = cornerData.topRightCornerRadius - yInOriginalArea - 1 + cornerData.borderWidth; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.topRightCornerDRadius) + { + const gRGB *src = (gRGB *)(src_row + src_x * src_bypp); + gRGB *gDst = (gRGB *)dst; + gDst->b += (((src->b - gDst->b) * src->a) >> 8); + gDst->g += (((src->g - gDst->g) * src->a) >> 8); + gDst->r += (((src->r - gDst->r) * src->a) >> 8); + gDst->a += (((0xFF - gDst->a) * src->a) >> 8); + dst++; + continue; + } + else if (squared_dst < cornerData.topRightCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, src, alpha); + } + dst++; + } + dst_row += dst_stride; + } + } + else + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)pixmap.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + int yInOriginalArea = y - aTop; + + for (int x = rLeft; x < rRight; ++x) + { + int xInOriginalArea = x - aLeft; + int src_x = (int)((x - aLeft) * scaleX); + const uint32_t *src = (const uint32_t *)(src_row + src_x * src_bypp); + dx = xInOriginalArea - cornerData.w_topRightCornerRadius; + dy = cornerData.topRightCornerRadius - yInOriginalArea - 1 + cornerData.borderWidth; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.topRightCornerDRadius) + { + *dst = *src; + dst++; + continue; + } + else if (squared_dst < cornerData.topRightCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, src, alpha); + } + dst++; + } + dst_row += dst_stride; + } + } +} + +void drawAngle32ScaledBl(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag) +{ + double alpha = 1.0; + int dx = 0, dy = 0, squared_dst = 0; + const std::unordered_map &radiusData = cornerData.RadiusData; + const int src_bypp = pixmap.surface->bypp; + const int dst_bypp = surface->bypp; + const int src_stride = pixmap.surface->stride; + const int dst_stride = surface->stride; + const float scaleX = (float)pixmap.size().width() / (float)area.width(); + const float scaleY = (float)pixmap.size().height() / (float)area.height(); + const int aLeft = area.left(); + const int aTop = area.top(); + const int rLeft = cornerRect.left(); + const int rRight = cornerRect.right(); + const int rTop = cornerRect.top(); + const int rBottom = cornerRect.bottom(); + uint8_t *dst_row = (uint8_t *)surface->data + rLeft * dst_bypp + rTop * dst_stride; + + if (flag & gPixmap::blitAlphaTest) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)pixmap.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + int yInOriginalArea = y - aTop; + + for (int x = rLeft; x < rRight; ++x) + { + int xInOriginalArea = x - aLeft; + int src_x = (int)((x - aLeft) * scaleX); + const uint32_t *src = (const uint32_t *)(src_row + src_x * src_bypp); + dx = cornerData.bottomLeftCornerRadius - xInOriginalArea - 1 + cornerData.borderWidth; + dy = yInOriginalArea - cornerData.h_bottomLeftCornerRadius; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.bottomLeftCornerDRadius) + { + if (*src & 0x80000000) + *dst = *src; + dst++; + continue; + } + else if (squared_dst < cornerData.bottomLeftCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, src, alpha); + } + dst++; + } + dst_row += dst_stride; + } + } + else if (flag & gPixmap::blitAlphaBlend) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)pixmap.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + int yInOriginalArea = y - aTop; + + for (int x = rLeft; x < rRight; ++x) + { + int xInOriginalArea = x - aLeft; + int src_x = (int)((x - aLeft) * scaleX); + const uint32_t *src = (const uint32_t *)(src_row + src_x * src_bypp); + dx = cornerData.bottomLeftCornerRadius - xInOriginalArea - 1 + cornerData.borderWidth; + dy = yInOriginalArea - cornerData.h_bottomLeftCornerRadius; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.bottomLeftCornerDRadius) + { + const gRGB *src = (gRGB *)(src_row + src_x * src_bypp); + gRGB *gDst = (gRGB *)dst; + gDst->b += (((src->b - gDst->b) * src->a) >> 8); + gDst->g += (((src->g - gDst->g) * src->a) >> 8); + gDst->r += (((src->r - gDst->r) * src->a) >> 8); + gDst->a += (((0xFF - gDst->a) * src->a) >> 8); + dst++; + continue; + } + else if (squared_dst < cornerData.bottomLeftCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, src, alpha); + } + dst++; + } + dst_row += dst_stride; + } + } + else + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)pixmap.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + int yInOriginalArea = y - aTop; + + for (int x = rLeft; x < rRight; ++x) + { + int xInOriginalArea = x - aLeft; + int src_x = (int)((x - aLeft) * scaleX); + const uint32_t *src = (const uint32_t *)(src_row + src_x * src_bypp); + dx = cornerData.bottomLeftCornerRadius - xInOriginalArea - 1 + cornerData.borderWidth; + dy = yInOriginalArea - cornerData.h_bottomLeftCornerRadius; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.bottomLeftCornerDRadius) + { + *dst = *src; + dst++; + continue; + } + else if (squared_dst < cornerData.bottomLeftCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, src, alpha); + } + dst++; + } + dst_row += dst_stride; + } + } +} + +void drawAngle32ScaledBr(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag) +{ + double alpha = 1.0; + int dx = 0, dy = 0, squared_dst = 0; + const std::unordered_map &radiusData = cornerData.RadiusData; + const int src_bypp = pixmap.surface->bypp; + const int dst_bypp = surface->bypp; + const int src_stride = pixmap.surface->stride; + const int dst_stride = surface->stride; + const float scaleX = (float)pixmap.size().width() / (float)area.width(); + const float scaleY = (float)pixmap.size().height() / (float)area.height(); + const int aLeft = area.left(); + const int aTop = area.top(); + const int rLeft = cornerRect.left(); + const int rRight = cornerRect.right(); + const int rTop = cornerRect.top(); + const int rBottom = cornerRect.bottom(); + uint8_t *dst_row = (uint8_t *)surface->data + rLeft * dst_bypp + rTop * dst_stride; + + if (flag & gPixmap::blitAlphaTest) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)pixmap.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + int yInOriginalArea = y - aTop; + + for (int x = rLeft; x < rRight; ++x) + { + int xInOriginalArea = x - aLeft; + int src_x = (int)((x - aLeft) * scaleX); + const uint32_t *src = (const uint32_t *)(src_row + src_x * src_bypp); + dx = xInOriginalArea - cornerData.w_bottomRightCornerRadius; + dy = yInOriginalArea - cornerData.h_bottomRightCornerRadius; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.bottomRightCornerDRadius) + { + if (*src & 0x80000000) + *dst = *src; + dst++; + continue; + } + else if (squared_dst < cornerData.bottomRightCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, src, alpha); + } + dst++; + } + dst_row += dst_stride; + } + } + else if (flag & gPixmap::blitAlphaBlend) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)pixmap.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + int yInOriginalArea = y - aTop; + + for (int x = rLeft; x < rRight; ++x) + { + int xInOriginalArea = x - aLeft; + int src_x = (int)((x - aLeft) * scaleX); + const uint32_t *src = (const uint32_t *)(src_row + src_x * src_bypp); + dx = xInOriginalArea - cornerData.w_bottomRightCornerRadius; + dy = yInOriginalArea - cornerData.h_bottomRightCornerRadius; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.bottomRightCornerDRadius) + { + const gRGB *src = (gRGB *)(src_row + src_x * src_bypp); + gRGB *gDst = (gRGB *)dst; + gDst->b += (((src->b - gDst->b) * src->a) >> 8); + gDst->g += (((src->g - gDst->g) * src->a) >> 8); + gDst->r += (((src->r - gDst->r) * src->a) >> 8); + gDst->a += (((0xFF - gDst->a) * src->a) >> 8); + dst++; + continue; + } + else if (squared_dst < cornerData.bottomRightCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, src, alpha); + } + dst++; + } + dst_row += dst_stride; + } + } + else + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)pixmap.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + int yInOriginalArea = y - aTop; + + for (int x = rLeft; x < rRight; ++x) + { + int xInOriginalArea = x - aLeft; + int src_x = (int)((x - aLeft) * scaleX); + const uint32_t *src = (const uint32_t *)(src_row + src_x * src_bypp); + dx = xInOriginalArea - cornerData.w_bottomRightCornerRadius; + dy = yInOriginalArea - cornerData.h_bottomRightCornerRadius; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.bottomRightCornerDRadius) + { + *dst = *src; + dst++; + continue; + } + else if (squared_dst < cornerData.bottomRightCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, src, alpha); + } + dst++; + } + dst_row += dst_stride; + } + } +} + +void drawAngle8Tl(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag) +{ + double alpha = 1.0; + int dx = 0, dy = 0, squared_dst = 0; + const std::unordered_map &radiusData = cornerData.RadiusData; + const uint8_t *srcptr = (uint8_t *)pixmap.surface->data; + uint32_t *dstptr = (uint32_t *)surface->data; + + srcptr += (cornerRect.left() - area.left()) + (cornerRect.top() - area.top()) * pixmap.surface->stride; + dstptr += cornerRect.left() + cornerRect.top() * surface->stride / 4; + for (int y = cornerRect.top(); y < cornerRect.bottom(); y++) + { + int yInOriginalArea = y - area.top(); + const uint8_t *src = srcptr; + uint32_t *dst = dstptr; + + for (int x = cornerRect.left(); x < cornerRect.right(); x++) + { + int xInOriginalArea = x - area.left(); + dx = cornerData.topLeftCornerRadius - xInOriginalArea - 1 + cornerData.borderWidth; + dy = cornerData.topLeftCornerRadius - yInOriginalArea - 1 + cornerData.borderWidth; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.topLeftCornerDRadius) + { + if (flag & gPixmap::blitAlphaTest) + { + if (!(pal[*src] & 0xFF000000)) + { + src++; + dst++; + } + else + *dst++ = pal[*src++]; + } + else if (flag & gPixmap::blitAlphaBlend) + { + gRGB *gDst = (gRGB *)dst; + gDst->alpha_blend(pal[*src++]); + dst++; + } + else + *dst++ = pal[*src++]; + continue; + } + else if (squared_dst < cornerData.topLeftCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, &pal[*src], alpha); + } + ++dst; + ++src; + } + srcptr += pixmap.surface->stride; + dstptr = (uint32_t *)((uint8_t *)dstptr + surface->stride); + } +} + +void drawAngle8Tr(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag) +{ + double alpha = 1.0; + int dx = 0, dy = 0, squared_dst = 0; + const std::unordered_map &radiusData = cornerData.RadiusData; + const uint8_t *srcptr = (uint8_t *)pixmap.surface->data; + uint32_t *dstptr = (uint32_t *)surface->data; + + srcptr += (cornerRect.left() - area.left()) + (cornerRect.top() - area.top()) * pixmap.surface->stride; + dstptr += cornerRect.left() + cornerRect.top() * surface->stride / 4; + for (int y = cornerRect.top(); y < cornerRect.bottom(); y++) + { + int yInOriginalArea = y - area.top(); + const uint8_t *src = srcptr; + uint32_t *dst = dstptr; + + for (int x = cornerRect.left(); x < cornerRect.right(); x++) + { + int xInOriginalArea = x - area.left(); + dx = xInOriginalArea - cornerData.w_topRightCornerRadius; + dy = cornerData.topRightCornerRadius - yInOriginalArea - 1 + cornerData.borderWidth; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.topRightCornerDRadius) + { + if (flag & gPixmap::blitAlphaTest) + { + if (!(pal[*src] & 0xFF000000)) + { + src++; + dst++; + } + else + *dst++ = pal[*src++]; + } + else if (flag & gPixmap::blitAlphaBlend) + { + gRGB *gDst = (gRGB *)dst; + gDst->alpha_blend(pal[*src++]); + dst++; + } + else + *dst++ = pal[*src++]; + continue; + } + else if (squared_dst < cornerData.topRightCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, &pal[*src], alpha); + } + ++dst; + ++src; + } + srcptr += pixmap.surface->stride; + dstptr = (uint32_t *)((uint8_t *)dstptr + surface->stride); + } +} + +void drawAngle8Bl(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag) +{ + double alpha = 1.0; + int dx = 0, dy = 0, squared_dst = 0; + const std::unordered_map &radiusData = cornerData.RadiusData; + const uint8_t *srcptr = (uint8_t *)pixmap.surface->data; + uint32_t *dstptr = (uint32_t *)surface->data; + + srcptr += (cornerRect.left() - area.left()) + (cornerRect.top() - area.top()) * pixmap.surface->stride; + dstptr += cornerRect.left() + cornerRect.top() * surface->stride / 4; + for (int y = cornerRect.top(); y < cornerRect.bottom(); y++) + { + int yInOriginalArea = y - area.top(); + const uint8_t *src = srcptr; + uint32_t *dst = dstptr; + + for (int x = cornerRect.left(); x < cornerRect.right(); x++) + { + int xInOriginalArea = x - area.left(); + dx = cornerData.bottomLeftCornerRadius - xInOriginalArea - 1 + cornerData.borderWidth; + dy = yInOriginalArea - cornerData.h_bottomLeftCornerRadius; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.bottomLeftCornerDRadius) + { + if (flag & gPixmap::blitAlphaTest) + { + if (!(pal[*src] & 0xFF000000)) + { + src++; + dst++; + } + else + *dst++ = pal[*src++]; + } + else if (flag & gPixmap::blitAlphaBlend) + { + gRGB *gDst = (gRGB *)dst; + gDst->alpha_blend(pal[*src++]); + dst++; + } + else + *dst++ = pal[*src++]; + continue; + } + else if (squared_dst < cornerData.bottomLeftCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, &pal[*src], alpha); + } + ++dst; + ++src; + } + srcptr += pixmap.surface->stride; + dstptr = (uint32_t *)((uint8_t *)dstptr + surface->stride); + } +} + +void drawAngle8Br(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag) +{ + double alpha = 1.0; + int dx = 0, dy = 0, squared_dst = 0; + const std::unordered_map &radiusData = cornerData.RadiusData; + const uint8_t *srcptr = (uint8_t *)pixmap.surface->data; + uint32_t *dstptr = (uint32_t *)surface->data; + + srcptr += (cornerRect.left() - area.left()) + (cornerRect.top() - area.top()) * pixmap.surface->stride; + dstptr += cornerRect.left() + cornerRect.top() * surface->stride / 4; + for (int y = cornerRect.top(); y < cornerRect.bottom(); y++) + { + int yInOriginalArea = y - area.top(); + const uint8_t *src = srcptr; + uint32_t *dst = dstptr; + + for (int x = cornerRect.left(); x < cornerRect.right(); x++) + { + int xInOriginalArea = x - area.left(); + dx = xInOriginalArea - cornerData.w_bottomRightCornerRadius; + dy = yInOriginalArea - cornerData.h_bottomRightCornerRadius; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.bottomRightCornerDRadius) + { + if (flag & gPixmap::blitAlphaTest) + { + if (!(pal[*src] & 0xFF000000)) + { + src++; + dst++; + } + else + *dst++ = pal[*src++]; + } + else if (flag & gPixmap::blitAlphaBlend) + { + gRGB *gDst = (gRGB *)dst; + gDst->alpha_blend(pal[*src++]); + dst++; + } + else + *dst++ = pal[*src++]; + continue; + } + else if (squared_dst < cornerData.bottomRightCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, &pal[*src], alpha); + } + ++dst; + ++src; + } + srcptr += pixmap.surface->stride; + dstptr = (uint32_t *)((uint8_t *)dstptr + surface->stride); + } +} + +void drawAngle8ScaledTl(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag) +{ + double alpha = 1.0; + int dx = 0, dy = 0, squared_dst = 0; + const std::unordered_map &radiusData = cornerData.RadiusData; + const int src_bypp = pixmap.surface->bypp; + const int dst_bypp = surface->bypp; + const int src_stride = pixmap.surface->stride; + const int dst_stride = surface->stride; + const float scaleX = (float)pixmap.size().width() / (float)area.width(); + const float scaleY = (float)pixmap.size().height() / (float)area.height(); + const int aLeft = area.left(); + const int aTop = area.top(); + const int rLeft = cornerRect.left(); + const int rRight = cornerRect.right(); + const int rTop = cornerRect.top(); + const int rBottom = cornerRect.bottom(); + uint8_t *dst_row = (uint8_t *)surface->data + rLeft * dst_bypp + rTop * dst_stride; + + if (flag & gPixmap::blitAlphaTest) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)pixmap.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + int yInOriginalArea = y - aTop; + + for (int x = rLeft; x < rRight; ++x) + { + int xInOriginalArea = x - aLeft; + int src_x = (int)((x - aLeft) * scaleX); + const uint8_t *src = src_row + src_x * src_bypp; + dx = cornerData.topLeftCornerRadius - xInOriginalArea - 1 + cornerData.borderWidth; + dy = cornerData.topLeftCornerRadius - yInOriginalArea - 1 + cornerData.borderWidth; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.topLeftCornerDRadius) + { + if (pal[*src] & 0x80000000) + *dst = pal[*src]; + dst++; + continue; + } + else if (squared_dst < cornerData.topLeftCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, &pal[*src], alpha); + } + dst++; + } + dst_row += dst_stride; + } + } + else if (flag & gPixmap::blitAlphaBlend) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)pixmap.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + int yInOriginalArea = y - aTop; + + for (int x = rLeft; x < rRight; ++x) + { + int xInOriginalArea = x - aLeft; + int src_x = (int)((x - aLeft) * scaleX); + const uint8_t *src = src_row + src_x * src_bypp; + dx = cornerData.topLeftCornerRadius - xInOriginalArea - 1 + cornerData.borderWidth; + dy = cornerData.topLeftCornerRadius - yInOriginalArea - 1 + cornerData.borderWidth; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.topLeftCornerDRadius) + { + gRGB *gDst = (gRGB *)dst; + gDst->alpha_blend(pal[*src]); + dst++; + continue; + } + else if (squared_dst < cornerData.topLeftCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, &pal[*src], alpha); + } + dst++; + } + dst_row += dst_stride; + } + } + else + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)pixmap.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + int yInOriginalArea = y - aTop; + + for (int x = rLeft; x < rRight; ++x) + { + int xInOriginalArea = x - aLeft; + int src_x = (int)((x - aLeft) * scaleX); + const uint8_t *src = src_row + src_x * src_bypp; + dx = cornerData.topLeftCornerRadius - xInOriginalArea - 1 + cornerData.borderWidth; + dy = cornerData.topLeftCornerRadius - yInOriginalArea - 1 + cornerData.borderWidth; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.topLeftCornerDRadius) + { + *dst = pal[*src]; + dst++; + continue; + } + else if (squared_dst < cornerData.topLeftCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, &pal[*src], alpha); + } + dst++; + } + dst_row += dst_stride; + } + } +} + +void drawAngle8ScaledTr(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag) +{ + double alpha = 1.0; + int dx = 0, dy = 0, squared_dst = 0; + const std::unordered_map &radiusData = cornerData.RadiusData; + const int src_bypp = pixmap.surface->bypp; + const int dst_bypp = surface->bypp; + const int src_stride = pixmap.surface->stride; + const int dst_stride = surface->stride; + const float scaleX = (float)pixmap.size().width() / (float)area.width(); + const float scaleY = (float)pixmap.size().height() / (float)area.height(); + const int aLeft = area.left(); + const int aTop = area.top(); + const int rLeft = cornerRect.left(); + const int rRight = cornerRect.right(); + const int rTop = cornerRect.top(); + const int rBottom = cornerRect.bottom(); + uint8_t *dst_row = (uint8_t *)surface->data + rLeft * dst_bypp + rTop * dst_stride; + + if (flag & gPixmap::blitAlphaTest) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)pixmap.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + int yInOriginalArea = y - aTop; + + for (int x = rLeft; x < rRight; ++x) + { + int xInOriginalArea = x - aLeft; + int src_x = (int)((x - aLeft) * scaleX); + const uint8_t *src = src_row + src_x * src_bypp; + dx = xInOriginalArea - cornerData.w_topRightCornerRadius; + dy = cornerData.topRightCornerRadius - yInOriginalArea - 1 + cornerData.borderWidth; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.topRightCornerDRadius) + { + if (pal[*src] & 0x80000000) + *dst = pal[*src]; + dst++; + continue; + } + else if (squared_dst < cornerData.topRightCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, &pal[*src], alpha); + } + dst++; + } + dst_row += dst_stride; + } + } + else if (flag & gPixmap::blitAlphaBlend) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)pixmap.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + int yInOriginalArea = y - aTop; + + for (int x = rLeft; x < rRight; ++x) + { + int xInOriginalArea = x - aLeft; + int src_x = (int)((x - aLeft) * scaleX); + const uint8_t *src = src_row + src_x * src_bypp; + dx = xInOriginalArea - cornerData.w_topRightCornerRadius; + dy = cornerData.topRightCornerRadius - yInOriginalArea - 1 + cornerData.borderWidth; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.topRightCornerDRadius) + { + gRGB *gDst = (gRGB *)dst; + gDst->alpha_blend(pal[*src]); + dst++; + continue; + } + else if (squared_dst < cornerData.topRightCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, &pal[*src], alpha); + } + dst++; + } + dst_row += dst_stride; + } + } + else + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)pixmap.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + int yInOriginalArea = y - aTop; + + for (int x = rLeft; x < rRight; ++x) + { + int xInOriginalArea = x - aLeft; + int src_x = (int)((x - aLeft) * scaleX); + const uint8_t *src = src_row + src_x * src_bypp; + dx = xInOriginalArea - cornerData.w_topRightCornerRadius; + dy = cornerData.topRightCornerRadius - yInOriginalArea - 1 + cornerData.borderWidth; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.topRightCornerDRadius) + { + *dst = pal[*src]; + dst++; + continue; + } + else if (squared_dst < cornerData.topRightCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, &pal[*src], alpha); + } + dst++; + } + dst_row += dst_stride; + } + } +} + +void drawAngle8ScaledBl(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag) +{ + double alpha = 1.0; + int dx = 0, dy = 0, squared_dst = 0; + const std::unordered_map &radiusData = cornerData.RadiusData; + const int src_bypp = pixmap.surface->bypp; + const int dst_bypp = surface->bypp; + const int src_stride = pixmap.surface->stride; + const int dst_stride = surface->stride; + const float scaleX = (float)pixmap.size().width() / (float)area.width(); + const float scaleY = (float)pixmap.size().height() / (float)area.height(); + const int aLeft = area.left(); + const int aTop = area.top(); + const int rLeft = cornerRect.left(); + const int rRight = cornerRect.right(); + const int rTop = cornerRect.top(); + const int rBottom = cornerRect.bottom(); + uint8_t *dst_row = (uint8_t *)surface->data + rLeft * dst_bypp + rTop * dst_stride; + + if (flag & gPixmap::blitAlphaTest) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)pixmap.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + int yInOriginalArea = y - aTop; + + for (int x = rLeft; x < rRight; ++x) + { + int xInOriginalArea = x - aLeft; + int src_x = (int)((x - aLeft) * scaleX); + const uint8_t *src = src_row + src_x * src_bypp; + dx = cornerData.bottomLeftCornerRadius - xInOriginalArea - 1 + cornerData.borderWidth; + dy = yInOriginalArea - cornerData.h_bottomLeftCornerRadius; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.bottomLeftCornerDRadius) + { + if (pal[*src] & 0x80000000) + *dst = pal[*src]; + dst++; + continue; + } + else if (squared_dst < cornerData.bottomLeftCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, &pal[*src], alpha); + } + dst++; + } + dst_row += dst_stride; + } + } + else if (flag & gPixmap::blitAlphaBlend) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)pixmap.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + int yInOriginalArea = y - aTop; + + for (int x = rLeft; x < rRight; ++x) + { + int xInOriginalArea = x - aLeft; + int src_x = (int)((x - aLeft) * scaleX); + const uint8_t *src = src_row + src_x * src_bypp; + dx = cornerData.bottomLeftCornerRadius - xInOriginalArea - 1 + cornerData.borderWidth; + dy = yInOriginalArea - cornerData.h_bottomLeftCornerRadius; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.bottomLeftCornerDRadius) + { + gRGB *gDst = (gRGB *)dst; + gDst->alpha_blend(pal[*src]); + dst++; + continue; + } + else if (squared_dst < cornerData.bottomLeftCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, &pal[*src], alpha); + } + dst++; + } + dst_row += dst_stride; + } + } + else + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)pixmap.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + int yInOriginalArea = y - aTop; + + for (int x = rLeft; x < rRight; ++x) + { + int xInOriginalArea = x - aLeft; + int src_x = (int)((x - aLeft) * scaleX); + const uint8_t *src = src_row + src_x * src_bypp; + dx = cornerData.bottomLeftCornerRadius - xInOriginalArea - 1 + cornerData.borderWidth; + dy = yInOriginalArea - cornerData.h_bottomLeftCornerRadius; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.bottomLeftCornerDRadius) + { + *dst = pal[*src]; + dst++; + continue; + } + else if (squared_dst < cornerData.bottomLeftCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, &pal[*src], alpha); + } + dst++; + } + dst_row += dst_stride; + } + } +} + +void drawAngle8ScaledBr(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag) +{ + double alpha = 1.0; + int dx = 0, dy = 0, squared_dst = 0; + const std::unordered_map &radiusData = cornerData.RadiusData; + const int src_bypp = pixmap.surface->bypp; + const int dst_bypp = surface->bypp; + const int src_stride = pixmap.surface->stride; + const int dst_stride = surface->stride; + const float scaleX = (float)pixmap.size().width() / (float)area.width(); + const float scaleY = (float)pixmap.size().height() / (float)area.height(); + const int aLeft = area.left(); + const int aTop = area.top(); + const int rLeft = cornerRect.left(); + const int rRight = cornerRect.right(); + const int rTop = cornerRect.top(); + const int rBottom = cornerRect.bottom(); + uint8_t *dst_row = (uint8_t *)surface->data + rLeft * dst_bypp + rTop * dst_stride; + + if (flag & gPixmap::blitAlphaTest) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)pixmap.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + int yInOriginalArea = y - aTop; + + for (int x = rLeft; x < rRight; ++x) + { + int xInOriginalArea = x - aLeft; + int src_x = (int)((x - aLeft) * scaleX); + const uint8_t *src = src_row + src_x * src_bypp; + dx = xInOriginalArea - cornerData.w_bottomRightCornerRadius; + dy = yInOriginalArea - cornerData.h_bottomRightCornerRadius; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.bottomRightCornerDRadius) + { + if (pal[*src] & 0x80000000) + *dst = pal[*src]; + dst++; + continue; + } + else if (squared_dst < cornerData.bottomRightCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, &pal[*src], alpha); + } + dst++; + } + dst_row += dst_stride; + } + } + else if (flag & gPixmap::blitAlphaBlend) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)pixmap.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + int yInOriginalArea = y - aTop; + + for (int x = rLeft; x < rRight; ++x) + { + int xInOriginalArea = x - aLeft; + int src_x = (int)((x - aLeft) * scaleX); + const uint8_t *src = src_row + src_x * src_bypp; + dx = xInOriginalArea - cornerData.w_bottomRightCornerRadius; + dy = yInOriginalArea - cornerData.h_bottomRightCornerRadius; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.bottomRightCornerDRadius) + { + gRGB *gDst = (gRGB *)dst; + gDst->alpha_blend(pal[*src]); + dst++; + continue; + } + else if (squared_dst < cornerData.bottomRightCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, &pal[*src], alpha); + } + dst++; + } + dst_row += dst_stride; + } + } + else + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)pixmap.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + int yInOriginalArea = y - aTop; + + for (int x = rLeft; x < rRight; ++x) + { + int xInOriginalArea = x - aLeft; + int src_x = (int)((x - aLeft) * scaleX); + const uint8_t *src = src_row + src_x * src_bypp; + dx = xInOriginalArea - cornerData.w_bottomRightCornerRadius; + dy = yInOriginalArea - cornerData.h_bottomRightCornerRadius; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= cornerData.bottomRightCornerDRadius) + { + *dst = pal[*src]; + dst++; + continue; + } + else if (squared_dst < cornerData.bottomRightCornerSRadius) + { + alpha = radiusData.at(squared_dst); + blendPixelRounded(dst, &pal[*src], alpha); + } + dst++; + } + dst_row += dst_stride; + } + } +} diff --git a/lib/gdi/drawing.h b/lib/gdi/drawing.h new file mode 100644 index 00000000000..fa42fda503a --- /dev/null +++ b/lib/gdi/drawing.h @@ -0,0 +1,67 @@ +/* +Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License + +Copyright (c) 2023-2024 openATV + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +1. Non-Commercial Use: You may not use the Software or any derivative works + for commercial purposes without obtaining explicit permission from the + copyright holder. +2. Share Alike: If you distribute or publicly perform the Software or any + derivative works, you must do so under the same license terms, and you + must make the source code of any derivative works available to the + public. +3. Attribution: You must give appropriate credit to the original author(s) + of the Software by including a prominent notice in your derivative works. +THE SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, +ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more details about the CC BY-NC-SA 4.0 License, please visit: +https://creativecommons.org/licenses/by-nc-sa/4.0/ +*/ + +#ifndef __drawing__ +#define __drawing__ + +#include "gpixmap.h" +#include + +void duplicate_32fc(uint32_t *out, const uint32_t in, size_t size); +uint32_t *createGradientBuffer2(int graSize, const gRGB &startColor, const gRGB &endColor); +uint32_t *createGradientBuffer3(int graSize, const std::vector &colors); +void drawAngleTl(gUnmanagedSurface *surface, const uint32_t *src, const eRect &area, uint8_t direction, const eRect &cornerRect, const CornerData &cornerData); +void drawAngleTr(gUnmanagedSurface *surface, const uint32_t *src, const eRect &area, uint8_t direction, const eRect &cornerRect, const CornerData &cornerData); +void drawAngleBl(gUnmanagedSurface *surface, const uint32_t *src, const eRect &area, uint8_t direction, const eRect &cornerRect, const CornerData &cornerData); +void drawAngleBr(gUnmanagedSurface *surface, const uint32_t *src, const eRect &area, uint8_t direction, const eRect &cornerRect, const CornerData &cornerData); + +void drawAngle32Tl(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); +void drawAngle32Tr(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); +void drawAngle32Bl(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); +void drawAngle32Br(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); + +void drawAngle32ScaledTl(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); +void drawAngle32ScaledTr(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); +void drawAngle32ScaledBl(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); +void drawAngle32ScaledBr(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); + +void drawAngle8Tl(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); +void drawAngle8Tr(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); +void drawAngle8Bl(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); +void drawAngle8Br(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); + +void drawAngle8ScaledTl(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); +void drawAngle8ScaledTr(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); +void drawAngle8ScaledBl(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); +void drawAngle8ScaledBr(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); + +#endif \ No newline at end of file diff --git a/lib/gdi/gpixmap.cpp b/lib/gdi/gpixmap.cpp index 19cddee8e3c..4ec0f1b7eba 100644 --- a/lib/gdi/gpixmap.cpp +++ b/lib/gdi/gpixmap.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #ifndef BYTE_ORDER @@ -451,18 +452,1192 @@ static void convert_palette(uint32_t* pal, const gPalette& clut) #define FIX 0x10000 -void gPixmap::blit(const gPixmap &src, const eRect &_pos, const gRegion &clip, int flag) +void gPixmap::drawRectangle(const gRegion ®ion, const eRect &area, const gRGB &backgroundColor, const gRGB &borderColor, int borderWidth, const std::vector &gradientColors, uint8_t direction, int radius, uint8_t edges, bool alphablend, int gradientFullSize) +{ + if (surface->bpp < 32) + { + eWarning("[gPixmap] couldn't rgbfill %d bpp", surface->bpp); + return; + } + + const uint8_t GRADIENT_VERTICAL = 1; + uint32_t backColor = backgroundColor.argb(); + backColor ^= 0xFF000000; + uint32_t borderCol = borderColor.argb(); + borderCol ^= 0xFF000000; + uint32_t *gradientBuf = nullptr; + + const int gradientSize = (gradientFullSize) ? gradientFullSize : (direction == GRADIENT_VERTICAL) ? area.height() : area.width(); + + if(!direction) + gradientBuf = createGradientBuffer2(gradientSize, backgroundColor, backgroundColor); + else if(gradientColors.at(1) == gradientColors.at(2)) + gradientBuf = createGradientBuffer2(gradientSize, gradientColors.at(0), gradientColors.at(1)); + else + gradientBuf = createGradientBuffer3(gradientSize, gradientColors); + + CornerData cornerData(radius, edges, area.width(), area.height(), borderWidth, borderCol); + + for (unsigned int i = 0; i < region.rects.size(); ++i) + { + eRect reg = area; + reg &= region.rects[i]; + + if (reg.empty()) + continue; + + int corners = 0; + eRect cornerRect; + + if (cornerData.topLeftCornerRadius) + { + cornerRect = eRect(area.left(), area.top(), cornerData.topLeftCornerRadius, cornerData.topLeftCornerRadius); + cornerRect &= region.rects[i]; + if (!cornerRect.empty()) + { + corners += 1; + drawAngleTl(surface, gradientBuf, area, direction, cornerRect, cornerData); + } + } + if (cornerData.topRightCornerRadius) + { + cornerRect = eRect(area.right() - cornerData.topRightCornerRadius, area.top(), cornerData.topRightCornerRadius, cornerData.topRightCornerRadius); + cornerRect &= region.rects[i]; + if (!cornerRect.empty()) + { + corners += 2; + drawAngleTr(surface, gradientBuf, area, direction, cornerRect, cornerData); + } + } + if (cornerData.bottomLeftCornerRadius) + { + cornerRect = eRect(area.left(), area.bottom() - cornerData.bottomLeftCornerRadius, cornerData.bottomLeftCornerRadius, cornerData.bottomLeftCornerRadius); + cornerRect &= region.rects[i]; + if (!cornerRect.empty()) + { + corners += 4; + drawAngleBl(surface, gradientBuf, area, direction, cornerRect, cornerData); + } + } + + if (cornerData.bottomRightCornerRadius) + { + cornerRect = eRect(area.right() - cornerData.bottomRightCornerRadius, area.bottom() - cornerData.bottomRightCornerRadius, cornerData.bottomRightCornerRadius, cornerData.bottomRightCornerRadius); + cornerRect &= region.rects[i]; + if (!cornerRect.empty()) + { + corners += 8; + drawAngleBr(surface, gradientBuf, area, direction, cornerRect, cornerData); + } + } + + if (cornerData.isCircle) + continue; + + const int bottom = MAX(cornerData.bottomRightCornerRadius, cornerData.bottomLeftCornerRadius); + const int top = MAX(cornerData.topRightCornerRadius, cornerData.topLeftCornerRadius); + + int topw = area.width(); + int topl = area.left(); + int bottomw = area.width(); + int bottoml = area.left(); + + if (corners & 1) + { + topw -= cornerData.topLeftCornerRadius; + topl += cornerData.topLeftCornerRadius; + } + if (corners & 2) + topw -= cornerData.topRightCornerRadius; + + if (corners & 4) + { + bottomw -= cornerData.bottomLeftCornerRadius; + bottoml += cornerData.bottomLeftCornerRadius; + } + if (corners & 8) + bottomw -= cornerData.bottomRightCornerRadius; + + eRect topRect = eRect(topl, area.top(), topw, top); + topRect &= region.rects[i]; + + eRect bottomRect = eRect(bottoml, area.bottom() - bottom, bottomw, bottom); + bottomRect &= region.rects[i]; + + eRect mRect = eRect(area.left(), area.top() + top, area.width(), area.height() - top - bottom); + mRect &= region.rects[i]; + const int blendRatio = 12; + if (!mRect.empty()) + { + if (alphablend && !cornerData.radiusSet) + { + for (int y = mRect.top(); y < mRect.bottom(); y++) + { + uint32_t *dstptr = (uint32_t *)(((uint8_t *)surface->data) + y * surface->stride + mRect.left() * surface->bypp); + uint32_t *gradientBuf2 = gradientBuf + mRect.left() - area.left(); + int width = mRect.width(); + gRGB *src = (gRGB *)gradientBuf2; + gRGB *dst = (gRGB *)dstptr; + while (width >= blendRatio) + { + for (int i = 0; i < blendRatio; ++i) + { + dst[i].b += (((src->b - dst[i].b) * src->a) >> 8); + dst[i].g += (((src->g - dst[i].g) * src->a) >> 8); + dst[i].r += (((src->r - dst[i].r) * src->a) >> 8); + dst[i].a += (((0xFF - dst[i].a) * src->a) >> 8); + } + + dst += blendRatio; + src += blendRatio; + width -= blendRatio; + } + + while (width > 0) + { + dst->b += (((src->b - dst->b) * src->a) >> 8); + dst->g += (((src->g - dst->g) * src->a) >> 8); + dst->r += (((src->r - dst->r) * src->a) >> 8); + dst->a += (((0xFF - dst->a) * src->a) >> 8); + + ++dst; + ++src; + --width; + } + } + } + else + { + int linesize = mRect.width() * surface->bypp; + for (int y = mRect.top(); y < mRect.bottom(); y++) + { + uint32_t *dst = (uint32_t *)(((uint8_t *)surface->data) + y * surface->stride + mRect.left() * surface->bypp); + uint32_t *gradientBuf2 = gradientBuf + mRect.left() - area.left(); + std::memcpy(dst, gradientBuf2, linesize); + } + } // if blitAlphaBlend + } // if center + + if (top && !topRect.empty()) + { + int linesize = topRect.width() * surface->bypp; + for (int y = topRect.top(); y < topRect.bottom(); y++) + { + uint32_t *dst = (uint32_t *)(((uint8_t *)surface->data) + y * surface->stride + topRect.left() * surface->bypp); + uint32_t *gradientBuf2 = gradientBuf + topRect.left() - area.left(); + std::memcpy(dst, gradientBuf2, linesize); + } + } // if top + + if (bottom && !bottomRect.empty()) + { + int linesize = bottomRect.width() * surface->bypp; + for (int y = bottomRect.top(); y < bottomRect.bottom(); y++) + { + uint32_t *dst = (uint32_t *)(((uint8_t *)surface->data) + y * surface->stride + bottomRect.left() * surface->bypp); + uint32_t *gradientBuf2 = gradientBuf + bottomRect.left() - area.left(); + std::memcpy(dst, gradientBuf2, linesize); + } + } + + } // for region + + if (gradientBuf) + free(gradientBuf); +} + +void gPixmap::blitRounded32Bit(const gPixmap &src, const eRect &pos, const eRect &clip, int cornerRadius, int edges, int flag) +{ + CornerData cornerData(cornerRadius, edges, pos.width(), pos.height(), 0, 0xFF000000); + int corners = 0; + eRect cornerRect; + if (cornerData.topLeftCornerRadius) + { + cornerRect = eRect(pos.left(), pos.top(), cornerData.topLeftCornerRadius, cornerData.topLeftCornerRadius); + cornerRect &= clip; + if (!cornerRect.empty()) + { + corners += 1; + drawAngle32Tl(surface, src, pos, cornerRect, cornerData, flag); + } + } + if (cornerData.topRightCornerRadius) + { + cornerRect = eRect(pos.right() - cornerData.topRightCornerRadius, pos.top(), cornerData.topRightCornerRadius, cornerData.topRightCornerRadius); + cornerRect &= clip; + if (!cornerRect.empty()) + { + corners += 2; + drawAngle32Tr(surface, src, pos, cornerRect, cornerData, flag); + } + } + if (cornerData.bottomLeftCornerRadius) + { + cornerRect = eRect(pos.left(), pos.bottom() - cornerData.bottomLeftCornerRadius, cornerData.bottomLeftCornerRadius, cornerData.bottomLeftCornerRadius); + cornerRect &= clip; + if (!cornerRect.empty()) + { + corners += 4; + drawAngle32Bl(surface, src, pos, cornerRect, cornerData, flag); + } + } + + if (cornerData.bottomRightCornerRadius) + { + cornerRect = eRect(pos.right() - cornerData.bottomRightCornerRadius, pos.bottom() - cornerData.bottomRightCornerRadius, cornerData.bottomRightCornerRadius, cornerData.bottomRightCornerRadius); + cornerRect &= clip; + if (!cornerRect.empty()) + { + corners += 8; + drawAngle32Br(surface, src, pos, cornerRect, cornerData, flag); + } + } + + if (cornerData.isCircle) + return; + + const int bottom = MAX(cornerData.bottomRightCornerRadius, cornerData.bottomLeftCornerRadius); + const int top = MAX(cornerData.topRightCornerRadius, cornerData.topLeftCornerRadius); + + int topw = pos.width(); + int topl = pos.left(); + int bottomw = pos.width(); + int bottoml = pos.left(); + + if (corners & 1) + { + topw -= cornerData.topLeftCornerRadius; + topl += cornerData.topLeftCornerRadius; + } + if (corners & 2) + topw -= cornerData.topRightCornerRadius; + + if (corners & 4) + { + bottomw -= cornerData.bottomLeftCornerRadius; + bottoml += cornerData.bottomLeftCornerRadius; + } + if (corners & 8) + bottomw -= cornerData.bottomRightCornerRadius; + + eRect topRect = eRect(topl, pos.top(), topw, top); + topRect &= clip; + + eRect bottomRect = eRect(bottoml, pos.bottom() - bottom, bottomw, bottom); + bottomRect &= clip; + + eRect mRect = eRect(pos.left(), pos.top() + top, pos.width(), pos.height() - top - bottom); + mRect &= clip; + + const int aLeft = pos.left(); + const int aTop = pos.top(); + + if (!mRect.empty()) + { + const int rLeft = mRect.left(); + const int rTop = mRect.top(); + const int rBottom = mRect.bottom(); + const int rWidth = mRect.width(); + int linesize = rWidth * surface->bypp; + uint32_t *srcptr = (uint32_t *)src.surface->data; + uint32_t *dstptr = (uint32_t *)surface->data; + + srcptr += (rLeft - aLeft) + (rTop - aTop) * src.surface->stride / 4; + dstptr += rLeft + rTop * surface->stride / 4; + for (int y = rTop; y < rBottom; y++) + { + if (flag & blitAlphaTest) + { + int width = rWidth; + uint32_t *src = srcptr; + uint32_t *dst = dstptr; + + while (width--) + { + if (!((*src) & 0xFF000000)) + { + src++; + dst++; + } + else + *dst++ = *src++; + } + } + else if (flag & blitAlphaBlend) + { + int width = rWidth; + gRGB *src = (gRGB *)srcptr; + gRGB *dst = (gRGB *)dstptr; + + while (width--) { + dst->b += (((src->b - dst->b) * src->a) >> 8); + dst->g += (((src->g - dst->g) * src->a) >> 8); + dst->r += (((src->r - dst->r) * src->a) >> 8); + dst->a += (((0xFF - dst->a) * src->a) >> 8); + ++src; + ++dst; + } + } + else + std::memcpy(dstptr, srcptr, linesize); + srcptr = (uint32_t *)((uint8_t *)srcptr + src.surface->stride); + dstptr = (uint32_t *)((uint8_t *)dstptr + surface->stride); + } + } + if (top && !topRect.empty()) + { + const int rLeft = topRect.left(); + const int rTop = topRect.top(); + const int rBottom = topRect.bottom(); + const int rWidth = topRect.width(); + int linesize = rWidth * surface->bypp; + uint32_t *srcptr = (uint32_t *)src.surface->data; + uint32_t *dstptr = (uint32_t *)surface->data; + + srcptr += (rLeft - aLeft) + (rTop - aTop) * src.surface->stride / 4; + dstptr += rLeft + rTop * surface->stride / 4; + for (int y = rTop; y < rBottom; y++) + { + if (flag & blitAlphaTest) + { + int width = rWidth; + uint32_t *src = srcptr; + uint32_t *dst = dstptr; + + while (width--) + { + if (!((*src) & 0xFF000000)) + { + src++; + dst++; + } + else + *dst++ = *src++; + } + } + else if (flag & blitAlphaBlend) + { + int width = rWidth; + gRGB *src = (gRGB *)srcptr; + gRGB *dst = (gRGB *)dstptr; + + while (width--) { + dst->b += (((src->b - dst->b) * src->a) >> 8); + dst->g += (((src->g - dst->g) * src->a) >> 8); + dst->r += (((src->r - dst->r) * src->a) >> 8); + dst->a += (((0xFF - dst->a) * src->a) >> 8); + ++src; + ++dst; + } + } + else + std::memcpy(dstptr, srcptr, linesize); + srcptr = (uint32_t *)((uint8_t *)srcptr + src.surface->stride); + dstptr = (uint32_t *)((uint8_t *)dstptr + surface->stride); + } + } + + if (bottom && !bottomRect.empty()) + { + const int rLeft = bottomRect.left(); + const int rTop = bottomRect.top(); + const int rBottom = bottomRect.bottom(); + const int rWidth = bottomRect.width(); + int linesize = rWidth * surface->bypp; + uint32_t *srcptr = (uint32_t *)src.surface->data; + uint32_t *dstptr = (uint32_t *)surface->data; + + srcptr += (rLeft - aLeft) + (rTop - aTop) * src.surface->stride / 4; + dstptr += rLeft + rTop * surface->stride / 4; + for (int y = rTop; y < rBottom; y++) + { + if (flag & blitAlphaTest) + { + int width = rWidth; + uint32_t *src = srcptr; + uint32_t *dst = dstptr; + + while (width--) + { + if (!((*src) & 0xFF000000)) + { + src++; + dst++; + } + else + *dst++ = *src++; + } + } + else if (flag & blitAlphaBlend) + { + int width = rWidth; + gRGB *src = (gRGB *)srcptr; + gRGB *dst = (gRGB *)dstptr; + + while (width--) { + dst->b += (((src->b - dst->b) * src->a) >> 8); + dst->g += (((src->g - dst->g) * src->a) >> 8); + dst->r += (((src->r - dst->r) * src->a) >> 8); + dst->a += (((0xFF - dst->a) * src->a) >> 8); + ++src; + ++dst; + } + } + else + std::memcpy(dstptr, srcptr, linesize); + srcptr = (uint32_t *)((uint8_t *)srcptr + src.surface->stride); + dstptr = (uint32_t *)((uint8_t *)dstptr + surface->stride); + } + } +} + +void gPixmap::blitRounded32BitScaled(const gPixmap &src, const eRect &pos, const eRect &clip, int cornerRadius, int edges, int flag) +{ + CornerData cornerData(cornerRadius, edges, pos.width(), pos.height(), 0, 0xFF000000); + int corners = 0; + eRect cornerRect; + if (cornerData.topLeftCornerRadius) + { + cornerRect = eRect(pos.left(), pos.top(), cornerData.topLeftCornerRadius, cornerData.topLeftCornerRadius); + cornerRect &= clip; + if (!cornerRect.empty()) + { + corners += 1; + drawAngle32ScaledTl(surface, src, pos, cornerRect, cornerData, flag); + } + } + if (cornerData.topRightCornerRadius) + { + cornerRect = eRect(pos.right() - cornerData.topRightCornerRadius, pos.top(), cornerData.topRightCornerRadius, cornerData.topRightCornerRadius); + cornerRect &= clip; + if (!cornerRect.empty()) + { + corners += 2; + drawAngle32ScaledTr(surface, src, pos, cornerRect, cornerData, flag); + } + } + if (cornerData.bottomLeftCornerRadius) + { + cornerRect = eRect(pos.left(), pos.bottom() - cornerData.bottomLeftCornerRadius, cornerData.bottomLeftCornerRadius, cornerData.bottomLeftCornerRadius); + cornerRect &= clip; + if (!cornerRect.empty()) + { + corners += 4; + drawAngle32ScaledBl(surface, src, pos, cornerRect, cornerData, flag); + } + } + + if (cornerData.bottomRightCornerRadius) + { + cornerRect = eRect(pos.right() - cornerData.bottomRightCornerRadius, pos.bottom() - cornerData.bottomRightCornerRadius, cornerData.bottomRightCornerRadius, cornerData.bottomRightCornerRadius); + cornerRect &= clip; + if (!cornerRect.empty()) + { + corners += 8; + drawAngle32ScaledBr(surface, src, pos, cornerRect, cornerData, flag); + } + } + + if (cornerData.isCircle) + return; + + const int bottom = MAX(cornerData.bottomRightCornerRadius, cornerData.bottomLeftCornerRadius); + const int top = MAX(cornerData.topRightCornerRadius, cornerData.topLeftCornerRadius); + + int topw = pos.width(); + int topl = pos.left(); + int bottomw = pos.width(); + int bottoml = pos.left(); + + if (corners & 1) + { + topw -= cornerData.topLeftCornerRadius; + topl += cornerData.topLeftCornerRadius; + } + if (corners & 2) + topw -= cornerData.topRightCornerRadius; + + if (corners & 4) + { + bottomw -= cornerData.bottomLeftCornerRadius; + bottoml += cornerData.bottomLeftCornerRadius; + } + if (corners & 8) + bottomw -= cornerData.bottomRightCornerRadius; + + eRect topRect = eRect(topl, pos.top(), topw, top); + topRect &= clip; + + eRect bottomRect = eRect(bottoml, pos.bottom() - bottom, bottomw, bottom); + bottomRect &= clip; + + eRect mRect = eRect(pos.left(), pos.top() + top, pos.width(), pos.height() - top - bottom); + mRect &= clip; + + const int src_bypp = src.surface->bypp; + const int dst_bypp = surface->bypp; + const int src_stride = src.surface->stride; + const int dst_stride = surface->stride; + const float scaleX = (float)src.size().width() / (float)pos.width(); + const float scaleY = (float)src.size().height() / (float)pos.height(); + const int aLeft = pos.left(); + const int aTop = pos.top(); + + if (!mRect.empty()) + { + const int rLeft = mRect.left(); + const int rRight = mRect.right(); + const int rTop = mRect.top(); + const int rBottom = mRect.bottom(); + uint8_t *dst_row = (uint8_t *)surface->data + rLeft * dst_bypp + rTop * dst_stride; + if (flag & blitAlphaTest) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)src.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + + for (int x = rLeft; x < rRight; ++x) + { + int src_x = (int)((x - aLeft) * scaleX); + const uint32_t *src = (const uint32_t *)(src_row + src_x * src_bypp); + if (*src & 0x80000000) + *dst = *src; + dst++; + } + dst_row += dst_stride; + } + } + else if (flag & blitAlphaBlend) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)src.surface->data + src_y * src_stride; + gRGB *dst = (gRGB *)dst_row; + + for (int x = rLeft; x < rRight; ++x) + { + int src_x = (int)((x - aLeft) * scaleX); + const gRGB *src = (gRGB *)(src_row + src_x * src_bypp); + dst->b += (((src->b - dst->b) * src->a) >> 8); + dst->g += (((src->g - dst->g) * src->a) >> 8); + dst->r += (((src->r - dst->r) * src->a) >> 8); + dst->a += (((0xFF - dst->a) * src->a) >> 8); + dst++; + } + dst_row += dst_stride; + } + } + else + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)src.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + + for (int x = rLeft; x < rRight; ++x) + { + int src_x = (int)((x - aLeft) * scaleX); + const uint32_t *src = (const uint32_t *)(src_row + src_x * src_bypp); + *dst++ = *src; + } + dst_row += dst_stride; + } + } + } + if (top && !topRect.empty()) + { + const int rLeft = topRect.left(); + const int rRight = topRect.right(); + const int rTop = topRect.top(); + const int rBottom = topRect.bottom(); + uint8_t *dst_row = (uint8_t *)surface->data + rLeft * dst_bypp + rTop * dst_stride; + + if (flag & blitAlphaTest) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)src.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + + for (int x = rLeft; x < rRight; ++x) + { + int src_x = (int)((x - aLeft) * scaleX); + const uint32_t *src = (const uint32_t *)(src_row + src_x * src_bypp); + if (*src & 0x80000000) + *dst = *src; + dst++; + } + dst_row += dst_stride; + } + } + else if (flag & blitAlphaBlend) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)src.surface->data + src_y * src_stride; + gRGB *dst = (gRGB *)dst_row; + + for (int x = rLeft; x < rRight; ++x) + { + int src_x = (int)((x - aLeft) * scaleX); + const gRGB *src = (gRGB *)(src_row + src_x * src_bypp); + dst->b += (((src->b - dst->b) * src->a) >> 8); + dst->g += (((src->g - dst->g) * src->a) >> 8); + dst->r += (((src->r - dst->r) * src->a) >> 8); + dst->a += (((0xFF - dst->a) * src->a) >> 8); + dst++; + } + dst_row += dst_stride; + } + } + else + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)src.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + + for (int x = rLeft; x < rRight; ++x) + { + int src_x = (int)((x - aLeft) * scaleX); + const uint32_t *src = (const uint32_t *)(src_row + src_x * src_bypp); + *dst = *src; + dst++; + } + dst_row += dst_stride; + } + } + } + if (bottom && !bottomRect.empty()) + { + const int rLeft = bottomRect.left(); + const int rRight = bottomRect.right(); + const int rTop = bottomRect.top(); + const int rBottom = bottomRect.bottom(); + uint8_t *dst_row = (uint8_t *)surface->data + rLeft * dst_bypp + rTop * dst_stride; + + if (flag & blitAlphaTest) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)src.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + + for (int x = rLeft; x < rRight; ++x) + { + int src_x = (int)((x - aLeft) * scaleX); + const uint32_t *src = (const uint32_t *)(src_row + src_x * src_bypp); + if (*src & 0x80000000) + *dst = *src; + dst++; + } + dst_row += dst_stride; + } + } + else if (flag & blitAlphaBlend) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)src.surface->data + src_y * src_stride; + gRGB *dst = (gRGB *)dst_row; + + for (int x = rLeft; x < rRight; ++x) + { + int src_x = (int)((x - aLeft) * scaleX); + const gRGB *src = (gRGB *)(src_row + src_x * src_bypp); + dst->b += (((src->b - dst->b) * src->a) >> 8); + dst->g += (((src->g - dst->g) * src->a) >> 8); + dst->r += (((src->r - dst->r) * src->a) >> 8); + dst->a += (((0xFF - dst->a) * src->a) >> 8); + dst++; + } + dst_row += dst_stride; + } + } + else + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)src.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + + for (int x = rLeft; x < rRight; ++x) + { + int src_x = (int)((x - aLeft) * scaleX); + const uint32_t *src = (const uint32_t *)(src_row + src_x * src_bypp); + *dst = *src; + dst++; + } + dst_row += dst_stride; + } + } + } +} + +void gPixmap::blitRounded8Bit(const gPixmap &src, const eRect &pos, const eRect &clip, int cornerRadius, int edges, int flag) +{ + + int corners = 0; + uint32_t pal[256]; + convert_palette(pal, src.surface->clut); + CornerData cornerData(cornerRadius, edges, pos.width(), pos.height(), 0, 0xFF000000); + eRect cornerRect; + if (cornerData.topLeftCornerRadius) + { + cornerRect = eRect(pos.left(), pos.top(), cornerData.topLeftCornerRadius, cornerData.topLeftCornerRadius); + cornerRect &= clip; + if (!cornerRect.empty()) + { + corners += 1; + drawAngle8Tl(surface, src, pal, pos, cornerRect, cornerData, flag); + } + } + if (cornerData.topRightCornerRadius) + { + cornerRect = eRect(pos.right() - cornerData.topRightCornerRadius, pos.top(), cornerData.topRightCornerRadius, cornerData.topRightCornerRadius); + cornerRect &= clip; + if (!cornerRect.empty()) + { + corners += 2; + drawAngle8Tr(surface, src, pal, pos, cornerRect, cornerData, flag); + } + } + if (cornerData.bottomLeftCornerRadius) + { + cornerRect = eRect(pos.left(), pos.bottom() - cornerData.bottomLeftCornerRadius, cornerData.bottomLeftCornerRadius, cornerData.bottomLeftCornerRadius); + cornerRect &= clip; + if (!cornerRect.empty()) + { + corners += 4; + drawAngle8Bl(surface, src, pal, pos, cornerRect, cornerData, flag); + } + } + + if (cornerData.bottomRightCornerRadius) + { + cornerRect = eRect(pos.right() - cornerData.bottomRightCornerRadius, pos.bottom() - cornerData.bottomRightCornerRadius, cornerData.bottomRightCornerRadius, cornerData.bottomRightCornerRadius); + cornerRect &= clip; + if (!cornerRect.empty()) + { + corners += 8; + drawAngle8Br(surface, src, pal, pos, cornerRect, cornerData, flag); + } + } + + if (cornerData.isCircle) + return; + + const int bottom = MAX(cornerData.bottomRightCornerRadius, cornerData.bottomLeftCornerRadius); + const int top = MAX(cornerData.topRightCornerRadius, cornerData.topLeftCornerRadius); + + int topw = pos.width(); + int topl = pos.left(); + int bottomw = pos.width(); + int bottoml = pos.left(); + + if (corners & 1) + { + topw -= cornerData.topLeftCornerRadius; + topl += cornerData.topLeftCornerRadius; + } + if (corners & 2) + topw -= cornerData.topRightCornerRadius; + + if (corners & 4) + { + bottomw -= cornerData.bottomLeftCornerRadius; + bottoml += cornerData.bottomLeftCornerRadius; + } + if (corners & 8) + bottomw -= cornerData.bottomRightCornerRadius; + + eRect topRect = eRect(topl, pos.top(), topw, top); + topRect &= clip; + + eRect bottomRect = eRect(bottoml, pos.bottom() - bottom, bottomw, bottom); + bottomRect &= clip; + + eRect mRect = eRect(pos.left(), pos.top() + top, pos.width(), pos.height() - top - bottom); + mRect &= clip; + + if (!mRect.empty()) + { + const uint8_t *srcptr = (uint8_t *)src.surface->data; + uint32_t *dstptr = (uint32_t *)surface->data; + + srcptr += (mRect.left() - pos.left()) + (mRect.top() - pos.top()) * src.surface->stride; + dstptr += mRect.left() + mRect.top() * surface->stride / 4; + for (int y = mRect.bottom(); y > mRect.top(); --y) + { + if (flag & blitAlphaTest) + { + blit_8i_to_32_at((uint32_t *)dstptr, srcptr, pal, mRect.width()); + } + else if (flag & blitAlphaBlend) + { + blit_8i_to_32_ab((gRGB *)dstptr, srcptr, (const gRGB *)pal, mRect.width()); + } + else + blit_8i_to_32((uint32_t *)dstptr, srcptr, pal, mRect.width()); + srcptr += src.surface->stride; + dstptr = (uint32_t *)((uint8_t *)dstptr + surface->stride); + } + } + if (top && !topRect.empty()) + { + const uint8_t *srcptr = (uint8_t *)src.surface->data; + uint32_t *dstptr = (uint32_t *)surface->data; + + srcptr += (topRect.left() - pos.left()) + (topRect.top() - pos.top()) * src.surface->stride; + dstptr += topRect.left() + topRect.top() * surface->stride / 4; + for (int y = topRect.top(); y < topRect.bottom(); y++) + { + if (flag & blitAlphaTest) + { + blit_8i_to_32_at((uint32_t *)dstptr, srcptr, pal, topRect.width()); + } + else if (flag & blitAlphaBlend) + { + blit_8i_to_32_ab((gRGB *)dstptr, srcptr, (const gRGB *)pal, topRect.width()); + } + else + blit_8i_to_32((uint32_t *)dstptr, srcptr, pal, topRect.width()); + srcptr += src.surface->stride; + dstptr = (uint32_t *)((uint8_t *)dstptr + surface->stride); + } + } + + if (bottom && !bottomRect.empty()) + { + const uint8_t *srcptr = (uint8_t *)src.surface->data; + uint32_t *dstptr = (uint32_t *)surface->data; + + srcptr += (bottomRect.left() - pos.left()) + (bottomRect.top() - pos.top()) * src.surface->stride; + dstptr += bottomRect.left() + (bottomRect.top()) * surface->stride / 4; + for (int y = (bottomRect.top() - pos.top()); y < (bottomRect.top() - pos.top() + bottom); y++) + { + if (flag & blitAlphaTest) + { + blit_8i_to_32_at((uint32_t *)dstptr, srcptr, pal, bottomRect.width()); + } + else if (flag & blitAlphaBlend) + { + blit_8i_to_32_ab((gRGB *)dstptr, srcptr, (const gRGB *)pal, bottomRect.width()); + } + else + blit_8i_to_32((uint32_t *)dstptr, srcptr, pal, bottomRect.width()); + srcptr += src.surface->stride; + dstptr = (uint32_t *)((uint8_t *)dstptr + surface->stride); + } + } +} + +void gPixmap::blitRounded8BitScaled(const gPixmap &src, const eRect &pos, const eRect &clip, int cornerRadius, int edges, int flag) +{ + int corners = 0; + uint32_t pal[256]; + convert_palette(pal, src.surface->clut); + CornerData cornerData(cornerRadius, edges, pos.width(), pos.height(), 0, 0xFF000000); + eRect cornerRect; + + if (cornerData.topLeftCornerRadius) + { + cornerRect = eRect(pos.left(), pos.top(), cornerData.topLeftCornerRadius, cornerData.topLeftCornerRadius); + cornerRect &= clip; + if (!cornerRect.empty()) + { + corners += 1; + drawAngle8ScaledTl(surface, src, pal, pos, cornerRect, cornerData, flag); + } + } + if (cornerData.topRightCornerRadius) + { + cornerRect = eRect(pos.right() - cornerData.topRightCornerRadius, pos.top(), cornerData.topRightCornerRadius, cornerData.topRightCornerRadius); + cornerRect &= clip; + if (!cornerRect.empty()) + { + corners += 2; + drawAngle8ScaledTr(surface, src, pal, pos, cornerRect, cornerData, flag); + } + } + if (cornerData.bottomLeftCornerRadius) + { + cornerRect = eRect(pos.left(), pos.bottom() - cornerData.bottomLeftCornerRadius, cornerData.bottomLeftCornerRadius, cornerData.bottomLeftCornerRadius); + cornerRect &= clip; + if (!cornerRect.empty()) + { + corners += 4; + drawAngle8ScaledBl(surface, src, pal, pos, cornerRect, cornerData, flag); + } + } + + if (cornerData.bottomRightCornerRadius) + { + cornerRect = eRect(pos.right() - cornerData.bottomRightCornerRadius, pos.bottom() - cornerData.bottomRightCornerRadius, cornerData.bottomRightCornerRadius, cornerData.bottomRightCornerRadius); + cornerRect &= clip; + if (!cornerRect.empty()) + { + corners += 8; + drawAngle8ScaledBr(surface, src, pal, pos, cornerRect, cornerData, flag); + } + } + + if (cornerData.isCircle) + return; + + const int bottom = MAX(cornerData.bottomRightCornerRadius, cornerData.bottomLeftCornerRadius); + const int top = MAX(cornerData.topRightCornerRadius, cornerData.topLeftCornerRadius); + + int topw = pos.width(); + int topl = pos.left(); + int bottomw = pos.width(); + int bottoml = pos.left(); + + if (corners & 1) + { + topw -= cornerData.topLeftCornerRadius; + topl += cornerData.topLeftCornerRadius; + } + if (corners & 2) + topw -= cornerData.topRightCornerRadius; + + if (corners & 4) + { + bottomw -= cornerData.bottomLeftCornerRadius; + bottoml += cornerData.bottomLeftCornerRadius; + } + if (corners & 8) + bottomw -= cornerData.bottomRightCornerRadius; + + eRect topRect = eRect(topl, pos.top(), topw, top); + topRect &= clip; + + eRect bottomRect = eRect(bottoml, pos.bottom() - bottom, bottomw, bottom); + bottomRect &= clip; + + eRect mRect = eRect(pos.left(), pos.top() + top, pos.width(), pos.height() - top - bottom); + mRect &= clip; + + const int src_bypp = src.surface->bypp; + const int dst_bypp = surface->bypp; + const int src_stride = src.surface->stride; + const int dst_stride = surface->stride; + const float scaleX = (float)src.size().width() / (float)pos.width(); + const float scaleY = (float)src.size().height() / (float)pos.height(); + const int aLeft = pos.left(); + const int aTop = pos.top(); + + if (!mRect.empty()) + { + const int rLeft = mRect.left(); + const int rRight = mRect.right(); + const int rTop = mRect.top(); + const int rBottom = mRect.bottom(); + uint8_t *dst_row = (uint8_t *)surface->data + rLeft * dst_bypp + rTop * dst_stride; + if (flag & blitAlphaTest) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)src.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + + for (int x = rLeft; x < rRight; ++x) + { + int src_x = (int)((x - aLeft) * scaleX); + const uint8_t *src = src_row + src_x * src_bypp; + if (pal[*src] & 0x80000000) + *dst = pal[*src]; + dst++; + } + dst_row += dst_stride; + } + } + else if (flag & blitAlphaBlend) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)src.surface->data + src_y * src_stride; + gRGB *dst = (gRGB *)dst_row; + + for (int x = rLeft; x < rRight; ++x) + { + int src_x = (int)((x - aLeft) * scaleX); + const uint8_t *src = src_row + src_x * src_bypp; + dst->alpha_blend(pal[*src]); + dst++; + } + dst_row += dst_stride; + } + } + else + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)src.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + + for (int x = rLeft; x < rRight; ++x) + { + int src_x = (int)((x - aLeft) * scaleX); + const uint8_t *src = src_row + src_x * src_bypp; + *dst = pal[*src]; + dst++; + } + dst_row += dst_stride; + } + } + } + if (top && !topRect.empty()) + { + const int rLeft = topRect.left(); + const int rRight = topRect.right(); + const int rTop = topRect.top(); + const int rBottom = topRect.bottom(); + uint8_t *dst_row = (uint8_t *)surface->data + rLeft * dst_bypp + rTop * dst_stride; + + if (flag & blitAlphaTest) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)src.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + + for (int x = rLeft; x < rRight; ++x) + { + int src_x = (int)((x - aLeft) * scaleX); + const uint8_t *src = src_row + src_x * src_bypp; + if (pal[*src] & 0x80000000) + *dst = pal[*src]; + dst++; + } + dst_row += dst_stride; + } + } + else if (flag & blitAlphaBlend) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)src.surface->data + src_y * src_stride; + gRGB *dst = (gRGB *)dst_row; + + for (int x = rLeft; x < rRight; ++x) + { + int src_x = (int)((x - aLeft) * scaleX); + const uint8_t *src = src_row + src_x * src_bypp; + dst->alpha_blend(pal[*src]); + dst++; + } + dst_row += dst_stride; + } + } + else + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)src.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + + for (int x = rLeft; x < rRight; ++x) + { + int src_x = (int)((x - aLeft) * scaleX); + const uint8_t *src = src_row + src_x * src_bypp; + *dst = pal[*src]; + dst++; + } + dst_row += dst_stride; + } + } + } + if (bottom && !bottomRect.empty()) + { + const int rLeft = bottomRect.left(); + const int rRight = bottomRect.right(); + const int rTop = bottomRect.top(); + const int rBottom = bottomRect.bottom(); + uint8_t *dst_row = (uint8_t *)surface->data + rLeft * dst_bypp + rTop * dst_stride; + + if (flag & blitAlphaTest) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)src.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + + for (int x = rLeft; x < rRight; ++x) + { + int src_x = (int)((x - aLeft) * scaleX); + const uint8_t *src = src_row + src_x * src_bypp; + if (pal[*src] & 0x80000000) + *dst = pal[*src]; + dst++; + } + dst_row += dst_stride; + } + } + else if (flag & blitAlphaBlend) + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)src.surface->data + src_y * src_stride; + gRGB *dst = (gRGB *)dst_row; + + for (int x = rLeft; x < rRight; ++x) + { + int src_x = (int)((x - aLeft) * scaleX); + const uint8_t *src = src_row + src_x * src_bypp; + dst->alpha_blend(pal[*src]); + dst++; + } + dst_row += dst_stride; + } + } + else + { + for (int y = rTop; y < rBottom; ++y) + { + int src_y = (int)((y - aTop) * scaleY); + const uint8_t *src_row = (const uint8_t *)src.surface->data + src_y * src_stride; + uint32_t *dst = (uint32_t *)dst_row; + + for (int x = rLeft; x < rRight; ++x) + { + int src_x = (int)((x - aLeft) * scaleX); + const uint8_t *src = src_row + src_x * src_bypp; + *dst = pal[*src]; + dst++; + } + dst_row += dst_stride; + } + } + } +} + +void gPixmap::blit(const gPixmap &src, const eRect &_pos, const gRegion &clip, int cornerRadius, int edges, int flag) { bool accel = (surface->data_phys && src.surface->data_phys); bool accumulate = accel && (gAccel::getInstance()->accumulate() >= 0); int accelerationthreshold = GFX_SURFACE_BLIT_ACCELERATION_THRESHOLD; -// eDebug("[gPixmap] blit: -> %d,%d+%d,%d -> %d,%d+%d,%d, flags=0x%x, accel=%d", -// _pos.x(), _pos.y(), _pos.width(), _pos.height(), -// clip.extends.x(), clip.extends.y(), clip.extends.width(), clip.extends.height(), -// flag, accel); eRect pos = _pos; -// eDebug("[gPixmap] source size: %d %d", src.size().width(), src.size().height()); + // eDebug("[gPixmap] source size: %d %d", src.size().width(), src.size().height()); int scale_x = FIX, scale_y = FIX; @@ -470,7 +1645,7 @@ void gPixmap::blit(const gPixmap &src, const eRect &_pos, const gRegion &clip, i { // pos' size is ignored if left or top aligning. // if its size isn't set, centre and right/bottom aligning is ignored - + if (_pos.size().isValid()) { if (flag & blitHAlignCenter) @@ -565,14 +1740,33 @@ void gPixmap::blit(const gPixmap &src, const eRect &_pos, const gRegion &clip, i eRect srcarea = area; srcarea.moveBy(-pos.x(), -pos.y()); -// eDebug("[gPixmap] srcarea before scale: %d %d %d %d", -// srcarea.x(), srcarea.y(), srcarea.width(), srcarea.height()); + // eDebug("[gPixmap] srcarea before scale: %d %d %d %d", + // srcarea.x(), srcarea.y(), srcarea.width(), srcarea.height()); if (flag & blitScale) srcarea = eRect(srcarea.x() * FIX / scale_x, srcarea.y() * FIX / scale_y, srcarea.width() * FIX / scale_x, srcarea.height() * FIX / scale_y); -// eDebug("[gPixmap] srcarea after scale: %d %d %d %d", -// srcarea.x(), srcarea.y(), srcarea.width(), srcarea.height()); + // eDebug("[gPixmap] srcarea after scale: %d %d %d %d", + // srcarea.x(), srcarea.y(), srcarea.width(), srcarea.height()); + if (cornerRadius && surface->bpp == 32) + { + if (src.surface->bpp == 32) + { + if (flag & blitScale) + blitRounded32BitScaled(src, pos, clip.rects[i], cornerRadius, edges, flag); + else + blitRounded32Bit(src, pos, clip.rects[i], cornerRadius, edges, flag); + } + else + { + if (flag & blitScale) + blitRounded8BitScaled(src, pos, clip.rects[i], cornerRadius, edges, flag); + else + blitRounded8Bit(src, pos, clip.rects[i], cornerRadius, edges, flag); + } + + continue; + } #ifdef FORCE_NO_ACCELNEVER accel = false; #else @@ -731,7 +1925,8 @@ void gPixmap::blit(const gPixmap &src, const eRect &_pos, const gRegion &clip, i gRGB *dst = (gRGB*)dstptr; for (int x = 0; x < width; ++x) { - dst->alpha_blend(src_row_ptr[(x * src_width) / width]); + const gRGB &src_pixel = src_row_ptr[(x * src_width) / width]; + dst->alpha_blend(src_pixel); ++dst; } dstptr += surface->stride; diff --git a/lib/gdi/gpixmap.h b/lib/gdi/gpixmap.h index 8a1a07e9e7a..112ce2e3e48 100644 --- a/lib/gdi/gpixmap.h +++ b/lib/gdi/gpixmap.h @@ -9,6 +9,7 @@ #include #include #include +#include struct gRGB { @@ -164,6 +165,7 @@ struct gUnmanagedSurface gPalette clut; void *data; int data_phys; + bool transparent = true; gUnmanagedSurface(); gUnmanagedSurface(int width, int height, int bpp); @@ -202,6 +204,14 @@ class gPixmap: public iObject blitVAlignBottom = 128 }; + enum + { + RADIUS_TOP_LEFT = 1, + RADIUS_TOP_RIGHT = 2, + RADIUS_BOTTOM_LEFT = 4, + RADIUS_BOTTOM_RIGHT = 8, + }; + enum { accelNever = -1, accelAuto = 0, @@ -228,13 +238,140 @@ class gPixmap: public iObject void fill(const gRegion &clip, const gColor &color); void fill(const gRegion &clip, const gRGB &color); - void blit(const gPixmap &src, const eRect &pos, const gRegion &clip, int flags=0); + void blit(const gPixmap &src, const eRect &pos, const gRegion &clip, int cornerRadius, int edges, int flags=0); + + void blitRounded32Bit(const gPixmap &src, const eRect &pos, const eRect &clip, int cornerRadius, int edges, int flag); + void blitRounded32BitScaled(const gPixmap &src, const eRect &pos, const eRect &clip, int cornerRadius, int edges, int flag); + void blitRounded8Bit(const gPixmap &src, const eRect &pos, const eRect &clip, int cornerRadius, int edges, int flag); + void blitRounded8BitScaled(const gPixmap &src, const eRect &pos, const eRect &clip, int cornerRadius, int edges, int flag); void mergePalette(const gPixmap &target); void line(const gRegion &clip, ePoint start, ePoint end, gColor color); void line(const gRegion &clip, ePoint start, ePoint end, gRGB color); void line(const gRegion &clip, ePoint start, ePoint end, unsigned int color); + + void drawRectangle(const gRegion ®ion, const eRect &area, const gRGB &backgroundColor, const gRGB &borderColor, int borderWidth, const std::vector &gradientColors, uint8_t direction, int radius, uint8_t edges, bool alphablend, int gradientFullSize = 0); }; SWIG_TEMPLATE_TYPEDEF(ePtr, gPixmapPtr); + +#ifndef SWIG +struct CornerData +{ + int width; + int height; + int topLeftCornerRadius; + int topLeftCornerSRadius; + int topLeftCornerDRadius; + int topRightCornerRadius; + int topRightCornerSRadius; + int topRightCornerDRadius; + int bottomLeftCornerRadius; + int bottomLeftCornerSRadius; + int bottomLeftCornerDRadius; + int bottomRightCornerRadius; + int bottomRightCornerSRadius; + int bottomRightCornerDRadius; + int borderWidth; + int cornerRadius; + int w_topRightCornerRadius; + int h_bottomLeftCornerRadius; + int w_bottomRightCornerRadius; + int h_bottomRightCornerRadius; + uint32_t borderCol; + + bool radiusSet = false; + bool isCircle = false; + + std::unordered_map RadiusData; + + CornerData(int radius, uint8_t edges, int h, int w, int bw, uint32_t borderColor) + { + cornerRadius = checkRadiusValue(radius, h, w); + radiusSet = cornerRadius > 0; + topLeftCornerRadius = (gPixmap::RADIUS_TOP_LEFT & edges) ? cornerRadius: 0; + topRightCornerRadius = (gPixmap::RADIUS_TOP_RIGHT & edges) ? cornerRadius: 0; + bottomLeftCornerRadius = (gPixmap::RADIUS_BOTTOM_LEFT & edges) ? cornerRadius: 0; + bottomRightCornerRadius = (gPixmap::RADIUS_BOTTOM_RIGHT & edges) ? cornerRadius: 0; + topLeftCornerSRadius = topLeftCornerRadius * topLeftCornerRadius; + topLeftCornerDRadius = (topLeftCornerRadius - 1) * (topLeftCornerRadius - 1); + topRightCornerSRadius = topRightCornerRadius * topRightCornerRadius; + topRightCornerDRadius = (topRightCornerRadius - 1) * (topRightCornerRadius - 1); + bottomLeftCornerSRadius = bottomLeftCornerRadius * bottomLeftCornerRadius; + bottomLeftCornerDRadius = (bottomLeftCornerRadius - 1) * (bottomLeftCornerRadius - 1); + bottomRightCornerSRadius = bottomRightCornerRadius * bottomRightCornerRadius; + bottomRightCornerDRadius = (bottomRightCornerRadius - 1) * (bottomRightCornerRadius - 1); + width = h; + height = w; + borderWidth = bw; + borderCol = borderColor; + + w_topRightCornerRadius = w - topRightCornerRadius; + if(width > height) + w_topRightCornerRadius += (width - height); + else if (height > width) + w_topRightCornerRadius -= (height - width); + + h_bottomLeftCornerRadius = h - bottomLeftCornerRadius; + if(width > height) + h_bottomLeftCornerRadius -= (width - height); + else if (height > width) + h_bottomLeftCornerRadius += (height - width); + + w_bottomRightCornerRadius = w - bottomRightCornerRadius; + if(width > height) + w_bottomRightCornerRadius += (width - height); + else if (height > width) + w_bottomRightCornerRadius -= (height - width); + + h_bottomRightCornerRadius = h - bottomRightCornerRadius; + if(width > height) + h_bottomRightCornerRadius -= (width - height); + else if (height > width) + h_bottomRightCornerRadius += (height - width); + + isCircle = ((edges == 15) && (width == height) && (cornerRadius == width / 2)); + caclCornerAlpha(); + } + + int checkRadiusValue(int r, const int w, const int h) + { + int minDimension = (w < h) ? w : h; + if (r > minDimension / 2) { + r = minDimension / 2; + } + return r; + } + + void caclCornerAlpha() + { + int dx = 0, dy = 0, squared_dst = 0; + double alpha = 0.0, distance = 0.0; + int r = cornerRadius; + for (int y = 0; y < r; y++) + { + for (int x = 0; x < r; x++) + { + dx = r - x - 1; + dy = r - y - 1; + squared_dst = dx * dx + dy * dy; + if (squared_dst <= (r - 1) * (r - 1)) + continue; + else if (squared_dst >= r * r) + continue; + else + { + if (RadiusData.find(squared_dst) == RadiusData.end()) + { + distance = sqrt(squared_dst); + alpha = (r - distance); + RadiusData[squared_dst] = alpha; + } + } + } + } + } +}; +#endif + #endif diff --git a/lib/gdi/grc.cpp b/lib/gdi/grc.cpp index b2179bcbd95..bd1b5f00d0f 100644 --- a/lib/gdi/grc.cpp +++ b/lib/gdi/grc.cpp @@ -1,97 +1,117 @@ #include +#include #include #include #include #include +#include #ifdef USE_LIBVUGLES2 #include #endif + #ifndef SYNC_PAINT void *gRC::thread_wrapper(void *ptr) { - return ((gRC*)ptr)->thread(); + return ((gRC *)ptr)->thread(); } #endif -gRC *gRC::instance=0; +gRC *gRC::instance = 0; -gRC::gRC(): rp(0), wp(0) +gRC::gRC() : rp(0), wp(0) #ifdef SYNC_PAINT -,m_notify_pump(eApp, 0, "gRC") + , + m_notify_pump(eApp, 0, "gRC") #else -,m_notify_pump(eApp, 1, "gRC") + , + m_notify_pump(eApp, 1, "gRC") #endif + , + m_spinner_enabled(0), m_spinneronoff(1), m_prev_idle_count(0) // NOSONAR { ASSERT(!instance); - instance=this; + instance = this; CONNECT(m_notify_pump.recv_msg, gRC::recv_notify); #ifndef SYNC_PAINT pthread_mutex_init(&mutex, 0); pthread_cond_init(&cond, 0); pthread_attr_t attr; pthread_attr_init(&attr); - if (pthread_attr_setstacksize(&attr, 2048*1024) != 0) - eDebug("[gRC] pthread_attr_setstacksize failed"); + if (pthread_attr_setstacksize(&attr, 2048 * 1024) != 0) + eDebug("[gRC] Error: pthread_attr_setstacksize failed!"); int res = pthread_create(&the_thread, &attr, thread_wrapper, this); pthread_attr_destroy(&attr); if (res) - eFatal("[gRC] thread couldn't be created"); + eFatal("[gRC] Error: Thread couldn't be created!"); else - eDebug("[gRC] thread created successfully"); + eDebug("[gRC] Thread created successfully."); +#endif +} + +#ifdef CONFIG_ION +void gRC::lock() +{ +#ifndef SYNC_PAINT + pthread_mutex_lock(&mutex); #endif - m_spinner_enabled = 0; - m_spinneronoff = 1; } +void gRC::unlock() +{ +#ifndef SYNC_PAINT + pthread_mutex_unlock(&mutex); +#endif +} +#endif + DEFINE_REF(gRC); gRC::~gRC() { - instance=0; - + instance = 0; gOpcode o; - o.opcode=gOpcode::shutdown; + o.opcode = gOpcode::shutdown; submit(o); #ifndef SYNC_PAINT - eDebug("[gRC] waiting for gRC thread shutdown"); + eDebug("[gRC] Waiting for gRC thread shutdown."); pthread_join(the_thread, 0); - eDebug("[gRC] thread has finished"); + eDebug("[gRC] Thread has finished."); #endif } void gRC::submit(const gOpcode &o) { - while(1) + while (1) { #ifndef SYNC_PAINT pthread_mutex_lock(&mutex); #endif - int tmp=wp+1; - if ( tmp == MAXSIZE ) - tmp=0; - if ( tmp == rp ) + int tmp = wp + 1; + if (tmp == MAXSIZE) + tmp = 0; + if (tmp == rp) { #ifndef SYNC_PAINT - pthread_cond_signal(&cond); // wakeup gdi thread + pthread_cond_signal(&cond); // wakeup gdi thread pthread_mutex_unlock(&mutex); #else thread(); #endif - //eDebug("[gRC] render buffer full..."); - //fflush(stdout); - usleep(1000); // wait 1 msec + // eDebug("[gRC] Render buffer full."); + // fflush(stdout); + usleep(1000); // wait 1 msec continue; } - int free=rp-wp; - if ( free <= 0 ) - free+=MAXSIZE; - queue[wp++]=o; - if ( wp == MAXSIZE ) + int free = rp - wp; + if (free <= 0) + free += MAXSIZE; + queue[wp++] = o; + if (wp == MAXSIZE) wp = 0; - if (o.opcode==gOpcode::flush||o.opcode==gOpcode::shutdown||o.opcode==gOpcode::notify) + if (o.opcode == gOpcode::flush || o.opcode == gOpcode::shutdown || o.opcode == gOpcode::notify) #ifndef SYNC_PAINT - pthread_cond_signal(&cond); // wakeup gdi thread + pthread_cond_signal(&cond); // wakeup gdi thread pthread_mutex_unlock(&mutex); #else thread(); // paint @@ -104,7 +124,8 @@ void *gRC::thread() { int need_notify = 0; #ifdef USE_LIBVUGLES2 - if (gles_open()) { + if (gles_open()) + { gles_state_open(); gles_viewport(720, 576, 720 * 4); } @@ -119,26 +140,27 @@ void *gRC::thread() #ifndef SYNC_PAINT pthread_mutex_lock(&mutex); #endif - if ( rp != wp ) + if (rp != wp) { - /* make sure the spinner is not displayed when something is painted */ + /* make sure the spinner is not displayed when something is painted */ disableSpinner(); gOpcode o(queue[rp++]); - if ( rp == MAXSIZE ) - rp=0; + if (rp == MAXSIZE) + rp = 0; #ifndef SYNC_PAINT pthread_mutex_unlock(&mutex); #endif - if (o.opcode==gOpcode::shutdown) + if (o.opcode == gOpcode::shutdown) break; - else if (o.opcode==gOpcode::notify) + else if (o.opcode == gOpcode::notify) need_notify = 1; - else if (o.opcode==gOpcode::setCompositing) + else if (o.opcode == gOpcode::setCompositing) { m_compositing = o.parm.setCompositing; m_compositing->Release(); - } else if(o.dc) + } + else if (o.dc) { o.dc->exec(&o); // o.dc is a gDC* filled with grabref... so we must release it here @@ -153,21 +175,21 @@ void *gRC::thread() m_notify_pump.send(1); } #ifndef SYNC_PAINT - while(rp == wp) + while (rp == wp) { - /* when the main thread is non-idle for a too long time without any display output, - we want to display a spinner. */ - struct timespec timeout = {}; + /* when the main thread is non-idle for a too long time without any display output, + we want to display a spinner. */ + struct timespec timeout; clock_gettime(CLOCK_REALTIME, &timeout); if (m_spinner_enabled) { - timeout.tv_nsec += 100*1000*1000; + timeout.tv_nsec += 100 * 1000 * 1000; /* yes, this is required. */ - if (timeout.tv_nsec > 1000*1000*1000) + if (timeout.tv_nsec > 1000 * 1000 * 1000) { - timeout.tv_nsec -= 1000*1000*1000; + timeout.tv_nsec -= 1000 * 1000 * 1000; timeout.tv_sec++; } } @@ -191,9 +213,14 @@ void *gRC::thread() if (!idle) { if (!m_spinner_enabled) - eDebug("[gRC] main thread is non-idle! display spinner!"); + { + eDebug("[gRC] Warning: Main thread is busy, displaying spinner!"); + std::ofstream dummy("/tmp/doPythonStackTrace"); + dummy.close(); + } enableSpinner(); - } else + } + else disableSpinner(); } pthread_mutex_unlock(&mutex); @@ -224,7 +251,7 @@ void gRC::enableSpinner() { if (!m_spinner_dc) { - eDebug("[gRC] enabelSpinner: no spinner DC!"); + eDebug("[gRC] enableSpinner Error: No spinner DC!"); return; } @@ -246,7 +273,7 @@ void gRC::disableSpinner() if (!m_spinner_dc) { - eDebug("[gRC] disableSpinner: no spinner DC!"); + eDebug("[gRC] disableSpinner Error: No spinner DC!"); return; } @@ -261,11 +288,11 @@ void gRC::disableSpinner() static int gPainter_instances; -gPainter::gPainter(gDC *dc, eRect rect): m_dc(dc), m_rc(gRC::getInstance()) +gPainter::gPainter(gDC *dc, eRect rect) : m_dc(dc), m_rc(gRC::getInstance()) { -// ASSERT(!gPainter_instances); + // ASSERT(!gPainter_instances); gPainter_instances++; -// begin(rect); + // begin(rect); } gPainter::~gPainter() @@ -276,7 +303,7 @@ gPainter::~gPainter() void gPainter::setBackgroundColor(const gColor &color) { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; gOpcode o; o.opcode = gOpcode::setBackgroundColor; @@ -289,7 +316,7 @@ void gPainter::setBackgroundColor(const gColor &color) void gPainter::setForegroundColor(const gColor &color) { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; gOpcode o; o.opcode = gOpcode::setForegroundColor; @@ -302,7 +329,7 @@ void gPainter::setForegroundColor(const gColor &color) void gPainter::setBackgroundColor(const gRGB &color) { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; gOpcode o; o.opcode = gOpcode::setBackgroundColorRGB; @@ -315,7 +342,7 @@ void gPainter::setBackgroundColor(const gRGB &color) void gPainter::setForegroundColor(const gRGB &color) { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; gOpcode o; o.opcode = gOpcode::setForegroundColorRGB; @@ -326,9 +353,50 @@ void gPainter::setForegroundColor(const gRGB &color) m_rc->submit(o); } +void gPainter::setGradient(const std::vector &colors, uint8_t orientation, bool alphablend, int fullSize) +{ + if (m_dc->islocked()) + return; + gOpcode o; + o.opcode = gOpcode::setGradient; + o.dc = m_dc.grabRef(); + o.parm.gradient = new gOpcode::para::pgradient; + o.parm.gradient->colors = colors; + o.parm.gradient->orientation = orientation; + o.parm.gradient->alphablend = alphablend; + o.parm.gradient->fullSize = fullSize; + m_rc->submit(o); +} + +void gPainter::setRadius(int radius, uint8_t edges) +{ + if (m_dc->islocked()) + return; + gOpcode o; + o.opcode = gOpcode::setRadius; + o.dc = m_dc.grabRef(); + o.parm.radius = new gOpcode::para::pradius; + o.parm.radius->radius = radius; + o.parm.radius->edges = edges; + m_rc->submit(o); +} + +void gPainter::setBorder(const gRGB &borderColor, int width) +{ + if (m_dc->islocked()) + return; + gOpcode o; + o.opcode = gOpcode::setBorder; + o.dc = m_dc.grabRef(); + o.parm.border = new gOpcode::para::pborder; + o.parm.border->color = borderColor; + o.parm.border->width = width; + m_rc->submit(o); +} + void gPainter::setFont(gFont *font) { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; gOpcode o; o.opcode = gOpcode::setFont; @@ -340,13 +408,14 @@ void gPainter::setFont(gFont *font) m_rc->submit(o); } -void gPainter::renderText(const eRect &pos, const std::string &string, int flags, gRGB bordercolor, int border) +void gPainter::renderText(const eRect &pos, const std::string &string, int flags, gRGB bordercolor, int border, int markedpos, int *offset) { - if (string.empty()) return; - if ( m_dc->islocked() ) + if (string.empty()) + return; + if (m_dc->islocked()) return; gOpcode o; - o.opcode=gOpcode::renderText; + o.opcode = gOpcode::renderText; o.dc = m_dc.grabRef(); o.parm.renderText = new gOpcode::para::prenderText; o.parm.renderText->area = pos; @@ -354,31 +423,35 @@ void gPainter::renderText(const eRect &pos, const std::string &string, int flags o.parm.renderText->flags = flags; o.parm.renderText->border = border; o.parm.renderText->bordercolor = bordercolor; + o.parm.renderText->markedpos = markedpos; + o.parm.renderText->offset = offset; + if (markedpos >= 0) + o.parm.renderText->scrollpos = eConfigManager::getConfigIntValue("config.usage.cursorscroll"); m_rc->submit(o); } void gPainter::renderPara(eTextPara *para, ePoint offset) { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; ASSERT(para); gOpcode o; - o.opcode=gOpcode::renderPara; + o.opcode = gOpcode::renderPara; o.dc = m_dc.grabRef(); o.parm.renderPara = new gOpcode::para::prenderPara; o.parm.renderPara->offset = offset; - para->AddRef(); + para->AddRef(); o.parm.renderPara->textpara = para; m_rc->submit(o); } void gPainter::fill(const eRect &area) { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; gOpcode o; - o.opcode=gOpcode::fill; + o.opcode = gOpcode::fill; o.dc = m_dc.grabRef(); o.parm.fill = new gOpcode::para::pfillRect; @@ -388,10 +461,10 @@ void gPainter::fill(const eRect &area) void gPainter::fill(const gRegion ®ion) { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; gOpcode o; - o.opcode=gOpcode::fillRegion; + o.opcode = gOpcode::fillRegion; o.dc = m_dc.grabRef(); o.parm.fillRegion = new gOpcode::para::pfillRegion; @@ -401,10 +474,10 @@ void gPainter::fill(const gRegion ®ion) void gPainter::clear() { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; gOpcode o; - o.opcode=gOpcode::clear; + o.opcode = gOpcode::clear; o.dc = m_dc.grabRef(); o.parm.fill = new gOpcode::para::pfillRect; o.parm.fill->area = eRect(); @@ -423,16 +496,16 @@ void gPainter::blit(gPixmap *pixmap, ePoint pos, const eRect &clip, int flags) void gPainter::blit(gPixmap *pixmap, const eRect &pos, const eRect &clip, int flags) { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; gOpcode o; ASSERT(pixmap); - o.opcode=gOpcode::blit; + o.opcode = gOpcode::blit; o.dc = m_dc.grabRef(); pixmap->AddRef(); - o.parm.blit = new gOpcode::para::pblit; + o.parm.blit = new gOpcode::para::pblit; o.parm.blit->pixmap = pixmap; o.parm.blit->clip = clip; o.parm.blit->flags = flags; @@ -440,24 +513,35 @@ void gPainter::blit(gPixmap *pixmap, const eRect &pos, const eRect &clip, int fl m_rc->submit(o); } +void gPainter::drawRectangle(const eRect &area) { + if ( m_dc->islocked() ) + return; + gOpcode o; + o.opcode=gOpcode::rectangle; + o.dc = m_dc.grabRef(); + o.parm.rectangle = new gOpcode::para::prectangle; + o.parm.rectangle->area = area; + m_rc->submit(o); +} + void gPainter::setPalette(gRGB *colors, int start, int len) { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; if (len <= 0) return; ASSERT(colors); gOpcode o; - o.opcode=gOpcode::setPalette; + o.opcode = gOpcode::setPalette; o.dc = m_dc.grabRef(); - gPalette *p=new gPalette; + gPalette *p = new gPalette; o.parm.setPalette = new gOpcode::para::psetPalette; - p->data=new gRGB[static_cast(len)]; + p->data = new gRGB[static_cast(len)]; - memcpy(static_cast(p->data), colors, len*sizeof(gRGB)); - p->start=start; - p->colors=len; + memcpy(static_cast(p->data), colors, len * sizeof(gRGB)); + p->start = start; + p->colors = len; o.parm.setPalette->palette = p; m_rc->submit(o); } @@ -470,7 +554,7 @@ void gPainter::setPalette(gPixmap *source) void gPainter::mergePalette(gPixmap *target) { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; ASSERT(target); gOpcode o; @@ -484,10 +568,10 @@ void gPainter::mergePalette(gPixmap *target) void gPainter::line(ePoint start, ePoint end) { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; gOpcode o; - o.opcode=gOpcode::line; + o.opcode = gOpcode::line; o.dc = m_dc.grabRef(); o.parm.line = new gOpcode::para::pline; o.parm.line->start = start; @@ -497,10 +581,10 @@ void gPainter::line(ePoint start, ePoint end) void gPainter::setOffset(ePoint val) { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; gOpcode o; - o.opcode=gOpcode::setOffset; + o.opcode = gOpcode::setOffset; o.dc = m_dc.grabRef(); o.parm.setOffset = new gOpcode::para::psetOffset; o.parm.setOffset->rel = 0; @@ -510,10 +594,10 @@ void gPainter::setOffset(ePoint val) void gPainter::moveOffset(ePoint rel) { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; gOpcode o; - o.opcode=gOpcode::setOffset; + o.opcode = gOpcode::setOffset; o.dc = m_dc.grabRef(); o.parm.setOffset = new gOpcode::para::psetOffset; o.parm.setOffset->rel = 1; @@ -523,10 +607,10 @@ void gPainter::moveOffset(ePoint rel) void gPainter::resetOffset() { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; gOpcode o; - o.opcode=gOpcode::setOffset; + o.opcode = gOpcode::setOffset; o.dc = m_dc.grabRef(); o.parm.setOffset = new gOpcode::para::psetOffset; o.parm.setOffset->rel = 0; @@ -536,7 +620,7 @@ void gPainter::resetOffset() void gPainter::resetClip(const gRegion ®ion) { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; gOpcode o; o.opcode = gOpcode::setClip; @@ -548,7 +632,7 @@ void gPainter::resetClip(const gRegion ®ion) void gPainter::clip(const gRegion ®ion) { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; gOpcode o; o.opcode = gOpcode::addClip; @@ -560,7 +644,7 @@ void gPainter::clip(const gRegion ®ion) void gPainter::clippop() { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; gOpcode o; o.opcode = gOpcode::popClip; @@ -570,7 +654,7 @@ void gPainter::clippop() void gPainter::waitVSync() { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; gOpcode o; o.opcode = gOpcode::waitVSync; @@ -580,7 +664,7 @@ void gPainter::waitVSync() void gPainter::flip() { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; gOpcode o; o.opcode = gOpcode::flip; @@ -590,7 +674,7 @@ void gPainter::flip() void gPainter::notify() { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; gOpcode o; o.opcode = gOpcode::notify; @@ -610,7 +694,7 @@ void gPainter::setCompositing(gCompositingData *comp) void gPainter::flush() { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; gOpcode o; o.opcode = gOpcode::flush; @@ -620,16 +704,16 @@ void gPainter::flush() void gPainter::end() { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; } void gPainter::sendShow(ePoint point, eSize size) { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; gOpcode o; - o.opcode=gOpcode::sendShow; + o.opcode = gOpcode::sendShow; o.dc = m_dc.grabRef(); o.parm.setShowHideInfo = new gOpcode::para::psetShowHideInfo; o.parm.setShowHideInfo->point = point; @@ -639,24 +723,47 @@ void gPainter::sendShow(ePoint point, eSize size) void gPainter::sendHide(ePoint point, eSize size) { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; gOpcode o; - o.opcode=gOpcode::sendHide; + o.opcode = gOpcode::sendHide; o.dc = m_dc.grabRef(); o.parm.setShowHideInfo = new gOpcode::para::psetShowHideInfo; o.parm.setShowHideInfo->point = point; o.parm.setShowHideInfo->size = size; m_rc->submit(o); } - #ifdef USE_LIBVUGLES2 +void gPainter::sendShowItem(long dir, ePoint point, eSize size) +{ + if (m_dc->islocked()) + return; + gOpcode o; + o.opcode = gOpcode::sendShowItem; + o.dc = m_dc.grabRef(); + o.parm.setShowItemInfo = new gOpcode::para::psetShowItemInfo; + o.parm.setShowItemInfo->dir = dir; + o.parm.setShowItemInfo->point = point; + o.parm.setShowItemInfo->size = size; + m_rc->submit(o); +} +void gPainter::setFlush(bool val) +{ + if (m_dc->islocked()) + return; + gOpcode o; + o.opcode = gOpcode::setFlush; + o.dc = m_dc.grabRef(); + o.parm.setFlush = new gOpcode::para::psetFlush; + o.parm.setFlush->enable = val; + m_rc->submit(o); +} void gPainter::setView(eSize size) { - if ( m_dc->islocked() ) + if (m_dc->islocked()) return; gOpcode o; - o.opcode=gOpcode::setView; + o.opcode = gOpcode::setView; o.dc = m_dc.grabRef(); o.parm.setViewInfo = new gOpcode::para::psetViewInfo; o.parm.setViewInfo->size = size; @@ -667,9 +774,15 @@ void gPainter::setView(eSize size) gDC::gDC() { m_spinner_pic = 0; + m_border_width = 0; + m_radius = 0; + m_radius_edges = 0; + m_gradient_orientation = 0; + m_gradient_alphablend = false; + m_gradient_fullSize = 0; } -gDC::gDC(gPixmap *pixmap): m_pixmap(pixmap) +gDC::gDC(gPixmap *pixmap) : m_pixmap(pixmap) { m_spinner_pic = 0; } @@ -710,13 +823,64 @@ void gDC::exec(const gOpcode *o) o->parm.setFont->font->Release(); delete o->parm.setFont; break; + case gOpcode::setGradient: + m_gradient_colors = o->parm.gradient->colors; + m_gradient_orientation = o->parm.gradient->orientation; + m_gradient_alphablend = o->parm.gradient->alphablend; + m_gradient_fullSize = o->parm.gradient->fullSize; + delete o->parm.gradient; + break; + case gOpcode::setRadius: + m_radius = o->parm.radius->radius; + m_radius_edges = o->parm.radius->edges; + delete o->parm.radius; + break; + case gOpcode::setBorder: + m_border_color = o->parm.border->color; + m_border_width = o->parm.border->width; + delete o->parm.border; + break; case gOpcode::renderText: { ePtr para = new eTextPara(o->parm.renderText->area); int flags = o->parm.renderText->flags; + int border = o->parm.renderText->border; + int markedpos = o->parm.renderText->markedpos; + int scrollpos = o->parm.renderText->scrollpos; + if (markedpos != -1) + border = 0; ASSERT(m_current_font); para->setFont(m_current_font); + + if (flags & gPainter::RT_ELLIPSIS) + { + if (flags & gPainter::RT_WRAP) // Remove wrap + flags -= gPainter::RT_WRAP; + std::string text = o->parm.renderText->text; + text += u8"…"; + + eTextPara testpara(o->parm.renderText->area); + testpara.setFont(m_current_font); + testpara.renderString(text.c_str(), 0); + int bw = testpara.getBoundBox().width(); + int w = o->parm.renderText->area.width(); + if (bw > w) // Available space not fit + { + float pers = (float)w / (float)bw; + text = o->parm.renderText->text; + int ns = text.size() * pers; + if ((int)text.size() > ns) + { + text.resize(ns); + text += u8"…"; + } + if (o->parm.renderText->text) + free(o->parm.renderText->text); + o->parm.renderText->text = strdup(text.c_str()); + } + } para->renderString(o->parm.renderText->text, (flags & gPainter::RT_WRAP) ? RS_WRAP : 0, o->parm.renderText->border); + if (o->parm.renderText->text) free(o->parm.renderText->text); if (flags & gPainter::RT_HALIGN_LEFT) @@ -801,7 +965,7 @@ void gDC::exec(const gOpcode *o) case gOpcode::blit: { gRegion clip; - // this code should be checked again but i'm too tired now + // this code should be checked again but i'm too tired now o->parm.blit->position.moveBy(m_current_offset); @@ -809,21 +973,39 @@ void gDC::exec(const gOpcode *o) { o->parm.blit->clip.moveBy(m_current_offset); clip.intersect(gRegion(o->parm.blit->clip), m_current_clip); - } else + } + else clip = m_current_clip; - - m_pixmap->blit(*o->parm.blit->pixmap, o->parm.blit->position, clip, o->parm.blit->flags); + if (!o->parm.blit->pixmap->surface->transparent) + o->parm.blit->flags &=~(gPixmap::blitAlphaTest|gPixmap::blitAlphaBlend); + m_pixmap->blit(*o->parm.blit->pixmap, o->parm.blit->position, clip, m_radius, m_radius_edges, o->parm.blit->flags); + m_radius = 0; + m_radius_edges = 0; o->parm.blit->pixmap->Release(); delete o->parm.blit; break; } + case gOpcode::rectangle: + { + o->parm.rectangle->area.moveBy(m_current_offset); + gRegion clip = m_current_clip & o->parm.rectangle->area; + m_pixmap->drawRectangle(clip, o->parm.rectangle->area, m_background_color_rgb, m_border_color, m_border_width, m_gradient_colors, m_gradient_orientation, m_radius, m_radius_edges, m_gradient_alphablend, m_gradient_fullSize); + m_border_width = 0; + m_radius = 0; + m_radius_edges = 0; + m_gradient_orientation = 0; + m_gradient_fullSize = 0; + m_gradient_alphablend = false; + delete o->parm.rectangle; + break; + } case gOpcode::setPalette: if (o->parm.setPalette->palette->start > m_pixmap->surface->clut.colors) o->parm.setPalette->palette->start = m_pixmap->surface->clut.colors; - if (o->parm.setPalette->palette->colors > (m_pixmap->surface->clut.colors-o->parm.setPalette->palette->start)) - o->parm.setPalette->palette->colors = m_pixmap->surface->clut.colors-o->parm.setPalette->palette->start; + if (o->parm.setPalette->palette->colors > (m_pixmap->surface->clut.colors - o->parm.setPalette->palette->start)) + o->parm.setPalette->palette->colors = m_pixmap->surface->clut.colors - o->parm.setPalette->palette->start; if (o->parm.setPalette->palette->colors) - memcpy(static_cast(m_pixmap->surface->clut.data+o->parm.setPalette->palette->start), o->parm.setPalette->palette->data, o->parm.setPalette->palette->colors*sizeof(gRGB)); + memcpy(static_cast(m_pixmap->surface->clut.data + o->parm.setPalette->palette->start), o->parm.setPalette->palette->data, o->parm.setPalette->palette->colors * sizeof(gRGB)); delete[] o->parm.setPalette->palette->data; delete o->parm.setPalette->palette; @@ -866,7 +1048,7 @@ void gDC::exec(const gOpcode *o) if (o->parm.setOffset->rel) m_current_offset += o->parm.setOffset->value; else - m_current_offset = o->parm.setOffset->value; + m_current_offset = o->parm.setOffset->value; delete o->parm.setOffset; break; case gOpcode::waitVSync: @@ -880,6 +1062,10 @@ void gDC::exec(const gOpcode *o) case gOpcode::sendHide: break; #ifdef USE_LIBVUGLES2 + case gOpcode::sendShowItem: + break; + case gOpcode::setFlush: + break; case gOpcode::setView: break; #endif @@ -893,7 +1079,7 @@ void gDC::exec(const gOpcode *o) incrementSpinner(); break; default: - eFatal("[gDC] illegal opcode %d. expect memory leak!", o->opcode); + eFatal("[gRC] gDC Error: Illegal opcode %d, expect memory leak!", o->opcode); } } @@ -901,9 +1087,9 @@ gRGB gDC::getRGB(gColor col) { if ((!m_pixmap) || (!m_pixmap->surface->clut.data)) return gRGB(col, col, col); - if (col<0) + if (col < 0) { - eFatal("[gDC] getRGB transp"); + eFatal("[gRC] gDC Error: getRGB transp!"); return gRGB(0, 0, 0, 0xFF); } return m_pixmap->surface->clut.data[col]; @@ -913,8 +1099,8 @@ void gDC::enableSpinner() { ASSERT(m_spinner_saved); - /* save the background to restore it later. We need to negative position because we want to blit from the middle of the screen. */ - m_spinner_saved->blit(*m_pixmap, eRect(-m_spinner_pos.topLeft(), eSize()), gRegion(eRect(ePoint(0, 0), m_spinner_saved->size())), 0); + /* save the background to restore it later. We need to negative position because we want to blit from the middle of the screen. */ + m_spinner_saved->blit(*m_pixmap, eRect(-m_spinner_pos.topLeft(), eSize()), gRegion(eRect(ePoint(0, 0), m_spinner_saved->size())), 0, 0 ,0); incrementSpinner(); } @@ -923,8 +1109,8 @@ void gDC::disableSpinner() { ASSERT(m_spinner_saved); - /* restore background */ - m_pixmap->blit(*m_spinner_saved, eRect(m_spinner_pos.topLeft(), eSize()), gRegion(m_spinner_pos), 0); + /* restore background */ + m_pixmap->blit(*m_spinner_saved, eRect(m_spinner_pos.topLeft(), eSize()), gRegion(m_spinner_pos), 0, 0, 0); } void gDC::incrementSpinner() @@ -948,12 +1134,12 @@ void gDC::incrementSpinner() } #endif - m_spinner_temp->blit(*m_spinner_saved, eRect(0, 0, 0, 0), eRect(ePoint(0, 0), m_spinner_pos.size())); + m_spinner_temp->blit(*m_spinner_saved, eRect(0, 0, 0, 0), eRect(ePoint(0, 0), m_spinner_pos.size()), 0, 0, 0); if (m_spinner_pic[m_spinner_i]) - m_spinner_temp->blit(*m_spinner_pic[m_spinner_i], eRect(0, 0, 0, 0), eRect(ePoint(0, 0), m_spinner_pos.size()), gPixmap::blitAlphaBlend); + m_spinner_temp->blit(*m_spinner_pic[m_spinner_i], eRect(0, 0, 0, 0), eRect(ePoint(0, 0), m_spinner_pos.size()), 0, 0, gPixmap::blitAlphaBlend); - m_pixmap->blit(*m_spinner_temp, eRect(m_spinner_pos.topLeft(), eSize()), gRegion(m_spinner_pos), 0); + m_pixmap->blit(*m_spinner_temp, eRect(m_spinner_pos.topLeft(), eSize()), gRegion(m_spinner_pos), 0, 0, 0); m_spinner_i++; m_spinner_i %= m_spinner_num; } diff --git a/lib/gdi/grc.h b/lib/gdi/grc.h index af873abb48f..2c218c56167 100644 --- a/lib/gdi/grc.h +++ b/lib/gdi/grc.h @@ -8,12 +8,13 @@ */ // for debugging use: -//#define SYNC_PAINT +// #define SYNC_PAINT #undef SYNC_PAINT #include #include #include +#include #include #include @@ -35,8 +36,12 @@ struct gOpcode renderPara, setFont, - fill, fillRegion, clear, + fill, + fillRegion, + clear, blit, + gradient, + rectangle, setPalette, mergePalette, @@ -49,9 +54,15 @@ struct gOpcode setBackgroundColorRGB, setForegroundColorRGB, + setGradient, + setRadius, + setBorder, + setOffset, - setClip, addClip, popClip, + setClip, + addClip, + popClip, flush, @@ -59,7 +70,9 @@ struct gOpcode flip, notify, - enableSpinner, disableSpinner, incrementSpinner, + enableSpinner, + disableSpinner, + incrementSpinner, shutdown, @@ -67,6 +80,8 @@ struct gOpcode sendShow, sendHide, #ifdef USE_LIBVUGLES2 + sendShowItem, + setFlush, setView, #endif } opcode; @@ -91,6 +106,9 @@ struct gOpcode int flags; int border; gRGB bordercolor; + int markedpos; + int scrollpos; + int *offset; } *renderText; struct prenderPara @@ -117,6 +135,31 @@ struct gOpcode eRect clip; } *blit; + struct pgradient + { + std::vector colors; + uint8_t orientation; + bool alphablend; + int fullSize; + } *gradient; + + struct pradius + { + int radius; + uint8_t edges; + } *radius; + + struct pborder + { + gRGB color; + int width; + } *border; + + struct prectangle + { + eRect area; + } *rectangle; + struct pmergePalette { gPixmap *target; @@ -156,6 +199,18 @@ struct gOpcode eSize size; } *setShowHideInfo; #ifdef USE_LIBVUGLES2 + struct psetShowItemInfo + { + long dir; + ePoint point; + eSize size; + } *setShowItemInfo; + + struct psetFlush + { + bool enable; + } *setFlush; + struct psetViewInfo { eSize size; @@ -166,8 +221,8 @@ struct gOpcode #define MAXSIZE 2048 - /* gRC is the singleton which controls the fifo and dispatches commands */ -class gRC: public iObject, public sigc::trackable +/* gRC is the singleton which controls the fifo and dispatches commands */ +class gRC : public iObject, public sigc::trackable { DECLARE_REF(gRC); friend class gPainter; @@ -198,6 +253,7 @@ class gRC: public iObject, public sigc::trackable ePtr m_compositing; int m_prev_idle_count; + public: gRC(); virtual ~gRC(); @@ -212,7 +268,7 @@ class gRC: public iObject, public sigc::trackable static gRC *getInstance(); }; - /* gPainter is the user frontend, which in turn sends commands through gRC */ +/* gPainter is the user frontend, which in turn sends commands through gRC */ class gPainter { ePtr m_dc; @@ -222,8 +278,9 @@ class gPainter gOpcode *beginptr; void begin(const eRect &rect); void end(); + public: - gPainter(gDC *dc, eRect rect=eRect()); + gPainter(gDC *dc, eRect rect = eRect()); virtual ~gPainter(); void setBackgroundColor(const gColor &color); @@ -232,26 +289,32 @@ class gPainter void setBackgroundColor(const gRGB &color); void setForegroundColor(const gRGB &color); + void setBorder(const gRGB &borderColor, int width); + void setGradient(const std::vector &colors, uint8_t orientation, bool alphablend, int fullSize = 0); + void setRadius(int radius, uint8_t edges); + void setFont(gFont *font); - /* flags only THESE: */ + /* flags only THESE: */ enum { - // todo, make mask. you cannot align both right AND center AND block ;) - RT_HALIGN_BIDI = 0, /* default */ + // todo, make mask. you cannot align both right AND center AND block ;) + RT_HALIGN_BIDI = 0, /* default */ RT_HALIGN_LEFT = 1, RT_HALIGN_RIGHT = 2, RT_HALIGN_CENTER = 4, RT_HALIGN_BLOCK = 8, - RT_VALIGN_TOP = 0, /* default */ + RT_VALIGN_TOP = 0, /* default */ RT_VALIGN_CENTER = 16, RT_VALIGN_BOTTOM = 32, - RT_WRAP = 64 + RT_WRAP = 64, + RT_ELLIPSIS = 128, + RT_BLEND = 256 }; - void renderText(const eRect &position, const std::string &string, int flags=0, gRGB bordercolor=gRGB(), int border=0); + void renderText(const eRect &position, const std::string &string, int flags = 0, gRGB bordercolor = gRGB(), int border = 0, int markedpos = -1, int *offset = 0); - void renderPara(eTextPara *para, ePoint offset=ePoint(0, 0)); + void renderPara(eTextPara *para, ePoint offset = ePoint(0, 0)); void fill(const eRect &area); void fill(const gRegion &area); @@ -271,11 +334,20 @@ class gPainter BT_VALIGN_BOTTOM = 128 }; + enum + { + GRADIENT_OFF = 0, + GRADIENT_VERTICAL = 1, + GRADIENT_HORIZONTAL = 2 + }; + void blitScale(gPixmap *pixmap, const eRect &pos, const eRect &clip=eRect(), int flags=0, int aflags = BT_SCALE); void blit(gPixmap *pixmap, ePoint pos, const eRect &clip=eRect(), int flags=0); void blit(gPixmap *pixmap, const eRect &pos, const eRect &clip=eRect(), int flags=0); - void setPalette(gRGB *colors, int start=0, int len=256); + void drawRectangle(const eRect &area); + + void setPalette(gRGB *colors, int start = 0, int len = 256); void setPalette(gPixmap *source); void mergePalette(gPixmap *target); @@ -298,13 +370,16 @@ class gPainter void sendShow(ePoint point, eSize size); void sendHide(ePoint point, eSize size); #ifdef USE_LIBVUGLES2 + void sendShowItem(long dir, ePoint point, eSize size); + void setFlush(bool val); void setView(eSize size); #endif }; -class gDC: public iObject +class gDC : public iObject { DECLARE_REF(gDC); + protected: ePtr m_pixmap; @@ -313,6 +388,17 @@ class gDC: public iObject ePtr m_current_font; ePoint m_current_offset; + std::vector m_gradient_colors; + uint8_t m_gradient_orientation; + bool m_gradient_alphablend; + int m_gradient_fullSize; + + int m_radius; + uint8_t m_radius_edges; + + gRGB m_border_color; + int m_border_width; + std::stack m_clip_stack; gRegion m_current_clip; @@ -320,13 +406,18 @@ class gDC: public iObject ePtr *m_spinner_pic; eRect m_spinner_pos; int m_spinner_num, m_spinner_i; + public: virtual void exec(const gOpcode *opcode); gDC(gPixmap *pixmap); gDC(); virtual ~gDC(); gRegion &getClip() { return m_current_clip; } - int getPixmap(ePtr &pm) { pm = m_pixmap; return 0; } + int getPixmap(ePtr &pm) + { + pm = m_pixmap; + return 0; + } gRGB getRGB(gColor col); virtual eSize size() { return m_pixmap->size(); } virtual int islocked() const { return 0; } diff --git a/lib/gui/ewidget.cpp b/lib/gui/ewidget.cpp index 886987a1d78..cbf3ec91bd1 100644 --- a/lib/gui/ewidget.cpp +++ b/lib/gui/ewidget.cpp @@ -23,6 +23,10 @@ eWidget::eWidget(eWidget *parent): m_animation(this), m_parent(parent ? parent-> m_current_focus = 0; m_focus_owner = 0; m_notify_child_on_position_change = 1; + m_cornerRadius = 0; + m_cornerRadiusEdges = 0; + m_have_border_color = false; + m_border_width = 0; } void eWidget::move(ePoint pos) @@ -358,15 +362,51 @@ int eWidget::event(int event, void *data, void *data2) // dumpRegion(*(gRegion*)data); if (!isTransparent()) { - if (!m_have_background_color) + bool drawborder = (m_have_border_color && m_border_width); + + if (m_have_background_color) + painter.setBackgroundColor(m_background_color); + const int r = getCornerRadius(); + + if (r) { - ePtr style; - if (!getStyle(style)) - style->paintBackground(painter, ePoint(0, 0), size()); - } else + if (r) + painter.setRadius(r, m_cornerRadiusEdges); + if (r && drawborder) + { + painter.setBackgroundColor(m_border_color); + painter.drawRectangle(eRect(ePoint(0, 0), size())); + if (r) + painter.setRadius(r, m_cornerRadiusEdges); + painter.setBackgroundColor(m_have_background_color ? m_background_color : gRGB(0, 0, 0)); + painter.drawRectangle(eRect(m_border_width, m_border_width, size().width() - m_border_width * 2, size().height() - m_border_width * 2)); + drawborder = false; + } + else + painter.drawRectangle(eRect(ePoint(0, 0), size())); + } + else { - painter.setBackgroundColor(m_background_color); - painter.clear(); + if (!m_have_background_color) + { + ePtr style; + if (!getStyle(style)) + style->paintBackground(painter, ePoint(0, 0), size()); + } + else + { + //painter.setBackgroundColor(m_background_color); + painter.clear(); + } + } + if (drawborder) + { + painter.setForegroundColor(m_border_color); + eSize s(size()); + painter.fill(eRect(0, 0, s.width(), m_border_width)); + painter.fill(eRect(0, m_border_width, m_border_width, s.height() - m_border_width)); + painter.fill(eRect(m_border_width, s.height() - m_border_width, s.width() - m_border_width, m_border_width)); + painter.fill(eRect(s.width() - m_border_width, m_border_width, m_border_width, s.height() - m_border_width)); } } else { @@ -419,3 +459,39 @@ void eWidget::notifyShowHide() for (ePtrList::iterator i(m_childs.begin()); i != m_childs.end(); ++i) i->notifyShowHide(); } + +void eWidget::setCornerRadius(int radius, int edges) +{ + m_cornerRadius = radius; + m_cornerRadiusEdges = edges; + invalidate(); +} + +void eWidget::setBorderWidth(int pixel) +{ + m_border_width = pixel; + invalidate(); +} + +void eWidget::setBorderColor(const gRGB &color) +{ + m_border_color = color; + m_have_border_color = true; + invalidate(); +} + +int eWidget::getCornerRadius() +{ + int r = m_cornerRadius; + if(r) { + const int w = m_size.width(); + const int h = m_size.height(); + if(w && h) { + int minDimension = (w < h) ? w : h; + if (r > minDimension / 2) { + r = minDimension / 2; + } + } + } + return r; +} diff --git a/lib/gui/ewidget.h b/lib/gui/ewidget.h index a0ad46b3bee..963d311410d 100644 --- a/lib/gui/ewidget.h +++ b/lib/gui/ewidget.h @@ -48,6 +48,12 @@ class eWidget void setBackgroundColor(const gRGB &col); void clearBackgroundColor(); + void setBorderWidth(int pixel); + void setBorderColor(const gRGB &color); + + void setWidgetBorderWidth(int pixel) { setBorderWidth(pixel); } + void setWidgetBorderColor(const gRGB &color) { setBorderColor(color); } + void setZPosition(int z); void setTransparent(int transp); @@ -97,6 +103,19 @@ class eWidget int m_z_position; int m_lowered; int m_notify_child_on_position_change; + + bool m_gradient_set; + bool m_gradient_alphablend; + int m_gradient_direction; + gRGB m_gradient_startcolor, m_gradient_endcolor; + + bool m_have_border_color; + int m_border_width; + gRGB m_border_color; + + int m_cornerRadius; + int m_cornerRadiusEdges; + protected: void mayKillFocus(); public: @@ -132,6 +151,23 @@ class eWidget void setPositionNotifyChild(int n) { m_notify_child_on_position_change = 1; } void notifyShowHide(); + + void setCornerRadius(int radius, int edges); + int getCornerRadiusEdges() {return m_cornerRadiusEdges;} + int getCornerRadius(); + + enum + { + RADIUS_TOP_LEFT = 1, + RADIUS_TOP_RIGHT = 2, + RADIUS_TOP = 3, + RADIUS_BOTTOM_LEFT = 4, + RADIUS_BOTTOM_RIGHT = 8, + RADIUS_BOTTOM = 12, + RADIUS_LEFT = 5, + RADIUS_RIGHT = 10, + RADIUS_ALL = 15, + }; }; extern eWidgetDesktop *getDesktop(int which); diff --git a/lib/gui/ewidgetdesktop.cpp b/lib/gui/ewidgetdesktop.cpp index 8a443f3c428..e686dc85508 100644 --- a/lib/gui/ewidgetdesktop.cpp +++ b/lib/gui/ewidgetdesktop.cpp @@ -59,7 +59,7 @@ int eWidgetDesktop::movedWidget(eWidget *root) return 0; /* native move ok */ } -void eWidgetDesktop::calcWidgetClipRegion(eWidget *widget, gRegion &parent_visible) +void eWidgetDesktop::calcWidgetClipRegion(eWidget *widget, gRegion &parent_visible, bool parent) { /* start with our clip region, clipped with the parent's */ if (widget->m_vis & eWidget::wVisShow) @@ -68,7 +68,7 @@ void eWidgetDesktop::calcWidgetClipRegion(eWidget *widget, gRegion &parent_visib widget->m_visible_region.moveBy(widget->position()); widget->m_visible_region &= parent_visible; // in parent space! - if (!widget->isTransparent()) + if (!widget->isTransparent() && (widget->m_cornerRadius == 0 || parent)) /* remove everything this widget will contain from parent's visible list, unless widget is transparent. */ parent_visible -= widget->m_visible_region; // will remove child regions too! @@ -87,7 +87,7 @@ void eWidgetDesktop::calcWidgetClipRegion(eWidget *widget, gRegion &parent_visib if (i != widget->m_childs.end()) { if (i->m_vis & eWidget::wVisShow) - calcWidgetClipRegion(*i, widget->m_visible_region); + calcWidgetClipRegion(*i, widget->m_visible_region, false); else clearVisibility(*i); } diff --git a/lib/gui/ewidgetdesktop.h b/lib/gui/ewidgetdesktop.h index 7f76430fc76..a4c39e0adfc 100644 --- a/lib/gui/ewidgetdesktop.h +++ b/lib/gui/ewidgetdesktop.h @@ -80,7 +80,7 @@ class eWidgetDesktop: public sigc::trackable void setMargins(const eRect& value) { m_margins = value; } private: ePtrList m_root; - void calcWidgetClipRegion(eWidget *widget, gRegion &parent_visible); + void calcWidgetClipRegion(eWidget *widget, gRegion &parent_visible, bool parent = true); void paintBackground(eWidgetDesktopCompBuffer *comp); eMainloop *m_mainloop; diff --git a/lib/gui/ewindow.cpp b/lib/gui/ewindow.cpp index 9e7ded23d16..ecb1781409a 100644 --- a/lib/gui/ewindow.cpp +++ b/lib/gui/ewindow.cpp @@ -138,4 +138,11 @@ void eWindow::setAnimationMode(int mode) * 0x11 = animation on */ m_animation_mode = mode; +} + +void eWindow::setCornerRadius(int radius, int edges) +{ + /* set corner radius for child, too */ + eWidget::setCornerRadius(radius, edges); + m_child->setCornerRadius(radius, edges); } \ No newline at end of file diff --git a/lib/gui/ewindow.h b/lib/gui/ewindow.h index 223a1dd4538..9fdf8827df9 100644 --- a/lib/gui/ewindow.h +++ b/lib/gui/ewindow.h @@ -23,6 +23,7 @@ class eWindow: public eWidget }; void setBackgroundColor(const gRGB &col); + void setCornerRadius(int radius, int edges); void setFlag(int flags); void clearFlag(int flags); diff --git a/lib/python/skin.py b/lib/python/skin.py index 49ddf01cc47..2f8689831d2 100644 --- a/lib/python/skin.py +++ b/lib/python/skin.py @@ -1,6 +1,6 @@ from xml.etree.cElementTree import Element, ElementTree, fromstring -from enigma import addFont, eLabel, ePixmap, ePoint, eRect, eSize, eWindow, eWindowStyleManager, eWindowStyleSkinned, getDesktop, gFont, getFontFaces, gMainDC, gRGB, BT_ALPHATEST, BT_ALPHABLEND, BT_HALIGN_CENTER, BT_HALIGN_LEFT, BT_HALIGN_RIGHT, BT_KEEP_ASPECT_RATIO, BT_SCALE, BT_VALIGN_BOTTOM, BT_VALIGN_CENTER, BT_VALIGN_TOP +from enigma import addFont, eLabel, ePixmap, ePoint, eRect, eSize, eWidget, eWindow, eWindowStyleManager, eWindowStyleSkinned, getDesktop, gFont, getFontFaces, gMainDC, gRGB, BT_ALPHATEST, BT_ALPHABLEND, BT_HALIGN_CENTER, BT_HALIGN_LEFT, BT_HALIGN_RIGHT, BT_KEEP_ASPECT_RATIO, BT_SCALE, BT_VALIGN_BOTTOM, BT_VALIGN_CENTER, BT_VALIGN_TOP from os.path import basename, dirname, isfile from Components.config import ConfigSubsection, ConfigText, config @@ -291,6 +291,26 @@ def parseValuePair(s, scale, object=None, desktop=None, size=None): def parsePosition(s, scale, object=None, desktop=None, size=None): return ePoint(*parseValuePair(s, scale, object, desktop, size)) +def parseRadius(value): + data = [x.strip() for x in value.split(";")] + if len(data) == 2: + edges = [x.strip() for x in data[1].split(",")] + edgesMask = { + "topLeft": eWidget.RADIUS_TOP_LEFT, + "topRight": eWidget.RADIUS_TOP_RIGHT, + "top": eWidget.RADIUS_TOP, + "bottomLeft": eWidget.RADIUS_BOTTOM_LEFT, + "bottomRight": eWidget.RADIUS_BOTTOM_RIGHT, + "bottom": eWidget.RADIUS_BOTTOM, + "left": eWidget.RADIUS_LEFT, + "right": eWidget.RADIUS_RIGHT, + } + edgeValue = 0 + for e in edges: + edgeValue += edgesMask.get(e, 0) + return int(data[0]), edgeValue + else: + return int(data[0]), eWidget.RADIUS_ALL def parseSize(s, scale, object=None, desktop=None): return eSize(*[max(0, x) for x in parseValuePair(s, scale, object, desktop)]) @@ -496,6 +516,12 @@ def font(self, value): def secondfont(self, value): self.guiObject.setSecondFont(parseFont(value, self.scaleTuple)) + + def widgetBorderColor(self, value): + self.guiObject.setWidgetBorderColor(parseColor(value)) + + def widgetBorderWidth(self, value): + self.guiObject.setWidgetBorderWidth(parseScale(value)) def zPosition(self, value): self.guiObject.setZPosition(int(value)) @@ -516,7 +542,7 @@ def backgroundPixmap(self, value): def selectionPixmap(self, value): self.guiObject.setSelectionPicture(loadPixmap(value, self.desktop)) - + def selectionPixmapLarge(self, value): self.guiObject.setSelectionPictureLarge(loadPixmap(value, self.desktop)) @@ -666,6 +692,10 @@ def borderColor(self, value): def borderWidth(self, value): self.guiObject.setBorderWidth(parseScale(value)) + + def cornerRadius(self, value): + radius, edgeValue = parseRadius(value) + self.guiObject.setCornerRadius(radius, edgeValue) def scrollbarSliderBorderWidth(self, value): self.guiObject.setScrollbarBorderWidth(parseScale(value)) From 2a89a9f23cb60657b2b80f77e4c31efcb4d12617 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Wed, 17 Jan 2024 13:18:02 +0000 Subject: [PATCH 046/183] dos2unix files --- lib/gdi/drawing.h | 132 +++++++++++++++++++++++----------------------- 1 file changed, 66 insertions(+), 66 deletions(-) diff --git a/lib/gdi/drawing.h b/lib/gdi/drawing.h index fa42fda503a..01b5d482012 100644 --- a/lib/gdi/drawing.h +++ b/lib/gdi/drawing.h @@ -1,67 +1,67 @@ -/* -Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License - -Copyright (c) 2023-2024 openATV - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -1. Non-Commercial Use: You may not use the Software or any derivative works - for commercial purposes without obtaining explicit permission from the - copyright holder. -2. Share Alike: If you distribute or publicly perform the Software or any - derivative works, you must do so under the same license terms, and you - must make the source code of any derivative works available to the - public. -3. Attribution: You must give appropriate credit to the original author(s) - of the Software by including a prominent notice in your derivative works. -THE SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, -ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -For more details about the CC BY-NC-SA 4.0 License, please visit: -https://creativecommons.org/licenses/by-nc-sa/4.0/ -*/ - -#ifndef __drawing__ -#define __drawing__ - -#include "gpixmap.h" -#include - -void duplicate_32fc(uint32_t *out, const uint32_t in, size_t size); -uint32_t *createGradientBuffer2(int graSize, const gRGB &startColor, const gRGB &endColor); -uint32_t *createGradientBuffer3(int graSize, const std::vector &colors); -void drawAngleTl(gUnmanagedSurface *surface, const uint32_t *src, const eRect &area, uint8_t direction, const eRect &cornerRect, const CornerData &cornerData); -void drawAngleTr(gUnmanagedSurface *surface, const uint32_t *src, const eRect &area, uint8_t direction, const eRect &cornerRect, const CornerData &cornerData); -void drawAngleBl(gUnmanagedSurface *surface, const uint32_t *src, const eRect &area, uint8_t direction, const eRect &cornerRect, const CornerData &cornerData); -void drawAngleBr(gUnmanagedSurface *surface, const uint32_t *src, const eRect &area, uint8_t direction, const eRect &cornerRect, const CornerData &cornerData); - -void drawAngle32Tl(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); -void drawAngle32Tr(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); -void drawAngle32Bl(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); -void drawAngle32Br(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); - -void drawAngle32ScaledTl(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); -void drawAngle32ScaledTr(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); -void drawAngle32ScaledBl(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); -void drawAngle32ScaledBr(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); - -void drawAngle8Tl(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); -void drawAngle8Tr(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); -void drawAngle8Bl(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); -void drawAngle8Br(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); - -void drawAngle8ScaledTl(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); -void drawAngle8ScaledTr(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); -void drawAngle8ScaledBl(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); -void drawAngle8ScaledBr(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); - +/* +Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License + +Copyright (c) 2023-2024 openATV + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +1. Non-Commercial Use: You may not use the Software or any derivative works + for commercial purposes without obtaining explicit permission from the + copyright holder. +2. Share Alike: If you distribute or publicly perform the Software or any + derivative works, you must do so under the same license terms, and you + must make the source code of any derivative works available to the + public. +3. Attribution: You must give appropriate credit to the original author(s) + of the Software by including a prominent notice in your derivative works. +THE SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, +ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more details about the CC BY-NC-SA 4.0 License, please visit: +https://creativecommons.org/licenses/by-nc-sa/4.0/ +*/ + +#ifndef __drawing__ +#define __drawing__ + +#include "gpixmap.h" +#include + +void duplicate_32fc(uint32_t *out, const uint32_t in, size_t size); +uint32_t *createGradientBuffer2(int graSize, const gRGB &startColor, const gRGB &endColor); +uint32_t *createGradientBuffer3(int graSize, const std::vector &colors); +void drawAngleTl(gUnmanagedSurface *surface, const uint32_t *src, const eRect &area, uint8_t direction, const eRect &cornerRect, const CornerData &cornerData); +void drawAngleTr(gUnmanagedSurface *surface, const uint32_t *src, const eRect &area, uint8_t direction, const eRect &cornerRect, const CornerData &cornerData); +void drawAngleBl(gUnmanagedSurface *surface, const uint32_t *src, const eRect &area, uint8_t direction, const eRect &cornerRect, const CornerData &cornerData); +void drawAngleBr(gUnmanagedSurface *surface, const uint32_t *src, const eRect &area, uint8_t direction, const eRect &cornerRect, const CornerData &cornerData); + +void drawAngle32Tl(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); +void drawAngle32Tr(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); +void drawAngle32Bl(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); +void drawAngle32Br(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); + +void drawAngle32ScaledTl(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); +void drawAngle32ScaledTr(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); +void drawAngle32ScaledBl(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); +void drawAngle32ScaledBr(gUnmanagedSurface *surface, const gPixmap &pixmap, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); + +void drawAngle8Tl(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); +void drawAngle8Tr(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); +void drawAngle8Bl(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); +void drawAngle8Br(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); + +void drawAngle8ScaledTl(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); +void drawAngle8ScaledTr(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); +void drawAngle8ScaledBl(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); +void drawAngle8ScaledBr(gUnmanagedSurface *surface, const gPixmap &pixmap, const uint32_t *pal, const eRect &area, const eRect &cornerRect, const CornerData &cornerData, int flag); + #endif \ No newline at end of file From 019966636abcae1360777b388a1a038080d1361f Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Wed, 17 Jan 2024 13:19:18 +0000 Subject: [PATCH 047/183] PEP8 double aggressive E301 ~ E306 --- lib/python/skin.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/python/skin.py b/lib/python/skin.py index 2f8689831d2..e926c3e8c4d 100644 --- a/lib/python/skin.py +++ b/lib/python/skin.py @@ -291,6 +291,7 @@ def parseValuePair(s, scale, object=None, desktop=None, size=None): def parsePosition(s, scale, object=None, desktop=None, size=None): return ePoint(*parseValuePair(s, scale, object, desktop, size)) + def parseRadius(value): data = [x.strip() for x in value.split(";")] if len(data) == 2: @@ -312,6 +313,7 @@ def parseRadius(value): else: return int(data[0]), eWidget.RADIUS_ALL + def parseSize(s, scale, object=None, desktop=None): return eSize(*[max(0, x) for x in parseValuePair(s, scale, object, desktop)]) From f86173648e83e985e09c2aa7394d585f9dff2d39 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Wed, 17 Jan 2024 13:19:28 +0000 Subject: [PATCH 048/183] PEP8 double aggressive W291 ~ W293 and W391 --- lib/python/skin.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/python/skin.py b/lib/python/skin.py index e926c3e8c4d..4124cb3a960 100644 --- a/lib/python/skin.py +++ b/lib/python/skin.py @@ -518,7 +518,7 @@ def font(self, value): def secondfont(self, value): self.guiObject.setSecondFont(parseFont(value, self.scaleTuple)) - + def widgetBorderColor(self, value): self.guiObject.setWidgetBorderColor(parseColor(value)) @@ -544,7 +544,7 @@ def backgroundPixmap(self, value): def selectionPixmap(self, value): self.guiObject.setSelectionPicture(loadPixmap(value, self.desktop)) - + def selectionPixmapLarge(self, value): self.guiObject.setSelectionPictureLarge(loadPixmap(value, self.desktop)) @@ -694,7 +694,7 @@ def borderColor(self, value): def borderWidth(self, value): self.guiObject.setBorderWidth(parseScale(value)) - + def cornerRadius(self, value): radius, edgeValue = parseRadius(value) self.guiObject.setCornerRadius(radius, edgeValue) From c89b900c5e8b91278110a1e7af488cc79e40c7bc Mon Sep 17 00:00:00 2001 From: openvix-build Date: Wed, 17 Jan 2024 13:37:00 +0000 Subject: [PATCH 049/183] openvix: developer 6.4.012.004 --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index c7ce05d7d73..71bdd9974f0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1233,3 +1233,4 @@ openvix: developer 6.4.011.012 openvix: developer 6.4.012.001 openvix: developer 6.4.012.002 openvix: developer 6.4.012.003 +openvix: developer 6.4.012.004 From e6c0e4a1e6096c678a7af1c08b66eef113e9b8c1 Mon Sep 17 00:00:00 2001 From: Rob van der Does Date: Thu, 18 Jan 2024 16:32:24 +0100 Subject: [PATCH 050/183] [Translations] Update Dutch (NL) translation. --- po/nl.po | 81 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 48 insertions(+), 33 deletions(-) diff --git a/po/nl.po b/po/nl.po index 4d62cee7fc3..74d1ae0f55e 100644 --- a/po/nl.po +++ b/po/nl.po @@ -3,8 +3,8 @@ msgid "" msgstr "" "Project-Id-Version: ViX\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-01-10 10:06+0000\n" -"PO-Revision-Date: 2024-01-11 15:34+0100\n" +"POT-Creation-Date: 2024-01-17 21:39+0000\n" +"PO-Revision-Date: 2024-01-18 16:29+0100\n" "Last-Translator: Rob van der Does \n" "Language-Team: Andy Blackburn, Rob van der Does\n" "Language: nl\n" @@ -30,6 +30,13 @@ msgstr "" "\n" "(verzoek tot afsluiten veranderd naar stand-by omdat er een stream-klant actief is.)" +msgid "" +"\n" +"After pressing OK, please wait!" +msgstr "" +"\n" +"Druk op OK en een ogenblik geduld!" + msgid "" "\n" "It contains other items." @@ -2145,6 +2152,9 @@ msgstr "Amerikaanse sporten" msgid "An empty filename is illegal." msgstr "Een lege bestandsnaam is ongeldig." +msgid "An error occurred while downloading the packetlist. Please try again." +msgstr "Er is een fout opgetreden bij het downloaden van de pakketlijst. Probeer het nogmaals." + msgid "An unknown error occurred!" msgstr "Er is een onbekende fout opgetreden!" @@ -5198,6 +5208,9 @@ msgstr "" msgid "Do you want to install plugins" msgstr "Wilt u het plugins installeren" +msgid "Do you want to install the package:\n" +msgstr "Wilt u het volgende pakket installeren:\n" + msgid "Do you want to play DVD in drive?" msgstr "Wilt u de DVD in de speler afspelen?" @@ -5208,6 +5221,12 @@ msgstr "Wilt u de DVD bekijken alvorens te schrijven?" msgid "Do you want to reboot your %s %s" msgstr "Wilt u uw %s %s opnieuw opstarten?" +msgid "Do you want to reboot your receiver?" +msgstr "Wilt u uw ontvanger opnieuw opstarten?" + +msgid "Do you want to remove the package:\n" +msgstr "Wilt u het volgende pakket verwijderen:\n" + msgid "Do you want to restart GUI now ?" msgstr "Wilt u de gebruikersinterface nu opnieuw starten?" @@ -5226,6 +5245,9 @@ msgstr "Wilt u uw instelingen nu terugzetten?" msgid "Do you want to resume playback?" msgstr "Wilt u het afspelen vervolgen?" +msgid "Do you want to update the package:\n" +msgstr "Wilt u het volgende pakket upgraden:\n" + #, python-format msgid "Do you want to update your %s %s?" msgstr "Wilt u uw %s %s updaten?" @@ -5294,6 +5316,9 @@ msgstr "Download plugins" msgid "Downloading" msgstr "Bezig met downloaden" +msgid "Downloading a new packet list. Please wait..." +msgstr "Downloadt een nieuwe pakketlijst. Even wachten..." + msgid "Downloading plugin information. Please wait..." msgstr "Haalt plugininformatie op. Even wachten..." @@ -9894,12 +9919,21 @@ msgstr "PRIMETIME" msgid "PVR" msgstr "PVR" +msgid "Package Manager" +msgstr "Package Manager" + msgid "Package list update" msgstr "Pakketlijst vernieuwen" +msgid "Package manager" +msgstr "Package manager" + msgid "Packages" msgstr "Pakketten" +msgid "Packages to update" +msgstr "Pakketten om te updaten" + msgid "Page down" msgstr "Pagina naar beneden" @@ -11239,6 +11273,9 @@ msgstr "" msgid "Reflash recommended!" msgstr "Opnieuw flashen wordt aanbevolen!" +msgid "Refresh list" +msgstr "Ververs lijst" + msgid "Refresh rate" msgstr "Herhalingsfrequentie" @@ -11311,6 +11348,9 @@ msgstr "Bron afstandsbediening*" msgid "Remote control type" msgstr "Type afstandsbediening" +msgid "Removal has completed." +msgstr "Verwijdering is gereed." + msgid "Remove" msgstr "Verwijder" @@ -13229,6 +13269,9 @@ msgstr "Toont een waarschuwing (pop-up) als de OpenTV download bezig is." msgid "Show or hide the extended description, (skin dependant)." msgstr "Toon of verberg de uitgebreide beschrijving (skin afhankelijk)." +msgid "Show packages to be updated" +msgstr "Toon pakketten die geupdated moeten worden" + msgid "Show picon background color" msgstr "Toon picon-achtergrondkleur" @@ -15614,6 +15657,9 @@ msgstr[1] "Update gereed, %d pakketten geïnstalleerd." msgid "Update failed. Your %s %s does not have a working internet connection." msgstr "Update is mislukt. Uw %s %s heeft geen werkende internetverbinding." +msgid "Update has completed." +msgstr "Update is gereed." + msgid "Update interval (in seconds)" msgstr "Updateinterval (in secondes)" @@ -18534,13 +18580,6 @@ msgstr "| aparte lijst van voorvoegsels die u van namen wil verwijderen, geschei #~ "\n" #~ "Geavanceerde opties en instellingen." -#~ msgid "" -#~ "\n" -#~ "After pressing OK, please wait!" -#~ msgstr "" -#~ "\n" -#~ "Druk op OK en een ogenblik geduld!" - #, python-format #~ msgid "" #~ "\n" @@ -18727,9 +18766,6 @@ msgstr "| aparte lijst van voorvoegsels die u van namen wil verwijderen, geschei #~ msgid "Always ask" #~ msgstr "Altijd vragen" -#~ msgid "An error occurred while downloading the packetlist. Please try again." -#~ msgstr "Er is een fout opgetreden bij het downloaden van de pakketlijst. Probeer het nogmaals." - #~ msgid "Android Mode" #~ msgstr "Android mode" @@ -18772,9 +18808,6 @@ msgstr "| aparte lijst van voorvoegsels die u van namen wil verwijderen, geschei #~ msgid "Background delete speed" #~ msgstr "Snelheid verwijderen op de achtergrond" -#~ msgid "Backup completed." -#~ msgstr "Back-up gereed." - #~ msgid "Backup failed." #~ msgstr "Back-up is mislukt." @@ -18854,18 +18887,6 @@ msgstr "| aparte lijst van voorvoegsels die u van namen wil verwijderen, geschei #~ "Wilt u het Recovery Image flashen?\n" #~ "Dit zal alle eMMC slots veranderen." -#~ msgid "Do you want to install the package:\n" -#~ msgstr "Wilt u het volgende pakket installeren:\n" - -#~ msgid "Do you want to reboot your receiver?" -#~ msgstr "Wilt u uw ontvanger opnieuw opstarten?" - -#~ msgid "Do you want to remove the package:\n" -#~ msgstr "Wilt u het volgende pakket verwijderen:\n" - -#~ msgid "Do you want to upgrade the package:\n" -#~ msgstr "Wilt u een upgrade van het volgende pakket:\n" - #~ msgid "DownLoad" #~ msgstr "DownLoad" @@ -19082,9 +19103,6 @@ msgstr "| aparte lijst van voorvoegsels die u van namen wil verwijderen, geschei #~ msgid "Packet management" #~ msgstr "Pakketbeheer" -#~ msgid "Packet manager" -#~ msgstr "Pakketbeheer" - #~ msgid "Percentage right" #~ msgstr "Percentage rechts" @@ -19356,9 +19374,6 @@ msgstr "| aparte lijst van voorvoegsels die u van namen wil verwijderen, geschei #~ msgid "Transponder Information" #~ msgstr "Transponderinformatie" -#~ msgid "Trying to download a new packetlist. Please wait..." -#~ msgstr "Probeert een nieuwe pakketlijst te downloaden. Even wachten..." - # #~ msgid "Tuning Info: Live Values" #~ msgstr "Tunerinfo: terugmeldingen" From f34542942b4cf38ea1821f9f5b0dfcd807d290ba Mon Sep 17 00:00:00 2001 From: Orlandoxx <95180049+Orlandoxx@users.noreply.github.com> Date: Thu, 18 Jan 2024 19:15:37 +0200 Subject: [PATCH 051/183] Updated Finnish (fi.po) translation --- po/fi.po | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/po/fi.po b/po/fi.po index 73c0d413a7c..ed76f864e70 100644 --- a/po/fi.po +++ b/po/fi.po @@ -5,7 +5,7 @@ msgstr "" "Project-Id-Version: enigma2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-12-27 23:35+0000\n" -"PO-Revision-Date: 2024-01-15 17:42+0200\n" +"PO-Revision-Date: 2024-01-18 18:30+0200\n" "Last-Translator: Orlandox\n" "Language-Team: timoj/Kojo/Samzam/Orlandox\n" "Language: fi\n" @@ -5026,7 +5026,7 @@ msgid "Do you want to install plugins" msgstr "Haluatko asentaa pluginin?" msgid "Do you want to install the package:\n" -msgstr "Haluatko asentaa IPKG-paketin:\n" +msgstr "Haluatko asentaa ohjelmapaketin:\n" msgid "Do you want to play DVD in drive?" msgstr "Haluatko toistaa asemassa olevan DVD:n?" @@ -13543,7 +13543,7 @@ msgstr "" "Suomenkielinen käännös: timoj, Kojo, Samzam, Orlandox\n" "\n" "Ylläpito : Orlandox\n" -"--- 15.01.2024 ---\n" +"--- 18.01.2024 ---\n" "http://www.huoltovalikko.com" msgid "TS file is too large for ISO9660 level 1!" @@ -19310,10 +19310,10 @@ msgid "Copy eMMC slots confirmation" msgstr "eMMC-paikkojen kopioinnin vahvistus" msgid "Package manager" -msgstr "Ohjelmistopakettien hallinnointi" +msgstr "Ohjelmapakettien hallinnointi" msgid "Package Manager" -msgstr "Ohjelmistopakettien hallinnointi" +msgstr "Ohjelmapakettien hallinnointi" msgid "Refresh list" msgstr "Päivitä lista" @@ -19328,7 +19328,10 @@ msgid "Update has completed." msgstr "Päivitys on valmis." msgid "Show packages to be updated" -msgstr "Näytä päivitettävät ohjelmistopaketit" +msgstr "Näytä päivitettävät ohjelmapaketit" msgid "Packages to update" -msgstr "Päivitettävät ohjelmistopaketit" +msgstr "Päivitettävät ohjelmapaketit" + +msgid "Do you want to update the package:\n" +msgstr "Haluatko päivittää ohjelmapaketin:\n" From 74dae0329df3c2e75c44b16f75c986b36f3b43f9 Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Sat, 20 Jan 2024 11:22:37 +0200 Subject: [PATCH 052/183] Corner radius for additional items [Added] Corner rounding for listbox items [Fixed] eSlider with rounded corners background *** Code based on openatv with some fixes. Thanks to @jbleyel! --- lib/gui/elistbox.cpp | 49 ++++++++++++++ lib/gui/elistbox.h | 27 ++++++++ lib/gui/elistboxcontent.cpp | 110 ++++++++++++++++++++++++++++---- lib/gui/elistboxcontent.h | 12 ++++ lib/gui/eslider.cpp | 96 +++++++++++++++++++++++----- lib/gui/eslider.h | 5 +- lib/gui/ewidget.h | 2 +- lib/gui/ewindowstyle.cpp | 5 ++ lib/gui/ewindowstyle.h | 2 + lib/gui/ewindowstyleskinned.cpp | 7 ++ lib/gui/ewindowstyleskinned.h | 1 + lib/python/skin.py | 8 +++ lib/service/listboxservice.cpp | 20 +++++- 13 files changed, 310 insertions(+), 34 deletions(-) diff --git a/lib/gui/elistbox.cpp b/lib/gui/elistbox.cpp index 06b5f949deb..115e35f69b8 100644 --- a/lib/gui/elistbox.cpp +++ b/lib/gui/elistbox.cpp @@ -3,6 +3,9 @@ #include #include +int eListbox::defaultItemRadius[2] = {0,0}; +int eListbox::defaultItemRadiusEdges[2] = {0,0}; + eListbox::eListbox(eWidget *parent) : eWidget(parent), m_scrollbar_mode(showNever), m_prev_scrollbar_page(-1), m_content_changed(false), m_enabled_wrap_around(false), m_scrollbar_width(10), m_scrollbar_height(10), @@ -12,6 +15,14 @@ eListbox::eListbox(eWidget *parent) : memset(static_cast(&m_style), 0, sizeof(m_style)); m_style.m_text_offset = ePoint(1,1); + for (int x = 0; x < 2; x++) + { + if (eListbox::defaultItemRadius[x] && eListbox::defaultItemRadiusEdges[x]) + setItemCornerRadiusInternal(eListbox::defaultItemRadius[x], eListbox::defaultItemRadiusEdges[x], x); + else + setItemCornerRadiusInternal(0, 0, x); + } + allowNativeKeys(true); } @@ -550,6 +561,25 @@ int eListbox::event(int event, void *data, void *data2) gRegion entryrect = m_orientation == orVertical ? eRect(0, 0, size().width(), m_itemheight) : eRect(0, 0, m_itemwidth, size().height()); const gRegion &paint_region = *(gRegion*)data; + if (!isTransparent()) + { + int cornerRadius = getCornerRadius(); + int cornerRadiusEdges = getCornerRadiusEdges(); + painter.clip(paint_region); + style->setStyle(painter, eWindowStyle::styleListboxNormal); + if (m_style.m_background_color_set) + painter.setBackgroundColor(m_style.m_background_color); + + if (cornerRadius && cornerRadiusEdges) + { + painter.setRadius(cornerRadius, cornerRadiusEdges); + painter.drawRectangle(eRect(ePoint(0, 0), size())); + } + else + painter.clear(); + painter.clippop(); + } + int xoffset = 0; int yoffset = 0; if (m_scrollbar && m_scrollbar_mode == showLeft) @@ -987,3 +1017,22 @@ struct eListboxStyle *eListbox::getLocalStyle(void) m_style.m_transparent_background = isTransparent(); return &m_style; } + +void eListbox::setItemCornerRadiusInternal(int radius, int edges, int index) +{ + m_style.m_itemCornerRadius[index] = radius; + m_style.m_itemCornerRadiusEdges[index] = edges; +} + +void eListbox::setItemCornerRadius(int radius, int edges) +{ + for (int x = 0; x < 2; x++) + { + setItemCornerRadiusInternal(radius, edges, x); + } +} + +void eListbox::setItemCornerRadiusSelected(int radius, int edges) +{ + setItemCornerRadiusInternal(radius, edges, 1); +} \ No newline at end of file diff --git a/lib/gui/elistbox.h b/lib/gui/elistbox.h index a96c4b9aad9..784e221116d 100644 --- a/lib/gui/elistbox.h +++ b/lib/gui/elistbox.h @@ -90,6 +90,16 @@ struct eListboxStyle int m_valign, m_halign, m_border_size, m_scrollbarborder_width; ePtr m_font, m_secondfont; ePoint m_text_offset; + int m_itemCornerRadius[2]; + int m_itemCornerRadiusEdges[2]; + int cornerRadius(int mode) + { + return m_itemCornerRadius[mode]; + } + int cornerRadiusEdges(int mode) + { + return m_itemCornerRadiusEdges[mode]; + } }; #endif @@ -188,6 +198,20 @@ class eListbox: public eWidget int getScrollbarHeight() { return m_scrollbar_height; } int getMaxItemTextWidth() { return m_content->getMaxItemTextWidth(); } + void setItemCornerRadius(int radius, int edges); + void setItemCornerRadiusSelected(int radius, int edges); + + static void setDefaultItemRadius(int radius, int radiusEdges) + { + defaultItemRadius[0] = radius; + defaultItemRadiusEdges[0] = radiusEdges; + } + static void setDefaultItemRadiusSelected(int radius, int radiusEdges) + { + defaultItemRadius[1] = radius; + defaultItemRadiusEdges[1] = radiusEdges; + } + #ifndef SWIG struct eListboxStyle *getLocalStyle(void); @@ -219,6 +243,7 @@ class eListbox: public eWidget int m_orientation; int m_items_per_page; int m_selection_enabled; + void setItemCornerRadiusInternal(int radius, int edges, int index); bool m_native_keys_bound; @@ -226,6 +251,8 @@ class eListbox: public eWidget eSlider *m_scrollbar; eListboxStyle m_style; ePtr m_scrollbarpixmap, m_scrollbarbackgroundpixmap; + static int defaultItemRadius[2]; + static int defaultItemRadiusEdges[2]; #endif }; diff --git a/lib/gui/elistboxcontent.cpp b/lib/gui/elistboxcontent.cpp index ed13c38a388..b1751578220 100644 --- a/lib/gui/elistboxcontent.cpp +++ b/lib/gui/elistboxcontent.cpp @@ -3,6 +3,7 @@ #include #include #include +#include /* The basic idea is to have an interface which gives all relevant list processing functions, and can be used by the listbox to browse trough @@ -178,13 +179,16 @@ int eListboxPythonStringContent::getMaxItemTextWidth() void eListboxPythonStringContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected) { ePtr fnt; - painter.clip(eRect(offset, m_itemsize)); + eRect itemRect(offset, m_itemsize); + painter.clip(itemRect); style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal); bool validitem = (m_list && cursorValid()); eListboxStyle *local_style = 0; bool cursorValid = this->cursorValid(); gRGB border_color; int border_size = 0; + int radius = 0; + int edges = 0; /* get local listbox style, if present */ if (m_listbox) @@ -194,6 +198,8 @@ void eListboxPythonStringContent::paint(gPainter &painter, eWindowStyle &style, { border_size = local_style->m_border_size; border_color = local_style->m_border_color; + radius = local_style->cornerRadius(selected ? 1:0); + edges = local_style->cornerRadiusEdges(selected ? 1:0); fnt = local_style->m_font; if (selected) { @@ -228,6 +234,12 @@ void eListboxPythonStringContent::paint(gPainter &painter, eWindowStyle &style, if (validitem) painter.blit(local_style->m_background, ePoint(offset.x() + (m_itemsize.width() - local_style->m_background->size().width()) / 2, offset.y()), eRect(), 0); } } + else if (local_style && !local_style->m_background && cursorValid && radius) + { + if(radius) + painter.setRadius(radius, edges); + painter.drawRectangle(itemRect); + } else painter.clear(); } else @@ -240,7 +252,7 @@ void eListboxPythonStringContent::paint(gPainter &painter, eWindowStyle &style, if (validitem) painter.blit(local_style->m_background, ePoint(offset.x() + (m_itemsize.width() - local_style->m_background->size().width()) / 2, offset.y()), eRect(), gPainter::BT_ALPHATEST); } } - else if (selected && !local_style->m_selection) + else if (selected && !local_style->m_selection && cursorValid && !radius && !local_style->m_background) painter.clear(); } @@ -269,6 +281,11 @@ void eListboxPythonStringContent::paint(gPainter &painter, eWindowStyle &style, else painter.blit(local_style->m_selection, ePoint(offset.x() + (m_itemsize.width() - local_style->m_selection->size().width()) / 2, offset.y()), eRect(), gPainter::BT_ALPHATEST); } + else if (selected && local_style && radius && !local_style->m_selection) { + if(radius) + painter.setRadius(radius, edges); + painter.drawRectangle(itemRect); + } if (item == Py_None) { @@ -401,6 +418,8 @@ void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style, bool cursorValid = this->cursorValid(); gRGB border_color; int border_size = 0; + int radius = 0; + int edges = 0; painter.clip(itemrect); style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal); @@ -415,6 +434,8 @@ void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style, border_color = local_style->m_border_color; fnt = local_style->m_font; fnt2 = local_style->m_secondfont; + radius = local_style->cornerRadius(selected ? 1:0); + edges = local_style->cornerRadiusEdges(selected ? 1:0); if (selected) { /* if we have a local background color set, use that. */ @@ -444,11 +465,18 @@ void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style, /* if we have no transparent background */ { /* blit background picture, if available (otherwise, clear only) */ - if (local_style && local_style->m_background && cursorValid) + if (local_style && local_style->m_background && cursorValid) { if (m_listbox && m_listbox->getOrientation() == 1) painter.blit(local_style->m_background, ePoint(offset.x(), offset.y() + (m_itemsize.height() - local_style->m_background->size().height()) / 2), eRect(), 0); else painter.blit(local_style->m_background, ePoint(offset.x() + (m_itemsize.width() - local_style->m_background->size().width()) / 2, offset.y()), eRect(), 0); + } + else if (local_style && !local_style->m_background && cursorValid && radius) + { + if(radius) + painter.setRadius(radius, edges); + painter.drawRectangle(itemrect); + } else painter.clear(); } else @@ -458,7 +486,7 @@ void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style, painter.blit(local_style->m_background, ePoint(offset.x(), offset.y() + (m_itemsize.height() - local_style->m_background->size().height()) / 2), eRect(), gPainter::BT_ALPHATEST); else painter.blit(local_style->m_background, ePoint(offset.x() + (m_itemsize.width() - local_style->m_background->size().width()) / 2, offset.y()), eRect(), gPainter::BT_ALPHATEST); - else if (selected && !local_style->m_selection) + else if (selected && !local_style->m_selection && !radius) painter.clear(); } @@ -478,6 +506,10 @@ void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style, painter.blit(local_style->m_selection, ePoint(offset.x(), offset.y() + (m_itemsize.height() - local_style->m_selection->size().height()) / 2), eRect(), gPainter::BT_ALPHATEST); else painter.blit(local_style->m_selection, ePoint(offset.x() + (m_itemsize.width() - local_style->m_selection->size().width()) / 2, offset.y()), eRect(), gPainter::BT_ALPHATEST); + } else if (selected && radius && !local_style->m_selection) { + if(radius) + painter.setRadius(radius, edges); + painter.drawRectangle(itemrect); } /* the first tuple element is a string for the left side. the second one will be called, and the result shall be an tuple. @@ -1000,7 +1032,8 @@ int eListboxPythonMultiContent::getMaxItemTextWidth() void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected) { - gRegion itemregion(eRect(offset, m_itemsize)); + eRect itemRect = eRect(offset, m_itemsize); + gRegion itemregion(itemRect); eListboxStyle *local_style = 0; eRect sel_clip(m_selection_clip); bool cursorValid = this->cursorValid(); @@ -1021,8 +1054,28 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c } painter.clip(itemregion); - clearRegion(painter, style, local_style, ePyObject(), ePyObject(), ePyObject(), ePyObject(), selected, itemregion, sel_clip, offset, m_itemsize, cursorValid, true, isverticallb); - + + if(local_style) { + int mode = (selected) ? 1:0; + int radius = local_style->cornerRadius(mode); + int edges = local_style->cornerRadiusEdges(mode); + if (radius) { + gRGB color = style.getColor(selected ? eWindowStyleSkinned::colListboxSelectedBackground : eWindowStyleSkinned::colListboxBackground);; + if (selected && local_style->m_background_color_selected_set) + color = local_style->m_background_color_selected; + if (!selected && local_style->m_background_color_set) + color = local_style->m_background_color; + + painter.setRadius(radius, edges); + painter.setBackgroundColor(gRGB(color)); + painter.drawRectangle(itemRect); + } + else + clearRegion(painter, style, local_style, ePyObject(), ePyObject(), ePyObject(), ePyObject(), selected, itemregion, sel_clip, offset, m_itemsize, cursorValid, true, isverticallb); + } + else + clearRegion(painter, style, local_style, ePyObject(), ePyObject(), ePyObject(), ePyObject(), selected, itemregion, sel_clip, offset, m_itemsize, cursorValid, true, isverticallb); + // Draw frame here so to be under the content if (selected && !sel_clip.valid() && (!local_style || !local_style->m_selection) && (!local_style || !local_style->m_border_set)) style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry); @@ -1128,7 +1181,7 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c pfnt = PyTuple_GET_ITEM(item, 5), pflags = PyTuple_GET_ITEM(item, 6), pstring = PyTuple_GET_ITEM(item, 7), - pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, pborderWidth, pborderColor; + pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, pborderWidth, pborderColor, pCornerRadius, pCornerEdges; if (!(px && py && pwidth && pheight && pfnt && pflags && pstring)) { @@ -1157,6 +1210,12 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c if (size > 13) pborderColor = lookupColor(PyTuple_GET_ITEM(item, 13), data); + if (size > 14) + pCornerRadius = PyTuple_GET_ITEM(item, 14); + + if (size > 15) + pCornerEdges = PyTuple_GET_ITEM(item, 15); + if (PyLong_Check(pstring) && data) /* if the string is in fact a number, it refers to the 'data' list. */ pstring = PyTuple_GetItem(data, PyLong_AsLong(pstring)); @@ -1173,6 +1232,11 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c int fnt = PyLong_AsLong(pfnt); int bwidth = pborderWidth ? PyLong_AsLong(pborderWidth) : 0; + int cornerRadius = pCornerRadius ? PyLong_AsLong(pCornerRadius) : 0; + int cornerEdges = pCornerEdges ? PyLong_AsLong(pCornerEdges) : 15; + if (cornerRadius || cornerEdges) + bwidth = 0; // border not supported for rounded edges + if (m_font.find(fnt) == m_font.end()) { eDebug("[eListboxPythonMultiContent] specified font %d was not found!", fnt); @@ -1183,9 +1247,21 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c painter.clip(rect); { - gRegion rc(rect); - bool mustClear = (selected && pbackColorSelected) || (!selected && pbackColor); - clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, m_itemsize, cursorValid, mustClear, isverticallb); + if(cornerRadius && (pbackColor || pbackColorSelected)) + { + if(selected && !pbackColorSelected) + pbackColorSelected = pbackColor; + unsigned int color = PyLong_AsUnsignedLongMask(selected ? pbackColorSelected : pbackColor); + painter.setBackgroundColor(gRGB(color)); + painter.setRadius(cornerRadius, cornerEdges); + painter.drawRectangle(itemRect); + } + else + { + gRegion rc(rect); + bool mustClear = (selected && pbackColorSelected) || (!selected && pbackColor); + clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, m_itemsize, cursorValid, mustClear, isverticallb); + } } painter.setFont(m_font[fnt]); @@ -1193,7 +1269,7 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c painter.clippop(); // draw border - if (bwidth) + if (bwidth && cornerRadius == 0) { eRect rect(eRect(x, y, width, height)); painter.clip(rect); @@ -1381,6 +1457,8 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c int width = PyFloat_Check(pwidth) ? (int)PyFloat_AsDouble(pwidth) : PyLong_AsLong(pwidth); int height = PyFloat_Check(pheight) ? (int)PyFloat_AsDouble(pheight) : PyLong_AsLong(pheight); int flags = 0; + int radius = 0; + int edges = 0; ePtr pixmap; if (SwigFromPython(pixmap, ppixmap)) { @@ -1397,6 +1475,12 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c if (size > 8) flags = PyLong_AsLong(PyTuple_GET_ITEM(item, 8)); + if (size > 9) + radius = PyLong_AsLong(PyTuple_GET_ITEM(item, 9)); + + if (size > 10) + edges = PyLong_AsLong(PyTuple_GET_ITEM(item, 10)); + eRect rect(x, y, width, height); painter.clip(rect); @@ -1406,6 +1490,8 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, m_itemsize, cursorValid, mustClear, isverticallb); } flags |= (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : (type == TYPE_PIXMAP_ALPHABLEND) ? gPainter::BT_ALPHABLEND : 0; + if(radius && edges) + painter.setRadius(radius, edges); painter.blit(pixmap, rect, rect, flags); painter.clippop(); break; diff --git a/lib/gui/elistboxcontent.h b/lib/gui/elistboxcontent.h index 9b83413efcf..25f0031bc7e 100644 --- a/lib/gui/elistboxcontent.h +++ b/lib/gui/elistboxcontent.h @@ -110,6 +110,8 @@ class eListboxPythonMultiContent: public eListboxPythonStringContent #define RT_VALIGN_CENTER 16 #define RT_VALIGN_BOTTOM 32 #define RT_WRAP 64 +#define RT_ELLIPSIS 128 +#define RT_BLEND 256 #define BT_ALPHATEST 1 #define BT_ALPHABLEND 2 #define BT_SCALE 4 @@ -123,6 +125,16 @@ class eListboxPythonMultiContent: public eListboxPythonStringContent #define BT_VALIGN_BOTTOM 128 #define BT_ALIGN_CENTER BT_HALIGN_CENTER | BT_VALIGN_CENTER +#define RADIUS_TOP_LEFT 1 +#define RADIUS_TOP_RIGHT 2 +#define RADIUS_TOP 3 +#define RADIUS_BOTTOM_LEFT 4 +#define RADIUS_BOTTOM_RIGHT 8 +#define RADIUS_BOTTOM 12 +#define RADIUS_LEFT 5 +#define RADIUS_RIGHT 10 +#define RADIUS_ALL RADIUS_TOP | RADIUS_BOTTOM + #endif // SWIG #endif diff --git a/lib/gui/eslider.cpp b/lib/gui/eslider.cpp index 65d95f15e00..2996e5f84cb 100644 --- a/lib/gui/eslider.cpp +++ b/lib/gui/eslider.cpp @@ -1,7 +1,7 @@ #include eSlider::eSlider(eWidget *parent) - :eWidget(parent), m_have_border_color(false), m_have_foreground_color(false), + :eWidget(parent), m_have_border_color(false), m_have_foreground_color(false), m_have_background_color(false), m_min(0), m_max(0), m_value(0), m_start(0), m_orientation(orHorizontal), m_orientation_swapped(0), m_border_width(0) { @@ -49,6 +49,13 @@ void eSlider::setForegroundColor(const gRGB &color) invalidate(); } +void eSlider::setBackgroundColor(const gRGB &col) +{ + m_background_color = col; + m_have_background_color = true; + invalidate(); +} + int eSlider::event(int event, void *data, void *data2) { switch (event) @@ -59,34 +66,91 @@ int eSlider::event(int event, void *data, void *data2) eSize s(size()); getStyle(style); - /* paint background */ - eWidget::event(evtPaint, data, data2); + /* paint background */ + int cornerRadius = getCornerRadius(); + if(!cornerRadius) // don't call eWidget paint if radius or gradient + eWidget::event(evtPaint, data, data2); gPainter &painter = *(gPainter*)data2; - style->setStyle(painter, eWindowStyle::styleLabel); // TODO - own style + bool drawborder = (m_have_border_color && m_border_width); + if (m_backgroundpixmap) { - painter.blit(m_backgroundpixmap, ePoint(0, 0), eRect(), isTransparent() ? gPainter::BT_ALPHATEST : 0); + if (cornerRadius) + painter.setRadius(cornerRadius, getCornerRadiusEdges()); + painter.blit(m_backgroundpixmap, ePoint(0, 0), eRect(), isTransparent() ? gPainter::BT_ALPHABLEND : 0); + } else if(m_have_background_color && !cornerRadius) { + painter.setBackgroundColor(m_background_color); + painter.clear(); } + if(cornerRadius) + { + if(m_have_background_color) { + painter.setBackgroundColor(m_background_color); + } + painter.setRadius(cornerRadius, getCornerRadiusEdges()); + + if (drawborder) + { + if (m_have_border_color) + painter.setBackgroundColor(m_border_color); + else + { + gRGB color = style->getColor(eWindowStyle::styleLabel); + painter.setBackgroundColor(color); + } + painter.drawRectangle(eRect(ePoint(0, 0), size())); + painter.setBackgroundColor((m_have_background_color) ? m_background_color : gRGB(0, 0, 0)); + painter.setRadius(cornerRadius, getCornerRadiusEdges()); + painter.drawRectangle(eRect(m_border_width, m_border_width, size().width() - m_border_width * 2, size().height() - m_border_width * 2)); + drawborder = false; + } + else { + painter.drawRectangle(eRect(ePoint(0, 0), size())); + } + } + + style->setStyle(painter, eWindowStyle::styleLabel); // TODO - own style + if (!m_pixmap) { - if (m_have_foreground_color) - painter.setForegroundColor(m_foreground_color); - painter.fill(m_currently_filled); + if (cornerRadius) + { + if (m_have_foreground_color) + painter.setBackgroundColor(m_foreground_color); + painter.setRadius(cornerRadius, getCornerRadiusEdges()); + eRect rect = eRect(m_currently_filled.extends); + if (m_orientation == orHorizontal) + rect.setHeight(size().height()-m_border_width*2); + else + rect.setWidth(size().width()-m_border_width*2); + painter.drawRectangle(rect); + } + else { + if (m_have_foreground_color) + painter.setForegroundColor(m_foreground_color); + painter.fill(m_currently_filled); + } } - else - painter.blit(m_pixmap, ePoint(0, 0), m_currently_filled.extends, isTransparent() ? gPainter::BT_ALPHATEST : 0); + else { - if (m_have_border_color) - painter.setForegroundColor(m_border_color); + if (cornerRadius) + painter.setRadius(cornerRadius, getCornerRadiusEdges()); + painter.blit(m_pixmap, ePoint(0, 0), m_currently_filled.extends, isTransparent() ? gPainter::BT_ALPHABLEND : 0); + } + + if(drawborder) { + if (m_have_border_color) + painter.setForegroundColor(m_border_color); - painter.fill(eRect(0, 0, s.width(), m_border_width)); - painter.fill(eRect(0, m_border_width, m_border_width, s.height() - m_border_width)); - painter.fill(eRect(m_border_width, s.height() - m_border_width, s.width() - m_border_width, m_border_width)); - painter.fill(eRect(s.width() - m_border_width, m_border_width, m_border_width, s.height() - m_border_width)); + painter.fill(eRect(0, 0, s.width(), m_border_width)); + painter.fill(eRect(0, m_border_width, m_border_width, s.height() - m_border_width)); + painter.fill(eRect(m_border_width, s.height() - m_border_width, s.width() - m_border_width, m_border_width)); + painter.fill(eRect(s.width() - m_border_width, m_border_width, m_border_width, s.height() - m_border_width)); + } return 0; } diff --git a/lib/gui/eslider.h b/lib/gui/eslider.h index e1df11a5aae..13ef2cc89ae 100644 --- a/lib/gui/eslider.h +++ b/lib/gui/eslider.h @@ -15,6 +15,7 @@ class eSlider: public eWidget void setBorderWidth(int pixel); void setBorderColor(const gRGB &color); void setForegroundColor(const gRGB &color); + void setBackgroundColor(const gRGB &col) override; void setPixmap(gPixmap *pixmap); void setPixmap(ePtr &pixmap); void setBackgroundPixmap(gPixmap *pixmap); @@ -26,12 +27,12 @@ class eSlider: public eWidget { evtChangedSlider = evtUserWidget }; - bool m_have_border_color, m_have_foreground_color; + bool m_have_border_color, m_have_foreground_color, m_have_background_color; int m_min, m_max, m_value, m_start, m_orientation, m_orientation_swapped, m_border_width; ePtr m_pixmap, m_backgroundpixmap; gRegion m_currently_filled; - gRGB m_border_color, m_foreground_color; + gRGB m_border_color, m_foreground_color, m_background_color; }; #endif diff --git a/lib/gui/ewidget.h b/lib/gui/ewidget.h index 963d311410d..67aedb52691 100644 --- a/lib/gui/ewidget.h +++ b/lib/gui/ewidget.h @@ -45,7 +45,7 @@ class eWidget SWIG_VOID(int) getStyle(ePtr &SWIG_NAMED_OUTPUT(style)) { if (!m_style) return 1; style = m_style; return 0; } void setStyle(eWindowStyle *style) { m_style = style; } - void setBackgroundColor(const gRGB &col); + virtual void setBackgroundColor(const gRGB &col); void clearBackgroundColor(); void setBorderWidth(int pixel); diff --git a/lib/gui/ewindowstyle.cpp b/lib/gui/ewindowstyle.cpp index 5ebb398ba57..d972616ff63 100644 --- a/lib/gui/ewindowstyle.cpp +++ b/lib/gui/ewindowstyle.cpp @@ -134,6 +134,11 @@ void eWindowStyleSimple::setStyle(gPainter &painter, int what) } } +gRGB eWindowStyleSimple::getColor(int what) +{ + return nullptr; +} + void eWindowStyleSimple::drawFrame(gPainter &painter, const eRect &frame, int what) { gColor c1, c2; diff --git a/lib/gui/ewindowstyle.h b/lib/gui/ewindowstyle.h index 919dd15cd37..b09d489f3b3 100644 --- a/lib/gui/ewindowstyle.h +++ b/lib/gui/ewindowstyle.h @@ -48,6 +48,7 @@ class eWindowStyle: public eWindowStyle_ENUMS, public iObject virtual void setStyle(gPainter &painter, int what) = 0; virtual void drawFrame(gPainter &painter, const eRect &frame, int type) = 0; virtual RESULT getFont(int what, ePtr &font) = 0; + virtual gRGB getColor(int what) = 0; #endif virtual ~eWindowStyle() = 0; }; @@ -98,6 +99,7 @@ class eWindowStyleSimple: public eWindowStyle void setStyle(gPainter &painter, int what); void drawFrame(gPainter &painter, const eRect &frame, int what); RESULT getFont(int what, ePtr &font); + gRGB getColor(int what); }; #endif diff --git a/lib/gui/ewindowstyleskinned.cpp b/lib/gui/ewindowstyleskinned.cpp index ae47311a6d0..d07259f7496 100644 --- a/lib/gui/ewindowstyleskinned.cpp +++ b/lib/gui/ewindowstyleskinned.cpp @@ -268,6 +268,13 @@ void eWindowStyleSkinned::setColor(int what, const gRGB &col) m_color[what] = col; } +gRGB eWindowStyleSkinned::getColor(int what) +{ + if ((what < colMax) && (what >= 0)) + return m_color[what]; + return nullptr; +} + void eWindowStyleSkinned::setTitleOffset(const eSize &offset) { m_title_offset = offset; diff --git a/lib/gui/ewindowstyleskinned.h b/lib/gui/ewindowstyleskinned.h index a6cdb891dd4..707b9a0640b 100644 --- a/lib/gui/ewindowstyleskinned.h +++ b/lib/gui/ewindowstyleskinned.h @@ -73,6 +73,7 @@ class eWindowStyleSkinned: public eWindowStyle }; void setColor(int what, const gRGB &back); + gRGB getColor(int what); void setTitleOffset(const eSize &offset); void setTitleFont(gFont *fnt); diff --git a/lib/python/skin.py b/lib/python/skin.py index 4124cb3a960..a5ed7264c6a 100644 --- a/lib/python/skin.py +++ b/lib/python/skin.py @@ -534,6 +534,14 @@ def itemHeight(self, value): def itemWidth(self, value): self.guiObject.setItemWidth(parseScale(value)) + def itemCornerRadius(self, value): + radius, edgeValue = parseRadius(value) + self.guiObject.setItemCornerRadius(radius, edgeValue) + + def itemCornerRadiusSelected(self, value): + radius, edgeValue = parseRadius(value) + self.guiObject.setItemCornerRadiusSelected(radius, edgeValue) + def pixmap(self, value): if value.endswith(".svg"): # if grafic is svg force alphatest to "blend" self.guiObject.setAlphatest(BT_ALPHABLEND) diff --git a/lib/service/listboxservice.cpp b/lib/service/listboxservice.cpp index 2b975c9eea8..721b57d6c87 100644 --- a/lib/service/listboxservice.cpp +++ b/lib/service/listboxservice.cpp @@ -715,11 +715,19 @@ void eListboxServiceContent::paint(gPainter &painter, eWindowStyle &style, const style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal); eListboxStyle *local_style = 0; + eRect itemRect = eRect(offset, m_itemsize); + int radius = 0; + int edges = 0; /* get local listbox style, if present */ if (m_listbox) local_style = m_listbox->getLocalStyle(); + if (local_style) { + radius = local_style->cornerRadius(selected ? 1:0); + edges = local_style->cornerRadiusEdges(selected ? 1:0); + } + if (marked == 1) // marked { style.setStyle(painter, eWindowStyle::styleListboxMarked); @@ -764,13 +772,19 @@ void eListboxServiceContent::paint(gPainter &painter, eWindowStyle &style, const /* blit background picture, if available (otherwise, clear only) */ if (local_style && local_style->m_background) painter.blit(local_style->m_background, offset, eRect(), 0); + else if (local_style && !local_style->m_background && radius) + { + if(radius) + painter.setRadius(radius, edges); + painter.drawRectangle(itemRect); + } else painter.clear(); } else { if (local_style->m_background) painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHABLEND); - else if (selected && !local_style->m_selection && !local_style->m_selection_large) + else if (selected && !local_style->m_selection && !local_style->m_selection_large && !radius) painter.clear(); } @@ -784,8 +798,8 @@ void eListboxServiceContent::paint(gPainter &painter, eWindowStyle &style, const } // Draw the frame for selected item here so to be under the content - if (selected && (!local_style || (!local_style->m_selection && !local_style->m_selection_large))) - style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry); + if (selected && (!local_style || (!local_style->m_selection && !local_style->m_selection_large)) && !radius) + style.drawFrame(painter, itemRect, eWindowStyle::frameListboxEntry); eServiceReference ref = *m_cursor; std::string orig_ref_str = ref.toString(); From 1850857bf026245b3350a302efc43160988594ce Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Sat, 20 Jan 2024 12:13:19 +0200 Subject: [PATCH 053/183] [Fixed] eSlider rendering when corner radius and borders present --- lib/gui/eslider.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/gui/eslider.cpp b/lib/gui/eslider.cpp index 2996e5f84cb..d7e21312b7f 100644 --- a/lib/gui/eslider.cpp +++ b/lib/gui/eslider.cpp @@ -124,9 +124,11 @@ int eSlider::event(int event, void *data, void *data2) painter.setRadius(cornerRadius, getCornerRadiusEdges()); eRect rect = eRect(m_currently_filled.extends); if (m_orientation == orHorizontal) - rect.setHeight(size().height()-m_border_width*2); + rect.setHeight(size().height()-m_border_width); else - rect.setWidth(size().width()-m_border_width*2); + rect.setWidth(size().width()-m_border_width); + rect.setX(m_border_width); + rect.setY(m_border_width); painter.drawRectangle(rect); } else { From dcf6050d3e90e8cefa6be7ad4178012c555c2b57 Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Sun, 21 Jan 2024 16:22:21 +0200 Subject: [PATCH 054/183] [Fixed] rounded progressbars rendering --- lib/gui/eslider.cpp | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/lib/gui/eslider.cpp b/lib/gui/eslider.cpp index d7e21312b7f..7f74ad04e90 100644 --- a/lib/gui/eslider.cpp +++ b/lib/gui/eslider.cpp @@ -124,11 +124,9 @@ int eSlider::event(int event, void *data, void *data2) painter.setRadius(cornerRadius, getCornerRadiusEdges()); eRect rect = eRect(m_currently_filled.extends); if (m_orientation == orHorizontal) - rect.setHeight(size().height()-m_border_width); + rect.setHeight(size().height()-m_border_width*2); else - rect.setWidth(size().width()-m_border_width); - rect.setX(m_border_width); - rect.setY(m_border_width); + rect.setWidth(size().width()-m_border_width*2); painter.drawRectangle(rect); } else { @@ -183,14 +181,24 @@ int eSlider::event(int event, void *data, void *data2) num_pix = 0; if (m_orientation == orHorizontal) - m_currently_filled = eRect(start_pix, 0, num_pix, pixsize); + m_currently_filled = eRect(start_pix + m_border_width, m_border_width, num_pix, pixsize); else - m_currently_filled = eRect(0, start_pix, pixsize, num_pix); + m_currently_filled = eRect(m_border_width, start_pix + m_border_width, pixsize, num_pix); + const int cornerRadius = getCornerRadius(); + + if (cornerRadius) + { + invalidate(old_currently_filled); + invalidate(m_currently_filled); + } + else + { // redraw what *was* filled before and now isn't. - invalidate(m_currently_filled - old_currently_filled); + invalidate(m_currently_filled - old_currently_filled); // redraw what wasn't filled before and is now. - invalidate(old_currently_filled - m_currently_filled); + invalidate(old_currently_filled - m_currently_filled); + } return 0; } From c6f6cfef5526955ea0dabf8545814edada35f705 Mon Sep 17 00:00:00 2001 From: Huevos Date: Sun, 21 Jan 2024 16:16:06 +0100 Subject: [PATCH 055/183] [Directories] add comment --- lib/python/Tools/Directories.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/python/Tools/Directories.py b/lib/python/Tools/Directories.py index 6eb56becee0..e667c818152 100644 --- a/lib/python/Tools/Directories.py +++ b/lib/python/Tools/Directories.py @@ -48,6 +48,12 @@ PATH_CREATE = 0 PATH_DONTCREATE = 1 +# +# ${libdir} = /usr/lib +# ${sysconfdir} = /etc/enigma2 +# ${datadir} = /usr/share +# + defaultPaths = { SCOPE_HOME: ("", PATH_DONTCREATE), # User home directory SCOPE_LANGUAGE: (eEnv.resolve("${datadir}/enigma2/po/"), PATH_DONTCREATE), From 30925e90953ed24b8d8500ec97ab7dc020d69370 Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Mon, 22 Jan 2024 13:28:48 +0200 Subject: [PATCH 056/183] [Removed] test values --- lib/gui/elistboxcontent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gui/elistboxcontent.cpp b/lib/gui/elistboxcontent.cpp index b1751578220..f33ef46e525 100644 --- a/lib/gui/elistboxcontent.cpp +++ b/lib/gui/elistboxcontent.cpp @@ -1233,7 +1233,7 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c int bwidth = pborderWidth ? PyLong_AsLong(pborderWidth) : 0; int cornerRadius = pCornerRadius ? PyLong_AsLong(pCornerRadius) : 0; - int cornerEdges = pCornerEdges ? PyLong_AsLong(pCornerEdges) : 15; + int cornerEdges = pCornerEdges ? PyLong_AsLong(pCornerEdges) : 0; if (cornerRadius || cornerEdges) bwidth = 0; // border not supported for rounded edges From 59d908a06187722688e438d3952b03723e5dfc20 Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Wed, 24 Jan 2024 12:43:09 +0200 Subject: [PATCH 057/183] [Updated] Logic to draw borders in eSlider (needs testing) --- lib/gui/eslider.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gui/eslider.cpp b/lib/gui/eslider.cpp index 7f74ad04e90..31a1c9af44c 100644 --- a/lib/gui/eslider.cpp +++ b/lib/gui/eslider.cpp @@ -73,7 +73,7 @@ int eSlider::event(int event, void *data, void *data2) gPainter &painter = *(gPainter*)data2; - bool drawborder = (m_have_border_color && m_border_width); + bool drawborder = m_border_width; if (m_backgroundpixmap) From 1f7c6477beee078607fc08a5144cd7ab9ef672f0 Mon Sep 17 00:00:00 2001 From: Gordon Lack Date: Wed, 24 Jan 2024 21:47:23 +0000 Subject: [PATCH 058/183] Correct inverted logic for, and options which limitEvent --- lib/python/Screens/InfoBarGenerics.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py index 361c88573c4..464f5f57ad2 100644 --- a/lib/python/Screens/InfoBarGenerics.py +++ b/lib/python/Screens/InfoBarGenerics.py @@ -3359,7 +3359,7 @@ def startInstantRecording(self, limitEvent=False): if limitEvent: end = info["end"] else: - if limitEvent: + if not limitEvent: self.session.open(MessageBox, _("No event info found, recording indefinitely."), MessageBox.TYPE_INFO, simple=True) if isinstance(serviceref, eServiceReference): @@ -3452,7 +3452,7 @@ def recordQuestionCallback(self, answer): self.deleteRecording = True self.stopAllCurrentRecordings(list) elif answer[1] in ("indefinitely", "manualduration", "manualendtime", "event"): - self.startInstantRecording(limitEvent=answer[1] in ("event", "manualendtime") or False) + self.startInstantRecording(limitEvent=answer[1] in ("manualduration", "manualendtime", "event") or False) if answer[1] == "manualduration": self.changeDuration(len(self.recording) - 1) elif answer[1] == "manualendtime": From e876d3d19f9925df6c8f1f41f894aa8f4b230f19 Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Thu, 25 Jan 2024 16:10:50 +0200 Subject: [PATCH 059/183] [Added] Possinility pager to handle onSelChanged event --- lib/python/Components/Addons/Pager.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/python/Components/Addons/Pager.py b/lib/python/Components/Addons/Pager.py index 6cc9e71b181..967017e91a0 100644 --- a/lib/python/Components/Addons/Pager.py +++ b/lib/python/Components/Addons/Pager.py @@ -35,8 +35,11 @@ def onContainerShown(self): if hasattr(self.source, "instance") and hasattr(self.source.instance, "setScrollbarMode"): self.source.instance.setScrollbarMode(2) - if self.initPager not in self.source.onSelectionChanged: + if hasattr(self.source, "onSelectionChanged") and self.initPager not in self.source.onSelectionChanged: self.source.onSelectionChanged.append(self.initPager) + if hasattr(self.source, "onSelChanged") and self.initPager not in self.source.onSelChanged: + self.source.onSelChanged.append(self.initPager) + self.initPager() GUI_WIDGET = eListbox From c40e27fc282aaeab4bec5cc064752150264b280e Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Sat, 20 Jan 2024 14:47:18 +0200 Subject: [PATCH 060/183] [display800] add PackageManager --- data/display800/skin_display_templates.xml | 7 +++++++ lib/python/Plugins/SystemPlugins/ViX/PackageManager.py | 7 ++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/data/display800/skin_display_templates.xml b/data/display800/skin_display_templates.xml index feff284bd26..0b47936d2f8 100644 --- a/data/display800/skin_display_templates.xml +++ b/data/display800/skin_display_templates.xml @@ -437,5 +437,12 @@ + + + + + + + diff --git a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py index 64553a424ca..9e163a1cc87 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py +++ b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py @@ -13,7 +13,7 @@ from Screens.Ipkg import Ipkg from Screens.MessageBox import MessageBox -from Screens.Screen import Screen +from Screens.Screen import Screen, ScreenSummary from Screens.Standby import TryQuitMainloop from Tools.Directories import resolveFilename, SCOPE_PLUGINS, SCOPE_CURRENT_PLUGIN, SCOPE_CURRENT_SKIN @@ -47,6 +47,11 @@ def load_cache(cache_file): return pickle.load(open(cache_file, "rb")) +class PackageManagerSummary(ScreenSummary): + def __init__(self, session, parent): + ScreenSummary.__init__(self, session, parent=parent) + + class PackageManager(Screen, NumericalTextInput): skin = [""" From f99544810a4cccf73ab3571ebe2c28984c6f3cb8 Mon Sep 17 00:00:00 2001 From: Huevos Date: Thu, 25 Jan 2024 16:24:36 +0100 Subject: [PATCH 061/183] [ImageManager] fix summary --- lib/python/Plugins/SystemPlugins/ViX/ImageManager.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/python/Plugins/SystemPlugins/ViX/ImageManager.py b/lib/python/Plugins/SystemPlugins/ViX/ImageManager.py index 8b78472163c..a952ffb7279 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/ImageManager.py +++ b/lib/python/Plugins/SystemPlugins/ViX/ImageManager.py @@ -234,12 +234,15 @@ def __init__(self, session): if self.selectionChanged not in self["list"].onSelectionChanged: self["list"].onSelectionChanged.append(self.selectionChanged) + def createSummary(self): + from Screens.PluginBrowser import PluginBrowserSummary + return PluginBrowserSummary + def selectionChanged(self): - # Where is this used? self.onChangedEntry does not appear to be populated anywhere. Maybe dead code. item = self["list"].getCurrent() # (name, link) desc = self["backupstatus"].text if item: - name = item[1] + name = item[0] else: name = "" for cb in self.onChangedEntry: From f32700af50450a8f6fff81b2ba0302b79cc81c67 Mon Sep 17 00:00:00 2001 From: Huevos Date: Thu, 25 Jan 2024 16:26:04 +0100 Subject: [PATCH 062/183] [PackageManager] add filtering based on package status --- .../SystemPlugins/ViX/PackageManager.py | 73 ++++++++++++++++--- 1 file changed, 64 insertions(+), 9 deletions(-) diff --git a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py index 9e163a1cc87..050d0ea487a 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py +++ b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py @@ -90,7 +90,7 @@ class PackageManager(Screen, NumericalTextInput): def __init__(self, session): Screen.__init__(self, session) NumericalTextInput.__init__(self) - self.setTitle(_("Package manager")) + self.title = _("Package manager") self.setUseableChars("1234567890abcdefghijklmnopqrstuvwxyz") @@ -98,7 +98,6 @@ def __init__(self, session): { "ok": self.go, "cancel": self.exit, - "save": self.reload, "gotAsciiCode": self.keyGotAscii, "1": self.keyNumberGlobal, "2": self.keyNumberGlobal, @@ -112,11 +111,21 @@ def __init__(self, session): "0": self.keyNumberGlobal }, -1) + self["filterActions"] = NumberActionMap(["SetupActions"], + { + "deleteBackward": self.filterPrev, + "deleteForward": self.filterNext, + "save": self.reload, + }, -1) + self["filterActions"].setEnabled(False) + self.list = [] self.statuslist = [] self["list"] = List(self.list) self["key_red"] = StaticText(_("Close")) - self["key_green"] = StaticText(_("Refresh list")) + self["key_green"] = StaticText() + self["key_previous"] = StaticText() + self["key_next"] = StaticText() self.imagePath = "%s/images/" % os.path.dirname(os.path.realpath(__file__)) self.list_updating = True @@ -130,6 +139,12 @@ def __init__(self, session): self.cache_file = "/etc/enigma2/packetmanager.cache" # Path to cache directory self.oktext = _("\nAfter pressing OK, please wait!") self.unwanted_extensions = ("-dbg", "-dev", "-doc", "-staticdev", "-src", "busybox") + self.filters = {"All": _("All"), "Installed": _("Installed"), "Upgradeable": _("Upgradeable"), "Installable": _("Installable")} + + + self.installedpng = LoadPixmap(cached=True, path=self.imagePath + "installed.png") + self.upgradeablepng = LoadPixmap(cached=True, path=self.imagePath + "upgradeable.png") + self.installablepng = LoadPixmap(cached=True, path=self.imagePath + "installable.png") self.ipkg = IpkgComponent() self.ipkg.addCallback(self.ipkgCallback) @@ -339,18 +354,16 @@ def buildEntryComponent(self, name, version, description, state): if not description: description = "No description available." if state == "installed": - installedpng = LoadPixmap(cached=True, path=self.imagePath + "installed.png") - return ((name, version, _(description), state, installedpng, divpng)) + return ((name, version, _(description), state, self.installedpng, divpng)) elif state == "upgradeable": - upgradeablepng = LoadPixmap(cached=True, path=self.imagePath + "upgradeable.png") - return ((name, version, _(description), state, upgradeablepng, divpng)) + return ((name, version, _(description), state, self.upgradeablepng, divpng)) else: - installablepng = LoadPixmap(cached=True, path=self.imagePath + "installable.png") - return ((name, version, _(description), state, installablepng, divpng)) + return ((name, version, _(description), state, self.installablepng, divpng)) def buildPacketList(self): self.list = [] self.cachelist = [] + self.i = 0 if self.cache_ttl > 0 and self.vc != 0: print("Loading packagelist cache from ", self.cache_file) try: @@ -377,6 +390,48 @@ def buildPacketList(self): self.cachelist.append([x[0], x[1], x[2], status]) write_cache(self.cache_file, self.cachelist) self["list"].setList(self.list) + self.updateTexts() + + def filterPrev(self): + self.i -= 1 + self.filterList() + + def filterNext(self): + self.i += 1 + self.filterList() + def filterList(self): + if self.list: + filter = self.getCurrentFilter() + if filter == "All": + self["list"].setList(self.list) + elif filter == "Installed": + self["list"].setList([x for x in self.list if x[4] is self.installedpng]) + elif filter == "Upgradeable": + self["list"].setList([x for x in self.list if x[4] is self.upgradeablepng]) + elif filter == "Installable": + self["list"].setList([x for x in self.list if x[4] is self.installablepng]) + self.updateTexts() + + def getCurrentFilter(self): + return list(self.filters.keys())[self.i % len(self.filters)] + + def updateTexts(self): + if self.list: + self["filterActions"].setEnabled(True) + self.title = _("Package manager") + " - " + self.filters[self.getCurrentFilter()] + self["key_green"].text = _("Refresh list") + self["key_previous"].text = _("PREVIOUS") + self["key_next"].text = _("NEXT") + else: + self["filterActions"].setEnabled(False) + self.title = _("Package manager") + self["key_green"].text = "" + self["key_previous"].text = "" + self["key_next"].text = "" + def reloadPluginlist(self): plugins.readPluginList(resolveFilename(SCOPE_PLUGINS)) + + def createSummary(self): + return PackageManagerSummary From f9e1f6f0c30a3304d71c1820040e173a2c50b950 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Thu, 25 Jan 2024 15:27:56 +0000 Subject: [PATCH 063/183] PEP8 double aggressive E22, E224, E241, E242 and E27 --- lib/python/Plugins/SystemPlugins/ViX/PackageManager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py index 050d0ea487a..4c5997a41e0 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py +++ b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py @@ -422,13 +422,13 @@ def updateTexts(self): self.title = _("Package manager") + " - " + self.filters[self.getCurrentFilter()] self["key_green"].text = _("Refresh list") self["key_previous"].text = _("PREVIOUS") - self["key_next"].text = _("NEXT") + self["key_next"].text = _("NEXT") else: self["filterActions"].setEnabled(False) self.title = _("Package manager") self["key_green"].text = "" self["key_previous"].text = "" - self["key_next"].text = "" + self["key_next"].text = "" def reloadPluginlist(self): plugins.readPluginList(resolveFilename(SCOPE_PLUGINS)) From 9ffd320c613762660a02bf938c4e8927544cd021 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Thu, 25 Jan 2024 15:28:23 +0000 Subject: [PATCH 064/183] PEP8 double aggressive E301 ~ E306 --- lib/python/Plugins/SystemPlugins/ViX/PackageManager.py | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py index 4c5997a41e0..879902b5245 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py +++ b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py @@ -141,7 +141,6 @@ def __init__(self, session): self.unwanted_extensions = ("-dbg", "-dev", "-doc", "-staticdev", "-src", "busybox") self.filters = {"All": _("All"), "Installed": _("Installed"), "Upgradeable": _("Upgradeable"), "Installable": _("Installable")} - self.installedpng = LoadPixmap(cached=True, path=self.imagePath + "installed.png") self.upgradeablepng = LoadPixmap(cached=True, path=self.imagePath + "upgradeable.png") self.installablepng = LoadPixmap(cached=True, path=self.imagePath + "installable.png") From fe76d324dac6eac96a4794ce39dcf702df61e1b0 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Thu, 25 Jan 2024 15:28:33 +0000 Subject: [PATCH 065/183] PEP8 double aggressive W291 ~ W293 and W391 --- lib/python/Plugins/SystemPlugins/ViX/PackageManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py index 879902b5245..7c4114319ed 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py +++ b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py @@ -428,7 +428,7 @@ def updateTexts(self): self["key_green"].text = "" self["key_previous"].text = "" self["key_next"].text = "" - + def reloadPluginlist(self): plugins.readPluginList(resolveFilename(SCOPE_PLUGINS)) From 239206bc3175d26e273ffbeab02bac3ab90426bd Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Thu, 25 Jan 2024 18:23:00 +0200 Subject: [PATCH 066/183] [Added] summary screen for package manager in display480 skin --- data/display480/skin_display.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/data/display480/skin_display.xml b/data/display480/skin_display.xml index 5bfa149f76e..20112bad905 100644 --- a/data/display480/skin_display.xml +++ b/data/display480/skin_display.xml @@ -564,10 +564,17 @@ - + + + + + + + + From 47941ca57f894f63c2183e06b4572205c19dc951 Mon Sep 17 00:00:00 2001 From: Orlandoxx <95180049+Orlandoxx@users.noreply.github.com> Date: Thu, 25 Jan 2024 18:53:07 +0200 Subject: [PATCH 067/183] Updated Finnish (fi.po) translation Added [PackageManager] changes. --- po/fi.po | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/po/fi.po b/po/fi.po index ed76f864e70..9eb2d1aa610 100644 --- a/po/fi.po +++ b/po/fi.po @@ -5,7 +5,7 @@ msgstr "" "Project-Id-Version: enigma2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-12-27 23:35+0000\n" -"PO-Revision-Date: 2024-01-18 18:30+0200\n" +"PO-Revision-Date: 2024-01-25 18:50+0200\n" "Last-Translator: Orlandox\n" "Language-Team: timoj/Kojo/Samzam/Orlandox\n" "Language: fi\n" @@ -13,7 +13,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.4.2\n" #, python-format msgid "" @@ -13543,7 +13543,7 @@ msgstr "" "Suomenkielinen käännös: timoj, Kojo, Samzam, Orlandox\n" "\n" "Ylläpito : Orlandox\n" -"--- 18.01.2024 ---\n" +"--- 25.01.2024 ---\n" "http://www.huoltovalikko.com" msgid "TS file is too large for ISO9660 level 1!" @@ -19335,3 +19335,12 @@ msgstr "Päivitettävät ohjelmapaketit" msgid "Do you want to update the package:\n" msgstr "Haluatko päivittää ohjelmapaketin:\n" + +msgid "Installed" +msgstr "Asennettu" + +msgid "Upgradeable" +msgstr "Päivitettävissä" + +msgid "Installable" +msgstr "Asennettavissa" From e41b666f2c9d76904448322f6d02a018b2557fb4 Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Fri, 26 Jan 2024 15:41:36 +0200 Subject: [PATCH 068/183] [Fixed] Pager code [Added] Posibility in GEPG to specify text sides margins [Fixed] GEPG timer icon position [Fixed] Single EPG timer icons position --- lib/python/Components/Addons/Pager.py | 10 +++++----- lib/python/Components/EpgListGrid.py | 17 ++++++++++++----- lib/python/Components/EpgListSingle.py | 7 ++++--- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/lib/python/Components/Addons/Pager.py b/lib/python/Components/Addons/Pager.py index 967017e91a0..70180324c86 100644 --- a/lib/python/Components/Addons/Pager.py +++ b/lib/python/Components/Addons/Pager.py @@ -33,12 +33,12 @@ def __init__(self): def onContainerShown(self): # disable listboxes default scrollbars if hasattr(self.source, "instance") and hasattr(self.source.instance, "setScrollbarMode"): - self.source.instance.setScrollbarMode(2) + self.source.instance.setScrollbarMode(eListbox.showNever) - if hasattr(self.source, "onSelectionChanged") and self.initPager not in self.source.onSelectionChanged: - self.source.onSelectionChanged.append(self.initPager) - if hasattr(self.source, "onSelChanged") and self.initPager not in self.source.onSelChanged: - self.source.onSelChanged.append(self.initPager) + onSelectionChanged = x if isinstance((x := getattr(self.source, "onSelectionChanged", None))) else getattr(self.source, "onSelChanged", None) + + if isinstance(onSelectionChanged, list) and self.initPager not in onSelectionChanged: + onSelectionChanged.append(self.initPager) self.initPager() diff --git a/lib/python/Components/EpgListGrid.py b/lib/python/Components/EpgListGrid.py index 06ecea72d4d..7abc00db942 100644 --- a/lib/python/Components/EpgListGrid.py +++ b/lib/python/Components/EpgListGrid.py @@ -91,6 +91,7 @@ def __init__(self, session, isInfobar, selChangedCB=None): self.eventBorderWidth = 1 self.eventNamePadding = 3 self.serviceNumberWidth = 0 + self.eventTextSidesMargin = 0 self.l.setBuildFunc(self.buildEntry) self.loadConfig() @@ -145,6 +146,9 @@ def applySkin(self, desktop, screen): self.foreColorNow = parseColor(value).argb() elif attrib == "EntryForegroundColorNowSelected": self.foreColorNowSelected = parseColor(value).argb() + + elif attrib == "EventTextSidesMargin": + self.eventTextSidesMargin = parseScale(value) elif attrib == "ServiceBorderColor": self.borderColorService = parseColor(value).argb() @@ -616,7 +620,7 @@ def buildEntry(self, service, serviceName, events, picon, channel): png=infoPix, flags=BT_ALIGN_CENTER)) else: res.append(MultiContentEntryText( - pos=(evX, evY), size=(evW, evH), + pos=(evX + self.eventTextSidesMargin, evY), size=(evW - self.eventTextSidesMargin * 2, evH), font=1, flags=int(config.epgselection.grid.event_alignment.value), text=ev[1], color=foreColor, color_sel=foreColorSel, @@ -655,16 +659,19 @@ def buildEntry(self, service, serviceName, events, picon, channel): pix_size = timerIcon.size() pix_width = pix_size.width() pix_height = pix_size.height() + isTimerIconAdded = False if config.epgselection.grid.rec_icon_height.value == "middle": recIconHeight = top + (height - pix_height) // 2 elif config.epgselection.grid.rec_icon_height.value == "top": recIconHeight = top + 3 else: - recIconHeight = top + height - pix_height - applySkinFactor(5) + recIconHeight = top + height - pix_height - 10 if matchType == 0: - pos = (left + xpos + ewidth - pix_width - applySkinFactor(5), recIconHeight) + pos = (left + xpos + ewidth - pix_width - 10, recIconHeight) + isTimerIconAdded = True else: - pos = (left + xpos + ewidth - pix_width - applySkinFactor(5), recIconHeight) + pos = (left + xpos + ewidth - pix_width - 10, recIconHeight) + isTimerIconAdded = True res.append(MultiContentEntryPixmapAlphaBlend( pos=pos, size=(pix_width, pix_height), png=timerIcon)) @@ -673,7 +680,7 @@ def buildEntry(self, service, serviceName, events, picon, channel): pix_width = pix_size.width() pix_height = pix_size.height() res.append(MultiContentEntryPixmapAlphaBlend( - pos=(pos[0] - pix_width - applySkinFactor(5), pos[1]), size=(pix_width, pix_height), + pos=(pos[0] - pix_width - (5 if isTimerIconAdded else 10) , pos[1]), size=(pix_width, pix_height), png=autoTimerIcon)) return res diff --git a/lib/python/Components/EpgListSingle.py b/lib/python/Components/EpgListSingle.py index 1af1b1d0d15..61f81d93e18 100644 --- a/lib/python/Components/EpgListSingle.py +++ b/lib/python/Components/EpgListSingle.py @@ -91,13 +91,14 @@ def buildEntry(self, service, eventId, beginTime, duration, eventName): pix_width = pix_size.width() pix_height = pix_size.height() eventW -= pix_width - res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, r3.left() + r3.width() - pix_width, (r3.height() - pix_height) // 2, pix_width, pix_height, timerIcon)) + posX = r3.left() + r3.width() - pix_width + res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, posX, (r3.height() - pix_height) // 2, pix_width, pix_height, timerIcon)) if autoTimerIcon: pix_size = autoTimerIcon.size() pix_width = pix_size.width() pix_height = pix_size.height() - eventW -= pix_width - res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, r3.left() + r3.width() - pix_width * 2 - 10, (r3.height() - pix_height) // 2, pix_width, pix_height, autoTimerIcon)) + eventW -= pix_width + 6 + res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, posX - pix_width - 6, (r3.height() - pix_height) // 2, pix_width, pix_height, autoTimerIcon)) res.append((eListboxPythonMultiContent.TYPE_TEXT, r3.left(), r3.top(), eventW, r3.height(), 0, RT_HALIGN_LEFT | RT_VALIGN_CENTER, eventName)) return res From c6d5037d64d5291cb5763655822104564bfd5090 Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Fri, 26 Jan 2024 15:51:41 +0200 Subject: [PATCH 069/183] [Fixed] issue in pager [Fixed] possibility width to become negative --- lib/python/Components/Addons/Pager.py | 2 +- lib/python/Components/EpgListGrid.py | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/python/Components/Addons/Pager.py b/lib/python/Components/Addons/Pager.py index 70180324c86..ba575edba11 100644 --- a/lib/python/Components/Addons/Pager.py +++ b/lib/python/Components/Addons/Pager.py @@ -35,7 +35,7 @@ def onContainerShown(self): if hasattr(self.source, "instance") and hasattr(self.source.instance, "setScrollbarMode"): self.source.instance.setScrollbarMode(eListbox.showNever) - onSelectionChanged = x if isinstance((x := getattr(self.source, "onSelectionChanged", None))) else getattr(self.source, "onSelChanged", None) + onSelectionChanged = x if (x := getattr(self.source, "onSelectionChanged", None)) else getattr(self.source, "onSelChanged", None) if isinstance(onSelectionChanged, list) and self.initPager not in onSelectionChanged: onSelectionChanged.append(self.initPager) diff --git a/lib/python/Components/EpgListGrid.py b/lib/python/Components/EpgListGrid.py index 7abc00db942..f6cf9e217d2 100644 --- a/lib/python/Components/EpgListGrid.py +++ b/lib/python/Components/EpgListGrid.py @@ -619,8 +619,12 @@ def buildEntry(self, service, serviceName, events, picon, channel): pos=(left + xpos + self.eventBorderWidth, evY), size=(ewidth - 2 * self.eventBorderWidth, evH), png=infoPix, flags=BT_ALIGN_CENTER)) else: + evW -= self.eventTextSidesMargin * 2 + evX += self.eventTextSidesMargin + if evW < 0: + evW = 0 res.append(MultiContentEntryText( - pos=(evX + self.eventTextSidesMargin, evY), size=(evW - self.eventTextSidesMargin * 2, evH), + pos=(evX, evY), size=(evW, evH), font=1, flags=int(config.epgselection.grid.event_alignment.value), text=ev[1], color=foreColor, color_sel=foreColorSel, From 9a43f79e7ec440767658f2c7a1137ffe0fb236f2 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Fri, 26 Jan 2024 13:59:49 +0000 Subject: [PATCH 070/183] PEP8 double aggressive E20 and E211 --- lib/python/Components/EpgListGrid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/Components/EpgListGrid.py b/lib/python/Components/EpgListGrid.py index f6cf9e217d2..1d54bf5a8bc 100644 --- a/lib/python/Components/EpgListGrid.py +++ b/lib/python/Components/EpgListGrid.py @@ -684,7 +684,7 @@ def buildEntry(self, service, serviceName, events, picon, channel): pix_width = pix_size.width() pix_height = pix_size.height() res.append(MultiContentEntryPixmapAlphaBlend( - pos=(pos[0] - pix_width - (5 if isTimerIconAdded else 10) , pos[1]), size=(pix_width, pix_height), + pos=(pos[0] - pix_width - (5 if isTimerIconAdded else 10), pos[1]), size=(pix_width, pix_height), png=autoTimerIcon)) return res From 0aedcb6721f2b443ade9a9e24ff9641b75146dec Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Fri, 26 Jan 2024 14:00:35 +0000 Subject: [PATCH 071/183] PEP8 double aggressive W291 ~ W293 and W391 --- lib/python/Components/EpgListGrid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/Components/EpgListGrid.py b/lib/python/Components/EpgListGrid.py index 1d54bf5a8bc..e0dbc8f8de7 100644 --- a/lib/python/Components/EpgListGrid.py +++ b/lib/python/Components/EpgListGrid.py @@ -146,7 +146,7 @@ def applySkin(self, desktop, screen): self.foreColorNow = parseColor(value).argb() elif attrib == "EntryForegroundColorNowSelected": self.foreColorNowSelected = parseColor(value).argb() - + elif attrib == "EventTextSidesMargin": self.eventTextSidesMargin = parseScale(value) From f5e5368dfdb0150d6b101cb719d06ba38b39a36f Mon Sep 17 00:00:00 2001 From: Huevos Date: Fri, 26 Jan 2024 23:46:44 +0100 Subject: [PATCH 072/183] [ViX plugin] remove some images --- lib/python/Plugins/SystemPlugins/ViX/Makefile.am | 3 +-- .../SystemPlugins/ViX/images/installable.png | Bin 986 -> 0 bytes .../SystemPlugins/ViX/images/installed.png | Bin 2055 -> 0 bytes .../Plugins/SystemPlugins/ViX/images/remove.png | Bin 2201 -> 0 bytes .../Plugins/SystemPlugins/ViX/images/upgrade.png | Bin 2603 -> 0 bytes .../SystemPlugins/ViX/images/upgradeable.png | Bin 2055 -> 0 bytes lib/python/Plugins/SystemPlugins/ViX/install.png | Bin 2176 -> 0 bytes .../Plugins/SystemPlugins/ViX/installable.png | Bin 1023 -> 0 bytes .../Plugins/SystemPlugins/ViX/installed.png | Bin 2092 -> 0 bytes lib/python/Plugins/SystemPlugins/ViX/noprev.png | Bin 1467 -> 0 bytes lib/python/Plugins/SystemPlugins/ViX/remove.png | Bin 2238 -> 0 bytes lib/python/Plugins/SystemPlugins/ViX/update.png | Bin 3630 -> 0 bytes lib/python/Plugins/SystemPlugins/ViX/upgrade.png | Bin 2640 -> 0 bytes .../Plugins/SystemPlugins/ViX/upgradeable.png | Bin 2092 -> 0 bytes 14 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 lib/python/Plugins/SystemPlugins/ViX/images/installable.png delete mode 100644 lib/python/Plugins/SystemPlugins/ViX/images/installed.png delete mode 100644 lib/python/Plugins/SystemPlugins/ViX/images/remove.png delete mode 100644 lib/python/Plugins/SystemPlugins/ViX/images/upgrade.png delete mode 100644 lib/python/Plugins/SystemPlugins/ViX/images/upgradeable.png delete mode 100644 lib/python/Plugins/SystemPlugins/ViX/install.png delete mode 100644 lib/python/Plugins/SystemPlugins/ViX/installable.png delete mode 100644 lib/python/Plugins/SystemPlugins/ViX/installed.png delete mode 100644 lib/python/Plugins/SystemPlugins/ViX/noprev.png delete mode 100644 lib/python/Plugins/SystemPlugins/ViX/remove.png delete mode 100644 lib/python/Plugins/SystemPlugins/ViX/update.png delete mode 100644 lib/python/Plugins/SystemPlugins/ViX/upgrade.png delete mode 100644 lib/python/Plugins/SystemPlugins/ViX/upgradeable.png diff --git a/lib/python/Plugins/SystemPlugins/ViX/Makefile.am b/lib/python/Plugins/SystemPlugins/ViX/Makefile.am index 375395f99c3..45740583978 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/Makefile.am +++ b/lib/python/Plugins/SystemPlugins/ViX/Makefile.am @@ -4,7 +4,6 @@ SUBDIRS = images install_PYTHON = *.py -install_DATA = *.png \ - *.xml \ +install_DATA = *.xml \ LICENSE \ maintainer.info diff --git a/lib/python/Plugins/SystemPlugins/ViX/images/installable.png b/lib/python/Plugins/SystemPlugins/ViX/images/installable.png deleted file mode 100644 index f52b66c25b69d78239d595fd59df2d9f5199f583..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 986 zcmV<0110>4P)3kf!tJ2inC>yT(u5)4g8=YjqCDOo4M69}2b zctoI721dYOCc>`v0hVbjr!&=HF9r}u6>%Uj5vGJnVW2ce4VE4;nXE}L70^f1OEhFiVH#4Q|UY9 z6m3&0ZDmmj!+>(eAmq0@8LLXLRY)1Ju$VsK%d4%FbF6OBgz0d{aAMuxZYQBLlbCj3+}Hzwf}Oz(D}>7hz4Oqft74G zs)r^)(K0BJLNG$U!Qgio@qSqPvJeCU+KsJa)nN8O&c@i(tieEy8!WqqxU6u)UoS9X zxy@GXP4Aq|Ay-I8%Mc*rMocLQO*TTUsVfbQJ7_I%AO1~iGr|}XUpxsY08mDZw5G&V zBH8w8Ejaha+FhQG6)7>0zBHtPMxc=f?|3kg8!Od!B?BvVSOXW()nJAtZ2t9W7 z&*7GyTTgFZWaHykyJrgJJOw<%n15dF+v82VzGb%_I&-u#x9XP=&YxrL&v(xE-K&h> z0%QAnRw~ij;_fDEc6@Rhb$=FsOp6n6e|>J-3uXHL+Wnuw-`t|JV6JZ~zW@LL07*qo IM6N<$g1!{a2mk;8 diff --git a/lib/python/Plugins/SystemPlugins/ViX/images/installed.png b/lib/python/Plugins/SystemPlugins/ViX/images/installed.png deleted file mode 100644 index 479088db9cbf128df9192b93e6cea3955c1f6ffe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2055 zcmd^A`9IW&AO0X$n_c&@k|aVzQ6q{RgF%*YG-9@KA3LLoSz>bES90fw1~Vkb8b`v0 zklRS(7!sK^m~xD3HjK~u{vF@v^?KgV>-pjN?RmYQWLq0^q0_&f1^_?^W?>3HQLX<` zfam0*J_|Mj01sem?EpQoAP54YF@WepKsf_AhvCwy=2ndZ6x;y?Hy+g>e(e-tSR0_| z1t@s|itfBuBLwvFB%lR=iZ7t-aRw4DX`Co@GyFVeQ5G7f;#$R};m>^)%YXeO_(<>u z?u`CpacHtEyimsS>3N$pH4pL`J)F?(FcBlXs7aK#S+sjXmK|4?{%eQC*&m+(t&9M`S5^mS03ZS4Y=sVH?!F zUz+7HZHSyZk=@2mTJJ`+IHvVnaxYTzELQg`*ZQOU8n#l?uLOdtHP4;971n&yKi>pj zr=Bvc6ZA?qv>r}m-g;bPn$+n^=2)ck+7-^&WRKWn4|_MTu(eAbMT4&CE&36S1~IKh z@$F{m-6k=OR$2X)8SgFA-r40-><|(>f4w)a{1l4AmJw}wx*3a)Qw6C^Jus#O8#$=8r zBhu~$HX++riLSYZq`73@7nbhDI+&VkIYaIlO}_oC;kDx`8sRN!iM`jtTBW0Vy@| z9%ft9!OV5A{WHgR4J>7Xgwdl5%V6v_*tH7|GQsQ(5V;Kov%%Dp=EG;yrvQKpz`S@mgA{kAG$_de43hG=ApxZ_`__(Ed=i)MJoTwu=ZBI+ zA2h|)Nno&~!mE$u6T0~WxBKmwZ79$ad71khz`ioX+Vvwmo<`Q{A_*HIt-A-*nFC|` z9fd#r*A`JL8b6GD^f%=*%=_u`=JN7S{yDXu7+fkGerT&X4+!LJ4-V`?gIS3?92U}4 zK76N0-@S)U$c{v9;`jDth^iKlV99VCw?bBh?D6INLmA2+m7EOGp2%erCp7=!;!dj! zUG+|`iBLd7iFGb}nMCm(Q=AB#!jkhl4MJ)FhjKmc`*{1`{KM`e?IXWT_`J|LyYIsM z>?Y(pn+;a0T1T;D!bF*W@4dHHJ92$2^?REbmm-IPHld)b~^Rg8Tzv458z#n&-V z-=Y#X(4z9!@`X0Q8JuifPrJ%d8FUB#1uMP7e3!Hm@1V?N?V;FqtPDnZcaBF#<_$Mm?kUK z2CbDEw(T4{`fa8hg+{qRI(ma3S*dbUU9CoQ1Fy9iLxsAMLq;j1zc^Mo)z;0nIpC91 zarYJZ!i_W?*$KkVUH#wQN#GKMid7x2%7fFRP#X(qkwR04bGSggGDX zQGI2)fJt4C%3AomkhHsCQf_aa)n0J& zPEh>%avbj1oOUrmV1GrDWOLxUqt8bZEf{FBD#Xare)_~0$=P^loJ3%R{7mPK!kSHh z)TpvhI%8$|W-6t#8802F?A1tfrH=(};g()WAr2?;m27xz)&{I&XMR>2AD-OE7GVQh o0q$;sq+a&sL&IB$c93TaqCHvj^S?Tsh?7MJU{D*=I%8DKe`?c{LjV8( diff --git a/lib/python/Plugins/SystemPlugins/ViX/images/remove.png b/lib/python/Plugins/SystemPlugins/ViX/images/remove.png deleted file mode 100644 index 28b29c05532d9623cc6fb145bbbe4a7413f98661..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2201 zcmd^>`9IT-1IOQUd?;6<`h18sN6CF36|pRvD~%+#k82s4B<*9;;S6b#RfZ_dB0egl z!;v|1ggM3xi^}GVMvU$K@%=l#ugBx{dOe=MzkYaSxVbvW>{i+h0Due%X^-A%!~a=Q zbSDE@yJ`VI6mWC)Klzi=&W-bdm+2kjn)2#sF$b05lR}_(E30 zSKaEenEo9A7PQZ)9#9VjG(!RPzvWJn04rz<0pwR|ZOW|w77 z;FZyjp{`ll!LOu`U6HpVC?ake;+jroFIy*%8TjVyLnR+@PE&Tf1M|$)^nG+JjAZS1 zQ^n)1ns=TFuF3>khA!K%O=|Icz;L-yrxjeFizzjTD6zO&h0JH$;$Iralw0AePY~Xm zDdpIwHwC@fcFOt`RJMHI0&<2|R=Jq>xO!sGdPM!-XxXp(zWr7`hicy5p9hqD+8pA-p+?$)H``sbB9F8 z%)jD_m0x{#csCO`x|Q=ySjiE5C>t}X;hM1p#T;SnqOgq%R({!fqiu5@5X9qYt*-(wI|D{`2*E*VqP9@QSvxLJmnwUb0 z_)?ZsJce~M0~4ZoR^h->x{(o4KT8*?>m>=xmozeybaoo#K?YqZvEz7F!*5o?l2z65 z!u_nRfTGyzn_uF;#0#fjBB0A&p+r%YZO4FIt4>{{AJ-INKG~Xm>6f6);$_sshHLNo z88$k_*nnuvCSi)ru5S3+xOC{@tEhR&BfmcsLRIgTdoIuJwm3y{EN=H7RpSmCSaieA zETSogU{^n{CeghNHv@m^6@GbYx=oggTYW4q{en^WCc49=jL6jZBr#5X?=b7eN=&QU z=TBgG$;=7PHw8p|c!iP;m@7H*v_lC{50d4NJ}#{sA^(`guFn^$5h~@knk%H8M-EpT zJ{k28wU=9O2nbzOsUJd^nUsw6zkR<24Nn?CsVQ`vd!6GX^pIey@42NUKI3d;+)mp| z7eo7o-?`cyqyp?x;s%h7Zlt>+H_xcV+2)%WDqcCk1jv#QXeWT{f(GLNfJ}pP@lYU4`(I43 z{WNHup(HKry>M}(d2wSg>rrI+U3cu|lH=hDTjNeMils!u5+gsf&b98xDyapHu@Am6 zytAKIpc2PSqMEm&Ewy#--TKGPa$u?XtkXUz{jD;kNN+f5w(m_bz3&AV=RHg4^);J| zfA2>LOHEKHGV_VC_Mw}5&L3&RnL4wONS}G_LlfbUga2A~woG&rLqel(V>`!;MQrBw zc)g^Fp941jIlnHWP+rjZ#Y-9Yweo_3JSwh1u2FF~5eK7oJk!)iig^9#>ZI{k%~MO) z96ydk3<+p$h}%+XZL-yQyNKyxs(n$HcvTWM%44d*wGSeOtA=j{n<$a;RMoV*sT#KB zYjOSV%t_u5@>0%MhTfoQ;xE?y^js(Y1*>}+s+eyb@v2Nzur==bb*%?o_M(AVRx~#a zKvR51?t2P5WoDFm-}yZ;n>ZF)Z)$?^Egj9t7`v@*(qHcMv|wE?o~Ypq{fAUPO9L^-K0u)m2P}`Uu7N)Br?zt;70X z1*}kq!$l*Cv&LZzTOApFYw)d-ky`~CJ`y60ssI2 diff --git a/lib/python/Plugins/SystemPlugins/ViX/images/upgrade.png b/lib/python/Plugins/SystemPlugins/ViX/images/upgrade.png deleted file mode 100644 index 860d3f1360270c67e922bb720b9af58520c354dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2603 zcmd^=i9geg1INFH#}Qq4a^$8AdvY}Kw47UQm{5+DJ0i@r4H3ETqmeOWVQR@@jvRB} z3N<&mLn!2U^u*-X^LP9{uh-}E`3v5kPolZm4MBc!egFUjQAoJu?^gTIyqv$&X_~JF z06;&?O>ZL>j|#v1s#NtTeAIYRKe`@~)TVElAJV*U9oB7<-X7ltxkvnn&g|2*D6uXc z-8yc=#Ppiw^b5j*)pd!Md8~Vk&#*_;vNoBniSLTW?B;gZU90RQ`Ya&lEG>sm?)VYa zyW!LH?TS@7`Qt9ai#f0#D5FhM(un)SPKP3MF)t^@#Jnx>Ee~5)4KTEOsVwb><+y@T z+ti`%@5P$_G_!{tp1H$-qFcrAmb!NI`f);7?+;zmEaqxM5{tckG#vMKP5~V9bV%}y zL8#=d)aRo|ijL%}r9-f5zA3f=hR%aIz126NkOqye*f~@#qiW`3JWHfp^Lmw$)ax#c zl!14=P~2aCr#fX#LA{DQR~NnOzXW6sAl+-^6>!7__Fq>LgbKNV5O^!F!Lz*PNhL_Q4ua@hu^}S+SVbdB-IThv zzgyI?3W&ttdtT&SI*h`#!H_vz8tLOZ<908{GwK%g9imo_U6AB8O<($DSYp5%IS&%+ zl7ExDxvy;s+PRu-S+bY@VS~^)C4ZMBE)z7smQ%aaknxHI#^eI>ZnjC3pqEpy;4%e8 zJb|`kX_7}`cLiLhckB$KW58eCS*1r7@Xv^3#4Hb_H#S5O~ zF?B$Qfc9t#D0>@KGeB%|N5@nFU=ImI4Al9ll1ea#T4~nMqT$^-;KIE-1gdipO9nd+ z$a|@4g%L|T(uzOe5<4{XDfcPkG8$<`Q{}%ASW&q79}h=(OS4w&#|T-MYFfc=l(Z}d~{jeywH=Ehr2F%EnP<9?e&B8(Pamy z*m!}jmW(%>vvu_mj4t^foYJ*a`duPf#)log;&_VPJEqyCd9|baPm82lJy1{>{)%FP z)d6E8O4?V0=LaDPUb~*o1=`bL#X(Gad31q`w@fsjY1)K`f=b-ErF89Vvh}QMmA%4_ zb^;}P!EfIuWd zc~n9}k4SIw_J}h#2IUxqcRiYm52V$WK2N_m!|kWD1a+Joxqc$PDv?nO9+Iow+o9cT zJ{imw(DxWzCs8=~0;jbGcoKxx{#I#E_S4RfxqQ$@&RyRn0o6U$cEB}l8VZgSEc3s?i9yRwN}JC=_RYi z4y8a|0WrTzrMEeIQd$R7Yep;E!~^hlN>_dPmv(p^Oaf;OT8$y9c^OIiI4zq`L4tL; zeH8?kEPe}-B`6F%+RSk>vMWXgKigto;^u;2y>kFjn3vxt*tV$;Aq*wxx ztg(agigzltAD4I{toMyp$uRPbyv|X?rgP%^}Q_C=^2kx;t=(O2cR6$P5%DE*PwfK zBvFJ?;{vsw4+d*oPxmh8J9*OK0w#;`C~=aTCt`h+h)v#j;mES@o_T7FpB&%LC-D2q zY4<&N@N!5Z>J%hXRgWZl7FMXN2!cOQfD(<}U&O&;4b^Kw%3_oPmsb^o0lGtw2gUaKwO$jKuL$6KnO9;!}Y}M^V2t5vtEaO z(g-Vazc?4AL@Lzr^bC{x(BA=>%*xy;la+rgL(A;V|NaQG!t6FT+I7vC>3i({x+qaL zbvZ`sEcTVecJ^HJHCweO()fjG_+rzr`Iz_=ZB5k-9pWo0Z%|CurgLaNTQv`mJ+R+a zVKM2QouLywF{8?Xfp04AHR?4joI?mDJLd{%y&hB1@%|OPFV{)^y1WK_%W?2(f5Gq7 z(s&A(woa+6c#h4Pog8jqw&*#1=r4Si#YbN3pIa~j=706JPl&E07~9*=@G~yBeYgSK z?z_6erL02FV_kgmm8~AZowQWnY7|HLC;Q=dl!>kO0QddOFTk-RMfP8bITRuCn%5Te Q_w@lNgckt7Dd)G)%id6Vk5lkK zAw&uc9>AfB;kpuh=33~Pt5|{S@e&S|GERkZ4$m}wYj|~{&Kksuny3D0lckC-)d{E+ zHhCmwopI5pMam)9sNhg9Wlqf>ZxGdPmp&k97%XZ33$lM{{l8;xz@tRSMQdS`bNu7ERn-R$!7P;?i^C_Nf z2j10GKiv4u4C1ZqeyjWsmM=!^OD2((RCmIXW7Ui!ZW2{X3nA@d+Lj-V9-~sqeDa!1 zGn)d4+la87sP0vh3W|ijwQ~jeZz`BDxc0bd*p)DjEN+YF{*<){dK0O4vP!P_$N09A z)o)q8{s!j0r@UzIvWb6GIZunk<2|#V82Ec&a8EUTZ^!qP-3YUTYp8ms29fAPR!KIo z<*_d(o@Km?#xIsA-jK;?47*pL9ad-7L4Q#{ljBpa-Mdo|SR)bDELSjLKJ-03c~~la zNF`@PJEPhBEj=) zU^qY)9|($oEQj}F#vm(z&5j1aJP>RFe*z!_4l<2FhUbSdA2#E0Q)39Y2Vrez4h>#mwfvR3gk|C=2tDowoh~@ z0$k)6B>bM0AYJ!LgSByIsKaTYPdq1HEHU(Ac!0W%IUH9U92#Wng*FAJU@WRwdaTC5 zASB#F5{)wUMJl52=zOg_ec#>a^NUloqRZ4I=wt+B00~9kb3I9Zz2Zj_06+k&jfL$A z{+9*V9&*W?{DoE%gu!j&A@q@@l0E4U_lAk=p*zf5kkf`pD9$~3tQ_-(4h~yMKE*N z7|~v|ndUSeNg}o!|2V+5WnQ+`S|`d;?)#li&-jJDP#^R2c)Eqe_OA>2n~z7?At!$( z-89i9qSlYYij{_Qwh-4mV!0Vv-FB@O!O#RHHbrZtd&_NQ@h%O%Q_mIiB>eUELkwfE z?ho5KCi~ab8hm$o)9-K1zI7XTE$$r1ir5pbE?50i{-60I%iv?Azi91sn7*!K1AQ`k z#HCe|bLl$CudKJP3#&2r<$Zry5A`o?rD``;+Vx~ONvnH#vSwt*LV}4B`29=S2({ju zvyw9aUh?>;fAx@GhZT0bOU|j{qa6o-UwpL!z|q;MAzo$!A6f zT`ahWgUebn&A+#P*+e}uO3ZA+AdqzO@*449ZT1g#XB!v4t`1~6yK-b*S==_UFf+%+ zajYrY;p7~)bHqjwTo&d*EXa!El3;r*oh??uKsq>uV9q=B6iEqUOygQ#ku3krOHyp- zw;$_0=U)*X9G8wx*NgUXDh8mvK+0MmW|qbNoSbKw8PcU2ZW7{X-KI$ec*QfQ z#HX#9IpN-{K8Ln&QXDCK=NJ2fJ;qKqDR_TlZ%>z-X^8xCuGoI6G3hI+QlB}L3qV$$%Ima zPx|jaPLoH^`wx|8In>3rM{n)_#LMXNH6}dm*nT0(?o3e-nVtO_dH4`p$lCopQ-tAa zwJ28eauO)$DwciTyy7*0uSVByFHI2-=eBhI*q3dyDAx8E*ET)Nn~wD-Yw4#uo6UWk z9jx)#$(m!7(7i^R1skSDd-5fXYLsQ$%4`VpD_HI2Hrr z2ngm0vqop!~av@aN&nk6ym1U$X5o@ne|D{m+q%>;Mp2ZJy nC%sH8DoTW$zVQa7=>q^pQ%>hZ*0?{MG&*2nWPzwNbWQjlf>xYl diff --git a/lib/python/Plugins/SystemPlugins/ViX/install.png b/lib/python/Plugins/SystemPlugins/ViX/install.png deleted file mode 100644 index 1287c35a683e69a7b5cb5d0f197dd339aac7ab84..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2176 zcmd^B`#aMOAO6~$;-TbhNOD{`B@{Yf+E7b#NbMqGB)l^l+sw=~M5&iOn94lr5k>JR zYKvvoT28aZT9l~eP|gae-pAwlJKoQAeeV1ET-SZwKit>-!>2G93D?pv(EtEID*ypQ zZL;&fs}A18=yzLMH_4dbA3+Gg#uJD!X&AsK4tow`5s(s-fI(qm;>fsej5h#)f#74I z{+r^Bjg7kcySQukg64bz<2!LUIrSJBZ%a2s{pLrr< zj!sHReE@OOoDck`14wKGGF~bXUMNvsg9rj}N*g$-O_?ZEBMQ`U9F1#JdTHEkIZ|B` zPnX_jLKm7B3|i**>?#_xsr<6%Qm<{H7+NfGx+ZlkmAO}pcvZ?^)uYF5%OmfPCU6xr z!6&AC?(yQfV(r%=SqLWbmDAdlGrCmL`6}t1szkmzk++5POq1O88>wB3{7gIji59s- zhxBxNX1i_{PcN%OpUN|!b{J%L8q&IqYQ9<)_uG|7omgW3myH7Nm z>gwvs%F6Qc^3u}M!otGr?Ci|U%=Gm1M3Iu}A&Q2bW*WTXF<#IV3&f~|ATU%ROT3VW$ zo12=N8XFrM8XD^B>+9<3YHMq6-@aW_Q^RJntE#H5U%$>`u_`Jm%F4=0OG`^iO0HhL zT3lRQR8&-0SXfX{ke8R2o106g)3dX)sZ=V3LLrmML?V$uAmH(M91e%YVw01Tlai7W z6BFa(R$*hW|D{KIaAiC;{DJC!r7mr-T@CFg4$w;>`!J3ZEpgorsG7n z*p!m_3VU>(ABghC-*MI|d@8C|*ISIDt9Z?--emeV)5c$%JBMPAt+N>Oo;_*QEA*d= z>(5P-Xb<-B2%q1gC%meYRh63-`{zW~6577H1;vOTn^kY)=Eh?k_=WM>e?`AnM_i>M zX756i>eryQ-}?C`w+esoA!l2y_XAE@BoKgnFvx0S{v;f{F_f=GgmhnT7O73AKp5b9BpjBn_AcHhO}kK4Z^KXj>e-u>%A=$%-r`4bfecpsOTl%y8? za}S4waU&zXS+wZad%6-WiZ^%!dQa#&;_Pv+=I;-3n^b$;>;5=Lut0^)dfuHrY>XeU`Cpl?t<$6iYVMDaJ&^Ix-`cc~!aul^d7lxd683~K?dJ)P$3to&!t71krvK5$>nPp;zJ?4iH?jK?lmmRhMGwv`-Am9>GQ zGj|nzd^7IDy~mIQLYLKxF6r%szNlMp_n>nvEGt)!xm$-tCfsIFYrO+dp0@bEYRZ*& zc{`NhhP-NTrTpO-M4#GiT~?Z^mb4P-aKsmi(NU-EyBY``;Gx)4_O*Hei#5xEn$r<0 zy0J=$h#$jahH3@~2AE#TUe-GnJKAQ@&&D4 zlNK{JgKOSwZQ%Er5oVO<8pHkvcJkZC_%kpKBpChvh*EsIaq~+60{oG%2fop{{{WpL Bo*4iD diff --git a/lib/python/Plugins/SystemPlugins/ViX/installable.png b/lib/python/Plugins/SystemPlugins/ViX/installable.png deleted file mode 100644 index 09baa812ce69737a3374d1ddce66788a8a3c67e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1023 zcmVD#FAup7 z{xdk*V3qyS58DJ+KH1^w{^>0KY@y?|{(FLN6S2{9Mp36}^_BArZ(kVM8XV5-ERkL! zl>5@e;bQ8A@5fILj&1=)4$`F#*Ax!rQTC#w z#B0krr*56D2aa3V@b;JhL7phb7+O+s8W1b-*L&~ot_xa493L#S1BhYdMYx#QFifm1 zC%yd3BNwx^APWgLmpe6q8taf~QxXhKN9Te4`6*c^!4n9X#dt)ZR0c-CU?#$@_5qe@ zET=QoU@ry`NELA)F%hPON@1WhM-7%9F`2AMFcr{Jft8LZRxuM?2rig{TuLF#Pv5k3 z4ZvJV#Y+oa`B?RF-wz`eMGV04=Jd5Hz(Ev+rd^Qei$rpN_@hyY!Y~LZ z4I|0`IsI676}aA4aYGYmZVT?OKDGaHztH*1#fS!BM1hrTH>!swLD4cOkwP#+zQN#k z81a5s`mzuN0@{tOW7S~xK+eY4)U3fkjTy=2~9Rat*I*wjXP*9a3B6nYcs+a6JIs2tuSj937^yr2P2K1G@&*GxfpyXHQHv z-Ytbv0svHRQn>!&T>nG8vBAx1X6)q4(@W(_$eAdf7zjOf_0Qp!o?B0EUS#9rSG#8l zPR?pX2*?eBZCv`*~jP*XwzHdtT2w$;r`1=HRaf0RWIe*jgd? z+30^OCAN>4Y3cfXQYFJtWS1acaws+!4?ul_aQI^gBGwO&#AAKJZujCZ0e~3b3Efi7zBu(B}ty&H{O=MKt5!CR}r41hRj#Bdvwe( zRnMDo$c!v=Ib04(k++Oiw2o1-iPLn;JmryR9Q^ij9NW+<>w+K6^)Xx7E?&hUQ5~78 zM`}4wtZhhYjYDwHEgqq4CYu58Ey8*V<=v+oip; zOMUB{%XG;f_HX_3Wv-+!J zZol)>VK?e1rkaZ_`H(s!)PX>+)5bksuu-KfborFmi*X;ud|<# zjPK=5^LJ3m#f*g=L~M4}{O+HflbNH7i(B7=D;j#2*Gz8(KI~_DKPzbyg7AA`)w7fB zOS6>LD*6o56z`h;;dMx5y7gUD$z=7+=4|s)(+K}V$SY#{U=k|zT5uh@d5PwgeT6=i zoACD&`az*7v6X{rb9iYPy12Ng`6SF=VKn3ACKpaoh_PE@7cV=*{#iBi9Vk= z&sadPcQQWh7U!{)YnIQqEZpSmmHe|;zOvWF7qZwtVwb@x9$4QmaNvOHD`4}q(0>^$ z=7H3~-4hF7>^j)C3HI{9%vBJ*4&D)fDf`JsPUw#TfCxZFI=bwi|IY)s2qd-kd!Yeg z1$DLUUdgs6sJSU7FrOxNZ>&$$a5|;kd8n8s-Lj!lE2{(kawhO-WlwNLsw3*O=utp$rjNgQi+Xn)U1^G@u7);l{$Ne~fN`!K|1)5D4zp+fiLMs5*QZvyT6qnxu!f&8mqCSoIJvBM9?a7;L?ubg68BCXS%##A*L-#bq$?P6w7WV_%PKUz5a0wDeRr=*0Cj==^oMz(O>7 zWy)K$b|laYkk@{&^gjO=z)I<*Z`(YeP$%9~NS$+6k%eMJ5)y$nSEvWx?j#^uz>|r! zm7P&Q0V5LJfb?pEn<#OkEvo-N>U2>hNeUW)X+_kAnVcA z{pHQ!C$U!|o%07&6lsCd{Fo4Rt|s}KrNN;4B{30WahL=32LHhpHepn$QxaSTRZto; z))Jnaes}fls#yzX2&v$wp4EVcm5(ze)l;83uE+&Kiq+;29y?nsf7Lc%)YLnDy{72* zmy<-9&!2bcxaF*w1Xn~rUV_LOeF>OCq1JHeVpELaDY5uEp4;p7rY?QuFcLPkogNjY z^-g_a%_nGFAqE*9Lh;PWZVOJ}$PgHcD>vcZR6e8-$F;T7_JJE0gb$vKoc-DlWcJiOv diff --git a/lib/python/Plugins/SystemPlugins/ViX/noprev.png b/lib/python/Plugins/SystemPlugins/ViX/noprev.png deleted file mode 100644 index 0a7cf2b480bc2f2fbecceef4a7ac0bc203bb1a09..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1467 zcmbVMc~H^`6vk3y47v zdXNH9kh*!L1&Oj|ixIP>EUwWGsi6?M{N2p{(;siXZ{EB&@0dXTpBpOZba~AOb!%je)<7s}>NUVHDhLpS=to@3Rf5z#N6vCKqk3kTLu zMR`*?XS)t3sAC!AfRmc*o9ior(wlN=A)Q-`^A*|wjJ=+R)D|)L&s@MLCd<5$+*>6# z?2eiKELV-yNc%oY4KjhRR4X%x)R2#M$0M$93!BOpqYekPDJgkazk)Bv^QP?L`n<#m z(wZo)yL4#{Qe@Wb#!4gv1e^E!;j#>y9r3(1$a6!yqccCmcCNLXB3gs!J9*ajO!Ep| z-q}Per%|>v1s}<0#((rcriq*WeI= zjDgemqk&MokT>N^`RUp1WJ+-JU9ccOE^%qr>c^PzRYg1+a6z#Y0w>U}Vg4gn?WG%+ z(;p9b{(Rxf!Q71k#fi%mM^u^CCgGGT#Va$4VhLD(QR~JUurTIW_qyKzaMyT{ zylXMP%+57;8@OaKM!8>^7cOt4$&b$13rCOKlAZqQW7V4!)i`o@x7}}7f44U7kOgR8 zInz#!Xr*Pfw#n>wp;(R%E~7@RjM*kL}BHc5 zjCb{~%>s5yxL_rLe4fsTYF*0d$-Iu3r8AVs8-=RWHtUU=mQHc=WbTH$f1@_#@pIuIt!8M^J;wG zDzQ%c-4h==;(GZbYI1gvO)KDYK-G1@v`q4g+2B(wdp^6CL0xr-B*(AnIQ2ixV%Vom zRlzu=wX`Q_=PVqO)@-f!g8yVreLnKXIr#6RN+O8CC=ZA||FM$5kIxV%1l4*-xPGk5ybAVLh5)Rl9ZKU$Rw{Jcv(mXMoEWphn;NrDe zX<{~xlgq+}Qt0wOB}1f=GPh-`1*S^K5(v;wUAcV1+80>+FmFDxe(rv+8vJcR^?zGs br%74`45*LaGtb9YR;GyUsoIf6e$N5soU+|{^KoD@Wb4Ko#K@eO4 zBv?X6K;3go+Gly3^$}UEDMizD^>b`vyKkqRX3n`UU-09(ktQ5{rdH;*1kv{!-u^ zmOSPiHktZ(HRt70Y1QVt#+~I~OMv?7UpmkKf`MYDbK-gn2hBh^_>vN01%Ycj=egE5 zyvh0ws$oE5Z_fN8xWfZ?_<&S0u%8Sl#Q@Mii0(^C6|AyZsF3zu0ERnYTLUQL0aZMp zd`0RE9Z(~Pn?^%4iNbnhXb?*lktmOhRl^pE7==olrpRNSKpj%leO`;7441Z|$|7&+ zlIqW-u9(M;>R>Ytpkoi&CCEG8g}J1wVjrLMqnmr&QgFVf)6}=;3)qOndfeL`+mz3Km8-t_1Eg2e z*wpH@Zt%>VTI+kC?H_cw(%Zu7H+`~Ne{w(tG{Gjl)!|VWCcD?Of=w*$GqiD2GqHL) z#8Y#lxI7!YTr}$OavWPU>|4pY(ZPK;y%Suw5Lo;3pQgn)29Hud>!1C;g}uXA<_A?V zk)(v!FN^1Gj`T{ciV!>EN|LQxmUDFGEy z>il9n$?K6tFx@GrOrQ42KfTN4<9td??a3a_^QceiB|~IV*^!81?>Lf5wHH2=;#m_NzGv%v?eU_A%?vd$k^1F!u7lZ%RN zMyqn_f~}i_Jm0-|{(EI*o6Fr@er2e+2LM2TaEyb~Zv1}+;PgjC6##@#XoQtBs%Mp(Hw($c2`{IJMG}~|k_f)47i11CC+g|Z zv{N*pny#X-Oi?`}Q9Ijy4y50qC~Ta`m2;4}?UfsLW9w_=*GT>pOaQds z&lkxpw`}W^YSO3<^q4b58c#N*hWzFgn!E~nRD1n>@34hN9?>h9utl9>u_|i6)h!== z^g3uk^!T5TIZ(y>#V#wedri*LZSq<@N0jFJbxb;8=a(==M`72#ti>=~b+^2KYvp`> zX1J3r6|we2TKwg3&fDNN`$F27%4d=Bk`LCij?CzU>I0tCVONQH-lcl4fRC@yl3w%q z$Dg&y0m?W@?#PpZvZ3ssv&4;s93^U*^maq3xZTjP3f-q8&VmT3jao1KnnKM0(#Rlx zwD;YIZK!`tA6iMK?c$p>TfVahOL^aIIpG;QJ^j|^{R|-t*8lFcPMiX;M{dq5TkmF~ z18VEMLWE_ek*;j`=`kQ%6asArNF7ig5&&d3!`YdF^2%xli!C?n6h5z4lA$69;lzDf zVkTvhXql?Qy?&rYN#k-!%Ipyc_5mRcBtjO3y zOB7P<2@2tqi&)5yD*9AC3>YjQyzOHkN6%1HQtvELu`FJX=ye*K;tq_rSCiKNP77dMKvi~~KOC3tO+Z}TM9-$=`MRz0}Y3P!M=}$7%mhB*C zxnsV}DfZ-XZOP%x@0rL{?xAC`UJh^Knr0dtjnWg%(f%C@%%~IwrEyCZdG P_hSHPqywTH?tS||cNXQD diff --git a/lib/python/Plugins/SystemPlugins/ViX/update.png b/lib/python/Plugins/SystemPlugins/ViX/update.png deleted file mode 100644 index 0ece6c76a7a87233bb21644f2c0d68e0f8218eea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3630 zcmV+}4$<+6P)%3km`O0RsaB+S=OB z&(GP}*^G>g8X6k-`1sS)(_vv@Ha0dJ8yq`3JDQrBWLrpjdU_TW6<1eR1qB6oCnn3w%SlN|Z*Fe#zW@ON0ivR!X=!QG)6-B;P*PG-iHV81hX9LG=UrI_!g@uLd>+89R0FaQ7e}8|Hl9JJ*7A!3+larHe zY-)0Ha?#Pz3JVL0ii)PDrWY3%f`WorSXetdJ8w}1h=_=#bpVuZn6=P5-MMXuYr>Fh>{e*;se{n#lsHmf(qeDYOpP!$ZnVA$66lP{- z;Nak_tgLr;cY%R{Z(lPbBO_c~T<7QK7#J9?uC5Xi6LfTRVq#+Y`ue`UzRk_ej*gBi zD=JM*O$G)AU0hr}K0Wfk0A*!m#ghO}Pfs;9HKC!Q85tRRdV1)$2XS$6jg5^ZB_&Qx zP58wCq@<+b;o%4e2j8v;*4Eba^z>_MYg$@bTU%RweSIJxAW=UQCMG7|tN;ZD1y)v7 z)z#I`oB(fcZ}IW*rKP2omX-?&3ROrf-Kqc^8ykp#YR{Yi@9*!-%*@7@2vSi`*}GQP z*Vo{!1aot9v$M0HprBJyQL1_XXlQ5$2M0hvK-=5fz`($saR9!I08mIa5)u-FgM$bN z2)nzx92^|N!op5SJmsS$;rdR!~FdGy1Kfuva)=9e3E@b$HTXOe}Blx$ef&< z3JMCAmX=^&U$L>V?70B2u&~#p00II6Jv~0imH?rjoVB&JtE;Q8udlSUv;+hM0RaIL z5)wT=K0ZA?zrVk&t*xD%oxHrf4Gj%FJv|N%4iOO%0002ExVR4w4-gO#R8&;=_xHEA zw+00Ty}i8y0|Tn6s=2wj3=9kf1qLQ2CKD4A92^`lFfg{ZwhIdjI5;@}|NjLA1^>(d z-r`kH00003bW%=JaRB@qPI!(001C=UL_t(|+P&9%P*YbL0C3Ch+SdB0;~zT1@McDo zmlT3nhL(aLuku>9MR^3|Wr>(TC`A#FhX^YKf+Hw0tyZv2frSFviA-7&UXx&o5tM{y z5)29w2#E-U+_2xd0mRnb|8~C%C+Ftop5OV-Babcbyt8HXe;Qjr0ORiS=g&v_`{#$X zKi_}wVCCuL^s~{$#b-~OTxU%gEiJ|D&S=`Li_2MA8jX*vxtSOmU}l$=X*r{dkV^g1 zvUJBil#G}r3z~TzIj}n+*dx`}pU;mrdh(d5>(b4Ib(bS^Y z?Zu3pEeyuaoh>`0ADU#nVIaiPGBdLv^PuHSh`u+Hf+!hHw7hsa(<;@)9}H>KlP8|5 zVEEz)Zv4D%yjbBEGu){M-0j^DTyuA~-(gR6x8Ga7{D(X&GwsX*0zv}<%nsY76&$og zSXoevc|6xI)fE}iCy~{j!qqLS{UaO3eK4L*zj!uDo^m&J=drJuvZ*LcO?d>4n9U(C zHxr3#Mo7ra%t5<-J>hVy#rOC>997-H`To&Hz0!vLh1H%gV5`snWIUzUa%S5&3Id0~ zHl=7&)p| zj-YR_Go=-j+FCZ7$7yYwQV(_2PjHt5z<^26H#V-ENek`yarM%rKP)G`aGD`ApKl~> z$c{ut96~mX2Rb89ph`(n3PnRxZDJ0A2L?ghHd~)0Ns1E+>NL1f>0MgtJ!41g$-Q~` z^5xvzbGfgrN8uE*S1Ml`g^UPgoCJ_JjOl07iG4%uo^kDc^};T;Jypy)z~fL;ItK;9 zcF)LcsWP3YGs?=0XVQp0dY5nB{OPA$6z9(AoIBx;WG@506bw&fh|t6X^3BEudG>(Z zuJr7hof5Mq`V>4su1zQuDs`8ny*gVO&6hGiEkH(MdZKYi+OIu&j~+d`dGqRTzdd{i z>40--_0FlFI;KH%Lu4TsLWxL#kT*8SWLBW^ctiD2oMcd}kaVe4DekP!PIZ?^7*QA% z?QiQs_ZdTmqhoq08ZNy@w~>M~U_e}gOxys8iu8jo^|(Zy+>J*9b0!3NHSDUyg;Mg5dQELOCs)b%1|q;xOeU>CR9M-vKr z+tD%6+tO^j=aV~+Z(rZUJUsXC&Z$Hi-Gd)h2or*gAwV{5kj0Zv4^x(#xlBI;*XRaM zVbZLkl|^Vhq?jENC?k9MuDimF$20+1Fjzs3WtEu$AU6;+(t4MkH@hR`7 z96x_)VY?7F)PTI+Ad4qYYSII;G&2ca9{jxx%DxE|i$JhHz$Ua#^eGGXx~2vP5sA$d zO=Zv?KwwHVJzK5M19N?IGS|a@$RIOa0Fj80F$>7X1{pp1#i%AmrfCj!4D)l2ZV>jd zc&yqT_Kadi3qu@P-Rt6%+I=|G%)%#)LfPY38jjva^sMjQyN8mwetn&}x^?UKTN9j( zs+CE7T|w`32>tmko8XxFiuY&^w!8iGZQnag8A7JwaT>U z!1kh8MiGe=+ahxHk~*8y-DGy@V=*x?dwvgj_g&w+jg8jUe@y0%?><8(7wK_HA2L*J z2wD4-`r@P07p4o!G_u2%i55A`RB6(bA_YFPVq-}+YHCQaZ64LLE_qGy6k3^&g+)`$ zp7fA{b>$7F(RbfxIX2OeN>SIK8jJ}*bQ=UWZcP@@d^E&NN?v!ctF(P+g2iizy%t+i zQgY)6X?v7Sk|=>jC%ai_Xb?@5^vZ+pehCV4?yWQD?_QZ{3WVEHBDkRdWZgJ+;nvcN z05@7GtuCmJ4#TDFYHKCH#2=9-?=HDfLn=1nt32qbGj0?O&AiH-MvK`~`mccRd_Qlr zULUjbk3aVP&iFG!C)?g?p#TO8?d23ebQ=VW50{pn$-Hx%db`ZcxgPxN_AZr}z~;5= zPVPufmfs*1xwp=`Iyr}A9vm~T%5$sBGpEJ;?mYuT_PI4m=3`(!_x&#Mvp^@8-a@6Q ze$8kFWRp>TQe&o1vl$dtdF|piLX7B6nF0MRYp4{w3-)siNpDS@GP{v_qlv@8;4i z%W#8B=W@9@@p%@M^nEa7jdy*o=r@tQ;H`1Pm`D+~vN(WjGA@>9mD0F-MN}0+_8*rh zZa8%8PIiFkfboJ!5gH{_WyqRvgPXt%3uAKW@p&*ckj#}|9BJ`k279w3;sl!wgypxb_ylHWXm6I0S^Oj8yb%edWDL|Ir z9t=!fzTAM37E$eGw_I+itB|l+xLSqW^5y07mvT({^5toU!{AGZuix4fAg^>`vR;_r zwO7TM`hrOmM*54cM#8!;qRJ~SCcj`}GKIy;u~hWB-I#Pq_v%-#!(>yFCa(ZldV9ca z?=49&(h91La^>>Fr%`2TNse_dE!AMkTCDci5<2bu2)!DD^&gr-`(z_V&!A%MoXEduf)6~mg8nEb(+GiLyq#9yt|YF8G|=mIrxX1&?>06DsHbY%rE zAReIF(UtdCR^YauR{$ACwfXt^zuwn9)s4yLAJpO#jw#^|K<*zsieK6k-|AZX_I+sY zee{(`JEzrFKtHq#3v*ih5fy5TWTw4_nf61W{$K$Gs=&mn`?Yc`e`G|B#ST|g00JfI z2)b)d7pTDsycyIu`l&UiJ3~={0H7A&P|KmOheqbL>kVk}aU-cm=GB;dWLTSzVcl9S zLXeN5ccUR_qoQIC@9zQ_?;xcD^o8{-78bPl$$bB|k!|zPmH81}CQyOshm#LR`XTM% zZQF+D=K8_Y>Mo58SF9QM(9Bh!68$j!fBeM$H`;fNNI(^kWdHyG07*qoM6N<$f|#Vd AYXATM diff --git a/lib/python/Plugins/SystemPlugins/ViX/upgrade.png b/lib/python/Plugins/SystemPlugins/ViX/upgrade.png deleted file mode 100644 index 135058409c17f45c0da3e5de6c87163a828a311b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2640 zcmd^=i9geg1INFH#}Qq4a^$95dvY}Kw47UQm{5+DJ42Xjn=^9XMLH~a5&oZ+ec z4G}!t27kxL6(8v2j{)>ue4H^-NUW0^#scHy671KHfdT;NhndM;_|kFFmtR#X?nRH9 zF6%`%z?0hbEb>EI4y?j@jMF>fyTK2LA5oe8I_9NTC1cws?dX_3)0_c*Xpou?(ISue zfc_c!s7Bg4(=7ZA~9deUQr33a-EvjM=0P_k1tW@S~arcY5TG0P>j1 zk!>}t=#7(vu)ZHUCRvQN#v~?d=XfOU?Yx{~$kSo*bNZp;cT%5^9m_kAtCx=yUGhz^ zjZjn`)bXvJaUp5Q@S3fC)e5q9A;zOr!X>Xy2|>B(Oivkn#|^>#^>?ac)-=Skq-$-- ztKo}(<{-kYR#py2Tx9)qEkOVt$*JKty!8uiRVajvxnL6i{)dUQ9Dxn&L0^Z!>}h;j zVRmJogai>yD-O8V*s{5i-IIWGdO6nF9bomx*t8FkjoRXpz6P$1X?>dE1s}s(!~jt& zaWL^LvJsBARMdZ#*D|F54%dbgohmnlq#rA*N2!@m)(`fIJJ$fA_y^C6y~;+AxOONa zheJJmVt2y!WMRgysqIxy9!P8ex+GFK2@Q}KKEmv1|uav*!K^|8F1PCbiX8-cHQMH4_W;aw! zHK6D&29JR_JylQ+VpA>48eTHEUk_Y*aF0N7DrQPy7XVpLHO(+$S!Y_w2V7#Ox?Z7c z;e?cWTJdzn?}Dt#-TtpM$9N0VJ176g0uF9p{kVTcA~rJKkI&9B2nODQM6#4OD}2@A46AQkqg&&8XV0JJNp-rQz%cwZ`2@>D`eu}*k2=>6LK3WQBb@`Z zug#1DoAhz%0GIC=Ydq7i4i5#Dx^YVA*ji`nTGc6eh8^$vM>rh0*DRvdIJ+neA=G1! z8XaA~7cjw`iZr;H^=#Qt7_*x{VV~}Pm9!M}mp&A9jLXY}mf(eWCiW3@FVr%;`} zyAHPUqdqty$hTOy%H+?%C=^A`ZSdnDP$oY>|IP*mi-mG2hlU=L-sJ5QXKxM3(2MT7 zx0D=8sxE(?d2x=@S9=-aFg1GfRD5+Jy-smhrfz?idb{Ox5Q|UGeQ1MJ$i@>eqdCZx zAh7~b8$J~>#cB5A8h@ST!$*f7C1I_dP2*;mWpC=nddHg-z7ak_-O?odJ zbAl+USga2Md7xgr8+5Bb7OvG$Akk2eBOGX1I%zAx|KaXu6hB?S@lP_9vVbHP5kmIuW6~h&^^xZ71 zCCcyg*6Ft{7@bTMWEYWK$y$HT%fDn0##cory;bE?qP2|?hEw$9s>lr!{VsPxOP@cN zVwSe!s1aXTgbCB;(`-&u%}#(lC=!Y8edi;nawC)E z{E#fm&E^R4(5S@3f}M7h*7QwG{W?EqzdK9CH=4e;nN>ScdX>AGA<->fJ8ySgXqMA) zt`GC%MTC8mkx1hR>0;!C^DrgijmdQxd3kw7^xnVUhN{_WwLw!h}gtWXfJpk8-P=B> zdhe#Jn7n7@{(@uw%M$J0i8uu|VGo!;(gD@%=O=grvR_XUhAT8JQW|)m(58)auL_>i zr|mDHv*?c!r#QJHHpYn9ps&dF*Cn*icRyxsRf-BCIjc6I6X;Xqoqa3zY ztmcK>lGwxcad&mFb4w{G>F5&(F2a7ak(hmP=5|}w>(Ec?VdZX@=c5!zMcN)7VKN^E zI>A#}nY-oEvX7;xnSJ@+AE8$nJ!Xb`E*Z1^kKJAuCrYQT#Au$!z7pHXo^QEfqxwV= zzc>S1Y928g7oDcAtC*rfe1v87OUPO@HmzrCX8zKLc00;U2Cb_rbh0;QOerAXP340o z-R8v$aDil}TmjA37Bdv^9 zUB?dtMenkB$V&tBi-y3$ufC2+;nf5qJG)t4`X$VVTfp7^>#H0}%CtP@PQ(kP{}r1@5+ZMSZbN=wAAp3L!rmA-M*R=otb3OL diff --git a/lib/python/Plugins/SystemPlugins/ViX/upgradeable.png b/lib/python/Plugins/SystemPlugins/ViX/upgradeable.png deleted file mode 100644 index 1702177f7b6bc2ebbe2f00e5586cda197209d183..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2092 zcmd^A`8(7LAN|fumR!s2hKnp+B}I%S-Rw)F$WFG*WEo=%V;MV1lJ%01UG}AnvCB5| z+D#}KWH6U3$yiI4n3?bE{X5?CJfF{b&hz>Fc%E|-%}wv}aEWjM0Kj8tfUrDeh5rpF z>~uTLpKUoMVVu4l&I;>>3vmv>0J^SN7tBRNA7^)rCC1q`%%6;655GhZXtlt?K zUv`y50Yn~f%@erd#-p3deKYKLtt3f@chKt|P#Me_xUT>r0S5PBQ^IoG2snEy=dz^@k|Ve{fL>Xo!p!8LS&?lZD|Qs*Dq9tzRJvhF2He$`6eH$(7h;f<2!fx2;>+E1Dh@g1g_@2&DEZfyr1)zn87pYEm*@1^&f=Y2HG z8L=szL{?H=2}^cWGj1ZRYIuNsz9#C0qj z%E|vw!KZ_3&zpvw2%nHeZK2(t(-uJwBK1L9@eS`tuU4|kJ+n98!ORbooc1oum}iyq zv@ks0E&YYAHwIhrQqAjrOi$^ZU~9Oll1HK+i9Tc=XBkx%l{=A@@;(B;SS)u(Dy1>l zIbS2V&bWh~Q$Lg8S*FpulkZz29^QN{f5K$wM{@kIWb%+=#)w8rv&lQUZ*-?<`h;Y` z^xyIA$`v%dx(UDR&zC(CrQgn2FPz{Tw^V4%>_yh=$&<(xu&Vz^k-UXm{?R_ebX@@x zR#}l-Al4D1JhKwa0Ox1c#E4`CVox*!tQj1+n)U(#vQ7=d1~Pd;P#9#|ei$U<>#Q08ii`!vH*S`#9#wI(gpI7zpk`nA=%X@*Dy`D==qnGmzj^KN#Bpt zJ~ESZ5}MK>vZF7l$SP2-UyV$1Q*16*6` zbu0CC;x&r@BhKWM-{=eVk-v_oTSzSLI=_E-xfN_P@@A5aVjV+kAF-J;lPVlc#ng_N zF8b#8ovMYgG=A|-k=jeWWmeL7#|E#dS900n-rD*{p-pNUb{TW{#&!} zTn65VIruU|_XMlUl>ULH&dGx&Iy zoKeL~I}Z4<_<99^qtg=u-Hivvoq&lKd4b>iyRlV#G#6hj9Jp8kmo{UV{Am5UiF&3V zo7#j$AnD}gHR8V-te>pTHV!^5O~`b5<;c2%m{n{+YKEiTSW|@U={b1kh=n3JF3f{C zkQvP(&cZC6D^kQlI@kqZ4mwFlWCXZh59x6+-t&3`p z*xLVvm(t>GeEPCuJ4b}onIJ1XJNqr{@CmMfx%*|N5X;eOTBPi5e?GsfNcvUtiu(Y* z8eO}+G(|j|+tR$aFWqKZq=EUQVRVis8Rtz_*GYCTo*SPXtikN0&7Bm}-A9}G8>U8k z@+34EEl0luTDZCK^aHI>27T$~i{mLHL_t?#L|QKyHkZfNvHkV_2h7 zMsFq~&%gHUF2MqO15p{Y_PyY*!b*TFQ From 6faf053ba54e67a65de9de7eb5ea3022810036e9 Mon Sep 17 00:00:00 2001 From: Huevos Date: Sat, 27 Jan 2024 01:15:02 +0100 Subject: [PATCH 073/183] [PackageManager] simplify 1) Remove caching (which was broken anyway in the original). What is the point caching stall data. 2) Use images from skin_default, https://github.com/OpenViX/oe-alliance-e2-skindefault/commit/c7b89073439447a53357662bc17867421764ad5e 3) Add opkg update on green button 4) Reduce time of load list when first opening.. --- .../SystemPlugins/ViX/PackageManager.py | 337 +++++------------- 1 file changed, 86 insertions(+), 251 deletions(-) diff --git a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py index 7c4114319ed..bad28a14240 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py +++ b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py @@ -1,13 +1,9 @@ -import os -import time -import pickle - -from enigma import eRCInput, getPrevAsciiCode +from time import time from Components.Console import Console from Components.Ipkg import IpkgComponent from Components.Sources.List import List -from Components.ActionMap import NumberActionMap +from Components.ActionMap import ActionMap from Components.PluginComponent import plugins from Components.Sources.StaticText import StaticText @@ -16,35 +12,8 @@ from Screens.Screen import Screen, ScreenSummary from Screens.Standby import TryQuitMainloop -from Tools.Directories import resolveFilename, SCOPE_PLUGINS, SCOPE_CURRENT_PLUGIN, SCOPE_CURRENT_SKIN +from Tools.Directories import resolveFilename, SCOPE_PLUGINS, SCOPE_CURRENT_SKIN from Tools.LoadPixmap import LoadPixmap -from Tools.NumericalTextInput import NumericalTextInput - - -def write_cache(cache_file, cache_data): - try: - path = os.path.dirname(cache_file) - if not os.path.isdir(path): - os.mkdir(path) - pickle.dump(cache_data, open(cache_file, "wb"), -1) - except Exception as ex: - print("Failed to write cache data to %s:" % cache_file, ex) - - -def valid_cache(cache_file, cache_ttl): - try: - mtime = os.stat(cache_file)[os.stat.ST_MTIME] - except: - return 0 - curr_time = time.time() - if (curr_time - mtime) > cache_ttl: - return 0 - else: - return 1 - - -def load_cache(cache_file): - return pickle.load(open(cache_file, "rb")) class PackageManagerSummary(ScreenSummary): @@ -52,7 +21,7 @@ def __init__(self, session, parent): ScreenSummary.__init__(self, session, parent=parent) -class PackageManager(Screen, NumericalTextInput): +class PackageManager(Screen): skin = [""" @@ -89,196 +58,99 @@ class PackageManager(Screen, NumericalTextInput): def __init__(self, session): Screen.__init__(self, session) - NumericalTextInput.__init__(self) self.title = _("Package manager") - self.setUseableChars("1234567890abcdefghijklmnopqrstuvwxyz") - - self["shortcuts"] = NumberActionMap(["SetupActions", "InputAsciiActions"], + self["actions"] = ActionMap(["SetupActions"], { "ok": self.go, - "cancel": self.exit, - "gotAsciiCode": self.keyGotAscii, - "1": self.keyNumberGlobal, - "2": self.keyNumberGlobal, - "3": self.keyNumberGlobal, - "4": self.keyNumberGlobal, - "5": self.keyNumberGlobal, - "6": self.keyNumberGlobal, - "7": self.keyNumberGlobal, - "8": self.keyNumberGlobal, - "9": self.keyNumberGlobal, - "0": self.keyNumberGlobal + "save": self.rebuildList, + "cancel": self.cancel, }, -1) - self["filterActions"] = NumberActionMap(["SetupActions"], + self["filterActions"] = ActionMap(["SetupActions"], { "deleteBackward": self.filterPrev, "deleteForward": self.filterNext, - "save": self.reload, }, -1) self["filterActions"].setEnabled(False) self.list = [] - self.statuslist = [] self["list"] = List(self.list) self["key_red"] = StaticText(_("Close")) - self["key_green"] = StaticText() + self["key_green"] = StaticText(_("opkg update")) self["key_previous"] = StaticText() self["key_next"] = StaticText() - self.imagePath = "%s/images/" % os.path.dirname(os.path.realpath(__file__)) - self.list_updating = True + self.list_updating = False # because IpkgComponent sends multiple responses and we only want to react to one of them self.packetlist = [] self.installed_packetlist = {} self.upgradeable_packages = {} self.Console = Console() - self.cmdList = [] - self.cachelist = [] - self.cache_ttl = 86400 #600 is default, 0 disables, Seconds cache is considered valid (24h should be ok for caching opkgs) - self.cache_file = "/etc/enigma2/packetmanager.cache" # Path to cache directory - self.oktext = _("\nAfter pressing OK, please wait!") self.unwanted_extensions = ("-dbg", "-dev", "-doc", "-staticdev", "-src", "busybox") self.filters = {"All": _("All"), "Installed": _("Installed"), "Upgradeable": _("Upgradeable"), "Installable": _("Installable")} - self.installedpng = LoadPixmap(cached=True, path=self.imagePath + "installed.png") - self.upgradeablepng = LoadPixmap(cached=True, path=self.imagePath + "upgradeable.png") - self.installablepng = LoadPixmap(cached=True, path=self.imagePath + "installable.png") + self.installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "icons/installed.png")) + self.upgradeablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "icons/upgradeable.png")) + self.installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "icons/installable.png")) + self.divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "div-h.png")) + self.upgradepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "icons/upgrade.png")) + self.removepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "icons/remove.png")) self.ipkg = IpkgComponent() self.ipkg.addCallback(self.ipkgCallback) - self.onLayoutFinish.append(self.rebuildList) - - rcinput = eRCInput.getInstance() - rcinput.setKeyboardMode(rcinput.kmAscii) - - def keyNumberGlobal(self, val): - key = self.getKey(val) - if key is not None: - keyvalue = key.encode("utf-8") - if len(keyvalue) == 1: - self.setNextIdx(keyvalue[0]) - - def keyGotAscii(self): - keyvalue = chr(getPrevAsciiCode()).encode("utf-8") - if len(keyvalue) == 1: - self.setNextIdx(keyvalue[0]) - - def setNextIdx(self, char): - if char in ("0", "1", "a"): - self["list"].setIndex(0) - else: - idx = self.getNextIdx(char) - if idx and idx <= self["list"].count: - self["list"].setIndex(idx) - - def getNextIdx(self, char): - for idx, i in enumerate(self["list"].list): - if i[0] and (i[0][0] == char): - return idx - - def exit(self): + self.onLayoutFinish.append(self.buildList) + + def cancel(self): self.ipkg.stop() - if self.Console is not None: - self.Console.killAll() - rcinput = eRCInput.getInstance() - rcinput.setKeyboardMode(rcinput.kmNone) + self.Console.killAll() self.close() - def reload(self): - if os.path.exists(self.cache_file): - os.unlink(self.cache_file) - self.list_updating = True - self.rebuildList() - - def setStatus(self, status=None): - if status: - self.statuslist = [] - divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "div-h.png")) - if status == "update": - statuspng = LoadPixmap(cached=True, path=self.imagePath + "upgrade.png") - self.statuslist.append((_("Package list update"), "", _("Downloading a new packet list. Please wait..."), "", statuspng, divpng)) - self["list"].setList(self.statuslist) - elif status == "error": - statuspng = LoadPixmap(cached=True, path=self.imagePath + "remove.png") - self.statuslist.append((_("Error"), "", _("An error occurred while downloading the packetlist. Please try again."), "", statuspng, divpng)) - self["list"].setList(self.statuslist) + def setStatus(self, status): + if status == "updating": + self["list"].setList([(_("Running opkg update"), "", _("Downloading the latest package list. Please wait..."), "", self.upgradepng, self.divpng)]) + elif status == "loading": + self["list"].setList([(_("Package list loading"), "", _("Loading the package list. Please wait..."), "", self.upgradepng, self.divpng)]) + elif status == "error": + self["list"].setList([(_("Error"), "", _("An error occurred while downloading the packetlist. Please try again."), "", self.removepng, self.divpng)]) def rebuildList(self): - self.setStatus("update") - self.inv_cache = 0 - self.vc = valid_cache(self.cache_file, self.cache_ttl) - if self.cache_ttl > 0 and self.vc != 0: - try: - self.buildPacketList() - except: - self.inv_cache = 1 - if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0: - self.run = 0 - self.ipkg.startCmd(IpkgComponent.CMD_UPDATE) + if not self.list_updating: + self.list_updating = True + self.setStatus("updating") + self.ipkg.startCmd(IpkgComponent.CMD_UPDATE) # sync opkg with the feeds def go(self, returnValue=None): - cur = self["list"].getCurrent() - if cur: + if cur := self["list"].getCurrent(): status = cur[3] package = cur[0] - self.cmdList = [] + self.wasRemove = False if status == "installed": - self.cmdList.append((IpkgComponent.CMD_REMOVE, {"package": package})) - if len(self.cmdList): - self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n") + package + "\n" + self.oktext) + self.wasRemove = True + self.cmd = (IpkgComponent.CMD_REMOVE, {"package": package}) + self.session.openWithCallback(self.runCommand, MessageBox, _("Do you want to remove the package:\n") + package) elif status == "upgradeable": - self.cmdList.append((IpkgComponent.CMD_INSTALL, {"package": package})) - if len(self.cmdList): - self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to update the package:\n") + package + "\n" + self.oktext) + self.cmd = (IpkgComponent.CMD_INSTALL, {"package": package}) + self.session.openWithCallback(self.runCommand, MessageBox, _("Do you want to update the package:\n") + package) elif status == "installable": - self.cmdList.append((IpkgComponent.CMD_INSTALL, {"package": package})) - if len(self.cmdList): - self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n") + package + "\n" + self.oktext) + self.cmd = (IpkgComponent.CMD_INSTALL, {"package": package}) + self.session.openWithCallback(self.runCommand, MessageBox, _("Do you want to install the package:\n") + package) - def runRemove(self, result): - if result: - self.session.openWithCallback(self.runRemoveFinished, Ipkg, cmdList=self.cmdList) - - def runRemoveFinished(self): - self.session.openWithCallback(self.RemoveReboot, MessageBox, _("Removal has completed.") + "\n" + _("Do you want to reboot your receiver?"), MessageBox.TYPE_YESNO) - - def RemoveReboot(self, result): - if result is None: - return - if not result: - cur = self["list"].getCurrent() - if cur: - item = self["list"].getIndex() - self.list[item] = self.buildEntryComponent(cur[0], cur[1], cur[2], "installable") - self.cachelist[item] = [cur[0], cur[1], cur[2], "installable"] - self["list"].setList(self.list) - write_cache(self.cache_file, self.cachelist) - self.reloadPluginlist() + def runCommand(self, result): if result: - self.session.open(TryQuitMainloop, retvalue=3) + self.session.openWithCallback(self.runCommandFinished, Ipkg, cmdList=[self.cmd]) - def runUpgrade(self, result): + def runCommandFinished(self): + msg = _("Removal has completed.") if self.wasRemove else _("Update has completed.") + self.session.openWithCallback(self.Reboot, MessageBox, msg + "\n" + _("Do you want to reboot your receiver?"), MessageBox.TYPE_YESNO) + + def Reboot(self, result): if result: - self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList=self.cmdList) - - def runUpgradeFinished(self): - self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Update has completed.") + "\n" + _("Do you want to reboot your receiver?"), MessageBox.TYPE_YESNO) - - def UpgradeReboot(self, result): - if result is None: - return - if not result: - cur = self["list"].getCurrent() - if cur: - item = self["list"].getIndex() - self.list[item] = self.buildEntryComponent(cur[0], cur[1], cur[2], "installed") - self.cachelist[item] = [cur[0], cur[1], cur[2], "installed"] + self.session.open(TryQuitMainloop, retvalue=3) + elif result is False: # result is None would mean the MessageBox was exited + if cur := self["list"].getCurrent(): + self.list[self["list"].getIndex()] = self.buildEntryComponent(cur[0], cur[1], cur[2], "installable" if self.wasRemove else "installed") self["list"].setList(self.list) - write_cache(self.cache_file, self.cachelist) self.reloadPluginlist() - if result: - self.session.open(TryQuitMainloop, retvalue=3) def ipkgCallback(self, event, param): if event == IpkgComponent.EVENT_ERROR: @@ -287,11 +159,12 @@ def ipkgCallback(self, event, param): elif event == IpkgComponent.EVENT_DONE: if self.list_updating: self.list_updating = False - if not self.Console: - self.Console = Console() - cmd = self.ipkg.ipkg + " list" - self.Console.ePopen(cmd, self.OpkgList_Finished) - pass + self.buildList() + + def buildList(self): + self.setStatus("loading") + cmd = self.ipkg.ipkg + " list" + self.Console.ePopen(cmd, self.OpkgList_Finished) def OpkgList_Finished(self, result, retval, extra_args=None): if result: @@ -315,80 +188,50 @@ def OpkgList_Finished(self, result, retval, extra_args=None): last_packet = self.packetlist[-1] last_packet[2] = last_packet[2] + x self.packetlist[:-1] + last_packet - - if not self.Console: - self.Console = Console() cmd = self.ipkg.ipkg + " list_installed" self.Console.ePopen(cmd, self.OpkgListInstalled_Finished) def OpkgListInstalled_Finished(self, result, retval, extra_args=None): if result: - self.installed_packetlist = {} - for x in result.splitlines(): - tokens = x.split(" - ") - name = tokens[0].strip() - if not any(name.endswith(x) for x in self.unwanted_extensions): - l = len(tokens) - version = l > 1 and tokens[1].strip() or "" - self.installed_packetlist[name] = version - if not self.Console: - self.Console = Console() - cmd = "opkg list-upgradable" + self.installed_packetlist = self.parseResult(result) + cmd = self.ipkg.ipkg + " list-upgradable" self.Console.ePopen(cmd, self.OpkgListUpgradeable_Finished) def OpkgListUpgradeable_Finished(self, result, retval, extra_args=None): if result: - self.upgradeable_packages = {} - for x in result.splitlines(): - tokens = x.split(" - ") - name = tokens[0].strip() - if not any(name.endswith(x) for x in self.unwanted_extensions): - l = len(tokens) - version = l > 2 and tokens[2].strip() or "" - self.upgradeable_packages[name] = version + self.upgradeable_packages = self.parseResult(result) self.buildPacketList() + def parseResult(self, result): + packages = {} + for x in result.splitlines(): + tokens = x.split(" - ") + name = tokens[0].strip() + if not any(name.endswith(x) for x in self.unwanted_extensions): + l = len(tokens) + version = l > 1 and tokens[-1].strip() or "" + packages[name] = version + return packages + def buildEntryComponent(self, name, version, description, state): - divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "div-h.png")) - if not description: - description = "No description available." - if state == "installed": - return ((name, version, _(description), state, self.installedpng, divpng)) - elif state == "upgradeable": - return ((name, version, _(description), state, self.upgradeablepng, divpng)) - else: - return ((name, version, _(description), state, self.installablepng, divpng)) + description = _(description) if description else _("No description available.") + png = state == "installed" and self.installedpng or state == "upgradeable" and self.upgradeablepng or self.installablepng + return ((name, version, description, state, png, self.divpng)) def buildPacketList(self): self.list = [] - self.cachelist = [] self.i = 0 - if self.cache_ttl > 0 and self.vc != 0: - print("Loading packagelist cache from ", self.cache_file) - try: - self.cachelist = load_cache(self.cache_file) - if len(self.cachelist) > 0: - for x in self.cachelist: - self.list.append(self.buildEntryComponent(x[0], x[1], x[2], x[3])) - self["list"].setList(self.list) - except: - self.inv_cache = 1 - - if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0: - print("rebuilding fresh package list") - for x in self.packetlist: - status = "" - if x[0] in self.installed_packetlist: - if x[0] in self.upgradeable_packages: - status = "upgradeable" - else: - status = "installed" + for x in self.packetlist: + status = "" + if x[0] in self.installed_packetlist: + if x[0] in self.upgradeable_packages: + status = "upgradeable" else: - status = "installable" - self.list.append(self.buildEntryComponent(x[0], x[1], x[2], status)) - self.cachelist.append([x[0], x[1], x[2], status]) - write_cache(self.cache_file, self.cachelist) - self["list"].setList(self.list) + status = "installed" + else: + status = "installable" + self.list.append(self.buildEntryComponent(x[0], x[1], x[2], status)) + self["list"].setList(self.list) self.updateTexts() def filterPrev(self): @@ -401,8 +244,7 @@ def filterNext(self): def filterList(self): if self.list: - filter = self.getCurrentFilter() - if filter == "All": + if (filter := self.getCurrentFilter()) == "All": self["list"].setList(self.list) elif filter == "Installed": self["list"].setList([x for x in self.list if x[4] is self.installedpng]) @@ -419,15 +261,8 @@ def updateTexts(self): if self.list: self["filterActions"].setEnabled(True) self.title = _("Package manager") + " - " + self.filters[self.getCurrentFilter()] - self["key_green"].text = _("Refresh list") self["key_previous"].text = _("PREVIOUS") - self["key_next"].text = _("NEXT") - else: - self["filterActions"].setEnabled(False) - self.title = _("Package manager") - self["key_green"].text = "" - self["key_previous"].text = "" - self["key_next"].text = "" + self["key_next"].text = _("NEXT") def reloadPluginlist(self): plugins.readPluginList(resolveFilename(SCOPE_PLUGINS)) From 1d020873b7b3c0e99bfcf5da6ad1f516ed6f0c49 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Sat, 27 Jan 2024 00:16:28 +0000 Subject: [PATCH 074/183] PEP8 double aggressive E22, E224, E241, E242 and E27 --- lib/python/Plugins/SystemPlugins/ViX/PackageManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py index bad28a14240..a17177b516e 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py +++ b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py @@ -262,7 +262,7 @@ def updateTexts(self): self["filterActions"].setEnabled(True) self.title = _("Package manager") + " - " + self.filters[self.getCurrentFilter()] self["key_previous"].text = _("PREVIOUS") - self["key_next"].text = _("NEXT") + self["key_next"].text = _("NEXT") def reloadPluginlist(self): plugins.readPluginList(resolveFilename(SCOPE_PLUGINS)) From 48603f6f82f65c55bf3f67a1ccd1174e77db50bc Mon Sep 17 00:00:00 2001 From: Orlandoxx <95180049+Orlandoxx@users.noreply.github.com> Date: Sat, 27 Jan 2024 08:15:28 +0200 Subject: [PATCH 075/183] Updated Finnish (fi.po) translation [PackageManager] simplify changes. --- po/fi.po | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/po/fi.po b/po/fi.po index 9eb2d1aa610..fa8e84ea7a9 100644 --- a/po/fi.po +++ b/po/fi.po @@ -5,7 +5,7 @@ msgstr "" "Project-Id-Version: enigma2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-12-27 23:35+0000\n" -"PO-Revision-Date: 2024-01-25 18:50+0200\n" +"PO-Revision-Date: 2024-01-27 08:14+0200\n" "Last-Translator: Orlandox\n" "Language-Team: timoj/Kojo/Samzam/Orlandox\n" "Language: fi\n" @@ -13543,7 +13543,7 @@ msgstr "" "Suomenkielinen käännös: timoj, Kojo, Samzam, Orlandox\n" "\n" "Ylläpito : Orlandox\n" -"--- 25.01.2024 ---\n" +"--- 27.01.2024 ---\n" "http://www.huoltovalikko.com" msgid "TS file is too large for ISO9660 level 1!" @@ -19344,3 +19344,18 @@ msgstr "Päivitettävissä" msgid "Installable" msgstr "Asennettavissa" + +msgid "opkg update" +msgstr "Pakettilistojen (opkg) päivitys" + +msgid "Running opkg update" +msgstr "Opkg päivitys käynnissä" + +msgid "Downloading the latest package list. Please wait..." +msgstr "Päivitetään uusinta pakettilistaa. Odota..." + +msgid "Package list loading" +msgstr "Pakettilistan lataus" + +msgid "Loading the package list. Please wait..." +msgstr "Ladataan pakettilistaa. Odota..." From df276581fdaabbc85ef150bcd975d4bf115831b1 Mon Sep 17 00:00:00 2001 From: Gordon Lack Date: Sat, 27 Jan 2024 11:06:42 +0000 Subject: [PATCH 076/183] Cast to (long long) is to cater for older 32-bit time fields --- lib/base/eerror.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/base/eerror.cpp b/lib/base/eerror.cpp index e14a6d134ef..192357a549e 100644 --- a/lib/base/eerror.cpp +++ b/lib/base/eerror.cpp @@ -144,7 +144,8 @@ int formatTime(char *buf, int bufferSize, int flags) if (!(flags & _DBGFLG_NOTIME)) { if (debugTime & 1) { clock_gettime(CLOCK_MONOTONIC, &tp); - pos += snprintf(buf, bufferSize, "<%6lu.%04lu> ", tp.tv_sec, tp.tv_nsec/100000); +/* Cast to (long long) is to cater for older 32-bit time fields */ + pos += snprintf(buf, bufferSize, "<%6lld.%04lld> ", (long long)tp.tv_sec, (long long)tp.tv_nsec/100000); } if (debugTime & 2) { @@ -152,8 +153,9 @@ int formatTime(char *buf, int bufferSize, int flags) struct timeval tim; gettimeofday(&tim, NULL); localtime_r(&tim.tv_sec, &loctime); - pos += snprintf(buf + pos, bufferSize - pos, "%02d:%02d:%02d.%04lu ", - loctime.tm_hour, loctime.tm_min, loctime.tm_sec, tim.tv_usec / 100L); +/* Cast to (long long) is to cater for older 32-bit time fields */ + pos += snprintf(buf + pos, bufferSize - pos, "%02d:%02d:%02d.%04lld ", + loctime.tm_hour, loctime.tm_min, loctime.tm_sec, (long long)tim.tv_usec / 100L); } } From 89fd7b91c581d4bdc0a355cb40f48b8beb5a1522 Mon Sep 17 00:00:00 2001 From: Huevos Date: Sat, 27 Jan 2024 19:47:03 +0100 Subject: [PATCH 077/183] [PackageManager] simplify list filtering --- .../Plugins/SystemPlugins/ViX/PackageManager.py | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py index a17177b516e..c65e6593a3b 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py +++ b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py @@ -87,7 +87,7 @@ def __init__(self, session): self.upgradeable_packages = {} self.Console = Console() self.unwanted_extensions = ("-dbg", "-dev", "-doc", "-staticdev", "-src", "busybox") - self.filters = {"All": _("All"), "Installed": _("Installed"), "Upgradeable": _("Upgradeable"), "Installable": _("Installable")} + self.filters = {"all": _("All"), "installed": _("Installed"), "upgradeable": _("Upgradeable"), "installable": _("Installable")} self.installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "icons/installed.png")) self.upgradeablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "icons/upgradeable.png")) @@ -244,14 +244,7 @@ def filterNext(self): def filterList(self): if self.list: - if (filter := self.getCurrentFilter()) == "All": - self["list"].setList(self.list) - elif filter == "Installed": - self["list"].setList([x for x in self.list if x[4] is self.installedpng]) - elif filter == "Upgradeable": - self["list"].setList([x for x in self.list if x[4] is self.upgradeablepng]) - elif filter == "Installable": - self["list"].setList([x for x in self.list if x[4] is self.installablepng]) + self["list"].setList(self.list if (filter := self.getCurrentFilter()) == "all" else [x for x in self.list if x[3] == filter]) self.updateTexts() def getCurrentFilter(self): From 0219d003e4c17014b99747e26d64d9b3b58ebeec Mon Sep 17 00:00:00 2001 From: Huevos Date: Sat, 27 Jan 2024 19:49:48 +0100 Subject: [PATCH 078/183] [PackageManager] remain in current list after updating a package --- lib/python/Plugins/SystemPlugins/ViX/PackageManager.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py index c65e6593a3b..a276b7adfb4 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py +++ b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py @@ -146,11 +146,10 @@ def runCommandFinished(self): def Reboot(self, result): if result: self.session.open(TryQuitMainloop, retvalue=3) - elif result is False: # result is None would mean the MessageBox was exited - if cur := self["list"].getCurrent(): - self.list[self["list"].getIndex()] = self.buildEntryComponent(cur[0], cur[1], cur[2], "installable" if self.wasRemove else "installed") - self["list"].setList(self.list) - self.reloadPluginlist() + elif cur := self["list"].getCurrent(): + self.list[self.list.index(cur)] = self.buildEntryComponent(cur[0], cur[1], cur[2], "installable" if self.wasRemove else "installed") + self.filterList() + self.reloadPluginlist() def ipkgCallback(self, event, param): if event == IpkgComponent.EVENT_ERROR: From 45fd36ab622f7967fb050446dff7ad52bb1725c1 Mon Sep 17 00:00:00 2001 From: Huevos Date: Sat, 27 Jan 2024 22:56:35 +0100 Subject: [PATCH 079/183] [socket] update timestamp --- lib/network/socket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/network/socket.cpp b/lib/network/socket.cpp index bd94428cfba..94b4af236fe 100644 --- a/lib/network/socket.cpp +++ b/lib/network/socket.cpp @@ -213,7 +213,7 @@ int eSocket::writeBlock(const char *data, unsigned int len) // and eDebug self can cause a call of writeBlock !! struct timespec tp = {}; clock_gettime(CLOCK_MONOTONIC, &tp); - fprintf(stderr, "<%6lu.%06lu> [eSocket] write: %m\n", tp.tv_sec, tp.tv_nsec/1000); + fprintf(stderr, "<%6lld.%06lld> [eSocket] write: %m\n", (long long)tp.tv_sec, (long long)tp.tv_nsec/1000); } if (tw < 0) tw = 0; From a7ff313fd340cbb635f0c4bafc78951492a91ae9 Mon Sep 17 00:00:00 2001 From: Huevos Date: Sat, 27 Jan 2024 23:16:14 +0100 Subject: [PATCH 080/183] [eerror] update timestamp --- lib/base/eerror.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/base/eerror.cpp b/lib/base/eerror.cpp index 192357a549e..f87990011da 100644 --- a/lib/base/eerror.cpp +++ b/lib/base/eerror.cpp @@ -145,7 +145,7 @@ int formatTime(char *buf, int bufferSize, int flags) if (debugTime & 1) { clock_gettime(CLOCK_MONOTONIC, &tp); /* Cast to (long long) is to cater for older 32-bit time fields */ - pos += snprintf(buf, bufferSize, "<%6lld.%04lld> ", (long long)tp.tv_sec, (long long)tp.tv_nsec/100000); + pos += snprintf(buf, bufferSize, "<%6lld.%06lld> ", (long long)tp.tv_sec, (long long)tp.tv_nsec/1000); } if (debugTime & 2) { From e61216500e8d366aa8b41bfd86530c4df02fcd46 Mon Sep 17 00:00:00 2001 From: Huevos Date: Sun, 28 Jan 2024 03:04:35 +0100 Subject: [PATCH 081/183] [OnlineUpdateCheck] fix software update icons in non release images --- lib/python/Components/OnlineUpdateCheck.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/Components/OnlineUpdateCheck.py b/lib/python/Components/OnlineUpdateCheck.py index 1fb5592bef4..0552fa29cc9 100644 --- a/lib/python/Components/OnlineUpdateCheck.py +++ b/lib/python/Components/OnlineUpdateCheck.py @@ -249,7 +249,7 @@ def createCheckJob(self): def JobStart(self): config.softwareupdate.updatefound.setValue(False) - if (SystemInfo["imagetype"] != "release" and feedsstatuscheck.getFeedsBool() == "unknown") or (SystemInfo["imagetype"] == "release" and feedsstatuscheck.getFeedsBool() in ("stable", "unstable")): + if (SystemInfo["imagetype"] != "release" and feedsstatuscheck.getFeedsBool() in ("alien", "developer")) or (SystemInfo["imagetype"] == "release" and feedsstatuscheck.getFeedsBool() in ("stable", "unstable")): print("[OnlineUpdateCheckPoller] Starting background check.") feedsstatuscheck.startCheck() else: From 57099df250fa219c5dc0a9e6731224d36e7b9077 Mon Sep 17 00:00:00 2001 From: Huevos Date: Sun, 28 Jan 2024 03:56:33 +0100 Subject: [PATCH 082/183] [OnlineUpdateCheck] simplify previous commit --- lib/python/Components/OnlineUpdateCheck.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/python/Components/OnlineUpdateCheck.py b/lib/python/Components/OnlineUpdateCheck.py index 0552fa29cc9..48c5768dbe5 100644 --- a/lib/python/Components/OnlineUpdateCheck.py +++ b/lib/python/Components/OnlineUpdateCheck.py @@ -98,10 +98,10 @@ def getFeedStatus(self): except: print("[OnlineUpdateCheck][getFeedStatus] ERROR:", sys.exc_info()[0]) trafficLight = -2 - if SystemInfo["imagetype"] == "developer" and "openvixdev" in SystemInfo["feedsurl"]: + elif SystemInfo["imagetype"] == "developer" and "openvixdev" in SystemInfo["feedsurl"]: print("[OnlineUpdateCheck][getFeedStatus] Official developer feeds") trafficLight = "developer" - elif officialReleaseFeedsUri not in SystemInfo["feedsurl"]: # if not using official feeds mark as alien. There is no status test for alien feeds (including official developer feeds). + else: # if not using official feeds mark as alien. There is no status test for alien feeds (including official developer feeds). print("[OnlineUpdateCheck][getFeedStatus] Alien feeds url: %s" % SystemInfo["feedsurl"]) status = 0 trafficLight = "alien" @@ -249,7 +249,7 @@ def createCheckJob(self): def JobStart(self): config.softwareupdate.updatefound.setValue(False) - if (SystemInfo["imagetype"] != "release" and feedsstatuscheck.getFeedsBool() in ("alien", "developer")) or (SystemInfo["imagetype"] == "release" and feedsstatuscheck.getFeedsBool() in ("stable", "unstable")): + if feedsstatuscheck.getFeedsBool() in ("alien", "developer", "stable", "unstable"): print("[OnlineUpdateCheckPoller] Starting background check.") feedsstatuscheck.startCheck() else: From 4db181b00b0c47134c45a8b54c082197252eeaf8 Mon Sep 17 00:00:00 2001 From: Huevos Date: Sun, 28 Jan 2024 23:28:37 +0100 Subject: [PATCH 083/183] [Pager] fix onSelectionChanged --- lib/python/Components/Addons/Pager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/Components/Addons/Pager.py b/lib/python/Components/Addons/Pager.py index ba575edba11..b11ba82728c 100644 --- a/lib/python/Components/Addons/Pager.py +++ b/lib/python/Components/Addons/Pager.py @@ -35,7 +35,7 @@ def onContainerShown(self): if hasattr(self.source, "instance") and hasattr(self.source.instance, "setScrollbarMode"): self.source.instance.setScrollbarMode(eListbox.showNever) - onSelectionChanged = x if (x := getattr(self.source, "onSelectionChanged", None)) else getattr(self.source, "onSelChanged", None) + onSelectionChanged = x if (x := getattr(self.source, "onSelectionChanged", None)) is not None else getattr(self.source, "onSelChanged", None) if isinstance(onSelectionChanged, list) and self.initPager not in onSelectionChanged: onSelectionChanged.append(self.initPager) From 46155336a34a87747632c63bb1495f7818e1281e Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Mon, 29 Jan 2024 10:24:55 +0200 Subject: [PATCH 084/183] [Added] [Pager] Possibility pager to be hidden and shown in sync with connected widget --- lib/python/Components/Addons/Pager.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/python/Components/Addons/Pager.py b/lib/python/Components/Addons/Pager.py index b11ba82728c..d57372f5f9a 100644 --- a/lib/python/Components/Addons/Pager.py +++ b/lib/python/Components/Addons/Pager.py @@ -35,6 +35,9 @@ def onContainerShown(self): if hasattr(self.source, "instance") and hasattr(self.source.instance, "setScrollbarMode"): self.source.instance.setScrollbarMode(eListbox.showNever) + if self.source: + self.source.onVisibilityChange.append(self.onSourceVisibleChanged) + onSelectionChanged = x if (x := getattr(self.source, "onSelectionChanged", None)) is not None else getattr(self.source, "onSelChanged", None) if isinstance(onSelectionChanged, list) and self.initPager not in onSelectionChanged: @@ -44,6 +47,12 @@ def onContainerShown(self): GUI_WIDGET = eListbox + def onSourceVisibleChanged(self, visible): + if visible: + self.show() + else: + self.hide() + def buildEntry(self, currentPage, pageCount): width = self.l.getItemSize().width() height = self.l.getItemSize().height() From dcc46a0d507e68fc051ff55a125bd5cbb49f67d5 Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Mon, 29 Jan 2024 10:39:21 +0200 Subject: [PATCH 085/183] [Fixed] Exception when event is not defined --- lib/python/Components/Addons/Pager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/Components/Addons/Pager.py b/lib/python/Components/Addons/Pager.py index d57372f5f9a..4544db09bae 100644 --- a/lib/python/Components/Addons/Pager.py +++ b/lib/python/Components/Addons/Pager.py @@ -35,7 +35,7 @@ def onContainerShown(self): if hasattr(self.source, "instance") and hasattr(self.source.instance, "setScrollbarMode"): self.source.instance.setScrollbarMode(eListbox.showNever) - if self.source: + if self.source and hasattr(self.source, "onVisibilityChange"): self.source.onVisibilityChange.append(self.onSourceVisibleChanged) onSelectionChanged = x if (x := getattr(self.source, "onSelectionChanged", None)) is not None else getattr(self.source, "onSelChanged", None) From 8c90fec14e3e246f4bb96bac544f0b133e4ba11c Mon Sep 17 00:00:00 2001 From: Tony Whalley Date: Sat, 27 Jan 2024 14:18:36 +0100 Subject: [PATCH 086/183] resolve python 3.12 syntax issues --- lib/python/Components/Network.py | 2 +- lib/python/Components/PackageInfo.py | 2 +- lib/python/Components/Renderer/NextEpgInfo.py | 2 +- lib/python/Screens/About.py | 2 +- lib/python/Screens/ChannelSelection.py | 2 +- lib/python/Tools/Hex2strColor.py | 2 +- tools/genmetaindex.py | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/python/Components/Network.py b/lib/python/Components/Network.py index 70eecc555d2..e128c821135 100644 --- a/lib/python/Components/Network.py +++ b/lib/python/Components/Network.py @@ -183,7 +183,7 @@ def loadNetworkConfig(self, iface, callback=None): callback(True) def loadNameserverConfig(self): - ipRegexp = "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" # noqa: W605 + ipRegexp = r"[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" # noqa: W605 nameserverPattern = re.compile("nameserver +" + ipRegexp) ipPattern = re.compile(ipRegexp) diff --git a/lib/python/Components/PackageInfo.py b/lib/python/Components/PackageInfo.py index 9632984a75d..4e4a180c666 100644 --- a/lib/python/Components/PackageInfo.py +++ b/lib/python/Components/PackageInfo.py @@ -190,7 +190,7 @@ def fillPackagesList(self, prerequisites=True): self.directory = [self.directory] for directory in self.directory: - packages += crawlDirectory(directory, ".*\.info$") # noqa: W605 + packages += crawlDirectory(directory, r".*\.info$") # noqa: W605 for package in packages: self.readInfo(package[0] + "/", package[0] + "/" + package[1]) diff --git a/lib/python/Components/Renderer/NextEpgInfo.py b/lib/python/Components/Renderer/NextEpgInfo.py index a05bff4ad40..d6bf9093336 100644 --- a/lib/python/Components/Renderer/NextEpgInfo.py +++ b/lib/python/Components/Renderer/NextEpgInfo.py @@ -16,7 +16,7 @@ def __init__(self): self.hideLabel = 0 self.timecolor = "" self.labelcolor = "" - self.foregroundColor = "\c00f0f0f0" # noqa: W605 + self.foregroundColor = r"\c00f0f0f0" # noqa: W605 self.numOfSpaces = 1 GUI_WIDGET = eLabel diff --git a/lib/python/Screens/About.py b/lib/python/Screens/About.py index 9ea58ece9b7..fc784da1d25 100644 --- a/lib/python/Screens/About.py +++ b/lib/python/Screens/About.py @@ -94,7 +94,7 @@ def populate(self): tempinfo = "" elif path.exists("/proc/hisi/msp/pm_cpu"): try: - tempinfo = search("temperature = (\d+) degree", open("/proc/hisi/msp/pm_cpu").read()).group(1) # noqa: W605 + tempinfo = search(r"temperature = (\d+) degree", open("/proc/hisi/msp/pm_cpu").read()).group(1) # noqa: W605 except: tempinfo = "" if tempinfo and int(tempinfo) > 0: diff --git a/lib/python/Screens/ChannelSelection.py b/lib/python/Screens/ChannelSelection.py index c86f4c4bd45..70d549cc621 100644 --- a/lib/python/Screens/ChannelSelection.py +++ b/lib/python/Screens/ChannelSelection.py @@ -1337,7 +1337,7 @@ def exitContext(self, close=False): class ChannelSelectionBase(Screen, HelpableScreen): - orbposReStr = "\(satellitePosition *== *(\d+)" # noqa: W605 + orbposReStr = r"\(satellitePosition *== *(\d+)" # noqa: W605 orbposRe = None # Lazy compilation def __init__(self, session): diff --git a/lib/python/Tools/Hex2strColor.py b/lib/python/Tools/Hex2strColor.py index 4bb4e98f790..7d7d7b68de0 100644 --- a/lib/python/Tools/Hex2strColor.py +++ b/lib/python/Tools/Hex2strColor.py @@ -3,4 +3,4 @@ def Hex2strColor(rgb): - return "\c%08x" % rgb # noqa: W605 + return r"\c%08x" % rgb # noqa: W605 diff --git a/tools/genmetaindex.py b/tools/genmetaindex.py index 9422db6663b..b1cde7cfdaa 100644 --- a/tools/genmetaindex.py +++ b/tools/genmetaindex.py @@ -21,7 +21,7 @@ for i in p.findall("info"): if not info: info = i - assert info + assert info is not None for i in info[:]: if i.tag not in ["name", "packagename", "packagetype", "shortdescription"]: From c75a5636a84f749110498af94c33dc0167b240e5 Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Tue, 30 Jan 2024 17:37:59 +0100 Subject: [PATCH 087/183] [OE-A 5.4] update E2(6.5) config, GitCommitInfo, workflow, readme --- .github/workflows/enigma2.yml | 6 +++--- README.md | 4 ++-- configure.ac | 2 +- lib/python/Screens/GitCommitInfo.py | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/enigma2.yml b/.github/workflows/enigma2.yml index d57b2e9489f..df45e30f3ef 100644 --- a/.github/workflows/enigma2.yml +++ b/.github/workflows/enigma2.yml @@ -17,8 +17,8 @@ jobs: runs-on: ubuntu-22.04 strategy: matrix: - gcc: [11] - python: ['3.11'] + gcc: [13] + python: ['3.12'] steps: - name: install dev packages run: | @@ -31,7 +31,7 @@ jobs: sudo apt-get install build-essential sudo apt-get install automake sudo apt-get install libtool - sudo apt-get install python${{ matrix.python }}-dev + sudo apt-get install python3-dev sudo apt-get install zlib1g-dev sudo apt-get install gettext sudo apt-get install swig diff --git a/README.md b/README.md index 669570b590b..76fa9c27bff 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ ## OpenViX python3 is built using oe-alliance build-environment and several git repositories: ## -> [https://github.com/oe-alliance/oe-alliance-core/tree/5.3](https://github.com/oe-alliance/oe-alliance-core/tree/5.3 "OE-Alliance") +> [https://github.com/oe-alliance/oe-alliance-core/tree/5.3](https://github.com/oe-alliance/oe-alliance-core/tree/5.4 "OE-Alliance") > > [https://github.com/OpenViX/enigma2/tree/Release](https://github.com/OpenViX/enigma2/tree/Release "openViX E2") @@ -76,7 +76,7 @@ ---------- 10 - Clone oe-alliance git - git clone https://github.com/oe-alliance/build-enviroment.git -b 5.3 + git clone https://github.com/oe-alliance/build-enviroment.git -b 5.4 ---------- 11 - Switch to folder build-enviroment diff --git a/configure.ac b/configure.ac index 0df4240158a..477cb5ca80e 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([enigma2],[6.4],[http://www.world-of-satellite.com]) +AC_INIT([enigma2],[6.5],[http://www.world-of-satellite.com]) AM_INIT_AUTOMAKE([dist-bzip2 no-define tar-pax -Wno-portability]) AC_CONFIG_HEADERS([enigma2_config.h]) diff --git a/lib/python/Screens/GitCommitInfo.py b/lib/python/Screens/GitCommitInfo.py index 7a89f93410c..c9da7072200 100644 --- a/lib/python/Screens/GitCommitInfo.py +++ b/lib/python/Screens/GitCommitInfo.py @@ -26,7 +26,7 @@ project = 0 projects = [ - ("https://api.github.com/repos/oe-alliance/oe-alliance-core/commits?sha=5.3", "OE-A Core"), + ("https://api.github.com/repos/oe-alliance/oe-alliance-core/commits?sha=5.4", "OE-A Core"), ("https://api.github.com/repos/OpenViX/enigma2/commits?sha=%s" % getattr(E2Branches, SystemInfo["imagetype"], "Release"), "Enigma2"), ("https://api.github.com/repos/OpenViX/skins/commits", "ViX Skins"), ("https://api.github.com/repos/oe-alliance/oe-alliance-plugins/commits", "OE-A Plugins"), From fabd6eac6539af0c4ec64fc89c13d1908689eeb7 Mon Sep 17 00:00:00 2001 From: AbuBaniaz Date: Wed, 31 Jan 2024 18:52:34 +0000 Subject: [PATCH 088/183] [README.md] Tweak previous commit about branch --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 76fa9c27bff..91e8f7552bd 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ ## OpenViX python3 is built using oe-alliance build-environment and several git repositories: ## -> [https://github.com/oe-alliance/oe-alliance-core/tree/5.3](https://github.com/oe-alliance/oe-alliance-core/tree/5.4 "OE-Alliance") +> [https://github.com/oe-alliance/oe-alliance-core/tree/5.4](https://github.com/oe-alliance/oe-alliance-core/tree/5.4 "OE-Alliance") > > [https://github.com/OpenViX/enigma2/tree/Release](https://github.com/OpenViX/enigma2/tree/Release "openViX E2") From cdd61a61b8eba6f00b26b0586d93434315b352ef Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Thu, 1 Feb 2024 08:54:14 +0100 Subject: [PATCH 089/183] [IPKinstaller] - fix plugin source by adding path+plugin name --- .../Plugins/SystemPlugins/ViX/IPKInstaller.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/python/Plugins/SystemPlugins/ViX/IPKInstaller.py b/lib/python/Plugins/SystemPlugins/ViX/IPKInstaller.py index e9d8fd72994..5aa10f0e3d0 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/IPKInstaller.py +++ b/lib/python/Plugins/SystemPlugins/ViX/IPKInstaller.py @@ -116,17 +116,21 @@ def populate_List(self): del self.list[:] f = listdir(self.defaultDir) + self.loadDir = self.defaultDir.replace(" ", "%20") for line in f: if line.find(".ipk") != -1: - self.list.append(line) - + self.list.append(path.join(self.loadDir, line)) + # print(f"[IPKinstaller]1 f:{f} self.list:{self.list}") if path.ismount("/media/usb"): f = listdir("/media/usb") + self.loadDir = "/media/usb" for line in f: if line.find(".ipk") != -1: - self.list.append(line) + # print(f"[IPKinstaller]2 f:{f} line:{line}") + self.list.append(path.join(self.loadDir, line)) self.list.sort() + # print(f"[IPKinstaller]3 f:{f} self.list:{self.list}") self["list"].l.setList(self.list) def keyInstall(self): @@ -138,8 +142,8 @@ def Install(self, answer): if answer is True: sel = self["list"].getCurrent() if sel: - self.defaultDir = self.defaultDir.replace(" ", "%20") - cmd1 = "/usr/bin/opkg install " + path.join(self.defaultDir, sel) + cmd1 = f"/usr/bin/opkg install {sel}" + print(f"[IPKinstaller]4 sel:{sel}, cmd1:{cmd1}") self.session.openWithCallback(self.installFinished(sel), Console, title=_("Installing..."), cmdlist=[cmd1], closeOnSuccess=True) def installFinished(self, sel): From 9a21aafbffe9778e137686d7260c75e0fd012298 Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Thu, 1 Feb 2024 08:55:14 +0100 Subject: [PATCH 090/183] [HdmiCec] - fix invalid Cec address - tidy up comments --- lib/python/Components/HdmiCec.py | 58 ++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/lib/python/Components/HdmiCec.py b/lib/python/Components/HdmiCec.py index 356e24af081..a7742524759 100644 --- a/lib/python/Components/HdmiCec.py +++ b/lib/python/Components/HdmiCec.py @@ -78,7 +78,7 @@ 0xA1: "", 0xA2: "", 0xFF: "", - } + } # noqa E123 CtrlByte0 = { # Information only: control byte 0 status/action request by command (see cmdList) 0x00: {0x00: "", @@ -321,7 +321,7 @@ 0x04: "<1.3a>", 0x05: "<1.4>", 0x06: "<2.0>"}, - } + } # noqa E123 def getPhysicalAddress(): @@ -353,9 +353,15 @@ def __init__(self): self.delay.timeout.get().append(self.sendStandbyMessages) self.useStandby = True self.handlingStandbyFromTV = False - if config.hdmicec.enabled.value and config.hdmicec.fixed_physical_address.value[1:3] != ".0": - print("[HdmiCEC][init]phsyical address changed by setup value:", config.hdmicec.fixed_physical_address.value) - setFixedPhysicalAddress(config.hdmicec.fixed_physical_address.value) + if config.hdmicec.enabled.value: + countDots = config.hdmicec.fixed_physical_address.value.count(".") + print(f"[HdmiCEC][init]2countDots:{countDots}") + if countDots == 3 and config.hdmicec.fixed_physical_address.value[1:3] != ".0": + try: + print(f"[HdmiCEC][init]phsyical address changed by setup value:{config.hdmicec.fixed_physical_address.value}") + setFixedPhysicalAddress(config.hdmicec.fixed_physical_address.value) + except: + setFixedPhysicalAddress("0.0.0.0") else: print("[HdmiCEC][init] no set physical address ") setFixedPhysicalAddress("0.0.0.0") # no fixed physical address send 0 to eHdmiCec C++ driver @@ -385,34 +391,34 @@ def messageReceived(self, message): ctrl0 = message.getControl0() ctrl1 = message.getControl1() ctrl2 = message.getControl2() - msgaddress = message.getAddress() # 0 = TV, 5 = receiver 15 = broadcast - print("[HdmiCEC][messageReceived0]: msgaddress=%s CECcmd=%s, cmd=%X, ctrl0=%s, length=%s" % (msgaddress, CECcmd, cmd, ctrl0, length)) + msgaddress = message.getAddress() # 0 = TV, 5 = receiver 15 = broadcast + print(f"[HdmiCEC][messageReceived0]: msgaddress={msgaddress} CECcmd={CECcmd}, cmd=%X, ctrl0={cmd}, length={ctrl0}") if config.hdmicec.debug.value != "0": self.debugRx(length, cmd, ctrl0) if msgaddress > 15: # workaround for wrong address from driver (e.g. hd51, message comes from tv -> address is only sometimes 0, dm920, same tv -> address is always 0) print("[HdmiCEC][messageReceived1a]: msgaddress > 15 reset to 0") msgaddress = 0 if cmd == 0x00: - if length == 0: # only polling message ( it's same as ping ) + if length == 0: # only polling message ( it's same as ping ) print("[HdmiCEC][messageReceived1b]: received polling message") else: - if ctrl0 == 68: # feature abort - print("[HdmiCEC][messageReceived2]: volume forwarding not supported by device %02x" % (msgaddress)) + if ctrl0 == 68: # feature abort + print(f"[HdmiCEC][messageReceived2]: volume forwarding not supported by device {msgaddress:02x}") self.volumeForwardingEnabled = False - elif cmd == 0x46: # request name + elif cmd == 0x46: # request name self.sendMessage(msgaddress, "osdname") - elif cmd == 0x72 or cmd == 0x7e: # system audio mode status 114 or 126 + elif cmd == 0x72 or cmd == 0x7e: # system audio mode status 114 or 126 if ctrl0 == 1: - self.volumeForwardingDestination = 5 # on: send volume keys to receiver + self.volumeForwardingDestination = 5 # on: send volume keys to receiver else: - self.volumeForwardingDestination = 0 # off: send volume keys to tv - print("[HdmiCEC][messageReceived4]: volume forwarding=%s, msgaddress=%s" % (self.volumeForwardingDestination, msgaddress)) + self.volumeForwardingDestination = 0 # off: send volume keys to tv + print(f"[HdmiCEC][messageReceived4]: volume forwarding={self.volumeForwardingDestination}, msgaddress={msgaddress}") if config.hdmicec.volume_forwarding.value: - print("[HdmiCEC][messageReceived5]: volume forwarding to device %02x enabled" % self.volumeForwardingDestination) + print(f"[HdmiCEC][messageReceived5]: volume forwarding to device {self.volumeForwardingDestination:02x}enabled") self.volumeForwardingEnabled = True - elif cmd == 0x83: # request address + elif cmd == 0x83: # request address self.sendMessage(msgaddress, "reportaddress") - elif cmd == 0x85: # request active source + elif cmd == 0x85: # request active source if not Screens.Standby.inStandby: if config.hdmicec.report_active_source.value: self.sendMessage(msgaddress, "sourceactive") @@ -424,30 +430,30 @@ def messageReceived(self, message): if not Screens.Standby.inStandby: if config.hdmicec.report_active_source.value: self.sendMessage(msgaddress, "sourceactive") - elif cmd == 0x8c: # request vendor id + elif cmd == 0x8c: # request vendor id self.sendMessage(msgaddress, "vendorid") - elif cmd == 0x8d: # menu request - if ctrl0 == 1: # query + elif cmd == 0x8d: # menu request + if ctrl0 == 1: # query if Screens.Standby.inStandby: self.sendMessage(msgaddress, "menuinactive") else: self.sendMessage(msgaddress, "menuactive") - elif cmd == 0x8f: # request power status + elif cmd == 0x8f: # request power status if Screens.Standby.inStandby: self.sendMessage(msgaddress, "powerinactive") else: self.sendMessage(msgaddress, "poweractive") - elif cmd == 0x90: # receive powerstatus report + elif cmd == 0x90: # receive powerstatus report if ctrl0 == 0: # some box is powered if config.hdmicec.next_boxes_detect.value: self.useStandby = False print("[HDMI-CEC][messageReceived7] powered box found") - elif cmd == 0x9F: # request get CEC version + elif cmd == 0x9F: # request get CEC version self.sendMessage(msgaddress, "sendcecversion") if cmd == 0x36 and config.hdmicec.handle_tv_standby.value: # handle standby request from the tv self.handlingStandbyFromTV = True # avoid echoing the "System Standby" command back to the tv - self.standby() # handle standby + self.standby() # handle standby self.handlingStandbyFromTV = False # after handling the standby command, we are free to send "standby" ourselves again if Screens.Standby.inStandby and config.hdmicec.handle_tv_wakeup.value: # handle wakeup requests from the tv @@ -569,7 +575,7 @@ def secondBoxActive(self): self.sendMessage(0, "getpowerstatus") def configVolumeForwarding(self, configElement): - print("[HdmiCEC][configVolumeForwarding]: hdmicec.enabled=%s, hdmicec.volume_forwarding=%s" % (config.hdmicec.enabled.value, config.hdmicec.volume_forwarding.value)) + print(f"[HdmiCEC][configVolumeForwarding]: hdmicec.enabled={config.hdmicec.enabled.value}, hdmicec.volume_forwarding={config.hdmicec.volume_forwarding.value}") if config.hdmicec.enabled.value and config.hdmicec.volume_forwarding.value: self.sendMessage(0x05, "givesystemaudiostatus") self.sendMessage(0x00, "givesystemaudiostatus") From be8b1fcb3e81f62bfc229be5003ab38ba0219ada Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Thu, 1 Feb 2024 07:58:05 +0000 Subject: [PATCH 091/183] PEP8 double aggressive E225 ~ E228 and E231 --- lib/python/Components/HdmiCec.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/python/Components/HdmiCec.py b/lib/python/Components/HdmiCec.py index a7742524759..fd89fc5a303 100644 --- a/lib/python/Components/HdmiCec.py +++ b/lib/python/Components/HdmiCec.py @@ -78,7 +78,7 @@ 0xA1: "", 0xA2: "", 0xFF: "", - } # noqa E123 + } # noqa E123 CtrlByte0 = { # Information only: control byte 0 status/action request by command (see cmdList) 0x00: {0x00: "", @@ -321,7 +321,7 @@ 0x04: "<1.3a>", 0x05: "<1.4>", 0x06: "<2.0>"}, - } # noqa E123 + } # noqa E123 def getPhysicalAddress(): From 19344dcf6e10270b1df8556e4a9e7b7f922945b0 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Thu, 1 Feb 2024 07:58:26 +0000 Subject: [PATCH 092/183] PEP8 double aggressive W291 ~ W293 and W391 --- lib/python/Plugins/SystemPlugins/ViX/IPKInstaller.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/python/Plugins/SystemPlugins/ViX/IPKInstaller.py b/lib/python/Plugins/SystemPlugins/ViX/IPKInstaller.py index 5aa10f0e3d0..a57f3b732b1 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/IPKInstaller.py +++ b/lib/python/Plugins/SystemPlugins/ViX/IPKInstaller.py @@ -116,7 +116,7 @@ def populate_List(self): del self.list[:] f = listdir(self.defaultDir) - self.loadDir = self.defaultDir.replace(" ", "%20") + self.loadDir = self.defaultDir.replace(" ", "%20") for line in f: if line.find(".ipk") != -1: self.list.append(path.join(self.loadDir, line)) @@ -130,7 +130,7 @@ def populate_List(self): self.list.append(path.join(self.loadDir, line)) self.list.sort() - # print(f"[IPKinstaller]3 f:{f} self.list:{self.list}") + # print(f"[IPKinstaller]3 f:{f} self.list:{self.list}") self["list"].l.setList(self.list) def keyInstall(self): From 2bcc20aba8a38cd42cc7282c06430c43cb8b7c85 Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Thu, 1 Feb 2024 17:00:01 +0200 Subject: [PATCH 093/183] [Added] Service Info Header addon --- lib/python/Components/Addons/GUIAddon.py | 5 +- .../Components/Addons/ServiceInfoBar.py | 307 ++++++++++++++++++ .../Components/Converter/PliExtraInfo.py | 25 ++ 3 files changed, 336 insertions(+), 1 deletion(-) create mode 100644 lib/python/Components/Addons/ServiceInfoBar.py diff --git a/lib/python/Components/Addons/GUIAddon.py b/lib/python/Components/Addons/GUIAddon.py index f1264cc34ed..eef11b40adf 100644 --- a/lib/python/Components/Addons/GUIAddon.py +++ b/lib/python/Components/Addons/GUIAddon.py @@ -10,7 +10,10 @@ def __init__(self): def connectRelatedElement(self, relatedElementName, container): relatedElementNames = relatedElementName.split(",") if len(relatedElementNames) == 1: - self.source = container[relatedElementName] + if relatedElementName == "session": + self.source = container.session + else: + self.source = container[relatedElementName] elif len(relatedElementNames) > 1: for x in relatedElementNames: if x in container: diff --git a/lib/python/Components/Addons/ServiceInfoBar.py b/lib/python/Components/Addons/ServiceInfoBar.py new file mode 100644 index 00000000000..9f6871c76ab --- /dev/null +++ b/lib/python/Components/Addons/ServiceInfoBar.py @@ -0,0 +1,307 @@ +from Components.Addons.GUIAddon import GUIAddon + +from enigma import eListbox, eListboxPythonMultiContent, BT_ALIGN_CENTER, iPlayableService, iRecordableService, eServiceReference, iServiceInformation, gFont, RT_HALIGN_LEFT, RT_VALIGN_CENTER, RT_VALIGN_TOP, RT_HALIGN_CENTER, eTimer, getDesktop, eSize + +from skin import parseScale, applySkinFactor, parseColor, parseFont + +from Components.MultiContent import MultiContentEntryPixmapAlphaBlend, MultiContentEntryText +from Components.ServiceEventTracker import ServiceEventTracker +from Components.Converter.ServiceInfo import getVideoHeight +from Components.Converter.VAudioInfo import StdAudioDesc +from Components.Converter.PliExtraInfo import createCurrentCaidLabel +from Components.Label import Label + +from Components.config import config + +from Screens.InfoBarGenerics import hasActiveSubservicesForCurrentChannel + +from Tools.Directories import resolveFilename, SCOPE_GUISKIN +from Tools.LoadPixmap import LoadPixmap + +import NavigationInstance + + +class ServiceInfoBar(GUIAddon): + def __init__(self): + GUIAddon.__init__(self) + self.nav = NavigationInstance.instance + self.nav.record_event.append(self.gotRecordEvent) + self.elements = [] + self.l = eListboxPythonMultiContent() # noqa: E741 + self.l.setBuildFunc(self.buildEntry) + self.l.setItemHeight(36) + self.l.setItemWidth(36) + self.spacing = applySkinFactor(10) + self.orientations = {"orHorizontal": eListbox.orHorizontal, "orVertical": eListbox.orVertical} + self.orientation = eListbox.orHorizontal + self.alignment = "left" + self.pixmaps = {} + self.pixmapsDisabled = {} + self.separatorLineColor = 0xC0C0C0 + self.foreColor = 0xFFFFFF + self.separatorLineThickness = 0 + self.autoresizeMode = "auto" # possible values: auto, fixed, condensed + self.font = gFont("Regular", 18) + self.__event_tracker = None + self.current_crypto = "---" + self.refreshCryptoInfo = eTimer() + self.refreshCryptoInfo.callback.append(self.checkCrypto_update) + self.refreshAddon = eTimer() + self.refreshAddon.callback.append(self.updateAddon) + self.textRenderer = Label("") + self.prevElement = None + self.lastElement = None + self.permanentIcons = [] + self.records_running = 0 + + + + def onContainerShown(self): + self.textRenderer.GUIcreate(self.relatedScreen.instance) + self.l.setItemHeight(self.instance.size().height()) + self.l.setItemWidth(self.instance.size().width()) + self.updateAddon() + if not self.__event_tracker: + self.__event_tracker = ServiceEventTracker(screen=self.relatedScreen, + eventmap={ + iPlayableService.evStart: self.updateAddon, + iPlayableService.evEnd: self.updateAddon, + iPlayableService.evUpdatedInfo: self.updateAddon, + iPlayableService.evVideoSizeChanged: self.updateAddon, + iPlayableService.evHBBTVInfo: self.updateAddon + } + ) + + def destroy(self): + self.nav.record_event.remove(self.gotRecordEvent) + self.refreshCryptoInfo.stop() + self.refreshAddon.stop() + self.refreshCryptoInfo.callback.remove(self.checkCrypto_update) + self.refreshAddon.callback.remove(self.updateAddon) + GUIAddon.destroy(self) + + GUI_WIDGET = eListbox + + def gotRecordEvent(self, service, event): + prev_records = self.records_running + if event in (iRecordableService.evEnd, iRecordableService.evStart, None): + recs = self.nav.getRecordings() + self.records_running = len(recs) + if self.records_running != prev_records: + self.updateAddon() + + def scheduleAddonUpdate(self): + self.refreshAddon.stop() + self.refreshAddon.start(1000) + + def checkCrypto_update(self): + if NavigationInstance.instance is not None: + service = NavigationInstance.instance.getCurrentService() + info = service and service.info() + if info: + new_crypto = createCurrentCaidLabel(info) + if new_crypto != self.current_crypto: + self.current_crypto = new_crypto + self.updateAddon() + + def updateAddon(self): + self.refreshAddon.stop() + l_list = [] + l_list.append((self.elements,)) + self.l.setList(l_list) + + def detectVisible(self, key): + if self.nav is not None: + service = self.nav.getCurrentService() + info = service and service.info() + isRef = isinstance(service, eServiceReference) + #self.current_info = info + if not info: + return None + video_height = None + video_aspect = None + video_height = getVideoHeight(info) + if key == "videoRes": + if video_height >= 720 and video_height < 1500: + return "IS_HD" + elif video_height >= 1500: + return "IS_4K" + else: + return "IS_SD" + elif key == "txt": + tpid = info.getInfo(iServiceInformation.sTXTPID) + if tpid > 0: + return key + elif key == "dolby" and not isRef: + audio = service.audioTracks() + if audio: + n = audio.getNumberOfTracks() + idx = 0 + while idx < n: + i = audio.getTrackInfo(idx) + description = StdAudioDesc(i.getDescription()) + if description and description.split()[0] in ("AC4", "AAC+", "AC3", "AC3+", "Dolby", "DTS", "DTS-HD", "HE-AAC", "IPCM", "LPCM", "WMA Pro"): + return key + idx += 1 + elif key == "crypt" and not isRef: + if info.getInfo(iServiceInformation.sIsCrypted) == 1: + return key + elif key == "audiotrack" and not isRef: + audio = service.audioTracks() + if bool(audio) and audio.getNumberOfTracks() > 1: + return key + elif key == "subtitletrack" and not isRef: + subtitle = service and service.subtitle() + subtitlelist = subtitle and subtitle.getSubtitleList() + if subtitlelist and len(subtitlelist) > 0: + return key + elif key == "hbbtv" and not isRef: + if info.getInfoString(iServiceInformation.sHBBTVUrl) != "": + return key + elif key == "subservices" and not isRef: + sRef = info.getInfoString(iServiceInformation.sServiceref) + url = "http://%s:%s/" % (config.misc.softcam_streamrelay_url.getHTML(), config.misc.softcam_streamrelay_port.value) + splittedRef = sRef.split(url.replace(":", "%3a")) + if len(splittedRef) > 1: + sRef = splittedRef[1].split(":")[0].replace("%3a", ":") + if hasActiveSubservicesForCurrentChannel(sRef): + return key + elif key == "stream" and not isRef: + if service.streamed() is not None: + return key + elif key == "currentCrypto" and not isRef: + self.current_crypto = createCurrentCaidLabel(info) + self.refreshCryptoInfo.start(1000) + return key + elif key == "record": + self.gotRecordEvent(None, None) + if self.records_running > 0: + return key + return None + + def buildEntry(self, sequence): + xPos = self.instance.size().width() if self.alignment == "right" else 0 + yPos = 0 + + res = [None] + + for x in sequence: + enabledKey = self.detectVisible(x) if x != "separator" else "separator" + pic = None + if enabledKey: + if enabledKey in self.pixmaps: + pic = LoadPixmap(resolveFilename(SCOPE_GUISKIN, self.pixmaps[enabledKey])) + elif self.autoresizeMode in ["auto", "fixed"] or x in self.permanentIcons: + if x == "videoRes": + enabledKey = "IS_SD" + if enabledKey in self.pixmaps: + pic = LoadPixmap(resolveFilename(SCOPE_GUISKIN, self.pixmaps[enabledKey])) + if x in self.pixmapsDisabled: + pic = LoadPixmap(resolveFilename(SCOPE_GUISKIN, self.pixmapsDisabled[x])) + + if enabledKey or self.autoresizeMode in ["auto", "fixed"] or x in self.permanentIcons: + if enabledKey != "separator" and enabledKey != "currentCrypto": + if pic: + pixd_size = pic.size() + pixd_width = pixd_size.width() + pixd_height = pixd_size.height() + pic_x_pos = (xPos - pixd_width) if self.alignment == "right" else xPos + pic_y_pos = yPos + (self.instance.size().height() - pixd_height) // 2 + res.append(MultiContentEntryPixmapAlphaBlend( + pos=(pic_x_pos, pic_y_pos), + size=(pixd_width, pixd_height), + png=pic, + backcolor=None, backcolor_sel=None, flags=BT_ALIGN_CENTER)) + if self.alignment == "right": + xPos -= pixd_width + self.spacing + else: + xPos += pixd_width + self.spacing + else: + if enabledKey == "separator": + if self.lastElement != "separator": + res.append(MultiContentEntryText( + pos=(xPos-self.separatorLineThickness, yPos), size=(self.separatorLineThickness, self.instance.size().height()), + font=0, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER, + text="", + color=self.separatorLineColor, color_sel=self.separatorLineColor, + backcolor=self.separatorLineColor, backcolor_sel=self.separatorLineColor)) + if self.alignment == "right": + xPos -= self.separatorLineThickness + self.spacing + else: + xPos += self.separatorLineThickness + self.spacing + else: + textWidth = self._calcTextWidth(self.current_crypto, font=self.font, size=eSize(self.getDesktopWith() // 3, 0)) + res.append(MultiContentEntryText( + pos=(xPos-textWidth, yPos-2), size=(textWidth, self.instance.size().height()), + font=0, flags=RT_HALIGN_CENTER | RT_VALIGN_TOP, + text=self.current_crypto, + color=self.foreColor, color_sel=self.foreColor, + backcolor=None, backcolor_sel=None)) + if self.alignment == "right": + xPos -= textWidth + self.spacing + else: + xPos += textWidth + self.spacing + + if enabledKey: + self.prevElement = self.lastElement + self.lastElement = enabledKey + + if self.lastElement == "separator" and self.prevElement != "currentCrypto": + res.pop() + + return res + + def getDesktopWith(self): + return getDesktop(0).size().width() + + def _calcTextWidth(self, text, font=None, size=None): + if size: + self.textRenderer.instance.resize(size) + if font: + self.textRenderer.instance.setFont(font) + self.textRenderer.text = text + return self.textRenderer.instance.calculateSize().width() + + def postWidgetCreate(self, instance): + instance.setSelectionEnable(False) + instance.setContent(self.l) + instance.allowNativeKeys(False) + + def applySkin(self, desktop, parent): + attribs = [] + for (attrib, value) in self.skinAttributes[:]: + if attrib == "pixmaps": + self.pixmaps = dict(item.split(':') for item in value.split(',')) + if attrib == "pixmapsDisabled": + self.pixmapsDisabled = dict(item.split(':') for item in value.split(',')) + elif attrib == "spacing": + self.spacing = parseScale(value) + elif attrib == "alignment": + self.alignment = value + elif attrib == "orientation": + self.orientation = self.orientations.get(value, self.orientations["orHorizontal"]) + if self.orientation == eListbox.orHorizontal: + self.instance.setOrientation(eListbox.orVertical) + self.l.setOrientation(eListbox.orVertical) + else: + self.instance.setOrientation(eListbox.orHorizontal) + self.l.setOrientation(eListbox.orHorizontal) + elif attrib == "elements": + self.elements = value.split(",") + elif attrib == "separatorLineColor": + self.foreColor = parseColor(value).argb() + elif attrib == "separatorLineThickness": + self.separatorLineThickness = parseScale(value) + elif attrib == "autoresizeMode": + self.autoresizeMode = value + elif attrib == "font": + self.font = parseFont(value, ((1, 1), (1, 1))) + elif attrib == "foregroundColor": + self.foreColor = parseColor(value).argb() + elif attrib == "permanent": + self.permanentIcons = value.split(",") + else: + attribs.append((attrib, value)) + self.skinAttributes = attribs + self.l.setFont(0, self.font) + return GUIAddon.applySkin(self, desktop, parent) diff --git a/lib/python/Components/Converter/PliExtraInfo.py b/lib/python/Components/Converter/PliExtraInfo.py index 3853b78ac30..b4abcc6ea7c 100644 --- a/lib/python/Components/Converter/PliExtraInfo.py +++ b/lib/python/Components/Converter/PliExtraInfo.py @@ -71,6 +71,31 @@ def addspace(text): text += " " return text +def getCryptoInfo(info): + ecmdata = GetEcmInfo() + if info and info.getInfo(iServiceInformation.sIsCrypted) == 1: + data = ecmdata.getEcmData() + current_source = data[0] + current_caid = data[1] + current_provid = data[2] + current_ecmpid = data[3] + else: + current_source = "" + current_caid = "0" + current_provid = "0" + current_ecmpid = "0" + return current_source, current_caid, current_provid, current_ecmpid + +def createCurrentCaidLabel(info): + current_source, current_caid, current_provid, current_ecmpid = getCryptoInfo(info) + res = "---" + if not pathExists("/tmp/ecm.info"): + return "FTA" + for caid_entry in caid_data: + if int(caid_entry[0], 16) <= int(current_caid, 16) <= int(caid_entry[1], 16): + res = caid_entry[4] + return res + class PliExtraInfo(Poll, Converter, object): From ece0a517a494bc8b65ce6cbe21320fc585e4fdd0 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Thu, 1 Feb 2024 22:25:56 +0000 Subject: [PATCH 094/183] PEP8 double aggressive E22, E224, E241, E242 and E27 --- lib/python/Components/Addons/ServiceInfoBar.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/python/Components/Addons/ServiceInfoBar.py b/lib/python/Components/Addons/ServiceInfoBar.py index 9f6871c76ab..40166adb782 100644 --- a/lib/python/Components/Addons/ServiceInfoBar.py +++ b/lib/python/Components/Addons/ServiceInfoBar.py @@ -220,7 +220,7 @@ def buildEntry(self, sequence): if enabledKey == "separator": if self.lastElement != "separator": res.append(MultiContentEntryText( - pos=(xPos-self.separatorLineThickness, yPos), size=(self.separatorLineThickness, self.instance.size().height()), + pos=(xPos - self.separatorLineThickness, yPos), size=(self.separatorLineThickness, self.instance.size().height()), font=0, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER, text="", color=self.separatorLineColor, color_sel=self.separatorLineColor, @@ -232,7 +232,7 @@ def buildEntry(self, sequence): else: textWidth = self._calcTextWidth(self.current_crypto, font=self.font, size=eSize(self.getDesktopWith() // 3, 0)) res.append(MultiContentEntryText( - pos=(xPos-textWidth, yPos-2), size=(textWidth, self.instance.size().height()), + pos=(xPos - textWidth, yPos - 2), size=(textWidth, self.instance.size().height()), font=0, flags=RT_HALIGN_CENTER | RT_VALIGN_TOP, text=self.current_crypto, color=self.foreColor, color_sel=self.foreColor, From 9078510cf87d4169b570144c446d3b506325734e Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Thu, 1 Feb 2024 22:26:12 +0000 Subject: [PATCH 095/183] PEP8 double aggressive E225 ~ E228 and E231 --- lib/python/Components/Addons/ServiceInfoBar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/Components/Addons/ServiceInfoBar.py b/lib/python/Components/Addons/ServiceInfoBar.py index 40166adb782..f6a52f01b36 100644 --- a/lib/python/Components/Addons/ServiceInfoBar.py +++ b/lib/python/Components/Addons/ServiceInfoBar.py @@ -40,7 +40,7 @@ def __init__(self): self.separatorLineColor = 0xC0C0C0 self.foreColor = 0xFFFFFF self.separatorLineThickness = 0 - self.autoresizeMode = "auto" # possible values: auto, fixed, condensed + self.autoresizeMode = "auto" # possible values: auto, fixed, condensed self.font = gFont("Regular", 18) self.__event_tracker = None self.current_crypto = "---" From c0a38ddf8bc750d06163cc800fa56850bd30ac54 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Thu, 1 Feb 2024 22:26:22 +0000 Subject: [PATCH 096/183] PEP8 double aggressive E301 ~ E306 --- lib/python/Components/Addons/ServiceInfoBar.py | 2 -- lib/python/Components/Converter/PliExtraInfo.py | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/python/Components/Addons/ServiceInfoBar.py b/lib/python/Components/Addons/ServiceInfoBar.py index f6a52f01b36..aff190db7b1 100644 --- a/lib/python/Components/Addons/ServiceInfoBar.py +++ b/lib/python/Components/Addons/ServiceInfoBar.py @@ -54,8 +54,6 @@ def __init__(self): self.permanentIcons = [] self.records_running = 0 - - def onContainerShown(self): self.textRenderer.GUIcreate(self.relatedScreen.instance) self.l.setItemHeight(self.instance.size().height()) diff --git a/lib/python/Components/Converter/PliExtraInfo.py b/lib/python/Components/Converter/PliExtraInfo.py index b4abcc6ea7c..5ec3359d0d9 100644 --- a/lib/python/Components/Converter/PliExtraInfo.py +++ b/lib/python/Components/Converter/PliExtraInfo.py @@ -71,6 +71,7 @@ def addspace(text): text += " " return text + def getCryptoInfo(info): ecmdata = GetEcmInfo() if info and info.getInfo(iServiceInformation.sIsCrypted) == 1: @@ -86,6 +87,7 @@ def getCryptoInfo(info): current_ecmpid = "0" return current_source, current_caid, current_provid, current_ecmpid + def createCurrentCaidLabel(info): current_source, current_caid, current_provid, current_ecmpid = getCryptoInfo(info) res = "---" From 324fa7298adee167c7b87624e73f3f68659533b3 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Thu, 1 Feb 2024 22:26:32 +0000 Subject: [PATCH 097/183] PEP8 double aggressive W291 ~ W293 and W391 --- .../Components/Addons/ServiceInfoBar.py | 20 +++++++++---------- .../Components/Converter/PliExtraInfo.py | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/python/Components/Addons/ServiceInfoBar.py b/lib/python/Components/Addons/ServiceInfoBar.py index aff190db7b1..6c34ac1365f 100644 --- a/lib/python/Components/Addons/ServiceInfoBar.py +++ b/lib/python/Components/Addons/ServiceInfoBar.py @@ -40,7 +40,7 @@ def __init__(self): self.separatorLineColor = 0xC0C0C0 self.foreColor = 0xFFFFFF self.separatorLineThickness = 0 - self.autoresizeMode = "auto" # possible values: auto, fixed, condensed + self.autoresizeMode = "auto" # possible values: auto, fixed, condensed self.font = gFont("Regular", 18) self.__event_tracker = None self.current_crypto = "---" @@ -53,7 +53,7 @@ def __init__(self): self.lastElement = None self.permanentIcons = [] self.records_running = 0 - + def onContainerShown(self): self.textRenderer.GUIcreate(self.relatedScreen.instance) self.l.setItemHeight(self.instance.size().height()) @@ -69,7 +69,7 @@ def onContainerShown(self): iPlayableService.evHBBTVInfo: self.updateAddon } ) - + def destroy(self): self.nav.record_event.remove(self.gotRecordEvent) self.refreshCryptoInfo.stop() @@ -79,7 +79,7 @@ def destroy(self): GUIAddon.destroy(self) GUI_WIDGET = eListbox - + def gotRecordEvent(self, service, event): prev_records = self.records_running if event in (iRecordableService.evEnd, iRecordableService.evStart, None): @@ -87,11 +87,11 @@ def gotRecordEvent(self, service, event): self.records_running = len(recs) if self.records_running != prev_records: self.updateAddon() - + def scheduleAddonUpdate(self): self.refreshAddon.stop() self.refreshAddon.start(1000) - + def checkCrypto_update(self): if NavigationInstance.instance is not None: service = NavigationInstance.instance.getCurrentService() @@ -239,19 +239,19 @@ def buildEntry(self, sequence): xPos -= textWidth + self.spacing else: xPos += textWidth + self.spacing - + if enabledKey: self.prevElement = self.lastElement self.lastElement = enabledKey - + if self.lastElement == "separator" and self.prevElement != "currentCrypto": res.pop() return res - + def getDesktopWith(self): return getDesktop(0).size().width() - + def _calcTextWidth(self, text, font=None, size=None): if size: self.textRenderer.instance.resize(size) diff --git a/lib/python/Components/Converter/PliExtraInfo.py b/lib/python/Components/Converter/PliExtraInfo.py index 5ec3359d0d9..72969b4c2e3 100644 --- a/lib/python/Components/Converter/PliExtraInfo.py +++ b/lib/python/Components/Converter/PliExtraInfo.py @@ -86,7 +86,7 @@ def getCryptoInfo(info): current_provid = "0" current_ecmpid = "0" return current_source, current_caid, current_provid, current_ecmpid - + def createCurrentCaidLabel(info): current_source, current_caid, current_provid, current_ecmpid = getCryptoInfo(info) From 5cb91438346d114bb8ded386734a2b5c7599b67d Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Fri, 2 Feb 2024 22:00:41 +0200 Subject: [PATCH 098/183] [Fixed] Exception when comparing eServiceReference with null --- lib/service/iservice.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/service/iservice.h b/lib/service/iservice.h index 7f2a44367fe..7ac55f7a821 100644 --- a/lib/service/iservice.h +++ b/lib/service/iservice.h @@ -184,7 +184,7 @@ class eServiceReference std::string toCompareString() const; bool operator==(const eServiceReference &c) const { - if (type != c.type) + if (!c || type != c.type) return 0; return (memcmp(data, c.data, sizeof(int)*8)==0) && (path == c.path); } @@ -194,6 +194,8 @@ class eServiceReference } bool operator<(const eServiceReference &c) const { + if (!c) return 0; + if (type < c.type) return 1; From 7b3e646e09ebf4fe448e72c2874e4d7c98803675 Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Fri, 2 Feb 2024 22:12:12 +0200 Subject: [PATCH 099/183] [Updated] ServiceInfoBar general handling and optimizations --- .../Components/Addons/ServiceInfoBar.py | 150 ++++++++++-------- 1 file changed, 86 insertions(+), 64 deletions(-) diff --git a/lib/python/Components/Addons/ServiceInfoBar.py b/lib/python/Components/Addons/ServiceInfoBar.py index 6c34ac1365f..0b25f6baff7 100644 --- a/lib/python/Components/Addons/ServiceInfoBar.py +++ b/lib/python/Components/Addons/ServiceInfoBar.py @@ -1,6 +1,6 @@ from Components.Addons.GUIAddon import GUIAddon -from enigma import eListbox, eListboxPythonMultiContent, BT_ALIGN_CENTER, iPlayableService, iRecordableService, eServiceReference, iServiceInformation, gFont, RT_HALIGN_LEFT, RT_VALIGN_CENTER, RT_VALIGN_TOP, RT_HALIGN_CENTER, eTimer, getDesktop, eSize +from enigma import eListbox, eListboxPythonMultiContent, BT_ALIGN_CENTER, iPlayableService, iRecordableService, eServiceReference, iServiceInformation, gFont, RT_HALIGN_LEFT, RT_VALIGN_CENTER, RT_VALIGN_TOP, RT_HALIGN_CENTER, eTimer, getDesktop, eSize, eStreamServer from skin import parseScale, applySkinFactor, parseColor, parseFont @@ -10,6 +10,7 @@ from Components.Converter.VAudioInfo import StdAudioDesc from Components.Converter.PliExtraInfo import createCurrentCaidLabel from Components.Label import Label +from Components.Sources.StreamService import StreamServiceList from Components.config import config @@ -40,7 +41,7 @@ def __init__(self): self.separatorLineColor = 0xC0C0C0 self.foreColor = 0xFFFFFF self.separatorLineThickness = 0 - self.autoresizeMode = "auto" # possible values: auto, fixed, condensed + self.autoresizeMode = "auto" # possible values: auto, fixed, condensed self.font = gFont("Regular", 18) self.__event_tracker = None self.current_crypto = "---" @@ -49,10 +50,9 @@ def __init__(self): self.refreshAddon = eTimer() self.refreshAddon.callback.append(self.updateAddon) self.textRenderer = Label("") - self.prevElement = None - self.lastElement = None self.permanentIcons = [] self.records_running = 0 + self.streamServer = eStreamServer.getInstance() def onContainerShown(self): self.textRenderer.GUIcreate(self.relatedScreen.instance) @@ -80,6 +80,13 @@ def destroy(self): GUI_WIDGET = eListbox + def remove_doubles(self, a_list): + duplicate = None + for item in a_list: + if duplicate != item: + duplicate = item + yield item + def gotRecordEvent(self, service, event): prev_records = self.records_running if event in (iRecordableService.evEnd, iRecordableService.evStart, None): @@ -104,8 +111,23 @@ def checkCrypto_update(self): def updateAddon(self): self.refreshAddon.stop() + + filteredElements = [] + + for x in self.elements: + enabledKey = self.detectVisible(x) if x != "separator" else "separator" + if enabledKey: + filteredElements.append(enabledKey) + elif self.autoresizeMode in ["auto", "fixed"] or x in self.permanentIcons: + filteredElements.append(x + "!") + + filteredElements = list(self.remove_doubles(filteredElements)) + + if filteredElements[-1] == "separator" and len(filteredElements) > 1 and filteredElements[len(filteredElements)-2] != "currentCrypto": + del filteredElements[-1] + l_list = [] - l_list.append((self.elements,)) + l_list.append((filteredElements,)) self.l.setList(l_list) def detectVisible(self, key): @@ -128,7 +150,7 @@ def detectVisible(self, key): return "IS_SD" elif key == "txt": tpid = info.getInfo(iServiceInformation.sTXTPID) - if tpid > 0: + if tpid > 0 and tpid < 100000: return key elif key == "dolby" and not isRef: audio = service.audioTracks() @@ -165,7 +187,9 @@ def detectVisible(self, key): if hasActiveSubservicesForCurrentChannel(sRef): return key elif key == "stream" and not isRef: - if service.streamed() is not None: + if self.streamServer is None: + return None + if service.streamed() is not None and ((self.streamServer.getConnectedClients() or StreamServiceList) and True or False): return key elif key == "currentCrypto" and not isRef: self.current_crypto = createCurrentCaidLabel(info) @@ -175,6 +199,13 @@ def detectVisible(self, key): self.gotRecordEvent(None, None) if self.records_running > 0: return key + elif key == "gamma" and not isRef: + if info.getInfo(iServiceInformation.sGamma) == 1: + return "IS_HDR" + if info.getInfo(iServiceInformation.sGamma) == 2: + return "IS_HDR10" + if info.getInfo(iServiceInformation.sGamma) == 3: + return "IS_HLG" return None def buildEntry(self, sequence): @@ -184,69 +215,60 @@ def buildEntry(self, sequence): res = [None] for x in sequence: - enabledKey = self.detectVisible(x) if x != "separator" else "separator" + enabledKey = x + isOn = True + if x[-1] == "!": + enabledKey = enabledKey.rstrip("!") + isOn = False + pic = None - if enabledKey: + if isOn: if enabledKey in self.pixmaps: pic = LoadPixmap(resolveFilename(SCOPE_GUISKIN, self.pixmaps[enabledKey])) - elif self.autoresizeMode in ["auto", "fixed"] or x in self.permanentIcons: - if x == "videoRes": - enabledKey = "IS_SD" - if enabledKey in self.pixmaps: - pic = LoadPixmap(resolveFilename(SCOPE_GUISKIN, self.pixmaps[enabledKey])) - if x in self.pixmapsDisabled: - pic = LoadPixmap(resolveFilename(SCOPE_GUISKIN, self.pixmapsDisabled[x])) + else: + if enabledKey in self.pixmapsDisabled: + pic = LoadPixmap(resolveFilename(SCOPE_GUISKIN, self.pixmapsDisabled[enabledKey])) - if enabledKey or self.autoresizeMode in ["auto", "fixed"] or x in self.permanentIcons: - if enabledKey != "separator" and enabledKey != "currentCrypto": - if pic: - pixd_size = pic.size() - pixd_width = pixd_size.width() - pixd_height = pixd_size.height() - pic_x_pos = (xPos - pixd_width) if self.alignment == "right" else xPos - pic_y_pos = yPos + (self.instance.size().height() - pixd_height) // 2 - res.append(MultiContentEntryPixmapAlphaBlend( - pos=(pic_x_pos, pic_y_pos), - size=(pixd_width, pixd_height), - png=pic, - backcolor=None, backcolor_sel=None, flags=BT_ALIGN_CENTER)) - if self.alignment == "right": - xPos -= pixd_width + self.spacing - else: - xPos += pixd_width + self.spacing + if enabledKey != "separator" and enabledKey != "currentCrypto": + if pic: + pixd_size = pic.size() + pixd_width = pixd_size.width() + pixd_height = pixd_size.height() + pic_x_pos = (xPos - pixd_width) if self.alignment == "right" else xPos + pic_y_pos = yPos + (self.instance.size().height() - pixd_height) // 2 + res.append(MultiContentEntryPixmapAlphaBlend( + pos=(pic_x_pos, pic_y_pos), + size=(pixd_width, pixd_height), + png=pic, + backcolor=None, backcolor_sel=None, flags=BT_ALIGN_CENTER)) + if self.alignment == "right": + xPos -= pixd_width + self.spacing + else: + xPos += pixd_width + self.spacing + else: + if enabledKey == "separator": + res.append(MultiContentEntryText( + pos=(xPos-self.separatorLineThickness, yPos), size=(self.separatorLineThickness, self.instance.size().height()), + font=0, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER, + text="", + color=self.separatorLineColor, color_sel=self.separatorLineColor, + backcolor=self.separatorLineColor, backcolor_sel=self.separatorLineColor)) + if self.alignment == "right": + xPos -= self.separatorLineThickness + self.spacing + else: + xPos += self.separatorLineThickness + self.spacing else: - if enabledKey == "separator": - if self.lastElement != "separator": - res.append(MultiContentEntryText( - pos=(xPos - self.separatorLineThickness, yPos), size=(self.separatorLineThickness, self.instance.size().height()), - font=0, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER, - text="", - color=self.separatorLineColor, color_sel=self.separatorLineColor, - backcolor=self.separatorLineColor, backcolor_sel=self.separatorLineColor)) - if self.alignment == "right": - xPos -= self.separatorLineThickness + self.spacing - else: - xPos += self.separatorLineThickness + self.spacing + textWidth = self._calcTextWidth(self.current_crypto, font=self.font, size=eSize(self.getDesktopWith() // 3, 0)) + res.append(MultiContentEntryText( + pos=(xPos-textWidth, yPos-2), size=(textWidth, self.instance.size().height()), + font=0, flags=RT_HALIGN_CENTER | RT_VALIGN_TOP, + text=self.current_crypto, + color=self.foreColor, color_sel=self.foreColor, + backcolor=None, backcolor_sel=None)) + if self.alignment == "right": + xPos -= textWidth + self.spacing else: - textWidth = self._calcTextWidth(self.current_crypto, font=self.font, size=eSize(self.getDesktopWith() // 3, 0)) - res.append(MultiContentEntryText( - pos=(xPos - textWidth, yPos - 2), size=(textWidth, self.instance.size().height()), - font=0, flags=RT_HALIGN_CENTER | RT_VALIGN_TOP, - text=self.current_crypto, - color=self.foreColor, color_sel=self.foreColor, - backcolor=None, backcolor_sel=None)) - if self.alignment == "right": - xPos -= textWidth + self.spacing - else: - xPos += textWidth + self.spacing - - if enabledKey: - self.prevElement = self.lastElement - self.lastElement = enabledKey - - if self.lastElement == "separator" and self.prevElement != "currentCrypto": - res.pop() - + xPos += textWidth + self.spacing return res def getDesktopWith(self): From 0823aba89090ee0e254a0b5e45d9006cbdd957c6 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Sat, 3 Feb 2024 00:41:45 +0000 Subject: [PATCH 100/183] PEP8 double aggressive E22, E224, E241, E242 and E27 --- lib/python/Components/Addons/ServiceInfoBar.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/python/Components/Addons/ServiceInfoBar.py b/lib/python/Components/Addons/ServiceInfoBar.py index 0b25f6baff7..1f2572b8cd6 100644 --- a/lib/python/Components/Addons/ServiceInfoBar.py +++ b/lib/python/Components/Addons/ServiceInfoBar.py @@ -123,7 +123,7 @@ def updateAddon(self): filteredElements = list(self.remove_doubles(filteredElements)) - if filteredElements[-1] == "separator" and len(filteredElements) > 1 and filteredElements[len(filteredElements)-2] != "currentCrypto": + if filteredElements[-1] == "separator" and len(filteredElements) > 1 and filteredElements[len(filteredElements) - 2] != "currentCrypto": del filteredElements[-1] l_list = [] @@ -248,7 +248,7 @@ def buildEntry(self, sequence): else: if enabledKey == "separator": res.append(MultiContentEntryText( - pos=(xPos-self.separatorLineThickness, yPos), size=(self.separatorLineThickness, self.instance.size().height()), + pos=(xPos - self.separatorLineThickness, yPos), size=(self.separatorLineThickness, self.instance.size().height()), font=0, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER, text="", color=self.separatorLineColor, color_sel=self.separatorLineColor, @@ -260,7 +260,7 @@ def buildEntry(self, sequence): else: textWidth = self._calcTextWidth(self.current_crypto, font=self.font, size=eSize(self.getDesktopWith() // 3, 0)) res.append(MultiContentEntryText( - pos=(xPos-textWidth, yPos-2), size=(textWidth, self.instance.size().height()), + pos=(xPos - textWidth, yPos - 2), size=(textWidth, self.instance.size().height()), font=0, flags=RT_HALIGN_CENTER | RT_VALIGN_TOP, text=self.current_crypto, color=self.foreColor, color_sel=self.foreColor, From e74b41ea9727bf560a7f19a7f892ecd52fd8943e Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Sat, 3 Feb 2024 00:42:00 +0000 Subject: [PATCH 101/183] PEP8 double aggressive E225 ~ E228 and E231 --- lib/python/Components/Addons/ServiceInfoBar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/Components/Addons/ServiceInfoBar.py b/lib/python/Components/Addons/ServiceInfoBar.py index 1f2572b8cd6..5353ac0ccc1 100644 --- a/lib/python/Components/Addons/ServiceInfoBar.py +++ b/lib/python/Components/Addons/ServiceInfoBar.py @@ -41,7 +41,7 @@ def __init__(self): self.separatorLineColor = 0xC0C0C0 self.foreColor = 0xFFFFFF self.separatorLineThickness = 0 - self.autoresizeMode = "auto" # possible values: auto, fixed, condensed + self.autoresizeMode = "auto" # possible values: auto, fixed, condensed self.font = gFont("Regular", 18) self.__event_tracker = None self.current_crypto = "---" From 4a55058314facbe3e32a61c97ca8ead948f6da49 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Sat, 3 Feb 2024 00:42:19 +0000 Subject: [PATCH 102/183] PEP8 double aggressive W291 ~ W293 and W391 --- lib/python/Components/Addons/ServiceInfoBar.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/python/Components/Addons/ServiceInfoBar.py b/lib/python/Components/Addons/ServiceInfoBar.py index 5353ac0ccc1..4f26e0e0bb0 100644 --- a/lib/python/Components/Addons/ServiceInfoBar.py +++ b/lib/python/Components/Addons/ServiceInfoBar.py @@ -41,7 +41,7 @@ def __init__(self): self.separatorLineColor = 0xC0C0C0 self.foreColor = 0xFFFFFF self.separatorLineThickness = 0 - self.autoresizeMode = "auto" # possible values: auto, fixed, condensed + self.autoresizeMode = "auto" # possible values: auto, fixed, condensed self.font = gFont("Regular", 18) self.__event_tracker = None self.current_crypto = "---" @@ -84,9 +84,9 @@ def remove_doubles(self, a_list): duplicate = None for item in a_list: if duplicate != item: - duplicate = item + duplicate = item yield item - + def gotRecordEvent(self, service, event): prev_records = self.records_running if event in (iRecordableService.evEnd, iRecordableService.evStart, None): @@ -111,18 +111,18 @@ def checkCrypto_update(self): def updateAddon(self): self.refreshAddon.stop() - + filteredElements = [] - + for x in self.elements: enabledKey = self.detectVisible(x) if x != "separator" else "separator" if enabledKey: filteredElements.append(enabledKey) elif self.autoresizeMode in ["auto", "fixed"] or x in self.permanentIcons: filteredElements.append(x + "!") - + filteredElements = list(self.remove_doubles(filteredElements)) - + if filteredElements[-1] == "separator" and len(filteredElements) > 1 and filteredElements[len(filteredElements) - 2] != "currentCrypto": del filteredElements[-1] From 52e2bc194ccbd5ddc38f86bba8bdb0ee95b945be Mon Sep 17 00:00:00 2001 From: Huevos Date: Sat, 3 Feb 2024 12:53:23 +0100 Subject: [PATCH 103/183] [VideoSetup] use Setup as parent class --- lib/python/Screens/VideoMode.py | 50 ++++++++------------------------- 1 file changed, 11 insertions(+), 39 deletions(-) diff --git a/lib/python/Screens/VideoMode.py b/lib/python/Screens/VideoMode.py index 70ac3ccf04e..4f3a6c50950 100644 --- a/lib/python/Screens/VideoMode.py +++ b/lib/python/Screens/VideoMode.py @@ -1,17 +1,15 @@ from os import path from enigma import iPlayableService, iServiceInformation, eTimer, eServiceCenter, eServiceReference, eDVBDB -from Components.ActionMap import ActionMap from Components.AVSwitch import iAVSwitch as iAV from Components.config import config, configfile, getConfigListEntry -from Components.ConfigList import ConfigListScreen from Components.Label import Label -from Components.Pixmap import Pixmap from Components.ServiceEventTracker import ServiceEventTracker -from Components.Sources.Boolean import Boolean from Components.SystemInfo import SystemInfo from Screens.ChannelSelection import FLAG_IS_DEDICATED_3D +from Screens.MessageBox import MessageBox from Screens.Screen import Screen +from Screens.Setup import Setup from Tools.Directories import isPluginInstalled from Tools.HardwareInfo import HardwareInfo @@ -21,26 +19,12 @@ videomode = "/proc/stb/video/videomode" -class VideoSetup(ConfigListScreen, Screen): +class VideoSetup(Setup): def __init__(self, session): - Screen.__init__(self, session) - self.skinName = ["Setup"] - self.setTitle(_("Video & Audio Settings")) - self["HelpWindow"] = Pixmap() - self["HelpWindow"].hide() - self["VKeyIcon"] = Boolean(False) - self["footnote"] = Label() - self.onChangedEntry = [] - # handle hotplug by re-creating setup + Setup.__init__(self, session, None) + self.title = _("Video & Audio Settings") self.onShow.append(self.startHotplug) self.onHide.append(self.stopHotplug) - - self.list = [] - ConfigListScreen.__init__(self, self.list, session=session, on_change=self.changedEntry, fullUI=True) - - self["actions"] = ActionMap(["SetupActions"], - {"save": self.apply, }, -2) - self["description"] = Label("") self.createSetup() self.grabLastGoodMode() @@ -55,8 +39,10 @@ def createSetup(self): self.list = [ getConfigListEntry(_("Video output"), config.av.videoport, _("Configures which video output connector will be used.")) ] + if config.av.videoport.value == "Scart": + config.av.autores.value = "disabled" if config.av.videoport.value in ("HDMI", "YPbPr", "Scart-YPbPr") and not isPluginInstalled("AutoResolution"): - self.list.append(getConfigListEntry(_("Automatic resolution"), config.av.autores, _("If enabled the output resolution of the box will try to match the resolution of the video content"))) + self.list.append(getConfigListEntry(_("Automatic resolution *"), config.av.autores, _("If enabled the output resolution of the box will try to match the resolution of the video content"))) if config.av.autores.value in ("all", "hd"): self.list.append(getConfigListEntry(_("Force de-interlace"), config.av.autores_deinterlace, _("If enabled the video will always be de-interlaced."))) self.list.append(getConfigListEntry(_("Automatic resolution label"), config.av.autores_label_timeout, _("Allows you to adjust the amount of time the resolution infomation display on screen."))) @@ -161,14 +147,6 @@ def createSetup(self): if config.usage.sort_settings.value: self["config"].list.sort(key=lambda x: x[0]) - def keyLeft(self): - ConfigListScreen.keyLeft(self) - self.createSetup() - - def keyRight(self): - ConfigListScreen.keyRight(self) - self.createSetup() - def confirm(self, confirmed): if not confirmed: config.av.videoport.setValue(self.last_good[0]) @@ -176,7 +154,7 @@ def confirm(self, confirmed): config.av.videorate[self.last_good[1]].setValue(self.last_good[2]) iAV.setMode(*self.last_good) else: - self.keySave() + Setup.keySave(self) def grabLastGoodMode(self): port = config.av.videoport.value @@ -184,21 +162,15 @@ def grabLastGoodMode(self): rate = config.av.videorate[mode].value self.last_good = (port, mode, rate) - def saveAll(self): - if config.av.videoport.value == 'Scart': - config.av.autores.setValue('disabled') - ConfigListScreen.saveAll(self) - - def apply(self): + def keySave(self): port = config.av.videoport.value mode = config.av.videomode[port].value rate = config.av.videorate[mode].value if (port, mode, rate) != self.last_good: iAV.setMode(port, mode, rate) - from Screens.MessageBox import MessageBox self.session.openWithCallback(self.confirm, MessageBox, _("Is this video mode ok?"), MessageBox.TYPE_YESNO, timeout=20, default=False) else: - self.keySave() + Setup.keySave(self) class AutoVideoModeLabel(Screen): From 9b12d7cf6821069bb7605365377ce56898982d35 Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Sat, 3 Feb 2024 15:06:12 +0200 Subject: [PATCH 104/183] [Added] possibility to invoke current service change manually [Added] more events handling in ServiceInfoBar --- .../Components/Addons/ServiceInfoBar.py | 40 ++++++++++++------- .../Components/Sources/CurrentService.py | 25 ++++++++++-- 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/lib/python/Components/Addons/ServiceInfoBar.py b/lib/python/Components/Addons/ServiceInfoBar.py index 4f26e0e0bb0..4dbcda6aeaa 100644 --- a/lib/python/Components/Addons/ServiceInfoBar.py +++ b/lib/python/Components/Addons/ServiceInfoBar.py @@ -27,6 +27,10 @@ def __init__(self): GUIAddon.__init__(self) self.nav = NavigationInstance.instance self.nav.record_event.append(self.gotRecordEvent) + self.refreshCryptoInfo = eTimer() + self.refreshCryptoInfo.callback.append(self.checkCrypto_update) + self.refreshAddon = eTimer() + self.refreshAddon.callback.append(self.updateAddon) self.elements = [] self.l = eListboxPythonMultiContent() # noqa: E741 self.l.setBuildFunc(self.buildEntry) @@ -41,18 +45,15 @@ def __init__(self): self.separatorLineColor = 0xC0C0C0 self.foreColor = 0xFFFFFF self.separatorLineThickness = 0 - self.autoresizeMode = "auto" # possible values: auto, fixed, condensed + self.autoresizeMode = "auto" # possible values: auto, fixed, condensed self.font = gFont("Regular", 18) self.__event_tracker = None self.current_crypto = "---" - self.refreshCryptoInfo = eTimer() - self.refreshCryptoInfo.callback.append(self.checkCrypto_update) - self.refreshAddon = eTimer() - self.refreshAddon.callback.append(self.updateAddon) self.textRenderer = Label("") self.permanentIcons = [] self.records_running = 0 self.streamServer = eStreamServer.getInstance() + self.currentServiceSource = None def onContainerShown(self): self.textRenderer.GUIcreate(self.relatedScreen.instance) @@ -62,14 +63,18 @@ def onContainerShown(self): if not self.__event_tracker: self.__event_tracker = ServiceEventTracker(screen=self.relatedScreen, eventmap={ - iPlayableService.evStart: self.updateAddon, - iPlayableService.evEnd: self.updateAddon, - iPlayableService.evUpdatedInfo: self.updateAddon, + iPlayableService.evStart: self.scheduleAddonUpdate, + iPlayableService.evEnd: self.scheduleAddonUpdate, + iPlayableService.evUpdatedInfo: self.scheduleAddonUpdate, iPlayableService.evVideoSizeChanged: self.updateAddon, - iPlayableService.evHBBTVInfo: self.updateAddon + iPlayableService.evHBBTVInfo: self.scheduleAddonUpdate, + iPlayableService.evNewProgramInfo: self.scheduleAddonUpdate, + iPlayableService.evCuesheetChanged: self.scheduleAddonUpdate, } ) - + self.currentServiceSource = self.source.screen["CurrentService"] + if self.currentServiceSource and self.updateAddon not in self.currentServiceSource.onManualNewService: + self.currentServiceSource.onManualNewService.append(self.scheduleAddonUpdate) def destroy(self): self.nav.record_event.remove(self.gotRecordEvent) self.refreshCryptoInfo.stop() @@ -97,7 +102,7 @@ def gotRecordEvent(self, service, event): def scheduleAddonUpdate(self): self.refreshAddon.stop() - self.refreshAddon.start(1000) + self.refreshAddon.start(350) def checkCrypto_update(self): if NavigationInstance.instance is not None: @@ -191,8 +196,9 @@ def detectVisible(self, key): return None if service.streamed() is not None and ((self.streamServer.getConnectedClients() or StreamServiceList) and True or False): return key - elif key == "currentCrypto" and not isRef: - self.current_crypto = createCurrentCaidLabel(info) + elif key == "currentCrypto": + if not isRef: + self.current_crypto = createCurrentCaidLabel(info) self.refreshCryptoInfo.start(1000) return key elif key == "record": @@ -226,6 +232,10 @@ def buildEntry(self, sequence): if enabledKey in self.pixmaps: pic = LoadPixmap(resolveFilename(SCOPE_GUISKIN, self.pixmaps[enabledKey])) else: + if enabledKey == "videoRes": + enabledKey = "IS_HD" + if enabledKey in self.pixmaps: + pic = LoadPixmap(resolveFilename(SCOPE_GUISKIN, self.pixmaps[enabledKey])) if enabledKey in self.pixmapsDisabled: pic = LoadPixmap(resolveFilename(SCOPE_GUISKIN, self.pixmapsDisabled[enabledKey])) @@ -248,7 +258,7 @@ def buildEntry(self, sequence): else: if enabledKey == "separator": res.append(MultiContentEntryText( - pos=(xPos - self.separatorLineThickness, yPos), size=(self.separatorLineThickness, self.instance.size().height()), + pos=(xPos-self.separatorLineThickness, yPos), size=(self.separatorLineThickness, self.instance.size().height()), font=0, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER, text="", color=self.separatorLineColor, color_sel=self.separatorLineColor, @@ -260,7 +270,7 @@ def buildEntry(self, sequence): else: textWidth = self._calcTextWidth(self.current_crypto, font=self.font, size=eSize(self.getDesktopWith() // 3, 0)) res.append(MultiContentEntryText( - pos=(xPos - textWidth, yPos - 2), size=(textWidth, self.instance.size().height()), + pos=(xPos-textWidth, yPos-2), size=(textWidth, self.instance.size().height()), font=0, flags=RT_HALIGN_CENTER | RT_VALIGN_TOP, text=self.current_crypto, color=self.foreColor, color_sel=self.foreColor, diff --git a/lib/python/Components/Sources/CurrentService.py b/lib/python/Components/Sources/CurrentService.py index bbf3e2ba9c3..e560d5e5976 100644 --- a/lib/python/Components/Sources/CurrentService.py +++ b/lib/python/Components/Sources/CurrentService.py @@ -1,4 +1,4 @@ -from enigma import iPlayableService +from enigma import iPlayableService, eServiceCenter from Components.Element import cached from Components.PerServiceDisplay import PerServiceBase @@ -23,13 +23,18 @@ def __init__(self, navcore): iPlayableService.evHBBTVInfo: self.serviceEvent }, with_event=True) self.navcore = navcore + self.srv = None + self.info = None + self.onManualNewService = [] def serviceEvent(self, event): + self.srv = None + self.info = None self.changed((self.CHANGED_SPECIFIC, event)) @cached def getCurrentService(self): - return self.navcore.getCurrentService() + return self.srv or self.navcore.getCurrentService() def getCurrentServiceReference(self): return self.navcore.getCurrentlyPlayingServiceReference() @@ -39,11 +44,25 @@ def getCurrentServiceReference(self): @cached def getCurrentServiceRef(self): if NavigationInstance.instance is not None: - return NavigationInstance.instance.getCurrentlyPlayingServiceOrGroup() + return self.srv or NavigationInstance.instance.getCurrentlyPlayingServiceOrGroup() return None serviceref = property(getCurrentServiceRef) + def newService(self, ref): + if ref and isinstance(ref, bool): + self.srv = None + elif ref: + self.srv = ref + self.info = eServiceCenter.getInstance().info(ref) + else: + self.srv = ref + + for x in self.onManualNewService: + x() + + self.changed((self.CHANGED_SPECIFIC, iPlayableService.evStart)) + def destroy(self): PerServiceBase.destroy(self) Source.destroy(self) From 42e02200e5f987a9a777c584b4114a8f5292d794 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Sat, 3 Feb 2024 13:30:40 +0000 Subject: [PATCH 105/183] PEP8 double aggressive E22, E224, E241, E242 and E27 --- lib/python/Components/Addons/ServiceInfoBar.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/python/Components/Addons/ServiceInfoBar.py b/lib/python/Components/Addons/ServiceInfoBar.py index 4dbcda6aeaa..f1c4664036c 100644 --- a/lib/python/Components/Addons/ServiceInfoBar.py +++ b/lib/python/Components/Addons/ServiceInfoBar.py @@ -258,7 +258,7 @@ def buildEntry(self, sequence): else: if enabledKey == "separator": res.append(MultiContentEntryText( - pos=(xPos-self.separatorLineThickness, yPos), size=(self.separatorLineThickness, self.instance.size().height()), + pos=(xPos - self.separatorLineThickness, yPos), size=(self.separatorLineThickness, self.instance.size().height()), font=0, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER, text="", color=self.separatorLineColor, color_sel=self.separatorLineColor, @@ -270,7 +270,7 @@ def buildEntry(self, sequence): else: textWidth = self._calcTextWidth(self.current_crypto, font=self.font, size=eSize(self.getDesktopWith() // 3, 0)) res.append(MultiContentEntryText( - pos=(xPos-textWidth, yPos-2), size=(textWidth, self.instance.size().height()), + pos=(xPos - textWidth, yPos - 2), size=(textWidth, self.instance.size().height()), font=0, flags=RT_HALIGN_CENTER | RT_VALIGN_TOP, text=self.current_crypto, color=self.foreColor, color_sel=self.foreColor, From 86a487c1d69a61a00910fd1cb9c3e621e0d7a337 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Sat, 3 Feb 2024 13:30:55 +0000 Subject: [PATCH 106/183] PEP8 double aggressive E225 ~ E228 and E231 --- lib/python/Components/Addons/ServiceInfoBar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/Components/Addons/ServiceInfoBar.py b/lib/python/Components/Addons/ServiceInfoBar.py index f1c4664036c..aff8f73a01f 100644 --- a/lib/python/Components/Addons/ServiceInfoBar.py +++ b/lib/python/Components/Addons/ServiceInfoBar.py @@ -45,7 +45,7 @@ def __init__(self): self.separatorLineColor = 0xC0C0C0 self.foreColor = 0xFFFFFF self.separatorLineThickness = 0 - self.autoresizeMode = "auto" # possible values: auto, fixed, condensed + self.autoresizeMode = "auto" # possible values: auto, fixed, condensed self.font = gFont("Regular", 18) self.__event_tracker = None self.current_crypto = "---" From 94cf57b198465cd11564bb2d02918b06771986e8 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Sat, 3 Feb 2024 13:31:05 +0000 Subject: [PATCH 107/183] PEP8 double aggressive E301 ~ E306 --- lib/python/Components/Addons/ServiceInfoBar.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/python/Components/Addons/ServiceInfoBar.py b/lib/python/Components/Addons/ServiceInfoBar.py index aff8f73a01f..549b6cd0755 100644 --- a/lib/python/Components/Addons/ServiceInfoBar.py +++ b/lib/python/Components/Addons/ServiceInfoBar.py @@ -75,6 +75,7 @@ def onContainerShown(self): self.currentServiceSource = self.source.screen["CurrentService"] if self.currentServiceSource and self.updateAddon not in self.currentServiceSource.onManualNewService: self.currentServiceSource.onManualNewService.append(self.scheduleAddonUpdate) + def destroy(self): self.nav.record_event.remove(self.gotRecordEvent) self.refreshCryptoInfo.stop() From 7eb5da0a790239ac966bc25774c519c7047cf35c Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Sat, 3 Feb 2024 13:31:15 +0000 Subject: [PATCH 108/183] PEP8 double aggressive W291 ~ W293 and W391 --- lib/python/Components/Addons/ServiceInfoBar.py | 2 +- lib/python/Components/Sources/CurrentService.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/python/Components/Addons/ServiceInfoBar.py b/lib/python/Components/Addons/ServiceInfoBar.py index 549b6cd0755..d12529a1c54 100644 --- a/lib/python/Components/Addons/ServiceInfoBar.py +++ b/lib/python/Components/Addons/ServiceInfoBar.py @@ -45,7 +45,7 @@ def __init__(self): self.separatorLineColor = 0xC0C0C0 self.foreColor = 0xFFFFFF self.separatorLineThickness = 0 - self.autoresizeMode = "auto" # possible values: auto, fixed, condensed + self.autoresizeMode = "auto" # possible values: auto, fixed, condensed self.font = gFont("Regular", 18) self.__event_tracker = None self.current_crypto = "---" diff --git a/lib/python/Components/Sources/CurrentService.py b/lib/python/Components/Sources/CurrentService.py index e560d5e5976..d4f2b7e61f3 100644 --- a/lib/python/Components/Sources/CurrentService.py +++ b/lib/python/Components/Sources/CurrentService.py @@ -57,7 +57,7 @@ def newService(self, ref): self.info = eServiceCenter.getInstance().info(ref) else: self.srv = ref - + for x in self.onManualNewService: x() From 8ffaeca8e265d4ac025bb2475666d781ee312f6f Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Sat, 3 Feb 2024 17:37:51 +0200 Subject: [PATCH 109/183] [Added] Rounded corners for ePixmap. Thanks @jbleyel --- lib/gui/epixmap.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/gui/epixmap.cpp b/lib/gui/epixmap.cpp index 721898d125c..8963ca83ed6 100644 --- a/lib/gui/epixmap.cpp +++ b/lib/gui/epixmap.cpp @@ -91,6 +91,8 @@ int ePixmap::event(int event, void *data, void *data2) // eWidget::event(event, data, data2); gPainter &painter = *(gPainter*)data2; + int cornerRadius = getCornerRadius(); + if (m_pixmap) { int flags = 0; @@ -102,9 +104,14 @@ int ePixmap::event(int event, void *data, void *data2) flags = gPainter::BT_ALPHABLEND; if (m_scale) flags |= gPainter::BT_SCALE; + + painter.setRadius(cornerRadius, getCornerRadiusEdges()); painter.blit(m_pixmap, eRect(ePoint(0, 0), s), eRect(), flags); } + if(cornerRadius) + return 0; // border not suppored for rounded edges + if (m_have_border_color) painter.setForegroundColor(m_border_color); From 601f5961ddaf9dcaf6d09f676190accd4069266f Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Sun, 4 Feb 2024 16:31:13 +0200 Subject: [PATCH 110/183] [Updated] Subservices detection [Updated] ServiceInfoBar --- .../Components/Addons/ServiceInfoBar.py | 12 ++-- .../Components/Converter/ServiceInfo.py | 7 +- lib/python/Screens/InfoBarGenerics.py | 71 ++++++++++++------- 3 files changed, 50 insertions(+), 40 deletions(-) diff --git a/lib/python/Components/Addons/ServiceInfoBar.py b/lib/python/Components/Addons/ServiceInfoBar.py index d12529a1c54..97e76737e94 100644 --- a/lib/python/Components/Addons/ServiceInfoBar.py +++ b/lib/python/Components/Addons/ServiceInfoBar.py @@ -102,8 +102,9 @@ def gotRecordEvent(self, service, event): self.updateAddon() def scheduleAddonUpdate(self): - self.refreshAddon.stop() - self.refreshAddon.start(350) + if hasattr(self, "refreshAddon"): + self.refreshAddon.stop() + self.refreshAddon.start(300) def checkCrypto_update(self): if NavigationInstance.instance is not None: @@ -185,12 +186,7 @@ def detectVisible(self, key): if info.getInfoString(iServiceInformation.sHBBTVUrl) != "": return key elif key == "subservices" and not isRef: - sRef = info.getInfoString(iServiceInformation.sServiceref) - url = "http://%s:%s/" % (config.misc.softcam_streamrelay_url.getHTML(), config.misc.softcam_streamrelay_port.value) - splittedRef = sRef.split(url.replace(":", "%3a")) - if len(splittedRef) > 1: - sRef = splittedRef[1].split(":")[0].replace("%3a", ":") - if hasActiveSubservicesForCurrentChannel(sRef): + if hasActiveSubservicesForCurrentChannel(service): return key elif key == "stream" and not isRef: if self.streamServer is None: diff --git a/lib/python/Components/Converter/ServiceInfo.py b/lib/python/Components/Converter/ServiceInfo.py index 8de932d67d6..777cd26a079 100644 --- a/lib/python/Components/Converter/ServiceInfo.py +++ b/lib/python/Components/Converter/ServiceInfo.py @@ -214,12 +214,7 @@ def getBoolean(self): elif self.type == self.IS_CRYPTED: return info.getInfo(iServiceInformation.sIsCrypted) == 1 elif self.type == self.SUBSERVICES_AVAILABLE: - sRef = info.getInfoString(iServiceInformation.sServiceref) - sr_url = "http://%s:%s/" % (config.misc.softcam_streamrelay_url.getHTML(), config.misc.softcam_streamrelay_port.value) - splittedRef = sRef.split(sr_url.replace(":", "%3a")) - if len(splittedRef) > 1: - sRef = splittedRef[1].split(":")[0].replace("%3a", ":") - return hasActiveSubservicesForCurrentChannel(sRef) + return hasActiveSubservicesForCurrentChannel(service) elif self.type == self.HAS_HBBTV: return info.getInfoString(iServiceInformation.sHBBTVUrl) != "" elif self.type == self.AUDIOTRACKS_AVAILABLE: diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py index 464f5f57ad2..0dfd492c751 100644 --- a/lib/python/Screens/InfoBarGenerics.py +++ b/lib/python/Screens/InfoBarGenerics.py @@ -252,28 +252,41 @@ def getPossibleSubservicesForCurrentChannel(current_service): return [] -def getActiveSubservicesForCurrentChannel(current_service): - if current_service: - possibleSubservices = getPossibleSubservicesForCurrentChannel(current_service) - activeSubservices = [] - epgCache = eEPGCache.getInstance() - for subservice in possibleSubservices: - events = epgCache.lookupEvent(['BDTS', (subservice, 0, -1)]) - if events and len(events) == 1: - event = events[0] - title = event[2] - if title and "Sendepause" not in title: - starttime = datetime.datetime.fromtimestamp(event[0]).strftime('%H:%M') - endtime = datetime.datetime.fromtimestamp(event[0] + event[1]).strftime('%H:%M') - servicename = eServiceReference(subservice).getServiceName() - schedule = str(starttime) + "-" + str(endtime) - activeSubservices.append((servicename + " " + schedule + " " + title, subservice)) - return activeSubservices - - -def hasActiveSubservicesForCurrentChannel(current_service): - activeSubservices = getActiveSubservicesForCurrentChannel(current_service) - return bool(activeSubservices and len(activeSubservices) > 1) +def getActiveSubservicesForCurrentChannel(service): + info = service and service.info() + sRef = info and info.getInfoString(iServiceInformation.sServiceref) + url = "http://%s:%s/" % (config.misc.softcam_streamrelay_url.getHTML(), config.misc.softcam_streamrelay_port.value) + splittedRef = sRef.split(url.replace(":", "%3a")) + if len(splittedRef) > 1: + sRef = splittedRef[1].split(":")[0].replace("%3a", ":") + current_service = ':'.join(sRef.split(':')[:11]) + if info: + if current_service: + possibleSubservices = getPossibleSubservicesForCurrentChannel(current_service) + activeSubservices = [] + epgCache = eEPGCache.getInstance() + for subservice in possibleSubservices: + events = epgCache.lookupEvent(['BDTS', (subservice, 0, -1)]) + if events and len(events) == 1: + event = events[0] + title = event[2] + if title and "Sendepause" not in title: + starttime = datetime.datetime.fromtimestamp(event[0]).strftime('%H:%M') + endtime = datetime.datetime.fromtimestamp(event[0] + event[1]).strftime('%H:%M') + current_show_name = "%s %s-%s" % (title, str(starttime), str(endtime)) + activeSubservices.append((current_show_name, subservice)) + if not activeSubservices: + subservices = service and service.subServices() + if subservices: + for idx in range(0, subservices.getNumberOfSubservices()): + subservice = subservices.getSubservice(idx) + print (" ---->",subservice.toString()) + activeSubservices.append((subservice.getName(), subservice.toString())) + return activeSubservices + +def hasActiveSubservicesForCurrentChannel(service): + activeSubservices = getActiveSubservicesForCurrentChannel(service) + return bool(activeSubservices and len(activeSubservices)) class InfoBarDish: @@ -3674,7 +3687,8 @@ def GreenPressed(self): def checkSubservicesAvail(self): serviceRef = self.session.nav.getCurrentlyPlayingServiceReference() - if not serviceRef or not hasActiveSubservicesForCurrentChannel(serviceRef.toString()): + service = self.session.nav.getCurrentService() + if not serviceRef or not hasActiveSubservicesForCurrentChannel(service): self["SubserviceQuickzapAction"].setEnabled(False) self.bouquets = self.bsel = self.selectedSubservice = None @@ -3704,9 +3718,14 @@ def changeSubservice(self, direction): def subserviceSelection(self): serviceRef = self.session.nav.getCurrentlyPlayingServiceReference() if serviceRef: - subservices = getActiveSubservicesForCurrentChannel(serviceRef.toString()) - if subservices and len(subservices) > 1 and serviceRef.toString() in [x[1] for x in subservices]: - selection = [x[1] for x in subservices].index(serviceRef.toString()) + service = self.session.nav.getCurrentService() + subservices = getActiveSubservicesForCurrentChannel(service) + if subservices and len(subservices) > 1 and (serviceRef.toString() in [x[1] for x in subservices] or service.subServices()): + try: + selection = [x[1] for x in subservices].index(serviceRef.toString()) + except: + selection = 0 + self.bouquets = self.servicelist and self.servicelist.getBouquetList() if self.bouquets and len(self.bouquets): keys = ["red", "blue", "", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"] + [""] * (len(subservices) - 10) From cf4d72a6253299018f0196f81c9f4e7ced8b932a Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Sun, 4 Feb 2024 14:35:00 +0000 Subject: [PATCH 111/183] PEP8 double aggressive E20 and E211 --- lib/python/Screens/InfoBarGenerics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py index 0dfd492c751..639c848f9f3 100644 --- a/lib/python/Screens/InfoBarGenerics.py +++ b/lib/python/Screens/InfoBarGenerics.py @@ -280,7 +280,7 @@ def getActiveSubservicesForCurrentChannel(service): if subservices: for idx in range(0, subservices.getNumberOfSubservices()): subservice = subservices.getSubservice(idx) - print (" ---->",subservice.toString()) + print(" ---->",subservice.toString()) activeSubservices.append((subservice.getName(), subservice.toString())) return activeSubservices From 6d74f87efd3bb0f33747c98d6b439a4346493a18 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Sun, 4 Feb 2024 14:35:26 +0000 Subject: [PATCH 112/183] PEP8 double aggressive E225 ~ E228 and E231 --- lib/python/Screens/InfoBarGenerics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py index 639c848f9f3..6d2d5f5d612 100644 --- a/lib/python/Screens/InfoBarGenerics.py +++ b/lib/python/Screens/InfoBarGenerics.py @@ -280,7 +280,7 @@ def getActiveSubservicesForCurrentChannel(service): if subservices: for idx in range(0, subservices.getNumberOfSubservices()): subservice = subservices.getSubservice(idx) - print(" ---->",subservice.toString()) + print(" ---->", subservice.toString()) activeSubservices.append((subservice.getName(), subservice.toString())) return activeSubservices From 773b6aa814b1ce8aeef8ee95063ae660ddf77b57 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Sun, 4 Feb 2024 14:35:37 +0000 Subject: [PATCH 113/183] PEP8 double aggressive E301 ~ E306 --- lib/python/Screens/InfoBarGenerics.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py index 6d2d5f5d612..b35c2da2704 100644 --- a/lib/python/Screens/InfoBarGenerics.py +++ b/lib/python/Screens/InfoBarGenerics.py @@ -284,6 +284,7 @@ def getActiveSubservicesForCurrentChannel(service): activeSubservices.append((subservice.getName(), subservice.toString())) return activeSubservices + def hasActiveSubservicesForCurrentChannel(service): activeSubservices = getActiveSubservicesForCurrentChannel(service) return bool(activeSubservices and len(activeSubservices)) From cf814f67a579be90277f25eabfa79239104dcb70 Mon Sep 17 00:00:00 2001 From: Orlandoxx <95180049+Orlandoxx@users.noreply.github.com> Date: Sun, 4 Feb 2024 16:51:09 +0200 Subject: [PATCH 114/183] Updated Finnish (fi.po) translation. Fixed "Automatic resolution *" change. --- po/fi.po | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/po/fi.po b/po/fi.po index fa8e84ea7a9..e5ce1c3c353 100644 --- a/po/fi.po +++ b/po/fi.po @@ -5,7 +5,7 @@ msgstr "" "Project-Id-Version: enigma2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-12-27 23:35+0000\n" -"PO-Revision-Date: 2024-01-27 08:14+0200\n" +"PO-Revision-Date: 2024-02-04 16:46+0200\n" "Last-Translator: Orlandox\n" "Language-Team: timoj/Kojo/Samzam/Orlandox\n" "Language: fi\n" @@ -2497,8 +2497,8 @@ msgstr "Äänen ja tekstityksen kielivalinnat" msgid "Automatic reload" msgstr "Automaattinen uudelleenlataus" -msgid "Automatic resolution" -msgstr "Automaattinen resoluutio" +msgid "Automatic resolution *" +msgstr "Automaattinen resoluutio *" msgid "Automatic resolution label" msgstr "Resoluution vaihtumisen ilmoitus" @@ -13543,7 +13543,8 @@ msgstr "" "Suomenkielinen käännös: timoj, Kojo, Samzam, Orlandox\n" "\n" "Ylläpito : Orlandox\n" -"--- 27.01.2024 ---\n" +"--- 04.02.2024 ---\n" +"\n" "http://www.huoltovalikko.com" msgid "TS file is too large for ISO9660 level 1!" From 23fa97f90bfa711f2f9f5d6f404ddea59558ecd9 Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Wed, 7 Feb 2024 15:15:15 +0200 Subject: [PATCH 115/183] [Updated] IPTV providers handling --- lib/dvb/db.cpp | 10 ++++++++++ lib/service/iservice.h | 14 +++++++++++++- lib/service/service.cpp | 25 +++++++++++++++++++++++++ lib/service/servicedvb.cpp | 15 ++++++++------- lib/service/servicemp3.cpp | 19 ++++++++----------- 5 files changed, 64 insertions(+), 19 deletions(-) diff --git a/lib/dvb/db.cpp b/lib/dvb/db.cpp index fa9a705acbd..e94b3b58bb3 100644 --- a/lib/dvb/db.cpp +++ b/lib/dvb/db.cpp @@ -207,6 +207,16 @@ RESULT eDVBService::getName(const eServiceReference &ref, std::string &name) name = m_service_name; else name = "(...)"; + + std::string res_name = ""; + std::string res_provider = ""; + eServiceReference::parseNameAndProviderFromName(name, res_name, res_provider); + name = res_name; + + if (!res_provider.empty() && m_provider_name.empty()) { + m_provider_name = res_provider; + } + return 0; } diff --git a/lib/service/iservice.h b/lib/service/iservice.h index 7ac55f7a821..4ee3ee9e8ff 100644 --- a/lib/service/iservice.h +++ b/lib/service/iservice.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +52,8 @@ class eServiceReference inline int getSortKey() const { return (flags & hasSortKey) ? data[3] : ((flags & sort1) ? 1 : 0); } + static RESULT parseNameAndProviderFromName(std::string &sourceName, std::string& name, std::string& prov); + #ifndef SWIG int data[8]; std::string path; @@ -88,9 +91,18 @@ class eServiceReference // real existing service ( for dvb eServiceDVB ) #ifndef SWIG std::string name; + std::string prov; int number; #endif - std::string getName() const { return name; } + std::string getName() const { + if (!name.empty()) { + std::vector name_split = split(name, "•"); + std::string name_res = name_split[0]; + return name_res; + } + return name; + } + std::string getProvider() const { return prov; } void setName( const std::string &n ) { name=n; } int getChannelNum() const { return number; } void setChannelNum(const int n) { number = n; } diff --git a/lib/service/service.cpp b/lib/service/service.cpp index 7813262ecfc..050856ba8f2 100644 --- a/lib/service/service.cpp +++ b/lib/service/service.cpp @@ -25,6 +25,18 @@ static std::string encode(const std::string s) return res; } +RESULT eServiceReference::parseNameAndProviderFromName(std::string &sourceName, std::string& name, std::string& prov) { + prov = ""; + if (!sourceName.empty()) { + std::vector name_split = split(sourceName, "•"); + name = name_split[0]; + if (name_split.size() > 1) { + prov = name_split[1]; + } + } + return 0; +} + void eServiceReference::eServiceReferenceBase(const std::string &string) { const char *c = string.c_str(); @@ -58,6 +70,13 @@ void eServiceReference::eServiceReferenceBase(const std::string &string) path = string; name = string; } + + std::string res_name = ""; + std::string res_provider = ""; + eServiceReference::parseNameAndProviderFromName(name, res_name, res_provider); + name = res_name; + prov = res_provider; + eDebug("[eServiceReference] URL=%s name=%s", path.c_str(), name.c_str()); return; } @@ -112,6 +131,12 @@ void eServiceReference::eServiceReferenceBase(const std::string &string) path = urlDecode(path); name = urlDecode(name); + + std::string res_name = ""; + std::string res_provider = ""; + eServiceReference::parseNameAndProviderFromName(name, res_name, res_provider); + name = res_name; + prov = res_provider; } eServiceReference::eServiceReference(const std::string &string) diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp index af3d3f68d90..4e066d7d441 100644 --- a/lib/service/servicedvb.cpp +++ b/lib/service/servicedvb.cpp @@ -388,13 +388,14 @@ RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, st } m_parser.m_name = name; } - if (!name.empty()) { - std::vector name_split = split(name, "•"); - name = name_split[0]; - if (name_split.size() > 1) { - m_parser.m_prov = name_split[1]; - } - } + + std::string res_name = ""; + std::string res_provider = ""; + eServiceReference::parseNameAndProviderFromName(name, res_name, res_provider); + name = res_name; + m_parser.m_name = name; + if (m_parser.m_prov.empty() && !ref.prov.empty()) m_parser.m_prov = ref.prov; + return 0; } diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index 3aaaa9aeba5..59718d5eae8 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -262,10 +262,12 @@ RESULT eStaticServiceMP3Info::getName(const eServiceReference &ref, std::string else name = ref.path; } - if (!name.empty()) { - std::vector name_split = split(name, "•"); - name = name_split[0]; - } + + std::string res_name = ""; + std::string res_provider = ""; + eServiceReference::parseNameAndProviderFromName(name, res_name, res_provider); + name = res_name; + return 0; } @@ -1205,13 +1207,8 @@ RESULT eServiceMP3::getName(std::string &name) else name = title; - if (!name.empty()) { - std::vector name_split = split(name, "•"); - name = name_split[0]; - if (name_split.size() > 1) { - m_prov = name_split[1]; - } - } + m_prov = m_ref.prov; + return 0; } From 06408b1fe939ca185d83837ef0604056521a07b3 Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Tue, 6 Feb 2024 10:37:57 +0100 Subject: [PATCH 116/183] [Cfile] - add new function - Merged from OpenATV(jbleyel) commit 98c6a97 --- lib/base/cfile.cpp | 160 ++++++++++++++++++++++++++++++++++++++++----- lib/base/cfile.h | 50 +++++++++----- 2 files changed, 177 insertions(+), 33 deletions(-) diff --git a/lib/base/cfile.cpp b/lib/base/cfile.cpp index acaba2f2534..a5640a9bf82 100644 --- a/lib/base/cfile.cpp +++ b/lib/base/cfile.cpp @@ -1,11 +1,16 @@ #include #include +#include #include "cfile.h" -int CFile::parseIntHex(int *result, const char *filename) +#define eDebugErrorOpenFile(MODULE, FILENAME) eDebug("[%s] Error %d: Unable to open file '%s'! (%m)", MODULE, errno, FILENAME) +#define eDebugErrorReadFile(MODULE, FILENAME) eDebug("[%s] Error %d: Unable to read from file '%s'! (%m)", MODULE, errno, FILENAME) +#define eDebugErrorWriteFile(MODULE, FILENAME) eDebug("[%s] Error %d: Unable to write to file '%s'! (%m)", MODULE, errno, FILENAME) + +int CFile::parseIntHex(int *result, const char *fileName) { - CFile f(filename, "r"); + CFile f(fileName, "r"); if (!f) return -1; if (fscanf(f, "%x", result) != 1) @@ -13,9 +18,9 @@ int CFile::parseIntHex(int *result, const char *filename) return 0; } -int CFile::parseInt(int *result, const char *filename) +int CFile::parseInt(int *result, const char *fileName) { - CFile f(filename, "r"); + CFile f(fileName, "r"); if (!f) return -1; if (fscanf(f, "%d", result) != 1) @@ -23,41 +28,51 @@ int CFile::parseInt(int *result, const char *filename) return 0; } -int CFile::writeIntHex(const char *filename, int value) +int CFile::parsePts_t(pts_t *result, const char *fileName) { - CFile f(filename, "w"); + CFile f(fileName, "r"); + if (!f) + return -1; + if (fscanf(f, "%lld", result) != 1) + return -2; + return 0; +} + +int CFile::writeIntHex(const char *fileName, int value) +{ + CFile f(fileName, "w"); if (!f) return -1; return fprintf(f, "%x", value); } -int CFile::writeInt(const char *filename, int value) +int CFile::writeInt(const char *fileName, int value) { - CFile f(filename, "w"); + CFile f(fileName, "w"); if (!f) return -1; return fprintf(f, "%d", value); } -int CFile::writeStr(const char *filename, std::string value) +int CFile::writeStr(const char *fileName, const std::string &value) { - CFile f(filename, "w"); + CFile f(fileName, "w"); if (f) fprintf(f, "%s", value.c_str()); return 0; } -int CFile::write(const char *filename, const char *value) +int CFile::write(const char *fileName, const char *value) { - CFile f(filename, "w"); + CFile f(fileName, "w"); if (!f) return -1; return fprintf(f, "%s", value); } -std::string CFile::read(const std::string &filename) +std::string CFile::read(const char *fileName) { - std::ifstream file(filename.c_str()); + std::ifstream file(fileName); if (!file.good()) return std::string(); std::stringstream ss; @@ -65,17 +80,126 @@ std::string CFile::read(const std::string &filename) return ss.str(); } -bool CFile::contains_word(const std::string &filename, const std::string &word_to_match) +bool CFile::contains_word(const char *fileName, const std::string &word_to_match) { std::string word; - std::ifstream file(filename.c_str()); + std::ifstream file(fileName); if (!file.good()) return false; - while(file >> word) - if(word == word_to_match) + while (file >> word) + if (word == word_to_match) return true; return false; } + +int CFile::parseIntHex(int *result, const char *fileName, const char *moduleName, int flags) +{ + CFile f(fileName, "r"); + if (!f) + { + if (!(flags & CFILE_FLAGS_SUPPRESS_NOT_EXISTS)) + eDebugErrorOpenFile(moduleName, fileName); + return -1; + } + if (fscanf(f, "%x", result) != 1) + { + if (!(flags & CFILE_FLAGS_SUPPRESS_READWRITE_ERROR)) + eDebugErrorReadFile(moduleName, fileName); + return -2; + } + return 0; +} + +int CFile::parseInt(int *result, const char *fileName, const char *moduleName, int flags) +{ + CFile f(fileName, "r"); + if (!f) + { + if (!(flags & CFILE_FLAGS_SUPPRESS_NOT_EXISTS)) + eDebugErrorOpenFile(moduleName, fileName); + return -1; + } + if (fscanf(f, "%d", result) != 1) + { + if (!(flags & CFILE_FLAGS_SUPPRESS_READWRITE_ERROR)) + eDebugErrorReadFile(moduleName, fileName); + return -2; + } + return 0; +} + +int CFile::writeIntHex(const char *fileName, int value, const char *moduleName, int flags) +{ + CFile f(fileName, "w"); + if (!f) + { + if (!(flags & CFILE_FLAGS_SUPPRESS_NOT_EXISTS)) + eDebugErrorOpenFile(moduleName, fileName); + return -1; + } + int ret = fprintf(f, "%x", value); + if (ret < 0 && !(flags & CFILE_FLAGS_SUPPRESS_READWRITE_ERROR)) + eDebugErrorWriteFile(moduleName, fileName); + return ret; +} + +int CFile::writeInt(const char *fileName, int value, const char *moduleName, int flags) +{ + CFile f(fileName, "w"); + if (!f) + { + if (!(flags & CFILE_FLAGS_SUPPRESS_NOT_EXISTS)) + eDebugErrorOpenFile(moduleName, fileName); + return -1; + } + int ret = fprintf(f, "%d", value); + if (ret < 0 && !(flags & CFILE_FLAGS_SUPPRESS_READWRITE_ERROR)) + eDebugErrorWriteFile(moduleName, fileName); + return ret; +} + +int CFile::writeStr(const char *fileName, const std::string &value, const char *moduleName, int flags) +{ + CFile f(fileName, "w"); + if (f) + { + int ret = fprintf(f, "%s", value.c_str()); + if (ret < 0 && !(flags & CFILE_FLAGS_SUPPRESS_READWRITE_ERROR)) + eDebugErrorWriteFile(moduleName, fileName); + } + else if (!(flags & CFILE_FLAGS_SUPPRESS_NOT_EXISTS)) + eDebugErrorOpenFile(moduleName, fileName); + return 0; +} + +int CFile::write(const char *fileName, const char *value, const char *moduleName, int flags) +{ + CFile f(fileName, "w"); + if (!f) + { + if (!(flags & CFILE_FLAGS_SUPPRESS_NOT_EXISTS)) + eDebugErrorOpenFile(moduleName, fileName); + return -1; + } + int ret = fprintf(f, "%s", value); + if (ret < 0 && !(flags & CFILE_FLAGS_SUPPRESS_READWRITE_ERROR)) + eDebugErrorWriteFile(moduleName, fileName); + return ret; +} + +std::string CFile::read(const char *fileName, const char *moduleName, int flags) +{ + std::ifstream file(fileName); + if (!file.good()) + { + if (!(flags & CFILE_FLAGS_SUPPRESS_NOT_EXISTS)) + eDebugErrorOpenFile(moduleName, fileName); + return std::string(); + } + std::stringstream ss; + ss << file.rdbuf(); + return ss.str(); +} diff --git a/lib/base/cfile.h b/lib/base/cfile.h index 2a55c875e8c..03ae26849db 100644 --- a/lib/base/cfile.h +++ b/lib/base/cfile.h @@ -4,16 +4,20 @@ #include #include +typedef long long pts_t; + /* Wrapper around FILE to prevent leaks and to make your code a bit more OO */ struct CFile { FILE *handle; - CFile(const char *filename, const char *mode) - : handle(fopen(filename, mode)) - {} - CFile(const std::string &filename, const char *mode) - : handle(fopen(filename.c_str(), mode)) - {} + CFile(const char *fileName, const char *mode) + : handle(fopen(fileName, mode)) + { + } + CFile(const std::string &fileName, const char *mode) + : handle(fopen(fileName.c_str(), mode)) + { + } ~CFile() { if (handle) @@ -21,17 +25,33 @@ struct CFile } void sync() { fsync(fileno(handle)); } operator bool() const { return handle != NULL; } - operator FILE*() const { return handle; } + operator FILE *() const { return handle; } /* Fetch integer from /proc files and such */ - static int parseIntHex(int *result, const char *filename); - static int parseInt(int *result, const char *filename); - static int writeIntHex(const char *filename, int value); - static int writeInt(const char *filename, int value); - static int writeStr(const char *filename, std::string value); - static int write(const char *filename, const char *value); - static std::string read(const std::string &filename); - static bool contains_word(const std::string &filename, const std::string &word); + static int parseIntHex(int *result, const char *fileName); + static int parseInt(int *result, const char *fileName); + static int parsePts_t(pts_t *result, const char *fileName); + static int writeIntHex(const char *fileName, int value); + static int writeInt(const char *fileName, int value); + static int writeStr(const char *fileName, const std::string &value); + static int write(const char *fileName, const char *value); + static std::string read(const char *fileName); + static bool contains_word(const char *fileName, const std::string &word); + + /* debug versions */ + static int parseIntHex(int *result, const char *fileName, const char *moduleName, int flags = 0); + static int parseInt(int *result, const char *fileName, const char *moduleName, int flags = 0); + static int writeIntHex(const char *fileName, int value, const char *moduleName, int flags = 0); + static int writeInt(const char *fileName, int value, const char *moduleName, int flags = 0); + static int writeStr(const char *fileName, const std::string &value, const char *moduleName, int flags = 0); + static int write(const char *fileName, const char *value, const char *moduleName, int flags = 0); + static std::string read(const char *fileName, const char *moduleName, int flags = 0); + + enum + { + CFILE_FLAGS_SUPPRESS_NOT_EXISTS = 2, + CFILE_FLAGS_SUPPRESS_READWRITE_ERROR = 4 + }; }; #endif From c8a70bbf399c55da3976a8b06cc0d17e8570dc3e Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Tue, 6 Feb 2024 11:20:47 +0100 Subject: [PATCH 117/183] [eAVSwitch] - add new C++ driver functionalty - merged from OpenATV(Jbleyel/Captain --- lib/driver/avswitch.cpp | 217 +++++++++++++++++++++++++++++++++++++++- lib/driver/avswitch.h | 25 ++++- 2 files changed, 238 insertions(+), 4 deletions(-) diff --git a/lib/driver/avswitch.cpp b/lib/driver/avswitch.cpp index a538771ca06..7c699d040d1 100644 --- a/lib/driver/avswitch.cpp +++ b/lib/driver/avswitch.cpp @@ -10,6 +10,18 @@ #include #include +const char *__MODULE__ = "eAVSwitch"; +const char *proc_hdmi_rx_monitor = "/proc/stb/hdmi-rx/0/hdmi_rx_monitor"; +const char *proc_hdmi_rx_monitor_audio = "/proc/stb/audio/hdmi_rx_monitor"; +const char *proc_policy169 = "/proc/stb/video/policy2"; +const char *proc_policy43 = "/proc/stb/video/policy"; +const char *proc_videoaspect_r = "/proc/stb/vmpeg/0/aspect"; +const char *proc_videoaspect_w = "/proc/stb/video/aspect"; +const char *proc_videomode = "/proc/stb/video/videomode"; +const char *proc_videomode_50 = "/proc/stb/video/videomode_50hz"; +const char *proc_videomode_60 = "/proc/stb/video/videomode_60hz"; +const char *proc_videomode_24 = "/proc/stb/video/videomode_24hz"; + eAVSwitch *eAVSwitch::instance = 0; eAVSwitch::eAVSwitch() @@ -117,6 +129,158 @@ bool eAVSwitch::haveScartSwitch() return !!strstr(tmp, "scart"); } +bool eAVSwitch::isActive() +{ + return m_active; +} + +// Get video aspect +int eAVSwitch::getAspect(int defaultVal, int flags) const +{ + int value = 0; + CFile::parseIntHex(&value, proc_videoaspect_r, __MODULE__, flags); + if (flags & FLAGS_DEBUG) + eDebug("[%s] %s: %d", __MODULE__, "getAspect", value); + return defaultVal; +} + +// read the preferred video modes +// parameters flags bit ( 1 = DEBUG , 2 = SUPPRESS_NOT_EXISTS , 4 = SUPPRESS_READWRITE_ERROR) +std::string eAVSwitch::getPreferredModes(int flags) const +{ + + const char *fileName = "/proc/stb/video/videomode_edid"; + const char *fileName2 = "/proc/stb/video/videomode_preferred"; + + std::string result = ""; + + if (access(fileName, R_OK) == 0) + { + result = CFile::read(fileName, __MODULE__, flags); + if (!result.empty() && result[result.length() - 1] == '\n') + { + result.erase(result.length() - 1); + } + } + + if (result.empty() && access(fileName2, R_OK) == 0) + { + result = CFile::read(fileName2, __MODULE__, flags); + if (!result.empty() && result[result.length() - 1] == '\n') + { + result.erase(result.length() - 1); + } + } + + return result; +} + +// readAvailableModes +// parameters flags bit ( 1 = DEBUG , 2 = SUPPRESS_NOT_EXISTS , 4 = SUPPRESS_READWRITE_ERROR) +std::string eAVSwitch::readAvailableModes(int flags) const +{ + + const char *fileName = "/proc/stb/video/videomode_choices"; + std::string result = ""; + if (access(fileName, R_OK) == 0) + { + result = CFile::read(fileName, __MODULE__, flags); + } + + if (!result.empty() && result[result.length() - 1] == '\n') + { + result.erase(result.length() - 1); + } + if (flags & FLAGS_DEBUG) + eDebug("[%s] %s: %s", __MODULE__, "readAvailableModes", result.c_str()); + return result; +} + +// Get progressive +bool eAVSwitch::getProgressive(int flags) const +{ + int value = 0; + CFile::parseIntHex(&value, "/proc/stb/vmpeg/0/progressive", __MODULE__, flags); + if (flags & FLAGS_DEBUG) + eDebug("[%s] %s: %d", __MODULE__, "getProgressive", value); + return value == 1; +} + +// Get screen resolution X +// parameters defaultVal = 0 +// parameters flags bit ( 1 = DEBUG , 2 = SUPPRESS_NOT_EXISTS , 4 = SUPPRESS_READWRITE_ERROR) +// @return resolution value +int eAVSwitch::getResolutionX(int defaultVal, int flags) const +{ + int value; + int ret = CFile::parseIntHex(&value, "/proc/stb/vmpeg/0/xres", __MODULE__, flags); + + if (ret != 0) + { + value = defaultVal; + } + else if (flags & FLAGS_DEBUG) + eDebug("[%s] %s: %d", __MODULE__, "getResolutionX", value); + + return value; +} + +// Get screen resolution Y +// parameters defaultVal = 0 +// parameters flags bit (1 = DEBUG , 2 = SUPPRESS_NOT_EXISTS , 4 = SUPPRESS_READWRITE_ERROR) +// @return resolution value +int eAVSwitch::getResolutionY(int defaultVal, int flags) const +{ + + int value; + int ret = CFile::parseIntHex(&value, "/proc/stb/vmpeg/0/yres", __MODULE__, flags); + + if (ret != 0) + { + value = defaultVal; + } + else if (flags & FLAGS_DEBUG) + eDebug("[%s] %s: %d", __MODULE__, "getResolutionY", value); + return value; +} + +// Get FrameRate +// parameters defaultVal +// parameters flags bit ( 1 = DEBUG , 2 = SUPPRESS_NOT_EXISTS , 4 = SUPPRESS_READWRITE_ERROR) +// @return +int eAVSwitch::getFrameRate(int defaultVal, int flags) const +{ + + const char *fileName = "/proc/stb/vmpeg/0/framerate"; + int value = 0; + int ret = CFile::parseInt(&value, fileName, __MODULE__, flags); + if (ret != 0) + { + value = defaultVal; + } + else if (flags & FLAGS_DEBUG) + eDebug("[%s] %s: %d", __MODULE__, "getFrameRate", value); + + return value; +} + +// Get VideoMode +// parameters defaultVal +// parameters flags bit ( 1 = DEBUG , 2 = SUPPRESS_NOT_EXISTS , 4 = SUPPRESS_READWRITE_ERROR) +// @return +std::string eAVSwitch::getVideoMode(const std::string &defaultVal, int flags) const +{ + std::string result = CFile::read(proc_videomode, __MODULE__, flags); + if (!result.empty() && result[result.length() - 1] == '\n') + { + result.erase(result.length() - 1); + } + if (flags & FLAGS_DEBUG) + eDebug("[%s] %s: %s", __MODULE__, "getVideoMode", result.c_str()); + + return result; +} + void eAVSwitch::setInput(int val) { /* @@ -143,9 +307,22 @@ void eAVSwitch::setInput(int val) close(fd); } -bool eAVSwitch::isActive() +// set VideoMode --> newMode +void eAVSwitch::setVideoMode(const std::string &newMode, int flags) const { - return m_active; + CFile::writeStr(proc_videomode, newMode, __MODULE__, flags); + if (flags & FLAGS_DEBUG) + eDebug("[%s] %s: %s", __MODULE__, "setVideoMode", newMode.c_str()); +} + +// @brief setAspect +// parameters newFormat (auto, 4:3, 16:9, 16:10) +// parameters flags bit ( 1 = DEBUG , 2 = SUPPRESS_NOT_EXISTS , 4 = SUPPRESS_READWRITE_ERROR) +void eAVSwitch::setAspect(const std::string &newFormat, int flags) const +{ + CFile::writeStr(proc_videoaspect_w, newFormat, __MODULE__, flags); + if (flags & FLAGS_DEBUG) + eDebug("[%s] %s: %s", __MODULE__, "setAspect", newFormat.c_str()); } void eAVSwitch::setColorFormat(int format) @@ -302,5 +479,41 @@ void eAVSwitch::setWSS(int val) // 0 = auto, 1 = auto(4:3_off) close(fd); } +// set Policy43 +void eAVSwitch::setPolicy43(const std::string &newPolicy, int flags) const +{ + + CFile::writeStr(proc_policy43, newPolicy, __MODULE__, flags); + + if (flags & FLAGS_DEBUG) + eDebug("[%s] %s: %s", __MODULE__, "setPolicy43", newPolicy.c_str()); +} + +// set Policy169 +// parameters newPolicy +void eAVSwitch::setPolicy169(const std::string &newPolicy, int flags) const +{ + + CFile::writeStr(proc_policy169, newPolicy, __MODULE__, flags); + + if (flags & FLAGS_DEBUG) + eDebug("[%s] %s: %s", __MODULE__, "setPolicy169", newPolicy.c_str()); +} + +// set VideoSize +// param top, left, width, height +void eAVSwitch::setVideoSize(int top, int left, int width, int height, int flags) const +{ + + CFile::writeIntHex("/proc/stb/vmpeg/0/dst_top", top, __MODULE__, flags); + CFile::writeIntHex("/proc/stb/vmpeg/0/dst_left", left, __MODULE__, flags); + CFile::writeIntHex("/proc/stb/vmpeg/0/dst_width", width, __MODULE__, flags); + CFile::writeIntHex("/proc/stb/vmpeg/0/dst_height", height, __MODULE__, flags); + CFile::writeInt("/proc/stb/vmpeg/0/dst_apply", 1, __MODULE__, flags); + + if (flags & FLAGS_DEBUG) + eDebug("[%s] %s: T:%d L:%d W:%d H:%d", __MODULE__, "setVideoSize", top, left, width, height); +} + //FIXME: correct "run/startlevel" eAutoInitP0 init_avswitch(eAutoInitNumbers::rc, "AVSwitch Driver"); diff --git a/lib/driver/avswitch.h b/lib/driver/avswitch.h index 33cdcacf6c1..dff024516da 100644 --- a/lib/driver/avswitch.h +++ b/lib/driver/avswitch.h @@ -27,12 +27,33 @@ class eAVSwitch: public sigc::trackable static eAVSwitch *getInstance(); bool haveScartSwitch(); int getVCRSlowBlanking(); - void setColorFormat(int format); + int getAspect(int defaultVal = 0, int flags = 0) const; + int getFrameRate(int defaultVal = 50000, int flags = 0) const; + bool getProgressive(int flags = 0) const; + int getResolutionX(int defaultVal = 0, int flags = 0) const; + int getResolutionY(int defaultVal = 0, int flags = 0) const; + std::string getVideoMode(const std::string &defaultVal = "", int flags = 0) const; + std::string getPreferredModes(int flags = 0) const; + std::string readAvailableModes(int flags = 0) const; + void setAspect(const std::string &newFormat, int flags = 0) const; void setAspectRatio(int ratio); - void setVideomode(int mode); + void setColorFormat(int format); void setInput(int val); void setWSS(int val); + void setVideomode(int mode); + void setVideoMode(const std::string &newMode, int flags = 0) const; + void setPolicy43(const std::string &newPolicy, int flags = 0) const; + void setPolicy169(const std::string &newPolicy, int flags = 0) const; + void setVideoSize(int top, int left, int width, int height, int flags = 0) const; bool isActive(); + + enum + { + FLAGS_DEBUG = 1, + FLAGS_SUPPRESS_NOT_EXISTS = 2, + FLAGS_SUPPRESS_READWRITE_ERROR = 4 + }; + PSignal1 vcr_sb_notifier; }; From 02b203c3994b2ef0d83531646e1d2d87602c75f2 Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Tue, 6 Feb 2024 11:31:11 +0100 Subject: [PATCH 118/183] [AVSwitch] - replace open/write with C++ drivers - merged from OpenATV(Jbleyel/Captain) --- lib/python/Components/AVSwitch.py | 178 ++++++++++++++++-------------- 1 file changed, 93 insertions(+), 85 deletions(-) diff --git a/lib/python/Components/AVSwitch.py b/lib/python/Components/AVSwitch.py index d85716e79a1..ffd32c077a6 100644 --- a/lib/python/Components/AVSwitch.py +++ b/lib/python/Components/AVSwitch.py @@ -22,11 +22,27 @@ class AVSwitch: rates["576i"] = {"50Hz": {50: "576i"}} rates["480p"] = {"60Hz": {60: "480p"}} rates["576p"] = {"50Hz": {50: "576p"}} - rates["720p"] = {"50Hz": {50: "720p50"}, "60Hz": {60: "720p"}, "multi": {50: "720p50", 60: "720p", 24: "720p24"}} - rates["1080i"] = {"50Hz": {50: "1080i50"}, "60Hz": {60: "1080i"}, "multi": {50: "1080i50", 60: "1080i", 24: "1080p24"}} - rates["1080p"] = {"50Hz": {50: "1080p50"}, "60Hz": {60: "1080p"}, "multi": {50: "1080p50", 60: "1080p", 24: "1080p24"}} - rates["2160p"] = {"50Hz": {50: "2160p50"}, "60Hz": {60: "2160p"}, "multi": {50: "2160p50", 60: "2160p", 24: "2160p24"}} - rates["2160p30"] = {"25Hz": {50: "2160p25"}, "30Hz": {60: "2160p30"}, "multi": {50: "2160p25", 60: "2160p30", 24: "2160p24"}} + rates["720p"] = {"50Hz": {50: "720p50"}, + "60Hz": {60: "720p"}, + "multi": {50: "720p50", 60: "720p"}, + "auto": {50: "720p50", 60: "720p", 24: "720p24"}} + rates["1080i"] = {"50Hz": {50: "1080i50"}, + "60Hz": {60: "1080i"}, + "multi": {50: "1080i50", 60: "1080i"}, + "auto": {50: "1080i50", 60: "1080i", 24: "1080i24"}} + rates["1080p"] = {"50Hz": {50: "1080p50"}, + "60Hz": {60: "1080p"}, + "multi": {50: "1080p50", 60: "1080p"}, + "auto": {50: "1080p50", 60: "1080p", 24: "1080p24"}} + rates["2160p30"] = {"25Hz": {50: "2160p25"}, + "30Hz": {60: "2160p30"}, + "multi": {50: "2160p25", 60: "2160p30"}, + "auto": {50: "2160p25", 60: "2160p30", 24: "2160p24"}} + rates["2160p"] = {"50Hz": {50: "2160p50"}, + "60Hz": {60: "2160p"}, + "multi": {50: "2160p50", 60: "2160p"}, + "auto": {50: "2160p50", 60: "2160p", 24: "2160p24"}} + rates["PC"] = { "1024x768": {60: "1024x768"}, # not possible on DM7025 "800x600": {60: "800x600"}, # also not possible @@ -61,7 +77,7 @@ class AVSwitch: if SystemInfo["hasScart"]: modes["Scart"] = ["PAL", "NTSC", "Multi"] - print("[AVSwitch] Modes-B are %s" % modes) + print(f"[AVSwitch] Modes found are: {modes}") def __init__(self): self.last_modes_preferred = [] @@ -69,27 +85,21 @@ def __init__(self): self.current_mode = None self.current_port = None self.readAvailableModes() - self.createConfig() self.readPreferredModes() + self.createConfig() def readAvailableModes(self): - try: - with open("/proc/stb/video/videomode_choices", "r") as fd: - modes = fd.read()[:-1] - except (IOError, OSError): - print("[AVSwitch] couldn't read available videomodes.") - modes = [] - return modes - return modes.split(" ") + SystemInfo["AvailableVideomodes"] = [] + SystemInfo["AvailableVideomodes"] = eAVSwitch.getInstance().readAvailableModes().split(" ") + # print(f"[AVSwitch][readAvailableModes] {SystemInfo['AvailableVideomodes']}") def readPreferredModes(self): - try: - with open("/proc/stb/video/videomode_preferred", "r") as fd: - modes = fd.read()[:-1] - self.modes_preferred = modes.split(" ") - except (IOError, OSError): - print("[AVSwitch] reading preferred modes failed, using all modes") - self.modes_preferred = self.readAvailableModes() + modes = [] + modes = eAVSwitch.getInstance().getPreferredModes(1) + # print("[AVSwitch] reading preferred modes", modes) + if not modes: + self.modes_preferred = SystemInfo["AvailableVideomodes"] + print(f"[AVSwitch][readPreferredModes]none, so using {self.modes_preferred}") if self.modes_preferred != self.last_modes_preferred: self.last_modes_preferred = self.modes_preferred self.on_hotplug("HDMI") # Must be HDMI. @@ -97,25 +107,27 @@ def readPreferredModes(self): # Check if a high-level mode with a given rate is available. # def isModeAvailable(self, port, mode, rate): - rate = self.rates[mode][rate] - for mode in rate.values(): - if mode not in self.readAvailableModes(): + rateNew = self.rates[mode][rate] + for modeNew in rateNew.values(): + # print(f"[AVSwitch][isModeAvailable] modeNew:{modeNew} videomodes:{SystemInfo['AvailableVideomodes']}") + if modeNew not in SystemInfo["AvailableVideomodes"]: + # print(f"[AVSwitch][isModeAvailable] modeNew:{modeNew} not available") return False + # print(f"[AVSwitch][isModeAvailable] modeNew:{modeNew} available") return True def isWidescreenMode(self, port, mode): return mode in self.widescreen_modes def setMode(self, port, mode, rate, force=None): - print("[AVSwitch] setMode - port: %s, mode: %s, rate: %s" % (port, mode, rate)) - # config.av.videoport.setValue(port) - # we can ignore "port" + print(f"[AVSwitch] setMode - port: {port}, mode: {mode}, rate: {rate}") self.current_mode = mode self.current_port = port modes = self.rates[mode][rate] mode_50 = modes.get(50) mode_60 = modes.get(60) mode_24 = modes.get(24) + print(f"[AVSwitch] setMode modes - setup_mode: {mode}, available: mode_50: {mode_50}, mode_60: {mode_60}, mode_24: {mode_24}") if mode_50 is None or force == 60: mode_50 = mode_60 if mode_60 is None or force == 50: @@ -127,18 +139,23 @@ def setMode(self, port, mode, rate, force=None): try: with open("/proc/stb/video/videomode_50hz", "w") as fd: fd.write(mode_50) - except (IOError, OSError): - print("[AVSwitch] cannot open /proc/stb/video/videomode_50hz") - try: + print(f"[AVSwitch][setMode][videomode_50hz] set to {mode_50}") with open("/proc/stb/video/videomode_60hz", "w") as fd: fd.write(mode_60) + print(f"[AVSwitch][setMode][videomode_60hz] set to {mode_60}") except (IOError, OSError): - print("[AVSwitch] cannot open /proc/stb/video/videomode_60hz") + print("[AVSwitch] cannot open /proc/stb/video/videomode_50hz or videomode_60hz") + try: + eAVSwitch.getInstance().setVideoMode(mode_50) + print(f"[AVSwitch][videomode] set to: {mode_50}") # fallback if no possibility to setup 50/60 hz mode + except (IOError, OSError): + print("[AVSwitch] fallback to mode 50 failed.") if SystemInfo["Has24hz"]: try: with open("/proc/stb/video/videomode_24hz", "w") as fd: fd.write(mode_24) + print(f"[AVSwitch][setMode][videomode_24hz] set to {mode_24}") except (IOError, OSError): print("[AVSwitch] cannot open /proc/stb/video/videomode_24hz") @@ -147,15 +164,8 @@ def setMode(self, port, mode, rate, force=None): # use 50Hz mode (if available) for booting with open("/etc/videomode", "w") as fd: fd.write(mode_50) - except IOError: + except (IOError, OSError): print("[AVSwitch] GigaBlue writing initial videomode to /etc/videomode failed.") - try: - set_mode = modes.get(int(rate)) - except Exception: # Don't support 50Hz, 60Hz for 1080p. - set_mode = mode_50 - print("[AVSwitch] set mode is %s" % set_mode) - with open("/proc/stb/video/videomode", "w") as fd: - fd.write(set_mode) map = {"cvbs": 0, "rgb": 1, "svideo": 2, "yuv": 3} self.setColorFormat(map[config.av.colorformat.value]) @@ -169,19 +179,15 @@ def saveMode(self, port, mode, rate): config.av.videorate[mode].setValue(rate) config.av.videorate[mode].save() - def isPortAvailable(self, port): - # fixme - return True - - def isPortUsed(self, port): + def isPortUsed(self, port): # used by VideoWizard if port == "HDMI": self.readPreferredModes() return len(self.modes_preferred) != 0 else: return True - def getPortList(self): - return [port for port in self.modes if self.isPortAvailable(port)] + def getPortList(self): # used by VideoWizard + return [port for port in self.modes] # Get a list with all modes, with all rates, for a given port. def getModeList(self, port): @@ -195,14 +201,12 @@ def getModeList(self, port): return res def createConfig(self, *args): - # hw_type = HardwareInfo().get_device_name() - # has_hdmi = HardwareInfo().has_hdmi() lst = [] config.av.videomode = ConfigSubDict() config.av.videorate = ConfigSubDict() # create list of output ports - portlist = self.getPortList() - print("[AVSwitch] portlist is %s" % portlist) + portlist = [port for port in self.modes] + print(f"[AVSwitch][createConfig] portlist is {portlist}") for port in portlist: descr = port if "HDMI" in port: @@ -213,7 +217,15 @@ def createConfig(self, *args): if len(modes): config.av.videomode[port] = ConfigSelection(choices=[mode for (mode, rates) in modes]) for (mode, rates) in modes: - config.av.videorate[mode] = ConfigSelection(choices=rates) + ratelist = [] + for rate in rates: + if rate == "auto": + if SystemInfo["Has24hz"]: + ratelist.append((rate, mode == "2160p30" and "auto (25Hz/30Hz/24Hz)" or "auto (50Hz/60Hz/24Hz)")) + else: + ratelist.append((rate, rate == "multi" and (mode == "2160p30" and "multi (25Hz/30Hz)" or "multi (50Hz/60Hz)") or rate)) + config.av.videorate[mode] = ConfigSelection(choices=ratelist) + print(f"[AVSwitch][createConfig] mode:{mode} rates:{ratelist}") config.av.videoport = ConfigSelection(choices=lst) def setInput(self, input): @@ -237,45 +249,41 @@ def setColorFormat(self, value): def setConfiguredMode(self): port = config.av.videoport.value if port not in config.av.videomode: - print("[AVSwitch] current port not available, not setting videomode") + print(f"[AVSwitch] current port: {port} not available, not setting videomode:{config.av.videomode}") return mode = config.av.videomode[port].value if mode not in config.av.videorate: - print("[AVSwitch] current mode not available, not setting videomode") + print(f"[AVSwitch] current mode:{mode} not available in config.av.videorate:{config.av.videorate}") return rate = config.av.videorate[mode].value self.setMode(port, mode, rate) - def setAspect(self, cfgelement): - print("[AVSwitch] setting aspect: %s" % cfgelement.value) - with open("/proc/stb/video/aspect", "w") as fd: - fd.write(cfgelement.value) + def setAspect(self, configElement): + eAVSwitch.getInstance().setAspect(configElement.value, 1) + print(f"[AVSwitch] setting aspect:{configElement.value}") - def setWss(self, cfgelement): - if not cfgelement.value: + def setWss(self, configElement): + if not configElement.value: wss = "auto(4:3_off)" else: wss = "auto" - print("[AVSwitch] setting wss: %s" % wss) + print(f"[AVSwitch] setting wss:{wss} configElement.value:{configElement.value}") with open("/proc/stb/denc/0/wss", "w") as fd: fd.write(wss) - def setPolicy43(self, cfgelement): - print("[AVSwitch] setting policy: %s" % cfgelement.value) - with open("/proc/stb/video/policy", "w") as fd: - fd.write(cfgelement.value) + def setPolicy43(self, configElement): + print(f"[AVSwitch] setting policy43:{configElement.value}") + eAVSwitch.getInstance().setPolicy43(configElement.value, 1) - def setPolicy169(self, cfgelement): - if path.exists("/proc/stb/video/policy2"): - print("[AVSwitch] setting policy2: %s" % cfgelement.value) - with open("/proc/stb/video/policy2", "w") as fd: - fd.write(cfgelement.value) + def setPolicy169(self, configElement): + print(f"[AVSwitch] setting policy169:{configElement.value}") + eAVSwitch.getInstance().setPolicy169(configElement.value, 1) def getOutputAspect(self): ret = (16, 9) port = config.av.videoport.value if port not in config.av.videomode: - print("[AVSwitch] current port not available in getOutputAspect!!! force 16:9") + print(f"[AVSwitch] current port:{port} not available in config.av.videomode:{config.av.videomode} force 16:9") else: mode = config.av.videomode[port].value force_widescreen = self.isWidescreenMode(port, mode) @@ -335,48 +343,48 @@ def InitAVSwitch(): # when YUV is not enabled, don't let the user select it if config.av.yuvenabled.value: colorformat_choices["yuv"] = _("YPbPr") - config.av.autores = ConfigSelection(choices={"disabled": _("Disabled"), "all": _("All resolutions"), "hd": _("only HD")}, default="disabled") + config.av.fixres = ConfigSelection(choices={"disabled": _("Disabled"), "all": _("All resolutions"), "hd": _("only HD")}, default="disabled") choicelist = [] for i in range(5, 16): choicelist.append(("%d" % i, ngettext("%d second", "%d seconds", i) % i)) - config.av.autores_label_timeout = ConfigSelection(default="5", choices=[("0", _("Not Shown"))] + choicelist) - config.av.autores_delay = ConfigSelectionNumber(min=0, max=15000, stepwidth=500, default=500, wraparound=True) - config.av.autores_deinterlace = ConfigYesNo(default=False) - config.av.autores_sd = ConfigSelection(choices={ + config.av.fixres_label_timeout = ConfigSelection(default="5", choices=[("0", _("Not Shown"))] + choicelist) + config.av.fixres_delay = ConfigSelectionNumber(min=500, max=15000, stepwidth=500, default=500, wraparound=True) + config.av.fixres_deinterlace = ConfigYesNo(default=False) + config.av.fixres_sd = ConfigSelection(choices={ "720p": _("720p"), "1080i": _("1080i") }, default="720p") - config.av.autores_480p24 = ConfigSelection(choices={ + config.av.fixres_480p24 = ConfigSelection(choices={ "480p24": _("480p 24Hz"), "720p24": _("720p 24Hz"), "1080p24": _("1080p 24Hz") }, default="1080p24") - config.av.autores_720p24 = ConfigSelection(choices={ + config.av.fixres_720p24 = ConfigSelection(choices={ "720p24": _("720p 24Hz"), "1080p24": _("1080p 24Hz") }, default="1080p24") - config.av.autores_1080p24 = ConfigSelection(choices={ + config.av.fixres_1080p24 = ConfigSelection(choices={ "1080p24": _("1080p 24Hz"), "1080p25": _("1080p 25Hz") }, default="1080p24") - config.av.autores_1080p25 = ConfigSelection(choices={ + config.av.fixres_1080p25 = ConfigSelection(choices={ "1080p25": _("1080p 25Hz"), "1080p50": _("1080p 50Hz") }, default="1080p25") - config.av.autores_1080p30 = ConfigSelection(choices={ + config.av.fixres_1080p30 = ConfigSelection(choices={ "1080p30": _("1080p 30Hz"), "1080p60": _("1080p 60Hz") }, default="1080p30") - config.av.autores_2160p24 = ConfigSelection(choices={ + config.av.fixres_2160p24 = ConfigSelection(choices={ "2160p24": _("2160p 24Hz"), "2160p25": _("2160p 25Hz"), "2160p30": _("2160p 30Hz") }, default="2160p24") - config.av.autores_2160p25 = ConfigSelection(choices={ + config.av.fixres_2160p25 = ConfigSelection(choices={ "2160p25": _("2160p 25Hz"), "2160p50": _("2160p 50Hz") }, default="2160p25") - config.av.autores_2160p30 = ConfigSelection(choices={ + config.av.fixres_2160p30 = ConfigSelection(choices={ "2160p30": _("2160p 30Hz"), "2160p60": _("2160p 60Hz") }, default="2160p30") @@ -468,7 +476,7 @@ def readChoices(procx, choices, default): choiceslist = procChoices.split(" ") choices = [(item, _(item)) for item in choiceslist] default = choiceslist[0] - print("[AVSwitch][readChoices from Proc] choices=%s, default=%s" % (choices, default)) + # print("[AVSwitch][readChoices from Proc] choices=%s, default=%s" % (choices, default)) return (choices, default) iAVSwitch.setInput("ENCODER") # Init on startup. From c305f3d4a4b5630fda8878ee30f4148a1c794e51 Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Tue, 6 Feb 2024 11:37:02 +0100 Subject: [PATCH 119/183] [VideoMode] - update auto resolution, use Setup(Thanks Huevos) --- lib/python/Screens/VideoMode.py | 296 +++++++++++++++++--------------- 1 file changed, 154 insertions(+), 142 deletions(-) diff --git a/lib/python/Screens/VideoMode.py b/lib/python/Screens/VideoMode.py index 4f3a6c50950..e575c39c30c 100644 --- a/lib/python/Screens/VideoMode.py +++ b/lib/python/Screens/VideoMode.py @@ -1,8 +1,8 @@ from os import path -from enigma import iPlayableService, iServiceInformation, eTimer, eServiceCenter, eServiceReference, eDVBDB +from enigma import iPlayableService, iServiceInformation, eTimer, eServiceCenter, eServiceReference, eDVBDB, eAVSwitch from Components.AVSwitch import iAVSwitch as iAV -from Components.config import config, configfile, getConfigListEntry +from Components.config import config, getConfigListEntry from Components.Label import Label from Components.ServiceEventTracker import ServiceEventTracker from Components.SystemInfo import SystemInfo @@ -19,6 +19,15 @@ videomode = "/proc/stb/video/videomode" +def getConfig_videomode(getmode, getrate): + port = config.av.videoport.value + mode = getmode[port].value + res = mode.replace("p30", "p")[:-1] + pol = mode.replace("p30", "p")[-1:] + rate = getrate[mode].value.replace("Hz", "") + return port, mode, res, pol, rate + + class VideoSetup(Setup): def __init__(self, session): Setup.__init__(self, session, None) @@ -40,39 +49,17 @@ def createSetup(self): getConfigListEntry(_("Video output"), config.av.videoport, _("Configures which video output connector will be used.")) ] if config.av.videoport.value == "Scart": - config.av.autores.value = "disabled" - if config.av.videoport.value in ("HDMI", "YPbPr", "Scart-YPbPr") and not isPluginInstalled("AutoResolution"): - self.list.append(getConfigListEntry(_("Automatic resolution *"), config.av.autores, _("If enabled the output resolution of the box will try to match the resolution of the video content"))) - if config.av.autores.value in ("all", "hd"): - self.list.append(getConfigListEntry(_("Force de-interlace"), config.av.autores_deinterlace, _("If enabled the video will always be de-interlaced."))) - self.list.append(getConfigListEntry(_("Automatic resolution label"), config.av.autores_label_timeout, _("Allows you to adjust the amount of time the resolution infomation display on screen."))) - if config.av.autores.value in ("hd"): - self.list.append(getConfigListEntry(_("Show SD as"), config.av.autores_sd, _("This option allows you to choose how to display standard defintion video on your TV."))) - self.list.append(getConfigListEntry(_("Show 480/576p 24fps as"), config.av.autores_480p24, _("This option allows you to choose how to display SD progressive 24Hz on your TV. (as not all TV's support these resolutions)"))) - self.list.append(getConfigListEntry(_("Show 720p 24fps as"), config.av.autores_720p24, _("This option allows you to choose how to display 720p 24Hz on your TV. (as not all TVs support these resolutions)"))) - self.list.append(getConfigListEntry(_("Show 1080p 24fps as"), config.av.autores_1080p24, _("This option allows you to choose how to display 1080p 24Hz on your TV. (as not all TVs support these resolutions)"))) - self.list.append(getConfigListEntry(_("Show 1080p 25fps as"), config.av.autores_1080p25, _("This option allows you to choose how to display 1080p 25Hz on your TV. (as not all TVs support these resolutions)"))) - self.list.append(getConfigListEntry(_("Show 1080p 30fps as"), config.av.autores_1080p30, _("This option allows you to choose how to display 1080p 30Hz on your TV. (as not all TVs support these resolutions)"))) - if "2160p24" in iAV.readAvailableModes(): - self.list.append(getConfigListEntry(_("Show 2160p 24fps as"), config.av.autores_2160p24, _("This option allows you to choose how to display 2160p 24Hz on your TV. (as not all TVs support these resolutions)"))) - self.list.append(getConfigListEntry(_("Show 2160p 25fps as"), config.av.autores_2160p25, _("This option allows you to choose how to display 2160p 25Hz on your TV. (as not all TVs support these resolutions)"))) - self.list.append(getConfigListEntry(_("Show 2160p 30fps as"), config.av.autores_2160p30, _("This option allows you to choose how to display 2160p 30Hz on your TV. (as not all TVs support these resolutions)"))) - + config.av.fixres.value = "disabled" # if we have modes for this port: - if (config.av.videoport.value in config.av.videomode and config.av.autores.value == "disabled") or config.av.videoport.value == "Scart": + if config.av.videoport.value in config.av.videomode or config.av.videoport.value == "Scart": # add mode- and rate-selection: self.list.append(getConfigListEntry(pgettext("Video output mode", "Mode"), config.av.videomode[config.av.videoport.value], _("This option configures the video output mode (or resolution)."))) if config.av.videomode[config.av.videoport.value].value == "PC": self.list.append(getConfigListEntry(_("Resolution"), config.av.videorate[config.av.videomode[config.av.videoport.value].value], _("This option configures the screen resolution in PC output mode."))) elif config.av.videoport.value != "Scart": - self.list.append(getConfigListEntry(_("Refresh rate"), config.av.videorate[config.av.videomode[config.av.videoport.value].value], _("Configure the refresh rate of the screen. Multi means refresh rate depends on the source 24/50/60Hz"))) - if config.av.autores.value in ("all", "hd") or config.av.videorate[config.av.videomode[config.av.videoport.value].value].value == "multi": - self.list.append(getConfigListEntry(_("Delay time"), config.av.autores_delay, _("Set the time before checking video source for resolution/refresh rate infomation."))) + self.list.append(getConfigListEntry(_("Refresh rate"), config.av.videorate[config.av.videomode[config.av.videoport.value].value], _("Configure screen refresh rate. Multi & Auto rates depend on the source 24/50/60Hz"))) port = config.av.videoport.value - if port not in config.av.videomode: - mode = None - else: - mode = config.av.videomode[port].value + mode = config.av.videomode[port].value if port in config.av.videomode else None # some modes (720p, 1080i) are always widescreen. Don't let the user select something here, "auto" is not what he wants. force_wide = iAV.isWidescreenMode(port, mode) # if not force_wide: @@ -92,11 +79,11 @@ def createSetup(self): if SystemInfo["ScartSwitch"]: self.list.append(getConfigListEntry(_("Auto scart switching"), config.av.vcrswitch, _("When enabled, your receiver will detect activity on the VCR SCART input."))) if SystemInfo["havecolorspace"]: - self.list.append(getConfigListEntry(_("HDMI Colorspace"), config.av.hdmicolorspace, _("Change the Colorspace from Auto to RGB"))) + self.list.append(getConfigListEntry(_("HDMI Colorspace"), config.av.hdmicolorspace, _("Change Colorspace setting - this may cause unexpected results or black screen"))) if SystemInfo["havecolorimetry"]: - self.list.append(getConfigListEntry(_("HDMI Colorimetry"), config.av.hdmicolorimetry, _("Change the Colorimetry for HDR"))) + self.list.append(getConfigListEntry(_("HDMI Colorimetry"), config.av.hdmicolorimetry, _("Change the Colorimetry for HDR - this may cause unexpected results or black screen"))) if SystemInfo["havehdmicolordepth"]: - self.list.append(getConfigListEntry(_("HDMI Colordepth"), config.av.hdmicolordepth, _("Change the Colordepth for UHD"))) + self.list.append(getConfigListEntry(_("HDMI Color depth"), config.av.hdmicolordepth, _("Change the Colordepth for UHD - this may cause unexpected results or black screen"))) if SystemInfo["havehdmihdrtype"]: self.list.append(getConfigListEntry(_("HDMI HDR Type"), config.av.hdmihdrtype, _("Enable or disable to force HDR Modes for UHD"))) if SystemInfo["HDRSupport"]: @@ -104,6 +91,24 @@ def createSetup(self): self.list.append(getConfigListEntry(_("HDR10 Support"), config.av.hdr10_support, _("Enable or disable to force HDR10 Modes for UHD"))) self.list.append(getConfigListEntry(_("Allow 12bit"), config.av.allow_12bit, _("Enable or disable the 12 Bit Color Mode"))) self.list.append(getConfigListEntry(_("Allow 10bit"), config.av.allow_10bit, _("Enable or disable the 10 Bit Color Mode"))) + if config.av.videoport.value in ("HDMI", "YPbPr", "Scart-YPbPr") and not isPluginInstalled("AutoResolution"): + self.list.append(getConfigListEntry(_("Force resolution override*"), config.av.fixres, _("Only use if you must force the output resolution - otherwise select 'Refresh Rate = auto'"))) + if config.av.fixres.value in ("all", "hd"): + self.list.append(getConfigListEntry(_("Force de-interlace"), config.av.fixres_deinterlace, _("If enabled the video will always be de-interlaced."))) + self.list.append(getConfigListEntry(_("Show resolution label"), config.av.fixres_label_timeout, _("Allows you to adjust the amount of time the resolution infomation display on screen."))) + if config.av.fixres.value in ("hd"): + self.list.append(getConfigListEntry(_("Show SD as"), config.av.fixres_sd, _("This option allows you to choose how to display standard defintion video on your TV."))) + self.list.append(getConfigListEntry(_("Show 480/576p 24fps as"), config.av.fixres_480p24, _("This option allows you to choose how to display SD progressive 24Hz on your TV. (as not all TV's support these resolutions)"))) + self.list.append(getConfigListEntry(_("Show 720p 24fps as"), config.av.fixres_720p24, _("This option allows you to choose how to display 720p 24Hz on your TV. (as not all TVs support these resolutions)"))) + self.list.append(getConfigListEntry(_("Show 1080p 24fps as"), config.av.fixres_1080p24, _("This option allows you to choose how to display 1080p 24Hz on your TV. (as not all TVs support these resolutions)"))) + self.list.append(getConfigListEntry(_("Show 1080p 25fps as"), config.av.fixres_1080p25, _("This option allows you to choose how to display 1080p 25Hz on your TV. (as not all TVs support these resolutions)"))) + self.list.append(getConfigListEntry(_("Show 1080p 30fps as"), config.av.fixres_1080p30, _("This option allows you to choose how to display 1080p 30Hz on your TV. (as not all TVs support these resolutions)"))) + if "2160p24" in SystemInfo["AvailableVideomodes"]: + self.list.append(getConfigListEntry(_("Show 2160p 24fps as"), config.av.fixres_2160p24, _("This option allows you to choose how to display 2160p 24Hz on your TV. (as not all TVs support these resolutions)"))) + self.list.append(getConfigListEntry(_("Show 2160p 25fps as"), config.av.fixres_2160p25, _("This option allows you to choose how to display 2160p 25Hz on your TV. (as not all TVs support these resolutions)"))) + self.list.append(getConfigListEntry(_("Show 2160p 30fps as"), config.av.fixres_2160p30, _("This option allows you to choose how to display 2160p 30Hz on your TV. (as not all TVs support these resolutions)"))) + if config.av.fixres.value in ("all", "hd") and config.av.videorate[config.av.videomode[config.av.videoport.value].value].value == "multi": + self.list.append(getConfigListEntry(_("Delay time"), config.av.fixres_delay, _("Set the time before checking video source for resolution/refresh rate infomation."))) if level >= 1: if SystemInfo["CanDownmixAC3"]: self.list.append(getConfigListEntry(_("AC3 downmix"), config.av.downmix_ac3, _("Choose whether multi channel ac3 sound tracks should be downmixed to stereo."))) @@ -173,7 +178,7 @@ def keySave(self): Setup.keySave(self) -class AutoVideoModeLabel(Screen): +class forceVideoModeLabel(Screen): def __init__(self, session): Screen.__init__(self, session) self["content"] = Label() @@ -183,7 +188,7 @@ def __init__(self, session): self.onShow.append(self.hide_me) def hide_me(self): - idx = config.av.autores_label_timeout.index + idx = config.av.fixres_label_timeout.index if idx: idx += 4 self.hideTimer.start(idx * 1000, True) @@ -202,23 +207,36 @@ def applySettings(mode=config.osd.threeDmode.value, znorm=int(config.osd.threeDz return -class AutoVideoMode(Screen): +class forceVideoMode(Screen): def __init__(self, session): Screen.__init__(self, session) + print("[VideoMode][forceVideoMode] Entered") self.current3dmode = config.osd.threeDmode.value self.__event_tracker = ServiceEventTracker(screen=self, eventmap={ iPlayableService.evStart: self.__evStart, iPlayableService.evVideoSizeChanged: self.VideoChanged, iPlayableService.evVideoProgressiveChanged: self.VideoChanged, iPlayableService.evVideoFramerateChanged: self.VideoChanged, - iPlayableService.evBuffering: self.BufferInfo, + # iPlayableService.evBuffering: self.evBuffering, + # iPlayableService.evEnd: self.VideoChanged, + # iPlayableService.evSeekableStatusChanged: self.VideoChanged, + # iPlayableService.evCuesheetChanged: self.VideoChanged, + # iPlayableService.evUpdatedInfo: self.VideoChanged, + # iPlayableService.evUpdatedEventInfo: self.evUpdatedEventInfo, + # iPlayableService.evEOF: self.evEOF, + # iPlayableService.evSOF: self.evSOF, + # iPlayableService.evGstreamerPlayStarted: self.evGstreamerPlayStarted, + }) + + self.firstrun = True self.delay = False self.bufferfull = True self.detecttimer = eTimer() self.detecttimer.callback.append(self.VideoChangeDetect) def checkIfDedicated3D(self): + print("[VideoMode][checkIfDedicated3D] Entered") service = self.session.nav.getCurrentlyPlayingServiceReference() servicepath = service and service.getPath() if servicepath and servicepath.startswith("/"): @@ -240,6 +258,7 @@ def __evStart(self): applySettings(isDedicated3D) else: applySettings() + self.VideoChanged() def BufferInfo(self): bufferInfo = self.session.nav.getCurrentService().streamed().getBufferCharge() @@ -249,62 +268,42 @@ def BufferInfo(self): else: self.bufferfull = False + def BufferInfoStop(self): + self.bufferfull = True + def VideoChanged(self): - if self.session.nav.getCurrentlyPlayingServiceReference() and not self.session.nav.getCurrentlyPlayingServiceReference().toString().startswith("4097:"): - delay = config.av.autores_delay.value - else: - delay = config.av.autores_delay.value * 2 - if not self.detecttimer.isActive() and not self.delay: - self.delay = True - self.detecttimer.start(delay) + if config.av.fixres.value == "disabled": + print("[VideoMode] autoresolution is disabled - resolution not changed !") + return else: - self.delay = True - self.detecttimer.stop() + print("[VideoMode][VideoChanged] Entered") + if self.session.nav.getCurrentlyPlayingServiceReference() and not self.session.nav.getCurrentlyPlayingServiceReference().toString().startswith("4097:"): + delay = config.av.fixres_delay.value + else: + delay = config.av.fixres_delay.value * 2 + if not self.detecttimer.isActive() and not self.delay: + self.delay = True + else: + self.delay = True + self.detecttimer.stop() + self.detecttimer.start(delay) def VideoChangeDetect(self): + print("[VideoMode][VideoChangeDetect] Entered") global resolutionlabel - config_port = config.av.videoport.value - print("[VideoMode][VideoChangeDetect] config.av.videomode keys", list(config.av.videomode.keys())) - try: - config_mode = str(config.av.videomode[config_port].value).replace("\n", "") - config_res = str(config.av.videomode[config_port].value[:-1]).replace("\n", "") - config_pol = str(config.av.videomode[config_port].value[-1:]).replace("\n", "") - config_rate = str(config.av.videorate[config_mode].value).replace("Hz", "").replace("\n", "") - print("[VideoMode][VideoChangeDetect] config_port, config_mode, config_res, config_pol, config_rate", config_port, " ", config_mode, " ", config_res, " ", config_pol, " ", config_rate) - except KeyError as e: - print("[VideoMode][VideoChangeDetect] config_port Keyerror use current values", e) - self.delay = False - self.detecttimer.stop() - return - with open(videomode, "r") as fd: - current_mode = fd.read()[:-1].replace("\n", "") + avSwitch = eAVSwitch.getInstance() + config_port, config_mode, config_res, config_pol, config_rate = getConfig_videomode(config.av.videomode, config.av.videorate) + current_mode = avSwitch.getVideoMode("") if current_mode.upper() in ("PAL", "NTSC"): current_mode = current_mode.upper() - video_height = None - video_width = None - video_pol = None - video_rate = None - try: - with open("/proc/stb/vmpeg/0/yres", "r") as fd: - video_height = int(fd.read(), 16) - except Exception: - pass - try: - with open("/proc/stb/vmpeg/0/xres", "r") as fd: - video_width = int(fd.read(), 16) - except Exception: - pass - try: - with open("/proc/stb/vmpeg/0/progressive", "r") as fd: - video_pol = "p" if int(fd.read(), 16) else "i" - except Exception: - pass - try: - with open("/proc/stb/vmpeg/0/framerate", "r") as fd: - video_rate = int(fd.read()) - except Exception: - pass + print(f"[VideoMode][VideoChangeDetect]2 current_mode:{current_mode} config_port:{config_port}, config_mode:{config_mode}, config_res:{config_res}, config_pol:{config_pol}, config_rate:{config_rate}") + + video_height = avSwitch.getResolutionY(0) + video_width = avSwitch.getResolutionX(0) + video_pol = "p" if avSwitch.getProgressive() else "i" + video_rate = avSwitch.getFrameRate(0) + print(f"[VideoMode][VideoChangeDetect]1 video_height:{video_height}, video_width:{video_width}, video_pol:{video_pol}, video_rate:{video_rate}") if not video_height or not video_width or not video_pol or not video_rate: info = None if self.session.nav.getCurrentService() is None else self.session.nav.getCurrentService().info() if info: @@ -312,6 +311,7 @@ def VideoChangeDetect(self): video_width = int(info.getInfo(iServiceInformation.sVideoWidth)) video_pol = ("i", "p")[info.getInfo(iServiceInformation.sProgressive)] video_rate = int(info.getInfo(iServiceInformation.sFrameRate)) + print(f"[VideoMode][VideoChangeDetect]2 have info - video_height:{video_height}, video_width:{video_width}, video_pol:{video_pol}, video_rate:{video_rate}") if video_height and video_width and video_pol and video_rate: resolutionlabel["content"].setText(_("Video content: %ix%i%s %iHz") % (video_width, video_height, video_pol, (video_rate + 500) // 1000)) if (1 < video_width <= 1024) and video_height <= 480 and video_rate in (23976, 24000, 25000, 29970, 50000, 59940): @@ -325,11 +325,14 @@ def VideoChangeDetect(self): elif (video_width == 3840) and video_height > 1080: new_res = "2160" else: + print(f"[VideoMode][VideoChangeDetect]new_res = config_res:{config_res}") new_res = config_res + print(f"[VideoMode][VideoChangeDetect]new_res:{new_res}, video_width:{video_width}, video_height:{video_height}, video_pol:{video_pol}, video_rate:{video_rate}") if video_rate != -1: - if video_rate == 25000 and video_pol == "i": + print(f"[VideoMode][VideoChangeDetect]video_rate:{video_rate}") + if video_rate == 25000: new_rate = 50000 - elif video_rate == 59940 or (video_rate == 29970 and video_pol == "i") or (video_rate == 29970 and video_pol == "p" and config.av.autores.value == "disabled"): + elif video_rate == 59940 or (video_rate == 29970 and video_pol == "i") or (video_rate == 29970 and video_pol == "p" and config.av.fixres.value == "disabled"): new_rate = 60000 elif video_rate == 23976: new_rate = 24000 @@ -337,105 +340,114 @@ def VideoChangeDetect(self): new_rate = 30000 else: new_rate = video_rate + print(f"[VideoMode][VideoChangeDetect]new_rate:{new_rate} = video_rate:{video_rate}") new_rate = str((new_rate + 500) // 1000) else: + print(f"[VideoMode][VideoChangeDetect]new_rate = config_rate:{config_rate}") new_rate = config_rate - if video_pol != -1: - new_pol = str(video_pol) - else: - new_pol = config_pol + new_pol = str(video_pol) if video_pol != -1 else config_pol write_mode = new_mode = None + print(f"[VideoMode][VideoChangeDetect] new_pol:{new_pol} video_pol:{video_pol} config_pol:{config_pol} config_mode:{config_mode} config.av.fixres.value:{config.av.fixres.value}") if config_mode in ("PAL", "NTSC"): write_mode = config_mode - elif config.av.autores.value == "all" or (config.av.autores.value == "hd" and int(new_res) >= 720): - if (config.av.autores_deinterlace.value and HardwareInfo().is_nextgen()) or (config.av.autores_deinterlace.value and not HardwareInfo().is_nextgen() and int(new_res) <= 720): + + elif config.av.fixres.value == "all" or (config.av.fixres.value == "hd" and int(new_res) >= 720): + print(f"[VideoMode][VideoChangeDetect] config.av.fixres.value = all or HD:{config.av.fixres.value}") + if (config.av.fixres_deinterlace.value and HardwareInfo().is_nextgen()) or (config.av.fixres_deinterlace.value and not HardwareInfo().is_nextgen() and int(new_res) <= 720): new_pol = new_pol.replace("i", "p") - if new_res + new_pol + new_rate in iAV.readAvailableModes(): + print(f"[VideoMode][VideoChangeDetect] new_res + new_pol + new_rate: {new_res + new_pol + new_rate}") + if new_res + new_pol + new_rate in SystemInfo["AvailableVideomodes"]: new_mode = new_res + new_pol + new_rate + print(f"[VideoMode][VideoChangeDetect]1 new_mode:{new_mode}") if new_mode == "480p24" or new_mode == "576p24": - new_mode = config.av.autores_480p24.value + new_mode = config.av.fixres_480p24.value if new_mode == "720p24": - new_mode = config.av.autores_720p24.value + new_mode = config.av.fixres_720p24.value if new_mode == "1080p24": - new_mode = config.av.autores_1080p24.value + new_mode = config.av.fixres_1080p24.value if new_mode == "1080p25": - new_mode = config.av.autores_1080p25.value + new_mode = config.av.fixres_1080p25.value if new_mode == "1080p30": - new_mode = config.av.autores_1080p30.value + new_mode = config.av.fixres_1080p30.value if new_mode == "2160p24": - new_mode = config.av.autores_2160p24.value + new_mode = config.av.fixres_2160p24.value if new_mode == "2160p25" or new_mode == "2160p50": - new_mode = config.av.autores_2160p25.value + new_mode = config.av.fixres_2160p25.value if new_mode == "2160p30" or new_mode == "2160p60" or new_mode == "2160p": - new_mode = config.av.autores_2160p30.value - elif new_res + new_pol in iAV.readAvailableModes(): + new_mode = config.av.fixres_2160p30.value + elif new_res + new_pol in SystemInfo["AvailableVideomodes"]: new_mode = new_res + new_pol + print(f"[VideoMode][VideoChangeDetect]2 new_mode:{new_mode}") if new_mode == "2160p30" or new_mode == "2160p60" or new_mode == "2160p": - new_mode = config.av.autores_2160p30.value + new_mode = config.av.fixres_2160p30.value else: new_mode = config_mode + new_rate + print(f"[VideoMode][VideoChangeDetect]3 new_mode:{new_mode}") write_mode = new_mode - elif config.av.autores.value == "hd" and int(new_res) <= 576: - if (config.av.autores_deinterlace.value and HardwareInfo().is_nextgen()) or (config.av.autores_deinterlace.value and not HardwareInfo().is_nextgen() and not config.av.autores_sd.value == "1080i"): - new_mode = config.av.autores_sd.value.replace("i", "p") + new_rate + print(f"[VideoMode][VideoChangeDetect]4 write_mode:{write_mode}, new_mode:{new_mode}") + elif config.av.fixres.value == "hd" and int(new_res) <= 576: + print("f[VideoMode][VideoChangeDetect] config.av.fixres.value = HD and less than 720:{config.av.fixres.value}") + if (config.av.fixres_deinterlace.value and HardwareInfo().is_nextgen()) or (config.av.fixres_deinterlace.value and not HardwareInfo().is_nextgen() and not config.av.fixres_sd.value == "1080i"): + new_mode = config.av.fixres_sd.value.replace("i", "p") + new_rate else: if new_pol in "p": - new_mode = config.av.autores_sd.value.replace("i", "p") + new_rate + new_mode = config.av.fixres_sd.value.replace("i", "p") + new_rate else: - new_mode = config.av.autores_sd.value + new_rate + new_mode = config.av.fixres_sd.value + new_rate if new_mode == "720p24": - new_mode = config.av.autores_720p24.value + new_mode = config.av.fixres_720p24.value if new_mode == "1080p24": - new_mode = config.av.autores_1080p24.value + new_mode = config.av.fixres_1080p24.value if new_mode == "1080p25": - new_mode = config.av.autores_1080p25.value + new_mode = config.av.fixres_1080p25.value if new_mode == "1080p30": - new_mode = config.av.autores_1080p30.value + new_mode = config.av.fixres_1080p30.value if new_mode == "2160p24": - new_mode = config.av.autores_2160p24.value + new_mode = config.av.fixres_2160p24.value if new_mode == "2160p25": - new_mode = config.av.autores_2160p25.value + new_mode = config.av.fixres_2160p25.value if new_mode == "2160p30": - new_mode = config.av.autores_2160p30.value + new_mode = config.av.fixres_2160p30.value write_mode = new_mode else: if video_rate == 25000: # videomode_25hz is not in proc and will be reset 2nd pass thru , so do it now. new_rate = 50 - if path.exists("%s_%shz" % (videomode, new_rate)) and config_rate == "multi": - try: # gbuhd4k/gbue4k sometimes will 1st time fail on open - with open("%s_%shz" % (videomode, new_rate), "r") as fd: - multi_videomode = fd.read().replace("\n", "") - if multi_videomode and (current_mode != multi_videomode): - write_mode = multi_videomode - else: - write_mode = current_mode - except IOError: + print(f"[VideoMode][VideoChangeDetect] else: video_rate:{video_rate}, new_rate:{new_rate}") + if path.exists(f"{videomode}_{new_rate}hz") and config_rate in ("multi", "auto"): + print(f"[VideoMode][VideoChangeDetect] path exists in proc: video_rate:{video_rate}, new_rate:{new_rate}, config_rate:{config_rate}") + with open(f"{videomode}_{new_rate}hz", "r") as fd: + multi_videomode = fd.read().replace("\n", "") + print(f"[VideoMode][VideoChangeDetect]1 multi_videomode:{multi_videomode}, current_mode:{current_mode}") + if multi_videomode and (current_mode != multi_videomode): + write_mode = multi_videomode + print(f"[VideoMode][VideoChangeDetect]2 write_mode:{write_mode}, multi_videomode:{multi_videomode}") + else: write_mode = current_mode - if write_mode and current_mode != write_mode: - resolutionlabel["restxt"].setText(_("Video mode: %s") % write_mode) - if config.av.autores.value != "disabled" and config.av.autores_label_timeout.value != "0": + print(f"[VideoMode][VideoChangeDetect]3 write_mode:{write_mode}, current_mode:{current_mode}") + print(f"[VideoMode][VideoChangeDetect]5 write_mode: {write_mode} current_mode: {current_mode}") + if write_mode and current_mode != write_mode or self.firstrun: + resolutionlabel["restxt"].setText(_(f"Video mode: {write_mode}")) + if config.av.fixres_label_timeout.value != "0": resolutionlabel.show() - print("[VideoMode] setMode - port: %s, mode: %s" % (config.av.videoport.value, write_mode)) - with open(videomode, "w+") as fd: - fd.write(write_mode) - # read_mode = fd.read().replace("\n", "") - # print("[VideoMode] fd.write_mode, read_mode", write_mode, " ", read_mode) - + print(f"[VideoMode] setMode - port: {config.av.videoport.value}, mode: {write_mode}") + avSwitch.setVideoMode(write_mode) + read_mode = avSwitch.getVideoMode("") + print(f"[VideoMode]3 fd.write_mode:{write_mode}, read_mode:{read_mode}") + else: + print(f"[VideoMode][VideoChangeDetect]6 VideoMode not changed write_mode: {write_mode} current_mode: {current_mode}") + resolutionlabel["restxt"].setText(_("Video mode: %s not available") % write_mode) + self.delay = False + self.detecttimer.stop() + self.firstrun = False iAV.setAspect(config.av.aspect) iAV.setWss(config.av.wss) iAV.setPolicy43(config.av.policy_43) iAV.setPolicy169(config.av.policy_169) - self.delay = False - self.detecttimer.stop() def autostart(session): global resolutionlabel - if not isPluginInstalled("AutoResolution"): - if resolutionlabel is None: - resolutionlabel = session.instantiateDialog(AutoVideoModeLabel) - AutoVideoMode(session) - else: - config.av.autores.setValue(False) - config.av.autores.save() - configfile.save() + print("[VideoMode][autostart] forceVideoMode entered") + if resolutionlabel is None: + resolutionlabel = session.instantiateDialog(forceVideoModeLabel) + forceVideoMode(session) From 5c0a327b7db547e0405902b47e74dcdfc8f778d5 Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Tue, 6 Feb 2024 11:59:17 +0100 Subject: [PATCH 120/183] [StartEnigma et al] call AVSwitch after StartEnigma initialisation --- data/videowizard.xml | 4 +- lib/python/Screens/InfoBarGenerics.py | 12 ++-- lib/python/Screens/Standby.py | 18 +++-- lib/python/Screens/UserInterfacePositioner.py | 6 +- lib/python/Screens/VideoWizard.py | 66 ++++++++++--------- lib/python/StartEnigma.py | 6 +- 6 files changed, 63 insertions(+), 49 deletions(-) diff --git a/data/videowizard.xml b/data/videowizard.xml index b3ddecba61a..8cdabf2da6b 100644 --- a/data/videowizard.xml +++ b/data/videowizard.xml @@ -1,5 +1,6 @@ +from Components.AVSwitch import iAVSwitch as avSwitch self.condition = len(self.listInputChannels()) > 1 @@ -42,7 +43,8 @@ self.selectKey("DOWN") -self.hw.saveMode(self.port, self.mode, self.rate) +from Components.AVSwitch import iAVSwitch as avSwitch +avSwitch.saveMode(self.port, self.mode, self.rate) from Components.config import configfile configfile.save() self.markDone() diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py index b35c2da2704..c9e15840b58 100644 --- a/lib/python/Screens/InfoBarGenerics.py +++ b/lib/python/Screens/InfoBarGenerics.py @@ -739,14 +739,14 @@ def doDimming(self): def unDimming(self): self.unDimmingTimer.stop() - self.doWriteAlpha(config.av.osd_alpha.value) + self.doWriteAlpha(config.misc.osd_alpha.value) def doWriteAlpha(self, value): if fileExists("/proc/stb/video/alpha"): f = open("/proc/stb/video/alpha", "w") f.write("%i" % (value)) f.close() - if value == config.av.osd_alpha.value: + if value == config.misc.osd_alpha.value: self.lastResetAlpha = True else: self.lastResetAlpha = False @@ -849,14 +849,14 @@ def doTimerHide(self): def doHide(self): if self.__state != self.STATE_HIDDEN: if self.dimmed > 0: - self.doWriteAlpha((config.av.osd_alpha.value * self.dimmed / config.usage.show_infobar_dimming_speed.value)) + self.doWriteAlpha((config.misc.osd_alpha.value * self.dimmed / config.usage.show_infobar_dimming_speed.value)) self.DimmingTimer.start(5, True) else: self.DimmingTimer.stop() self.hide() elif self.__state == self.STATE_HIDDEN and self.secondInfoBarScreen and self.secondInfoBarScreen.shown: if self.dimmed > 0: - self.doWriteAlpha((config.av.osd_alpha.value * self.dimmed / config.usage.show_infobar_dimming_speed.value)) + self.doWriteAlpha((config.misc.osd_alpha.value * self.dimmed / config.usage.show_infobar_dimming_speed.value)) self.DimmingTimer.start(5, True) else: self.DimmingTimer.stop() @@ -871,7 +871,7 @@ def doHide(self): self.EventViewIsShown = False # elif hasattr(self, "pvrStateDialog"): # if self.dimmed > 0: - # self.doWriteAlpha((config.av.osd_alpha.value*self.dimmed/config.usage.show_infobar_dimming_speed.value)) + # self.doWriteAlpha((config.misc.osd_alpha.value*self.dimmed/config.usage.show_infobar_dimming_speed.value)) # self.DimmingTimer.start(5, True) # else: # self.DimmingTimer.stop() @@ -932,7 +932,7 @@ def lockShow(self): def unlockShow(self): if config.usage.show_infobar_do_dimming.value and self.lastResetAlpha is False: - self.doWriteAlpha(config.av.osd_alpha.value) + self.doWriteAlpha(config.misc.osd_alpha.value) try: self.__locked -= 1 except: diff --git a/lib/python/Screens/Standby.py b/lib/python/Screens/Standby.py index c1b050ce245..a232e54ab7d 100644 --- a/lib/python/Screens/Standby.py +++ b/lib/python/Screens/Standby.py @@ -1,10 +1,9 @@ from os import path from time import time -from enigma import eDVBVolumecontrol, eTimer, eDVBLocalTimeHandler, eServiceReference, eStreamServer, iRecordableService, quitMainloop +from enigma import eAVSwitch, eDVBVolumecontrol, eTimer, eDVBLocalTimeHandler, eServiceReference, eStreamServer, iRecordableService, quitMainloop from Components.ActionMap import ActionMap -from Components.AVSwitch import AVSwitch from Components.config import config from Components.Console import Console import Components.ParentalControl @@ -61,7 +60,6 @@ def leaveMute(self): def __init__(self, session): Screen.__init__(self, session) self.skinName = "Standby" - self.avswitch = AVSwitch() print("[Standby] enter standby") @@ -114,9 +112,9 @@ def __init__(self, session): self.infoBarInstance and hasattr(self.infoBarInstance, "showPiP") and self.infoBarInstance.showPiP() if SystemInfo["ScartSwitch"]: - self.avswitch.setInput("SCART") + self.setInput("SCART") else: - self.avswitch.setInput("AUX") + self.setInput("AUX") if SystemInfo["brand"] in ('dinobot') or SystemInfo["HasHiSi"] or SystemInfo["boxtype"] in ("sfx6008", "sfx6018"): try: open("/proc/stb/hdmi/output", "w").write("off") @@ -141,7 +139,7 @@ def __onClose(self): self.session.nav.playService(self.prev_running_service) self.session.screen["Standby"].boolean = False globalActionMap.setEnabled(True) - self.avswitch.setInput("ENCODER") + self.setInput("ENCODER") self.leaveMute() if path.exists("/usr/scripts/standby_leave.sh"): Console().ePopen("/usr/scripts/standby_leave.sh") @@ -161,6 +159,14 @@ def stopService(self): self.prev_running_service = eServiceReference(config.tv.lastservice.value) self.session.nav.stopService() + def setInput(self, input): + INPUT = { + "ENCODER": 0, + "SCART": 1, + "AUX": 2 + } + eAVSwitch.getInstance().setInput(INPUT[input]) + class Standby(Standby2): def __init__(self, session): diff --git a/lib/python/Screens/UserInterfacePositioner.py b/lib/python/Screens/UserInterfacePositioner.py index 9cca94abd89..91d39cab265 100644 --- a/lib/python/Screens/UserInterfacePositioner.py +++ b/lib/python/Screens/UserInterfacePositioner.py @@ -40,7 +40,7 @@ def InitOsd(): config.osd.dst_top = ConfigSelectionNumber(default=0, stepwidth=1, min=0, max=576, wraparound=False) config.osd.dst_height = ConfigSelectionNumber(default=576, stepwidth=1, min=0, max=576, wraparound=False) config.osd.alpha = ConfigSelectionNumber(default=255, stepwidth=1, min=0, max=255, wraparound=False) - config.av.osd_alpha = NoSave(ConfigNumber(default=255)) + config.misc.osd_alpha = NoSave(ConfigNumber(default=255)) config.osd.threeDmode = ConfigSelection([("off", _("Off")), ("auto", _("Auto")), ("sidebyside", _("Side by Side")), ("topandbottom", _("Top and Bottom"))], "auto") config.osd.threeDznorm = ConfigSlider(default=50, increment=1, limits=(0, 100)) config.osd.show3dextensions = ConfigYesNo(default=False) @@ -97,7 +97,7 @@ def setOSDHeight(configElement): def setOSDAlpha(configElement): if SystemInfo["CanChangeOsdAlpha"]: print('[UserInterfacePositioner] Setting OSD alpha:', str(configElement.value)) - config.av.osd_alpha.setValue(configElement.value) + config.misc.osd_alpha.setValue(configElement.value) f = open("/proc/stb/video/alpha", "w") f.write(str(configElement.value)) f.close() @@ -158,6 +158,7 @@ def welcomeAction(self, answer): if self.restoreService not in self.onClose: self.onClose.append(self.restoreService) self.ConsoleB.ePopen('/usr/bin/showiframe /usr/share/enigma2/hd-testcard.mvi') + # config.osd.alpha.setValue(155) else: self.close() @@ -212,6 +213,7 @@ def __onClose(self): # This is called by the Wizard... def run(self): + # config.osd.alpha.setValue(self.alpha) config.osd.dst_left.save() config.osd.dst_width.save() config.osd.dst_top.save() diff --git a/lib/python/Screens/VideoWizard.py b/lib/python/Screens/VideoWizard.py index 53b1eac08f0..59c4e545d35 100644 --- a/lib/python/Screens/VideoWizard.py +++ b/lib/python/Screens/VideoWizard.py @@ -1,14 +1,10 @@ +from Components.config import config, ConfigBoolean, configfile +from Components.Pixmap import Pixmap +from Components.SystemInfo import SystemInfo, BoxInfo +from Screens.Rc import Rc from Screens.Wizard import WizardSummary from Screens.WizardLanguage import WizardLanguage -from Screens.Rc import Rc -from Components.AVSwitch import iAVSwitch as iAV - -from Components.Pixmap import Pixmap -from Components.config import config, ConfigBoolean, configfile -from Components.SystemInfo import SystemInfo - from Tools.Directories import resolveFilename, SCOPE_SKIN, SCOPE_CURRENT_SKIN -# from Tools.HardwareInfo import HardwareInfo config.misc.showtestcard = ConfigBoolean(default=False) @@ -49,14 +45,18 @@ class VideoWizard(WizardLanguage, Rc): """ def __init__(self, session): - # FIXME anyone knows how to use relative paths from the plugin's directory? self.xmlfile = resolveFilename(SCOPE_SKIN, "videowizard.xml") - self.hw = iAV # needed by VideoWizard.xml do not change WizardLanguage.__init__(self, session, showSteps=False, showStepSlider=False) Rc.__init__(self) + from Components.AVSwitch import iAVSwitch as avSwitch + self.avSwitch = avSwitch self["wizard"] = Pixmap() self["portpic"] = Pixmap() - + self.hasDVI = BoxInfo.getItem("dvi", False) + self.hasJack = BoxInfo.getItem("avjack", False) + self.hasRCA = BoxInfo.getItem("rca", False) + self.hasSCART = BoxInfo.getItem("scart", False) + self.portCount = 0 self.port = None self.mode = None self.rate = None @@ -66,20 +66,22 @@ def createSummary(self): return VideoWizardSummary def markDone(self): - iAV.saveMode(self.port, self.mode, self.rate) + self.avSwitch.saveMode(self.port, self.mode, self.rate) config.misc.videowizardenabled.value = 0 config.misc.videowizardenabled.save() configfile.save() def listInputChannels(self): - # hw_type = HardwareInfo().get_device_name() - # has_hdmi = HardwareInfo().has_hdmi() list = [] - for port in iAV.getPortList(): - if iAV.isPortUsed(port): + for port in self.avSwitch.getPortList(): + if self.avSwitch.isPortUsed(port): descr = port - if descr == "Scart" and not SystemInfo["hasScart"]: - continue + if descr == "HDMI" and self.hasDVI: + descr = "DVI" + if descr == "Scart" and self.hasRCA and not self.hasSCART: + descr = "RCA" + if descr == "Scart" and self.hasJack and not self.hasSCART: + descr = "Jack" if port != "DVI-PC": list.append((descr, port)) list.sort(key=lambda x: x[0]) @@ -92,8 +94,6 @@ def inputSelectionMade(self, index): self.inputSelect(index) def inputSelectionMoved(self): - # hw_type = HardwareInfo().get_device_name() - # has_hdmi = HardwareInfo().has_hdmi() print("[VideoWizard] input selection moved:", self.selection) self.inputSelect(self.selection) if self["portpic"].instance is not None: @@ -106,17 +106,17 @@ def inputSelectionMoved(self): def inputSelect(self, port): print("[VideoWizard] inputSelect:", port) - modeList = iAV.getModeList(self.selection) + modeList = self.avSwitch.getModeList(self.selection) print("[VideoWizard] modeList:", modeList) self.port = port if len(modeList) > 0: ratesList = self.listRates(modeList[0][0]) - iAV.setMode(port=port, mode=modeList[0][0], rate=ratesList[0][0]) + self.avSwitch.setMode(port=port, mode=modeList[0][0], rate=ratesList[0][0]) def listModes(self): list = [] print("[VideoWizard] modes for port", self.port) - for mode in iAV.getModeList(self.port): + for mode in self.avSwitch.getModeList(self.port): # if mode[0] != "PC": list.append((mode[0], mode[0])) print("[VideoWizard] modeslist:", list) @@ -135,20 +135,22 @@ def modeSelect(self, mode): ratesList = self.listRates(mode) print("[VideoWizard] ratesList:", ratesList) if self.port == "HDMI" and mode in ("720p", "1080i", "1080p", "2160p"): - self.rate = "multi" - iAV.setMode(port=self.port, mode=mode, rate="multi") + self.rate = "auto" + self.avSwitch.setMode(port=self.port, mode=mode, rate="auto") else: - iAV.setMode(port=self.port, mode=mode, rate=ratesList[0][0]) + self.avSwitch.setMode(port=self.port, mode=mode, rate=ratesList[0][0]) def listRates(self, querymode=None): if querymode is None: querymode = self.mode list = [] print("[VideoWizard] modes for port", self.port, "and mode", querymode) - for mode in iAV.getModeList(self.port): + for mode in self.avSwitch.getModeList(self.port): print("[VideoWizard] mode:", mode) if mode[0] == querymode: for rate in mode[1]: + if rate == "auto" and not SystemInfo["Has24hz"]: + continue if self.port == "DVI-PC": print("[VideoWizard] rate:", rate) if rate == "640x480": @@ -167,7 +169,7 @@ def rateSelectionMoved(self): self.rateSelect(self.selection) def rateSelect(self, rate): - iAV.setMode(port=self.port, mode=self.mode, rate=rate) + self.avSwitch.setMode(port=self.port, mode=self.mode, rate=rate) def showTestCard(self, selection=None): if selection is None: @@ -181,12 +183,12 @@ def showTestCard(self, selection=None): def keyNumberGlobal(self, number): if number in (1, 2, 3): if number == 1: - iAV.saveMode("HDMI", "720p", "multi") + self.avSwitch.saveMode("HDMI", "720p", "multi") elif number == 2: - iAV.saveMode("HDMI", "1080i", "multi") + self.avSwitch.saveMode("HDMI", "1080i", "multi") elif number == 3: - iAV.saveMode("Scart", "Multi", "multi") - iAV.setConfiguredMode() + self.avSwitch.saveMode("Scart", "Multi", "multi") + self.avSwitch.setConfiguredMode() self.close() WizardLanguage.keyNumberGlobal(self, number) diff --git a/lib/python/StartEnigma.py b/lib/python/StartEnigma.py index 99ac6df74aa..e12d86760e3 100644 --- a/lib/python/StartEnigma.py +++ b/lib/python/StartEnigma.py @@ -368,8 +368,10 @@ def runNextScreen(session, screensToRun, *result): session.scart = AutoScartControl(session) profile("Init:AutoVideoMode") - import Screens.VideoMode - Screens.VideoMode.autostart(session) + from Tools.Directories import isPluginInstalled # noqa: E402 don't move this import + if config.av.fixres.value != "disabled" and not isPluginInstalled("AutoResolution"): + import Screens.VideoMode + Screens.VideoMode.autostart(session) profile("RunReactor") profile_final() From d3720d6744fb3b4154018a1347c94d2648813866 Mon Sep 17 00:00:00 2001 From: Orlandoxx <95180049+Orlandoxx@users.noreply.github.com> Date: Wed, 7 Feb 2024 19:22:22 +0200 Subject: [PATCH 121/183] Updated Finnish (fi.po) translation. Added/changed Videomode translations. --- po/fi.po | 46 +++++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/po/fi.po b/po/fi.po index e5ce1c3c353..c9a16d3df49 100644 --- a/po/fi.po +++ b/po/fi.po @@ -5,7 +5,7 @@ msgstr "" "Project-Id-Version: enigma2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-12-27 23:35+0000\n" -"PO-Revision-Date: 2024-02-04 16:46+0200\n" +"PO-Revision-Date: 2024-02-07 19:20+0200\n" "Last-Translator: Orlandox\n" "Language-Team: timoj/Kojo/Samzam/Orlandox\n" "Language: fi\n" @@ -3167,14 +3167,14 @@ msgstr "Muuta toiston ja viiveen asetuksia?" msgid "Change step size" msgstr "Muuta askelkokoa" -msgid "Change the Colordepth for UHD" -msgstr "Vaihda UHD:n värisyvyyttä" +msgid "Change the Colordepth for UHD - this may cause unexpected results or black screen" +msgstr "Muuta UHD:n värisyvyyttä - tämä voi aiheuttaa odottamattomia tuloksia tai mustan ruudun" -msgid "Change the Colorimetry for HDR" -msgstr "Vaihda HDR:n väriavaruutta" +msgid "Change the Colorimetry for HDR - this may cause unexpected results or black screen" +msgstr "Muuta HDR:n kolorimetriaa - tämä voi aiheuttaa odottamattomia tuloksia tai mustan ruudun" -msgid "Change the Colorspace from Auto to RGB" -msgstr "Vaihda väriavaruus automaattisesta RGB:ksi" +msgid "Change Colorspace setting - this may cause unexpected results or black screen" +msgstr "Muuta väriavaruusasetusta - tämä voi aiheuttaa odottamattomia tuloksia tai mustan ruudun" msgid "Channel" msgstr "Kanava" @@ -3797,8 +3797,8 @@ msgstr "Määrittää mahdolliset taaksepäinkelauksen nopeudet." msgid "Configure the primary EPG language." msgstr "Määrittää ensisijaisen ohjelmaoppaan kielen." -msgid "Configure the refresh rate of the screen. Multi means refresh rate depends on the source 24/50/60Hz" -msgstr "Määritä näytön virkistystaajuus. Multi tarkoittaa vaihtelevaa taajuutta ohjelmalähteen mukaan: 24/50/60Hz" +msgid "Configure screen refresh rate. Multi & Auto rates depend on the source 24/50/60Hz" +msgstr "Määritä näytön virkistystaajuus. Multi & Auto -taajuudet riippuvat lähteestä 24/50/60Hz" msgid "Configure the second audio language." msgstr "Määrittää toissijaisen äänen kielen." @@ -6622,7 +6622,7 @@ msgstr "Kiintolevyn asetukset" msgid "HDMI" msgstr "HDMI" -msgid "HDMI Colordepth" +msgid "HDMI Color depth" msgstr "HDMI Värisyvyys" msgid "HDMI Colorimetry" @@ -7411,7 +7411,7 @@ msgid "Is this setting ok?" msgstr "Käytä näitä asetuksia?" msgid "Is this video mode ok?" -msgstr "Otetaanko tämä video-tila käyttöön?" +msgstr "Otetaanko tämä videotila käyttöön?" msgid "Isle of Man" msgstr "Isle of Man" @@ -11795,7 +11795,7 @@ msgid "Select video input with up/down buttons" msgstr "Valitse video-sisäänmeno ylös/alas-näppäimillä" msgid "Select video mode" -msgstr "Valitse video-tila" +msgstr "Valitse videotila" msgid "Select whether your SCR device is externally powered." msgstr "Valitse onko SCR-laitteesi jännite syötetty ulkoisesti." @@ -12216,7 +12216,7 @@ msgid "Show 2160p 30fps as" msgstr "Näytä 2160p 30fps näin:" msgid "Show 480/576p 24fps as" -msgstr "Näytä 1080p 24fps näin:" +msgstr "Näytä 480/576p 24fps näin:" msgid "Show 720p 24fps as" msgstr "Näytä 720p 24fps näin:" @@ -13543,7 +13543,7 @@ msgstr "" "Suomenkielinen käännös: timoj, Kojo, Samzam, Orlandox\n" "\n" "Ylläpito : Orlandox\n" -"--- 04.02.2024 ---\n" +"--- 07.02.2024 ---\n" "\n" "http://www.huoltovalikko.com" @@ -13986,7 +13986,7 @@ msgid "This option allows you to choose how to display 720p 24Hz on your TV. (as msgstr "Tämä asetus määrittää kuinka 720p 24Hz näytetään sinun TV:ssä. (koska kaikki TV:t eivät suoraan tue tätä resoluutiota)" msgid "This option allows you to choose how to display SD progressive 24Hz on your TV. (as not all TV's support these resolutions)" -msgstr "Tämä asetus määrittää kuinka SD-kuva 24Hz näytetään. (koska kaikki TV:t eivät suoraan tue tätä resoluutiota)" +msgstr "Tämä asetus määrittää kuinka SD progressiivinen 24Hz näytetään. (koska kaikki TV:t eivät suoraan tue tätä resoluutiota)" msgid "This option allows you to choose how to display elapsed time. As + or -" msgstr "Tämä asetus määrittää kuinka kulunut aika näytetään. Joko + tai -" @@ -15114,11 +15114,11 @@ msgstr "" "Seuraavaa tuloporttia tutkitaan automaattisesti 10 sekunnin kuluttua." msgid "Video mode selection." -msgstr "Video-tilan valinta." +msgstr "Videotilan valinta." #, python-format msgid "Video mode: %s" -msgstr "Video-tila: %s" +msgstr "Videotila: %s" msgid "Video output" msgstr "Video-ulostulo" @@ -19360,3 +19360,15 @@ msgstr "Pakettilistan lataus" msgid "Loading the package list. Please wait..." msgstr "Ladataan pakettilistaa. Odota..." + +msgid "Force resolution override*" +msgstr "Pakota resoluution ohitus*" + +msgid "Only use if you must force the output resolution - otherwise select 'Refresh Rate = auto'" +msgstr "Käytä vain, jos sinun täytyy pakottaa ulostuloresoluutio - muussa tapauksessa valitse 'Virkistystaajuus = auto'" + +msgid "Show resolution label" +msgstr "\"Näytä resoluutiotieto" + +msgid "Video mode: %s not available" +msgstr "Videotila: %s ei ole käytettävissä" From 63340bb646dabf9d59183d21553202c6c397ac09 Mon Sep 17 00:00:00 2001 From: Orlandoxx <95180049+Orlandoxx@users.noreply.github.com> Date: Wed, 7 Feb 2024 19:25:40 +0200 Subject: [PATCH 122/183] Update fi.po Changed all 'Colorimetry' translations. --- po/fi.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/po/fi.po b/po/fi.po index c9a16d3df49..27eae0f4052 100644 --- a/po/fi.po +++ b/po/fi.po @@ -6626,7 +6626,7 @@ msgid "HDMI Color depth" msgstr "HDMI Värisyvyys" msgid "HDMI Colorimetry" -msgstr "HDMI Väriavaruus" +msgstr "HDMI Kolorimetria" msgid "HDMI Colorspace" msgstr "HDMI Väriavaruus" From ddc3cba1b3d1b99c0350807b0df3f79ba27900f1 Mon Sep 17 00:00:00 2001 From: Tony Whalley Date: Thu, 8 Feb 2024 08:57:05 +0100 Subject: [PATCH 123/183] [AVSwitch] - fix preferred modes --- lib/python/Components/AVSwitch.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/python/Components/AVSwitch.py b/lib/python/Components/AVSwitch.py index ffd32c077a6..9e03e5cdcc6 100644 --- a/lib/python/Components/AVSwitch.py +++ b/lib/python/Components/AVSwitch.py @@ -94,10 +94,9 @@ def readAvailableModes(self): # print(f"[AVSwitch][readAvailableModes] {SystemInfo['AvailableVideomodes']}") def readPreferredModes(self): - modes = [] - modes = eAVSwitch.getInstance().getPreferredModes(1) + self.modes_preferred = eAVSwitch.getInstance().getPreferredModes(1) # print("[AVSwitch] reading preferred modes", modes) - if not modes: + if not self.modes_preferred: self.modes_preferred = SystemInfo["AvailableVideomodes"] print(f"[AVSwitch][readPreferredModes]none, so using {self.modes_preferred}") if self.modes_preferred != self.last_modes_preferred: From 8a16ef6b3b92a4929c1fa1a395d5edd634d99c4d Mon Sep 17 00:00:00 2001 From: Huevos Date: Fri, 9 Feb 2024 00:43:13 +0100 Subject: [PATCH 124/183] [ImageManager] move to index ... When flashing an image on a multiboot capable receiver a MessageBox asks which slot. Preselect the current slot. --- lib/python/Plugins/SystemPlugins/ViX/ImageManager.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/python/Plugins/SystemPlugins/ViX/ImageManager.py b/lib/python/Plugins/SystemPlugins/ViX/ImageManager.py index a952ffb7279..51b9aa341c6 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/ImageManager.py +++ b/lib/python/Plugins/SystemPlugins/ViX/ImageManager.py @@ -527,9 +527,15 @@ def keyRestore1(self): imagedict = GetImagelist() choices = [] currentimageslot = SystemInfo["MultiBootSlot"] - for x in imagedict.keys(): + idx = 0 + for i, x in enumerate(imagedict.keys()): choices.append(((_("slot%s %s - %s (current image)") if x == currentimageslot else _("slot%s %s - %s")) % (x, SystemInfo["canMultiBoot"][x]["slotname"], imagedict[x]["imagename"]), (x))) - self.session.openWithCallback(self.keyRestore2, MessageBox, message, list=choices, default=False, simple=True) + if x == currentimageslot: + idx = i + dialog = self.session.openWithCallback(self.keyRestore2, MessageBox, message, list=choices, default=False, simple=True) + if idx: + dialog["list"].moveToIndex(idx) + def keyRestore2(self, retval): if retval: From c965a73724af9a4b0b207b41b81e3093f15811da Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Thu, 8 Feb 2024 23:45:24 +0000 Subject: [PATCH 125/183] PEP8 double aggressive E301 ~ E306 --- lib/python/Plugins/SystemPlugins/ViX/ImageManager.py | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/python/Plugins/SystemPlugins/ViX/ImageManager.py b/lib/python/Plugins/SystemPlugins/ViX/ImageManager.py index 51b9aa341c6..86177145059 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/ImageManager.py +++ b/lib/python/Plugins/SystemPlugins/ViX/ImageManager.py @@ -536,7 +536,6 @@ def keyRestore1(self): if idx: dialog["list"].moveToIndex(idx) - def keyRestore2(self, retval): if retval: if SystemInfo["canMultiBoot"]: From 7d19429bc71007048aaf35674f219828ab865510 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Thu, 8 Feb 2024 23:45:34 +0000 Subject: [PATCH 126/183] PEP8 double aggressive W291 ~ W293 and W391 --- lib/python/Plugins/SystemPlugins/ViX/ImageManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/Plugins/SystemPlugins/ViX/ImageManager.py b/lib/python/Plugins/SystemPlugins/ViX/ImageManager.py index 86177145059..c1f14e77cb1 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/ImageManager.py +++ b/lib/python/Plugins/SystemPlugins/ViX/ImageManager.py @@ -535,7 +535,7 @@ def keyRestore1(self): dialog = self.session.openWithCallback(self.keyRestore2, MessageBox, message, list=choices, default=False, simple=True) if idx: dialog["list"].moveToIndex(idx) - + def keyRestore2(self, retval): if retval: if SystemInfo["canMultiBoot"]: From 24d4645ad4faf8e00d2b095d3cf79b0b4cc4c440 Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Fri, 9 Feb 2024 16:02:41 +0100 Subject: [PATCH 127/183] [AVSwitch] - add support for AutoResolution plugin --- lib/python/Components/AVSwitch.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/python/Components/AVSwitch.py b/lib/python/Components/AVSwitch.py index 9e03e5cdcc6..eb5846a38e2 100644 --- a/lib/python/Components/AVSwitch.py +++ b/lib/python/Components/AVSwitch.py @@ -5,6 +5,7 @@ from Components.config import ConfigBoolean, ConfigEnableDisable, ConfigNothing, ConfigSelection, ConfigSelectionNumber, ConfigSlider, ConfigSubDict, ConfigSubsection, ConfigYesNo, NoSave, config from Components.SystemInfo import SystemInfo from Tools.CList import CList +from Tools.Directories import isPluginInstalled # from Tools.HardwareInfo import HardwareInfo config.av = ConfigSubsection() @@ -92,6 +93,8 @@ def readAvailableModes(self): SystemInfo["AvailableVideomodes"] = [] SystemInfo["AvailableVideomodes"] = eAVSwitch.getInstance().readAvailableModes().split(" ") # print(f"[AVSwitch][readAvailableModes] {SystemInfo['AvailableVideomodes']}") + if isPluginInstalled("AutoResolution"): + return SystemInfo["AvailableVideomodes"] def readPreferredModes(self): self.modes_preferred = eAVSwitch.getInstance().getPreferredModes(1) From e5e6e43fdb37a27c71770c7cd3440d3d7177f24c Mon Sep 17 00:00:00 2001 From: openvix-build Date: Fri, 9 Feb 2024 18:10:17 +0000 Subject: [PATCH 128/183] openvix: developer 6.5.001.001 --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index 71bdd9974f0..9bbcef222ce 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1234,3 +1234,4 @@ openvix: developer 6.4.012.001 openvix: developer 6.4.012.002 openvix: developer 6.4.012.003 openvix: developer 6.4.012.004 +openvix: developer 6.5.001.001 From 8974262307d02dad18b2447674fadff756165d53 Mon Sep 17 00:00:00 2001 From: Gordon Lack Date: Sat, 10 Feb 2024 19:11:43 +0000 Subject: [PATCH 129/183] Add "Show packages" option in one more place. --- lib/python/Screens/SoftwareUpdate.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/python/Screens/SoftwareUpdate.py b/lib/python/Screens/SoftwareUpdate.py index 112f146877f..9c61e708efa 100644 --- a/lib/python/Screens/SoftwareUpdate.py +++ b/lib/python/Screens/SoftwareUpdate.py @@ -361,6 +361,7 @@ def startActualUpgrade(self, answer): if not self.ImageBackupDone and not config.softwareupdate.autoimagebackup.value and config.imagemanager.backuplocation.value: choices.append((_("Perform a full image backup"), "imagebackup")) choices.append((_("Update channel list only"), "channels")) + choices.append((_("Show packages to be updated"), "showlist")) choices.append((_("Cancel"), "")) self["actions"].setEnabled(True) upgrademessage = self.session.openWithCallback(self.startActualUpgrade, UpdateChoices, text=message, list=choices, skin_name="SoftwareUpdateChoices", var=self.trafficLight) From dc70cf1dfad37902cb92ec07195b644dae85eac6 Mon Sep 17 00:00:00 2001 From: Huevos Date: Sun, 11 Feb 2024 00:00:36 +0100 Subject: [PATCH 130/183] [ViX-plugin] simplify embedded skins --- .../SystemPlugins/ViX/BackupManager.py | 35 ++----------- .../Plugins/SystemPlugins/ViX/IPKInstaller.py | 30 +---------- .../Plugins/SystemPlugins/ViX/ImageManager.py | 50 +------------------ .../Plugins/SystemPlugins/ViX/MountManager.py | 26 +--------- .../SystemPlugins/ViX/PackageManager.py | 21 +++----- .../SystemPlugins/ViX/SoftcamManager.py | 17 +------ .../Plugins/SystemPlugins/ViX/SwapManager.py | 17 +------ lib/python/Plugins/SystemPlugins/ViX/ui.py | 5 +- 8 files changed, 19 insertions(+), 182 deletions(-) diff --git a/lib/python/Plugins/SystemPlugins/ViX/BackupManager.py b/lib/python/Plugins/SystemPlugins/ViX/BackupManager.py index bd5540665e3..2d87b5e4923 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/BackupManager.py +++ b/lib/python/Plugins/SystemPlugins/ViX/BackupManager.py @@ -139,12 +139,7 @@ def BackupManagerautostart(reason, session=None, **kwargs): class VIXBackupManager(Screen): skin = [""" - - - - - - + @@ -155,12 +150,6 @@ class VIXBackupManager(Screen): """, 560, 400, # screen - 0, 0, 140, 40, # colors - 140, 0, 140, 40, - 280, 0, 140, 40, - 0, 0, 140, 40, 20, - 140, 0, 140, 40, 20, - 280, 0, 140, 40, 20, 0, 45, 35, 25, # menu key 40, 45, 35, 25, # info key 0, 50, 560, 50, 18, # lab1 @@ -760,21 +749,10 @@ def Stage6(self, result=None, retval=None, extra_args=None): class BackupSelection(Screen): skin = [""" - - - - - - + """, 560, 400, # screen - 0, 0, 140, 40, # colors - 140, 0, 140, 40, - 280, 0, 140, 40, - 0, 0, 140, 40, 20, - 140, 0, 140, 40, 20, - 280, 0, 140, 40, 20, 5, 50, 550, 250, 25, 19, ] # noqa: E124 @@ -862,17 +840,10 @@ def closeRecursive(self): class XtraPluginsSelection(Screen): skin = [""" - - - - + """, 560, 400, # screen - 0, 0, 140, 40, # red - 140, 0, 140, 40, # green - 0, 0, 140, 40, 20, # red - 140, 0, 140, 40, 20, # green 5, 50, 550, 250, 25, 19, ] # noqa: E124 diff --git a/lib/python/Plugins/SystemPlugins/ViX/IPKInstaller.py b/lib/python/Plugins/SystemPlugins/ViX/IPKInstaller.py index a57f3b732b1..a767a19c7e7 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/IPKInstaller.py +++ b/lib/python/Plugins/SystemPlugins/ViX/IPKInstaller.py @@ -18,12 +18,7 @@ class VIXIPKInstaller(Screen): skin = [""" - - - - - - + @@ -31,12 +26,6 @@ class VIXIPKInstaller(Screen): """, 560, 400, # screen - 0, 0, 140, 40, # colors - 140, 0, 140, 40, - 280, 0, 140, 40, - 0, 0, 140, 40, 20, - 140, 0, 140, 40, 20, - 280, 0, 140, 40, 20, 0, 50, 560, 50, 18, # lab1 10, 105, 540, 260, 20, # list 26, @@ -165,27 +154,12 @@ def myclose(self): class IpkgInstaller(Screen): skin = [""" - - - - - - - - + """, 560, 450, # screen - 0, 0, 140, 40, # colors - 140, 0, 140, 40, - 280, 0, 140, 40, - 420, 0, 140, 40, - 0, 0, 140, 40, 20, - 140, 0, 140, 40, 20, - 280, 0, 140, 40, 20, - 420, 0, 140, 40, 20, 5, 50, 540, 360, 20, # list 0, 410, 560, 2, 5, 420, 550, 30, 22, diff --git a/lib/python/Plugins/SystemPlugins/ViX/ImageManager.py b/lib/python/Plugins/SystemPlugins/ViX/ImageManager.py index c1f14e77cb1..020ff6645c7 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/ImageManager.py +++ b/lib/python/Plugins/SystemPlugins/ViX/ImageManager.py @@ -134,14 +134,7 @@ class tmp: class VIXImageManager(Screen): skin = [""" - - - - - - - - + @@ -151,14 +144,6 @@ class VIXImageManager(Screen): """, 560, 400, # screen - 0, 0, 140, 40, # colors - 140, 0, 140, 40, - 280, 0, 140, 40, - 420, 0, 140, 40, - 0, 0, 140, 40, 20, - 140, 0, 140, 40, 20, - 280, 0, 140, 40, 20, - 420, 0, 140, 40, 20, 0, 45, 35, 25, # menu key 0, 50, 560, 50, 18, # lab1 10, 105, 540, 260, 20, # list @@ -873,14 +858,7 @@ def doBackup(self, answer): class ImageBackup(Screen): skin = [""" - - - - - - - - + @@ -888,14 +866,6 @@ class ImageBackup(Screen): """, 560, 400, # screen - 0, 0, 140, 40, # colors - 140, 0, 140, 40, - 280, 0, 140, 40, - 420, 0, 140, 40, - 0, 0, 140, 40, 20, - 140, 0, 140, 40, 20, - 280, 0, 140, 40, 20, - 420, 0, 140, 40, 20, 0, 50, 560, 50, 18, # lab1 10, 105, 540, 260, 20, # list 26, @@ -1569,14 +1539,6 @@ def BackupComplete(self, answer=None): class ImageManagerDownload(Screen): skin = [""" - - - - - - - - @@ -1584,14 +1546,6 @@ class ImageManagerDownload(Screen): """, 560, 400, # screen - 0, 0, 140, 40, # colors - 140, 0, 140, 40, - 280, 0, 140, 40, - 420, 0, 140, 40, - 0, 0, 140, 40, 20, - 140, 0, 140, 40, 20, - 280, 0, 140, 40, 20, - 420, 0, 140, 40, 20, 0, 50, 560, 50, 18, # lab1 10, 105, 540, 260, 20, # list 26, diff --git a/lib/python/Plugins/SystemPlugins/ViX/MountManager.py b/lib/python/Plugins/SystemPlugins/ViX/MountManager.py index 9006fe4364a..b477a5d5bfa 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/MountManager.py +++ b/lib/python/Plugins/SystemPlugins/ViX/MountManager.py @@ -200,14 +200,7 @@ class VIXDevicesPanel(Screen): - - - - - - - - + """, 560, 495, # screen 10, 50, 540, 400, # Listbox @@ -217,14 +210,6 @@ class VIXDevicesPanel(Screen): 24, 20, # fonts 80, 10, 10, 540, 425, 25, - 0, 0, 140, 40, # colors - 140, 0, 140, 40, - 280, 0, 140, 40, - 420, 0, 140, 40, - 0, 0, 140, 40, 20, - 140, 0, 140, 40, 20, - 280, 0, 140, 40, 20, - 420, 0, 140, 40, 20, ] # noqa: E124 def __init__(self, session): @@ -362,18 +347,11 @@ def addFstab(self, result=None, retval=None, extra_args=None): class DeviceMountSetup(Screen, ConfigListScreen): skin = [""" - - - - + """, 560, 450, # screen - 0, 0, 140, 40, # colors - 140, 0, 140, 40, - 0, 0, 140, 40, 20, - 140, 0, 140, 40, 20, 0, 50, 560, 275, 26, 20, # config 0, 365, 560, 20, 18, ] # noqa: E124 diff --git a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py index a276b7adfb4..746e3c8cebd 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py +++ b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py @@ -24,10 +24,7 @@ def __init__(self, session, parent): class PackageManager(Screen): skin = [""" - - - - + {"template": [ @@ -42,16 +39,12 @@ class PackageManager(Screen): """, - 530, 420, # Screen - 0, 0, 140, 40, # colours - 140, 0, 140, 40, - 0, 0, 140, 40, 20, - 140, 0, 140, 40, 20, - 5, 50, 520, 365, # list - 5, 1, 440, 28, # template - 5, 26, 440, 20, - 445, 2, 48, 48, - 5, 50, 510, 2, + 560, 420, # Screen + 5, 50, 550, 365, # list + 5, 1, 470, 28, # template + 5, 26, 470, 20, + 475, 2, 48, 48, + 5, 50, 540, 2, 22, 14, # font 52, # itemHeight ] diff --git a/lib/python/Plugins/SystemPlugins/ViX/SoftcamManager.py b/lib/python/Plugins/SystemPlugins/ViX/SoftcamManager.py index dc78b2a36e2..30bcf119716 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/SoftcamManager.py +++ b/lib/python/Plugins/SystemPlugins/ViX/SoftcamManager.py @@ -79,14 +79,7 @@ def spinnerSkin(skinName): class VIXSoftcamManager(Screen): skin = [""" - - - - - - - - + @@ -98,14 +91,6 @@ class VIXSoftcamManager(Screen): """, 560, 400, # screen - 0, 0, 140, 40, # colors - 140, 0, 140, 40, - 280, 0, 140, 40, - 420, 0, 140, 40, - 0, 0, 140, 40, 20, - 140, 0, 140, 40, 20, - 280, 0, 140, 40, 20, - 420, 0, 140, 40, 20, 0, 45, 35, 25, # menu key 40, 45, 35, 25, # info key 40, 110, 170, 20, 22, # lab1 diff --git a/lib/python/Plugins/SystemPlugins/ViX/SwapManager.py b/lib/python/Plugins/SystemPlugins/ViX/SwapManager.py index 1f5a2d21917..bded79762c7 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/SwapManager.py +++ b/lib/python/Plugins/SystemPlugins/ViX/SwapManager.py @@ -87,14 +87,7 @@ def startSwap2(self, result=None, retval=None, extra_args=None): # lets find sw class VIXSwap(Screen): skin = [""" - - - - - - - - + @@ -107,14 +100,6 @@ class VIXSwap(Screen): """, 560, 250, # screen - 0, 0, 140, 40, # colors - 140, 0, 140, 40, - 280, 0, 140, 40, - 420, 0, 140, 40, - 0, 0, 140, 40, 20, - 140, 0, 140, 40, 20, - 280, 0, 140, 40, 20, - 420, 0, 140, 40, 20, 10, 50, 32, 32, # lock off 10, 50, 32, 32, # lock on 50, 50, 360, 30, 20, diff --git a/lib/python/Plugins/SystemPlugins/ViX/ui.py b/lib/python/Plugins/SystemPlugins/ViX/ui.py index f7cee81dcd1..15ef978c7e9 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/ui.py +++ b/lib/python/Plugins/SystemPlugins/ViX/ui.py @@ -10,8 +10,7 @@ class VIXMenu(Screen, ProtectedScreen): skin = [""" - - + {"template": [ @@ -35,8 +34,6 @@ class VIXMenu(Screen, ProtectedScreen): """, 610, 410, # screen - 0, 0, 140, 40, # key red image - 0, 0, 140, 40, 20, # key red text 15, 60, 330, 286, # first menu Listbox 2, 0, 330, 26, # template one 22, # fonts From d324fff22691b61bf9bbc5f519d42ca0c0b994e6 Mon Sep 17 00:00:00 2001 From: openvix-build Date: Sun, 11 Feb 2024 10:42:35 +0000 Subject: [PATCH 131/183] openvix: developer 6.5.001.002 --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index 9bbcef222ce..76d48750e2c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1235,3 +1235,4 @@ openvix: developer 6.4.012.002 openvix: developer 6.4.012.003 openvix: developer 6.4.012.004 openvix: developer 6.5.001.001 +openvix: developer 6.5.001.002 From c6765ba229764f05d64eb99c48a1de84308b42e4 Mon Sep 17 00:00:00 2001 From: Tony Whalley Date: Sat, 10 Feb 2024 10:03:41 +0100 Subject: [PATCH 132/183] [VideoMode] - remove AutoResolution - use plugin --- lib/python/Screens/VideoMode.py | 316 +------------------------------- lib/python/StartEnigma.py | 6 - 2 files changed, 1 insertion(+), 321 deletions(-) diff --git a/lib/python/Screens/VideoMode.py b/lib/python/Screens/VideoMode.py index e575c39c30c..4a5ce2d41bc 100644 --- a/lib/python/Screens/VideoMode.py +++ b/lib/python/Screens/VideoMode.py @@ -1,31 +1,10 @@ -from os import path -from enigma import iPlayableService, iServiceInformation, eTimer, eServiceCenter, eServiceReference, eDVBDB, eAVSwitch +from enigma import eAVSwitch from Components.AVSwitch import iAVSwitch as iAV from Components.config import config, getConfigListEntry -from Components.Label import Label -from Components.ServiceEventTracker import ServiceEventTracker from Components.SystemInfo import SystemInfo -from Screens.ChannelSelection import FLAG_IS_DEDICATED_3D from Screens.MessageBox import MessageBox -from Screens.Screen import Screen from Screens.Setup import Setup -from Tools.Directories import isPluginInstalled -from Tools.HardwareInfo import HardwareInfo - -resolutionlabel = None -previous = None -isDedicated3D = False -videomode = "/proc/stb/video/videomode" - - -def getConfig_videomode(getmode, getrate): - port = config.av.videoport.value - mode = getmode[port].value - res = mode.replace("p30", "p")[:-1] - pol = mode.replace("p30", "p")[-1:] - rate = getrate[mode].value.replace("Hz", "") - return port, mode, res, pol, rate class VideoSetup(Setup): @@ -91,24 +70,6 @@ def createSetup(self): self.list.append(getConfigListEntry(_("HDR10 Support"), config.av.hdr10_support, _("Enable or disable to force HDR10 Modes for UHD"))) self.list.append(getConfigListEntry(_("Allow 12bit"), config.av.allow_12bit, _("Enable or disable the 12 Bit Color Mode"))) self.list.append(getConfigListEntry(_("Allow 10bit"), config.av.allow_10bit, _("Enable or disable the 10 Bit Color Mode"))) - if config.av.videoport.value in ("HDMI", "YPbPr", "Scart-YPbPr") and not isPluginInstalled("AutoResolution"): - self.list.append(getConfigListEntry(_("Force resolution override*"), config.av.fixres, _("Only use if you must force the output resolution - otherwise select 'Refresh Rate = auto'"))) - if config.av.fixres.value in ("all", "hd"): - self.list.append(getConfigListEntry(_("Force de-interlace"), config.av.fixres_deinterlace, _("If enabled the video will always be de-interlaced."))) - self.list.append(getConfigListEntry(_("Show resolution label"), config.av.fixres_label_timeout, _("Allows you to adjust the amount of time the resolution infomation display on screen."))) - if config.av.fixres.value in ("hd"): - self.list.append(getConfigListEntry(_("Show SD as"), config.av.fixres_sd, _("This option allows you to choose how to display standard defintion video on your TV."))) - self.list.append(getConfigListEntry(_("Show 480/576p 24fps as"), config.av.fixres_480p24, _("This option allows you to choose how to display SD progressive 24Hz on your TV. (as not all TV's support these resolutions)"))) - self.list.append(getConfigListEntry(_("Show 720p 24fps as"), config.av.fixres_720p24, _("This option allows you to choose how to display 720p 24Hz on your TV. (as not all TVs support these resolutions)"))) - self.list.append(getConfigListEntry(_("Show 1080p 24fps as"), config.av.fixres_1080p24, _("This option allows you to choose how to display 1080p 24Hz on your TV. (as not all TVs support these resolutions)"))) - self.list.append(getConfigListEntry(_("Show 1080p 25fps as"), config.av.fixres_1080p25, _("This option allows you to choose how to display 1080p 25Hz on your TV. (as not all TVs support these resolutions)"))) - self.list.append(getConfigListEntry(_("Show 1080p 30fps as"), config.av.fixres_1080p30, _("This option allows you to choose how to display 1080p 30Hz on your TV. (as not all TVs support these resolutions)"))) - if "2160p24" in SystemInfo["AvailableVideomodes"]: - self.list.append(getConfigListEntry(_("Show 2160p 24fps as"), config.av.fixres_2160p24, _("This option allows you to choose how to display 2160p 24Hz on your TV. (as not all TVs support these resolutions)"))) - self.list.append(getConfigListEntry(_("Show 2160p 25fps as"), config.av.fixres_2160p25, _("This option allows you to choose how to display 2160p 25Hz on your TV. (as not all TVs support these resolutions)"))) - self.list.append(getConfigListEntry(_("Show 2160p 30fps as"), config.av.fixres_2160p30, _("This option allows you to choose how to display 2160p 30Hz on your TV. (as not all TVs support these resolutions)"))) - if config.av.fixres.value in ("all", "hd") and config.av.videorate[config.av.videomode[config.av.videoport.value].value].value == "multi": - self.list.append(getConfigListEntry(_("Delay time"), config.av.fixres_delay, _("Set the time before checking video source for resolution/refresh rate infomation."))) if level >= 1: if SystemInfo["CanDownmixAC3"]: self.list.append(getConfigListEntry(_("AC3 downmix"), config.av.downmix_ac3, _("Choose whether multi channel ac3 sound tracks should be downmixed to stereo."))) @@ -176,278 +137,3 @@ def keySave(self): self.session.openWithCallback(self.confirm, MessageBox, _("Is this video mode ok?"), MessageBox.TYPE_YESNO, timeout=20, default=False) else: Setup.keySave(self) - - -class forceVideoModeLabel(Screen): - def __init__(self, session): - Screen.__init__(self, session) - self["content"] = Label() - self["restxt"] = Label() - self.hideTimer = eTimer() - self.hideTimer.callback.append(self.hide) - self.onShow.append(self.hide_me) - - def hide_me(self): - idx = config.av.fixres_label_timeout.index - if idx: - idx += 4 - self.hideTimer.start(idx * 1000, True) - - -def applySettings(mode=config.osd.threeDmode.value, znorm=int(config.osd.threeDznorm.value)): - global previous, isDedicated3D - mode = isDedicated3D and mode == "auto" and "sidebyside" or mode - mode == "3dmode" in SystemInfo["3DMode"] and mode or mode == "sidebyside" and "sbs" or mode == "topandbottom" and "tab" or "off" - if previous != (mode, znorm): - try: - open(SystemInfo["3DMode"], "w").write(mode) - open(SystemInfo["3DZNorm"], "w").write("%d" % znorm) - previous = (mode, znorm) - except Exception: - return - - -class forceVideoMode(Screen): - def __init__(self, session): - Screen.__init__(self, session) - print("[VideoMode][forceVideoMode] Entered") - self.current3dmode = config.osd.threeDmode.value - self.__event_tracker = ServiceEventTracker(screen=self, eventmap={ - iPlayableService.evStart: self.__evStart, - iPlayableService.evVideoSizeChanged: self.VideoChanged, - iPlayableService.evVideoProgressiveChanged: self.VideoChanged, - iPlayableService.evVideoFramerateChanged: self.VideoChanged, - # iPlayableService.evBuffering: self.evBuffering, - # iPlayableService.evEnd: self.VideoChanged, - # iPlayableService.evSeekableStatusChanged: self.VideoChanged, - # iPlayableService.evCuesheetChanged: self.VideoChanged, - # iPlayableService.evUpdatedInfo: self.VideoChanged, - # iPlayableService.evUpdatedEventInfo: self.evUpdatedEventInfo, - # iPlayableService.evEOF: self.evEOF, - # iPlayableService.evSOF: self.evSOF, - # iPlayableService.evGstreamerPlayStarted: self.evGstreamerPlayStarted, - - }) - - self.firstrun = True - self.delay = False - self.bufferfull = True - self.detecttimer = eTimer() - self.detecttimer.callback.append(self.VideoChangeDetect) - - def checkIfDedicated3D(self): - print("[VideoMode][checkIfDedicated3D] Entered") - service = self.session.nav.getCurrentlyPlayingServiceReference() - servicepath = service and service.getPath() - if servicepath and servicepath.startswith("/"): - if service.toString().startswith("1:"): - info = eServiceCenter.getInstance().info(service) - service = info and info.getInfoString(service, iServiceInformation.sServiceref) - return service and eDVBDB.getInstance().getFlag(eServiceReference(service)) & FLAG_IS_DEDICATED_3D == FLAG_IS_DEDICATED_3D and "sidebyside" - else: - return ".3d." in servicepath.lower() and "sidebyside" or ".tab." in servicepath.lower() and "topandbottom" - service = self.session.nav.getCurrentService() - info = service and service.info() - return info and info.getInfo(iServiceInformation.sIsDedicated3D) == 1 and "sidebyside" - - def __evStart(self): - if config.osd.threeDmode.value == "auto": - global isDedicated3D - isDedicated3D = self.checkIfDedicated3D() - if isDedicated3D: - applySettings(isDedicated3D) - else: - applySettings() - self.VideoChanged() - - def BufferInfo(self): - bufferInfo = self.session.nav.getCurrentService().streamed().getBufferCharge() - if bufferInfo[0] > 98: - self.bufferfull = True - self.VideoChanged() - else: - self.bufferfull = False - - def BufferInfoStop(self): - self.bufferfull = True - - def VideoChanged(self): - if config.av.fixres.value == "disabled": - print("[VideoMode] autoresolution is disabled - resolution not changed !") - return - else: - print("[VideoMode][VideoChanged] Entered") - if self.session.nav.getCurrentlyPlayingServiceReference() and not self.session.nav.getCurrentlyPlayingServiceReference().toString().startswith("4097:"): - delay = config.av.fixres_delay.value - else: - delay = config.av.fixres_delay.value * 2 - if not self.detecttimer.isActive() and not self.delay: - self.delay = True - else: - self.delay = True - self.detecttimer.stop() - - self.detecttimer.start(delay) - - def VideoChangeDetect(self): - print("[VideoMode][VideoChangeDetect] Entered") - global resolutionlabel - avSwitch = eAVSwitch.getInstance() - config_port, config_mode, config_res, config_pol, config_rate = getConfig_videomode(config.av.videomode, config.av.videorate) - current_mode = avSwitch.getVideoMode("") - if current_mode.upper() in ("PAL", "NTSC"): - current_mode = current_mode.upper() - print(f"[VideoMode][VideoChangeDetect]2 current_mode:{current_mode} config_port:{config_port}, config_mode:{config_mode}, config_res:{config_res}, config_pol:{config_pol}, config_rate:{config_rate}") - - video_height = avSwitch.getResolutionY(0) - video_width = avSwitch.getResolutionX(0) - video_pol = "p" if avSwitch.getProgressive() else "i" - video_rate = avSwitch.getFrameRate(0) - print(f"[VideoMode][VideoChangeDetect]1 video_height:{video_height}, video_width:{video_width}, video_pol:{video_pol}, video_rate:{video_rate}") - if not video_height or not video_width or not video_pol or not video_rate: - info = None if self.session.nav.getCurrentService() is None else self.session.nav.getCurrentService().info() - if info: - video_height = int(info.getInfo(iServiceInformation.sVideoHeight)) - video_width = int(info.getInfo(iServiceInformation.sVideoWidth)) - video_pol = ("i", "p")[info.getInfo(iServiceInformation.sProgressive)] - video_rate = int(info.getInfo(iServiceInformation.sFrameRate)) - print(f"[VideoMode][VideoChangeDetect]2 have info - video_height:{video_height}, video_width:{video_width}, video_pol:{video_pol}, video_rate:{video_rate}") - if video_height and video_width and video_pol and video_rate: - resolutionlabel["content"].setText(_("Video content: %ix%i%s %iHz") % (video_width, video_height, video_pol, (video_rate + 500) // 1000)) - if (1 < video_width <= 1024) and video_height <= 480 and video_rate in (23976, 24000, 25000, 29970, 50000, 59940): - new_res = "480" - elif (1 < video_width <= 1024) and video_height <= 576 and video_rate in (23976, 24000, 25000, 50000): - new_res = "576" - elif (video_width == 1280) and video_height <= 720: - new_res = "720" - elif (video_width == 1920) and video_height <= 1080: - new_res = "1080" - elif (video_width == 3840) and video_height > 1080: - new_res = "2160" - else: - print(f"[VideoMode][VideoChangeDetect]new_res = config_res:{config_res}") - new_res = config_res - print(f"[VideoMode][VideoChangeDetect]new_res:{new_res}, video_width:{video_width}, video_height:{video_height}, video_pol:{video_pol}, video_rate:{video_rate}") - if video_rate != -1: - print(f"[VideoMode][VideoChangeDetect]video_rate:{video_rate}") - if video_rate == 25000: - new_rate = 50000 - elif video_rate == 59940 or (video_rate == 29970 and video_pol == "i") or (video_rate == 29970 and video_pol == "p" and config.av.fixres.value == "disabled"): - new_rate = 60000 - elif video_rate == 23976: - new_rate = 24000 - elif video_rate == 29970: - new_rate = 30000 - else: - new_rate = video_rate - print(f"[VideoMode][VideoChangeDetect]new_rate:{new_rate} = video_rate:{video_rate}") - new_rate = str((new_rate + 500) // 1000) - else: - print(f"[VideoMode][VideoChangeDetect]new_rate = config_rate:{config_rate}") - new_rate = config_rate - new_pol = str(video_pol) if video_pol != -1 else config_pol - write_mode = new_mode = None - print(f"[VideoMode][VideoChangeDetect] new_pol:{new_pol} video_pol:{video_pol} config_pol:{config_pol} config_mode:{config_mode} config.av.fixres.value:{config.av.fixres.value}") - if config_mode in ("PAL", "NTSC"): - write_mode = config_mode - - elif config.av.fixres.value == "all" or (config.av.fixres.value == "hd" and int(new_res) >= 720): - print(f"[VideoMode][VideoChangeDetect] config.av.fixres.value = all or HD:{config.av.fixres.value}") - if (config.av.fixres_deinterlace.value and HardwareInfo().is_nextgen()) or (config.av.fixres_deinterlace.value and not HardwareInfo().is_nextgen() and int(new_res) <= 720): - new_pol = new_pol.replace("i", "p") - print(f"[VideoMode][VideoChangeDetect] new_res + new_pol + new_rate: {new_res + new_pol + new_rate}") - if new_res + new_pol + new_rate in SystemInfo["AvailableVideomodes"]: - new_mode = new_res + new_pol + new_rate - print(f"[VideoMode][VideoChangeDetect]1 new_mode:{new_mode}") - if new_mode == "480p24" or new_mode == "576p24": - new_mode = config.av.fixres_480p24.value - if new_mode == "720p24": - new_mode = config.av.fixres_720p24.value - if new_mode == "1080p24": - new_mode = config.av.fixres_1080p24.value - if new_mode == "1080p25": - new_mode = config.av.fixres_1080p25.value - if new_mode == "1080p30": - new_mode = config.av.fixres_1080p30.value - if new_mode == "2160p24": - new_mode = config.av.fixres_2160p24.value - if new_mode == "2160p25" or new_mode == "2160p50": - new_mode = config.av.fixres_2160p25.value - if new_mode == "2160p30" or new_mode == "2160p60" or new_mode == "2160p": - new_mode = config.av.fixres_2160p30.value - elif new_res + new_pol in SystemInfo["AvailableVideomodes"]: - new_mode = new_res + new_pol - print(f"[VideoMode][VideoChangeDetect]2 new_mode:{new_mode}") - if new_mode == "2160p30" or new_mode == "2160p60" or new_mode == "2160p": - new_mode = config.av.fixres_2160p30.value - else: - new_mode = config_mode + new_rate - print(f"[VideoMode][VideoChangeDetect]3 new_mode:{new_mode}") - write_mode = new_mode - print(f"[VideoMode][VideoChangeDetect]4 write_mode:{write_mode}, new_mode:{new_mode}") - elif config.av.fixres.value == "hd" and int(new_res) <= 576: - print("f[VideoMode][VideoChangeDetect] config.av.fixres.value = HD and less than 720:{config.av.fixres.value}") - if (config.av.fixres_deinterlace.value and HardwareInfo().is_nextgen()) or (config.av.fixres_deinterlace.value and not HardwareInfo().is_nextgen() and not config.av.fixres_sd.value == "1080i"): - new_mode = config.av.fixres_sd.value.replace("i", "p") + new_rate - else: - if new_pol in "p": - new_mode = config.av.fixres_sd.value.replace("i", "p") + new_rate - else: - new_mode = config.av.fixres_sd.value + new_rate - if new_mode == "720p24": - new_mode = config.av.fixres_720p24.value - if new_mode == "1080p24": - new_mode = config.av.fixres_1080p24.value - if new_mode == "1080p25": - new_mode = config.av.fixres_1080p25.value - if new_mode == "1080p30": - new_mode = config.av.fixres_1080p30.value - if new_mode == "2160p24": - new_mode = config.av.fixres_2160p24.value - if new_mode == "2160p25": - new_mode = config.av.fixres_2160p25.value - if new_mode == "2160p30": - new_mode = config.av.fixres_2160p30.value - write_mode = new_mode - else: - if video_rate == 25000: # videomode_25hz is not in proc and will be reset 2nd pass thru , so do it now. - new_rate = 50 - print(f"[VideoMode][VideoChangeDetect] else: video_rate:{video_rate}, new_rate:{new_rate}") - if path.exists(f"{videomode}_{new_rate}hz") and config_rate in ("multi", "auto"): - print(f"[VideoMode][VideoChangeDetect] path exists in proc: video_rate:{video_rate}, new_rate:{new_rate}, config_rate:{config_rate}") - with open(f"{videomode}_{new_rate}hz", "r") as fd: - multi_videomode = fd.read().replace("\n", "") - print(f"[VideoMode][VideoChangeDetect]1 multi_videomode:{multi_videomode}, current_mode:{current_mode}") - if multi_videomode and (current_mode != multi_videomode): - write_mode = multi_videomode - print(f"[VideoMode][VideoChangeDetect]2 write_mode:{write_mode}, multi_videomode:{multi_videomode}") - else: - write_mode = current_mode - print(f"[VideoMode][VideoChangeDetect]3 write_mode:{write_mode}, current_mode:{current_mode}") - print(f"[VideoMode][VideoChangeDetect]5 write_mode: {write_mode} current_mode: {current_mode}") - if write_mode and current_mode != write_mode or self.firstrun: - resolutionlabel["restxt"].setText(_(f"Video mode: {write_mode}")) - if config.av.fixres_label_timeout.value != "0": - resolutionlabel.show() - print(f"[VideoMode] setMode - port: {config.av.videoport.value}, mode: {write_mode}") - avSwitch.setVideoMode(write_mode) - read_mode = avSwitch.getVideoMode("") - print(f"[VideoMode]3 fd.write_mode:{write_mode}, read_mode:{read_mode}") - else: - print(f"[VideoMode][VideoChangeDetect]6 VideoMode not changed write_mode: {write_mode} current_mode: {current_mode}") - resolutionlabel["restxt"].setText(_("Video mode: %s not available") % write_mode) - self.delay = False - self.detecttimer.stop() - self.firstrun = False - iAV.setAspect(config.av.aspect) - iAV.setWss(config.av.wss) - iAV.setPolicy43(config.av.policy_43) - iAV.setPolicy169(config.av.policy_169) - - -def autostart(session): - global resolutionlabel - print("[VideoMode][autostart] forceVideoMode entered") - if resolutionlabel is None: - resolutionlabel = session.instantiateDialog(forceVideoModeLabel) - forceVideoMode(session) diff --git a/lib/python/StartEnigma.py b/lib/python/StartEnigma.py index e12d86760e3..5d5c562bc17 100644 --- a/lib/python/StartEnigma.py +++ b/lib/python/StartEnigma.py @@ -367,12 +367,6 @@ def runNextScreen(session, screensToRun, *result): # we need session.scart to access it from within menu.xml session.scart = AutoScartControl(session) - profile("Init:AutoVideoMode") - from Tools.Directories import isPluginInstalled # noqa: E402 don't move this import - if config.av.fixres.value != "disabled" and not isPluginInstalled("AutoResolution"): - import Screens.VideoMode - Screens.VideoMode.autostart(session) - profile("RunReactor") profile_final() runReactor() From 62e0bf439aac18bada6dd81470622c0848e0c8c5 Mon Sep 17 00:00:00 2001 From: Tony Whalley Date: Sat, 10 Feb 2024 10:07:44 +0100 Subject: [PATCH 133/183] [AVSwitch] - remove av fixres(AutoResolution) settings --- lib/python/Components/AVSwitch.py | 45 ------------------------------- 1 file changed, 45 deletions(-) diff --git a/lib/python/Components/AVSwitch.py b/lib/python/Components/AVSwitch.py index eb5846a38e2..3b3228792f3 100644 --- a/lib/python/Components/AVSwitch.py +++ b/lib/python/Components/AVSwitch.py @@ -345,51 +345,6 @@ def InitAVSwitch(): # when YUV is not enabled, don't let the user select it if config.av.yuvenabled.value: colorformat_choices["yuv"] = _("YPbPr") - config.av.fixres = ConfigSelection(choices={"disabled": _("Disabled"), "all": _("All resolutions"), "hd": _("only HD")}, default="disabled") - choicelist = [] - for i in range(5, 16): - choicelist.append(("%d" % i, ngettext("%d second", "%d seconds", i) % i)) - config.av.fixres_label_timeout = ConfigSelection(default="5", choices=[("0", _("Not Shown"))] + choicelist) - config.av.fixres_delay = ConfigSelectionNumber(min=500, max=15000, stepwidth=500, default=500, wraparound=True) - config.av.fixres_deinterlace = ConfigYesNo(default=False) - config.av.fixres_sd = ConfigSelection(choices={ - "720p": _("720p"), - "1080i": _("1080i") - }, default="720p") - config.av.fixres_480p24 = ConfigSelection(choices={ - "480p24": _("480p 24Hz"), - "720p24": _("720p 24Hz"), - "1080p24": _("1080p 24Hz") - }, default="1080p24") - config.av.fixres_720p24 = ConfigSelection(choices={ - "720p24": _("720p 24Hz"), - "1080p24": _("1080p 24Hz") - }, default="1080p24") - config.av.fixres_1080p24 = ConfigSelection(choices={ - "1080p24": _("1080p 24Hz"), - "1080p25": _("1080p 25Hz") - }, default="1080p24") - config.av.fixres_1080p25 = ConfigSelection(choices={ - "1080p25": _("1080p 25Hz"), - "1080p50": _("1080p 50Hz") - }, default="1080p25") - config.av.fixres_1080p30 = ConfigSelection(choices={ - "1080p30": _("1080p 30Hz"), - "1080p60": _("1080p 60Hz") - }, default="1080p30") - config.av.fixres_2160p24 = ConfigSelection(choices={ - "2160p24": _("2160p 24Hz"), - "2160p25": _("2160p 25Hz"), - "2160p30": _("2160p 30Hz") - }, default="2160p24") - config.av.fixres_2160p25 = ConfigSelection(choices={ - "2160p25": _("2160p 25Hz"), - "2160p50": _("2160p 50Hz") - }, default="2160p25") - config.av.fixres_2160p30 = ConfigSelection(choices={ - "2160p30": _("2160p 30Hz"), - "2160p60": _("2160p 60Hz") - }, default="2160p30") config.av.colorformat = ConfigSelection(choices=colorformat_choices, default="rgb") config.av.aspectratio = ConfigSelection(choices={ "4_3_letterbox": _("4:3 Letterbox"), From bb777fd4f0b0d91964df9113c083fc02dfc0add3 Mon Sep 17 00:00:00 2001 From: Tony Whalley Date: Sat, 10 Feb 2024 10:27:16 +0100 Subject: [PATCH 134/183] [VideoMode] - remove unused import --- lib/python/Screens/VideoMode.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/python/Screens/VideoMode.py b/lib/python/Screens/VideoMode.py index 4a5ce2d41bc..e445d915b92 100644 --- a/lib/python/Screens/VideoMode.py +++ b/lib/python/Screens/VideoMode.py @@ -1,5 +1,3 @@ -from enigma import eAVSwitch - from Components.AVSwitch import iAVSwitch as iAV from Components.config import config, getConfigListEntry from Components.SystemInfo import SystemInfo From 5d911c62cde3ef49dcf9cba81e64b997bbc28da2 Mon Sep 17 00:00:00 2001 From: openvix-build Date: Mon, 12 Feb 2024 21:31:48 +0000 Subject: [PATCH 135/183] openvix: developer 6.5.001.003 --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index 76d48750e2c..c6cda410583 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1236,3 +1236,4 @@ openvix: developer 6.4.012.003 openvix: developer 6.4.012.004 openvix: developer 6.5.001.001 openvix: developer 6.5.001.002 +openvix: developer 6.5.001.003 From 891f1ea3c013bdf0ec86fbc632fb89b767d15caf Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Tue, 13 Feb 2024 11:14:20 +0200 Subject: [PATCH 136/183] [Added] Rating icon renderer --- lib/python/Components/Renderer/RatingIcon.py | 48 ++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 lib/python/Components/Renderer/RatingIcon.py diff --git a/lib/python/Components/Renderer/RatingIcon.py b/lib/python/Components/Renderer/RatingIcon.py new file mode 100644 index 00000000000..e4a1289e8c2 --- /dev/null +++ b/lib/python/Components/Renderer/RatingIcon.py @@ -0,0 +1,48 @@ +from Components.Renderer.Renderer import Renderer +from Tools.Directories import SCOPE_GUISKIN, resolveFilename + +from enigma import ePixmap + + +class RatingIcon(Renderer): + def __init__(self): + Renderer.__init__(self) + self.small = 0 + + GUI_WIDGET = ePixmap + + def postWidgetCreate(self, instance): + self.changed((self.CHANGED_DEFAULT,)) + + def applySkin(self, desktop, parent): + attribs = self.skinAttributes[:] + for (attrib, value) in self.skinAttributes: + if attrib == "small": + if value == "1": + self.small = 1 + self.skinAttributes = attribs + rc = Renderer.applySkin(self, desktop, parent) + self.changed((self.CHANGED_DEFAULT,)) + return rc + + def changed(self, what): + if self.source and hasattr(self.source, "text") and self.instance: + if what[0] == self.CHANGED_CLEAR: + self.instance.setPixmap(None) + else: + if self.source.text: + age = int(self.source.text.replace("+", "")) + if age == 0: + self.instance.setPixmap(None) + self.instance.hide() + return + if age <= 15: + age += 3 + + pngEnding = "ratings/%d%s.png" % (age, "_s" if self.small else "" ) + print(pngEnding) + pngname = resolveFilename(SCOPE_GUISKIN, pngEnding) + self.instance.setPixmapFromFile(pngname) + self.instance.show() + else: + self.instance.setPixmap(None) From 69e3d60e979fbc8a1eaa94989159332800f5307b Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Tue, 13 Feb 2024 09:17:48 +0000 Subject: [PATCH 137/183] PEP8 double aggressive E20 and E211 --- lib/python/Components/Renderer/RatingIcon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/Components/Renderer/RatingIcon.py b/lib/python/Components/Renderer/RatingIcon.py index e4a1289e8c2..a9cf934eeb9 100644 --- a/lib/python/Components/Renderer/RatingIcon.py +++ b/lib/python/Components/Renderer/RatingIcon.py @@ -39,7 +39,7 @@ def changed(self, what): if age <= 15: age += 3 - pngEnding = "ratings/%d%s.png" % (age, "_s" if self.small else "" ) + pngEnding = "ratings/%d%s.png" % (age, "_s" if self.small else "") print(pngEnding) pngname = resolveFilename(SCOPE_GUISKIN, pngEnding) self.instance.setPixmapFromFile(pngname) From d286ff0f1e4cdd4f623a54061cb9e2214fb6bbb9 Mon Sep 17 00:00:00 2001 From: openvix-build Date: Wed, 14 Feb 2024 00:06:59 +0000 Subject: [PATCH 138/183] openvix: developer 6.5.001.004 --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index c6cda410583..636e928bef3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1237,3 +1237,4 @@ openvix: developer 6.4.012.004 openvix: developer 6.5.001.001 openvix: developer 6.5.001.002 openvix: developer 6.5.001.003 +openvix: developer 6.5.001.004 From f795965da48a263f007a104ab31a402bc2d2b667 Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Wed, 14 Feb 2024 16:54:21 +0100 Subject: [PATCH 139/183] [VideoMode] - prevent crash if Scart, tidy up --- lib/python/Screens/VideoMode.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/python/Screens/VideoMode.py b/lib/python/Screens/VideoMode.py index e445d915b92..0dc75f05da5 100644 --- a/lib/python/Screens/VideoMode.py +++ b/lib/python/Screens/VideoMode.py @@ -21,12 +21,9 @@ def stopHotplug(self): iAV.on_hotplug.remove(self.createSetup) def createSetup(self): - level = config.usage.setup_level.index self.list = [ getConfigListEntry(_("Video output"), config.av.videoport, _("Configures which video output connector will be used.")) ] - if config.av.videoport.value == "Scart": - config.av.fixres.value = "disabled" # if we have modes for this port: if config.av.videoport.value in config.av.videomode or config.av.videoport.value == "Scart": # add mode- and rate-selection: @@ -51,7 +48,7 @@ def createSetup(self): if config.av.videoport.value == "Scart": self.list.append(getConfigListEntry(_("Color format"), config.av.colorformat, _("Configure which color format should be used on the SCART output."))) - if level >= 1: + if config.usage.setup_level.index >= 1: self.list.append(getConfigListEntry(_("WSS on 4:3"), config.av.wss, _("When enabled, content with an aspect ratio of 4:3 will be stretched to fit the screen."))) if SystemInfo["ScartSwitch"]: self.list.append(getConfigListEntry(_("Auto scart switching"), config.av.vcrswitch, _("When enabled, your receiver will detect activity on the VCR SCART input."))) @@ -68,7 +65,7 @@ def createSetup(self): self.list.append(getConfigListEntry(_("HDR10 Support"), config.av.hdr10_support, _("Enable or disable to force HDR10 Modes for UHD"))) self.list.append(getConfigListEntry(_("Allow 12bit"), config.av.allow_12bit, _("Enable or disable the 12 Bit Color Mode"))) self.list.append(getConfigListEntry(_("Allow 10bit"), config.av.allow_10bit, _("Enable or disable the 10 Bit Color Mode"))) - if level >= 1: + if config.usage.setup_level.index >= 1: if SystemInfo["CanDownmixAC3"]: self.list.append(getConfigListEntry(_("AC3 downmix"), config.av.downmix_ac3, _("Choose whether multi channel ac3 sound tracks should be downmixed to stereo."))) if SystemInfo["CanDownmixDTS"]: From cb8bf14de5064619ad1821339ff50975112d6655 Mon Sep 17 00:00:00 2001 From: Huevos Date: Wed, 14 Feb 2024 23:11:13 +0100 Subject: [PATCH 140/183] [doc] update AUTOMATICBUTTONS --- doc/AUTOMATICBUTTONS | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/doc/AUTOMATICBUTTONS b/doc/AUTOMATICBUTTONS index fdefc5cf5b8..5f5c26d338f 100644 --- a/doc/AUTOMATICBUTTONS +++ b/doc/AUTOMATICBUTTONS @@ -24,13 +24,15 @@ in the screens correctly as if we had added them manually to every single screen alignment="left" zPosition="2" spacing="10" - spacingPixmapText="10" /> + spacingPixmapText="10" + buttonCornerRadius="6" /> Attributes: connection: comma separated list of the buttons this widget will control. pixmaps: comma separated list that contains "key_name" then a ":" then the path to the graphic to be used. spacing: is the spacing between the text and the next button. spacingPixmapText: is the spacing between the graphic and the text. + buttonCornerRadius (optional): add rounding to corners. By default the foreground text color will be the same as the default listbox text color. But this can be altered for each button with the "textColors" attribute. @@ -52,7 +54,8 @@ Example widget with colored text: alignment="left" zPosition="2" spacing="10" - spacingPixmapText="10" /> + spacingPixmapText="10" + buttonCornerRadius="6" /> It is also possible to have colored text and no graphics: @@ -67,7 +70,41 @@ It is also possible to have colored text and no graphics: transparent="1" alignment="left" zPosition="2" - spacing="10" /> + spacing="10" + buttonCornerRadius="6" /> + +Superimpose text over the graphic rather that have the graphic to the side of the text. + + + +Superimpose texted over a coloured background (no graphic). + + ========================================================================================================================================================================= From 9718d80db09b5881565df1d02ec98bc11331eff9 Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Wed, 14 Feb 2024 18:41:18 +0200 Subject: [PATCH 141/183] [Updated] CollorButtonSequence addon to support different render types --- lib/gui/elistboxcontent.cpp | 16 +++--- .../Components/Addons/ColorButtonsSequence.py | 52 ++++++++++++++++--- lib/python/Components/Converter/EventName.py | 2 +- lib/python/Components/MultiContent.py | 16 +++--- 4 files changed, 61 insertions(+), 25 deletions(-) diff --git a/lib/gui/elistboxcontent.cpp b/lib/gui/elistboxcontent.cpp index f33ef46e525..8f57923f081 100644 --- a/lib/gui/elistboxcontent.cpp +++ b/lib/gui/elistboxcontent.cpp @@ -1234,7 +1234,7 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c int cornerRadius = pCornerRadius ? PyLong_AsLong(pCornerRadius) : 0; int cornerEdges = pCornerEdges ? PyLong_AsLong(pCornerEdges) : 0; - if (cornerRadius || cornerEdges) + if (cornerRadius) bwidth = 0; // border not supported for rounded edges if (m_font.find(fnt) == m_font.end()) @@ -1247,14 +1247,14 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c painter.clip(rect); { - if(cornerRadius && (pbackColor || pbackColorSelected)) + if(cornerRadius && cornerEdges && (pbackColor || pbackColorSelected)) { + painter.setRadius(cornerRadius, cornerEdges); if(selected && !pbackColorSelected) pbackColorSelected = pbackColor; unsigned int color = PyLong_AsUnsignedLongMask(selected ? pbackColorSelected : pbackColor); painter.setBackgroundColor(gRGB(color)); - painter.setRadius(cornerRadius, cornerEdges); - painter.drawRectangle(itemRect); + painter.drawRectangle(rect); } else { @@ -1484,14 +1484,14 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c eRect rect(x, y, width, height); painter.clip(rect); - { + flags |= (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : (type == TYPE_PIXMAP_ALPHABLEND) ? gPainter::BT_ALPHABLEND : 0; + if(radius && edges) + painter.setRadius(radius, edges); + else { gRegion rc(rect); bool mustClear = (selected && pbackColorSelected) || (!selected && pbackColor); clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, m_itemsize, cursorValid, mustClear, isverticallb); } - flags |= (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : (type == TYPE_PIXMAP_ALPHABLEND) ? gPainter::BT_ALPHABLEND : 0; - if(radius && edges) - painter.setRadius(radius, edges); painter.blit(pixmap, rect, rect, flags); painter.clippop(); break; diff --git a/lib/python/Components/Addons/ColorButtonsSequence.py b/lib/python/Components/Addons/ColorButtonsSequence.py index 160d4218cec..23d25a90e8e 100644 --- a/lib/python/Components/Addons/ColorButtonsSequence.py +++ b/lib/python/Components/Addons/ColorButtonsSequence.py @@ -1,10 +1,10 @@ from Components.Addons.GUIAddon import GUIAddon -from enigma import eListbox, eListboxPythonMultiContent, BT_ALIGN_CENTER, RT_VALIGN_CENTER, RT_HALIGN_LEFT, eSize, getDesktop, gFont +from enigma import eListbox, eListboxPythonMultiContent, BT_ALIGN_CENTER, RT_VALIGN_CENTER, RT_HALIGN_LEFT, RT_HALIGN_CENTER, BT_SCALE, eSize, getDesktop, gFont from skin import parseScale, parseColor, parseFont, applySkinFactor -from Components.MultiContent import MultiContentEntryPixmapAlphaBlend +from Components.MultiContent import MultiContentEntryPixmapAlphaBlend, MultiContentEntryText from Components.Label import Label from Tools.Directories import resolveFilename, SCOPE_GUISKIN @@ -26,7 +26,9 @@ def __init__(self): self.colorIndicatorStyle = "pixmap" self.orientations = {"orHorizontal": eListbox.orHorizontal, "orVertical": eListbox.orVertical} self.orientation = eListbox.orHorizontal + self.renderType = "ImageTextRight" # Currently supported are ImageTextRight, ImageTextOver and ColorTextOver self.alignment = "left" + self.cornerRadius = 0 self.pixmaps = {} self.colors = {} self.textRenderer = Label("") @@ -62,9 +64,15 @@ def buildEntry(self, sequence): for x, val in sequence.items(): textColor = self.foreColor + buttonBgColor = self.foreColor + if x in self.colors: - textColor = parseColor(self.colors[x]).argb() - if x in self.pixmaps: + if self.renderType == "ImageTextRight": + textColor = parseColor(self.colors[x]).argb() + else: + buttonBgColor = parseColor(self.colors[x]).argb() + + if self.renderType != "ImageTextOver" and x in self.pixmaps: pic = LoadPixmap(resolveFilename(SCOPE_GUISKIN, self.pixmaps[x])) if pic: pixd_size = pic.size() @@ -92,11 +100,35 @@ def buildEntry(self, sequence): if textWidth < (minSectorWidth - self.spacingButtons - (self.spacingPixmapText if pic else 0) - pixd_width): textWidth = minSectorWidth - self.spacingButtons - (self.spacingPixmapText if pic else 0) - pixd_width if buttonText: - if textColor is not None: - res.append((eListboxPythonMultiContent.TYPE_TEXT, xPos, yPos, textWidth, height - 2, 0, RT_HALIGN_LEFT | RT_VALIGN_CENTER, buttonText, textColor)) + textFlags = RT_HALIGN_LEFT | RT_VALIGN_CENTER + textPaddings = 0 + backColor = None + if self.renderType in ["ColorTextOver", "ImageTextOver"]: + textFlags = RT_HALIGN_CENTER | RT_VALIGN_CENTER + textPaddings = self.spacingPixmapText + backColor = buttonBgColor + + if self.renderType == "ImageTextOver": + if x in self.pixmaps: + pic = LoadPixmap(resolveFilename(SCOPE_GUISKIN, self.pixmaps[x])) + if pic: + res.append(MultiContentEntryPixmapAlphaBlend( + pos=(xPos, yPos), + size=(textWidth + textPaddings*2, height), + png=pic, + backcolor=0x000000, backcolor_sel=None, flags=BT_SCALE, corner_radius=self.cornerRadius)) + res.append(MultiContentEntryText( + pos=(xPos + textPaddings, yPos), size=(textWidth, height - 2), + font=0, flags=textFlags, + text=buttonText, color=textColor, color_sel=textColor)) else: - res.append((eListboxPythonMultiContent.TYPE_TEXT, xPos, yPos, textWidth, height - 2, 0, RT_HALIGN_LEFT | RT_VALIGN_CENTER, buttonText)) - xPos += textWidth + self.spacingButtons + res.append(MultiContentEntryText( + pos=(xPos, yPos), size=(textWidth + textPaddings*2, height - 2), + font=0, flags=textFlags, + text=buttonText, color=textColor, color_sel=textColor, backcolor=backColor, corner_radius=self.cornerRadius)) + + + xPos += textWidth + textPaddings*2 + self.spacingButtons if xPos > width and self.layoutStyle != "fluid": self.layoutStyle = "fluid" return self.buildEntry(sequence) @@ -143,6 +175,10 @@ def applySkin(self, desktop, parent): self.foreColor = parseColor(value).argb() elif attrib == "textColors": self.colors = dict(item.split(':') for item in value.split(',')) + elif attrib == "buttonCornerRadius": + self.cornerRadius = parseScale(value) + elif attrib == "renderType": + self.renderType = value else: attribs.append((attrib, value)) self.skinAttributes = attribs diff --git a/lib/python/Components/Converter/EventName.py b/lib/python/Components/Converter/EventName.py index a38e3ea1988..26ec944b01a 100644 --- a/lib/python/Components/Converter/EventName.py +++ b/lib/python/Components/Converter/EventName.py @@ -285,7 +285,7 @@ def getText(self): if running_status in (6, 7): return _("Reserved for future use") return _("Undefined") - elif self.type in (self.NAME_NEXT, self.NAME_NEXT2) or (self.type >= self.NEXT_DESCRIPTION and not self.type == self.FORMAT_STRING): + elif self.type in (self.NAME_NEXT, self.NAME_NEXT2) or (self.type >= self.NEXT_DESCRIPTION and not self.type == self.FORMAT_STRING and not self.type == self.RAWRATING): try: reference = self.source.service info = reference and self.source.info diff --git a/lib/python/Components/MultiContent.py b/lib/python/Components/MultiContent.py index 8386f9108f6..de2f2fc7024 100644 --- a/lib/python/Components/MultiContent.py +++ b/lib/python/Components/MultiContent.py @@ -29,20 +29,20 @@ def MultiContentTemplateColor(n): return 0xff000000 | n -def MultiContentEntryText(pos=(0, 0), size=(0, 0), font=0, flags=RT_HALIGN_LEFT | RT_VALIGN_TOP, text="", color=None, color_sel=None, backcolor=None, backcolor_sel=None, border_width=None, border_color=None): - return eListboxPythonMultiContent.TYPE_TEXT, pos[0], pos[1], size[0], size[1], font, flags, text, __resolveColor(color), __resolveColor(color_sel), __resolveColor(backcolor), __resolveColor(backcolor_sel), border_width, __resolveColor(border_color) +def MultiContentEntryText(pos=(0, 0), size=(0, 0), font=0, flags=RT_HALIGN_LEFT | RT_VALIGN_TOP, text="", color=None, color_sel=None, backcolor=None, backcolor_sel=None, border_width=None, border_color=None, corner_radius=0, corner_edges=15): + return eListboxPythonMultiContent.TYPE_TEXT, pos[0], pos[1], size[0], size[1], font, flags, text, __resolveColor(color), __resolveColor(color_sel), __resolveColor(backcolor), __resolveColor(backcolor_sel), border_width, __resolveColor(border_color), corner_radius, corner_edges -def MultiContentEntryPixmap(pos=(0, 0), size=(0, 0), png=None, backcolor=None, backcolor_sel=None, flags=0): - return eListboxPythonMultiContent.TYPE_PIXMAP, pos[0], pos[1], size[0], size[1], __resolvePixmap(png), __resolveColor(backcolor), __resolveColor(backcolor_sel), flags +def MultiContentEntryPixmap(pos=(0, 0), size=(0, 0), png=None, backcolor=None, backcolor_sel=None, flags=0, corner_radius=0, corner_edges=15): + return eListboxPythonMultiContent.TYPE_PIXMAP, pos[0], pos[1], size[0], size[1], __resolvePixmap(png), __resolveColor(backcolor), __resolveColor(backcolor_sel), flags, corner_radius, corner_edges -def MultiContentEntryPixmapAlphaTest(pos=(0, 0), size=(0, 0), png=None, backcolor=None, backcolor_sel=None, flags=0): - return eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, pos[0], pos[1], size[0], size[1], __resolvePixmap(png), __resolveColor(backcolor), __resolveColor(backcolor_sel), flags +def MultiContentEntryPixmapAlphaTest(pos=(0, 0), size=(0, 0), png=None, backcolor=None, backcolor_sel=None, flags=0, corner_radius=0, corner_edges=15): + return eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, pos[0], pos[1], size[0], size[1], __resolvePixmap(png), __resolveColor(backcolor), __resolveColor(backcolor_sel), flags, corner_radius, corner_edges -def MultiContentEntryPixmapAlphaBlend(pos=(0, 0), size=(0, 0), png=None, backcolor=None, backcolor_sel=None, flags=0): - return eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, pos[0], pos[1], size[0], size[1], __resolvePixmap(png), __resolveColor(backcolor), __resolveColor(backcolor_sel), flags +def MultiContentEntryPixmapAlphaBlend(pos=(0, 0), size=(0, 0), png=None, backcolor=None, backcolor_sel=None, flags=0, corner_radius=0, corner_edges=15): + return eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, pos[0], pos[1], size[0], size[1], __resolvePixmap(png), __resolveColor(backcolor), __resolveColor(backcolor_sel), flags, corner_radius, corner_edges def MultiContentEntryProgress(pos=(0, 0), size=(0, 0), percent=None, borderWidth=None, foreColor=None, foreColorSelected=None, backColor=None, backColorSelected=None): From 7281825708a74b83b56dcd60f6c2d9358ae33a84 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Fri, 16 Feb 2024 09:35:49 +0000 Subject: [PATCH 142/183] PEP8 double aggressive E22, E224, E241, E242 and E27 --- lib/python/Components/Addons/ColorButtonsSequence.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/python/Components/Addons/ColorButtonsSequence.py b/lib/python/Components/Addons/ColorButtonsSequence.py index 23d25a90e8e..ff73d4b8072 100644 --- a/lib/python/Components/Addons/ColorButtonsSequence.py +++ b/lib/python/Components/Addons/ColorButtonsSequence.py @@ -114,7 +114,7 @@ def buildEntry(self, sequence): if pic: res.append(MultiContentEntryPixmapAlphaBlend( pos=(xPos, yPos), - size=(textWidth + textPaddings*2, height), + size =(textWidth + textPaddings * 2, height), png=pic, backcolor=0x000000, backcolor_sel=None, flags=BT_SCALE, corner_radius=self.cornerRadius)) res.append(MultiContentEntryText( @@ -123,12 +123,12 @@ def buildEntry(self, sequence): text=buttonText, color=textColor, color_sel=textColor)) else: res.append(MultiContentEntryText( - pos=(xPos, yPos), size=(textWidth + textPaddings*2, height - 2), + pos =(xPos, yPos), size =(textWidth + textPaddings * 2, height - 2), font=0, flags=textFlags, text=buttonText, color=textColor, color_sel=textColor, backcolor=backColor, corner_radius=self.cornerRadius)) - xPos += textWidth + textPaddings*2 + self.spacingButtons + xPos += textWidth + textPaddings * 2 + self.spacingButtons if xPos > width and self.layoutStyle != "fluid": self.layoutStyle = "fluid" return self.buildEntry(sequence) From e27d5f2b175437587a5ab6e60d6b5fa2ed0e6496 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Fri, 16 Feb 2024 09:36:04 +0000 Subject: [PATCH 143/183] PEP8 double aggressive E225 ~ E228 and E231 --- lib/python/Components/Addons/ColorButtonsSequence.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/Components/Addons/ColorButtonsSequence.py b/lib/python/Components/Addons/ColorButtonsSequence.py index ff73d4b8072..03482a398c3 100644 --- a/lib/python/Components/Addons/ColorButtonsSequence.py +++ b/lib/python/Components/Addons/ColorButtonsSequence.py @@ -26,7 +26,7 @@ def __init__(self): self.colorIndicatorStyle = "pixmap" self.orientations = {"orHorizontal": eListbox.orHorizontal, "orVertical": eListbox.orVertical} self.orientation = eListbox.orHorizontal - self.renderType = "ImageTextRight" # Currently supported are ImageTextRight, ImageTextOver and ColorTextOver + self.renderType = "ImageTextRight" # Currently supported are ImageTextRight, ImageTextOver and ColorTextOver self.alignment = "left" self.cornerRadius = 0 self.pixmaps = {} From 422fb55178215e1100a0f456af0d3fb477819534 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Fri, 16 Feb 2024 09:36:15 +0000 Subject: [PATCH 144/183] PEP8 double aggressive E301 ~ E306 --- lib/python/Components/Addons/ColorButtonsSequence.py | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/python/Components/Addons/ColorButtonsSequence.py b/lib/python/Components/Addons/ColorButtonsSequence.py index 03482a398c3..95b1f8566b3 100644 --- a/lib/python/Components/Addons/ColorButtonsSequence.py +++ b/lib/python/Components/Addons/ColorButtonsSequence.py @@ -127,7 +127,6 @@ def buildEntry(self, sequence): font=0, flags=textFlags, text=buttonText, color=textColor, color_sel=textColor, backcolor=backColor, corner_radius=self.cornerRadius)) - xPos += textWidth + textPaddings * 2 + self.spacingButtons if xPos > width and self.layoutStyle != "fluid": self.layoutStyle = "fluid" From c49b77ccb049dbb2ebc938e1bda2307441fe1b03 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Fri, 16 Feb 2024 09:36:25 +0000 Subject: [PATCH 145/183] PEP8 double aggressive W291 ~ W293 and W391 --- lib/python/Components/Addons/ColorButtonsSequence.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/Components/Addons/ColorButtonsSequence.py b/lib/python/Components/Addons/ColorButtonsSequence.py index 95b1f8566b3..f7d889e8c48 100644 --- a/lib/python/Components/Addons/ColorButtonsSequence.py +++ b/lib/python/Components/Addons/ColorButtonsSequence.py @@ -107,7 +107,7 @@ def buildEntry(self, sequence): textFlags = RT_HALIGN_CENTER | RT_VALIGN_CENTER textPaddings = self.spacingPixmapText backColor = buttonBgColor - + if self.renderType == "ImageTextOver": if x in self.pixmaps: pic = LoadPixmap(resolveFilename(SCOPE_GUISKIN, self.pixmaps[x])) From c540a5e084801ef6edac08ae16f41f2e60804458 Mon Sep 17 00:00:00 2001 From: openvix-build Date: Fri, 16 Feb 2024 11:14:18 +0000 Subject: [PATCH 146/183] openvix: developer 6.5.001.005 --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index 636e928bef3..70d9fe9bb9a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1238,3 +1238,4 @@ openvix: developer 6.5.001.001 openvix: developer 6.5.001.002 openvix: developer 6.5.001.003 openvix: developer 6.5.001.004 +openvix: developer 6.5.001.005 From 598a7a60d031c91b06a031456c0b06d9d3e122c1 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Fri, 16 Feb 2024 11:15:16 +0000 Subject: [PATCH 147/183] PEP8 double aggressive E251 and E252 --- lib/python/Components/Addons/ColorButtonsSequence.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/python/Components/Addons/ColorButtonsSequence.py b/lib/python/Components/Addons/ColorButtonsSequence.py index f7d889e8c48..e94a307a786 100644 --- a/lib/python/Components/Addons/ColorButtonsSequence.py +++ b/lib/python/Components/Addons/ColorButtonsSequence.py @@ -114,7 +114,7 @@ def buildEntry(self, sequence): if pic: res.append(MultiContentEntryPixmapAlphaBlend( pos=(xPos, yPos), - size =(textWidth + textPaddings * 2, height), + size=(textWidth + textPaddings * 2, height), png=pic, backcolor=0x000000, backcolor_sel=None, flags=BT_SCALE, corner_radius=self.cornerRadius)) res.append(MultiContentEntryText( @@ -123,7 +123,7 @@ def buildEntry(self, sequence): text=buttonText, color=textColor, color_sel=textColor)) else: res.append(MultiContentEntryText( - pos =(xPos, yPos), size =(textWidth + textPaddings * 2, height - 2), + pos=(xPos, yPos), size=(textWidth + textPaddings * 2, height - 2), font=0, flags=textFlags, text=buttonText, color=textColor, color_sel=textColor, backcolor=backColor, corner_radius=self.cornerRadius)) From 3592ca72b3a88448ac9329faf19c4d82b95a2619 Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Sun, 18 Feb 2024 16:27:40 +0200 Subject: [PATCH 148/183] [Added] hops to cryptoinfo string --- lib/python/Components/Converter/CryptoInfo.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/python/Components/Converter/CryptoInfo.py b/lib/python/Components/Converter/CryptoInfo.py index b8fbf994cdb..5dd38b7f747 100644 --- a/lib/python/Components/Converter/CryptoInfo.py +++ b/lib/python/Components/Converter/CryptoInfo.py @@ -80,9 +80,9 @@ def getText(self): textvalue = "%s - %s (Caid: %s, Prov: %s,)" % (source, caid, caid, prov) #new oscam ecm.info with port parametr elif reader != "" and source == "net" and port != "": - textvalue = "%s - Caid: %s, Prov: %s, Reader: %s, %s (%s:%s) - %s" % (source, caid, prov, reader, protocol, server, port, ecm_time.replace('msec', 'ms')) + textvalue = "%s - Caid: %s, Prov: %s, Reader: %s, %s (%s:%s@%s) - %s" % (source, caid, prov, reader, protocol, server, port, hops, ecm_time.replace('msec', 'ms')) elif reader != "" and source == "net": - textvalue = "%s - Caid: %s, Prov: %s, Reader: %s, %s (%s) - %s" % (source, caid, prov, reader, protocol, server, ecm_time.replace('msec', 'ms')) + textvalue = "%s - Caid: %s, Prov: %s, Reader: %s, %s (%s@%s) - %s" % (source, caid, prov, reader, protocol, server, hops, ecm_time.replace('msec', 'ms')) elif reader != "" and source != "net": textvalue = "%s - Caid: %s, Prov: %s, Reader: %s, %s (local) - %s" % (source, caid, prov, reader, protocol, ecm_time.replace('msec', 'ms')) elif server == "" and port == "" and protocol != "": From ccd821810237ea72074c61fc21f4be4308ca8a0c Mon Sep 17 00:00:00 2001 From: LraiZer Date: Fri, 16 Feb 2024 17:35:57 +0000 Subject: [PATCH 149/183] [epgcache] fix OPENTV, ATSC_EIT, EPG_IMPORT source type OPENTV and ATSC_EIT are no longer managing their own cached epg since this commit here. https://github.com/OpenViX/enigma2/commit/05ae1ffc0159a4dc4f5a0f1c3322c21fdd1e0d7a#diff-b15024bd2b4ea380025955f8d690ba180059716f8f64bd2366de9dcd0d44b0c0R1920 int source is not carried through this overload function, it is being reset as EPG_IMPORT source. These sources currently use this broken overload function: eEPGCache::OPENTV eEPGCache::ATSC_EIT --- lib/dvb/epgcache.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/dvb/epgcache.cpp b/lib/dvb/epgcache.cpp index 3f7d0e8ef27..a6bdcadeba8 100644 --- a/lib/dvb/epgcache.cpp +++ b/lib/dvb/epgcache.cpp @@ -1917,7 +1917,7 @@ void eEPGCache::submitEventData(const std::vector& sids, const std::vector< { event_types.push_back(event_type); } - submitEventData(sids, chids, start, duration, title, short_summary, long_description, event_types, parental_ratings, event_id, EPG_IMPORT); + submitEventData(sids, chids, start, duration, title, short_summary, long_description, event_types, parental_ratings, event_id, source); } void eEPGCache::submitEventData(const std::vector& sids, const std::vector& chids, long start, From fb9e9dd459895b94deabad85f4828f69def9462a Mon Sep 17 00:00:00 2001 From: openvix-build Date: Tue, 20 Feb 2024 09:18:03 +0000 Subject: [PATCH 150/183] openvix: developer 6.5.001.006 --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index 70d9fe9bb9a..1a39cae2b14 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1239,3 +1239,4 @@ openvix: developer 6.5.001.002 openvix: developer 6.5.001.003 openvix: developer 6.5.001.004 openvix: developer 6.5.001.005 +openvix: developer 6.5.001.006 From a3d8a192ac009de0cb20809c211845462d482e19 Mon Sep 17 00:00:00 2001 From: Open Vision python bot <39083056+norhap@users.noreply.github.com> Date: Thu, 22 Feb 2024 11:40:39 +0100 Subject: [PATCH 151/183] [servicedvb.cpp] fix showing now and next events in infobars config.usage.show_eit_nownext is now independent. Before this change the control was total of config.epg.eit. If you are using EPG IMPORT then dxNoEIT is also applied in the two information bars, therefore EIT is not shown in the information bars even if config.usage.show_eit_nownext was TRUE, the event information was always controlled by EPG IMPORT. Now if both parameters are enabled, you can show EIT in the information bars, EIT takes control in both bars and the EPG cache from EPG import will be shown in other types of interface, simple EPG, graphics, channel selection, etc. .that is to say as it has always been. --- lib/service/servicedvb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp index 4e066d7d441..199f31e7d08 100644 --- a/lib/service/servicedvb.cpp +++ b/lib/service/servicedvb.cpp @@ -1204,7 +1204,7 @@ void eDVBServicePlay::serviceEvent(int event) updateEpgCacheNowNext(); /* default behaviour is to start an eit reader, and wait for now/next info, unless this is disabled */ - if (m_dvb_service && m_dvb_service->useEIT() && eConfigManager::getConfigBoolValue("config.usage.show_eit_nownext", true)) + if (m_dvb_service && m_dvb_service->useEIT() || eConfigManager::getConfigBoolValue("config.usage.show_eit_nownext", true)) { ePtr m_demux; if (!m_service_handler.getDataDemux(m_demux)) From 8187aea67c7bdad31c94ef9946b561c4f2b694b6 Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Fri, 23 Feb 2024 10:41:05 +0100 Subject: [PATCH 152/183] [sub services] add option to display --- data/setup.xml | 1 + lib/python/Screens/InfoBarGenerics.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/data/setup.xml b/data/setup.xml index 09630474781..7502df1656a 100644 --- a/data/setup.xml +++ b/data/setup.xml @@ -108,6 +108,7 @@ config.usage.servicelist_cursor_behavior config.usage.multibouquet config.usage.panicbutton + config.vixsettings.Subservice config.usage.hide_number_markers config.usage.show_channel_jump_in_servicelist config.usage.servicelist_twolines diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py index c9e15840b58..af76c82c39b 100644 --- a/lib/python/Screens/InfoBarGenerics.py +++ b/lib/python/Screens/InfoBarGenerics.py @@ -3740,6 +3740,8 @@ def subserviceSelection(self): keys = ["red", "", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"] + [""] * (len(subservices) - 10) selection += 2 self.session.openWithCallback(self.subserviceSelected, ChoiceBox, title=_("Please select a sub service"), list=tlist, selection=selection, keys=keys, skin_name="SubserviceSelection") + else: + self.openTimerList() # no sub services, so take default for Green def subserviceSelected(self, service): if service and len(service) > 1: From 746003a00cdda57f709efb80981ac3831aeb6998 Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Fri, 23 Feb 2024 10:50:45 +0100 Subject: [PATCH 153/183] InfoBarGenerics] - minimise imports --- lib/python/Screens/InfoBarGenerics.py | 36 +++++++++++++-------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py index af76c82c39b..a663a0b6aa9 100644 --- a/lib/python/Screens/InfoBarGenerics.py +++ b/lib/python/Screens/InfoBarGenerics.py @@ -62,11 +62,11 @@ from time import time, localtime, strftime from bisect import insort -import os +from os import listdir, path as ospath from sys import maxsize import itertools import datetime -import pickle +from pickle import load as pickle_load, dump as pickle_dump, HIGHEST_PROTOCOL as pickle_HIGHEST_PROTOCOL from gettext import dgettext from re import match @@ -105,9 +105,9 @@ def setResumePoint(session): for k, v in list(resumePointCache.items()): if v[0] < lru: candidate = k - filepath = os.path.realpath(candidate.split(':')[-1]) + filepath = ospath.realpath(candidate.split(':')[-1]) mountpoint = findMountPoint(filepath) - if os.path.ismount(mountpoint) and not os.path.exists(filepath): + if ospath.ismount(mountpoint) and not ospath.exists(filepath): del resumePointCache[candidate] saveResumePoints() @@ -137,7 +137,7 @@ def saveResumePoints(): global resumePointCache, resumePointCacheLast try: f = open('/etc/enigma2/resumepoints.pkl', 'wb') - pickle.dump(resumePointCache, f, pickle.HIGHEST_PROTOCOL) + pickle_dump(resumePointCache, f, pickle_HIGHEST_PROTOCOL) f.close() except Exception as ex: print("[InfoBarGenerics] Failed to write resumepoints:%s" % ex) @@ -147,7 +147,7 @@ def saveResumePoints(): def loadResumePoints(): try: file = open('/etc/enigma2/resumepoints.pkl', 'rb') - PickleFile = pickle.load(file) + PickleFile = pickle_load(file) file.close() return PickleFile except Exception as ex: @@ -169,7 +169,7 @@ class whitelist: def reload_whitelist_vbi(): - whitelist.vbi = [line.strip() for line in open('/etc/enigma2/whitelist_vbi', 'r').readlines()] if os.path.isfile('/etc/enigma2/whitelist_vbi') else [] + whitelist.vbi = [line.strip() for line in open('/etc/enigma2/whitelist_vbi', 'r').readlines()] if ospath.isfile('/etc/enigma2/whitelist_vbi') else [] reload_whitelist_vbi() @@ -180,7 +180,7 @@ class InfoBarStreamRelay: FILENAME = "/etc/enigma2/whitelist_streamrelay" def __init__(self): - self.__srefs = self.__sanitizeData(open(self.FILENAME, 'r').readlines()) if os.path.isfile(self.FILENAME) else [] + self.__srefs = self.__sanitizeData(open(self.FILENAME, 'r').readlines()) if ospath.isfile(self.FILENAME) else [] def __sanitizeData(self, data): return list(set([line.strip() for line in data if line and isinstance(line, str) and match("^(?:[0-9A-F]+[:]){10}$", line.strip())])) if isinstance(data, list) else [] @@ -234,7 +234,7 @@ def reload_subservice_groupslist(force=False): if subservice_groupslist is None or force: try: groupedservices = "/etc/enigma2/groupedservices" - if not os.path.isfile(groupedservices): + if not ospath.isfile(groupedservices): groupedservices = "/usr/share/enigma2/groupedservices" subservice_groupslist = [list(g) for k, g in itertools.groupby([line.split('#')[0].strip() for line in open(groupedservices).readlines()], lambda x: not x) if not k] except: @@ -404,7 +404,7 @@ def ScreenSaverTimerStart(self): ref = self.session.nav.getCurrentlyPlayingServiceOrGroup() if ref and not (hasattr(self.session, "pipshown") and self.session.pipshown): ref = ref.toString().split(":") - flag = ref[2] == "2" or os.path.splitext(ref[10])[1].lower() in AUDIO_EXTENSIONS + flag = ref[2] == "2" or ospath.splitext(ref[10])[1].lower() in AUDIO_EXTENSIONS if time and flag: self.screenSaverTimer.startLongTimer(time) else: @@ -997,10 +997,10 @@ def avChange(self): audio_pid = None if av_val.find("|") > -1: split = av_val.split("|") - audio_pid = pickle_loads(split[0].encode()) - subs_pid = pickle_loads(split[1].encode()) + audio_pid = pickle_load(split[0].encode()) + subs_pid = pickle_load(split[1].encode()) elif av_val and av_val != "": - audio_pid = pickle_loads(av_val.encode()) + audio_pid = pickle_load(av_val.encode()) audio = service and service.audioTracks() playinga_idx = audio and audio.getCurrentTrack() if audio_pid and audio_pid != -1 and playinga_idx != audio_pid: @@ -2298,11 +2298,11 @@ def doActivityTimer(self): self.activityTimer.stop() self.activity = 0 hdd = 0 - if os.path.exists("/proc/stb/lcd/symbol_hdd"): + if ospath.exists("/proc/stb/lcd/symbol_hdd"): file = open("/proc/stb/lcd/symbol_hdd", "w") file.write('%d' % int(hdd)) file.close() - if os.path.exists("/proc/stb/lcd/symbol_hddprogress"): + if ospath.exists("/proc/stb/lcd/symbol_hddprogress"): file = open("/proc/stb/lcd/symbol_hddprogress", "w") file.write('%d' % int(self.activity)) file.close() @@ -2727,7 +2727,7 @@ def __hideTimeshiftState(self): self.pvrStateDialog.hide() def __timeshiftEventName(self, state): - if os.path.exists("%spts_livebuffer_%s.meta" % (config.usage.timeshift_path.value, self.pts_currplaying)): + if ospath.exists("%spts_livebuffer_%s.meta" % (config.usage.timeshift_path.value, self.pts_currplaying)): readmetafile = open("%spts_livebuffer_%s.meta" % (config.usage.timeshift_path.value, self.pts_currplaying), "r") servicerefname = readmetafile.readline()[0:-1] # noqa: F841 servicerefname assigned, not used eventname = readmetafile.readline()[0:-1] @@ -2850,7 +2850,7 @@ def getCCname(self): def getCCcamInfo(self): softcams = [] if pathExists('/usr/softcams/'): - softcams = os.listdir('/usr/softcams/') + softcams = listdir('/usr/softcams/') for softcam in softcams: if softcam.lower().startswith('cccam') and config.cccaminfo.showInExtensions.value: return [((boundFunction(self.getCCname), boundFunction(self.openCCcamInfo), lambda: True), None)] or [] @@ -2863,7 +2863,7 @@ def getOSname(self): def getOScamInfo(self): softcams = [] if pathExists('/usr/softcams/'): - softcams = os.listdir('/usr/softcams/') + softcams = listdir('/usr/softcams/') for softcam in softcams: if softcam.lower().startswith(('oscam', 'ncam')) and config.oscaminfo.showInExtensions.value: return [((boundFunction(self.getOSname), boundFunction(self.openOScamInfo), lambda: True), None)] or [] From 17bd1fd1c5b76175297a0f6b2c5c892d57dd9774 Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Fri, 23 Feb 2024 11:14:24 +0100 Subject: [PATCH 154/183] [camcontrol] f string --- lib/python/Tools/camcontrol.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/lib/python/Tools/camcontrol.py b/lib/python/Tools/camcontrol.py index f22f95bc194..27382b0f4d1 100644 --- a/lib/python/Tools/camcontrol.py +++ b/lib/python/Tools/camcontrol.py @@ -8,11 +8,11 @@ class CamControl: def __init__(self, name): self.name = name - print("[CamControl] self.name=%s" % self.name) + print(f"[CamControl] self.name={self.name}") self.link = '/etc/init.d/' + name - print("[CamControl] self.link=%s" % self.link) + print(f"[CamControl] self.link={self.link}") if not path.exists(self.link): - print("[CamControl] No softcam link %s" % self.link) + print(f"[CamControl] No softcam link {self.link}") def getList(self): result = [] @@ -20,14 +20,14 @@ def getList(self): for f in listdir("/etc/init.d"): if f.startswith(prefix): result.append(f[len(prefix):]) - print("[CamControl][getList] returnlist=%s" % result) + print(f"[CamControl][getList] returnlist={result}") return result def getConfigs(self, prefix): configs = [] if path.exists("/etc/tuxbox/config/%s" % prefix): - configs = listdir("/etc/tuxbox/config/%s" % prefix) - print("[CamControl][getList] configs=%s" % configs) + configs = listdir(f"/etc/tuxbox/config/{prefix}") + print(f"[CamControl][getList] configs={configs}") return configs def current(self): @@ -41,28 +41,28 @@ def current(self): def command(self, cmd): if path.exists(self.link): - cmd = "%s %s" % (self.link, cmd) - print("[CamControl][command]Executing %s" % cmd) + cmd = f"{self.link} {cmd}" + print(f"[CamControl][command]Executing {cmd}") eConsoleAppContainer().execute(cmd) def select(self, cam): - print("[CamControl]Selecting CAM:%s" % cam) + print(f"[CamControl]Selecting CAM:{cam}") if not cam: cam = "None" - dst = "%s.%s" % (self.name, cam) - print("[CamControl][select] dst:%s" % dst) - if not path.exists("/etc/init.d/%s" % dst): - print("[CamControl][select] init script does not exist:%s" % dst) + dst = f"{self.name}.{cam}" + print(f"[CamControl][select] dst:{dst}") + if not path.exists(f"/etc/init.d/{dst}"): + print(f"[CamControl][select] init script does not exist:{dst}") return try: - print("[CamControl][select][unlink] self.link=%s " % self.link) + print(f"[CamControl][select][unlink] self.link={self.link} ") unlink(self.link) except: pass try: - print("[CamControl][select][symlink] dst=%s self.link=%s" % (dst, self.link)) + print(f"[CamControl][select][symlink] dst={dst} self.link={self.link}") symlink(dst, self.link) except: - print("[CamControl][select] Failed to create symlink for softcam:%s" % dst) + print(f"[CamControl][select] Failed to create symlink for softcam:{dst}") import sys - print("[CamControl][select] sys info = %s" % sys.exc_info()[:2]) + print(f"[CamControl][select] sys info = {sys.exc_info()[:2]}") From e9779535ff41cd0ca2d65a6b65d47cedfab7a44b Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Fri, 23 Feb 2024 11:32:59 +0100 Subject: [PATCH 155/183] [Multiboot] - code cleanup, f string --- lib/python/Tools/Multiboot.py | 110 +++++++++++----------------------- 1 file changed, 36 insertions(+), 74 deletions(-) diff --git a/lib/python/Tools/Multiboot.py b/lib/python/Tools/Multiboot.py index da96583d575..11697dd4061 100644 --- a/lib/python/Tools/Multiboot.py +++ b/lib/python/Tools/Multiboot.py @@ -6,15 +6,12 @@ from Components.Console import Console from Components.SystemInfo import SystemInfo, BoxInfo as BoxInfoRunningInstance, BoxInformation -from Tools.Directories import fileHas, fileExists +from Tools.Directories import fileExists -if fileHas("/proc/cmdline", "kexec=1"): - from PIL import Image - from PIL import ImageDraw - from PIL import ImageFont +if SystemInfo["HasKexecMultiboot"]: + from PIL import Image, ImageDraw, ImageFont MbootList1 = ("/dev/mmcblk0p1", "/dev/mmcblk1p1", "/dev/mmcblk0p3", "/dev/mmcblk0p4", "/dev/mtdblock2", "/dev/block/by-name/bootoptions") -MbootList2 = ("/dev/%s" % SystemInfo["mtdrootfs"], ) # kexec kernel Vu+ multiboot class tmp: @@ -31,23 +28,18 @@ def getMultibootslots(): UUIDnum = 0 tmp.dir = tempfile.mkdtemp(prefix="getMultibootslots") tmpname = tmp.dir - MbootList = MbootList2 if fileHas("/proc/cmdline", "kexec=1") else MbootList1 + MbootList = MbootList1 if not SystemInfo["HasKexecMultiboot"] else (f"/dev/{SystemInfo['mtdrootfs']}", ) # kexec kernel Vu+ multiboot for device in MbootList: - print("[multiboot*****][getMultibootslots]00 device, bootslots", device, " ", bootslots) if len(bootslots) != 0: break - # print("[multiboot*****][getMultibootslots]0 device = ", device) if path.exists(device): - print("[multiboot*****][getMultibootslots]path found for device = ", device) - Console(binary=True).ePopen("mount %s %s" % (device, tmpname)) + Console(binary=True).ePopen(f"mount {device} {tmpname}") if path.isfile(path.join(tmpname, "STARTUP")): SystemInfo["MBbootdevice"] = device device2 = device.rsplit("/", 1)[1] - print("[Multiboot][[getMultibootslots]1 Bootdevice found: %s" % device2) + print(f"[Multiboot][[getMultibootslots]1 *** Bootdevice found: {device2}") SystemInfo["BootDevice"] = device2 for file in glob.glob(path.join(tmpname, "STARTUP_*")): - print("[multiboot*****] [getMultibootslots]2 tmpname = %s" % (tmpname)) - print("[multiboot] [getMultibootslots]4 file = ", file) slotnumber = file.rsplit("_", 3 if "BOXMODE" in file else 1)[1] slotname = file.rsplit("_", 3 if "BOXMODE" in file else 1)[0] slotname = file.rsplit("/", 1)[1] @@ -59,41 +51,36 @@ def getMultibootslots(): if "STARTUP_RECOVERY" in file: SystemInfo["RecoveryMode"] = True slotnumber = "0" - print("[multiboot] [getMultibootslots3] slot = %s file = %s" % (slotnumber, slotname)) if slotnumber.isdigit() and slotnumber not in bootslots: line = open(file).read().replace("'", "").replace('"', "").replace("\n", " ").replace("ubi.mtd", "mtd").replace("bootargs=", "") - # print("[Multiboot][getMultibootslots]6 readlines = %s " % line) slot = dict([(x.split("=", 1)[0].strip(), x.split("=", 1)[1].strip()) for x in line.strip().split(" ") if "=" in x]) if slotnumber == "0": slot["slotType"] = "" slot["startupfile"] = path.basename(file) else: slot["slotType"] = "eMMC" if "mmc" in slot["root"] else "USB" - if fileHas("/proc/cmdline", "kexec=1") and int(slotnumber) > 3: + if SystemInfo["HasKexecMultiboot"] and int(slotnumber) > 3: SystemInfo["HasKexecUSB"] = True - print("[Multiboot][getMultibootslots]6a slot", slot) if "root" in slot.keys(): if "UUID=" in slot["root"]: slotx = getUUIDtoSD(slot["root"]) UUID = slot["root"] UUIDnum += 1 - print("[Multiboot][getMultibootslots]6a slotx slot['root']", slotx, slot["root"]) if slotx is not None: slot["root"] = slotx - slot["kernel"] = "/linuxrootfs%s/zImage" % slotnumber + slot["kernel"] = f"/linuxrootfs{slotnumber}/zImage" if path.exists(slot["root"]) or slot["root"] == "ubi0:ubifs": slot["startupfile"] = path.basename(file) slot["slotname"] = slotname SystemInfo["HasMultibootMTD"] = slot.get("mtd") - if not fileHas("/proc/cmdline", "kexec=1") and "sda" in slot["root"]: # Not Kexec Vu+ receiver -- sf8008 type receiver with sd card, reset value as SD card slot has no rootsubdir + if not SystemInfo["HasKexecMultiboot"] and "sda" in slot["root"]: # Not Kexec Vu+ receiver -- sf8008 type receiver with sd card, reset value as SD card slot has no rootsubdir slot["rootsubdir"] = None slot["slotType"] = "SDCARD" else: SystemInfo["HasRootSubdir"] = slot.get("rootsubdir") if "kernel" not in slot.keys(): - slot["kernel"] = "%sp%s" % (slot["root"].split("p")[0], int(slot["root"].split("p")[1]) - 1) # oldstyle MB kernel = root-1 - # print("[multiboot] [getMultibootslots]7a HasMultibootMTD, kernel, root, SystemInfo['HasRootSubdir'] ", SystemInfo["HasMultibootMTD"], " ", slot["kernel"], " ", slot["root"], " ", SystemInfo["HasRootSubdir"]) + slot["kernel"] = f"{slot['root'].split('p')[0]}p{int(slot['root'].split('p')[1]) - 1}" # oldstyle MB kernel = root-1 else: continue bootslots[int(slotnumber)] = slot @@ -101,25 +88,19 @@ def getMultibootslots(): bootslots[int(slotnumber)] = slot else: continue - print("[multiboot] [getMultibootslots] Finished bootslots = %s" % bootslots) - Console(binary=True).ePopen("umount %s" % tmpname) + Console(binary=True).ePopen(f"umount {tmpname}") if not path.ismount(tmp.dir): rmdir(tmp.dir) if bootslots: - # print("[Multiboot] Bootslots found:", bootslots) bootArgs = open("/sys/firmware/devicetree/base/chosen/bootargs", "r").read() - print("[Multiboot][MultiBootSlot] bootArgs:", bootArgs) - if fileHas("/proc/cmdline", "kexec=1") and SystemInfo["HasRootSubdir"]: # Kexec Vu+ receiver + if SystemInfo["HasKexecMultiboot"] and SystemInfo["HasRootSubdir"]: # Kexec Vu+ receiver rootsubdir = [x for x in bootArgs.split() if x.startswith("rootsubdir")] char = "/" if "/" in rootsubdir[0] else "=" SystemInfo["MultiBootSlot"] = int(rootsubdir[0].rsplit(char, 1)[1][11:]) SystemInfo["VuUUIDSlot"] = (UUID, UUIDnum) if UUIDnum != 0 else "" - print("[Multiboot][MultiBootSlot]0 current slot used:", SystemInfo["MultiBootSlot"]) - # print("[Multiboot][MultiBootSlot]0 UID, UUIDnum:", SystemInfo["VuUUIDSlot"], " ", SystemInfo["VuUUIDSlot"][0], " ", SystemInfo["VuUUIDSlot"][1]) elif SystemInfo["HasRootSubdir"] and "root=/dev/sda" not in bootArgs: # RootSubdir receiver or sf8008 receiver with root in eMMC slot slot = [x[-1] for x in bootArgs.split() if x.startswith("rootsubdir")] SystemInfo["MultiBootSlot"] = int(slot[0]) - print("[Multiboot][MultiBootSlot]1 current slot used:", SystemInfo["MultiBootSlot"]) else: root = dict([(x.split("=", 1)[0].strip(), x.split("=", 1)[1].strip()) for x in bootArgs.strip().split(" ") if "=" in x])["root"] # Broadband receiver (e.g. gbue4k) or sf8008 with sd card as root/kernel pair for slot in bootslots.keys(): @@ -127,18 +108,16 @@ def getMultibootslots(): continue if bootslots[slot]["root"] == root: SystemInfo["MultiBootSlot"] = slot - print("[Multiboot][MultiBootSlot]2 current slot used:", SystemInfo["MultiBootSlot"]) + print(f"[Multiboot][MultiBootSlot]2 current slot used:{SystemInfo['MultiBootSlot']}") break return bootslots def getUUIDtoSD(UUID): # returns None on failure - # print("[multiboot][getUUIDtoSD2] UUID = ", UUID) - check = "/sbin/blkid" - if fileExists(check): - lines = subprocess.check_output([check]).decode(encoding="utf8", errors="ignore").split("\n") + if fileExists("/sbin/blkid"): + lines = subprocess.check_output(["/sbin/blkid"]).decode(encoding="utf8", errors="ignore").split("\n") + # print(f"[multiboot][getUUIDtoSD2] lines:{lines}") for line in lines: - # print("[Multiboot][getUUIDtoSD2] line", line) if UUID in line.replace('"', ''): return line.split(":")[0].strip() else: @@ -161,7 +140,6 @@ def GetImagelist(Recovery=None): else: # called by MultiBootSelector Imagelist[slot] = {"imagename": _("Recovery Mode")} continue - print("[multiboot] [GetImagelist] slot = ", slot) BuildVersion = " " Build = " " # ViX Build No. Creator = " " # Openpli Openvix Openatv etc @@ -169,43 +147,36 @@ def GetImagelist(Recovery=None): imagedir = "/" if SystemInfo["MultiBootSlot"] != slot or SystemInfo["HasHiSi"]: if SystemInfo["HasMultibootMTD"]: - Console(binary=True).ePopen("mount -t ubifs %s %s" % (SystemInfo["canMultiBoot"][slot]["root"], tmpname)) + Console(binary=True).ePopen(f"mount -t ubifs {SystemInfo['canMultiBoot'][slot]['root']} {tmpname}") else: - Console(binary=True).ePopen("mount %s %s" % (SystemInfo["canMultiBoot"][slot]["root"], tmpname)) + Console(binary=True).ePopen(f"mount {SystemInfo['canMultiBoot'][slot]['root']} {tmpname}") imagedir = sep.join([_f for _f in [tmpname, SystemInfo["canMultiBoot"][slot].get("rootsubdir", "")] if _f]) - # print("[multiboot] [GetImagelist]0 isfile = %s" % (path.join(imagedir, "usr/bin/enigma2"))) if path.isfile(path.join(imagedir, "usr/bin/enigma2")): - # print("[multiboot] [GetImagelist]1 Slot = %s imagedir = %s" % (slot, imagedir)) if path.isfile(path.join(imagedir, "usr/lib/enigma.info")): print("[multiboot] [GetImagelist] using enigma.info") BuildVersion = createInfo(slot, imagedir=imagedir) - # print("[multiboot] [GetImagelist] slot=%s, BuildVersion=%s" % (slot, BuildVersion)) else: - # print("[multiboot] [GetImagelist] using BoxBranding") - print("[multiboot] [GetImagelist]2 slot = %s imagedir = %s" % (slot, imagedir)) - Creator = open("%s/etc/issue" % imagedir).readlines()[-2].capitalize().strip()[:-6] - print("[multiboot] [GetImagelist] Creator = %s imagedir = %s" % (Creator, imagedir)) - if fileHas("/proc/cmdline", "kexec=1") and path.isfile(path.join(imagedir, "etc/vtiversion.info")): + print("[multiboot] [GetImagelist] using BoxInfo") + Creator = open(f"{imagedir}/etc/issue").readlines()[-2].capitalize().strip()[:-6] + if SystemInfo["HasKexecMultiboot"] and path.isfile(path.join(imagedir, "etc/vtiversion.info")): Vti = open(path.join(imagedir, "etc/vtiversion.info")).read() - # print("[BootInfo]6 vti = ", Vti) date = VerDate(imagedir) Creator = Vti[0:3] Build = Vti[-8:-1] - BuildVersion = "%s %s (%s) " % (Creator, Build, date) - # print("[BootInfo]8 BuildVersion = ", BuildVersion ) + BuildVersion = f"{Creator} {Build} ({date}) " else: date = VerDate(imagedir) Creator = Creator.replace("-release", " ") - BuildVersion = "%s (%s)" % (Creator, date) - if fileHas("/proc/cmdline", "kexec=1") and Recovery and config.usage.bootlogo_identify.value: + BuildVersion = f"{Creator} ({date})" + if SystemInfo["HasKexecMultiboot"] and Recovery and config.usage.bootlogo_identify.value: bootmviSlot(imagedir=imagedir, text=BuildVersion, slot=slot) - Imagelist[slot] = {"imagename": "%s" % BuildVersion} + Imagelist[slot] = {"imagename": f"{BuildVersion}"} elif path.isfile(path.join(imagedir, "usr/bin/enigmax")): Imagelist[slot] = {"imagename": _("Deleted image")} else: Imagelist[slot] = {"imagename": _("Empty slot")} if SystemInfo["MultiBootSlot"] != slot: - Console(binary=True).ePopen("umount %s" % tmpname) + Console(binary=True).ePopen(f"umount {tmpname}") if not path.ismount(tmp.dir): rmdir(tmp.dir) return Imagelist @@ -229,9 +200,7 @@ def VerDate(imagedir): date2 = datetime.fromtimestamp(stat(path.join(imagedir, "usr/bin/enigma2")).st_mtime).strftime("%Y-%m-%d") if fileExists(path.join(imagedir, "usr/share/bootlogo.mvi")): date3 = datetime.fromtimestamp(stat(path.join(imagedir, "usr/share/bootlogo.mvi")).st_mtime).strftime("%Y-%m-%d") - print("[multiboot][VerDate]1 date1, date2, date3", date1, " ", date2, " ", date3) date = max(date1, date2, date3) # this is comparing strings - print("[multiboot][VerDate]2 date = %s" % date) date = datetime.strptime(date, '%Y-%m-%d').strftime("%d-%m-%Y") return date @@ -239,17 +208,16 @@ def VerDate(imagedir): def emptySlot(slot): tmp.dir = tempfile.mkdtemp(prefix="emptySlot") if SystemInfo["HasMultibootMTD"]: - Console(binary=True).ePopen("mount -t ubifs %s %s" % (SystemInfo["canMultiBoot"][slot]["root"], tmp.dir)) + Console(binary=True).ePopen(f"mount -t ubifs {SystemInfo['canMultiBoot'][slot]['root']} {tmp.dir}") else: - Console(binary=True).ePopen("mount %s %s" % (SystemInfo["canMultiBoot"][slot]["root"], tmp.dir)) + Console(binary=True).ePopen(f"mount {SystemInfo['canMultiBoot'][slot]['root']} {tmp.dir}") imagedir = sep.join([_f for _f in [tmp.dir, SystemInfo["canMultiBoot"][slot].get("rootsubdir", "")] if _f]) if path.isfile(path.join(imagedir, "usr/bin/enigma2")): rename((path.join(imagedir, "usr/bin/enigma2")), (path.join(imagedir, "usr/bin/enigmax"))) ret = 0 else: - print("[multiboot2] NO enigma2 found to rename") - ret = 4 - Console(binary=True).ePopen("umount %s" % tmp.dir) + ret = 4 # NO enigma2 found to rename + Console(binary=True).ePopen(f"umount {tmp.dir}") if not path.ismount(tmp.dir): rmdir(tmp.dir) return ret @@ -259,30 +227,24 @@ def bootmviSlot(imagedir="/", text=" ", slot=0): inmviPath = path.join(imagedir, "usr/share/bootlogo.mvi") outmviPath = path.join(imagedir, "usr/share/enigma2/bootlogo.mvi") txtPath = path.join(imagedir, "usr/share/enigma2/bootlogo.txt") - text = "booting slot %s %s" % (slot, text) - print("[multiboot][bootmviSlot] inPath, outpath ", inmviPath, " ", outmviPath) + text = f"booting slot {slot} {text}" if path.exists(inmviPath): if path.exists(outmviPath) and path.exists(txtPath) and open(txtPath).read() == text: return - print("[multiboot][bootmviSlot] Copy /usr/share/bootlogo.mvi to /tmp/bootlogo.m1v") - Console(binary=True).ePopen("cp %s /tmp/bootlogo.m1v" % inmviPath) - print("[multiboot][bootmviSlot] Dump iframe to png") + Console(binary=True).ePopen(f"cp {inmviPath} /tmp/bootlogo.m1v") Console(binary=True).ePopen("ffmpeg -skip_frame nokey -i /tmp/bootlogo.m1v -vsync 0 -y /tmp/out1.png 2>/dev/null") Console(binary=True).ePopen("rm -f /tmp/mypicture.m1v") if path.exists("/tmp/out1.png"): img = Image.open("/tmp/out1.png") # Open an Image else: - print("[multiboot][bootmviSlot] unable to create new bootlogo cannot open out1.png") return I1 = ImageDraw.Draw(img) # Call draw Method to add 2D graphics in an image myFont = ImageFont.truetype("/usr/share/fonts/OpenSans-Regular.ttf", 65) # Custom font style and font size - print("[multiboot][bootmviSlot] Write text to png") I1.text((52, 12), text, font=myFont, fill=(255, 0, 0)) # Add Text to an image I1.text((50, 10), text, font=myFont, fill=(255, 255, 255)) img.save("/tmp/out1.png") # Save the edited image - print("[multiboot][bootmviSlot] Repack bootlogo") Console(binary=True).ePopen("ffmpeg -i /tmp/out1.png -r 25 -b 20000 -y /tmp/mypicture.m1v 2>/dev/null") - Console(binary=True).ePopen("cp /tmp/mypicture.m1v %s" % outmviPath) + Console(binary=True).ePopen(f"cp /tmp/mypicture.m1v {outmviPath}") with open(txtPath, "w") as f: f.write(text) @@ -291,12 +253,12 @@ def restoreSlots(): for slot in SystemInfo["canMultiBoot"]: tmp.dir = tempfile.mkdtemp(prefix="restoreSlot") if SystemInfo["HasMultibootMTD"]: - Console(binary=True).ePopen("mount -t ubifs %s %s" % (SystemInfo["canMultiBoot"][slot]["root"], tmp.dir)) + Console(binary=True).ePopen(f"mount -t ubifs {SystemInfo['canMultiBoot'][slot]['root']} {tmp.dir}") else: - Console(binary=True).ePopen("mount %s %s" % (SystemInfo["canMultiBoot"][slot]["root"], tmp.dir)) + Console(binary=True).ePopen(f"mount {SystemInfo['canMultiBoot'][slot]['root']} {tmp.dir}") imagedir = sep.join([_f for _f in [tmp.dir, SystemInfo["canMultiBoot"][slot].get("rootsubdir", "")] if _f]) if path.isfile(path.join(imagedir, "usr/bin/enigmax")): rename((path.join(imagedir, "usr/bin/enigmax")), (path.join(imagedir, "usr/bin/enigma2"))) - Console(binary=True).ePopen("umount %s" % tmp.dir) + Console(binary=True).ePopen(f"umount {tmp.dir}") if not path.ismount(tmp.dir): rmdir(tmp.dir) From 2e7fdeb136aa21a3320de47ac37de7d1085c4360 Mon Sep 17 00:00:00 2001 From: Orlandoxx <95180049+Orlandoxx@users.noreply.github.com> Date: Fri, 23 Feb 2024 21:15:24 +0200 Subject: [PATCH 156/183] Updated Finnish (fi.po) translation Added 'Subservices'. --- po/fi.po | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/po/fi.po b/po/fi.po index 27eae0f4052..189affef2fa 100644 --- a/po/fi.po +++ b/po/fi.po @@ -5,7 +5,7 @@ msgstr "" "Project-Id-Version: enigma2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-12-27 23:35+0000\n" -"PO-Revision-Date: 2024-02-07 19:20+0200\n" +"PO-Revision-Date: 2024-02-23 21:13+0200\n" "Last-Translator: Orlandox\n" "Language-Team: timoj/Kojo/Samzam/Orlandox\n" "Language: fi\n" @@ -6626,7 +6626,7 @@ msgid "HDMI Color depth" msgstr "HDMI Värisyvyys" msgid "HDMI Colorimetry" -msgstr "HDMI Kolorimetria" +msgstr "HDMI Väriavaruus" msgid "HDMI Colorspace" msgstr "HDMI Väriavaruus" @@ -13543,7 +13543,7 @@ msgstr "" "Suomenkielinen käännös: timoj, Kojo, Samzam, Orlandox\n" "\n" "Ylläpito : Orlandox\n" -"--- 07.02.2024 ---\n" +"--- 23.02.2024 ---\n" "\n" "http://www.huoltovalikko.com" @@ -19372,3 +19372,9 @@ msgstr "\"Näytä resoluutiotieto" msgid "Video mode: %s not available" msgstr "Videotila: %s ei ole käytettävissä" + +msgid "Show available subservices" +msgstr "Näytä käytettävissä olevat alipalvelut" + +msgid "if set will display subservices else timers." +msgstr "Jos asetettu näyttää alipalvelut muutoin ajastimet." From 33f69119fb530e8775929ec153e47d32586ff452 Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Sat, 24 Feb 2024 12:10:17 +0100 Subject: [PATCH 157/183] PEP8 - step 1 cleanup --- .../Components/Addons/ColorButtonsSequence.py | 12 +++---- lib/python/Components/Addons/ScreenHeader.py | 12 +++---- .../Components/Addons/ServiceInfoBar.py | 28 ++++++--------- lib/python/Components/Converter/CryptoInfo.py | 34 +++++++++---------- .../Components/Converter/ServiceInfo.py | 8 ++--- lib/python/Screens/InfoBar.py | 2 +- lib/python/Screens/InfoBarGenerics.py | 1 - 7 files changed, 45 insertions(+), 52 deletions(-) diff --git a/lib/python/Components/Addons/ColorButtonsSequence.py b/lib/python/Components/Addons/ColorButtonsSequence.py index e94a307a786..52fea20a592 100644 --- a/lib/python/Components/Addons/ColorButtonsSequence.py +++ b/lib/python/Components/Addons/ColorButtonsSequence.py @@ -118,14 +118,14 @@ def buildEntry(self, sequence): png=pic, backcolor=0x000000, backcolor_sel=None, flags=BT_SCALE, corner_radius=self.cornerRadius)) res.append(MultiContentEntryText( - pos=(xPos + textPaddings, yPos), size=(textWidth, height - 2), - font=0, flags=textFlags, - text=buttonText, color=textColor, color_sel=textColor)) + pos=(xPos + textPaddings, yPos), size=(textWidth, height - 2), + font=0, flags=textFlags, + text=buttonText, color=textColor, color_sel=textColor)) else: res.append(MultiContentEntryText( - pos=(xPos, yPos), size=(textWidth + textPaddings * 2, height - 2), - font=0, flags=textFlags, - text=buttonText, color=textColor, color_sel=textColor, backcolor=backColor, corner_radius=self.cornerRadius)) + pos=(xPos, yPos), size=(textWidth + textPaddings * 2, height - 2), + font=0, flags=textFlags, + text=buttonText, color=textColor, color_sel=textColor, backcolor=backColor, corner_radius=self.cornerRadius)) xPos += textWidth + textPaddings * 2 + self.spacingButtons if xPos > width and self.layoutStyle != "fluid": diff --git a/lib/python/Components/Addons/ScreenHeader.py b/lib/python/Components/Addons/ScreenHeader.py index 13534975c8f..8126e105aba 100644 --- a/lib/python/Components/Addons/ScreenHeader.py +++ b/lib/python/Components/Addons/ScreenHeader.py @@ -54,12 +54,12 @@ def buildEntry(self, sequence): yPos = self.instance.size().height() * 2 // 3 - 3 itemHeight = self.instance.size().height() // 3 res.append(MultiContentEntryText( - pos=(0, yPos), - size=(self.instance.size().width(), itemHeight), - font=2 if isOneItem and idx == 0 else idx, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER, - text=x.text, - color=foreColor, color_sel=foreColor, - backcolor=self.backgroundColor, backcolor_sel=self.backgroundColor)) + pos=(0, yPos), + size=(self.instance.size().width(), itemHeight), + font=2 if isOneItem and idx == 0 else idx, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER, + text=x.text, + color=foreColor, color_sel=foreColor, + backcolor=self.backgroundColor, backcolor_sel=self.backgroundColor)) return res def postWidgetCreate(self, instance): diff --git a/lib/python/Components/Addons/ServiceInfoBar.py b/lib/python/Components/Addons/ServiceInfoBar.py index 97e76737e94..0d9fd737f60 100644 --- a/lib/python/Components/Addons/ServiceInfoBar.py +++ b/lib/python/Components/Addons/ServiceInfoBar.py @@ -1,21 +1,15 @@ -from Components.Addons.GUIAddon import GUIAddon - from enigma import eListbox, eListboxPythonMultiContent, BT_ALIGN_CENTER, iPlayableService, iRecordableService, eServiceReference, iServiceInformation, gFont, RT_HALIGN_LEFT, RT_VALIGN_CENTER, RT_VALIGN_TOP, RT_HALIGN_CENTER, eTimer, getDesktop, eSize, eStreamServer - from skin import parseScale, applySkinFactor, parseColor, parseFont -from Components.MultiContent import MultiContentEntryPixmapAlphaBlend, MultiContentEntryText -from Components.ServiceEventTracker import ServiceEventTracker +from Components.Addons.GUIAddon import GUIAddon +from Components.Converter.PliExtraInfo import createCurrentCaidLabel from Components.Converter.ServiceInfo import getVideoHeight from Components.Converter.VAudioInfo import StdAudioDesc -from Components.Converter.PliExtraInfo import createCurrentCaidLabel from Components.Label import Label +from Components.MultiContent import MultiContentEntryPixmapAlphaBlend, MultiContentEntryText +from Components.ServiceEventTracker import ServiceEventTracker from Components.Sources.StreamService import StreamServiceList - -from Components.config import config - from Screens.InfoBarGenerics import hasActiveSubservicesForCurrentChannel - from Tools.Directories import resolveFilename, SCOPE_GUISKIN from Tools.LoadPixmap import LoadPixmap @@ -142,11 +136,11 @@ def detectVisible(self, key): service = self.nav.getCurrentService() info = service and service.info() isRef = isinstance(service, eServiceReference) - #self.current_info = info + # self.current_info = info if not info: return None video_height = None - video_aspect = None + # video_aspect = None video_height = getVideoHeight(info) if key == "videoRes": if video_height >= 720 and video_height < 1500: @@ -267,11 +261,11 @@ def buildEntry(self, sequence): else: textWidth = self._calcTextWidth(self.current_crypto, font=self.font, size=eSize(self.getDesktopWith() // 3, 0)) res.append(MultiContentEntryText( - pos=(xPos - textWidth, yPos - 2), size=(textWidth, self.instance.size().height()), - font=0, flags=RT_HALIGN_CENTER | RT_VALIGN_TOP, - text=self.current_crypto, - color=self.foreColor, color_sel=self.foreColor, - backcolor=None, backcolor_sel=None)) + pos=(xPos - textWidth, yPos - 2), size=(textWidth, self.instance.size().height()), + font=0, flags=RT_HALIGN_CENTER | RT_VALIGN_TOP, + text=self.current_crypto, + color=self.foreColor, color_sel=self.foreColor, + backcolor=None, backcolor_sel=None)) if self.alignment == "right": xPos -= textWidth + self.spacing else: diff --git a/lib/python/Components/Converter/CryptoInfo.py b/lib/python/Components/Converter/CryptoInfo.py index 5dd38b7f747..9ba4deab68b 100644 --- a/lib/python/Components/Converter/CryptoInfo.py +++ b/lib/python/Components/Converter/CryptoInfo.py @@ -44,8 +44,8 @@ def getText(self): if ecm_info: # caid caid = "%0.4X" % int(ecm_info.get('caid', ecm_info.get('CAID', '0')), 16) - #pid - pid = "%0.4X" % int(ecm_info.get('pid', ecm_info.get('ECM PID', '0')), 16) + # pid + # pid = "%0.4X" % int(ecm_info.get('pid', ecm_info.get('ECM PID', '0')), 16) # oscam prov = "%0.6X" % int(ecm_info.get('provid', ecm_info.get('prov', ecm_info.get('Provider', '0'))), 16) @@ -54,14 +54,14 @@ def getText(self): else: ecm_time = ecm_info.get("ecm time", "").replace(".", "").lstrip("0") + " msec" - #from (oscam) + # from (oscam) from_item = ecm_info.get("from", "") from_splitted = from_item.split(":") - #protocol + # protocol protocol = ecm_info.get("protocol", "") # server server = from_splitted[0].strip() - #port + # port port = from_splitted[1].strip() if len(from_splitted) > 1 else "" # source if from_splitted[0].strip() == "local": @@ -70,28 +70,28 @@ def getText(self): source = "net" # hops hops = ecm_info.get("hops", "") - #system - system = ecm_info.get("system", "") - #provider - provider = ecm_info.get("provider", "") + # system + # system = ecm_info.get("system", "") + # provider + # provider = ecm_info.get("provider", "") # reader reader = ecm_info.get("reader", "") if source == "emu": - textvalue = "%s - %s (Caid: %s, Prov: %s,)" % (source, caid, caid, prov) - #new oscam ecm.info with port parametr + textvalue = f"{source} - {caid} (Caid: {caid}, Prov: {prov},)" + # new oscam ecm.info with port parametr elif reader != "" and source == "net" and port != "": - textvalue = "%s - Caid: %s, Prov: %s, Reader: %s, %s (%s:%s@%s) - %s" % (source, caid, prov, reader, protocol, server, port, hops, ecm_time.replace('msec', 'ms')) + textvalue = f"{source} - Caid: {caid}, Prov: {prov}, Reader: {reader}, {protocol} ({server}:{port}@{hops}) - {ecm_time.replace('msec', 'ms')}" elif reader != "" and source == "net": - textvalue = "%s - Caid: %s, Prov: %s, Reader: %s, %s (%s@%s) - %s" % (source, caid, prov, reader, protocol, server, hops, ecm_time.replace('msec', 'ms')) + textvalue = f"{source} - Caid: {caid}, Prov: {prov}, Reader: {reader}, {protocol} ({server}@{hops}) - {ecm_time.replace('msec', 'ms')}" elif reader != "" and source != "net": - textvalue = "%s - Caid: %s, Prov: %s, Reader: %s, %s (local) - %s" % (source, caid, prov, reader, protocol, ecm_time.replace('msec', 'ms')) + textvalue = f"{source} - Caid: {caid}, Prov: {prov}, Reader: {reader}, {protocol} (local) - {ecm_time.replace('msec', 'ms')}" elif server == "" and port == "" and protocol != "": - textvalue = "%s - Caid: %s, Prov: %s, %s - %s" % (source, caid, prov, protocol, ecm_time.replace('msec', 'ms')) + textvalue = f"{source} - Caid: {caid}, Prov: {prov}, {protocol} - {ecm_time.replace('msec', 'ms')}" elif server == "" and port == "" and protocol == "": - textvalue = "%s - Caid: %s - %s, Prov: %s" % (source, prov, caid, ecm_time.replace('msec', 'ms')) + textvalue = f"{source} - Caid: {caid}- {ecm_time.replace('msec', 'ms')}, Prov: {prov}" else: try: - textvalue = "%s - Caid: %s, Prov: %s, %s (%s:%s) - %s" % (source, caid, prov, protocol, server, port, ecm_time.replace('msec', 'ms')) + textvalue = f"{source} - Caid: {caid}, Prov: {prov}, {protocol} ({server}:{port}) - {ecm_time.replace('msec', 'ms')}" except: pass else: diff --git a/lib/python/Components/Converter/ServiceInfo.py b/lib/python/Components/Converter/ServiceInfo.py index 777cd26a079..6c3e9481f02 100644 --- a/lib/python/Components/Converter/ServiceInfo.py +++ b/lib/python/Components/Converter/ServiceInfo.py @@ -1,10 +1,10 @@ -from Components.Converter.Converter import Converter from enigma import iServiceInformation, iPlayableService -from Screens.InfoBarGenerics import hasActiveSubservicesForCurrentChannel -from Components.Element import cached + +from Components.Converter.Converter import Converter from Components.Converter.Poll import Poll from Components.Converter.VAudioInfo import StdAudioDesc -from Components.config import config +from Components.Element import cached +from Screens.InfoBarGenerics import hasActiveSubservicesForCurrentChannel from Tools.Transponder import ConvertToHumanReadable WIDESCREEN = [3, 4, 7, 8, 0xB, 0xC, 0xF, 0x10] diff --git a/lib/python/Screens/InfoBar.py b/lib/python/Screens/InfoBar.py index b847b1f59a5..348b2d67335 100644 --- a/lib/python/Screens/InfoBar.py +++ b/lib/python/Screens/InfoBar.py @@ -212,7 +212,7 @@ def showMovies(self, defaultRef=None): self.lastservice = self.session.nav.getCurrentlyPlayingServiceOrGroup() if self.lastservice and ':0:/' in self.lastservice.toString(): self.lastservice = enigma.eServiceReference(config.movielist.curentlyplayingservice.value) - self.session.openWithCallback(self.movieSelected, Screens.MovieSelection.MovieSelection, defaultRef or enigma.eServiceReference(config.usage.last_movie_played.value)) # , timeshiftEnabled=self.timeshiftEnabled()) # skip running stat here for no reason + self.session.openWithCallback(self.movieSelected, Screens.MovieSelection.MovieSelection, defaultRef or enigma.eServiceReference(config.usage.last_movie_played.value)) # , timeshiftEnabled=self.timeshiftEnabled()) skip running stat here for no reason def movieSelected(self, service): ref = self.lastservice diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py index a663a0b6aa9..63caf62637b 100644 --- a/lib/python/Screens/InfoBarGenerics.py +++ b/lib/python/Screens/InfoBarGenerics.py @@ -53,7 +53,6 @@ from Tools.Directories import pathExists, fileExists from Tools.KeyBindings import getKeyDescription, getKeyBindingKeys from Tools.General import isIPTV -from pickle import loads as pickle_loads import NavigationInstance From 9e42c0e579570ff7d44d96663de2a965ddf5dec1 Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Sat, 24 Feb 2024 12:12:03 +0100 Subject: [PATCH 158/183] [PacketManager] PEP8 - step 2 cleanup --- .../Plugins/SystemPlugins/ViX/PackageManager.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py index 746e3c8cebd..3b4a900ac2f 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py +++ b/lib/python/Plugins/SystemPlugins/ViX/PackageManager.py @@ -1,5 +1,3 @@ -from time import time - from Components.Console import Console from Components.Ipkg import IpkgComponent from Components.Sources.List import List @@ -47,7 +45,7 @@ class PackageManager(Screen): 5, 50, 540, 2, 22, 14, # font 52, # itemHeight - ] + ] # noqa: E124 def __init__(self, session): Screen.__init__(self, session) @@ -167,9 +165,9 @@ def OpkgList_Finished(self, result, retval, extra_args=None): tokens = x.split(" - ") name = tokens[0].strip() if name and not any(name.endswith(x) for x in self.unwanted_extensions): - l = len(tokens) - version = l > 1 and tokens[1].strip() or "" - descr = l > 2 and tokens[2].strip() or "" + tokenLength = len(tokens) + version = tokenLength > 1 and tokens[1].strip() or "" + descr = tokenLength > 2 and tokens[2].strip() or "" if name == last_name: continue last_name = name @@ -200,8 +198,8 @@ def parseResult(self, result): tokens = x.split(" - ") name = tokens[0].strip() if not any(name.endswith(x) for x in self.unwanted_extensions): - l = len(tokens) - version = l > 1 and tokens[-1].strip() or "" + tokenLength = len(tokens) + version = tokenLength > 1 and tokens[-1].strip() or "" packages[name] = version return packages From 75b8b4339336916da081edc3b4e31d87dcaab319 Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Sat, 24 Feb 2024 12:21:01 +0100 Subject: [PATCH 159/183] [PowerTimer] - f string cleanup --- lib/python/PowerTimer.py | 57 +++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 33 deletions(-) diff --git a/lib/python/PowerTimer.py b/lib/python/PowerTimer.py index 2bab472a8ec..2ccf7fcfe76 100644 --- a/lib/python/PowerTimer.py +++ b/lib/python/PowerTimer.py @@ -88,9 +88,9 @@ def __repr__(self): TIMERTYPE.RESTART: "restart" }[self.timerType] if not self.disabled: - return "PowerTimerEntry(type=%s, begin=%s)" % (timertype, ctime(self.begin)) + return f"PowerTimerEntry(type={timertype}, begin={ctime(self.begin)})" else: - return "PowerTimerEntry(type=%s, begin=%s Disabled)" % (timertype, ctime(self.begin)) + return f"PowerTimerEntry(type={timertype}, begin={ctime(self.begin)} Disabled)" def log(self, code, msg): self.log_entries.append((int(time()), code, msg)) @@ -107,7 +107,7 @@ def do_backoff(self): self.backoff *= 2 if self.backoff > 1800: self.backoff = 1800 - self.log(10, "backoff: retry in %d minutes" % (int(self.backoff) / 60)) + self.log(10, f"backoff: retry in {int(self.backoff) / 60} minutes") # # If this is the first backoff of a repeat timer remember the original # begin/end times, so that we can use *these* when setting up the repeat. @@ -124,7 +124,7 @@ def do_backoff(self): def activate(self): next_state = self.state + 1 - self.log(5, "activating state %d" % next_state) + self.log(5, f"activating state {next_state}") if next_state == self.StatePrepared and (self.timerType == TIMERTYPE.AUTOSTANDBY or self.timerType == TIMERTYPE.AUTODEEPSTANDBY): # This is the first action for an auto* timer. @@ -164,7 +164,7 @@ def activate(self): elif self.timerType == TIMERTYPE.STANDBY: if not Screens.Standby.inStandby: # not already in standby - Notifications.AddNotificationWithUniqueIDCallback(self.sendStandbyNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to set your\n%s %s to standby. Do that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendStandbyNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to set your\n{SystemInfo['MachineBrand']} {SystemInfo['MachineName']} to standby. Do that now?"), timeout=180) return True elif self.timerType == TIMERTYPE.AUTOSTANDBY: @@ -173,7 +173,7 @@ def activate(self): # retry return False if not Screens.Standby.inStandby: # not already in standby - Notifications.AddNotificationWithUniqueIDCallback(self.sendStandbyNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to set your\n%s %s to standby. Do that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendStandbyNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to set your\n{SystemInfo['MachineBrand']} {SystemInfo['MachineName']} to standby. Do that now?"), timeout=180) if self.autosleeprepeat == "once": eActionMap.getInstance().unbindAction('', self.keyPressed) return True @@ -213,7 +213,7 @@ def activate(self): quitMainloop(1) return True else: - Notifications.AddNotificationWithUniqueIDCallback(self.sendTryQuitMainloopNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to shutdown your %s %s.\nDo that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendTryQuitMainloopNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to shutdown your {SystemInfo['MachineBrand']} {SystemInfo['MachineName']}.\nDo that now?"), timeout=180) if self.autosleeprepeat == "once": eActionMap.getInstance().unbindAction('', self.keyPressed) return True @@ -234,7 +234,7 @@ def activate(self): if Screens.Standby.inStandby: # in standby quitMainloop(1) else: - Notifications.AddNotificationWithUniqueIDCallback(self.sendTryQuitMainloopNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to shutdown your %s %s.\nDo that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendTryQuitMainloopNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to shutdown your {SystemInfo['MachineBrand']} {SystemInfo['MachineName']}.\nDo that now?"), timeout=180) return True elif self.timerType == TIMERTYPE.REBOOT: @@ -246,7 +246,7 @@ def activate(self): if Screens.Standby.inStandby: # in standby quitMainloop(2) else: - Notifications.AddNotificationWithUniqueIDCallback(self.sendTryToRebootNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to reboot your %s %s.\nDo that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendTryToRebootNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to reboot your {SystemInfo['MachineBrand']} {SystemInfo['MachineName']}.\nDo that now?"), timeout=180) return True elif self.timerType == TIMERTYPE.RESTART: @@ -265,7 +265,7 @@ def activate(self): NavigationInstance.instance.PowerTimer.saveTimer() if self.afterEvent == AFTEREVENT.STANDBY: if not Screens.Standby.inStandby: # not already in standby - Notifications.AddNotificationWithUniqueIDCallback(self.sendStandbyNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to set your\n%s %s to standby. Do that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendStandbyNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to set your\n{SystemInfo['MachineBrand']} {SystemInfo['MachineName']} to standby. Do that now?"), timeout=180) elif self.afterEvent == AFTEREVENT.DEEPSTANDBY: if NavigationInstance.instance.RecordTimer.isRecording() or abs(NavigationInstance.instance.RecordTimer.getNextRecordingTime() - time()) <= 900 or abs(NavigationInstance.instance.RecordTimer.getNextZapTime() - time()) <= 900: self.do_backoff() @@ -275,7 +275,7 @@ def activate(self): if Screens.Standby.inStandby: # in standby quitMainloop(1) else: - Notifications.AddNotificationWithUniqueIDCallback(self.sendTryQuitMainloopNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to shutdown your %s %s.\nDo that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendTryQuitMainloopNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to shutdown your {SystemInfo['MachineBrand']} {SystemInfo['MachineName']}.\nDo that now?"), timeout=180) return True def setAutoincreaseEnd(self, entry=None): @@ -349,7 +349,7 @@ def timeChanged(self): self.backoff = 0 if int(old_prepare) > 60 and int(old_prepare) != int(self.start_prepare): - self.log(15, "time changed, start prepare is now: %s" % ctime(self.start_prepare)) + self.log(15, f"time changed, start prepare is now: {ctime(self.start_prepare)}") def createTimer(xml): @@ -480,7 +480,7 @@ def loadTimer(self): checkit = False # at moment it is enough when the message is displayed one time def saveTimer(self): - timerTypes = { + timerTypes = { # noqa: F841 TIMERTYPE.WAKEUP: "wakeup", TIMERTYPE.WAKEUPTOSTANDBY: "wakeuptostandby", TIMERTYPE.AUTOSTANDBY: "autostandby", @@ -490,7 +490,7 @@ def saveTimer(self): TIMERTYPE.REBOOT: "reboot", TIMERTYPE.RESTART: "restart" } - afterEvents = { + afterEvents = { # noqa: F841 AFTEREVENT.NONE: "nothing", AFTEREVENT.WAKEUPTOSTANDBY: "wakeuptostandby", AFTEREVENT.STANDBY: "standby", @@ -503,30 +503,21 @@ def saveTimer(self): continue list.append( '\n') else: for log_time, code, msg in timer.log_entries: - list.append('>\n%s\n{stringToXML(msg)}\n\n') list.append('\n') From f863933361e7049241cddf968c46f8b30df8fcd8 Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Sat, 24 Feb 2024 12:25:00 +0100 Subject: [PATCH 160/183] [RecordTimer] - f string cleanup --- lib/python/RecordTimer.py | 97 +++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 56 deletions(-) diff --git a/lib/python/RecordTimer.py b/lib/python/RecordTimer.py index 5dd8ee5099b..2096713bdc8 100644 --- a/lib/python/RecordTimer.py +++ b/lib/python/RecordTimer.py @@ -92,7 +92,7 @@ def findSafeRecordPath(dirname): try: makedirs(dirname) except Exception as ex: - print("[RecordTimer] Failed to create dir '%s':" % dirname, ex) + print(f"[RecordTimer] Failed to create dir '{dirname}':", ex) return None return dirname @@ -286,11 +286,11 @@ def __init__(self, serviceref, begin, end, name, description, eit, disabled=Fals def __repr__(self): ice = "" if self.ice_timer_id is not None: - ice = ", ice_timer_id=%s" % self.ice_timer_id + ice = f", ice_timer_id={self.ice_timer_id}" if not self.disabled: - return "RecordTimerEntry(name=%s, begin=%s, serviceref=%s, justplay=%s, isAutoTimer=%s, autoTimerId=%s%s)" % (self.name, ctime(self.begin), self.service_ref, self.justplay, self.isAutoTimer, self.autoTimerId, ice) + return f"RecordTimerEntry(name={self.name}, begin={ctime(self.begin)}, serviceref={self.service_ref}, justplay={self.justplay}, isAutoTimer={self.isAutoTimer}, autoTimerId={self.autoTimerId}{ice})" else: - return "RecordTimerEntry(name=%s, begin=%s, serviceref=%s, justplay=%s, isAutoTimer=%s, autoTimerId=%s%s, Disabled)" % (self.name, ctime(self.begin), self.service_ref, self.justplay, self.isAutoTimer, self.autoTimerId, ice) + return f"RecordTimerEntry(name={self.name}, begin={ctime(self.begin)}, serviceref={self.service_ref}, justplay={self.justplay}, isAutoTimer={self.isAutoTimer}, autoTimerId={self.autoTimerId}{ice}, Disabled)" def log(self, code, msg): self.log_entries.append((int(time()), code, msg)) @@ -311,7 +311,7 @@ def freespace(self): self.MountPath = dirname mountwriteable = access(dirname, W_OK) if not mountwriteable: - self.log(0, ("Mount '%s' is not writeable." % dirname)) + self.log(0, f"Mount '{dirname}' is not writeable.") return False s = statvfs(dirname) @@ -350,7 +350,7 @@ def calculateFilename(self, name=None): filename = ASCIItranslit.legacyEncode(filename) self.Filename = Directories.getRecordingFilename(filename, self.MountPath) - self.log(0, "Filename calculated as: '%s'" % self.Filename) + self.log(0, f"Filename calculated as: '{self.Filename}'") return self.Filename def getEventFromEPGId(self, id=None): @@ -421,7 +421,7 @@ def tryPrepare(self): if prep_res == -255: self.log(4, "failed to write meta information") else: - self.log(2, "'prepare' failed: error %d" % prep_res) + self.log(2, f"'prepare' failed: error {prep_res}") # we must calc new start time before stopRecordService call because in Screens/Standby.py TryQuitMainloop tries to get # the next start time in evEnd event handler... @@ -441,7 +441,7 @@ def do_backoff(self): self.backoff *= 2 if self.backoff > 100: self.backoff = 100 - self.log(10, "backoff: retry in %d seconds" % self.backoff) + self.log(10, f"backoff: retry in {self.backoff} seconds") def sendactivesource(self): if SystemInfo["hasHdmiCec"] and config.hdmicec.enabled.value and config.hdmicec.sourceactive_zaptimers.value: # Command the TV to switch to the correct HDMI input when zap timers activate @@ -467,7 +467,7 @@ def _bouquet_search(self): if config.usage.multibouquet.value: bqrootstr = '1:7:1:0:0:0:0:0:0:0:FROM BOUQUET "bouquets.tv" ORDER BY bouquet' else: - bqrootstr = '%s FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet' % self.service_types + bqrootstr = f'{self.service_types} FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet' serviceHandler = eServiceCenter.getInstance() rootbouquet = eServiceReference(bqrootstr) bouquet = eServiceReference(bqrootstr) @@ -505,7 +505,7 @@ def log_tuner(self, level, state): # Report the tuner that the current record feinfo = timer_rs and hasattr(timer_rs, "frontendInfo") and timer_rs.frontendInfo() fedata = feinfo and hasattr(feinfo, "getFrontendData") and feinfo.getFrontendData() tuner_info = fedata and "tuner_number" in fedata and chr(ord("A") + fedata.get("tuner_number")) or "(fallback) stream" - self.log(level, "%s recording on tuner: %s" % (state, tuner_info)) + self.log(level, f"{state} recording on tuner: {tuner_info}") def activate(self): if not self.InfoBarInstance: @@ -515,11 +515,11 @@ def activate(self): print("[RecordTimer] import 'Screens.InfoBar' failed") next_state = self.state + 1 - self.log(5, "activating state %d (%s)" % (next_state, TimerEntry.States.get(next_state, "?"))) + self.log(5, f"activating state {next_state} {TimerEntry.States.get(next_state, '?')}") if next_state == self.StatePrepared: if not self.justplay and not self.freespace(): - Notifications.AddPopup(text=_("Write error while recording. Disk full?\n%s") % self.name, type=MessageBox.TYPE_ERROR, timeout=5, id="DiskFullMessage") + Notifications.AddPopup(text=_(f"Write error while recording. Disk full?\n{self.name}"), type=MessageBox.TYPE_ERROR, timeout=5, id="DiskFullMessage") self.failed = True self.next_activation = time() self.end = time() + 5 @@ -652,7 +652,7 @@ def activate(self): self.InfoBarInstance.session.pip.servicePath = self.InfoBarInstance.servicelist and self.InfoBarInstance.servicelist.getCurrentServicePath() self.log(11, "zapping as PiP") if notify: - Notifications.AddPopup(text=_("Zapped to timer service %s as PiP!") % self.service_ref.getServiceName(), type=MessageBox.TYPE_INFO, timeout=5) + Notifications.AddPopup(text=_(f"Zapped to timer service {self.service_ref.getServiceName()} as PiP!"), type=MessageBox.TYPE_INFO, timeout=5) return True else: del self.InfoBarInstance.session.pip @@ -663,7 +663,7 @@ def activate(self): else: self.log(11, "zapping") if notify: - Notifications.AddPopup(text=_("Zapped to timer service %s!") % self.service_ref.getServiceName(), type=MessageBox.TYPE_INFO, timeout=5) + Notifications.AddPopup(text=_(f"Zapped to timer service {self.service_ref.getServiceName()}!"), type=MessageBox.TYPE_INFO, timeout=5) # If the user is looking at a MovieList then we need to update this # lastservice, so that we get back to the updated one when closing the @@ -691,7 +691,7 @@ def activate(self): record_res = self.record_service.start() self.setRecordingPreferredTuner(setdefault=True) if record_res: - self.log(13, "start recording error: %d" % record_res) + self.log(13, f"start recording error: {record_res}") self.do_backoff() # retry self.begin = time() + self.backoff @@ -703,7 +703,7 @@ def activate(self): old_end = self.end self.ts_dialog = None if self.setAutoincreaseEnd(): - self.log(12, "autoincrease recording %d minute(s)" % int((self.end - old_end) / 60)) + self.log(12, f"autoincrease recording {int(self.end - old_end) / 60} minute(s)") self.state -= 1 return True self.log_tuner(12, "stop") @@ -736,7 +736,7 @@ def activate(self): if self.afterEvent == AFTEREVENT.STANDBY or (not wasRecTimerWakeup and self.autostate and self.afterEvent == AFTEREVENT.AUTO) or self.wasInStandby: self.keypress() # this unbinds the keypress detection if not Screens.Standby.inStandby: # not already in standby - Notifications.AddNotificationWithCallback(self.sendStandbyNotification, MessageBox, _("A finished record timer wants to set your\n%s %s to standby. Do that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) + Notifications.AddNotificationWithCallback(self.sendStandbyNotification, MessageBox, _(f"A finished record timer wants to set your\n{SystemInfo['MachineBrand']} {SystemInfo['MachineName']} to standby. Do that now?"), timeout=180) elif self.afterEvent == AFTEREVENT.DEEPSTANDBY or (wasRecTimerWakeup and self.afterEvent == AFTEREVENT.AUTO and Screens.Standby.inStandby): if (abs(NavigationInstance.instance.RecordTimer.getNextRecordingTime() - time()) <= 900 or abs(NavigationInstance.instance.RecordTimer.getNextZapTime() - time()) <= 900) or NavigationInstance.instance.RecordTimer.getStillRecording(): print("[RecordTimer] Recording or Recording due is next 15 mins, not return to deepstandby") @@ -751,7 +751,7 @@ def activate(self): if int(ClientsStreaming("NUMBER").getText()) > 0: if not Screens.Standby.inStandby: # not already in standby Notifications.AddNotificationWithCallback(self.sendStandbyNotification, MessageBox, - _("A finished record timer wants to set your\n%s %s to standby. Do that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]) + _(f"A finished record timer wants to set your\n{SystemInfo['MachineBrand']} {SystemInfo['MachineName']} to standby. Do that now?") + _("\n(DeepStandby request changed to Standby owing to there being streaming clients.)"), timeout=180) return True @@ -759,7 +759,7 @@ def activate(self): if Screens.Standby.inStandby: # in standby quitMainloop(1) else: - Notifications.AddNotificationWithCallback(self.sendTryQuitMainloopNotification, MessageBox, _("A finished record timer wants to shut down\nyour %s %s. Shutdown now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) + Notifications.AddNotificationWithCallback(self.sendTryQuitMainloopNotification, MessageBox, _(f"A finished record timer wants to shut down\nyour {SystemInfo['MachineBrand']} {SystemInfo['MachineName']}. Shutdown now?"), timeout=180) return True def keypress(self, key=None, flag=1): @@ -811,7 +811,7 @@ def openChoiceActionBeforeZap(self): type = _("zap") elif self.always_zap: type = _("zap and record") - message = _("You must switch to the service %s (%s - '%s')!\n") % (type, self.service_ref.getServiceName(), self.name) + message = _(f"You must switch to the service {type} ({self.service_ref.getServiceName()} - '{self.name}')!\n") if self.repeated: message += _("Attention, this is repeated timer!\n") message += _("Timeshift is running. Select an action.\n") @@ -903,13 +903,13 @@ def timeChanged(self): self.backoff = 0 if int(old_prepare) > 60 and int(old_prepare) != int(self.start_prepare): - self.log(15, "record time changed, start prepare is now: %s" % ctime(self.start_prepare)) + self.log(15, f"record time changed, start prepare is now: {ctime(self.start_prepare)}") def gotRecordEvent(self, record, event): # TODO: this is not working (never true), please fix. (comparing two swig wrapped ePtrs) if self.__record_service.__deref__() != record.__deref__(): return - # self.log(16, "record event %d" % event) + # self.log(16, f"record event {event}") if event == iRecordableService.evRecordWriteError: print("[RecordTimer] WRITE ERROR on recording, disk full?") # show notification. the "id" will make sure that it will be @@ -921,7 +921,7 @@ def gotRecordEvent(self, record, event): # TODO: this has to be done. elif event == iRecordableService.evStart: RecordingsState(1) - text = _("A recording has been started:\n%s") % self.name + text = _(f"A recording has been started:\n{self.name}") notify = config.usage.show_message_when_recording_starts.value and not Screens.Standby.inStandby and self.InfoBarInstance and self.InfoBarInstance.execing if self.dirnameHadToFallback: text = "\n".join((text, _("Please note that the previously selected media could not be accessed and therefore the default directory is being used instead."))) @@ -1100,7 +1100,7 @@ def loadTimer(self, justLoad=False): # justLoad is passed on to record() if conflict_list: checkit = True if newTimer in conflict_list: - timer_text += _("\nTimer '%s' disabled!") % newTimer.name + timer_text += _(f"\nTimer '{newTimer.name}' disabled!") if checkit: from Tools.Notifications import AddPopup from Screens.MessageBox import MessageBox @@ -1120,36 +1120,21 @@ def saveTimer(self): continue list.append( '\n') else: for log_time, code, msg in entry.log_entries: - list.append('>\n%s\n{stringToXML(msg)}\n\n') list.append('\n') @@ -1284,7 +1269,7 @@ def record(self, entry, ignoreTSC=False, dosave=True, loadtimer=False, justLoad= entry.begin += 1 entry.conflict_detection = real_cd entry.timeChanged() - # print("[Timer] Record %s" % entry) + # print(f"[Timer] Record {entry}") entry.Timer = self self.addTimerEntry(entry) From 1b8b26cde26fcee15ccf7bb4a04dd0a2ebb81f63 Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Sat, 24 Feb 2024 12:30:25 +0100 Subject: [PATCH 161/183] [StartEnigma] - f string cleanup --- lib/python/StartEnigma.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/python/StartEnigma.py b/lib/python/StartEnigma.py index 5d5c562bc17..63d9e3fc3b5 100644 --- a/lib/python/StartEnigma.py +++ b/lib/python/StartEnigma.py @@ -208,7 +208,7 @@ def reloadSkin(self): # close all open dialogs by emptying the dialog stack # remove any return values and callbacks for a swift exit while self.current_dialog is not None and type(self.current_dialog) is not InfoBar.InfoBar: - print("[SkinReloader] closing %s" % type(self.current_dialog)) + print(f"[SkinReloader] closing {type(self.current_dialog)}") self.current_dialog.returnValue = None self.current_dialog.callback = None self.execEnd() @@ -439,11 +439,11 @@ def runNextScreen(session, screensToRun, *result): from Components.SystemInfo import SystemInfo # noqa: E402 don't move this import print("[StartEnigma] Starting Python Level Initialisation.") -print("[StartEnigma] Image Type -> '%s'" % SystemInfo["imagetype"]) -print("[StartEnigma] Image Version -> '%s'" % SystemInfo["imageversion"]) -print("[StartEnigma] Image Build -> '%s'" % SystemInfo["imagebuild"]) +print(f"[StartEnigma] Image Type -> {SystemInfo['imagetype']}") +print(f"[StartEnigma] Image Version -> {SystemInfo['imageversion']}") +print(f"[StartEnigma] Image Build -> {SystemInfo['imagebuild']}") if SystemInfo["imagetype"] != "release": - print("[StartEnigma] Image DevBuild -> '%s'" % SystemInfo["imagedevbuild"]) + print(f"[StartEnigma] Image DevBuild -> {SystemInfo['imagedevbuild']}") # SetupDevices sets up defaults:- language, keyboard, parental & expert config. From 693c251d82f7726d4c479057c71ba529afb6dd2f Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Sun, 25 Feb 2024 13:38:33 +0100 Subject: [PATCH 162/183] [SoftcamManager] PEP8 --- lib/python/Plugins/SystemPlugins/ViX/SoftcamManager.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/python/Plugins/SystemPlugins/ViX/SoftcamManager.py b/lib/python/Plugins/SystemPlugins/ViX/SoftcamManager.py index 30bcf119716..7c10b62f81b 100644 --- a/lib/python/Plugins/SystemPlugins/ViX/SoftcamManager.py +++ b/lib/python/Plugins/SystemPlugins/ViX/SoftcamManager.py @@ -383,7 +383,7 @@ def startShow(self): if data.find(startselectedcam) >= 0: filewrite = open("/tmp/SoftcamsScriptsRunning.tmp", "w") fileread = open("/tmp/SoftcamsScriptsRunning") - filewrite.writelines([x for x in fileread.readlines() if startselectedcam not in x]) + filewrite.writelines([cam for cam in fileread.readlines() if startselectedcam not in cam]) fileread.close() filewrite.close() rename("/tmp/SoftcamsScriptsRunning.tmp", "/tmp/SoftcamsScriptsRunning") @@ -415,7 +415,7 @@ def startShow(self): output.close() fileread = open("/tmp/SoftcamsDisableCheck") filewrite = open("/tmp/SoftcamsDisableCheck.tmp", "w") - filewrite.writelines([x for x in fileread.readlines() if startselectedcam not in x]) + filewrite.writelines([cam for cam in fileread.readlines() if startselectedcam not in cam]) fileread.close() filewrite.close() rename("/tmp/SoftcamsDisableCheck.tmp", "/tmp/SoftcamsDisableCheck") @@ -752,7 +752,7 @@ def JobStart(self): f = open(camconf, "r") for line in f.readlines(): if line.find("httpport") != -1: - port = re.sub("\D", "", line) # noqa: W605 + port = re.sub(r"\D", "", line) f.close() print("[SoftcamManager] Checking if " + softcamcheck + " is frozen") if port == "": @@ -826,7 +826,7 @@ def JobStart(self): if parts[0].startswith("yes"): allow = parts[0] if line.find("WEBINFO LISTEN PORT") != -1: - port = re.sub("\D", "", line) # noqa: W605 + port = re.sub(r"\D", "", line) f.close() if allow.lower().find("yes") != -1: print("[SoftcamManager] Checking if " + softcamcheck + " is frozen") From 741ceaffa89e783f9b6b94386adba40b77f3850d Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Sun, 25 Feb 2024 17:12:08 +0200 Subject: [PATCH 163/183] [Added] Stream url to the Swervicename converter --- lib/python/Components/Converter/ServiceName.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/python/Components/Converter/ServiceName.py b/lib/python/Components/Converter/ServiceName.py index c422f68c111..679a4ebadae 100644 --- a/lib/python/Components/Converter/ServiceName.py +++ b/lib/python/Components/Converter/ServiceName.py @@ -16,7 +16,8 @@ class ServiceName(Converter): PROVIDER = 3 REFERENCE = 4 EDITREFERENCE = 5 - FORMAT_STRING = 6 + STREAM_URL = 6 + FORMAT_STRING = 7 def __init__(self, type): Converter.__init__(self, type) @@ -36,6 +37,8 @@ def __init__(self, type): self.type = self.NAME_ONLY elif type == "NameAndEvent": self.type = self.NAME_EVENT + elif type == "StreamUrl": + self.type = self.STREAM_URL else: self.type = self.NAME @@ -87,6 +90,17 @@ def getText(self): if nref: service = nref return service.toString() + elif self.type == self.STREAM_URL: + srpart = "//%s:%s/" % (config.misc.softcam_streamrelay_url.getHTML(), config.misc.softcam_streamrelay_port.value) + if not service: + refstr = info.getInfoString(iServiceInformation.sServiceref) + path = refstr and eServiceReference(refstr).getPath() + if not path.startswith("//") and path.find(srpart) == -1: + return path + else: + return "" + path = service.getPath() + return "" if path.startswith("//") and path.find(srpart) == -1 else path elif self.type == self.FORMAT_STRING: name = self.getName(service, info) numservice = hasattr(self.source, "serviceref") and self.source.serviceref From 8a9afa0de2e95e9b48d3262d1b4658a1af52b9d1 Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Wed, 28 Feb 2024 15:54:10 +0100 Subject: [PATCH 164/183] [PowerTimer/RecordTimer] - revert notifications so that correct localisation happens --- lib/python/PowerTimer.py | 14 +++++++------- lib/python/RecordTimer.py | 18 +++++++++--------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/python/PowerTimer.py b/lib/python/PowerTimer.py index 2ccf7fcfe76..b72e318757d 100644 --- a/lib/python/PowerTimer.py +++ b/lib/python/PowerTimer.py @@ -164,7 +164,7 @@ def activate(self): elif self.timerType == TIMERTYPE.STANDBY: if not Screens.Standby.inStandby: # not already in standby - Notifications.AddNotificationWithUniqueIDCallback(self.sendStandbyNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to set your\n{SystemInfo['MachineBrand']} {SystemInfo['MachineName']} to standby. Do that now?"), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendStandbyNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to set your\n%s %s to standby. Do that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) return True elif self.timerType == TIMERTYPE.AUTOSTANDBY: @@ -173,7 +173,7 @@ def activate(self): # retry return False if not Screens.Standby.inStandby: # not already in standby - Notifications.AddNotificationWithUniqueIDCallback(self.sendStandbyNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to set your\n{SystemInfo['MachineBrand']} {SystemInfo['MachineName']} to standby. Do that now?"), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendStandbyNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to set your\n%s %s to standby. Do that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) if self.autosleeprepeat == "once": eActionMap.getInstance().unbindAction('', self.keyPressed) return True @@ -213,7 +213,7 @@ def activate(self): quitMainloop(1) return True else: - Notifications.AddNotificationWithUniqueIDCallback(self.sendTryQuitMainloopNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to shutdown your {SystemInfo['MachineBrand']} {SystemInfo['MachineName']}.\nDo that now?"), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendTryQuitMainloopNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to shutdown your %s %s.\nDo that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) if self.autosleeprepeat == "once": eActionMap.getInstance().unbindAction('', self.keyPressed) return True @@ -234,7 +234,7 @@ def activate(self): if Screens.Standby.inStandby: # in standby quitMainloop(1) else: - Notifications.AddNotificationWithUniqueIDCallback(self.sendTryQuitMainloopNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to shutdown your {SystemInfo['MachineBrand']} {SystemInfo['MachineName']}.\nDo that now?"), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendTryQuitMainloopNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to shutdown your %s %s.\nDo that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) return True elif self.timerType == TIMERTYPE.REBOOT: @@ -246,7 +246,7 @@ def activate(self): if Screens.Standby.inStandby: # in standby quitMainloop(2) else: - Notifications.AddNotificationWithUniqueIDCallback(self.sendTryToRebootNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to reboot your {SystemInfo['MachineBrand']} {SystemInfo['MachineName']}.\nDo that now?"), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendTryToRebootNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to reboot your %s %s.\nDo that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) return True elif self.timerType == TIMERTYPE.RESTART: @@ -265,7 +265,7 @@ def activate(self): NavigationInstance.instance.PowerTimer.saveTimer() if self.afterEvent == AFTEREVENT.STANDBY: if not Screens.Standby.inStandby: # not already in standby - Notifications.AddNotificationWithUniqueIDCallback(self.sendStandbyNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to set your\n{SystemInfo['MachineBrand']} {SystemInfo['MachineName']} to standby. Do that now?"), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendStandbyNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to set your\n%s %s to standby. Do that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) elif self.afterEvent == AFTEREVENT.DEEPSTANDBY: if NavigationInstance.instance.RecordTimer.isRecording() or abs(NavigationInstance.instance.RecordTimer.getNextRecordingTime() - time()) <= 900 or abs(NavigationInstance.instance.RecordTimer.getNextZapTime() - time()) <= 900: self.do_backoff() @@ -275,7 +275,7 @@ def activate(self): if Screens.Standby.inStandby: # in standby quitMainloop(1) else: - Notifications.AddNotificationWithUniqueIDCallback(self.sendTryQuitMainloopNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to shutdown your {SystemInfo['MachineBrand']} {SystemInfo['MachineName']}.\nDo that now?"), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendTryQuitMainloopNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to shutdown your %s %s.\nDo that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) return True def setAutoincreaseEnd(self, entry=None): diff --git a/lib/python/RecordTimer.py b/lib/python/RecordTimer.py index 2096713bdc8..3912897d248 100644 --- a/lib/python/RecordTimer.py +++ b/lib/python/RecordTimer.py @@ -519,7 +519,7 @@ def activate(self): if next_state == self.StatePrepared: if not self.justplay and not self.freespace(): - Notifications.AddPopup(text=_(f"Write error while recording. Disk full?\n{self.name}"), type=MessageBox.TYPE_ERROR, timeout=5, id="DiskFullMessage") + Notifications.AddPopup(text=_("Write error while recording. Disk full?\n%s") % self.name, type=MessageBox.TYPE_ERROR, timeout=5, id="DiskFullMessage") self.failed = True self.next_activation = time() self.end = time() + 5 @@ -652,7 +652,7 @@ def activate(self): self.InfoBarInstance.session.pip.servicePath = self.InfoBarInstance.servicelist and self.InfoBarInstance.servicelist.getCurrentServicePath() self.log(11, "zapping as PiP") if notify: - Notifications.AddPopup(text=_(f"Zapped to timer service {self.service_ref.getServiceName()} as PiP!"), type=MessageBox.TYPE_INFO, timeout=5) + Notifications.AddPopup(text=_("Zapped to timer service %s as PiP!") % self.service_ref.getServiceName(), type=MessageBox.TYPE_INFO, timeout=5) return True else: del self.InfoBarInstance.session.pip @@ -663,7 +663,7 @@ def activate(self): else: self.log(11, "zapping") if notify: - Notifications.AddPopup(text=_(f"Zapped to timer service {self.service_ref.getServiceName()}!"), type=MessageBox.TYPE_INFO, timeout=5) + Notifications.AddPopup(text=_("Zapped to timer service %s!") % self.service_ref.getServiceName(), type=MessageBox.TYPE_INFO, timeout=5) # If the user is looking at a MovieList then we need to update this # lastservice, so that we get back to the updated one when closing the @@ -736,7 +736,7 @@ def activate(self): if self.afterEvent == AFTEREVENT.STANDBY or (not wasRecTimerWakeup and self.autostate and self.afterEvent == AFTEREVENT.AUTO) or self.wasInStandby: self.keypress() # this unbinds the keypress detection if not Screens.Standby.inStandby: # not already in standby - Notifications.AddNotificationWithCallback(self.sendStandbyNotification, MessageBox, _(f"A finished record timer wants to set your\n{SystemInfo['MachineBrand']} {SystemInfo['MachineName']} to standby. Do that now?"), timeout=180) + Notifications.AddNotificationWithCallback(self.sendStandbyNotification, MessageBox, _("A finished record timer wants to set your\n%s %s to standby. Do that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) elif self.afterEvent == AFTEREVENT.DEEPSTANDBY or (wasRecTimerWakeup and self.afterEvent == AFTEREVENT.AUTO and Screens.Standby.inStandby): if (abs(NavigationInstance.instance.RecordTimer.getNextRecordingTime() - time()) <= 900 or abs(NavigationInstance.instance.RecordTimer.getNextZapTime() - time()) <= 900) or NavigationInstance.instance.RecordTimer.getStillRecording(): print("[RecordTimer] Recording or Recording due is next 15 mins, not return to deepstandby") @@ -751,7 +751,7 @@ def activate(self): if int(ClientsStreaming("NUMBER").getText()) > 0: if not Screens.Standby.inStandby: # not already in standby Notifications.AddNotificationWithCallback(self.sendStandbyNotification, MessageBox, - _(f"A finished record timer wants to set your\n{SystemInfo['MachineBrand']} {SystemInfo['MachineName']} to standby. Do that now?") + _("A finished record timer wants to set your\n%s %s to standby. Do that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]) + _("\n(DeepStandby request changed to Standby owing to there being streaming clients.)"), timeout=180) return True @@ -759,7 +759,7 @@ def activate(self): if Screens.Standby.inStandby: # in standby quitMainloop(1) else: - Notifications.AddNotificationWithCallback(self.sendTryQuitMainloopNotification, MessageBox, _(f"A finished record timer wants to shut down\nyour {SystemInfo['MachineBrand']} {SystemInfo['MachineName']}. Shutdown now?"), timeout=180) + Notifications.AddNotificationWithCallback(self.sendTryQuitMainloopNotification, MessageBox, _("A finished record timer wants to shut down\nyour %s %s. Shutdown now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) return True def keypress(self, key=None, flag=1): @@ -811,7 +811,7 @@ def openChoiceActionBeforeZap(self): type = _("zap") elif self.always_zap: type = _("zap and record") - message = _(f"You must switch to the service {type} ({self.service_ref.getServiceName()} - '{self.name}')!\n") + message = _("You must switch to the service %s (%s - '%s')!\n") % (type, self.service_ref.getServiceName(), self.name) if self.repeated: message += _("Attention, this is repeated timer!\n") message += _("Timeshift is running. Select an action.\n") @@ -921,7 +921,7 @@ def gotRecordEvent(self, record, event): # TODO: this has to be done. elif event == iRecordableService.evStart: RecordingsState(1) - text = _(f"A recording has been started:\n{self.name}") + text = _("A recording has been started:\n%s") % self.name notify = config.usage.show_message_when_recording_starts.value and not Screens.Standby.inStandby and self.InfoBarInstance and self.InfoBarInstance.execing if self.dirnameHadToFallback: text = "\n".join((text, _("Please note that the previously selected media could not be accessed and therefore the default directory is being used instead."))) @@ -1100,7 +1100,7 @@ def loadTimer(self, justLoad=False): # justLoad is passed on to record() if conflict_list: checkit = True if newTimer in conflict_list: - timer_text += _(f"\nTimer '{newTimer.name}' disabled!") + timer_text += _("\nTimer '%s' disabled!") % newTimer.name if checkit: from Tools.Notifications import AddPopup from Screens.MessageBox import MessageBox From 7827597f13a4e7e9592969ee5aa0a3ef77398663 Mon Sep 17 00:00:00 2001 From: Orlandoxx <95180049+Orlandoxx@users.noreply.github.com> Date: Wed, 28 Feb 2024 19:14:34 +0200 Subject: [PATCH 165/183] Updated Finnish (fi.po) translation --- po/fi.po | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/po/fi.po b/po/fi.po index 189affef2fa..37c0223cabd 100644 --- a/po/fi.po +++ b/po/fi.po @@ -5,7 +5,7 @@ msgstr "" "Project-Id-Version: enigma2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-12-27 23:35+0000\n" -"PO-Revision-Date: 2024-02-23 21:13+0200\n" +"PO-Revision-Date: 2024-02-28 19:12+0200\n" "Last-Translator: Orlandox\n" "Language-Team: timoj/Kojo/Samzam/Orlandox\n" "Language: fi\n" @@ -1593,8 +1593,8 @@ msgid "" "A finished powertimer wants to set your\n" "%s %s to standby. Do that now?" msgstr "" -"Valmis virta-ajastus haluaa sammuttaa\n" -"%s %s:n valmiustilaan. Sammutetaanko nyt?" +"Valmis virta-ajastus haluaa asettaa\n" +"%s %s:n valmiustilaan. Tehdäänkö se nyt?" #, python-format msgid "" @@ -1602,15 +1602,15 @@ msgid "" "Do that now?" msgstr "" "Valmis virta-ajastus haluaa sammuttaa\n" -"%s %s:n virransäästötilaan. Sammutetaanko nyt?" +"%s %s:n virransäästötilaan. Tehdäänkö se nyt?" #, python-format msgid "" "A finished record timer wants to set your\n" "%s %s to standby. Do that now?" msgstr "" -"Valmis tallennusajastus haluaa sammuttaa\n" -"%s %s:n valmiustilaan. Sammutetaanko nyt?" +"Valmis tallennusajastus haluaa asettaa\n" +"%s %s:n valmiustilaan. Tehdäänkö se nyt?" #, python-format msgid "" @@ -7219,7 +7219,7 @@ msgid "Information" msgstr "Tietoja" msgid "Infotainment" -msgstr "Informaatio" +msgstr "Ajankohtaisviihde" msgid "Init" msgstr "Palauta CA-moduulin alkuasetukset" @@ -13543,7 +13543,7 @@ msgstr "" "Suomenkielinen käännös: timoj, Kojo, Samzam, Orlandox\n" "\n" "Ylläpito : Orlandox\n" -"--- 23.02.2024 ---\n" +"--- 28.02.2024 ---\n" "\n" "http://www.huoltovalikko.com" @@ -16180,7 +16180,7 @@ msgstr "Kanavanvaihto ajastukseksi %s PiP:nä!" #, python-format msgid "Zapped to timer service %s!" -msgstr "Kanavanvaihto ajastukseksi %s!" +msgstr "Kanavanvaihto ajastukseksi: %s!" msgid "Zaps to EPG download transponder for EPG fetch." msgstr "Vaihto EPG:n lataustransponderiin EPG:n hakua varten." From 14c6ab7381b8bad83f1ddfafacc543db95f7d8eb Mon Sep 17 00:00:00 2001 From: Huevos Date: Thu, 29 Feb 2024 23:15:06 +0100 Subject: [PATCH 166/183] [ePicLoad] @Ocean character encoding patch --- lib/gdi/picload.cpp | 3 ++ lib/gdi/picload.h | 69 ++++++++++++++++++++++++++- lib/python/Components/MovieList.py | 2 +- lib/python/Components/VariableText.py | 9 +++- 4 files changed, 79 insertions(+), 4 deletions(-) diff --git a/lib/gdi/picload.cpp b/lib/gdi/picload.cpp index 2aecd0abe4b..08706ad32ef 100644 --- a/lib/gdi/picload.cpp +++ b/lib/gdi/picload.cpp @@ -942,7 +942,10 @@ void ePicLoad::gotMessage(const Message &msg) case Message::decode_finished: // called from main thread //eDebug("[ePicLoad] decode finished... %s", m_filepara->file); if(m_filepara->callback) + { + eDebug("[ePicLoad] picinfo... %s", m_filepara->picinfo.c_str()); PictureData(m_filepara->picinfo.c_str()); + } else { if(m_filepara != NULL) diff --git a/lib/gdi/picload.h b/lib/gdi/picload.h index cdcd3d25574..85114c1ee1c 100644 --- a/lib/gdi/picload.h +++ b/lib/gdi/picload.h @@ -31,10 +31,13 @@ struct Cfilepara palette_size(0), bits(24), id(mid), - picinfo(mfile), + picinfo(""), callback(true) { - picinfo += "\n" + size + "\n"; + if (is_valid_utf8(mfile)) + picinfo += std::string(mfile) + "\n" + size + "\n"; + else + picinfo += "\n" + size + "\n"; } ~Cfilepara() @@ -45,6 +48,59 @@ struct Cfilepara } void addExifInfo(std::string val) { picinfo += val + "\n"; } + bool is_valid_utf8(const char * string) + { + if (!string) + return true; + const unsigned char * bytes = (const unsigned char *)string; + unsigned int cp; + int num; + while (*bytes != 0x00) + { + if ((*bytes & 0x80) == 0x00) + { + // U+0000 to U+007F + cp = (*bytes & 0x7F); + num = 1; + } + else if ((*bytes & 0xE0) == 0xC0) + { + // U+0080 to U+07FF + cp = (*bytes & 0x1F); + num = 2; + } + else if ((*bytes & 0xF0) == 0xE0) + { + // U+0800 to U+FFFF + cp = (*bytes & 0x0F); + num = 3; + } + else if ((*bytes & 0xF8) == 0xF0) + { + // U+10000 to U+10FFFF + cp = (*bytes & 0x07); + num = 4; + } + else + return false; + bytes += 1; + for (int i = 1; i < num; ++i) + { + if ((*bytes & 0xC0) != 0x80) + return false; + cp = (cp << 6) | (*bytes & 0x3F); + bytes += 1; + } + if ((cp > 0x10FFFF) || + ((cp >= 0xD800) && (cp <= 0xDFFF)) || + ((cp <= 0x007F) && (num != 1)) || + ((cp >= 0x0080) && (cp <= 0x07FF) && (num != 2)) || + ((cp >= 0x0800) && (cp <= 0xFFFF) && (num != 3)) || + ((cp >= 0x10000) && (cp <= 0x1FFFFF) && (num != 4))) + return false; + } + return true; + } }; #endif @@ -101,6 +157,15 @@ class ePicLoad: public eMainloop, public eThread, public sigc::trackable, public ePicLoad(); ~ePicLoad(); +#ifdef SWIG +%typemap(in) (const char *filename) { + if (PyBytes_Check($input)) { + $1 = PyBytes_AsString($input); + } else { + $1 = PyBytes_AsString(PyUnicode_AsEncodedString($input, "utf-8", "surrogateescape")); + } +} +#endif RESULT startDecode(const char *filename, int x=0, int y=0, bool async=true); RESULT getThumbnail(const char *filename, int x=0, int y=0, bool async=true); RESULT setPara(PyObject *val); diff --git a/lib/python/Components/MovieList.py b/lib/python/Components/MovieList.py index 395aac80d3f..39bc0602818 100644 --- a/lib/python/Components/MovieList.py +++ b/lib/python/Components/MovieList.py @@ -47,7 +47,7 @@ def getItemDisplayNameText(itemRef, info, removeExtension=None): name = getItemDisplayName(itemRef, info, removeExtension) aname = name.encode('UTF-8', 'surrogateescape') if name != aname.decode('UTF-8', 'ignore'): - encoding = detect(aname)['encoding'] + encoding = detect(aname)['encoding'] or 'ascii' return aname.decode(encoding) return name diff --git a/lib/python/Components/VariableText.py b/lib/python/Components/VariableText.py index 04a2c225d24..3adbc9488ae 100644 --- a/lib/python/Components/VariableText.py +++ b/lib/python/Components/VariableText.py @@ -1,3 +1,5 @@ +from chardet import detect + class VariableText: """VariableText can be used for components which have a variable text, based on any widget with setText call""" @@ -8,7 +10,12 @@ def __init__(self): self.onChanged = [] def setText(self, text): - self.message = text + atext = text.encode('UTF-8', 'surrogateescape') + if text != atext.decode('UTF-8', 'ignore'): + encoding = detect(atext)['encoding'] or 'ascii' + self.message = atext.decode(encoding) + else: + self.message = text if self.instance: self.instance.setText(str(self.message) or "") for x in self.onChanged: From f3d82d0d86151e7cc04b6e9222e593f98249dc20 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Thu, 29 Feb 2024 22:16:57 +0000 Subject: [PATCH 167/183] PEP8 double aggressive E301 ~ E306 --- lib/python/Components/VariableText.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/python/Components/VariableText.py b/lib/python/Components/VariableText.py index 3adbc9488ae..c467c771a6e 100644 --- a/lib/python/Components/VariableText.py +++ b/lib/python/Components/VariableText.py @@ -1,5 +1,6 @@ from chardet import detect + class VariableText: """VariableText can be used for components which have a variable text, based on any widget with setText call""" From 0a831faf0e93d0ce246b4e544ef48c84230a4e0c Mon Sep 17 00:00:00 2001 From: openvix-build Date: Thu, 29 Feb 2024 23:13:01 +0000 Subject: [PATCH 168/183] openvix: developer 6.5.001.007 --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index 1a39cae2b14..87fe49a45e6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1240,3 +1240,4 @@ openvix: developer 6.5.001.003 openvix: developer 6.5.001.004 openvix: developer 6.5.001.005 openvix: developer 6.5.001.006 +openvix: developer 6.5.001.007 From 837c85cecf650048b97a72be22c0bd26860ad68a Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Fri, 1 Mar 2024 14:57:36 +0100 Subject: [PATCH 169/183] [HdmiCec] - fix & cleanup debug msgs and hdmicec log --- lib/python/Components/HdmiCec.py | 278 ++++++++++++++++--------------- 1 file changed, 142 insertions(+), 136 deletions(-) diff --git a/lib/python/Components/HdmiCec.py b/lib/python/Components/HdmiCec.py index fd89fc5a303..a394c6010dc 100644 --- a/lib/python/Components/HdmiCec.py +++ b/lib/python/Components/HdmiCec.py @@ -13,8 +13,7 @@ from Tools import Notifications from Tools.StbHardware import getFPWasTimerWakeup - -CEC = ["1.1", "1.2", "1.2a", "1.3", "1.3a", "1.4", "2.0?", "unknown"] # CEC Version's table, cmdList from http://www.cec-o-matic.com +CEC = ["1.1", "1.2", "1.2a", "1.3", "1.3a", "1.4", "2.0", "unknown"] # CEC Version's table, cmdList from http://www.cec-o-matic.com cmdList = { 0x00: "", 0x04: "", @@ -392,160 +391,166 @@ def messageReceived(self, message): ctrl1 = message.getControl1() ctrl2 = message.getControl2() msgaddress = message.getAddress() # 0 = TV, 5 = receiver 15 = broadcast - print(f"[HdmiCEC][messageReceived0]: msgaddress={msgaddress} CECcmd={CECcmd}, cmd=%X, ctrl0={cmd}, length={ctrl0}") - if config.hdmicec.debug.value != "0": - self.debugRx(length, cmd, ctrl0) - if msgaddress > 15: # workaround for wrong address from driver (e.g. hd51, message comes from tv -> address is only sometimes 0, dm920, same tv -> address is always 0) - print("[HdmiCEC][messageReceived1a]: msgaddress > 15 reset to 0") - msgaddress = 0 - if cmd == 0x00: - if length == 0: # only polling message ( it's same as ping ) - print("[HdmiCEC][messageReceived1b]: received polling message") - else: - if ctrl0 == 68: # feature abort - print(f"[HdmiCEC][messageReceived2]: volume forwarding not supported by device {msgaddress:02x}") - self.volumeForwardingEnabled = False - elif cmd == 0x46: # request name - self.sendMessage(msgaddress, "osdname") - elif cmd == 0x72 or cmd == 0x7e: # system audio mode status 114 or 126 - if ctrl0 == 1: - self.volumeForwardingDestination = 5 # on: send volume keys to receiver - else: - self.volumeForwardingDestination = 0 # off: send volume keys to tv - print(f"[HdmiCEC][messageReceived4]: volume forwarding={self.volumeForwardingDestination}, msgaddress={msgaddress}") - if config.hdmicec.volume_forwarding.value: - print(f"[HdmiCEC][messageReceived5]: volume forwarding to device {self.volumeForwardingDestination:02x}enabled") - self.volumeForwardingEnabled = True - elif cmd == 0x83: # request address - self.sendMessage(msgaddress, "reportaddress") - elif cmd == 0x85: # request active source - if not Screens.Standby.inStandby: - if config.hdmicec.report_active_source.value: - self.sendMessage(msgaddress, "sourceactive") - elif cmd == 0x86: - physicaladdress = ctrl0 * 256 + ctrl1 # request streaming path - ouraddress = eHdmiCEC.getInstance().getPhysicalAddress() - print("[HdmiCEC][messageReceived6]:cmd 134 physical address=%s ouraddress=%s" % (physicaladdress, ouraddress)) - if physicaladdress == ouraddress: + if CECcmd != "": + print(f"[HdmiCEC][messageReceived0]: msgaddress={msgaddress} CECcmd={CECcmd}, cmd={cmd}, ctrl0={ctrl0}, datalength={length}") + if config.hdmicec.debug.value != "0": + self.debugRx(length, cmd, ctrl0) + if msgaddress > 15: # workaround for wrong address from driver (e.g. hd51, message comes from tv -> address is only sometimes 0, dm920, same tv -> address is always 0) + print("[HdmiCEC][messageReceived1a]: msgaddress > 15 reset to 0") + msgaddress = 0 + if cmd == 0x00: + if length == 0: # only polling message ( it's same as ping ) + print("[HdmiCEC][messageReceived1b]: received polling message") + else: + if ctrl0 == 68: # feature abort + print(f"[HdmiCEC][messageReceived2]: volume forwarding not supported by device {msgaddress:02x}") + self.volumeForwardingEnabled = False + elif cmd == 0x46: # request name + self.sendMessage(msgaddress, "osdname") + elif cmd == 0x72 or cmd == 0x7e: # system audio mode status 114 or 126 + if ctrl0 == 1: + self.volumeForwardingDestination = 5 # on: send volume keys to receiver + else: + self.volumeForwardingDestination = 0 # off: send volume keys to tv + print(f"[HdmiCEC][messageReceived4]: volume forwarding={self.volumeForwardingDestination}, msgaddress={msgaddress}") + if config.hdmicec.volume_forwarding.value: + print(f"[HdmiCEC][messageReceived5]: volume forwarding to device {self.volumeForwardingDestination:02x} enabled") + self.volumeForwardingEnabled = True + elif cmd == 0x83: # request address + self.sendMessage(msgaddress, "reportaddress") + elif cmd == 0x85: # request active source if not Screens.Standby.inStandby: if config.hdmicec.report_active_source.value: self.sendMessage(msgaddress, "sourceactive") - elif cmd == 0x8c: # request vendor id - self.sendMessage(msgaddress, "vendorid") - elif cmd == 0x8d: # menu request - if ctrl0 == 1: # query - if Screens.Standby.inStandby: - self.sendMessage(msgaddress, "menuinactive") - else: - self.sendMessage(msgaddress, "menuactive") - elif cmd == 0x8f: # request power status - if Screens.Standby.inStandby: - self.sendMessage(msgaddress, "powerinactive") - else: - self.sendMessage(msgaddress, "poweractive") - elif cmd == 0x90: # receive powerstatus report - if ctrl0 == 0: # some box is powered - if config.hdmicec.next_boxes_detect.value: - self.useStandby = False - print("[HDMI-CEC][messageReceived7] powered box found") - elif cmd == 0x9F: # request get CEC version - self.sendMessage(msgaddress, "sendcecversion") - - if cmd == 0x36 and config.hdmicec.handle_tv_standby.value: # handle standby request from the tv - self.handlingStandbyFromTV = True # avoid echoing the "System Standby" command back to the tv - self.standby() # handle standby - self.handlingStandbyFromTV = False # after handling the standby command, we are free to send "standby" ourselves again - - if Screens.Standby.inStandby and config.hdmicec.handle_tv_wakeup.value: # handle wakeup requests from the tv - if ((cmd == 0x04 and config.hdmicec.tv_wakeup_detection.value == "wakeup") or - (cmd == 0x83 and config.hdmicec.tv_wakeup_detection.value == "requestphysicaladdress") or - (cmd == 0x85 and config.hdmicec.tv_wakeup_detection.value == "sourcerequest") or - (cmd == 0x8C and config.hdmicec.tv_wakeup_detection.value == "requestvendor") or - (cmd == 0x46 and config.hdmicec.tv_wakeup_detection.value == "osdnamerequest") or - (cmd != 0x36 and config.hdmicec.tv_wakeup_detection.value == "activity")): - self.wakeup() - elif ((cmd == 0x80 and config.hdmicec.handle_tv_wakeup.value == "routingrequest") or (cmd == 0x86 and config.hdmicec.handle_tv_wakeup.value == "streamrequest")): - physicaladdress = ctrl0 * 256 + ctrl1 + elif cmd == 0x86: + physicaladdress = ctrl0 * 256 + ctrl1 # request streaming path ouraddress = eHdmiCEC.getInstance().getPhysicalAddress() - print("[HdmiCEC][messageReceived8]:cmd 128 physical address=%s ouraddress=%s" % (physicaladdress, ouraddress)) + print(f"[HdmiCEC][messageReceived6]:cmd 134 physical address={physicaladdress} ouraddress={ouraddress}") if physicaladdress == ouraddress: + if not Screens.Standby.inStandby: + if config.hdmicec.report_active_source.value: + self.sendMessage(msgaddress, "sourceactive") + elif cmd == 0x8c: # request vendor id + self.sendMessage(msgaddress, "vendorid") + elif cmd == 0x8d: # menu request + if ctrl0 == 1: # query + if Screens.Standby.inStandby: + self.sendMessage(msgaddress, "menuinactive") + else: + self.sendMessage(msgaddress, "menuactive") + elif cmd == 0x8f: # request power status + if Screens.Standby.inStandby: + self.sendMessage(msgaddress, "powerinactive") + else: + self.sendMessage(msgaddress, "poweractive") + elif cmd == 0x90: # receive powerstatus report + if ctrl0 == 0: # some box is powered + if config.hdmicec.next_boxes_detect.value: + self.useStandby = False + print("[HDMI-CEC][messageReceived7] powered box found") + elif cmd == 0x9F: # request get CEC version + self.sendMessage(msgaddress, "sendcecversion") + + if cmd == 0x36 and config.hdmicec.handle_tv_standby.value: # handle standby request from the tv + self.handlingStandbyFromTV = True # avoid echoing the "System Standby" command back to the tv + self.standby() # handle standby + self.handlingStandbyFromTV = False # after handling the standby command, we are free to send "standby" ourselves again + + if Screens.Standby.inStandby and config.hdmicec.handle_tv_wakeup.value: # handle wakeup requests from the tv + if ((cmd == 0x04 and config.hdmicec.tv_wakeup_detection.value == "wakeup") or + (cmd == 0x83 and config.hdmicec.tv_wakeup_detection.value == "requestphysicaladdress") or + (cmd == 0x85 and config.hdmicec.tv_wakeup_detection.value == "sourcerequest") or + (cmd == 0x8C and config.hdmicec.tv_wakeup_detection.value == "requestvendor") or + (cmd == 0x46 and config.hdmicec.tv_wakeup_detection.value == "osdnamerequest") or + (cmd != 0x36 and config.hdmicec.tv_wakeup_detection.value == "activity")): self.wakeup() - elif cmd == 0x84 and config.hdmicec.tv_wakeup_detection.value == "tvreportphysicaladdress": - if (ctrl0 * 256 + ctrl1) == 0 and ctrl2 == 0: - self.wakeup() + elif ((cmd == 0x80 and config.hdmicec.handle_tv_wakeup.value == "routingrequest") or (cmd == 0x86 and config.hdmicec.handle_tv_wakeup.value == "streamrequest")): + physicaladdress = ctrl0 * 256 + ctrl1 + ouraddress = eHdmiCEC.getInstance().getPhysicalAddress() + print(f"[HdmiCEC][messageReceived8]:cmd 128 physical address={physicaladdress} ouraddress={ouraddress}") + if physicaladdress == ouraddress: + self.wakeup() + elif cmd == 0x84 and config.hdmicec.tv_wakeup_detection.value == "tvreportphysicaladdress": + if (ctrl0 * 256 + ctrl1) == 0 and ctrl2 == 0: + self.wakeup() + else: + return + # print(f"[HdmiCEC][messageReceived99]: Unrecognised command -> msgaddress={msgaddress} CECcmd={CECcmd}, cmd={cmd}, ctrl0={ctrl0}, datalength={length}") def sendMessage(self, msgaddress, message): cmd = 0 - data = "" + dataStructpack = "" if message == "keypoweroff": cmd = 0x44 # 68 - data = struct.pack("B", 0x6c) + dataStructpack = struct.pack("B", 0x6c) elif message == "keypoweron": cmd = 0x44 # 68 - data = struct.pack("B", 0x6d) + dataStructpack = struct.pack("B", 0x6d) elif message == "setsystemaudiomode": cmd = 0x70 # 112 msgaddress = 0x05 - data = self.packDevAddr() + dataStructpack = self.packDevAddr() elif message == "sourceactive": msgaddress = 0x0f # use broadcast for active source command cmd = 0x82 # 130 - data = self.packDevAddr() + dataStructpack = self.packDevAddr() elif message == "reportaddress": msgaddress = 0x0f # use broadcast address cmd = 0x84 # 132 - data = self.packDevAddr(True) + dataStructpack = self.packDevAddr(True) elif message == "vendorid": cmd = 0x87 - data = b"\x00\x00\x00" + dataStructpack = b"\x00\x00\x00" elif message == "menuactive": cmd = 0x8e # 142 - data = struct.pack("B", 0x00) + dataStructpack = struct.pack("B", 0x00) elif message == "menuinactive": cmd = 0x8e # 142 - data = struct.pack("B", 0x01) + dataStructpack = struct.pack("B", 0x01) elif message == "poweractive": cmd = 0x90 # 144 - data = struct.pack("B", 0x00) + dataStructpack = struct.pack("B", 0x00) elif message == "powerinactive": cmd = 0x90 # 144 - data = struct.pack("B", 0x01) + dataStructpack = struct.pack("B", 0x01) elif message == "sourceinactive": cmd = 0x9d # 157 - data = self.packDevAddr() + dataStructpack = self.packDevAddr() elif message == "sendcecversion": cmd = 0x9E # 158 - data = struct.pack("B", 0x04) # v1.3a - if data: # keep cmd+data calls above this line so binary data converted - CECcmd = cmdList.get(cmd, "") - if data: - encoder = chardet.detect(data)["encoding"] - data = data.decode(encoding=encoder, errors="ignore") - print("[HdmiCec][sendMessage]: CECcmd=%s cmd=%X, data=struct.pack" % (CECcmd, cmd)) - elif message == "wakeup": - if config.hdmicec.tv_wakeup_command.value == "textview": - cmd = 0x0d - else: - cmd = 0x04 - elif message == "standby": - cmd = 0x36 - elif message == "osdname": - cmd = 0x47 - data = uname()[1] - data = data[:14] - elif message == "givesystemaudiostatus": - cmd = 0x7d - msgaddress = 0x05 - elif message == "requestactivesource": - cmd = 0x85 - msgaddress = 0x0f # use broadcast address - elif message == "getpowerstatus": - self.useStandby = True - cmd = 0x8f - msgaddress = 0x0f # use broadcast msgaddress => boxes will send info + dataStructpack = struct.pack("B", 0x04) # v1.3a + if dataStructpack: # keep cmd+data calls above this line so binary data converted + CECcmd = cmdList.get(cmd, "").replace("<", "'").replace(">", "'") + print(f"[HdmiCec][sendMessage]: CECcmd={CECcmd}, dataStructpack=", dataStructpack) + encoder = chardet.detect(dataStructpack)["encoding"] + data = dataStructpack.decode(encoding=encoder, errors="ignore") + print(f"[HdmiCec][sendMessage]: CECcmd={CECcmd} cmd={cmd:X}, encoder={encoder}, data={data}" + "\n") + else: + data = "" + if message == "wakeup": + if config.hdmicec.tv_wakeup_command.value == "textview": + cmd = 0x0d + else: + cmd = 0x04 + elif message == "standby": + cmd = 0x36 + elif message == "osdname": + cmd = 0x47 + data = uname()[1] + data = data[:14] + elif message == "givesystemaudiostatus": + cmd = 0x7d + msgaddress = 0x05 + elif message == "requestactivesource": + cmd = 0x85 + msgaddress = 0x0f # use broadcast address + elif message == "getpowerstatus": + self.useStandby = True + cmd = 0x8f + msgaddress = 0x0f # use broadcast msgaddress => boxes will send info if cmd != 0: CECcmd = cmdList.get(cmd, "") - # print("[HdmiCEC][sendMessage3]: CECcmd=%s cmd=%X, msgaddress=%s data=%s" % (CECcmd, cmd, msgaddress, data)) + # print(f"[HdmiCEC][sendMessage3]: CECcmd={CECcmd} cmd={cmd:X}, msgaddress={msgaddress} data={data}") if config.hdmicec.minimum_send_interval.value != "0": self.queue.append((msgaddress, cmd, data)) if not self.wait.isActive(): @@ -559,7 +564,7 @@ def sendMsgQ(self): if len(self.queue): (msgaddress, cmd, data) = self.queue.pop(0) CECcmd = cmdList.get(cmd, "") # noqa: F841 - # print("[HdmiCEC][sendMsgQ1]: msgaddress=%s, CECcmd=%s cmd=%X,data=%s \n" % (msgaddress, CECcmd, cmd, data)) + # print(f"[HdmiCEC][sendMsgQ1]: msgaddress={msgaddress}, CECcmd={CECcmd} cmd={cmd:X},data={data}" + "\n") eHdmiCEC.getInstance().sendMessage(msgaddress, cmd, data, len(data)) self.wait.start(int(config.hdmicec.minimum_send_interval.value), True) @@ -681,7 +686,7 @@ def keyEvent(self, keyCode, keyEvent): if not self.waitKeyEvent.isActive(): self.waitKeyEvent.start(int(config.hdmicec.minimum_send_interval.value), True) else: - # print("[HdmiCEC][keyEvent3]: forwarding dest=%s, cmd=%X, data=%s" % (self.volumeForwardingDestination, cmd, data)) + # print(f"[HdmiCEC][keyEvent3]: forwarding dest={self.volumeForwardingDestination}, cmd={cmd:X}, data={data}") if config.hdmicec.force_volume_forwarding.value: eHdmiCEC.getInstance().sendMessage(0, cmd, data, len(data)) eHdmiCEC.getInstance().sendMessage(5, cmd, data, len(data)) @@ -700,36 +705,37 @@ def keyEvent(self, keyCode, keyEvent): def sendKeyEventQ(self): if len(self.queueKeyEvent): (msgaddress, cmd, data) = self.queueKeyEvent.pop(0) - # print("[HdmiCEC][sendKeyEventQ]: msgaddress=%s, cmd=%X, data=%s" % (msgaddress, cmd, data)) + # print(f"[HdmiCEC][sendKeyEventQ]: msgaddress={msgaddress}, cmd={cmd:X}, data={data}") eHdmiCEC.getInstance().sendMessage(msgaddress, cmd, data, len(data)) self.waitKeyEvent.start(int(config.hdmicec.minimum_send_interval.value), True) def debugTx(self, msgaddress, cmd, data): - txt = self.now(True) + self.opCode(cmd, True) + " " + "%02X" % (cmd) + " " + txt = self.now(True) + self.opCode(cmd, True) + " " + f"{cmd:02X}" + " " tmp = "" if len(data): - if cmd in [0x32, 0x47]: - for i in range(len(data)): - tmp += "%s" % data[i] + if cmd in [0x32, 0x47]: # set Menu Language/OSD Name + for info in data: + tmp += f"{info}" else: - for i in range(len(data)): - tmp += "%02X" % ord(data[i]) + " " + for bytes in data: + tmp += f"{ord(bytes):02X}" + " " tmp += 48 * " " - self.fdebug(txt + tmp[:48] + "[0x%02X]" % (msgaddress) + "\n") + self.fdebug(txt + tmp[:48] + f"[0x{msgaddress:02X}]") - def debugRx(self, length, cmd, ctrl): + def debugRx(self, length, cmd, ctrl0): txt = self.now() if cmd == 0 and length == 0: - txt += self.opCode(cmd) + " - " + txt += " -" else: + if cmd == 0: - txt += "" + 13 * " " + "< " + "%02X" % (cmd) + " " + txt += "" + 13 * " " + "< " + f"{cmd:02X}" + " " else: - txt += self.opCode(cmd) + " " + "%02X" % (cmd) + " " - if cmd == 0x9e: - txt += "%02X" % ctrl + 3 * " " + "[version: %s]" % CEC[ctrl] + txt += self.opCode(cmd) + f" {cmd:02X} " + if cmd == 0x9e and ctrl0 < len(CEC): + txt += f"{ctrl0:02X}" + 3 * " " + f"[version: {CEC[ctrl0]}]" else: - txt += "%02X" % ctrl + " " + txt += f"{ctrl0:02X}" txt += "\n" self.fdebug(txt) @@ -739,7 +745,7 @@ def opCode(self, cmd, out=False): send = ">" opCode = "" if cmd in cmdList: - opCode += "%s" % cmdList[cmd] + opCode += f"{cmdList[cmd]}" opCode += 30 * " " return opCode[:28] + send + " " From da22170f9f61986500a5ad1135a98f28cf23d9a3 Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Fri, 1 Mar 2024 13:59:55 +0000 Subject: [PATCH 170/183] PEP8 double aggressive W291 ~ W293 and W391 --- lib/python/Components/HdmiCec.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/python/Components/HdmiCec.py b/lib/python/Components/HdmiCec.py index a394c6010dc..a3a0dff2609 100644 --- a/lib/python/Components/HdmiCec.py +++ b/lib/python/Components/HdmiCec.py @@ -725,9 +725,9 @@ def debugTx(self, msgaddress, cmd, data): def debugRx(self, length, cmd, ctrl0): txt = self.now() if cmd == 0 and length == 0: - txt += " -" + txt += " -" else: - + if cmd == 0: txt += "" + 13 * " " + "< " + f"{cmd:02X}" + " " else: @@ -735,7 +735,7 @@ def debugRx(self, length, cmd, ctrl0): if cmd == 0x9e and ctrl0 < len(CEC): txt += f"{ctrl0:02X}" + 3 * " " + f"[version: {CEC[ctrl0]}]" else: - txt += f"{ctrl0:02X}" + txt += f"{ctrl0:02X}" txt += "\n" self.fdebug(txt) From f3795a8bc991ba78bc58de701b1d573ef9cfb539 Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Sat, 2 Mar 2024 11:26:10 +0100 Subject: [PATCH 171/183] [VariableText] - resolve no text crash --- lib/python/Components/VariableText.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/python/Components/VariableText.py b/lib/python/Components/VariableText.py index c467c771a6e..0aa98caccaa 100644 --- a/lib/python/Components/VariableText.py +++ b/lib/python/Components/VariableText.py @@ -11,12 +11,12 @@ def __init__(self): self.onChanged = [] def setText(self, text): - atext = text.encode('UTF-8', 'surrogateescape') - if text != atext.decode('UTF-8', 'ignore'): - encoding = detect(atext)['encoding'] or 'ascii' - self.message = atext.decode(encoding) - else: - self.message = text + self.message = text + if text: + atext = text.encode('UTF-8', 'surrogateescape') + if text != atext.decode('UTF-8', 'ignore'): + encoding = detect(atext)['encoding'] or 'ascii' + self.message = atext.decode(encoding) if self.instance: self.instance.setText(str(self.message) or "") for x in self.onChanged: From 6e0add30979b2c64eeea380c00d399f1a138f66d Mon Sep 17 00:00:00 2001 From: openvix-bot Date: Sat, 2 Mar 2024 10:28:19 +0000 Subject: [PATCH 172/183] PEP8 double aggressive W291 ~ W293 and W391 --- lib/python/Components/VariableText.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/Components/VariableText.py b/lib/python/Components/VariableText.py index 0aa98caccaa..494d7c66711 100644 --- a/lib/python/Components/VariableText.py +++ b/lib/python/Components/VariableText.py @@ -11,7 +11,7 @@ def __init__(self): self.onChanged = [] def setText(self, text): - self.message = text + self.message = text if text: atext = text.encode('UTF-8', 'surrogateescape') if text != atext.decode('UTF-8', 'ignore'): From 05a4f7a6712275b2f84d43c189e57ce4c0566446 Mon Sep 17 00:00:00 2001 From: Huevos Date: Sat, 2 Mar 2024 16:37:24 +0100 Subject: [PATCH 173/183] [VariableText] fix commit https://github.com/OpenViX/enigma2/commit/557b9ef9e84f546721e0c643165866853f2bed7c >>> str(None) or "" 'None' >>> >>> None or "" '' >>> --- lib/python/Components/VariableText.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/Components/VariableText.py b/lib/python/Components/VariableText.py index 494d7c66711..aa178c4b6dd 100644 --- a/lib/python/Components/VariableText.py +++ b/lib/python/Components/VariableText.py @@ -18,7 +18,7 @@ def setText(self, text): encoding = detect(atext)['encoding'] or 'ascii' self.message = atext.decode(encoding) if self.instance: - self.instance.setText(str(self.message) or "") + self.instance.setText(self.message or "") for x in self.onChanged: x() From 00554cf7ea8116d53a96ca582c1dbb2f149b710c Mon Sep 17 00:00:00 2001 From: openvix-build Date: Sat, 2 Mar 2024 15:44:15 +0000 Subject: [PATCH 174/183] openvix: developer 6.5.001.008 --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index 87fe49a45e6..caf1100d6d5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1241,3 +1241,4 @@ openvix: developer 6.5.001.004 openvix: developer 6.5.001.005 openvix: developer 6.5.001.006 openvix: developer 6.5.001.007 +openvix: developer 6.5.001.008 From 749fb065bd9db6cddb663d29d422ae018becb158 Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Sat, 2 Mar 2024 23:01:27 +0100 Subject: [PATCH 175/183] [Standby] -fix Deep Standby TV power off --- lib/python/Screens/Standby.py | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/lib/python/Screens/Standby.py b/lib/python/Screens/Standby.py index a232e54ab7d..860d5f92dd1 100644 --- a/lib/python/Screens/Standby.py +++ b/lib/python/Screens/Standby.py @@ -303,21 +303,11 @@ def getRecordEvent(self, recservice, event): def sendCEC(self): print("[Standby][sendCEC] entered ") - import struct from enigma import eHdmiCEC # noqa: E402 - physicaladdress = eHdmiCEC.getInstance().getPhysicalAddress() - msgaddress = 0x0f # use broadcast for active source command - cmd0 = 0x9d # 157 sourceinactive - data0 = struct.pack("BB", int(physicaladdress // 256), int(physicaladdress % 256)) - data0 = data0.decode("UTF-8", "ignore") - cmd1 = 0x44 # 68 keypoweroff - data1 = struct.pack("B", 0x6c) - data1 = data1.decode("UTF-8", "ignore") - cmd2 = 0x36 # 54 standby - data2 = "" - eHdmiCEC.getInstance().sendMessage(msgaddress, cmd0, data0, len(data0)) - eHdmiCEC.getInstance().sendMessage(msgaddress, cmd1, data1, len(data1)) - eHdmiCEC.getInstance().sendMessage(msgaddress, cmd2, data2, len(data2)) + msgaddress = 0x00 + cmd = 0x36 # 54 standby + data = "" + eHdmiCEC.getInstance().sendMessage(msgaddress, cmd, data, len(data)) print("[Standby][sendCEC] departed ") def close(self, value): From f5517f2c099d83c642d935489557a109accb4b38 Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Sat, 2 Mar 2024 23:02:02 +0100 Subject: [PATCH 176/183] Revert "[PowerTimer/RecordTimer] - revert notifications so that correct localisation happens" This reverts commit 8a9afa0de2e95e9b48d3262d1b4658a1af52b9d1. --- lib/python/PowerTimer.py | 14 +++++++------- lib/python/RecordTimer.py | 18 +++++++++--------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/python/PowerTimer.py b/lib/python/PowerTimer.py index b72e318757d..2ccf7fcfe76 100644 --- a/lib/python/PowerTimer.py +++ b/lib/python/PowerTimer.py @@ -164,7 +164,7 @@ def activate(self): elif self.timerType == TIMERTYPE.STANDBY: if not Screens.Standby.inStandby: # not already in standby - Notifications.AddNotificationWithUniqueIDCallback(self.sendStandbyNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to set your\n%s %s to standby. Do that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendStandbyNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to set your\n{SystemInfo['MachineBrand']} {SystemInfo['MachineName']} to standby. Do that now?"), timeout=180) return True elif self.timerType == TIMERTYPE.AUTOSTANDBY: @@ -173,7 +173,7 @@ def activate(self): # retry return False if not Screens.Standby.inStandby: # not already in standby - Notifications.AddNotificationWithUniqueIDCallback(self.sendStandbyNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to set your\n%s %s to standby. Do that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendStandbyNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to set your\n{SystemInfo['MachineBrand']} {SystemInfo['MachineName']} to standby. Do that now?"), timeout=180) if self.autosleeprepeat == "once": eActionMap.getInstance().unbindAction('', self.keyPressed) return True @@ -213,7 +213,7 @@ def activate(self): quitMainloop(1) return True else: - Notifications.AddNotificationWithUniqueIDCallback(self.sendTryQuitMainloopNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to shutdown your %s %s.\nDo that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendTryQuitMainloopNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to shutdown your {SystemInfo['MachineBrand']} {SystemInfo['MachineName']}.\nDo that now?"), timeout=180) if self.autosleeprepeat == "once": eActionMap.getInstance().unbindAction('', self.keyPressed) return True @@ -234,7 +234,7 @@ def activate(self): if Screens.Standby.inStandby: # in standby quitMainloop(1) else: - Notifications.AddNotificationWithUniqueIDCallback(self.sendTryQuitMainloopNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to shutdown your %s %s.\nDo that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendTryQuitMainloopNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to shutdown your {SystemInfo['MachineBrand']} {SystemInfo['MachineName']}.\nDo that now?"), timeout=180) return True elif self.timerType == TIMERTYPE.REBOOT: @@ -246,7 +246,7 @@ def activate(self): if Screens.Standby.inStandby: # in standby quitMainloop(2) else: - Notifications.AddNotificationWithUniqueIDCallback(self.sendTryToRebootNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to reboot your %s %s.\nDo that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendTryToRebootNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to reboot your {SystemInfo['MachineBrand']} {SystemInfo['MachineName']}.\nDo that now?"), timeout=180) return True elif self.timerType == TIMERTYPE.RESTART: @@ -265,7 +265,7 @@ def activate(self): NavigationInstance.instance.PowerTimer.saveTimer() if self.afterEvent == AFTEREVENT.STANDBY: if not Screens.Standby.inStandby: # not already in standby - Notifications.AddNotificationWithUniqueIDCallback(self.sendStandbyNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to set your\n%s %s to standby. Do that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendStandbyNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to set your\n{SystemInfo['MachineBrand']} {SystemInfo['MachineName']} to standby. Do that now?"), timeout=180) elif self.afterEvent == AFTEREVENT.DEEPSTANDBY: if NavigationInstance.instance.RecordTimer.isRecording() or abs(NavigationInstance.instance.RecordTimer.getNextRecordingTime() - time()) <= 900 or abs(NavigationInstance.instance.RecordTimer.getNextZapTime() - time()) <= 900: self.do_backoff() @@ -275,7 +275,7 @@ def activate(self): if Screens.Standby.inStandby: # in standby quitMainloop(1) else: - Notifications.AddNotificationWithUniqueIDCallback(self.sendTryQuitMainloopNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to shutdown your %s %s.\nDo that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendTryQuitMainloopNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to shutdown your {SystemInfo['MachineBrand']} {SystemInfo['MachineName']}.\nDo that now?"), timeout=180) return True def setAutoincreaseEnd(self, entry=None): diff --git a/lib/python/RecordTimer.py b/lib/python/RecordTimer.py index 3912897d248..2096713bdc8 100644 --- a/lib/python/RecordTimer.py +++ b/lib/python/RecordTimer.py @@ -519,7 +519,7 @@ def activate(self): if next_state == self.StatePrepared: if not self.justplay and not self.freespace(): - Notifications.AddPopup(text=_("Write error while recording. Disk full?\n%s") % self.name, type=MessageBox.TYPE_ERROR, timeout=5, id="DiskFullMessage") + Notifications.AddPopup(text=_(f"Write error while recording. Disk full?\n{self.name}"), type=MessageBox.TYPE_ERROR, timeout=5, id="DiskFullMessage") self.failed = True self.next_activation = time() self.end = time() + 5 @@ -652,7 +652,7 @@ def activate(self): self.InfoBarInstance.session.pip.servicePath = self.InfoBarInstance.servicelist and self.InfoBarInstance.servicelist.getCurrentServicePath() self.log(11, "zapping as PiP") if notify: - Notifications.AddPopup(text=_("Zapped to timer service %s as PiP!") % self.service_ref.getServiceName(), type=MessageBox.TYPE_INFO, timeout=5) + Notifications.AddPopup(text=_(f"Zapped to timer service {self.service_ref.getServiceName()} as PiP!"), type=MessageBox.TYPE_INFO, timeout=5) return True else: del self.InfoBarInstance.session.pip @@ -663,7 +663,7 @@ def activate(self): else: self.log(11, "zapping") if notify: - Notifications.AddPopup(text=_("Zapped to timer service %s!") % self.service_ref.getServiceName(), type=MessageBox.TYPE_INFO, timeout=5) + Notifications.AddPopup(text=_(f"Zapped to timer service {self.service_ref.getServiceName()}!"), type=MessageBox.TYPE_INFO, timeout=5) # If the user is looking at a MovieList then we need to update this # lastservice, so that we get back to the updated one when closing the @@ -736,7 +736,7 @@ def activate(self): if self.afterEvent == AFTEREVENT.STANDBY or (not wasRecTimerWakeup and self.autostate and self.afterEvent == AFTEREVENT.AUTO) or self.wasInStandby: self.keypress() # this unbinds the keypress detection if not Screens.Standby.inStandby: # not already in standby - Notifications.AddNotificationWithCallback(self.sendStandbyNotification, MessageBox, _("A finished record timer wants to set your\n%s %s to standby. Do that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) + Notifications.AddNotificationWithCallback(self.sendStandbyNotification, MessageBox, _(f"A finished record timer wants to set your\n{SystemInfo['MachineBrand']} {SystemInfo['MachineName']} to standby. Do that now?"), timeout=180) elif self.afterEvent == AFTEREVENT.DEEPSTANDBY or (wasRecTimerWakeup and self.afterEvent == AFTEREVENT.AUTO and Screens.Standby.inStandby): if (abs(NavigationInstance.instance.RecordTimer.getNextRecordingTime() - time()) <= 900 or abs(NavigationInstance.instance.RecordTimer.getNextZapTime() - time()) <= 900) or NavigationInstance.instance.RecordTimer.getStillRecording(): print("[RecordTimer] Recording or Recording due is next 15 mins, not return to deepstandby") @@ -751,7 +751,7 @@ def activate(self): if int(ClientsStreaming("NUMBER").getText()) > 0: if not Screens.Standby.inStandby: # not already in standby Notifications.AddNotificationWithCallback(self.sendStandbyNotification, MessageBox, - _("A finished record timer wants to set your\n%s %s to standby. Do that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]) + _(f"A finished record timer wants to set your\n{SystemInfo['MachineBrand']} {SystemInfo['MachineName']} to standby. Do that now?") + _("\n(DeepStandby request changed to Standby owing to there being streaming clients.)"), timeout=180) return True @@ -759,7 +759,7 @@ def activate(self): if Screens.Standby.inStandby: # in standby quitMainloop(1) else: - Notifications.AddNotificationWithCallback(self.sendTryQuitMainloopNotification, MessageBox, _("A finished record timer wants to shut down\nyour %s %s. Shutdown now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) + Notifications.AddNotificationWithCallback(self.sendTryQuitMainloopNotification, MessageBox, _(f"A finished record timer wants to shut down\nyour {SystemInfo['MachineBrand']} {SystemInfo['MachineName']}. Shutdown now?"), timeout=180) return True def keypress(self, key=None, flag=1): @@ -811,7 +811,7 @@ def openChoiceActionBeforeZap(self): type = _("zap") elif self.always_zap: type = _("zap and record") - message = _("You must switch to the service %s (%s - '%s')!\n") % (type, self.service_ref.getServiceName(), self.name) + message = _(f"You must switch to the service {type} ({self.service_ref.getServiceName()} - '{self.name}')!\n") if self.repeated: message += _("Attention, this is repeated timer!\n") message += _("Timeshift is running. Select an action.\n") @@ -921,7 +921,7 @@ def gotRecordEvent(self, record, event): # TODO: this has to be done. elif event == iRecordableService.evStart: RecordingsState(1) - text = _("A recording has been started:\n%s") % self.name + text = _(f"A recording has been started:\n{self.name}") notify = config.usage.show_message_when_recording_starts.value and not Screens.Standby.inStandby and self.InfoBarInstance and self.InfoBarInstance.execing if self.dirnameHadToFallback: text = "\n".join((text, _("Please note that the previously selected media could not be accessed and therefore the default directory is being used instead."))) @@ -1100,7 +1100,7 @@ def loadTimer(self, justLoad=False): # justLoad is passed on to record() if conflict_list: checkit = True if newTimer in conflict_list: - timer_text += _("\nTimer '%s' disabled!") % newTimer.name + timer_text += _(f"\nTimer '{newTimer.name}' disabled!") if checkit: from Tools.Notifications import AddPopup from Screens.MessageBox import MessageBox From 71bf846de1d00da53dbe260059e53aa037f65e65 Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Sat, 2 Mar 2024 23:02:24 +0100 Subject: [PATCH 177/183] Revert "[PowerTimer] - f string cleanup" This reverts commit 75b8b4339336916da081edc3b4e31d87dcaab319. --- lib/python/PowerTimer.py | 57 +++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/lib/python/PowerTimer.py b/lib/python/PowerTimer.py index 2ccf7fcfe76..2bab472a8ec 100644 --- a/lib/python/PowerTimer.py +++ b/lib/python/PowerTimer.py @@ -88,9 +88,9 @@ def __repr__(self): TIMERTYPE.RESTART: "restart" }[self.timerType] if not self.disabled: - return f"PowerTimerEntry(type={timertype}, begin={ctime(self.begin)})" + return "PowerTimerEntry(type=%s, begin=%s)" % (timertype, ctime(self.begin)) else: - return f"PowerTimerEntry(type={timertype}, begin={ctime(self.begin)} Disabled)" + return "PowerTimerEntry(type=%s, begin=%s Disabled)" % (timertype, ctime(self.begin)) def log(self, code, msg): self.log_entries.append((int(time()), code, msg)) @@ -107,7 +107,7 @@ def do_backoff(self): self.backoff *= 2 if self.backoff > 1800: self.backoff = 1800 - self.log(10, f"backoff: retry in {int(self.backoff) / 60} minutes") + self.log(10, "backoff: retry in %d minutes" % (int(self.backoff) / 60)) # # If this is the first backoff of a repeat timer remember the original # begin/end times, so that we can use *these* when setting up the repeat. @@ -124,7 +124,7 @@ def do_backoff(self): def activate(self): next_state = self.state + 1 - self.log(5, f"activating state {next_state}") + self.log(5, "activating state %d" % next_state) if next_state == self.StatePrepared and (self.timerType == TIMERTYPE.AUTOSTANDBY or self.timerType == TIMERTYPE.AUTODEEPSTANDBY): # This is the first action for an auto* timer. @@ -164,7 +164,7 @@ def activate(self): elif self.timerType == TIMERTYPE.STANDBY: if not Screens.Standby.inStandby: # not already in standby - Notifications.AddNotificationWithUniqueIDCallback(self.sendStandbyNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to set your\n{SystemInfo['MachineBrand']} {SystemInfo['MachineName']} to standby. Do that now?"), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendStandbyNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to set your\n%s %s to standby. Do that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) return True elif self.timerType == TIMERTYPE.AUTOSTANDBY: @@ -173,7 +173,7 @@ def activate(self): # retry return False if not Screens.Standby.inStandby: # not already in standby - Notifications.AddNotificationWithUniqueIDCallback(self.sendStandbyNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to set your\n{SystemInfo['MachineBrand']} {SystemInfo['MachineName']} to standby. Do that now?"), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendStandbyNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to set your\n%s %s to standby. Do that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) if self.autosleeprepeat == "once": eActionMap.getInstance().unbindAction('', self.keyPressed) return True @@ -213,7 +213,7 @@ def activate(self): quitMainloop(1) return True else: - Notifications.AddNotificationWithUniqueIDCallback(self.sendTryQuitMainloopNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to shutdown your {SystemInfo['MachineBrand']} {SystemInfo['MachineName']}.\nDo that now?"), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendTryQuitMainloopNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to shutdown your %s %s.\nDo that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) if self.autosleeprepeat == "once": eActionMap.getInstance().unbindAction('', self.keyPressed) return True @@ -234,7 +234,7 @@ def activate(self): if Screens.Standby.inStandby: # in standby quitMainloop(1) else: - Notifications.AddNotificationWithUniqueIDCallback(self.sendTryQuitMainloopNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to shutdown your {SystemInfo['MachineBrand']} {SystemInfo['MachineName']}.\nDo that now?"), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendTryQuitMainloopNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to shutdown your %s %s.\nDo that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) return True elif self.timerType == TIMERTYPE.REBOOT: @@ -246,7 +246,7 @@ def activate(self): if Screens.Standby.inStandby: # in standby quitMainloop(2) else: - Notifications.AddNotificationWithUniqueIDCallback(self.sendTryToRebootNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to reboot your {SystemInfo['MachineBrand']} {SystemInfo['MachineName']}.\nDo that now?"), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendTryToRebootNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to reboot your %s %s.\nDo that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) return True elif self.timerType == TIMERTYPE.RESTART: @@ -265,7 +265,7 @@ def activate(self): NavigationInstance.instance.PowerTimer.saveTimer() if self.afterEvent == AFTEREVENT.STANDBY: if not Screens.Standby.inStandby: # not already in standby - Notifications.AddNotificationWithUniqueIDCallback(self.sendStandbyNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to set your\n{SystemInfo['MachineBrand']} {SystemInfo['MachineName']} to standby. Do that now?"), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendStandbyNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to set your\n%s %s to standby. Do that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) elif self.afterEvent == AFTEREVENT.DEEPSTANDBY: if NavigationInstance.instance.RecordTimer.isRecording() or abs(NavigationInstance.instance.RecordTimer.getNextRecordingTime() - time()) <= 900 or abs(NavigationInstance.instance.RecordTimer.getNextZapTime() - time()) <= 900: self.do_backoff() @@ -275,7 +275,7 @@ def activate(self): if Screens.Standby.inStandby: # in standby quitMainloop(1) else: - Notifications.AddNotificationWithUniqueIDCallback(self.sendTryQuitMainloopNotification, "PT_StateChange", MessageBox, _(f"A finished powertimer wants to shutdown your {SystemInfo['MachineBrand']} {SystemInfo['MachineName']}.\nDo that now?"), timeout=180) + Notifications.AddNotificationWithUniqueIDCallback(self.sendTryQuitMainloopNotification, "PT_StateChange", MessageBox, _("A finished powertimer wants to shutdown your %s %s.\nDo that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) return True def setAutoincreaseEnd(self, entry=None): @@ -349,7 +349,7 @@ def timeChanged(self): self.backoff = 0 if int(old_prepare) > 60 and int(old_prepare) != int(self.start_prepare): - self.log(15, f"time changed, start prepare is now: {ctime(self.start_prepare)}") + self.log(15, "time changed, start prepare is now: %s" % ctime(self.start_prepare)) def createTimer(xml): @@ -480,7 +480,7 @@ def loadTimer(self): checkit = False # at moment it is enough when the message is displayed one time def saveTimer(self): - timerTypes = { # noqa: F841 + timerTypes = { TIMERTYPE.WAKEUP: "wakeup", TIMERTYPE.WAKEUPTOSTANDBY: "wakeuptostandby", TIMERTYPE.AUTOSTANDBY: "autostandby", @@ -490,7 +490,7 @@ def saveTimer(self): TIMERTYPE.REBOOT: "reboot", TIMERTYPE.RESTART: "restart" } - afterEvents = { # noqa: F841 + afterEvents = { AFTEREVENT.NONE: "nothing", AFTEREVENT.WAKEUPTOSTANDBY: "wakeuptostandby", AFTEREVENT.STANDBY: "standby", @@ -503,21 +503,30 @@ def saveTimer(self): continue list.append( '\n') else: for log_time, code, msg in timer.log_entries: - list.append(f'>\n{stringToXML(msg)}\n%s\n\n') list.append('\n') From c77429fc6c5674563c6c244ef18b04666cb6a3f2 Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Sun, 3 Mar 2024 09:52:51 +0100 Subject: [PATCH 178/183] Revert "[RecordTimer] - f string cleanup" This reverts commit f863933361e7049241cddf968c46f8b30df8fcd8. --- lib/python/RecordTimer.py | 97 ++++++++++++++++++++++----------------- 1 file changed, 56 insertions(+), 41 deletions(-) diff --git a/lib/python/RecordTimer.py b/lib/python/RecordTimer.py index 2096713bdc8..5dd8ee5099b 100644 --- a/lib/python/RecordTimer.py +++ b/lib/python/RecordTimer.py @@ -92,7 +92,7 @@ def findSafeRecordPath(dirname): try: makedirs(dirname) except Exception as ex: - print(f"[RecordTimer] Failed to create dir '{dirname}':", ex) + print("[RecordTimer] Failed to create dir '%s':" % dirname, ex) return None return dirname @@ -286,11 +286,11 @@ def __init__(self, serviceref, begin, end, name, description, eit, disabled=Fals def __repr__(self): ice = "" if self.ice_timer_id is not None: - ice = f", ice_timer_id={self.ice_timer_id}" + ice = ", ice_timer_id=%s" % self.ice_timer_id if not self.disabled: - return f"RecordTimerEntry(name={self.name}, begin={ctime(self.begin)}, serviceref={self.service_ref}, justplay={self.justplay}, isAutoTimer={self.isAutoTimer}, autoTimerId={self.autoTimerId}{ice})" + return "RecordTimerEntry(name=%s, begin=%s, serviceref=%s, justplay=%s, isAutoTimer=%s, autoTimerId=%s%s)" % (self.name, ctime(self.begin), self.service_ref, self.justplay, self.isAutoTimer, self.autoTimerId, ice) else: - return f"RecordTimerEntry(name={self.name}, begin={ctime(self.begin)}, serviceref={self.service_ref}, justplay={self.justplay}, isAutoTimer={self.isAutoTimer}, autoTimerId={self.autoTimerId}{ice}, Disabled)" + return "RecordTimerEntry(name=%s, begin=%s, serviceref=%s, justplay=%s, isAutoTimer=%s, autoTimerId=%s%s, Disabled)" % (self.name, ctime(self.begin), self.service_ref, self.justplay, self.isAutoTimer, self.autoTimerId, ice) def log(self, code, msg): self.log_entries.append((int(time()), code, msg)) @@ -311,7 +311,7 @@ def freespace(self): self.MountPath = dirname mountwriteable = access(dirname, W_OK) if not mountwriteable: - self.log(0, f"Mount '{dirname}' is not writeable.") + self.log(0, ("Mount '%s' is not writeable." % dirname)) return False s = statvfs(dirname) @@ -350,7 +350,7 @@ def calculateFilename(self, name=None): filename = ASCIItranslit.legacyEncode(filename) self.Filename = Directories.getRecordingFilename(filename, self.MountPath) - self.log(0, f"Filename calculated as: '{self.Filename}'") + self.log(0, "Filename calculated as: '%s'" % self.Filename) return self.Filename def getEventFromEPGId(self, id=None): @@ -421,7 +421,7 @@ def tryPrepare(self): if prep_res == -255: self.log(4, "failed to write meta information") else: - self.log(2, f"'prepare' failed: error {prep_res}") + self.log(2, "'prepare' failed: error %d" % prep_res) # we must calc new start time before stopRecordService call because in Screens/Standby.py TryQuitMainloop tries to get # the next start time in evEnd event handler... @@ -441,7 +441,7 @@ def do_backoff(self): self.backoff *= 2 if self.backoff > 100: self.backoff = 100 - self.log(10, f"backoff: retry in {self.backoff} seconds") + self.log(10, "backoff: retry in %d seconds" % self.backoff) def sendactivesource(self): if SystemInfo["hasHdmiCec"] and config.hdmicec.enabled.value and config.hdmicec.sourceactive_zaptimers.value: # Command the TV to switch to the correct HDMI input when zap timers activate @@ -467,7 +467,7 @@ def _bouquet_search(self): if config.usage.multibouquet.value: bqrootstr = '1:7:1:0:0:0:0:0:0:0:FROM BOUQUET "bouquets.tv" ORDER BY bouquet' else: - bqrootstr = f'{self.service_types} FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet' + bqrootstr = '%s FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet' % self.service_types serviceHandler = eServiceCenter.getInstance() rootbouquet = eServiceReference(bqrootstr) bouquet = eServiceReference(bqrootstr) @@ -505,7 +505,7 @@ def log_tuner(self, level, state): # Report the tuner that the current record feinfo = timer_rs and hasattr(timer_rs, "frontendInfo") and timer_rs.frontendInfo() fedata = feinfo and hasattr(feinfo, "getFrontendData") and feinfo.getFrontendData() tuner_info = fedata and "tuner_number" in fedata and chr(ord("A") + fedata.get("tuner_number")) or "(fallback) stream" - self.log(level, f"{state} recording on tuner: {tuner_info}") + self.log(level, "%s recording on tuner: %s" % (state, tuner_info)) def activate(self): if not self.InfoBarInstance: @@ -515,11 +515,11 @@ def activate(self): print("[RecordTimer] import 'Screens.InfoBar' failed") next_state = self.state + 1 - self.log(5, f"activating state {next_state} {TimerEntry.States.get(next_state, '?')}") + self.log(5, "activating state %d (%s)" % (next_state, TimerEntry.States.get(next_state, "?"))) if next_state == self.StatePrepared: if not self.justplay and not self.freespace(): - Notifications.AddPopup(text=_(f"Write error while recording. Disk full?\n{self.name}"), type=MessageBox.TYPE_ERROR, timeout=5, id="DiskFullMessage") + Notifications.AddPopup(text=_("Write error while recording. Disk full?\n%s") % self.name, type=MessageBox.TYPE_ERROR, timeout=5, id="DiskFullMessage") self.failed = True self.next_activation = time() self.end = time() + 5 @@ -652,7 +652,7 @@ def activate(self): self.InfoBarInstance.session.pip.servicePath = self.InfoBarInstance.servicelist and self.InfoBarInstance.servicelist.getCurrentServicePath() self.log(11, "zapping as PiP") if notify: - Notifications.AddPopup(text=_(f"Zapped to timer service {self.service_ref.getServiceName()} as PiP!"), type=MessageBox.TYPE_INFO, timeout=5) + Notifications.AddPopup(text=_("Zapped to timer service %s as PiP!") % self.service_ref.getServiceName(), type=MessageBox.TYPE_INFO, timeout=5) return True else: del self.InfoBarInstance.session.pip @@ -663,7 +663,7 @@ def activate(self): else: self.log(11, "zapping") if notify: - Notifications.AddPopup(text=_(f"Zapped to timer service {self.service_ref.getServiceName()}!"), type=MessageBox.TYPE_INFO, timeout=5) + Notifications.AddPopup(text=_("Zapped to timer service %s!") % self.service_ref.getServiceName(), type=MessageBox.TYPE_INFO, timeout=5) # If the user is looking at a MovieList then we need to update this # lastservice, so that we get back to the updated one when closing the @@ -691,7 +691,7 @@ def activate(self): record_res = self.record_service.start() self.setRecordingPreferredTuner(setdefault=True) if record_res: - self.log(13, f"start recording error: {record_res}") + self.log(13, "start recording error: %d" % record_res) self.do_backoff() # retry self.begin = time() + self.backoff @@ -703,7 +703,7 @@ def activate(self): old_end = self.end self.ts_dialog = None if self.setAutoincreaseEnd(): - self.log(12, f"autoincrease recording {int(self.end - old_end) / 60} minute(s)") + self.log(12, "autoincrease recording %d minute(s)" % int((self.end - old_end) / 60)) self.state -= 1 return True self.log_tuner(12, "stop") @@ -736,7 +736,7 @@ def activate(self): if self.afterEvent == AFTEREVENT.STANDBY or (not wasRecTimerWakeup and self.autostate and self.afterEvent == AFTEREVENT.AUTO) or self.wasInStandby: self.keypress() # this unbinds the keypress detection if not Screens.Standby.inStandby: # not already in standby - Notifications.AddNotificationWithCallback(self.sendStandbyNotification, MessageBox, _(f"A finished record timer wants to set your\n{SystemInfo['MachineBrand']} {SystemInfo['MachineName']} to standby. Do that now?"), timeout=180) + Notifications.AddNotificationWithCallback(self.sendStandbyNotification, MessageBox, _("A finished record timer wants to set your\n%s %s to standby. Do that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) elif self.afterEvent == AFTEREVENT.DEEPSTANDBY or (wasRecTimerWakeup and self.afterEvent == AFTEREVENT.AUTO and Screens.Standby.inStandby): if (abs(NavigationInstance.instance.RecordTimer.getNextRecordingTime() - time()) <= 900 or abs(NavigationInstance.instance.RecordTimer.getNextZapTime() - time()) <= 900) or NavigationInstance.instance.RecordTimer.getStillRecording(): print("[RecordTimer] Recording or Recording due is next 15 mins, not return to deepstandby") @@ -751,7 +751,7 @@ def activate(self): if int(ClientsStreaming("NUMBER").getText()) > 0: if not Screens.Standby.inStandby: # not already in standby Notifications.AddNotificationWithCallback(self.sendStandbyNotification, MessageBox, - _(f"A finished record timer wants to set your\n{SystemInfo['MachineBrand']} {SystemInfo['MachineName']} to standby. Do that now?") + _("A finished record timer wants to set your\n%s %s to standby. Do that now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]) + _("\n(DeepStandby request changed to Standby owing to there being streaming clients.)"), timeout=180) return True @@ -759,7 +759,7 @@ def activate(self): if Screens.Standby.inStandby: # in standby quitMainloop(1) else: - Notifications.AddNotificationWithCallback(self.sendTryQuitMainloopNotification, MessageBox, _(f"A finished record timer wants to shut down\nyour {SystemInfo['MachineBrand']} {SystemInfo['MachineName']}. Shutdown now?"), timeout=180) + Notifications.AddNotificationWithCallback(self.sendTryQuitMainloopNotification, MessageBox, _("A finished record timer wants to shut down\nyour %s %s. Shutdown now?") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]), timeout=180) return True def keypress(self, key=None, flag=1): @@ -811,7 +811,7 @@ def openChoiceActionBeforeZap(self): type = _("zap") elif self.always_zap: type = _("zap and record") - message = _(f"You must switch to the service {type} ({self.service_ref.getServiceName()} - '{self.name}')!\n") + message = _("You must switch to the service %s (%s - '%s')!\n") % (type, self.service_ref.getServiceName(), self.name) if self.repeated: message += _("Attention, this is repeated timer!\n") message += _("Timeshift is running. Select an action.\n") @@ -903,13 +903,13 @@ def timeChanged(self): self.backoff = 0 if int(old_prepare) > 60 and int(old_prepare) != int(self.start_prepare): - self.log(15, f"record time changed, start prepare is now: {ctime(self.start_prepare)}") + self.log(15, "record time changed, start prepare is now: %s" % ctime(self.start_prepare)) def gotRecordEvent(self, record, event): # TODO: this is not working (never true), please fix. (comparing two swig wrapped ePtrs) if self.__record_service.__deref__() != record.__deref__(): return - # self.log(16, f"record event {event}") + # self.log(16, "record event %d" % event) if event == iRecordableService.evRecordWriteError: print("[RecordTimer] WRITE ERROR on recording, disk full?") # show notification. the "id" will make sure that it will be @@ -921,7 +921,7 @@ def gotRecordEvent(self, record, event): # TODO: this has to be done. elif event == iRecordableService.evStart: RecordingsState(1) - text = _(f"A recording has been started:\n{self.name}") + text = _("A recording has been started:\n%s") % self.name notify = config.usage.show_message_when_recording_starts.value and not Screens.Standby.inStandby and self.InfoBarInstance and self.InfoBarInstance.execing if self.dirnameHadToFallback: text = "\n".join((text, _("Please note that the previously selected media could not be accessed and therefore the default directory is being used instead."))) @@ -1100,7 +1100,7 @@ def loadTimer(self, justLoad=False): # justLoad is passed on to record() if conflict_list: checkit = True if newTimer in conflict_list: - timer_text += _(f"\nTimer '{newTimer.name}' disabled!") + timer_text += _("\nTimer '%s' disabled!") % newTimer.name if checkit: from Tools.Notifications import AddPopup from Screens.MessageBox import MessageBox @@ -1120,21 +1120,36 @@ def saveTimer(self): continue list.append( '\n') else: for log_time, code, msg in entry.log_entries: - list.append(f'>\n{stringToXML(msg)}\n%s\n\n') list.append('\n') @@ -1269,7 +1284,7 @@ def record(self, entry, ignoreTSC=False, dosave=True, loadtimer=False, justLoad= entry.begin += 1 entry.conflict_detection = real_cd entry.timeChanged() - # print(f"[Timer] Record {entry}") + # print("[Timer] Record %s" % entry) entry.Timer = self self.addTimerEntry(entry) From da1066909f705c6e14cbe4cd7279d535b9794e67 Mon Sep 17 00:00:00 2001 From: Dimitar Tsenev Date: Sat, 9 Mar 2024 12:54:58 +0200 Subject: [PATCH 179/183] [Added] suppression of loading EIT events when there was epg import (#992) * [Added] suppression of loading EIT events when there was epg import * [Fixed] build error --- lib/dvb/epgcache.cpp | 18 ++++++++++++++++-- lib/dvb/epgcache.h | 2 ++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/dvb/epgcache.cpp b/lib/dvb/epgcache.cpp index a6bdcadeba8..c4158edeaf1 100644 --- a/lib/dvb/epgcache.cpp +++ b/lib/dvb/epgcache.cpp @@ -599,7 +599,7 @@ void eEPGCache::sectionRead(const uint8_t *data, int source, eEPGChannelData *ch TM = parseDVBtime((const uint8_t*)eit_event + 2, &event_hash); std::vector::iterator m_it=find(onid_blacklist.begin(),onid_blacklist.end(),onid); - if (m_it != onid_blacklist.end()) + if (m_it != onid_blacklist.end() || (source != EPG_IMPORT && getIsEpgEventSupressed(service))) goto next; if ( (TM != 3599) && // NVOD Service @@ -1895,7 +1895,13 @@ void eEPGCache::submitEventData(const std::vector& service eDVBChannelID chid; serviceRef->getChannelID(chid); chids.push_back(chid); - sids.push_back(serviceRef->getServiceID().get()); + int sid = serviceRef->getServiceID().get(); + sids.push_back(sid); + + uniqueEPGKey serviceKey(sid, chid.original_network_id.get(), chid.transport_stream_id.get()); + if (std::find(epgkey_blacklist.begin(), epgkey_blacklist.end(), serviceKey) == epgkey_blacklist.end()) { + epgkey_blacklist.push_back(serviceKey); + } // disable EIT event parsing when using EPG_IMPORT ePtr service; @@ -2109,6 +2115,14 @@ unsigned int eEPGCache::getEpgSources() return m_enabledEpgSources; } +bool eEPGCache::getIsEpgEventSupressed(const uniqueEPGKey epgKey) +{ + if (std::find(epgkey_blacklist.begin(), epgkey_blacklist.end(), epgKey) != epgkey_blacklist.end()) { + return true; + } + return false; +} + static const char* getStringFromPython(ePyObject obj) { const char *result = 0; diff --git a/lib/dvb/epgcache.h b/lib/dvb/epgcache.h index 34e4e1bb02e..ee54d5a1090 100644 --- a/lib/dvb/epgcache.h +++ b/lib/dvb/epgcache.h @@ -148,6 +148,7 @@ class eEPGCache: public eMainloop, private eThread, public sigc::trackable ePtr cleanTimer; bool load_epg; PSignal0 epgCacheStarted; + std::vector epgkey_blacklist; #ifdef ENABLE_PRIVATE_EPG contentMaps content_time_tables; @@ -261,6 +262,7 @@ class eEPGCache: public eMainloop, private eThread, public sigc::trackable void setEpgHistorySeconds(time_t seconds); void setEpgSources(unsigned int mask); unsigned int getEpgSources(); + bool getIsEpgEventSupressed(const uniqueEPGKey epgKey); void submitEventData(const std::vector& serviceRefs, long start, long duration, const char* title, const char* short_summary, const char* long_description, std::vector event_types, std::vector parental_ratings, uint16_t eventId=0); From 8ea017508febf530b027cb67896919caba99b280 Mon Sep 17 00:00:00 2001 From: openvix-build Date: Sun, 10 Mar 2024 10:31:25 +0000 Subject: [PATCH 180/183] openvix: developer 6.5.001.009 --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index caf1100d6d5..d08dc2d3c4c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1242,3 +1242,4 @@ openvix: developer 6.5.001.005 openvix: developer 6.5.001.006 openvix: developer 6.5.001.007 openvix: developer 6.5.001.008 +openvix: developer 6.5.001.009 From c90f3b47c55ace7c1bc3dfbad46222ce23ba19bf Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Mon, 11 Mar 2024 09:15:08 +0100 Subject: [PATCH 181/183] [HdmiCec] - don't issue TV standby on timer power up from Standby --- lib/python/Components/HdmiCec.py | 14 +++++++++++--- lib/python/Navigation.py | 26 ++++++++++++-------------- lib/python/Screens/Standby.py | 21 +++++++++++---------- 3 files changed, 34 insertions(+), 27 deletions(-) diff --git a/lib/python/Components/HdmiCec.py b/lib/python/Components/HdmiCec.py index a3a0dff2609..424a2757bfe 100644 --- a/lib/python/Components/HdmiCec.py +++ b/lib/python/Components/HdmiCec.py @@ -1,6 +1,6 @@ import chardet import datetime -from os import path, uname +from os import path, uname, remove import struct from sys import maxsize @@ -392,7 +392,7 @@ def messageReceived(self, message): ctrl2 = message.getControl2() msgaddress = message.getAddress() # 0 = TV, 5 = receiver 15 = broadcast if CECcmd != "": - print(f"[HdmiCEC][messageReceived0]: msgaddress={msgaddress} CECcmd={CECcmd}, cmd={cmd}, ctrl0={ctrl0}, datalength={length}") + print(f"[HdmiCEC][messageReceived0]: msgaddress={msgaddress} CECcmd={CECcmd}, cmd={cmd:02X}, ctrl0={ctrl0}, datalength={length}") if config.hdmicec.debug.value != "0": self.debugRx(length, cmd, ctrl0) if msgaddress > 15: # workaround for wrong address from driver (e.g. hd51, message comes from tv -> address is only sometimes 0, dm920, same tv -> address is always 0) @@ -533,7 +533,15 @@ def sendMessage(self, msgaddress, message): else: cmd = 0x04 elif message == "standby": - cmd = 0x36 + cecTimerWakeup = False + if path.exists("/tmp/was_cectimer_wakeup",): + with open("/tmp/was_cectimer_wakeup", "r") as f: + file = f.read() + cecTimerWakeup = int(file) and True or False + remove("/tmp/was_cectimer_wakeup") + print(f"[HdmiCec][sendMessage]: send message={message} cecTimerWakeup=", cecTimerWakeup) + if not cecTimerWakeup: + cmd = 0x36 elif message == "osdname": cmd = 0x47 data = uname()[1] diff --git a/lib/python/Navigation.py b/lib/python/Navigation.py index 16143821477..29dda8ef6f8 100644 --- a/lib/python/Navigation.py +++ b/lib/python/Navigation.py @@ -52,6 +52,7 @@ def __init__(self, nextRecordTimerAfterEventActionAuto=False, nextPowerManagerAf def _processTimerWakeup(self): now = time() + wakeup = "" timeHandlerCallbacks = eDVBLocalTimeHandler.getInstance().m_timeUpdated.get() if self.__nextRecordTimerAfterEventActionAuto and now < eDVBLocalTimeHandler.timeOK: # 01.01.2004 print("[Navigation] RECTIMER: wakeup to standby but system time not set.") @@ -62,21 +63,18 @@ def _processTimerWakeup(self): timeHandlerCallbacks.remove(self._processTimerWakeup) if self.__nextRecordTimerAfterEventActionAuto and abs(self.RecordTimer.getNextRecordingTime() - now) <= 360: - print("[Navigation] RECTIMER: wakeup to standby detected.") - f = open("/tmp/was_rectimer_wakeup", "w") - f.write("1") - f.close() - # as we woke the box to record, place the box in standby. - self.standbytimer = eTimer() - self.standbytimer.callback.append(self.gotostandby) - self.standbytimer.start(15000, True) - + wakeup = "/tmp/was_rectimer_wakeup" # set wakeup flags as RecordTimer woke the box to record, place the box in standby. elif self.__nextPowerManagerAfterEventActionAuto: - print("[Navigation] POWERTIMER: wakeup to standby detected.") - f = open("/tmp/was_powertimer_wakeup", "w") - f.write("1") - f.close() - # as a PowerTimer WakeToStandby was actiond to it. + wakeup = "/tmp/was_powertimer_wakeup" # set wakeup flags as a PowerTimer WakeToStandby was actioned. + if wakeup: + fwakeup = open(f"{wakeup}", "w") # set wakeup timer type + fwakeup.write("1") + fwakeup.close() + if path.exists(f"{wakeup}"): + print(f"[Navigation] TIMER: wakeup to standby detected, flag set: {wakeup}.") + fcec = open("/tmp/was_cectimer_wakeup", "w") # tell Cec was timer wakeup, so don't issue Standby to TV + fcec.write("1") + fcec.close() self.standbytimer = eTimer() self.standbytimer.callback.append(self.gotostandby) self.standbytimer.start(15000, True) diff --git a/lib/python/Screens/Standby.py b/lib/python/Screens/Standby.py index 860d5f92dd1..d6f4a3efbf1 100644 --- a/lib/python/Screens/Standby.py +++ b/lib/python/Screens/Standby.py @@ -38,6 +38,16 @@ def setLCDMiniTVMode(value): pass +def sendCEC(): + print("[Standby][sendCEC] entered ") + from enigma import eHdmiCEC # noqa: E402 + msgaddress = 0x00 + cmd = 0x36 # 54 standby + data = "" + eHdmiCEC.getInstance().sendMessage(msgaddress, cmd, data, len(data)) + print("[Standby][sendCEC] departed ") + + class Standby2(Screen): def Power(self): if SystemInfo["brand"] in ('dinobot') or SystemInfo["HasHiSi"] or SystemInfo["boxtype"] in ("sfx6008", "sfx6018"): @@ -301,21 +311,12 @@ def getRecordEvent(self, recservice, event): elif event == iRecordableService.evStart: self.stopTimer() - def sendCEC(self): - print("[Standby][sendCEC] entered ") - from enigma import eHdmiCEC # noqa: E402 - msgaddress = 0x00 - cmd = 0x36 # 54 standby - data = "" - eHdmiCEC.getInstance().sendMessage(msgaddress, cmd, data, len(data)) - print("[Standby][sendCEC] departed ") - def close(self, value): if self.connected: self.connected = False self.session.nav.record_event.remove(self.getRecordEvent) if config.hdmicec.enabled.value and self.retval == 1: - self.sendCEC() + sendCEC() if value: self.hide() if self.retval == 1: From 2a92646cacf5922dc150f2688b48e644f45dc3f1 Mon Sep 17 00:00:00 2001 From: LraiZer Date: Sun, 10 Mar 2024 21:35:50 +0000 Subject: [PATCH 182/183] [OpenTV] Add genre and parental rating to EPG cache * Add GBR OpenTV parental ratings used on 28.2e * Add GBR OpenTV genreId lists, mostly complete * Add ITA OpenTV parental ratings used on 13.0e * Add ITA OpenTV genreId lists, mostly complete * Prepare AUS and NZL for OpenTV genreId lists --- lib/dvb/epgchanneldata.cpp | 62 ++- lib/dvb/epgchanneldata.h | 3 + lib/dvb/opentv.cpp | 16 +- lib/dvb/opentv.h | 4 + lib/python/Components/Converter/EventName.py | 79 +++- lib/python/Components/Converter/genre.py | 438 ++++++++++++++++++- lib/python/Components/UsageConfig.py | 2 +- 7 files changed, 592 insertions(+), 12 deletions(-) diff --git a/lib/dvb/epgchanneldata.cpp b/lib/dvb/epgchanneldata.cpp index faeb66c2021..1de65d06a07 100644 --- a/lib/dvb/epgchanneldata.cpp +++ b/lib/dvb/epgchanneldata.cpp @@ -1822,13 +1822,17 @@ void eEPGChannelData::OPENTV_checkCompletion(uint32_t data_crc) { std::vector sids; std::vector chids; + std::vector event_types; + std::vector parental_ratings; eDVBChannelID chid = channel->getChannelID(); chid.transport_stream_id = m_OPENTV_channels_map[channelid].transportStreamId; chid.original_network_id = m_OPENTV_channels_map[channelid].originalNetworkId; chids.push_back(chid); sids.push_back(m_OPENTV_channels_map[channelid].serviceId); + event_types.push_back(it->second.genreId); + parental_ratings.push_back(getOpenTvParentalRating(chid.dvbnamespace.get(), it->second.parentalRating)); if (eEPGCache::getInstance()) - eEPGCache::getInstance()->submitEventData(sids, chids, it->second.startTime, it->second.duration, m_OPENTV_descriptors_map[it->second.title_crc].c_str(), "", "", 0, it->second.eventId, eEPGCache::OPENTV); + eEPGCache::getInstance()->submitEventData(sids, chids, it->second.startTime, it->second.duration, m_OPENTV_descriptors_map[it->second.title_crc].c_str(), "", "", event_types, parental_ratings, it->second.eventId, eEPGCache::OPENTV); } } m_OPENTV_descriptors_map.clear(); @@ -1896,6 +1900,8 @@ void eEPGChannelData::OPENTV_TitlesSection(const uint8_t *d) ote.startTime = (*title)->getStartTime(); ote.duration = (*title)->getDuration(); ote.title_crc = (*title)->getCRC32(); + ote.genreId = (*title)->getGenreId(); + ote.parentalRating = (*title)->getParentalRating(); m_OPENTV_EIT_map[etm] = ote; if (m_OPENTV_descriptors_map.find(ote.title_crc) == m_OPENTV_descriptors_map.end()) @@ -1927,11 +1933,15 @@ void eEPGChannelData::OPENTV_SummariesSection(const uint8_t *d) { std::vector sids; std::vector chids; + std::vector event_types; + std::vector parental_ratings; eDVBChannelID chid = channel->getChannelID(); chid.transport_stream_id = m_OPENTV_channels_map[channelid].transportStreamId; chid.original_network_id = m_OPENTV_channels_map[channelid].originalNetworkId; chids.push_back(chid); sids.push_back(m_OPENTV_channels_map[channelid].serviceId); + event_types.push_back(ote.genreId); + parental_ratings.push_back(getOpenTvParentalRating(chid.dvbnamespace.get(), ote.parentalRating)); // hack to fix split titles std::string sTitle = m_OPENTV_descriptors_map[ote.title_crc]; @@ -1940,7 +1950,7 @@ void eEPGChannelData::OPENTV_SummariesSection(const uint8_t *d) removePrefixesFromEventName(sTitle, sSummary); if (eEPGCache::getInstance()) - eEPGCache::getInstance()->submitEventData(sids, chids, ote.startTime, ote.duration, sTitle.c_str(), "", sSummary.c_str(), 0, ote.eventId, eEPGCache::OPENTV); + eEPGCache::getInstance()->submitEventData(sids, chids, ote.startTime, ote.duration, sTitle.c_str(), "", sSummary.c_str(), event_types, parental_ratings, ote.eventId, eEPGCache::OPENTV); } m_OPENTV_EIT_map.erase(otce); } @@ -1950,6 +1960,54 @@ void eEPGChannelData::OPENTV_SummariesSection(const uint8_t *d) OPENTV_checkCompletion(otss.getCrc32()); } +eit_parental_rating eEPGChannelData::getOpenTvParentalRating(int dvbnamespace, int parental_rating) +{ + eit_parental_rating epr; + + switch ((dvbnamespace >> 16) & 0xffff) + { + case 0x011A: // country code 'GBR' + /* 28.2e sends data {0,1,2,3,4,5} + classification {"",U,PG,12,15,18} + convert to ETSI min age with 3x */ + parental_rating = parental_rating * 3; + epr.country_code[0] = 'O'; + epr.country_code[1] = 'T'; + epr.country_code[2] = '1'; + break; + case 0x0082: // country code 'ITA' + /* 13.0e sends data {0,1,2,3,4,5} + classification {"",T,BA,12,14,18} + convert to ETSI min age with 3x */ + epr.country_code[0] = 'O'; + epr.country_code[1] = 'T'; + epr.country_code[2] = '2'; + parental_rating = parental_rating * 3; + break; + case 0x0618: // country code 'AUS' + epr.country_code[0] = 'O'; + epr.country_code[1] = 'T'; + epr.country_code[2] = '3'; + break; + case 0x0640: // country code 'NZL' + epr.country_code[0] = 'O'; + epr.country_code[1] = 'T'; + epr.country_code[2] = '4'; + break; + default: // country code 'ETSI' + epr.country_code[0] = 'O'; + epr.country_code[1] = 'T'; + epr.country_code[2] = 'V'; + break; + } + + if (parental_rating > 15) + epr.rating = 0; + else + epr.rating = parental_rating; + + return epr; +} void eEPGChannelData::cleanupOPENTV() { diff --git a/lib/dvb/epgchanneldata.h b/lib/dvb/epgchanneldata.h index 4da5d9503b8..7f3a57b98a7 100644 --- a/lib/dvb/epgchanneldata.h +++ b/lib/dvb/epgchanneldata.h @@ -129,6 +129,8 @@ class eEPGChannelData: public sigc::trackable uint32_t startTime; uint32_t duration; uint32_t title_crc; + uint8_t genreId; + uint8_t parentalRating; }; OpenTvDescriptorMap m_OPENTV_descriptors_map; std::map m_OPENTV_channels_map; @@ -136,6 +138,7 @@ class eEPGChannelData: public sigc::trackable ePtr m_OPENTV_Timer; ePtr m_OPENTV_ChannelsReader, m_OPENTV_TitlesReader, m_OPENTV_SummariesReader; ePtr m_OPENTV_ChannelsConn, m_OPENTV_TitlesConn, m_OPENTV_SummariesConn; + eit_parental_rating getOpenTvParentalRating(int dvbnamespace, int parental_rating); void OPENTV_checkCompletion(const uint32_t data_crc); void OPENTV_ChannelsSection(const uint8_t *d); void OPENTV_TitlesSection(const uint8_t *d); diff --git a/lib/dvb/opentv.cpp b/lib/dvb/opentv.cpp index eed9df12588..b3da978ef57 100644 --- a/lib/dvb/opentv.cpp +++ b/lib/dvb/opentv.cpp @@ -175,9 +175,9 @@ OpenTvTitle::OpenTvTitle(const uint8_t * const buffer, uint16_t startMjd) duration = UINT16(&buffer[4]) << 1; //genre content - //uint8_t flag1 = buffer[6]; - //uint8_t flag2 = buffer[7]; - //uint8_t flag3 = buffer[8]; + genreId = buffer[6]; + //uint8_t flag = buffer[7]; + parentalRating = buffer[8] & 0x0f; char tmp[OPENTV_EVENT_TITLE_LENGTH]; memset(tmp, '\0', OPENTV_EVENT_TITLE_LENGTH); @@ -231,6 +231,16 @@ uint32_t OpenTvTitle::getDuration(void) const return duration; } +uint8_t OpenTvTitle::getGenreId(void) const +{ + return genreId; +} + +uint8_t OpenTvTitle::getParentalRating(void) const +{ + return parentalRating; +} + void OpenTvTitle::setChannelId(uint16_t channelid) { channelId = channelid; diff --git a/lib/dvb/opentv.h b/lib/dvb/opentv.h index 50608e8fd40..e2c62a74b3f 100644 --- a/lib/dvb/opentv.h +++ b/lib/dvb/opentv.h @@ -66,6 +66,8 @@ class OpenTvTitle : public DescriptorContainer unsigned startTimeBcd : 32; unsigned duration : 24; unsigned crc32 : 32; + unsigned genreId : 8; + unsigned parentalRating : 8; std::string title; public: @@ -78,6 +80,8 @@ class OpenTvTitle : public DescriptorContainer uint32_t getStartTime(void) const; uint16_t getEventId(void) const; uint32_t getDuration(void) const; + uint8_t getGenreId(void) const; + uint8_t getParentalRating(void) const; void setChannelId(uint16_t channelid); void setEventId(uint16_t eventId); }; diff --git a/lib/python/Components/Converter/EventName.py b/lib/python/Components/Converter/EventName.py index 26ec944b01a..e67aa6d0aa3 100644 --- a/lib/python/Components/Converter/EventName.py +++ b/lib/python/Components/Converter/EventName.py @@ -2,7 +2,7 @@ from Components.Converter.Converter import Converter from Components.Element import cached -from Components.Converter.genre import getGenreStringSub +from Components.Converter.genre import getGenreStringSub, getGenreStringLong from Components.config import config from Tools.Directories import resolveFilename, SCOPE_CURRENT_SKIN from time import time, localtime, mktime, strftime @@ -65,6 +65,56 @@ def __init__(self): self.update([(i, (c, self.LONGTEXT[c], self.IMAGES[c])) for i, c in enumerate(self.SHORTTEXT)]) +class GBrClassifications(dict): + # British Board of Film Classification + # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + SHORTTEXT = ("", "", "", "U", "U", "U", "PG", "PG", "PG", "12", "12", "12", "15", "15", "15", "18") + LONGTEXT = { + "": _("Not Classified"), + "U": _("U - Suitable for all"), + "PG": _("PG - Parental Guidance"), + "12": _("Suitable for ages 12+"), + "15": _("Suitable for ages 15+"), + "18": _("Suitable only for Adults") + } + IMAGES = { + "": "ratings/blank.png", + "U": "ratings/GBR-U.png", + "PG": "ratings/GBR-PG.png", + "12": "ratings/GBR-12.png", + "15": "ratings/GBR-15.png", + "18": "ratings/GBR-18.png" + } + + def __init__(self): + self.update([(i, (c, self.LONGTEXT[c], self.IMAGES[c])) for i, c in enumerate(self.SHORTTEXT)]) + + +class ItaClassifications(dict): + # The classifications used by Sky Italia + # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + SHORTTEXT = ("", "", "", "T", "T", "T", "BA", "BA", "BA", "12", "12", "12", "14", "14", "14", "18") + LONGTEXT = { + "": _("Non Classificato"), + "T": _("Per Tutti"), + "BA": _("Bambini Accompagnati"), + "12": _("Dai 12 anni in su"), + "14": _("Dai 14 anni in su"), + "18": _("Dai 18 anni in su") + } + IMAGES = { + "": "ratings/blank.png", + "T": "ratings/ITA-T.png", + "BA": "ratings/ITA-BA.png", + "12": "ratings/ITA-12.png", + "14": "ratings/ITA-14.png", + "18": "ratings/ITA-18.png" + } + + def __init__(self): + self.update([(i, (c, self.LONGTEXT[c], self.IMAGES[c])) for i, c in enumerate(self.SHORTTEXT)]) + + # Each country classification object in the map tuple must be an object that # supports obj.get(key[, default]). It need not actually be a dict object. # @@ -75,7 +125,20 @@ def __init__(self): countries = { "ETSI": (ETSIClassifications(), lambda age: (_("bc%d") % age, _("Rating defined by broadcaster - %d") % age, "ratings/ETSI-na.png")), - "AUS": (AusClassifications(), lambda age: (_("BC%d") % age, _("Rating defined by broadcaster - %d") % age, "ratings/AUS-na.png")) + "AUS": (AusClassifications(), lambda age: (_("BC%d") % age, _("Rating defined by broadcaster - %d") % age, "ratings/AUS-na.png")), + "GBR": (GBrClassifications(), lambda age: (_("BC%d") % age, _("Rating defined by broadcaster - %d") % age, "ratings/GBR-na.png")), + "ITA": (ItaClassifications(), lambda age: (_("BC%d") % age, _("Rating defined by broadcaster - %d") % age, "ratings/ITA-na.png")) +} + + +# OpenTV country codes: epgchanneldata.cpp +# eEPGChannelData::getOpenTvParentalRating +opentv_countries = { + "OT1": "GBR", + "OT2": "ITA", + "OT3": "AUS", + "OT4": "NZL", + "OTV": "ETSI" } @@ -220,6 +283,8 @@ def getText(self): if rating: age = rating.getRating() country = rating.getCountryCode().upper() + if country in opentv_countries: + country = opentv_countries[country] if country in countries: c = countries[country] else: @@ -245,9 +310,13 @@ def getText(self): country = rating.getCountryCode().upper() else: country = "ETSI" - if config.misc.epggenrecountry.value: - country = config.misc.epggenrecountry.value - return self.separator.join((genretext for genretext in (self.trimText(getGenreStringSub(genre[0], genre[1], country=country)) for genre in genres) if genretext)) + if country in opentv_countries: + country = opentv_countries[country] + "OpenTV" + return self.separator.join((genretext for genretext in (self.trimText(getGenreStringLong(genre[0], genre[1], country=country)) for genre in genres) if genretext)) + else: + if config.misc.epggenrecountry.value: + country = config.misc.epggenrecountry.value + return self.separator.join((genretext for genretext in (self.trimText(getGenreStringSub(genre[0], genre[1], country=country)) for genre in genres) if genretext)) elif self.type == self.NAME_NOW: return pgettext("now/next: 'now' event label", "Now") + ": " + self.trimText(event.getEventName()) elif self.type == self.SHORT_DESCRIPTION: diff --git a/lib/python/Components/Converter/genre.py b/lib/python/Components/Converter/genre.py index f8a0f919859..460e9b74683 100644 --- a/lib/python/Components/Converter/genre.py +++ b/lib/python/Components/Converter/genre.py @@ -710,6 +710,423 @@ class GenresDEUIceTV: } +class GenresGBROpenTV: + maintype = ( + _("General"), # 0x0 + _("General"), # 0x1 + _("General"), # 0x2 + _("General"), # 0x3 + _("Children"), # 0x4 + _("Children"), # 0x5 + _("Entertainment"), # 0x6 + _("Entertainment"), # 0x7 + _("Music"), # 0x8 + _("Music"), # 0x9 + _("News/Documentary"), # 0xa + _("News/Documentary"), # 0xb + _("Movie"), # 0xc + _("Movie"), # 0xd + _("Sports"), # 0xe + _("Sports"), # 0xf + ) + + subtype = { + # General + 0: ( + _("No Category"), # 0x00 + ), + # General + 2: ( + _("No Category"), # 0x20 + _("Adult"), # 0x21 + _("Unused 0x22"), # 0x22 + _("Shopping"), # 0x23 + ), + # Children + 4: ( + _("General"), # 0x40 + _("Cartoons"), # 0x41 + _("Comedy"), # 0x42 + _("Drama"), # 0x43 + _("Educational"), # 0x44 + _("Under 5"), # 0x45 + _("Factual"), # 0x46 + _("Magazine"), # 0x47 + ), + # Entertainment + 6: ( + _("General"), # 0x60 + _("Action"), # 0x61 + _("Comedy"), # 0x62 + _("Detective"), # 0x63 + _("Drama"), # 0x64 + _("Game Show"), # 0x65 + _("Sci-FI"), # 0x66 + _("Soap"), # 0x67 + _("Animation"), # 0x68 + _("Chat Show"), # 0x69 + _("Cooking"), # 0x6a + _("Factual"), # 0x6b + _("Fashion"), # 0x6c + _("Home and Garden"), # 0x6d + _("Travel"), # 0x6e + _("Technology"), # 0x6f + ), + # Entertainment cont... + 7: ( + _("Arts"), # 0x70 + _("Lifestyle"), # 0x71 + _("Home"), # 0x72 + _("Magazine"), # 0x73 + _("Medical"), # 0x74 + _("Review"), # 0x75 + _("Antiques"), # 0x76 + _("Motors"), # 0x77 + _("Art/Literature"), # 0x78 + _("Ballet"), # 0x79 + _("Opera"), # 0x7a + ), + # Music + 8: ( + _("General"), # 0x80 + _("Classical"), # 0x81 + _("Folk and Country"), # 0x82 + _("National Music"), # 0x83 + _("Jazz"), # 0x84 + _("Opera"), # 0x85 + _("Rock/Pop"), # 0x86 + _("Alternative"), # 0x87 + _("Events"), # 0x88 + _("Club/Dance"), # 0x89 + _("Hip Hop"), # 0x8a + _("Soul/Rhythm Blues"), # 0x8b + _("Dance"), # 0x8c + _("Unused 0x8d"), # 0x8d + _("Unused 0x8e"), # 0x8e + _("Unused 0x8f"), # 0x8f + ), + # Music cont... + 9: ( + _("Features"), # 0x90 + _("Unused 0x91"), # 0x91 + _("Unused 0x92"), # 0x92 + _("Unused 0x93"), # 0x93 + _("Unused 0x94"), # 0x94 + _("Lifestyle"), # 0x95 + _("News and Weather"), # 0x96 + _("Easy Listening"), # 0x97 + _("Discussion"), # 0x98 + _("Entertainment"), # 0x99 + _("Religious"), # 0x9a + ), + # News/Documentary + 10: ( + _("General"), # 0xa0 + _("Business"), # 0xa1 + _("World Cultures"), # 0xa2 + _("Adventure"), # 0xa3 + _("Biography"), # 0xa4 + _("Educational"), # 0xa5 + _("Feature"), # 0xa6 + _("Politics"), # 0xa7 + _("News"), # 0xa8 + _("Nature"), # 0xa9 + _("Religious"), # 0xaa + _("Science"), # 0xab + _("Showbiz"), # 0xac + _("War"), # 0xad + _("Historical"), # 0xae + _("Ancient"), # 0xaf + ), + # News/Documentary cont... + 11: ( + _("Transport"), # 0xb0 + _("Docudrama"), # 0xb1 + _("World Affairs"), # 0xb2 + _("Events"), # 0xb3 + _("Entertainment"), # 0xb4 + ), + # Movie + 12: ( + _("General"), # 0xc0 + _("Action"), # 0xc1 + _("Animation"), # 0xc2 + _("Unused 0xc3"), # 0xc3 + _("Comedy"), # 0xc4 + _("Family"), # 0xc5 + _("Drama"), # 0xc6 + _("Unused 0xc7"), # 0xc7 + _("Sci-Fi"), # 0xc8 + _("Thriller"), # 0xc9 + _("Horror"), # 0xca + _("Romance"), # 0xcb + _("Musical"), # 0xcc + _("Mystery"), # 0xcd + _("Western"), # 0xce + _("Factual"), # 0xcf + ), + # Movie cont... + 13: ( + _("Fantasy"), # 0xd0 + _("Erotic"), # 0xd1 + _("Adventure"), # 0xd2 + _("War"), # 0xd3 + ), + # Sports + 14: ( + _("General"), # 0xe0 + _("American Football"), # 0xe1 + _("Athletics"), # 0xe2 + _("Baseball"), # 0xe3 + _("Basketball"), # 0xe4 + _("Boxing"), # 0xe5 + _("Cricket"), # 0xe6 + _("Fishing"), # 0xe7 + _("Football"), # 0xe8 + _("Golf"), # 0xe9 + _("Ice Hockey"), # 0xea + _("Motor Sport"), # 0xeb + _("Racing"), # 0xec + _("Rugby"), # 0xed + _("Equestrian"), # 0xee + _("Winter Sports"), # 0xef + ), + # Sports cont... + 15: ( + _("Snooker/Pool"), # 0xf0 + _("Tennis"), # 0xf1 + _("Wrestling"), # 0xf2 + _("Darts"), # 0xf3 + _("Watersports"), # 0xf4 + _("Extreme"), # 0xf5 + ), + } + + +class GenresITAOpenTV: + maintype = ( + _("Generale"), # 0x0 + _("Generale"), # 0x1 + _("Intrattenimento"), # 0x2 + _("Intrattenimento"), # 0x3 + _("Sport"), # 0x4 + _("Sport"), # 0x5 + _("Film"), # 0x6 + _("Film"), # 0x7 + _("Mondo e Tendenze"), # 0x8 + _("Mondo e Tendenze"), # 0x9 + _("Informazione"), # 0xa + _("Informazione"), # 0xb + _("Ragazzi e Musica"), # 0xc + _("Ragazzi e Musica"), # 0xd + _("Altri Programmi"), # 0xe + _("Altri Programmi"), # 0xf + ) + + subtype = { + # Generale + 0: ( + _("Non Definito"), # 0x00 + ), + # Intrattenimento + 2: ( + _("Generale"), # 0x20 + _("Fiction"), # 0x21 + _("Sit Com"), # 0x22 + _("Show"), # 0x23 + _("Telefilm"), # 0x24 + _("Soap Opera"), # 0x25 + _("Telenovela"), # 0x26 + _("Fantascienza"), # 0x27 + _("Animazione"), # 0x28 + _("Giallo"), # 0x29 + _("Drammatico"), # 0x2a + _("Romantico"), # 0x2b + _("Miniserie"), # 0x2c + _("Spettacolo"), # 0x2d + _("Quiz"), # 0x2e + _("Talk Show"), # 0x2f + ), + # Intrattenimento cont.. + 3: ( + _("Varieta"), # 0x30 + _("Festival"), # 0x31 + _("Teatro"), # 0x32 + _("Gioco"), # 0x33 + ), + # Sport + 4: ( + _("Generale"), # 0x40 + _("Calcio"), # 0x41 + _("Tennis"), # 0x42 + _("Motori"), # 0x43 + _("Altri"), # 0x44 + _("Baseball"), # 0x45 + _("Ciclismo"), # 0x46 + _("Rugby"), # 0x47 + _("Basket"), # 0x48 + _("Boxe"), # 0x49 + _("Atletica"), # 0x4a + _("Football USA"), # 0x4b + _("Hockey"), # 0x4c + _("Sci"), # 0x4d + _("Equestri"), # 0x4e + _("Golf"), # 0x4f + ), + # Sport cont.. + 5: ( + _("Nuoto"), # 0x50 + _("Wrestling"), # 0x51 + ), + # Film + 6: ( + _("Generale"), # 0x60 + _("Drammatico"), # 0x61 + _("Commedia"), # 0x62 + _("Romantico"), # 0x63 + _("Azione"), # 0x64 + _("Fantascienza"), # 0x65 + _("Western"), # 0x66 + _("Comico"), # 0x67 + _("Fantastico"), # 0x68 + _("Avventura"), # 0x69 + _("Poliziesco"), # 0x6a + _("Guerra"), # 0x6b + _("Horror"), # 0x6c + _("Animazione"), # 0x6d + _("Thriller"), # 0x6e + _("Musicale"), # 0x6f + ), + # Film cont.. + 7: ( + _("Corto"), # 0x70 + _("Cortometraggio"), # 0x71 + ), + # Mondo e Tendenze + 8: ( + _("Generale"), # 0x80 + _("Natura"), # 0x81 + _("Arte e Cultura"), # 0x82 + _("Lifestyle"), # 0x83 + _("Viaggi"), # 0x84 + _("Documentario"), # 0x85 + _("Societa"), # 0x86 + _("Scienza"), # 0x87 + _("Storia"), # 0x88 + _("Sport"), # 0x89 + _("Pesca"), # 0x8a + _("Popoli"), # 0x8b + _("Cinema"), # 0x8c + _("Musica"), # 0x8d + _("Hobby"), # 0x8e + _("Caccia"), # 0x8f + ), + # Mondo e Tendenze cont.. + 9: ( + _("Reportage"), # 0x90 + _("Magazine"), # 0x91 + _("Magazine Cultura"), # 0x92 + _("Magazine Scienza"), # 0x93 + _("Politica"), # 0x94 + _("Magazine Cinema"), # 0x95 + _("Magazine Sport"), # 0x96 + _("Attualita"), # 0x97 + _("Moda"), # 0x98 + _("Economia"), # 0x99 + _("Magazine Caccia e Pesca"), # 0x9a + _("Magazine Viaggi"), # 0x9b + _("Magazine Natura"), # 0x9c + _("Magazine Musica"), # 0x9d + _("Religione"), # 0x9e + _("Televendita"), # 0x9f + ), + # Informazione + 10: ( + _("Generale"), # 0xa0 + _("Notiziario"), # 0xa1 + _("Sport"), # 0xa2 + _("Economia"), # 0xa3 + ), + # Ragazzi e Musica + 12: ( + _("Generale"), # 0xc0 + _("Bambini"), # 0xc1 + _("Ragazzi"), # 0xc2 + _("Cartoni Animati"), # 0xc3 + _("Musica"), # 0xc4 + _("Film Animazione"), # 0xc5 + _("Film"), # 0xc6 + _("Telefilm"), # 0xc7 + _("Magazine"), # 0xc8 + _("Inutilizzato 0xc9"), # 0xc9 + _("Inutilizzato 0xca"), # 0xca + _("Inutilizzato 0xcb"), # 0xcb + _("Inutilizzato 0xcc"), # 0xcc + _("Inutilizzato 0xcd"), # 0xcd + _("Inutilizzato 0xce"), # 0xce + _("Inutilizzato 0xcf"), # 0xcf + ), + # Ragazzi e Musica cont.. + 13: ( + _("Inutilizzato 0xd0"), # 0xd0 + _("Inutilizzato 0xd1"), # 0xd1 + _("Inutilizzato 0xd2"), # 0xd2 + _("Inutilizzato 0xd3"), # 0xd3 + _("Danza"), # 0xd4 + ), + # Altri Programmi + 14: ( + _("Generale"), # 0xe0 + _("Educational"), # 0xe1 + _("Regionale"), # 0xe2 + _("Shopping"), # 0xe3 + _("Inutilizzato 0xe4"), # 0xe4 + _("Inizio e Fine Trasmissioni"), # 0xe5 + _("Eventi Speciali"), # 0xe6 + _("Film per Adulti"), # 0xe7 + ), + } + + +class GenresAUSOpenTV: + # TODO: "OT3": "AUS" + maintype = ( + _("General"), # 0x0 + ) + + subtype = { + 0: ( + _("No Category"), # 0x00 + ), + } + + +class GenresNZLOpenTV: + # TODO: "OT4": "NZL" + maintype = ( + _("General"), # 0x0 + ) + + subtype = { + 0: ( + _("No Category"), # 0x00 + ), + } + + +class GenresETSIOpenTV: + # TODO: "OTV": "ETSI + maintype = ( + _("General"), # 0x0 + ) + + subtype = { + 0: ( + _("No Category"), # 0x00 + ), + } + + def __getGenreStringMain(hn, ln, genres): # if hn == 0: # return _("Undefined content") @@ -752,11 +1169,30 @@ def __getGenreStringSubIceTV(hn, ln, genres): return "" +def __getGenreStringMainOpenTV(hn, ln, genres): + if hn < len(genres.maintype): + return genres.maintype[hn] + return "" + + +def __getGenreStringSubOpenTV(hn, ln, genres): + if hn in genres.subtype: + if ln < len(genres.subtype[hn]): + return genres.subtype[hn][ln] + return _("User defined 0x%02x" % ((hn << 4) | ln)) + return "" + + countries = { "AUS": (__getGenreStringMain, __getGenreStringMain, GenresAUS()), # Use illegal country names for IceTV genre tables so that they won't match real countries "AUSIceTV": (__getGenreStringMainIceTV, __getGenreStringSubIceTV, GenresAUSIceTV()), "DEUIceTV": (__getGenreStringMainIceTV, __getGenreStringSubIceTV, GenresDEUIceTV()), + "GBROpenTV": (__getGenreStringMainOpenTV, __getGenreStringSubOpenTV, GenresGBROpenTV()), + "ITAOpenTV": (__getGenreStringMainOpenTV, __getGenreStringSubOpenTV, GenresITAOpenTV()), + "AUSOpenTV": (__getGenreStringMainOpenTV, __getGenreStringSubOpenTV, GenresAUSOpenTV()), + "NZLOpenTV": (__getGenreStringMainOpenTV, __getGenreStringSubOpenTV, GenresNZLOpenTV()), + "ETSIOpenTV": (__getGenreStringMainOpenTV, __getGenreStringSubOpenTV, GenresETSIOpenTV()) } defaultGenre = GenresETSI() @@ -791,7 +1227,7 @@ def getGenreStringSub(hn, ln, country=None): def getGenreStringLong(hn, ln, country=None): # if hn == 0: # return _("Undefined content") + " " + str(ln) - if hn == 15 and not (hasattr(config.plugins, "icetv") and config.plugins.icetv.enable_epg.value): + if hn == 15 and "OpenTV" not in country and not (hasattr(config.plugins, "icetv") and config.plugins.icetv.enable_epg.value): return _("User defined") + " " + str(ln) main = getGenreStringMain(hn, ln, country=country) sub = getGenreStringSub(hn, ln, country=country) diff --git a/lib/python/Components/UsageConfig.py b/lib/python/Components/UsageConfig.py index ad79d90fc99..6b64f27a940 100644 --- a/lib/python/Components/UsageConfig.py +++ b/lib/python/Components/UsageConfig.py @@ -825,7 +825,7 @@ def EpgCacheChanged(configElement): config.misc.epgcachepath.addNotifier(EpgCacheChanged, immediate_feedback=False) config.misc.epgcachefilename.addNotifier(EpgCacheChanged, immediate_feedback=False) - config.misc.epgratingcountry = ConfigSelection(default="", choices=[("", _("Auto Detect")), ("ETSI", _("Generic")), ("AUS", _("Australia"))]) + config.misc.epgratingcountry = ConfigSelection(default="", choices=[("", _("Auto Detect")), ("ETSI", _("Generic")), ("AUS", _("Australia")), ("GBR", _("Great Britain")), ("ITA", _("Italy"))]) config.misc.epggenrecountry = ConfigSelection(default="", choices=[("", _("Auto Detect")), ("ETSI", _("Generic")), ("AUS", _("Australia"))]) config.misc.showradiopic = ConfigYesNo(default=True) From 6d4513f1d77f4e1cfe8d7e056b73fb70490114d6 Mon Sep 17 00:00:00 2001 From: TwolDE2 Date: Tue, 12 Mar 2024 15:03:11 +0100 Subject: [PATCH 183/183] [InputDeviceSetup] - reinstate non BoxBranding call --- lib/python/Screens/InputDeviceSetup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/python/Screens/InputDeviceSetup.py b/lib/python/Screens/InputDeviceSetup.py index d662e40a9da..61502e02f30 100644 --- a/lib/python/Screens/InputDeviceSetup.py +++ b/lib/python/Screens/InputDeviceSetup.py @@ -315,7 +315,7 @@ def __init__(self, session): def getDefaultRcType(self): boxtype = SystemInfo["model"] - procBoxtype = iRcTypeControl.SystemInfo["boxtype"] + procBoxtype = iRcTypeControl.getBoxType() print("[InputDevice] procBoxtype = %s, self.boxType = %s" % (procBoxtype, boxtype)) for x in self.defaultRcList: if x[0] in boxtype or x[0] in procBoxtype: