def get_live_data(name): PLog('get_live_data:') import resources.lib.EPG as EPG rec = EPG.EPG(ID='ARTE', mode='OnlyNow') # Daten holen PLog(len(rec)) if len(rec) == 0: msg1 = 'Sender %s:' % name msg2 = 'keine EPG-Daten gefunden' MyDialog(msg1, msg2, '') return li title = 'Arte' summ = '' descr = '' vonbis = '' img = '' href = '' if len(rec) > 0: # href (PRG-Seite) hier n.b. img = rec[2] sname = rec[3] stime = rec[4] summ = rec[5] vonbis = rec[6] sname = unescape(sname) title = sname summ = unescape(summ) PLog("title: " + title) summ = "[B]LAUFENDE SENDUNG [COLOR red](%s Uhr)[/COLOR][/B]\n\n%s" % ( vonbis, summ) title = sname try: # 'list' object in summ möglich - Urs. n.b. descr = summ.replace('\n', '||') # \n aus summ -> || except Exception as exception: PLog(str(exception)) descr = '' PLog(title) PLog(img) PLog(sname) PLog(stime) PLog(vonbis) zdf_streamlinks = ardundzdf.get_ZDFstreamlinks(skip_log=True) # Zeile zdf_streamlinks: "webtitle|href|thumb|tagline" for line in zdf_streamlinks: webtitle, href, thumb, tagline = line.split('|') # Bsp.: "ZDFneo " in "ZDFneo Livestream": if up_low('Arte ') in up_low(webtitle): # Arte mit Blank! href = href break if href == '': PLog('%s: Streamlink fehlt' % 'Arte ') if img == '': img = thumb # Fallback Senderlogo (+ in Main_arte) return title, summ, descr, vonbis, img, href
def date_human(myformat, now=''): PLog("date_human:") if now == '': now = EPG.get_unixtime(onlynow=True) now = int(now) s = datetime.datetime.fromtimestamp(now) date_human = s.strftime(myformat) return date_human
def iterprogrammes(self): epg = self.getepg() # delete cache first cachefile = os.path.join(util.DICTSTORE, "EPG_%s" % epg) if os.path.exists(cachefile): os.remove(cachefile) for start, _url, icon, prog1, _hour, desc, _fromto, _dt, end in EPG.EPG( epg): prog = re.sub("\[.*?\]", "", prog1).split("|")[-1].strip() start = datetime.utcfromtimestamp(int(start)).replace(tzinfo=UTC) end = datetime.utcfromtimestamp(int(end)).replace(tzinfo=UTC) yield programme(prog, start, end, icon=icon, desc=desc)
def test_jobs(): PLog("test_jobs:") # "Das Erste|https://mcdn.daserste.de/daserste/de/master.m3u8" - funkt. nicht mylist = [ "Das Erste|https://derste247livede.akamaized.net/hls/live/658317/daserste_de/profile1/1.m3u8", "BR Fernsehen-Nord|http://brlive-lh.akamaihd.net/i/bfsnord_germany@119898/master.m3u8", "hr-fernsehen|https://hrlive1-lh.akamaihd.net/i/hr_fernsehen@75910/master.m3u8", "MDR Sachsen|https://mdrsnhls-lh.akamaihd.net/i/livetvmdrsachsen_de@513998/master.m3u8", "Radio Bremen|https://rbfs-lh.akamaihd.net/i/rb_fs@438960/master.m3u8", "NDR Niedersachsen|https://ndrfs-lh.akamaihd.net/i/ndrfs_nds@430233/master.m3u8", "NDR Hamburg|https://ndrfs-lh.akamaihd.net/i/ndrfs_hh@430231/master.m3u8", "SR Fernsehen|https://srlive24-lh.akamaihd.net/i/sr_universal02@107595/master.m3u8", "Tagesschau24|http://tagesschau-lh.akamaihd.net/i/tagesschau_1@119231/master.m3u8", "Deutsche Welle|https://dwstream72-lh.akamaihd.net/i/dwstream72_live@123556/master.m3u8", "One|http://onelivestream-lh.akamaihd.net/i/one_livestream@568814/master.m3u8", ] add_sec = 10 now = EPG.get_unixtime(onlynow=True) now = int(now) end = now + 2 * add_sec now = now + add_sec job_list = [] i = 0 for item in mylist: i = i + 1 sender, url = item.split('|') PLog("job %s" % str(i)) end = now + 2 * add_sec now = now + add_sec title = "Testjob %s" % str(i) start_end = "%s|%s" % (str(now), str(end)) descr = u"Debug: Jobliste mit ausgewählten Jobs, Startzeit: jetzt + 10 Sec., Aufnahmezeit 10 Sec. (Endzeit: Startzeit + 10 Sec.)" status = "waiting" pid = '' block = '4Yp2C09aF1k5YC3d' JobID = ''.join(random.choice(block) for i in range(len(block))) # 16 stel. Job-ID job = JOBLINE_TEMPL % (start_end, title, descr, sender, url, status, pid, JobID) job_list.append(JOB_TEMPL % job) # job -> Marker jobs = "\n".join(job_list) page = JOBLIST_TEMPL % jobs # Jobliste -> Marker page = py2_encode(page) PLog(page[:80]) err_msg = RSave(JOBFILE, page) # Jobliste -> Livesystem return
def Kika_Live(): PLog('Kika_Live:') li = xbmcgui.ListItem() li = home(li, ID='Kinderprogramme') # Home-Button import resources.lib.EPG as EPG zdf_streamlinks = ardundzdf.get_ZDFstreamlinks() # Zeile zdf_streamlinks: "webtitle|href|thumb|tagline" for line in zdf_streamlinks: webtitle, href, thumb, tagline = line.split('|') # Bsp.: "ZDFneo " in "ZDFneo Livestream": if up_low('KiKA ') in up_low(webtitle): # Sender mit Blank! m3u8link = href break if m3u8link == '': PLog('%s: Streamlink fehlt' % 'KiKA ') ID = 'KIKA' title = 'KIKA TV-Live' Merk = '' rec = EPG.EPG(ID=ID, mode='OnlyNow') # Daten holen - nur aktuelle Sendung PLog(rec) # bei Bedarf if len(rec) == 0: # EPG-Satz leer? title = 'EPG nicht gefunden' summ = '' tagline = '' else: href=rec[1]; img=rec[2]; sname=rec[3]; stime=rec[4]; summ=rec[5]; vonbis=rec[6] if img.find('http') == -1: # Werbebilder today.de hier ohne http:// img = R('tv-kika.png') title = sname.replace('JETZT', ID) # JETZT durch Sender ersetzen # sctime = "[COLOR red] %s [/COLOR]" % stime # Darstellung verschlechtert # sname = sname.replace(stime, sctime) tagline = 'Zeit: ' + vonbis title = unescape(title); title = repl_json_chars(title) summ = unescape(summ); summ = repl_json_chars(summ) PLog("title: " + title); PLog(summ) title=py2_encode(title); m3u8link=py2_encode(m3u8link); img=py2_encode(img); summ=py2_encode(summ); fparams="&fparams={'path': '%s', 'title': '%s', 'thumb': '%s', 'descr': '%s', 'Merk': '%s'}" %\ (quote(m3u8link), quote(title), quote(img), quote_plus(summ), Merk) addDir(li=li, label=title, action="dirList", dirID="ardundzdf.SenderLiveResolution", fanart=R('tv-EPG-all.png'), thumb=img, fparams=fparams, summary=summ, tagline=tagline) xbmcplugin.endOfDirectory(HANDLE, cacheToDisc=True)
def JobStop(sender, job_title, start_end, job_active, pid, JobID): PLog("JobStop:") PLog(pid) PLog(JobID) PLog(job_active), PLog(start_end) if sender: # fehlt beim Recording msg1 = "%s: %s" % (sender, job_title) else: msg1 = job_title PLog("kill_pid: %s" % str(pid)) os.kill(int(pid), signal.SIGTERM) # auch Windows10 OK (aber Teilvideo beschäd.) icon = MSG_ICON xbmcgui.Dialog().notification("Jobliste:", u"Job wird gestoppt", icon, 3000) now = EPG.get_unixtime(onlynow=True) jobs = ReadJobs() # s. util newjob_list = [] # newjob_list: Liste nach Änderungen job_title = py2_encode(job_title) # type kann vom code-Format in jobs abweichen for job in jobs: my_JobID = stringextract('<JobID>', '</JobID>', job) if JobID in my_JobID: # sonst unverändert my_start_end = stringextract('<startend>', '</startend>', job) start, end = my_start_end.split('|') end = int(now) - 1 # end anpassen (Job abgelaufen) new_start_end = "%s|%d" % (start, end) job = job.replace( my_start_end, new_start_end) # job: <startend></startend> ändern PLog(my_start_end) PLog(new_start_end) newjob_list.append(JOB_TEMPL % job) # job -> Marker save_Joblist(jobs, newjob_list, "Jobliste:", "") # ohne notification return
def Kika_Live(): PLog('Kika_Live') li = xbmcgui.ListItem() li = home(li, ID='Kinderprogramme') # Home-Button import resources.lib.EPG as EPG m3u8link = 'https://kikade-lh.akamaihd.net/i/livetvkika_de@450035/master.m3u8' # neu 07.12.2017 ID = 'KIKA' title = 'KIKA TV-Live' Merk = '' rec = EPG.EPG(ID=ID, mode='OnlyNow') # Daten holen - nur aktuelle Sendung PLog(rec) # bei Bedarf if len(rec) == 0: # EPG-Satz leer? title = 'EPG nicht gefunden' summ = '' tagline = '' else: href=rec[1]; img=rec[2]; sname=rec[3]; stime=rec[4]; summ=rec[5]; vonbis=rec[6] if img.find('http') == -1: # Werbebilder today.de hier ohne http:// img = R('tv-kika.png') title = sname.replace('JETZT', ID) # JETZT durch Sender ersetzen # sctime = "[COLOR red] %s [/COLOR]" % stime # Darstellung verschlechtert # sname = sname.replace(stime, sctime) tagline = 'Zeit: ' + vonbis title = unescape(title); title = repl_json_chars(title) summ = unescape(summ); summ = repl_json_chars(summ) PLog("title: " + title); PLog(summ) title=py2_encode(title); m3u8link=py2_encode(m3u8link); img=py2_encode(img); summ=py2_encode(summ); fparams="&fparams={'path': '%s', 'title': '%s', 'thumb': '%s', 'descr': '%s', 'Merk': '%s'}" %\ (quote(m3u8link), quote(title), quote(img), quote_plus(summ), Merk) addDir(li=li, label=title, action="dirList", dirID="ardundzdf.SenderLiveResolution", fanart=R('tv-EPG-all.png'), thumb=img, fparams=fparams, summary=summ, tagline=tagline) xbmcplugin.endOfDirectory(HANDLE, cacheToDisc=True)
tcont = re.sub("ADDON_PATH[\s\t]*?=[\s\t]*?SETTINGS.getAddonInfo.+?\n", "ADDON_PATH = '%s'\n" % ardundzdf, tcont) tcont = re.sub( "USERDATA[\s\t]*?=[\s\t]*?xbmc.translatePath.+?\n", "USERDATA = '%s'\n" % os.path.join(addon.get_addondir("plugin.video.livestreams"), ""), tcont) tcont = re.sub("HANDLE[\s\t]*?=[\s\t]*?int.+?\n", "HANDLE = 1", tcont) with open(tfile, "w") as f: f.write(tcont) from resources.lib import util from resources.lib import EPG util.check_DataStores() e = EPG.EPG("ARD") class multi(): categories = ["Deutschland"] title = u"Das Erste" iconpath = os.path.join(ardundzdf, "resources", "images", "") usehlsproxy = False sender = "Das Erste" epg = None link = None def _link_epg(self): if not self.link or not self.epg: _, link, epg = util.get_playlist_img(self.sender) if not self.link:
def JobMonitor(): PLog("JobMonitor:") pre_rec = SETTINGS.getSetting( 'pref_pre_rec') # Vorlauf (Bsp. 00:15:00 = 15 Minuten) post_rec = SETTINGS.getSetting('pref_post_rec') # Nachlauf (dto.) pre_rec = re.search('= (\d+) Min', pre_rec).group(1) post_rec = re.search('= (\d+) Min', post_rec).group(1) if pre_rec == '0': pre_rec = JOBDELAY # Ausgleich Intervall if os.path.exists(JOB_STOP): # Ruine? os.remove(JOB_STOP) old_age = 0 if os.path.exists(JOBFILE): jobs = ReadJobs() # s. util old_age = os.stat( JOBFILE).st_mtime # Abgleich in Monitor (z.Z. n.verw.) else: jobs = [] PLog("JOBFILE_old_age: %d" % old_age) i = 0 monitor = xbmc.Monitor() while not monitor.abortRequested(): i = i + 1 PLog("Monitor_Lauf: %d" % i) if get_Setting('pref_epgRecord') == 'false': # direkter Zugriff (s.o.) PLog("Monitor: pref_epgRecord false - stop") xbmcgui.Dialog().notification("Aufnahme-Monitor:", "gestoppt", MSG_ICON, 3000) break open(MONITOR_ALIVE, 'w').close() # Lebendsignal - Abgleich mtime in JobMain xbmc.sleep(JOBDELAY * 1000) # Pause # xbmc.sleep(2000) # Debug if os.path.exists(JOB_STOP): PLog("Monitor: JOB_STOP gefunden - stop") xbmcgui.Dialog().notification("Aufnahme-Monitor:", "gestoppt", MSG_ICON, 3000) break if os.path.exists(JOBFILE): # bei jedem Durchgang neu einlesen jobs = ReadJobs() else: jobs = [] now = EPG.get_unixtime(onlynow=True) now = int(now) now_human = date_human("%Y.%m.%d_%H:%M:%S", now='') # Debug #--------------------------------------------------- # Schleife Jobliste PLog("scan_jobs:") newjob_list = [] cnt = 0 job_changed = False # newjob_list: Liste nach Änderungen for cnt in range(len(jobs)): myjob = jobs[cnt] PLog(myjob[:80]) status = stringextract('<status>', '</status>', myjob) PLog("scan_Job %d status: %s" % (cnt + 1, status)) start_end = stringextract('<startend>', '</startend>', myjob) start, end = start_end.split('|') # 1593627300|1593633300 start = int( start) - int(pre_rec) * 60 # Vorlauf (Min -> Sek) abziehen end = int( end) + int(post_rec) * 60 # Nachlauf (Min -> Sek) aufschlagen start_human = date_human("%Y.%m.%d_%H:%M:%S", now=start) mydate = date_human( "%Y%m%d_%H%M%S", now=start) # Zeitstempel für titel in LiveRecord end_human = date_human("%Y.%m.%d_%H:%M:%S", now=end) duration = end - start # in Sekunden für ffmpeg diff = start - now vorz = '' if diff < 0: vorz = "minus " diff = seconds_translate(diff) laenge = "" PIDffmpeg = '' # laenge entfällt hier # PLog("now %s, start %s, end %s" % (now, start, end)) # Debug PLog("now %s, start %s, end %s, start-now: %s" % (now_human, start_human, end_human, diff)) #--------------------------------------------------- # 1 Job -> Aufnahme if (now >= start and now <= end ) and status == 'waiting': # Job ist aufnahmereif PLog("Job ready: " + start_end) duration = end - now # Korrektur, falls start schon überschritten url = stringextract('<url>', '</url>', myjob) JobID = stringextract('<JobID>', '</JobID>', myjob) sender = stringextract('<sender>', '</sender>', myjob) title = stringextract('<title>', '</title>', myjob) title = "%s: %s" % (sender, title) # Titel: Sender + Sendung descr = stringextract('<descr>', '</descr>', myjob) started = date_human("%Y.%M.D_%H:%M:%S", now=start) dfname = make_filenames(title.strip()) # Name aus Titel # Textdatei txttitle = "%s_%s" % (mydate, dfname ) # Zeitstempel wie inLiveRecord detailtxt = MakeDetailText(title=txttitle, thumb='', quality='Livestream', summary=descr, tagline='', url=url) detailtxt = py2_encode(detailtxt) txttitle = py2_encode(txttitle) storetxt = 'Details zur Aufnahme ' + txttitle + ':\r\n\r\n' + detailtxt dest_path = SETTINGS.getSetting('pref_download_path') textfile = txttitle + '.txt' dfname = dfname + '.mp4' # LiveRecord ergänzt Zeitstempel textfile = py2_encode(textfile) pathtextfile = os.path.join(dest_path, textfile) storetxt = py2_encode(storetxt) RSave(pathtextfile, storetxt) # Begleitext speichern # duration = "00:00:10" # Debug: 10 Sec. PLog("Satz:") PLog(url) PLog(title) PLog(duration) PLog(detailtxt) PLog(started) myjob = myjob.replace('<status>waiting', '<status>gestartet') PLog("Job %d started" % cnt) job_changed = True PIDffmpeg = LiveRecord(url, title, duration, laenge='', epgJob=mydate, JobID=JobID) # Aufnehmen myjob = myjob.replace('<pid></pid>', '<pid>%s</pid>' % PIDffmpeg) #--------------------------------------------------- # Job zurück in Liste jobs[cnt] = JOB_TEMPL % myjob # Job -> Listenelement PLog("Job %d PIDffmpeg: %s" % (cnt + 1, PIDffmpeg)) cnt = cnt + 1 # und nächster Job #--------------------------------------------------- # Jobliste speichern, falls geändert if job_changed: newjobs = "\n".join(jobs) page = JOBLIST_TEMPL % newjobs # Jobliste -> Marker page = py2_encode(page) PLog(u"geänderte Jobliste speichern:") PLog(page[:80]) open(JOBFILE_LOCK, 'w').close() # Lock ein err_msg = RSave(JOBFILE, page) # Jobliste speichern xbmc.sleep(500) if os.path.exists(JOBFILE_LOCK): # Lock aus os.remove(JOBFILE_LOCK) if os.path.exists(MONITOR_ALIVE): # Aufräumen nach Monitor-Ende os.remove(MONITOR_ALIVE) return
def JobListe(): # Liste, Job-Status, Jobs löschen PLog("JobListe:") li = xbmcgui.ListItem() li = home(li, ID=NAME) # Home-Button if os.path.exists(JOBFILE): jobs = ReadJobs() # s. util if len(jobs) == 0: xbmcgui.Dialog().notification("Jobliste:", "keine Aufnahme-Jobs vorhanden", MSG_ICON, 3000) else: xbmcgui.Dialog().notification("Jobliste:", "nicht gefunden", MSG_ICON, 3000) now = EPG.get_unixtime(onlynow=True) now = int(now) globFiles = "%s/ThreadKill_*" % ADDON_DATA # KillFile-Ruinen löschen files = glob.glob(globFiles) if len(files) > 0: max_rec_time = 43200 # 12 Std. = max. Setting pref_LiveRecord_duration OldKillFile = files[ 0] # 1 reicht, ev. Rest wird bei Folge-Calls abgeräumt if os.stat(OldKillFile).st_mtime < ( now - max_rec_time): # falls älter als max_rec_time PLog("entferne OldKillFile: %s" % OldKillFile) os.remove(OldKillFile) now_human = date_human("%d.%m.%Y, %H:%M", now='') pre_rec = SETTINGS.getSetting( 'pref_pre_rec') # Vorlauf (Bsp. 00:15:00 = 15 Minuten) post_rec = SETTINGS.getSetting('pref_post_rec') # Nachlauf (dto.) pre_rec = re.search('= (\d+) Min', pre_rec).group(1) post_rec = re.search('= (\d+) Min', post_rec).group(1) anz_jobs = len(jobs) jobs.sort() for cnt in range(len(jobs)): myjob = jobs[cnt] PLog(myjob[:80]) status = stringextract('<status>', '</status>', myjob) status_real = status # wird aktualisiert s.u. PLog("JobListe_Job %d status: %s" % (cnt + 1, status)) start_end = stringextract('<startend>', '</startend>', myjob) start, end = start_end.split('|') # 1593627300|1593633300 start = int(start) end = int(end) descr = stringextract('<descr>', '</descr>', myjob) PLog(descr) if "Recording Live" in descr == False: # Vor- und Nachlauf entfallen pass else: start = int( start) - int(pre_rec) * 60 # Vorlauf (Min -> Sek) abziehen end = int( end) + int(post_rec) * 60 # Nachlauf (Min -> Sek) aufschlagen mydate = date_human("%Y%m%d_%H%M%S", now=start) # Zeitstempel für titel in LiveRecord start_human = date_human("%d.%m.%Y, %H:%M", now=start) end_human = date_human("%d.%m.%Y, %H:%M", now=end) pid = stringextract('<pid>', '</pid>', myjob) title = stringextract('<title>', '</title>', myjob) job_title = title # Abgleich in JobRemove alt JobID = stringextract('<JobID>', '</JobID>', myjob) # Abgleich in JobRemove neu sender = stringextract('<sender>', '</sender>', myjob) dfname = title.strip() # Recording Live: ohne Sender if sender: dfname = "%s: %s" % (sender, title ) # Titel: Sender + Sendung (mit Mark.) dfname = make_filenames(dfname.strip()) + ".mp4" # Name aus Titel dfname = "%s_%s" % (mydate, dfname) # wie LiveRecord dest_path = SETTINGS.getSetting('pref_download_path') video = os.path.join(dest_path, dfname) PLog("video: " + video) status_add = "" if os.path.exists(video): status_add = " | Video vorhanden: %s.." % dfname[: 28] # für Infobereich begrenzen else: status_add = " | Video fehlt: %s.." % dfname[:28] # dto. title = cleanmark(title) title = title.replace("JETZT: ", '') img = MSG_ICON # rot PLog(" end %s, now %s" % (end, now)) job_active = False if end < now: # abgelaufen img = R("icon-record-grey.png") # grau if status == "gestartet": status_real = "[B] Jobstatus: Aufnahme wurde gestartet [/B]" + status_add else: status_real = "[B] Jobstatus: Aufnahme wurde nicht gestartet [/B] - Ursache nicht bekannt" else: # noch aktiv img = MSG_ICON # grau job_active = True status_real = "Aufnahme geplant: %s" % start_human label = u'Job löschen: %s' % title if job_active: label = u'Job stoppen / löschen: %s' % title tag = u'Start: [B]%s[/B], Ende: [I][B]%s[/B][/I]' % (start_human, end_human) tag = u'%s\n%s' % (tag, status_real) max_reclist = SETTINGS.getSetting('pref_max_reclist') summ = u'[B]Anzahl Jobs[/B] in der Aufnahmeliste: %s' % (anz_jobs) summ = u"%s\n[B]Settings[/B]:\n[B]max. Größe der Aufnahmeliste:[/B] %s Jobs," % ( summ, max_reclist) summ = u"%s[B]Vorlauf:[/B] %s Min., [B]Nachlauf:[/B] %s Min." % ( summ, pre_rec, post_rec) fparams="&fparams={'sender':'%s','job_title':'%s','start_end':'%s','job_active':'%s','pid':'%s','JobID':'%s'}" %\ (sender, job_title, start_end, job_active, pid, JobID) addDir(li=li, label=label, action="dirList", dirID="resources.lib.epgRecord.JobRemove", fanart=R(ICON_DOWNL_DIR), thumb=img, fparams=fparams, tagline=tag, summary=summ) xbmcplugin.endOfDirectory(HANDLE, cacheToDisc=False)
def JobMain(action, start_end='', title='', descr='', sender='', url='', setSetting='', PIDffmpeg=''): PLog("JobMain:") PLog(action) PLog(sender) PLog(title) PLog(descr) PLog(start_end) PLog(PIDffmpeg) # mythreads = threading.enumerate() # liefert in Kodi nur MainThread status = os.path.exists(MONITOR_ALIVE) PLog("MONITOR_ALIVE pre: " + str(status)) # Eingangs-Status now = EPG.get_unixtime(onlynow=True) #------------------------ if action == 'init': # bei jedem Start ardundzdf.py if setSetting: # Aufruf: DownloadTools SETTINGS.setSetting('pref_epgRecord', 'true') xbmcgui.Dialog().notification("Aufnahme-Monitor:", "Start veranlasst", MSG_ICON, 3000) xbmc.executebuiltin('Container.Refresh') return if os.path.exists(MONITOR_ALIVE): # check Lebendsignal mtime = os.stat(MONITOR_ALIVE).st_mtime diff = int(now) - mtime PLog("now: %s, mtime: %d, diff: %d" % (now, mtime, diff)) if diff > JOBDELAY: # Monitor tot? PLog( "alive_veraltet: force init") # abhängig von JOBFILE, s.u. os.remove(MONITOR_ALIVE) else: PLog("alive_aktuell: return") return else: PLog("alive_fehlt: force init") # dto. if check_file(JOBFILE) == False: # JOBFILE leer/fehlt - kein Hindernis PLog("Aufnahmeliste leer") if os.path.exists(MONITOR_ALIVE) == False: # JobMonitor läuft bereits? bg_thread = Thread( target=JobMonitor, # sonst Thread JobMonitor starten args=()) bg_thread.start() xbmcgui.Dialog().notification("Aufnahme-Monitor:", "gestartet", MSG_ICON, 3000) else: PLog("running - skip init") return #------------------------ if action == 'stop': # DownloadTools <- jobs = ReadJobs() # s. util now = EPG.get_unixtime(onlynow=True) job_active = False PLog('Mark0') for job in jobs: start_end = stringextract('<startend>', '</startend>', job) start, end = start_end.split('|') # 1593627300|1593633300 if int(start) > int(now): job_active = True break if job_active: title = 'Aufnahme-Monitor stoppen' msg1 = "Mindestens ein Aufnahmejob ist noch aktiv!" msg2 = "Aufnahme-Monitor trotzdem stoppen?" ret = MyDialog(msg1=msg1, msg2=msg2, msg3='', ok=False, cancel='Abbruch', yes='JA', heading=title) if ret != 1: return open(JOB_STOP, 'w').close() # STOPFILE anlegen SETTINGS.setSetting( 'pref_epgRecord', 'false') # Setting muss manuell wieder eingeschaltet werden PLog("JOB_STOP set") # Status xbmc.executebuiltin('Container.Refresh') xbmcgui.Dialog().notification("Aufnahme-Monitor:", "Stop veranlasst", MSG_ICON, 3000) # Notification im Monitor # test_jobs # Debug return #------------------------ # die für Recording Live (LiveRecord) erzeugten Jobs werden nicht im JobMonitor # abgearbeitet, sondern direkt in m3u8.Main_m3u8 - entfallen mit Ende des # experimentellen m3u8-Aufnahmeverfahrens 30.08.2020 if action == 'setjob': # neuen Job an Aufnahmeliste anhängen + Bereinigung: Doppler # verhindern, Einträge auf pref_max_reclist beschränken title = cleanmark(title) # Farbe/fett aus ProgramRecord block = '4Yp2C09aF1k5YC3d' JobID = ''.join(random.choice(block) for i in range(len(block))) # 16 stel. Job-ID if "Recording Live" in descr: # Aufruf: LiveRecord, Start ohne EPG status = 'gestartet' # -> <status>, für JobMonitor tabu pid = "Thread_%s" % JobID # -> KillFile (JobRemove) - wie JobMonitor else: status = 'waiting' if PIDffmpeg: # Aufruf: LiveRecord via ffmpeg status = 'gestartet' # -> <status>, für JobMonitor tabu pid = PIDffmpeg # aus LiveRecord direkt oder via JobMonitor job_line = JOBLINE_TEMPL % (start_end, title, descr, sender, url, status, pid, JobID) new_job = JOB_TEMPL % job_line PLog(new_job[:80]) jobs = ReadJobs() # s. util job_list = [] cnt = 0 # Neubau Jobliste # Kontrolle erweitern, falls startend + sender nicht eindeutig genug: for job in jobs: list_startend = stringextract('<startend>', '</startend>', job) list_sender = stringextract('<sender>', '</sender>', job) if list_startend == start_end and list_sender == sender: # Kontrolle Doppler msg1 = "%s: %s\nStart/Ende (Unix-Format): %s" % (sender, title, start_end) msg2 = "Sendung ist bereits in der Jobliste - Abbruch" MyDialog(msg1, msg2, '') PLog("%s\n%s" % (msg1, msg2)) return # alte Liste unverändert else: job_list.append(JOB_TEMPL % job) # job -> Marker cnt = cnt + 1 new_job = py2_encode(new_job) job_list.append(new_job) # neuen Job anhängen maxlen = int(SETTINGS.getSetting('pref_max_reclist')) if len(job_list) > maxlen: while len(job_list) > maxlen: del job_list[0] # 1. Satz entf. PLog('%d/%d, Job entfernt: %s' % (maxlen, len(job_list), job_list[0])) jobs = "\n".join(job_list) page = JOBLIST_TEMPL % jobs # Jobliste -> Marker page = py2_encode(page) PLog(page[:80]) open(JOBFILE_LOCK, 'w').close() # Lock ein err_msg = RSave(JOBFILE, page) # Jobliste speichern if os.path.exists(JOBFILE_LOCK): # Lock aus os.remove(JOBFILE_LOCK) xbmcgui.Dialog().notification("Aufnahme-Monitor:", "Job hinzugefügt", MSG_ICON, 3000) PLog("JobID: %s" % JobID) if "ffmpeg-recording" in descr: # LiveRecord ffmpeg return JobID else: if os.path.exists( MONITOR_ALIVE) == False: # JobMonitor läuft bereits? bg_thread = Thread( target=JobMonitor, # sonst Thread JobMonitor starten args=()) bg_thread.start() return #------------------------ if action == 'listJobs': # Liste, Job-Status, Jobs löschen JobListe() return #------------------------ if action == 'deljob': # Job aus Aufnahmeliste entfernen JobRemove() return #------------------------ if action == 'test_jobs': # Testfunktion test_jobs() return