EventGhost/EventGhost

View on GitHub
plugins/XBMCEventReceiver/__init__.py

Summary

Maintainability
A
2 hrs
Test Coverage
# -*- coding: utf-8 -*-
#
# plugins/XBMCEventReceiver/__init__.py
#
# This file is a plugin for EventGhost.
# Copyright © 2005-2020 EventGhost Project <http://www.eventghost.net/>
#
# EventGhost 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.
#
# EventGhost 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 EventGhost. If not, see <http://www.gnu.org/licenses/>.
#
# This plugin is based on the Broadcaster plugin that was originally provided
# by the good work from Kingtd.  I have used it as a basis for true 2-way control
# too and from XBMC.  The following improvements have been made to v2.0:
#
#    - Enabled additional fields for configuration of HTTP.API destination in setup
#    - Enabled the invoking of XBMC Host Broadcast function with in the script
#      (so it is not necessary to do it manually)
#    - Cleaned up some of the code.
#    - Fixed error when trying to reconfigure plugin
#
# Future enhancements to make for future ver. as time permits such as:
#
#  - Extending response functionality as it applies to XBMC (once it is implemented @ the XBMC Host).
#  - Additional parsing of input from XBMC host
#
#  If you have any additional comments or suggestions feel free to contact me at vortexrotor@vortexbb.com

import eg

eg.RegisterPlugin(
    name = "XBMC Event Receiver",
    author = "vortexrotor",
    version = "2.0.5",
    kind = "program",
    guid = "{9872BD49-2022-4F1B-B362-85F1ED203B7E}",
    description = (
        "Receives events from XBMC Host UDP Broadcasts."
    ),
    url = "http://www.eventghost.net/forum/viewtopic.php?f=10&t=2140",
    icon = (
        "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA"
        "BGdBTUEAALGeYUxB9wAAACBjSFJNAAB6fAAAfosAAPoBAACHPAAAbUoAAPFDAAA2IAAAHlNX4WK7"
        "AAACYElEQVR42tTTPW8ScQDH8d/9n44HESgFKQjFWku1rUYdTEAT0sGHSU10cHZz0piYjqYxbia6"
        "+hB3Y0w3kzq0scaojdZqYiMp1dQWAlLg4A7ugbvzRXTy8wK+21dyXRe7QbBLuw6wG3ceJnJnLuTL"
        "279DrutySBIhEnUopSbjtMsYVzkXLSFEU5Y9dY/XW5Nlr207DpRWE+zzp6VHxWLpstpWKaEA5RT9"
        "XgCcC/jDDihjOpWI6vF4WkLweigULgdD4R/p4ZH30X1Dr6XhbK4i/OH43qSKVikJLhhGz26AEo61"
        "+Qz0roWR8RDWixtIJKP4/mUVA5EgkvvjOHEy/1FKj+XnwpHMxdipIhJH29C2o0hMVmH1KJQyxWTw"
        "FuKhKYCbaDUVOI4LwzKxOD8PAvkrMazOW1uSUH43ilCqgUYphvJyBitzKUyfLiCVBe7PPkVzp4l7"
        "dx9g+lwB5T9bePPqJTIjB4v0uqmVi4cHbx67UkFteRjRAx30mgEcym9iZz2NpRcyfAM6Om0Nruui"
        "sr2F8SNZuIQjEhl6Lj0LAY8Hcwtq6nwhStuQJB8sWOh3fTClBgIDOhj1wDAtcEFRq/5FW+shPRRF"
        "diyTYJNe4Kr1bfaJHiv0qAtBKTgX4D6CAJXAbQIhaYhyG16iIxvpwEfW0BITM75YrsJm3Ah6SnfB"
        "kCtzWmLikmabYLYAIRxO34Zp6nAs9VdX6xSVRn2lb7QWe2b3w9RxplwLy2AL8AOMIa5s3vb6gzUm"
        "+5mh1XXL0Lq2pVRVQ2z66J6fpLdaMqu6KjwUXo8XnFH0+w6k/3+mfwMAzwT87LI0qNEAAAAASUVO"
        "RK5CYII="
    ),
)

import wx
import os
import asyncore
import socket
import urllib

class Text:
    eventPrefix = "Event prefix:"
    xbmcip = "XBMC Host IP:"
    xbmchttpport = "XBMC HTTP Port:"
    zone = "XBMC Broadcast IP:"
    port = "UDP port:"
    selfXbmceventbroadcast = "Respond to Self Broadcast"
    delim = "Payload Delimiter"

class Xbmceventbroadcast:
    name="Xbmceventbroadcast"

class Server(asyncore.dispatcher):

    def __init__(self, port, selfXbmceventbroadcast,payDelim, plugin):
        self.selfXbmceventbroadcast=selfXbmceventbroadcast
        self.plugin=plugin
        self.port=port
        self.payDelim=payDelim
        asyncore.dispatcher.__init__(self)
        self.ipadd = socket.gethostbyname(socket.gethostname())
        self.create_socket(socket.AF_INET, socket.SOCK_DGRAM)
        eg.RestartAsyncore()
        self.bind(('', port))


    def handle_connect(self):
        print "XBMC Event Broadcast listener ENABLED on Local Host @ " + self.ipadd + ":" + str(self.port) + ". Response to XBMC is " + str(self.selfXbmceventbroadcast) + "."
        pass

    def handle_read(self):
        data, addr = self.recvfrom(1024)

        if (self.ipadd != addr[0]) or self.selfXbmceventbroadcast:
            data = unicode(data, 'UTF8')
            #print data
            bits = data.split(str(self.payDelim))
            commandSize=len(bits)
            if commandSize==1:
                self.plugin.TriggerEvent(bits[0])
            if commandSize==2:
                self.plugin.TriggerEvent(bits[0],bits[1])
            if commandSize>2:
                self.plugin.TriggerEvent(bits[0],bits[1:])
    def writable(self):
        return False  # we don't have anything to send !

