--- /dev/null
+# -*- coding: utf-8 -*-
+from enigma import eConsoleAppContainer, eTimer
+from xml.etree.cElementTree import parse as cet_parse
+from os import path, listdir
+from os import remove as os_remove
+
+class Bonjour:
+ AVAHI_SERVICES_DIR = '/etc/avahi/services/'
+ AVAHI_START_SCRIPT = '/etc/init.d/avahi-daemon'
+
+ def __init__(self):
+ self.services = []
+ self.files = {}
+
+ self.container = eConsoleAppContainer()
+ self.container.appClosed.append(self.cmdFinished)
+
+ self._timer = eTimer()
+ self._timer.callback.append(self.restartDaemon)
+ self._timerRunning = False
+
+ self.reloadConfig()
+
+ def __createServiceConfig(self, service):
+ lines = [
+ '<?xml version="1.0" standalone="no"?><!--*-nxml-*-->\n',
+ '<!DOCTYPE service-group SYSTEM "avahi-service.dtd">\n',
+ '<!-- This file has been created by enigma2-plugin-extensions-bonjour -->\n',
+ '<service-group>\n',
+ '\t<name replace-wildcards="yes">%s</name>\n' %(service['name']),
+ '\t<service>\n',
+ '\t\t<type>%s</type>\n' %(service['type']),
+ '\t\t<port>%s</port>\n' %(service['port'])
+ ]
+
+ if service['text'] is not None and service['text'] != "":
+ lines.add('\t\t<text-record>%s</text-record>\n' %(service['text']) )
+
+ lines.extend([
+ '\t</service>\n',
+ '</service-group>\n'
+ ])
+
+ return lines
+
+ def __writeService(self, service):
+ print "[Bonjour.__writeService] Creating service file '%s'" %(service['file'])
+ if 'type' in service and 'port' in service and 'file' in service:
+ filepath = "%s%s" %(self.AVAHI_SERVICES_DIR, service['file'])
+ file = open(filepath, 'w');
+ file.writelines(self.__createServiceConfig(service))
+ file.close()
+ return True
+
+ print "[Bonjour.__writeService] Cannot create service file '%s'" %(service['file'])
+ return False
+
+ def __deleteService(self, protocol):
+ filepath = "%s%s.service" %(self.AVAHI_SERVICES_DIR, protocol)
+ if path.exists(filepath):
+
+ os_remove(filepath)
+ return True
+
+ return False
+
+ def __parse(self, file):
+ print "[Bonjour.__parse] parsing %s%s" %(self.AVAHI_SERVICES_DIR, file)
+ config = cet_parse(self.AVAHI_SERVICES_DIR + file).getroot()
+
+ name = config.find('name').text
+
+ service = config.find('service')
+ type = service.find('type').text
+ port = service.find('port').text
+ text = service.get('text-record')
+ if text is None:
+ text = ""
+ else:
+ text = text.text
+
+ service = self.buildServiceFull(file, name, type, port, text)
+ self.registerService(service)
+
+ def __removeServiceFromList(self, service):
+ oldservices = self.services
+ self.services = []
+
+ for s in oldservices:
+ if s['file'] != service['file']:
+ self.services.append(s)
+ self.files[s['file']] = len(self.services) - 1
+
+ self.files[service['file']] = None
+
+
+ def reloadConfig(self):
+ self.services = []
+ self.files = {}
+ if path.exists(self.AVAHI_SERVICES_DIR):
+ print "[Bonjour.reloadConfig] reloading config"
+ service_files = filter( lambda x: x.endswith('.service'), listdir(self.AVAHI_SERVICES_DIR) )
+ for file in service_files:
+ self.__parse(file)
+
+ self.registerDefaultServices()
+
+
+ def registerService(self, service, replace = False):
+ print "[Bonjour.registerService] %s" %service
+
+ if 'type' in service and 'port' in service and 'file' in service:
+ if (service['file'] not in self.files) or replace:
+ filepath = "%s%s" %(self.AVAHI_SERVICES_DIR, service['file'])
+ if not self.__writeService(service):
+ return False
+
+ if replace and service['file'] in self.files:
+ self.__removeServiceFromList(service)
+
+
+ self.services.append(service)
+ self.files[service['file']] = len(self.services) - 1
+
+ if self._timerRunning:
+ self._timer.stop()
+
+ #if no other service is being registered for 15 seconds restart the daemon
+ self._timer.start(15000)
+ self._timerRunning = True
+
+ return True
+
+ else:
+ print "[Bonjour.registerService] Missing port or type definition in %s%s" %(self.AVAHI_SERVICES_DIR, service['file'])
+ return False
+
+
+ def updateService(self, service):
+ if 'type' in service and 'port' in service and 'file' in service:
+
+ filepath = "%s%s" %(self.AVAHI_SERVICES_DIR, service['file'])
+ if not path.exists(filepath):
+ print "[Bonjour.updateService] Cannot update non-existent service file '%s'" %(service['file'])
+ return False
+
+ else:
+ if not self.__writeService(service):
+ print "[Bonjour.updateService] Cannot write service file '%s'" %(service['file'])
+ return False
+
+ return True
+
+ def unregisterService(self, protocol):
+ if self.__deleteService(protocol):
+ self.reloadConfig()
+
+
+ def buildService(self, protocol, port, text="", udp = False):
+ file = "%s.service" %protocol
+
+ type = "_%s._tcp" %protocol
+ if udp:
+ type = "_%s._udp" %protocol
+
+ name = "%h "
+ name += protocol.upper()
+
+ return {
+ 'file' : file,
+ 'name' : name,
+ 'type' : type,
+ 'port' : port,
+ 'text' : text
+ }
+
+ def buildServiceFull(self, file, name, type, port, text="", udp = False):
+ return {
+ 'file' : file,
+ 'name' : name,
+ 'type' : type,
+ 'port' : port,
+ 'text' : text
+ }
+
+ def registerDefaultServices(self):
+ print "[Bonjour.registerDefaultServices] called"
+ service = self.buildService('ftp', '21')
+ filepath = "%s%s" %(self.AVAHI_SERVICES_DIR, service['file'])
+ if not path.exists(filepath):
+ self.registerService(service)
+
+ service = self.buildService('ssh', '22')
+ filepath = "%s%s" %(self.AVAHI_SERVICES_DIR, service['file'])
+ if not path.exists(filepath):
+ self.registerService(service)
+
+ service = self.buildService('sftp-ssh', '22')
+ filepath = "%s%s" %(self.AVAHI_SERVICES_DIR, service['file'])
+ if not path.exists(filepath):
+ self.registerService(service)
+
+ service = self.buildService('smb', '139')
+ filepath = "%s%s" %(self.AVAHI_SERVICES_DIR, service['file'])
+ if not path.exists(filepath):
+ self.registerService(service)
+
+ def stopTimer(self):
+ if self._timerRunning:
+ self._timer.stop()
+
+ def startDaemon(self):
+ print "[Bonjour.startDaemon] called"
+ cmd = [self.AVAHI_START_SCRIPT, 'start']
+ self.container.execute(*cmd)
+
+ def stopDaemon(self):
+ print "[Bonjour.stopDaemon] called"
+ cmd = [self.AVAHI_START_SCRIPT, 'stop']
+ self.container.execute(*cmd)
+
+ def restartDaemon(self):
+ print "[Bonjour.restartDaemon] called"
+ self.stopTimer()
+
+ cmd = [self.AVAHI_START_SCRIPT, 'restart']
+ self.container.execute(*cmd)
+
+ def cmdFinished(self, data):
+ print "[Bonjour.cmdFinished] %s" %(data)
+
+bonjour = Bonjour()
\ No newline at end of file
--- /dev/null
+# -*- coding: utf-8 -*-
+
+from enigma import eListboxPythonMultiContent, gFont
+
+from Plugins.Plugin import PluginDescriptor
+from Bonjour import bonjour
+
+from Screens.Screen import Screen
+from Components.MenuList import MenuList
+from Components.MultiContent import MultiContentEntryText
+from Components.ActionMap import ActionMap
+
+class BonjourScreen(Screen):
+ skin = """
+ <screen position="center,center" size="600,400" title="Bonjour" >
+ <widget name="menuList" position="10,10" size="580,380" scrollbarMode="showOnDemand" />
+ </screen>"""
+
+ def __init__(self, session, services, files):
+ Screen.__init__(self, session)
+ self.session = session
+ self.services = services
+ self.files = files
+
+ self["menuList"] = MenuList([], content=eListboxPythonMultiContent)
+ self["menuList"].l.setItemHeight(75)
+ self["menuList"].l.setFont(0, gFont("Regular", 20) )
+ self["menuList"].l.setFont(1, gFont("Regular", 16) )
+
+ self["actions"] = ActionMap(["OkCancelActions"],
+ {
+ "ok": self._ok,
+ "cancel": self._exit,
+ }, -1)
+
+ self.onLayoutFinish.append(self.buildMenu)
+ self.onLayoutFinish.append(self.layoutFinished)
+
+ def layoutFinished(self):
+ print "LAYOUT FINISHED!!"
+ self.setTitle(_("Bonjour: Overview"))
+
+ def _ok(self):
+ print "OK OK OK OK"
+ pass
+
+ def _exit(self):
+ self.close()
+
+ def buildMenu(self):
+ list = []
+ for key in sorted(self.files):
+ if self.files[key] != None:
+ list.append( self.__buildMenuEntry(self.services[self.files[key]]) )
+
+ self["menuList"].l.setList(list)
+ self["menuList"].setList(list)
+
+ def __buildMenuEntry(self, service):
+ print "[Bonjour.__buildMenuEntry] service=%s" %service
+
+ file = "%s" %(service['file'])
+ name = "Name: %s" %(service['name'])
+ type = "Type: %s" %(service['type'].split('.')[0].replace('_',''))
+ prot = "Protocol: %s" %(service['type'].split('.')[1].replace('_',''))
+ port = "Port: %s" %(service['port'])
+ text = "Text: %s" %(service['text'])
+
+ return [
+ service,
+ MultiContentEntryText(pos=(5, 0), size=(185, 30), font=0, text=file),
+ MultiContentEntryText(pos=(190, 0), size=(385, 30), font=0, text=name),
+ MultiContentEntryText(pos=(5, 25), size=(150, 30), font=1, text=type),
+ MultiContentEntryText(pos=(160, 25), size=(150, 30), font=1, text=prot),
+ MultiContentEntryText(pos=(315, 25), size=(150, 30), font=1, text=port),
+ MultiContentEntryText(pos=(5, 45), size=(570, 30), font=1, text=text)
+ ]
+
+def opencontrol(session):
+ bonjour.reloadConfig()
+ session.open(BonjourScreen, bonjour.services, bonjour.files)
+ print "[Bonjour.opencontrol] %s" %(bonjour.files)
+ #TODO GUI-Stuff
+
+
+def Plugins(**kwargs):
+ return [ PluginDescriptor(
+ name=_("Bonjour"), description=_("Control Bonjour (avahi-daemon)"),
+ where=[PluginDescriptor.WHERE_PLUGINMENU], icon="plugin.png", fnc=opencontrol)
+ ]