Compare commits

...

17 Commits

Author SHA1 Message Date
DYefremov
25fba17b9c version update -> 3.11.3 2024-11-28 22:45:38 +03:00
DYefremov
f77a55eadd fix assign ref data (#209) 2024-11-28 22:37:32 +03:00
DYefremov
b6e73e5e7a pos sort for picons downloader 2024-11-26 21:08:09 +03:00
DYefremov
780bda1f12 data read adjustment 2024-11-26 20:37:20 +03:00
DYefremov
a4a44692e2 fix warn 2024-11-26 20:18:46 +03:00
DYefremov
6db03b6cac version update -> 3.11.2 2024-11-10 00:00:03 +03:00
DYefremov
a94c53a9c9 fix extra service name for bouquet 2024-11-09 23:36:06 +03:00
DYefremov
b012fccd1a minor code cleanup 2024-11-03 14:53:24 +03:00
DYefremov
4062d206b8 minor code adjustment 2024-11-03 13:50:22 +03:00
DYefremov
a1f656fbca add additional reload data cmds 2024-11-01 14:40:05 +03:00
DYefremov
84afaee1d0 add encoding blacklist for *.m3u import 2024-10-29 22:25:43 +03:00
DYefremov
08619dd182 refactoring of getting service reference
* fix wrong duplicated services filtering #208
2024-10-26 13:13:55 +03:00
DYefremov
04f27eff88 hide error status on new data open 2024-10-26 10:15:15 +03:00
DYefremov
6e706dec2d README update 2024-10-25 20:52:34 +03:00
DYefremov
3bf787b9fb version update -> 3.11.1 2024-10-03 20:49:36 +03:00
audi06_19
3b1bb80d3c Turkish translation update (#207) 2024-09-30 07:44:12 +03:00
DYefremov
05fa5eaf11 kos web source correction 2024-09-28 16:49:24 +03:00
20 changed files with 152 additions and 95 deletions

View File

@@ -77,9 +77,11 @@ A ready-made [package](https://aur.archlinux.org/packages/demoneditor-bin) is al
**This program can be run on macOS.**
To run the program on macOS, you need to install [Homebrew](https://brew.sh/).
Then install the required components via terminal:
```brew install python3 gtk+3 pygobject3 adwaita-icon-theme python-requests gtksourceview3```
```brew install python3 gtk+3 pygobject3 adwaita-icon-theme gtksourceview3```
*Optional:* ```brew install pillow python-chardet```
```pip3 install requests telnetlib-313-and-up --break-system-packages```
*Optional:* ```brew install pillow python-chardet ffmpeg```
Launch is similar to Linux.

View File

@@ -529,8 +529,12 @@ def upload_data(*, settings, download_type=DownloadType.ALL, callback=log, done_
ht.send((f"{url}servicelistreload?mode=2", "Reloading Userbouquets."))
elif download_type is DownloadType.ALL or download_type is DownloadType.SERVICES:
ht.send((f"{url}servicelistreload?mode=0", "Reloading lamedb and Userbouquets."))
time.sleep(1)
ht.send((f"{url}servicelistreload?mode=4", "Updating parental control."))
if not settings.keep_power_mode:
ht.send((f"{url}powerstate?newstate=4", "Wakeup from Standby."))
elif download_type is DownloadType.SATELLITES:
ht.send((f"{url}servicelistreload?mode=3", "Reloading transponders."))
else:
ht.send((f"{url}reloadchannels", "Reloading channels..."))

View File

@@ -29,7 +29,7 @@ from app.commons import run_task
from app.settings import SettingsType
from .ecommons import Service, Satellite, Transponder, Bouquet, Bouquets, is_transponder_valid
from .enigma.blacklist import get_blacklist, write_blacklist
from .enigma.bouquets import to_bouquet_id, BouquetsWriter, BouquetsReader
from .enigma.bouquets import BouquetsWriter, BouquetsReader
from .enigma.lamedb import get_services as get_enigma_services, write_services as write_enigma_services
from .iptv import parse_m3u
from .neutrino.bouquets import get_bouquets as get_neutrino_bouquets, write_bouquets as write_neutrino_bouquets

View File

@@ -138,11 +138,10 @@ class BouquetsWriter:
bouquet.append(self._ALT.format(f_name))
self.write_bouquet(f"{p.parent}/{f_name}", srv.service, services)
else:
data = to_bouquet_id(srv)
if srv.service:
bouquet.append(f"#SERVICE {data}:{srv.service}\n#DESCRIPTION {srv.service}\n")
bouquet.append(f"#SERVICE {srv.fav_id}:{srv.service}\n#DESCRIPTION {srv.service}\n")
else:
bouquet.append(f"#SERVICE {data}\n")
bouquet.append(f"#SERVICE {srv.fav_id}\n")
with open(path, "w", encoding="utf-8", newline="\n") as file:
file.writelines(bouquet)
@@ -300,23 +299,15 @@ class BouquetsReader:
desc = desc.lstrip(":").strip() if desc else srv_data[-1].strip()
services.append(BouquetService(desc, BqServiceType.IPTV, srv, num))
else:
fav_id = f"{srv_data[3]}:{srv_data[4]}:{srv_data[5]}:{srv_data[6]}"
fav_id = srv.strip().upper()
name = None
if data_len == 12:
fav_id = f":".join(srv_data[:11])
name, sep, desc = str(srv_data[-1]).partition("\n#DESCRIPTION")
services.append(BouquetService(name, BqServiceType.DEFAULT, fav_id.upper(), num))
services.append(BouquetService(name, BqServiceType.DEFAULT, fav_id, num))
return bq_name.lstrip("#NAME").strip(), services
def to_bouquet_id(srv):
""" Creates bouquet channel id. """
data_type = srv.data_id
if data_type and len(data_type) > 4:
data_type = int(srv.data_id.split(":")[4])
return "{}:0:{:X}:{}:0:0:0:".format(1, data_type, srv.fav_id)
if __name__ == "__main__":
pass

View File

@@ -171,15 +171,16 @@ class LameDbReader:
ssid = str(data[0]).lstrip(sp).upper()
onid = str(data[1]).lstrip(sp).upper()
# For comparison in bouquets. Needed in upper case!!!
fav_id = f"{ssid}:{tid}:{nid}:{onid}"
fav_id = f"1:0:{srv_type:X}:{ssid}:{tid}:{nid}:{onid}:0:0:0:"
if len(data) > 9:
fav_id = f"{fav_id}:0:0:0:0"
picon_id = f"1_0_{srv_type:X}_{ssid}_{tid}_{nid}_{onid}_0_0_0.png"
s_id = f"1:0:{srv_type:X}:{ssid}:{tid}:{nid}:{onid}:0:0:0:"
all_flags = srv[2].split(",")
coded = CODED_ICON if list(filter(lambda x: x.startswith("C:"), all_flags)) else None
flags = list(filter(lambda x: x.startswith("f:"), all_flags))
hide = HIDE_ICON if flags and Flag.is_hide(Flag.parse(flags[0])) else None
locked = LOCKED_ICON if s_id in blacklist else None
locked = LOCKED_ICON if fav_id in blacklist else None
package = list(filter(lambda x: x.startswith("p:"), all_flags))
package = package[0][2:] if package else ""

View File

@@ -42,6 +42,7 @@ ENIGMA2_FAV_ID_FORMAT = " {}:{}:{:X}:{:X}:{:X}:{:X}:{:X}:0:0:0:{}:{}\n#DESCRIPTI
MARKER_FORMAT = " 1:64:{}:0:0:0:0:0:0:0::{}\n#DESCRIPTION {}\n"
PICON_FORMAT = "{}_{}_{:X}_{:X}_{:X}_{:X}_{:X}_0_0_0.png"
ENCODING_BLACKLIST = {"MacRoman"}
class StreamType(Enum):
DVB_TS = "1"
@@ -73,6 +74,7 @@ def parse_m3u(path, s_type, detect_encoding=True, params=None):
else:
enc = chardet.detect(data)
encoding = enc.get("encoding", "utf-8")
encoding = "utf-8" if encoding in ENCODING_BLACKLIST else encoding
aggr = [None] * 10
s_aggr = aggr[: -3]

View File

@@ -354,9 +354,9 @@ class PiconsParser(HTMLParser):
class ProviderParser(HTMLParser):
""" Parser for satellite html page. (https://www.lyngsat.com/*sat-name*.html) """
_POSITION_PATTERN = re.compile("at\s\d+\..*(?:E|W)']")
_ONID_TID_PATTERN = re.compile("^\d+-\d+.*")
_TRANSPONDER_FREQUENCY_PATTERN = re.compile("^\d+ [HVLR]+")
_POSITION_PATTERN = re.compile(r"at\s\d+\..*(?:E|W)']")
_ONID_TID_PATTERN = re.compile(r"^\d+-\d+.*")
_TRANSPONDER_FREQUENCY_PATTERN = re.compile(r"^\d+ [HVLR]+")
_DOMAINS = {"/tvchannels/", "/radiochannels/", "/packages/", "/logo/"}
_BASE_URL = "https://www.lyngsat.com"

View File

@@ -443,10 +443,8 @@ class ServicesParser(HTMLParser):
self._POS_PAT = re.compile(r".*?(\d+\.\d°[EW]).*")
# LyngSat.
self._TR_PAT = re.compile((r".*?(\d{4,5})\.?\d?\s+([RLHV]).*(DVB-S[2]?)/?(.*PSK)?\s"
r"?(T2-MI)?\s?(PLS\s+Multistream)?\s?"
r"SR-FEC:\s(\d+)-(\d+/\d+)\s+?(?:.*ONID-TID:\s+(\d+)-(\d+))?"))
self._TR_PAT = re.compile(r".*?(\d{4,5})\.?\d?\s+([RLHV]).*(DVB-S2?X?)/?(.*PSK)?.*SR-FEC:\s(\d+)-(\d+/\d+).*")
self._ID_PAT = re.compile(r"C/N lock:.*?(?:.*ONID-TID:\s+(\d+)-(\d+))?.*")
self._MULTI_PAT = re.compile(r"PLS\s+(Root|Gold|Combo)+\s(\d+)?\s+(?:Stream\s(\d+))")
# KingOfSat.
self._KING_TR_PAT = re.compile((r"(DVB-S[2]?)\s?(?:T2-MI,\s+PLP\s+(\d+))?.*"
@@ -616,13 +614,12 @@ class ServicesParser(HTMLParser):
services = []
pos, freq, sr, fec, pol, nsp, tid, nid = sat_position or 0, 0, 0, 0, 0, 0, 0, 0
sys = "DVB-S"
pos_found = False
tr = None
pos_found, tr, td, t_id = False, None, None, None
# Multi-stream.
multi_tr = None
multi = False
# Transponder.
for r in filter(lambda x: x and 6 < len(x) < 9, self._rows):
for r in self._rows:
if not pos_found:
pos_tr = re.match(self._POS_PAT, r[0].text)
if not pos_tr:
@@ -632,28 +629,23 @@ class ServicesParser(HTMLParser):
pos = self.get_position(pos_tr.group(1))
pos_found = True
if pos_found:
text = " ".join(c.text for c in r[1:])
td = re.match(self._TR_PAT, text)
if pos_found and not td:
td = re.match(self._TR_PAT, " ".join(c.text for c in r))
if td:
freq, pol = int(td.group(1)), get_key_by_value(POLARIZATION, td.group(2))
sys, mod, sr, _fec, = td.group(3), td.group(4), td.group(7), td.group(8)
sys, mod, fec, nsp, s2_flags, roll_off, pilot, inv = self.get_transponder_data(pos, _fec, sys, mod)
if td and not t_id:
t_id = re.match(self._ID_PAT, " ".join(c.text for c in r))
if t_id:
# The ONID-TID values may not present!
_nid, _tid = td.group(9), td.group(10)
_nid, _tid = t_id.group(1), t_id.group(2)
if _nid and _tid:
nid, tid = int(_nid), int(_tid)
else:
log((f"Values 'ONID-TID' for transponder [{self._t_url}] are not present."
" Default values are used."))
if td.group(5):
log(f"Detected T2-MI transponder! [{freq} {sr} {pol}]")
if td.group(6):
log(f"Detected multi-stream transponder! [{freq} {sr} {pol}]")
multi = True
freq, pol = int(td.group(1)), get_key_by_value(POLARIZATION, td.group(2))
sys, mod, sr, _fec = td.group(3), td.group(4), td.group(5), td.group(6)
sys, mod, fec, nsp, s2_flags, roll_off, pilot, inv = self.get_transponder_data(pos, _fec, sys, mod)
tr = self._TR.format(freq, sr, pol, fec, pos, inv, sys, s2_flags)
@@ -775,7 +767,7 @@ class ServicesParser(HTMLParser):
def get_service_data(s_type, pkg, sid, tid, nid, namespace, v_pid, a_pid, cas, use_pids=False):
sid = int(sid)
data_id = f"{sid:04x}:{namespace}:{tid:04x}:{nid:04x}:{s_type}:0:0"
fav_id = f"{sid}:{tid}:{nid}:{namespace}"
fav_id = f"1:0:{int(s_type):X}:{sid}:{tid}:{nid}:{namespace}:0:0:0:"
picon_id = f"1_0_{int(s_type):X}_{sid}_{tid}_{nid}_{namespace}_0_0_0.png"
# Flags.
flags = f"p:{pkg}"

View File

@@ -40,7 +40,7 @@ Author: Dmitriy Yefremov
<property name="icon_name">system-help</property>
<property name="type_hint">normal</property>
<property name="program_name">DemonEditor</property>
<property name="version">3.11.0 Beta</property>
<property name="version">3.11.3 Beta</property>
<property name="copyright">2018-2024 Dmitriy Yefremov
</property>
<property name="comments" translatable="yes">Enigma2 channel and satellite list editor.</property>

View File

@@ -110,16 +110,20 @@ class EpgCache(abc.ABC):
self._canceled = True
@abc.abstractmethod
def reset(self) -> None: pass
def reset(self) -> None:
pass
@abc.abstractmethod
def update_epg_data(self) -> bool: pass
def update_epg_data(self) -> bool:
pass
@abc.abstractmethod
def get_current_event(self, service_name) -> EpgEvent: pass
def get_current_event(self, service_name) -> EpgEvent:
pass
@abc.abstractmethod
def get_current_events(self, service_name) -> list: pass
def get_current_events(self, service_name) -> list:
pass
@staticmethod
def get_gz_file_name(url, path):
@@ -1209,7 +1213,7 @@ class EpgDialog:
fav_id = row[Column.FAV_ID]
fav_id_data = fav_id.split(":")
fav_id_data[3:7] = data[-3].split(":")
fav_id_data[3:7] = data[-3].split(":")[3:7]
if data[-2]:
row[Column.FAV_POS] = data[-2]

View File

@@ -1746,7 +1746,7 @@ Author: Dmitriy Yefremov
<object class="GtkLabel" id="app_ver_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label">3.11.0 Beta</property>
<property name="label">3.11.3 Beta</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>

View File

@@ -79,7 +79,7 @@ from .xml.edit import SatellitesTool
class Application(Gtk.Application):
""" Main application class. """
VERSION = "3.11.0"
VERSION = "3.11.3"
SERVICE_MODEL = "services_list_store"
FAV_MODEL = "fav_list_store"
@@ -2323,6 +2323,7 @@ class Application(Gtk.Application):
def update_data(self, data_path, callback=None):
self._services_load_spinner.start()
self.on_info_bar_close()
self._profile_combo_box.set_sensitive(False)
self._alt_revealer.set_visible(False)
self._filter_services_button.set_active(False)
@@ -2365,14 +2366,17 @@ class Application(Gtk.Application):
except FileNotFoundError as e:
msg = translate("Please, download files from receiver or setup your path for read data!")
self.show_error_message(getattr(e, "message", str(e)) + "\n\n" + msg)
self._services_load_spinner.stop()
return
except SyntaxError as e:
self.show_error_message(str(e))
self._services_load_spinner.stop()
return
except Exception as e:
msg = "Reading data error: {}"
log(msg.format(e), debug=self._settings.debug_mode, fmt_message=msg)
self.show_error_message("{}\n{}".format(translate("Reading data error!"), e))
self._services_load_spinner.stop()
return
else:
self.append_blacklist(black_list)

View File

@@ -49,7 +49,7 @@ from gi.repository import GdkPixbuf, GLib, Gio
from app.eparser import Service
from app.eparser.ecommons import Flag, BouquetService, Bouquet, BqType
from app.eparser.enigma.bouquets import BqServiceType, to_bouquet_id
from app.eparser.enigma.bouquets import BqServiceType
from app.settings import SettingsType, SEP, IS_WIN, IS_DARWIN, IS_LINUX
from .dialogs import show_dialog, DialogType, translate
from .uicommons import ViewTarget, BqGenType, Gtk, Gdk, HIDE_ICON, LOCKED_ICON, KeyboardKey, Column
@@ -294,7 +294,7 @@ def set_lock(blacklist, services, model, paths, target, services_model):
fav_id = model.get_value(itr, Column.SRV_FAV_ID if target is ViewTarget.SERVICES else Column.FAV_ID)
srv = services.get(fav_id, None)
if srv and srv.service_type not in skip_type:
bq_id = srv.data_id if srv.service_type == BqServiceType.IPTV.name else to_bouquet_id(srv)
bq_id = srv.data_id if srv.service_type == BqServiceType.IPTV.name else srv.fav_id
if not bq_id:
continue
blacklist.discard(bq_id) if locked else blacklist.add(bq_id)
@@ -819,7 +819,10 @@ def get_pos_num(pos):
if len(pos) > 1:
m = -1 if pos[-1] == "W" else 1
return float(pos[:-1]) * m
try:
return float(pos[:-1]) * m
except ValueError:
return -183
return -181.0 if pos == "T" else -182.0

View File

@@ -44,7 +44,7 @@ from app.tools.picons import (PiconsParser, parse_providers, Provider, convert_t
from app.tools.satellites import SatellitesParser, SatelliteSource
from .dialogs import show_dialog, DialogType, translate, get_builder, get_chooser_dialog
from .main_helper import (scroll_to, on_popup_menu, get_base_model, set_picon, get_picon_pixbuf, get_picon_dialog,
get_picon_file_name, get_pixbuf_from_data, get_pixbuf_at_scale)
get_picon_file_name, get_pixbuf_from_data, get_pixbuf_at_scale, get_pos_num)
from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, TV_ICON, Column, KeyboardKey, Page, ViewTarget
@@ -680,7 +680,7 @@ class PiconManager(Gtk.Box):
model.clear()
try:
for sat in sorted(sats):
for sat in sorted(sats, key=lambda s: get_pos_num(s[1]), reverse=True):
pos = sat[1]
name = f"{sat[0]} ({pos})"
if is_filter and pos not in self._sat_positions:
@@ -825,9 +825,10 @@ class PiconManager(Gtk.Box):
services = self._app.current_services
ids = set()
for s in (services.get(fav_id) for fav_id in fav_bouquet):
ids.add(s.picon_id)
ids.add(get_picon_file_name(s.service))
for s in (services.get(fav_id, None) for fav_id in fav_bouquet):
if s:
ids.add(s.picon_id)
ids.add(get_picon_file_name(s.service))
return ids
def process_provider(self, prv, picons_path):

View File

@@ -2,7 +2,7 @@
#
# The MIT License (MIT)
#
# Copyright (c) 2018-2023 Dmitriy Yefremov
# Copyright (c) 2018-2024 Dmitriy Yefremov
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -47,7 +47,7 @@ _UI_PATH = UI_RESOURCES_PATH + "service_details_dialog.glade"
class ServiceDetailsDialog:
_ENIGMA2_DATA_ID = "{:04x}:{:08x}:{:04x}:{:04x}:{}:{}"
_ENIGMA2_FAV_ID = "{:X}:{:X}:{:X}:{:X}"
_ENIGMA2_FAV_ID = "1:0:{:X}:{:X}:{:X}:{:X}:{:X}:0:0:0"
_ENIGMA2_TRANSPONDER_DATA = "{} {}:{}:{}:{}:{}:{}:{}"
@@ -303,6 +303,7 @@ class ServiceDetailsDialog:
data = srv.data_id.split(":")
tr_data = srv.transponder.split(":")
tr_type = TrType(srv.transponder_type)
data_len = len(tr_data)
self._namespace_entry.set_text(str(int(data[1], 16)))
self._transponder_id_entry.set_text(str(int(data[2], 16)))
@@ -311,11 +312,12 @@ class ServiceDetailsDialog:
if tr_type is TrType.Satellite:
self.select_active_text(self._invertion_combo_box, Inversion(tr_data[5]).name)
if srv.system == "DVB-S2":
self.select_active_text(self._mod_combo_box, MODULATION.get(tr_data[8]))
self.select_active_text(self._rolloff_combo_box, ROLL_OFF.get(tr_data[9]))
self.select_active_text(self._pilot_combo_box, Pilot(tr_data[10]).name)
self._tr_flag_entry.set_text(tr_data[7])
if len(tr_data) > 12:
if data_len > 9:
self.select_active_text(self._mod_combo_box, MODULATION.get(tr_data[8]))
self.select_active_text(self._rolloff_combo_box, ROLL_OFF.get(tr_data[9]))
self.select_active_text(self._pilot_combo_box, Pilot(tr_data[10]).name)
self._tr_flag_entry.set_text(tr_data[7])
if data_len > 12:
self._stream_id_entry.set_text(tr_data[11])
self._pls_code_entry.set_text(tr_data[12])
self.select_active_text(self._pls_mode_combo_box, PLS_MODE.get(tr_data[13]))
@@ -593,7 +595,7 @@ class ServiceDetailsDialog:
if self._s_type is SettingsType.ENIGMA_2:
namespace = int(self._namespace_entry.get_text())
data_id = self._ENIGMA2_DATA_ID.format(ssid, namespace, tr_id, net_id, service_type, 0)
fav_id = self._ENIGMA2_FAV_ID.format(ssid, tr_id, net_id, namespace)
fav_id = f"{self._reference_label.get_text()}:"
return fav_id, data_id
elif self._s_type is SettingsType.NEUTRINO_MP:
data = get_attributes(self._old_service.data_id)
@@ -615,7 +617,7 @@ class ServiceDetailsDialog:
freq = self._freq_entry.get_text()
rate = self._rate_entry.get_text()
pol = self._pol_combo_box.get_active_id()
pos = "{}{}".format(round(self._sat_pos_button.get_value(), 1), self._pos_side_box.get_active_id())
pos = f"{round(self._sat_pos_button.get_value(), 1)}{self._pos_side_box.get_active_id()}"
return freq, rate, pol, fec, system, pos
elif self._tr_type in (TrType.Terrestrial, TrType.ATSC):
return freq, o_srv.rate, o_srv.pol, fec, system, o_srv.pos
@@ -624,8 +626,8 @@ class ServiceDetailsDialog:
def get_satellite_transponder_data(self):
sys = self._sys_combo_box.get_active_id()
freq = "{}000".format(self._freq_entry.get_text())
rate = "{}000".format(self._rate_entry.get_text())
freq = f"{self._freq_entry.get_text()}000"
rate = f"{self._rate_entry.get_text()}000"
pol = self.get_value_from_combobox_id(self._pol_combo_box, POLARIZATION)
fec = self.get_value_from_combobox_id(self._fec_combo_box, FEC_DEFAULT)
sat_pos = self.get_sat_position()
@@ -645,9 +647,10 @@ class ServiceDetailsDialog:
pls_mode = self.get_value_from_combobox_id(self._pls_mode_combo_box, PLS_MODE)
pls_code = self._pls_code_entry.get_text()
st_id = self._stream_id_entry.get_text()
pls = ":{}:{}:{}".format(st_id, pls_code, pls_mode) if pls_mode and pls_code and st_id else ""
pls = f":{st_id}:{pls_code}:{pls_mode}" if pls_mode and pls_code and st_id else ""
return f"{dvb_s_tr}:{flag}:{mod}:{roll_off}:{pilot}{pls}"
return "{}:{}:{}:{}:{}{}".format(dvb_s_tr, flag, mod, roll_off, pilot, pls)
elif self._s_type is SettingsType.NEUTRINO_MP:
tr_data = get_attributes(self._old_service.transponder)
tr_data["frq"] = freq
@@ -658,7 +661,7 @@ class ServiceDetailsDialog:
tr_data["id"] = "{:04x}".format(int(self._transponder_id_entry.get_text()))
tr_data["inv"] = inv
return SP.join("{}{}{}".format(k, KSP, v) for k, v in tr_data.items())
return SP.join(f"{k}{KSP}{v}" for k, v in tr_data.items())
def get_sat_position(self):
sat_pos = self._sat_pos_button.get_value() * (-1 if self._pos_side_box.get_active_id() == "W" else 1)
@@ -666,11 +669,11 @@ class ServiceDetailsDialog:
return sat_pos
def get_terrestrial_transponder_data(self):
tr_data = re.split("\s|:", self._old_service.transponder)
tr_data = re.split(r"\s|:", self._old_service.transponder)
# frequency, bandwidth, code rate HP, code rate LP, modulation, transmission mode, guard interval, hierarchy,
# inversion, system, plp_id
# Bandwidth -> Pol, Rate HP -> FEC, TransmissionMode -> Roll off, GuardInterval -> Pilot, Hierarchy -> Pls Mode
tr_data[1] = "{}000".format(self._freq_entry.get_text())
tr_data[1] = f"{self._freq_entry.get_text()}000"
tr_data[2] = self.get_value_from_combobox_id(self._pol_combo_box, BANDWIDTH)
tr_data[3] = self.get_value_from_combobox_id(self._fec_combo_box, T_FEC)
tr_data[4] = self.get_value_from_combobox_id(self._rate_lp_combo_box, T_FEC)
@@ -681,28 +684,28 @@ class ServiceDetailsDialog:
tr_data[9] = get_value_by_name(Inversion, self._invertion_combo_box.get_active_id())
tr_data[10] = self.get_value_from_combobox_id(self._sys_combo_box, T_SYSTEM)
return "{} {}".format(tr_data[0], ":".join(tr_data[1:]))
return f"{tr_data[0]} {':'.join(tr_data[1:])}"
def get_cable_transponder_data(self):
tr_data = re.split("\s|:", self._old_service.transponder)
tr_data = re.split(r"\s|:", self._old_service.transponder)
# frequency, symbol_rate, modulation, inversion, fec_inner, system;
tr_data[1] = "{}000".format(self._freq_entry.get_text())
tr_data[2] = "{}000".format(self._rate_entry.get_text())
tr_data[1] = f"{self._freq_entry.get_text()}000"
tr_data[2] = f"{self._rate_entry.get_text()}000"
tr_data[3] = get_value_by_name(Inversion, self._invertion_combo_box.get_active_id())
tr_data[4] = self.get_value_from_combobox_id(self._mod_combo_box, C_MODULATION)
tr_data[5] = self.get_value_from_combobox_id(self._fec_combo_box, FEC_DEFAULT)
tr_data[6] = get_value_by_name(SystemCable, self._sys_combo_box.get_active_id())
return "{} {}".format(tr_data[0], ":".join(tr_data[1:]))
return f"{tr_data[0]} {':'.join(tr_data[1:])}"
def get_atsc_transponder_data(self):
tr_data = re.split("\s|:", self._old_service.transponder)
tr_data = re.split(r"\s|:", self._old_service.transponder)
# frequency, inversion, modulation, system
tr_data[1] = "{}000".format(self._freq_entry.get_text())
tr_data[1] = f"{self._freq_entry.get_text()}000"
tr_data[2] = get_value_by_name(Inversion, self._invertion_combo_box.get_active_id())
tr_data[3] = self.get_value_from_combobox_id(self._mod_combo_box, A_MODULATION)
return "{} {}".format(tr_data[0], ":".join(tr_data[1:]))
return f"{tr_data[0]} {':'.join(tr_data[1:])}"
def update_transponder_services(self, transponder, sat_pos):
for itr in self._transponder_services_iters:
@@ -714,13 +717,13 @@ class ServiceDetailsDialog:
fav_id = srv[Column.SRV_FAV_ID]
old_srv = self._services.pop(fav_id, None)
if not old_srv:
log("Update transponder services error: No service found for ID {}".format(srv[Column.SRV_FAV_ID]))
log(f"Update transponder services error: No service found for ID {srv[Column.SRV_FAV_ID]}")
continue
if self._s_type is SettingsType.NEUTRINO_MP:
flags = get_attributes(srv[Column.SRV_CAS_FLAGS])
flags["position"] = sat_pos
srv[Column.SRV_CAS_FLAGS] = SP.join("{}{}{}".format(k, KSP, v) for k, v in flags.items())
srv[Column.SRV_CAS_FLAGS] = SP.join(f"{k}{KSP}{v}" for k, v in flags.items())
self._services[fav_id] = Service(*srv[:Column.SRV_TOOLTIP])
self._current_model.set_row(itr, srv)
@@ -794,10 +797,9 @@ class ServiceDetailsDialog:
nid = int(self._network_id_entry.get_text())
if self._s_type is SettingsType.ENIGMA_2:
on_id = int(self._namespace_entry.get_text())
ref = "1:0:{:X}:{:X}:{:X}:{:X}:{:X}:0:0:0".format(srv_type, ssid, tid, nid, on_id)
self._reference_label.set_text(ref)
self._reference_label.set_text(self._ENIGMA2_FAV_ID.format(srv_type, ssid, tid, nid, on_id))
else:
self._reference_label.set_text("{:x}{:04x}{:04x}".format(tid, nid, ssid))
self._reference_label.set_text(f"{tid:x}{nid:04x}{ssid:04x}")
def update_ui_for_terrestrial(self):
tr_grid = self.get_transponder_grid_for_non_satellite()

View File

@@ -1,5 +1,5 @@
#!/bin/bash
VER="3.11.0_Beta"
VER="3.11.3_Beta"
B_PATH="dist/DemonEditor"
DEB_PATH="$B_PATH/usr/share/demoneditor"

View File

@@ -1,5 +1,5 @@
Package: demon-editor
Version: 3.11.0-Beta
Version: 3.11.3-Beta
Section: utils
Priority: optional
Architecture: all

View File

@@ -81,7 +81,7 @@ app = BUNDLE(coll,
'CFBundleGetInfoString': "Enigma2 channel and satellite editor",
'LSApplicationCategoryType': 'public.app-category.utilities',
'LSMinimumSystemVersion': '10.13',
'CFBundleShortVersionString': f"3.11.0.{BUILD_DATE} Beta",
'CFBundleShortVersionString': f"3.11.3.{BUILD_DATE} Beta",
'NSHumanReadableCopyright': u"Copyright © 2024, Dmitriy Yefremov",
'NSRequiresAquaSystemAppearance': 'false',
'NSHighResolutionCapable': 'true'

View File

@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: DemonEditor\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-04-16 15:59+0300\n"
"PO-Revision-Date: 2023-10-08 13:43+0300\n"
"PO-Revision-Date: 2024-09-29 22:18+0300\n"
"Last-Translator: audi06_19 <info@dreamosat-forum.com>\n"
"Language-Team: audi06_19 <info@dreamosat-forum.com>\n"
"Language: tr\n"
@@ -11,7 +11,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.5\n"
msgid "translator-credits"
msgstr "audi06_19 <info@dreamosat-forum.com>"
@@ -1534,3 +1534,54 @@ msgstr "Piconlar için ortak klasörü kullan"
msgid "Activates single folder use for several profiles."
msgstr "Birden fazla profil için tek klasör kullanımını etkinleştirir."
msgid "Events"
msgstr "Olaylar"
msgid "Markers"
msgstr "İşaretleyiciler"
msgid "IPTV only"
msgstr "Yalnızca IPTV"
msgid "No"
msgstr "Hayır"
msgid "Not found."
msgstr "Bulunamadı."
msgid "Current EPG cache contents."
msgstr "Geçerli EPG önbellek içerikleri."
msgid "Source error!"
msgstr "Kaynak hatası!"
msgid "The EPG source for the favorites list is not set!"
msgstr "Favoriler listesi için EPG kaynağı ayarlanmamış!"
msgid "Add to EPG sources list"
msgstr "EPG kaynakları listesine ekle"
msgid "Current bouquet"
msgstr "Mevcut buket"
msgid "Single bouquet"
msgstr "Tek buket"
msgid "Split by groups"
msgstr "Gruplara göre böl"
msgid "Create sub-bouquets"
msgstr "Alt buketler oluştur"
msgid "Add image"
msgstr "Resim ekle"
msgid "TV Format"
msgstr "TV Formatı"
msgid "Use with Streamrelay"
msgstr "Streamrelay ile kullan"
msgid "Remove use with Streamrelay"
msgstr "Streamrelay ile kullanımı kaldır"