class XbmceventbroadcastListener(eg.PluginClass):
    canMultiLoad = True
    text = Text

    def __init__(self):
        self.AddAction(self.Xbmceventbroadcast)

    def __start__(self, prefix=None, xbmcip="None", xbmchttpport=8080, zone="255.255.255.255", port=8279, selfXbmceventbroadcast=False, payDelim="&&"):
        self.info.eventPrefix = prefix
        self.xbmcip = xbmcip
        self.xbmchttpport = xbmchttpport
        self.port = port
        self.payDelim=payDelim
        self.zone = zone
        self.selfXbmceventbroadcast=selfXbmceventbroadcast

        try:
            self.server = Server(self.port, self.selfXbmceventbroadcast, self.payDelim, self)
        except socket.error, exc:
            raise self.Exception(exc[1])


    def __stop__(self):
        if self.server:
            self.server.close()
        self.server = None

    def Configure(self, prefix="XBMC-Event", xbmcip="192.168.1.1", xbmchttpport=8080, zone="224.0.0.2", port=8278, selfXbmceventbroadcast=False, payDelim="<b></b>"):
        panel = eg.ConfigPanel(self)

        editCtrl = panel.TextCtrl(prefix)
        xbmcipCtrl = panel.TextCtrl(xbmcip)
        xbmchttpportCtrl = panel.SpinIntCtrl(xbmchttpport, min=1, max=65535)
        zoneCtrl = panel.TextCtrl(zone)
        portCtrl = panel.SpinIntCtrl(port, min=1, max=65535)
        selfXbmceventbroadcastCtrl=panel.CheckBox(selfXbmceventbroadcast)
        payDelimCtrl = panel.TextCtrl(payDelim)

        panel.AddLine(self.text.eventPrefix, editCtrl)
        panel.AddLine(self.text.xbmcip, xbmcipCtrl)
        panel.AddLine(self.text.xbmchttpport, xbmchttpportCtrl)
        panel.AddLine(self.text.zone, zoneCtrl)
        panel.AddLine(self.text.port, portCtrl)

        panel.AddLine(self.text.selfXbmceventbroadcast,selfXbmceventbroadcastCtrl)
        panel.AddLine("Payload Delimiter", payDelimCtrl)

        while panel.Affirmed():
            panel.SetResult(editCtrl.GetValue(),xbmcipCtrl.GetValue(),int(xbmchttpportCtrl.GetValue()),zoneCtrl.GetValue(),int(portCtrl.GetValue()),selfXbmceventbroadcastCtrl.GetValue(), payDelimCtrl.GetValue() )
            v_header = urllib.quote("This is the Header")

            v_message = urllib.quote("This is the Message")

        host_xbmc = xbmcipCtrl.GetValue()
        port_xbmc = int(xbmchttpportCtrl.GetValue())
        udp_xbmc = int(portCtrl.GetValue())
        url_xbmc = "http://" + str(host_xbmc) + ":" + str(port_xbmc) + "/xbmcCmds/xbmcHttp?command=SetBroadcast&parameter=2;" + str(udp_xbmc) + "(Notification(" + v_header + "," + v_message + "))"
        print "str(url_xbmc)"
        try:
            urllib.urlopen(url_xbmc)
        except IOError:
            print 'Connection error'



    class Xbmceventbroadcast(eg.ActionWithStringParameter):

        def __call__(self, mesg, payload=""):
            res = self.bcastSend(mesg, payload)
            return res

        def bcastSend(self, eventString, payload=""):
            addr = (self.plugin.zone, self.plugin.port)
            UDPSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # Create socket
            UDPSock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
            if (payload==None):
                UDPSock.sendto(eg.ParseString(eventString),addr)
            else:
                UDPSock.sendto(eg.ParseString(eventString)+self.plugin.payDelim+eg.ParseString(payload),addr)
            UDPSock.close()

    def Configure(self, command="", payload=""):
        text = self.text
        panel = eg.ConfigPanel(self)

        commandCtrl = panel.TextCtrl(command)
        payloadCtrl = panel.TextCtrl(payload)

        commandlabel = panel.StaticText("Command:")
        payloadlabel = panel.StaticText("Payload:")
        panel.sizer.Add(commandlabel,0,wx.EXPAND)
        panel.sizer.Add(commandCtrl,0,wx.EXPAND)
        panel.sizer.Add((20, 20))
        panel.sizer.Add(payloadlabel,0,wx.EXPAND)
        panel.sizer.Add(payloadCtrl,0,wx.EXPAND)


        while panel.Affirmed():
            panel.SetResult(
                commandCtrl.GetValue(),
                payloadCtrl.GetValue()
            )