#!/usr/bin/env python
# -*- coding: windows-1251 -*-
# ReplaceGen.py - генератор файла replace.list
# для эмулятора mgcamd
# версия: 0.36
# =========================================================
# Адрес mgcamd - в его настройках в файле mg_cfg нужно
# указать такие-же параметры: L: { 01 } 127.0.0.1 10514
sServerHost = "127.0.0.1"
nServerPort = 10514
# Адрес и порт компьютера, куда пересылать сообщения mgcamd
sClientHost = "192.168.1.2"
nClientPort = 514
# путь к файлу replace.list
sRL = "/usr/keys/replace.list"
# путь к файлу с названиями каналов
sLame = "/etc/enigma2/lamedb"
# Кодировка, в которой писать русскоязычные названия каналов
# возможные значения: UTF-8, UTF-16, ISO-8859-5, KOI8-R, CP1251, CP866, Mac-cyrillic
# для отключения перекодирования поставить UTF-8
sCoding = 'UTF-8'
# =========================================================
def cm_key( sLine ):
ar = re.search( r"^(.+?)\#(.+)$", sLine )
if ar: return ar.group( 2 ) + ar.group( 1 )
else: return ''
from socket import *
import re
import os
nBufSize = 1024
aServerAddr = (sServerHost, nServerPort)
aClientAddr = (sClientHost, nClientPort)
# если уже запущена одна копия программы - убиваем её
sOldPid = None
nOldTime = None
for sp in os.listdir( '/proc' ):
if not os.path.isdir( '/proc/' + sp ) or not re.search( r"^\d+$", sp ) or not os.path.isfile( '/proc/' + sp + '/cmdline' ): continue
sCmd = ''
fh = open( '/proc/' + sp + '/cmdline', "r" )
sCmd = fh.readline()
fh.close()
if sCmd.count( 'ReplaceGen' ):
if nOldTime:
if nOldTime > os.path.getctime( '/proc/' + sp ): sOldPid = sp
try:
os.kill( int( sOldPid ), 1 )
except OSError:
print 1
else:
nOldTime = os.path.getctime( '/proc/' + sp )
sOldPid = sp
# Create socket and bind to address
UDPServerSock = socket(AF_INET,SOCK_DGRAM)
UDPServerSock.setsockopt( SOL_SOCKET, SO_REUSEADDR, 1 )
UDPServerSock.bind(aServerAddr)
UDPClientSock = socket(AF_INET,SOCK_DGRAM)
# Загружаем базу названий каналов
# 42d5:01680000:0011:0070:1:0
# TV-21
# p:HTB+,c:000153,c:0101a3,c:030153,C:0500,C:5601,f:40
aLame = []
if os.path.isfile( sLame ):
fh = open( sLame, "r" )
al = fh.readlines()
fh.close()
for n in range( len( al )):
ar = re.search( r"^([0-9A-Fa-f]+):[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+", al[ n ])
if not ar: continue
sServ = ar.group( 1 )
sServ = sServ.upper()
while len( sServ ) < 4: sServ = '0' + sServ
sName = al[ n + 1 ].strip()
if sCoding != "UTF-8": sName = sName.encode( sCoding )
sProv = ''
ar = re.search( r"p:([^,]+).*$", al[ n + 2 ])
if ar:
sProv = '[' + ar.group( 1 ).strip() + '] '
if sCoding != "UTF-8": sProv = sProv.encode( sCoding )
aLame.append([ sServ, sProv, sName, al[ n + 2 ]])
# добавляем названия каналов к строчкам, где их нет
if os.path.isfile( sRL ):
fh = open( sRL, "r" )
aRL = fh.readlines()
fh.close()
for n in range( len( aRL )):
aRL[ n ] = aRL[ n ].strip()
if not aRL[ n ].count( '#' ):
ar = re.search( r"R\:\s*\{\s*\{\s*([0-9A-Fa-f]+)\s*\}\s*\{\s*[0-9A-Fa-f]+\s*\}\s*\{\s*[0-9A-Fa-f]+\s*\}\s*\{\s*[0-9A-Fa-f]+\s*\}\s*\{\s*([0-9A-Fa-f]+)\s*\}", aRL[ n ])
sServ = ''
if ar:
sServ = ar.group( 1 )
while len( sServ ) < 4: sServ = '0' + sServ
sCaID = ar.group( 2 )
# в комментарии пишем название канала
sComment = None
for nl in range( len ( aLame )):
if aLame[ nl ][ 0 ] != sServ: continue
sComment = " \t # " + aLame[ nl ][ 1 ] + aLame[ nl ][ 2 ]
if re.search( r"C:" + sCaID, aLame[ nl ][ 3 ].upper()): break
if sComment:
aRL[ n ] += sComment
aRLold = aRL[:]
aRL.sort( key = cm_key )
if aRL != aRLold:
bFirstLine = 1
fh = open( sRL, "w" )
for n in range( len( aRL )):
if not len( aRL[ n ]): continue
if not bFirstLine: fh.write( '\n' )
fh.write( aRL[ n ])
bFirstLine = 0
fh.close()
sServiceID = None
aCaIDs = []
sCurCaID = None
sCurPID = None
sCurProvID = None
# Receive messages
while 1:
sData,aServerAddr = UDPServerSock.recvfrom(nBufSize)
if not sData: continue
UDPClientSock.sendto( sData, aClientAddr )
# [mg0] service 50EA index 0 pmt pid AB (17), pids: video 0x014D, audio 0x01A4
if sData.count('] service '):
# запоминаем код канала (serviceID)
ar = re.search( r"\] service ([0-9A-Fa-f]+) index", sData )
if ar:
sServiceID = ar.group( 1 )
sServiceID.upper()
while len( sServiceID ) < 4: sServiceID = '0' + sServiceID
aCaIDs = []
sCurCaID = None
sCurPID = None
# [mg0] ECM: CaID: 0x0500 -> CaPID: 0x0FAE ProvID: 023700
elif sData.count('] ECM: CaID: 0x'):
# добавляем в массив новую строку с CaID, PID, ProvID
ar = re.search( r"\]\s+ECM:\s+CaID\:\s+0x([0-9A-Fa-f]+)\s+-\>\s+CaPID\:\s+0x([0-9A-Fa-f]+) ProvID: ([0-9A-Fa-f]+)", sData )
if ar:
aCaIDs.append([ ar.group( 1 ), ar.group( 2 ), ar.group( 3 )])
sCurCaID = None
sCurPID = None
# system: Viaccess\ncaid: 0x0500\npid: 0x0fae
elif sData.count('\npid: 0x'):
# получен правильный CaID и PID (для mgcamd 1.37)
ar = re.search( r"\ncaid: 0x([0-9A-Fa-f]+)\npid: 0x([0-9A-Fa-f]+)", sData )
if ar:
sCurCaID = ar.group( 1 )
sCurCaID = sCurCaID.upper()
sCurPID = ar.group( 2 )
sCurPID = sCurPID.upper()
# ===== Viaccess ECM on CaID 0x0500, pid 0x0b58 ======
elif sData.count(' ECM on CaID 0x'):
# получен правильный CaID и PID (для mgcamd 1.35)
ar = re.search( r"ECM on CaID 0x([0-9A-Fa-f]+), pid 0x([0-9A-Fa-f]+)", sData )
if ar:
sCurCaID = ar.group( 1 )
sCurCaID = sCurCaID.upper()
sCurPID = ar.group( 2 )
sCurPID = sCurPID.upper()
# prov: 023700
elif sData.count('prov: '):
# получен правильный ProvID
ar = re.search( r"prov: ([0-9A-Fa-f]+)", sData )
if ar: sCurProvID = ar.group( 1 )
# если не было заголовка - нет всех данных, всё очищаем.
if not sServiceID or not sCurCaID or sCurCaID == '2600':
sServiceID = None
aCaIDs = []
sCurCaID = None
sCurPID = None
sCurProvID = None
continue
# читаем файл
if os.path.isfile( sRL ):
fh = open( sRL, "r" )
aRL = fh.readlines()
fh.close()
else: aRL = []
# вносим данные в replace.list
# R: {{2F47}{0500}{023700}{0FA3}{0500}{030600}{0BBB}}
for nc in range( len( aCaIDs )):
sCaID = aCaIDs[ nc ][ 0 ]
sPID = aCaIDs[ nc ][ 1 ]
sProvID = aCaIDs[ nc ][ 2 ]
if sPID.upper() == sCurPID: continue
sRepl = 'R: {{' + sServiceID + '}{' + sCaID + '}{' + sProvID + '}{' + sPID + '}{' + sCurCaID + '}{' + sCurProvID + '}{' + sCurPID + '}}'
aa = re.search( r'\{\s*\{\s*' + sServiceID + r'\s*\}\s*\{\s*' + sCaID + r'\s*\}\s*\{\s*' + sProvID + '\s*\}\s*\{\s*' + sPID + '\s*\}', '\n'.join( aRL ))
if not aa:
# в комментарии пишем название канала
sComment = None
for nl in range( len ( aLame )):
if aLame[ nl ][ 0 ] != sServiceID: continue
sComment = " \t # " + aLame[ nl ][ 1 ] + aLame[ nl ][ 2 ]
if re.search( r"C:" + sCaID, aLame[ nl ][ 3 ].upper()): break
if sComment:
sRepl += sComment
fh = open( sRL, "a" )
fh.write( '\n' + sRepl )
fh.close()
# очищаем все IDы
sServiceID = None
aCaIDs = []
sCurCaID = None
sCurPID = None
sCurProvID = None
# Close socket
UDPServerSock.close()