/usr/bin/pronto2lirc is in lirc 0.10.0-2.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | #! /usr/bin/python3
#
# A tool for converting Pronto format hex codes to lircd.conf format. Version 1.11
#
# Version History:
# 1.11 - Made more resiliant against whitespace imperfections in input files
# 1.1 - Added support for CCFTools/CCFDecompiler XML files and multiple devices
# 1.0 - Initial release
#
# Copyright by Olavi Akerman <olavi.akerman@gmail.com>
#
# pronto2lirc is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
import string
class CodeSequence: # Handles codesequences parsing and conversion
def ProcessPreamble(self,sPreamble):
if sPreamble[0]!="0000":
raise ValueError("Formats other than starting with 0000 are not supported!")
self.dIRFrequency=1000000/(int(sPreamble[1],16) * 0.241246) # Frequency of the IR carrier in Khz
self.lOnceSequenceLength=int(sPreamble[2],16) # No of pulses that is sent once when button is pressed
self.lRepeatableSequenceLength=int(sPreamble[3],16) # No of pulses that are repeatable while button pressed
def CreatePulses(self,sItems):
self.dPulseWidths=[] # Table of Pulse widths. Length is repsented in microseconds
for i in sItems:
self.dPulseWidths.append(1000000*int(i,16)/self.dIRFrequency) # Convert pulse widths to uS
if len(self.dPulseWidths)!=2*(self.lOnceSequenceLength+self.lRepeatableSequenceLength):
raise ValueError("Number of actual codes does not match the header information!")
def AnalyzeCode(self,sCodeName,sHexCodes):
# sHexTable=sHexCodes.split()
s="".join(sHexCodes.split()) # Remove whitespace formatting between sequences
sHexTable=[]
while s!='': # Re-split into group of 4
sHexTable.append(s[:4])
s=s[4:]
self.sCodeName=sCodeName.rstrip() # Name of the Code associated with code sequence
self.ProcessPreamble(sHexTable[:4]) # First four sequences make up Preamble
self.CreatePulses(sHexTable[4:]) # The rest are OnceSequence + RepeatableSequence
return self.dPulseWidths[-1] # Final gap=last off signal length
def WriteCodeSection(self,fOut):
fOut.write('\n\t\t\tname '+self.sCodeName.strip().replace(' ','')+'\n') # Can't contain whitespace
for i in range(len(self.dPulseWidths)-1): # Do not write the last signal as lircd.conf
# does not contain last off signal length
if (i%6) ==0:
fOut.write('\t\t\t\t')
fOut.write('%d ' % round(self.dPulseWidths[i]))
if (i+1)%6 ==0: # Group codes as six per line
fOut.write('\n')
fOut.write('\n') # Final EOL
class Device: # Handles devices
def AddCodes(self,sCodeName,sHexCodes): # Add new code sequence
seq=CodeSequence()
finalgap=seq.AnalyzeCode(sCodeName,sHexCodes)
if finalgap>self.lGap:
self.lGap=finalgap
self.sCodes.append(seq)
def ProcessHEX(self,fHexFile,sLine): # Process HEX files
while sLine!='' and sLine.strip()!='': # EOF?
[sCodeName,sHexCodes]=sLine.split(':')
self.AddCodes(sCodeName,sHexCodes)
sLine=fHexFile.readline()
def WriteLIRCCConfDevice(self,f):
f.write('begin remote\n')
f.write('\tname\t'+self.sDeviceName.replace(' ','')+'\n')
f.write('\tflags\tRAW_CODES\n')
f.write('\teps\t30\n')
f.write('\taeps\t100\n')
f.write('\tgap\t%d\n' % self.lGap )
f.write('\t\tbegin raw_codes\n')
for i in self.sCodes:
i.WriteCodeSection(f)
f.write('\t\tend raw_codes\n')
f.write('end remote\n')
def __init__(self,sDeviceName):
self.sDeviceName=sDeviceName # Name of the device
self.sCodes=[] # Codes contained in file
self.lGap=0 # Final Gap
class RemoteFilesParser:
def ProcessXML(self,fXMLFile):
def start_element(name,attrs):
if name=="RAWCODE":
self.Devices[-1].AddCodes(attrs['name'],attrs['data'])
if name=="DEVICE":
self.Devices.append(Device(attrs['name']))
p = xml.parsers.expat.ParserCreate()
p.StartElementHandler = start_element
fXMLFile.seek(0) # Need to start from the beginning
p.ParseFile(fXMLFile)
def __init__(self,sFileName):
self.Devices=[]
f=open(sFileName,'r')
sLine=f.readline()
if sLine.strip()=='<?xml version="1.0"?>': # Are we dealing with CCF Decompiler XML file?
self.ProcessXML(f)
else:
device=Device(sFileName.split('.')[:1][0])
self.Devices.append(device)
device.ProcessHEX(f,sLine)
f.close()
def WriteLIRCConf(self,sOutFileName):
f=open(sOutFileName,'w')
for d in self.Devices:
d.WriteLIRCCConfDevice(f)
f.close()
# Main
import sys
import xml.parsers.expat
if len(sys.argv)!=2 or sys.argv[1] == '-h' or sys.argv[1] == '--help':
print("Pronto codes converter to lircd.conf format (version 1.11)")
print()
print("Usage: pronto2lirc.py inputfile")
print()
print("Inputfile can be:")
print(" 1.An xml file output by CCFTools/CCFDecompiler.")
print(" 2.Text file where each line contains the name of the button and ")
print(" all codes associated with it")
print(" Button1:0000 00ac 000b 00de ...")
print()
print("Result: lircd.conf file is written to the current directory")
print(" containing all the Pronto codes extracted from")
print(" the input file")
print()
else:
p=RemoteFilesParser(sys.argv[1])
p.WriteLIRCConf('lircd.conf')
|