
name = "LIRC Client"
kind = "remote"
version = "0.1.0"
author = "Chris Strutton"
description = """<rst>
Plugin for sending and receiving LIRC eventstrings. Generates EventGhost events 
based on data received from the LIRC-server.  This code is an adaptation
of the work originally done by Jinxdone

For most setups only a slight adjustment of the "Timeout for enduring events" 
value is recommended.

*The configurable options are:*

- **Target Host**
  Host and port of the LIRC server. For WinLirc running on localhost 
  the default settings should be fine (127.0.0.1:8765)

- **Auto-retry settings**
  If the connection is lost or can not be established, try to (re)connect
  a number of times with a set interval between retries. Set either 
  value to 0 to disable.

- **List remotes from the LIRC server**
  Attempts to send a 'LIST' command to the server when connecting, 
  which tries to fetch information about configured remotes. 
  Uncheck if your server does not support this command.

- **Only use the first event**
  Only the first event from LIRC per keypress is processed, all subsequent events 
  from the same keypress will be discarded. (Effectively also disables the enduring 
  event behaviour)

- **Add remote-name**
  Adds the remote-name into the eventstring, use it if you want to distinguish 
  between multiple remotes.

- **Add repeat-tag**
  Adds "++" into the eventstring when the event in question is a repeating event.

- **Ignoretime after first event**
  You can specify a time during which after a first event any repeat-events are 
  discarded. The value is in milliseconds, set to 0 to disable. Useful if you 
  have problems with buttons you want only to trigger once and  not get multiple 
  events by accident.

- **Timeout for enduring events**
  Sets the timeout value for enduring events. If you increase it it will work 
  more reliably, but it adds 'lag' to the end of each event. You will get best 
  results when set as low as possible, however a value too low will tend to stop 
  your events abruptly and then immediately start a new one.
  (default = 200, recommended between 125-400, depending on your setup)
"""
###
########################### END PLUGIN DESCRIPTION ###########################


eg.RegisterPlugin(
    name=name, 
    description=description, 
    author=author, 
    version=version, 
    kind=kind,
    canMultiLoad=True,
    url = "http://www.eventghost.org/forum/viewtopic.php?t=219",
    icon = (
      "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBI"
      "WXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1wEDFyY0FznCDQAAAP9JREFUeNqVUrGRhDAMXP3Qh9sg"
      "QzEV0I3tjAqIKUVk0AFkVOAW9AFvY47zHa8Zz2rGXmm1MqEQzjnFl3DOUVUiW2uLRO99yt8WsNZi"
      "miY8iZ/SBYskZG6yI5d3VXlACwYgAkAONczN7Vn1RGbTNP8fIY1y6eo/K6jrOuUip4nRTxH+w9MH"
      "iknXdej7HgAwjqPiYRAAtG2LYRiw7zuY+UJW1Y9/oXolqyqICBGJCCJykc3MpwchBBhjYIw5JBEl"
      "jEVeSflXRl3XUabqkSSMR1WhqvDeo23bi9kVAGzbVuy+rivF+2VZEELAPM+3Ldxmz1ZLueycHAvc"
      "bM6K0Lc1/gLZfImV1GmwgAAAAABJRU5ErkJggg=="
    )
)

import socket, asyncore, time, threading
import LircChat

############################## BEGIN TEXT CLASS ##############################
###
class Text:
    version = version
    title = "LIRC Client plugin v" + version + " by Chris Strutton"
    host = "Host:"
    port = "Port:"
    hosttitle = "Target Host"
    onlyfirst = "Only use the first event"
    addremote = "Add remote-name"
    addrepeat = "Add repeat-tag"
    ignoretime = "Ignoretime after first event (ms)"
    timeout = "Timeout for enduring events (ms)"
    attemptlist = "List remotes from the LIRC server"
    retrytitle = "Auto-retry connection if disconnected"
    maxretries = "Retries"
    retryinterval = "Interval (s)"
    noremotesfound = "No remotes found!"
    noremotesfoundtip = "You can disable sending LIST on connect if it does not work on your setup"
    disconnected = "Disconnected from the LIRC server!"
    disconnectedtip = "Restart the plugin to manually reconnect (Right-click -> Disable, Enable)"
    reconnect = "Attempting to reconnect to the LIRC-server"
    reconnectinit = "Attempting to reconnect %i times with %i seconds between attempts"
    reconnectgiveup = "Giving up reconnection after %i failed retries"
    reconnected = "Auto-connected successfully after %i attempts"
    startupexception = "Could not connect to the LIRC server!"
    erroneousresponse = "Received an erroneous response from the LIRC-server"
    malformedresponse = "Received an malformed response from the LIRC-server"
    suspendconnection = "Closing the connection to the LIRC-server.."
    resumeconnection = "Resuming the connection to the LIRC-server.."
###
############################### END TEXT CLASS ###############################

import asyncore, asynchat, socket
import string,time


### The EventGhost classes and functions are over here..
class Lirc(eg.RawReceiverPlugin):
    text = Text

    class LircClientError(Exception):
        "LIRC Client Error:"

    def __init__(self):
        eg.RawReceiverPlugin.__init__(self)
        self.AddAction(self.Send)

    def __start__(
        self, host, port, onlyfirst, addremote, 
        addrepeat, ignoretime, timeout,  attemptlist, maxretries, retryinterval
    ):
        text = self.text
        self.port = port
        self.host = host
        self.onlyfirst = onlyfirst
        self.addremote = addremote
        self.addrepeat = addrepeat
        self.timeout = timeout / 1000.0
        self.ignoretime = ignoretime
        self.attemptlist = attemptlist
        self.maxretries = maxretries
        self.currentattempt = 0
        self.retryinterval = retryinterval
        self.Send.remotes = []
        self.Send.remotelist = []
        self.InitConnection()
        eg.RestartAsyncore()
        self.Chat.GetList()
        
        
    
        
        # Test if connection is formed succesfully, if not trigger retry
##        if not self.CheckConnection():
##           self.ReconnectTimer()

    def __stop__(self):
        if self.Chat:
            self.Chat.gracefulclose = 1
            self.Chat.handle_close()
        self.Chat = None

    def InitConnection(self):
        self.Chat = LircChat.LircChat(self.host, self.port,ButtonCallBack = self.FireEvent)
        while not self.Chat.Connected:
            eg.Print ("Waiting for Chat.Connected")
            asyncore.poll()


    def HandlePrint(self, msg):
        print("LIRC Client: %s" % msg)

      
    def HandleWarning(self, msg):
        self.PrintError("LIRC Client: %s" % msg)

    def HandleException(self, msg):
        raise self.LircClientError(msg)

    def OnComputerSuspend(self, suspendType):
        if self.Chat:
            self.Chat.handle_close()
            self.HandleWarning(self.text.suspendconnection)
        self.Chat = None

    def OnComputerResume(self, suspendType):
        self.HandleWarning(self.text.resumeconnection)
        self.InitConnection()
##        # Test if connection is formed succesfully, if not trigger retry
##        if not self.CheckConnection():
##           self.ReconnectTimer()


    def FireEvent(self):
        # shape the eventstring the way the user wants it
        # (add remote name, add is-repeat-tag, discard repeat events..)
        if self.Chat.GetCodeCount():
            code = self.Chat.GetNextCode()
        if self.addremote:
            EgEvent = code[3] + ":" + code[2]
        else:
            EgEvent = code[2]

        if code[1] == "00":
            if not self.onlyfirst:
                if self.ignoretime:
                    self.recvtime = time.time()
            self.TriggerEvent(EgEvent)
        else:
            if self.onlyfirst:
                return
            if self.addrepeat:
                EgEvent = EgEvent + "++"
            if self.ignoretime:
                if self.mscounter():
                    self.TriggerEvent(EgEvent)
            else:
                self.TriggerEvent(EgEvent)
    def mscounter(self):
        if time.time()*1000 - self.recvtime*1000 < self.ignoretime:
            return False
        else:
            return True








##    def CheckConnection(self):
##        if self.maxretries == 0 or self.retryinterval == 0:
##           return True
##        time.sleep(0.05)
##        if not self.reader:
##           return False
##        try:
##           self.reader.sbuffer = 'VERSION\n'
##        except:
##           return False
##        time.sleep(0.05)
##        asyncore.poll()
##        if not self.reader.connected:
##           return False
##        return True
##
##    def ReconnectTimer(self):
##        # If the connection drops try to reconnect n times with a pre-set
##        # time between the attempts. Drop conneciton attempts after n failures
##        if self.maxretries == 0 or self.retryinterval == 0:
##           return
##        self.reconnecttimer = threading.Timer(self.retryinterval, self.Reconnect)
##        if self.currentattempt == 0:
##           self.HandlePrint(self.text.reconnectinit % (self.maxretries, self.retryinterval))
##        if self.currentattempt < self.maxretries:
##           self.reconnecttimer.start()
##        else:
##           self.HandlePrint(self.text.reconnectgiveup % self.maxretries)
##
##    def Reconnect(self):
##        # First check if we are connected, if not then retry and check immediately again
##        # if we got connected successfully (asyncore wont seem to update connected status
##        # unless some traffic is sent/received so put one newline in the send buffer and poll it)
##        if self.CheckConnection():
##           return
##        else:
##           self.currentattempt += 1
##           self.InitConnection()
##           if self.CheckConnection():
##              self.HandlePrint(self.text.reconnected % (self.currentattempt - 1))           
##           else:
##              self.ReconnectTimer()

    def Configure(
        self,
        host="127.0.0.1",
        port=8765,
        onlyfirst = False,
        addremote = False,
        addrepeat = False,
        ignoretime = 0,
        timeout = 200,
        attemptlist = True,
        maxretries = 10,
        retryinterval = 30,
    ):
        text = self.text
        panel = eg.ConfigPanel(self)
        TitleText = wx.StaticText(panel, -1, text.title, style=wx.ALIGN_CENTER)
        HostText = wx.StaticText(panel, -1, text.host)
        HostCtrl = wx.TextCtrl(panel, -1, host)
        PortText = wx.StaticText(panel, -1, text.port)
        PortCtrl = eg.SpinIntCtrl(panel, -1, port, max=65535)
        AttemptListCtrl = wx.CheckBox(panel, -1, text.attemptlist)
        AttemptListCtrl.SetValue(attemptlist)

        RetryTitle = wx.StaticText(panel, -1, text.retrytitle)
        MaxRetriesText = wx.StaticText(panel, -1, text.maxretries)
        MaxRetriesCtrl = eg.SpinIntCtrl(panel, -1, maxretries)
        RetryIntervalText = wx.StaticText(panel, -1, text.retryinterval)
        RetryIntervalCtrl = eg.SpinIntCtrl(panel, -1, retryinterval, max=65535)
        RetryBox = wx.BoxSizer()
        RetryBox.Add(MaxRetriesCtrl, 0, wx.ALL, 2)
        RetryBox.Add(MaxRetriesText, 0, wx.ALL, 5)
        RetryBox.Add(RetryIntervalCtrl, 0, wx.ALL, 2)
        RetryBox.Add(RetryIntervalText, 0, wx.ALL, 5)

        HostSizer = wx.FlexGridSizer(cols=3)
        HostSizer.Add(HostText, 0, wx.ALL, 5)
        HostSizer.Add(HostCtrl, 0, wx.ALL, 3)
        HostSizer.Add(RetryTitle, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 54)
        HostSizer.Add(PortText, 0, wx.ALL, 5)
        HostSizer.Add(PortCtrl, 0, wx.ALL, 3)
        HostSizer.Add(RetryBox, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 50)

        HostBox = wx.StaticBox(panel, -1, text.hosttitle)
        shbSizer = wx.StaticBoxSizer(HostBox)
        shbSizer.Add(HostSizer, 0, wx.ALIGN_CENTER|wx.ALL, 5)

        OnlyFirstCtrl = wx.CheckBox(panel, -1, text.onlyfirst)
        OnlyFirstCtrl.SetValue(onlyfirst)
        AddRemoteCtrl = wx.CheckBox(panel, -1, text.addremote)
        AddRemoteCtrl.SetValue(addremote)
        AddRepeatCtrl = wx.CheckBox(panel, -1, text.addrepeat)
        AddRepeatCtrl.SetValue(addrepeat)
        IgnoreTimeText = wx.StaticText(panel, -1, text.ignoretime)
        IgnoreTimeCtrl = eg.SpinIntCtrl(panel, -1, ignoretime, max=60000)
        TimeoutText = wx.StaticText(panel, -1, text.timeout)
        TimeoutCtrl = eg.SpinIntCtrl(panel, -1, timeout, max=10000)

        IgnoreBox = wx.BoxSizer()
        IgnoreBox.Add(IgnoreTimeCtrl, 0, wx.ALL, 2)
        IgnoreBox.Add(IgnoreTimeText, 0, wx.ALL, 5)

        TimeoutBox = wx.BoxSizer()
        TimeoutBox.Add(TimeoutCtrl, 0, wx.ALL, 2)
        TimeoutBox.Add(TimeoutText, 0, wx.ALL, 5)

        FirstLineBox = wx.BoxSizer()
        FirstLineBox.Add(OnlyFirstCtrl, 0, wx.ALL, 5)
        FirstLineBox.Add(AttemptListCtrl, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 120)

        BoxSizer = wx.BoxSizer(wx.VERTICAL)
        BoxSizer.Add(FirstLineBox, 0, wx.ALL, 0)
        BoxSizer.Add(AddRemoteCtrl, 0, wx.ALL, 5)
        BoxSizer.Add(AddRepeatCtrl, 0, wx.ALL, 5)
        BoxSizer.Add(IgnoreBox, 0, wx.ALL, 3)
        BoxSizer.Add(TimeoutBox, 0, wx.ALL, 3)

        panel.sizer.Add(TitleText, 0, wx.EXPAND)
        panel.sizer.Add(shbSizer, 0, wx.EXPAND)
        panel.sizer.Add(BoxSizer, 0,)


        while panel.Affirmed():
            panel.SetResult(
                HostCtrl.GetValue(), 
                PortCtrl.GetValue(), 
                OnlyFirstCtrl.GetValue(), 
                AddRemoteCtrl.GetValue(), 
                AddRepeatCtrl.GetValue(), 
                IgnoreTimeCtrl.GetValue(),
                TimeoutCtrl.GetValue(),
                AttemptListCtrl.GetValue(),
                MaxRetriesCtrl.GetValue(),
                RetryIntervalCtrl.GetValue()
            )



# Action class for sending strings to the server
    class Send(eg.ActionClass):


########################## BEGIN ACTION DESCRIPTION ##########################
###
        name = "Send Event"
        description = """<rst>
Sends an eventstring to the LIRC-server for transmitting IR signals.

The plugin can fetch information about the available remotes and actions 
from the LIRC-server with the LIST command. If no information has been 
available or some other problem occurred the Remote and Action fields will 
have "N/A" values in them.

*The configurable options are:*

- **Command**
  Available commands are SEND_ONCE, SEND_START and SEND_STOP.
  
- **Remote**
  A List of the available remotes.
  
- **Action**
  A List of the actions available with the selected remote.

- **Repeat**
  Tells the LIRC-server to repeat the IR code n times.
  Only valid for the SEND_ONCE command.

- **Event String**
  The actual string to send, you can use either the Command selection or just 
  type in the string you want to send by hand. The actual string to send is 
  always what is in this field regardless of what is selected in the fields above.

More information at `the LIRC documentation`__

__ http://www.lirc.org/html/technical.html#applications
"""
###
########################### END ACTION DESCRIPTION ###########################


############################## BEGIN TEXT CLASS ##############################
###
        class Text:
            selectiontitle = "Command selection"
            actcmd = "Command"
            actremote = "Remote"
            actaction = "Action"
            actrepeat = "Repeat"
            actstring = "Event String:"
            acthelp = (
               "You may use the fields in the Command selection to help form a string to send.\n"
               "Or simply just type in the string directly into the field below."
            )
            acterrormsg = "Error while sending event! Send buffer is missing!"
###
############################### END TEXT CLASS ###############################


        text = Text

        class LircClientError(Exception):
            "LIRC Client Error:"

# The workhorse method.. (how tiny)!
        def __call__(self, msg):
            eg.Print("call: ",msg)
            self.plugin.Chat.SendDirective(directive = msg)
##            while self.plugin.Chat.BusyFlag:
##                asyncore.loop(count=1)

        def UpdateRemoteList(self):
            eg.Print("Update Remote List")
            self.remotes = self.plugin.Chat.GetList()
            eg.Print(self.remotes)
            self.remotelist = []
            for remote in self.remotes:
                self.remotelist.append(remote[0])
                eg.Print(self.remotelist[-1])

        def Configure(self, actionStr=""):
            text = self.text
            actionParam = "0"
            self.UpdateRemoteList()
            remotes = self.remotes
            remotelist = self.remotelist


            def OnCmdChoice(event):
               UpdateActionText()


            def OnRemoteChoice(event):
                actionCtrl.SetItems(remotes[remoteCtrl.GetSelection()][1])
                actionCtrl.SetSelection(0)
                UpdateActionText()

            def OnActionChoice(event):
                UpdateActionText()

            def OnRepeatSpin(event):
                UpdateActionText()

            def UpdateActionText():
                # Add an empty space at the end of the string to send, atleast
                # WinLirc seems to require it in the case the repeat value is omitted
                newstr = "%s %s %s" % (cmdlist[cmdCtrl.GetSelection()],
                                       remotelist[remoteCtrl.GetSelection()],
                                       remotes[remoteCtrl.GetSelection()][1][actionCtrl.GetSelection()])
                if cmdCtrl.GetSelection() == 0:
                   if repeatCtrl.GetValue() != 0:
                      newstr = "%s %s" % (newstr,
                                          str(repeatCtrl.GetValue()))
                textCtrl.SetValue(newstr)

            def UpdateCtrl(string, list, control):
                i = 0
                for item in list:
                   if string == item:
                      control.SetSelection(i)
                      return True
                   else:
                      i += 1
                return False

            def IsInt(str):
               try:
                  num = int(str)
               except ValueError:
                  return 0
               return num

            panel = eg.ConfigPanel(self)

            cmdlist = ["SEND_ONCE","SEND_START","SEND_STOP"]
            cmdCtrl = wx.Choice(panel, -1, choices=cmdlist)
            cmdCtrl.SetSelection(0)
            cmdText = wx.StaticText(panel, -1, text.actcmd)

            remoteCtrl = wx.Choice(panel, -1, choices=remotelist)
            remoteCtrl.SetSelection(0)
            remoteText = wx.StaticText(panel, -1, text.actremote)

            actionCtrl = wx.Choice(panel, -1, choices=remotes[0][1])  ##[1]
            actionCtrl.SetSelection(0)
            actionText = wx.StaticText(panel, -1, text.actaction)

            repeatCtrl = eg.SpinIntCtrl(panel, -1, actionParam, max=600)
            repeatText = wx.StaticText(panel, -1, text.actrepeat)

            stringText = wx.StaticText(panel, -1, text.actstring)
            textCtrl = wx.TextCtrl(panel, -1, actionStr)
            actionhelpText = wx.StaticText(panel, -1, text.acthelp)

            SelectionSizer = wx.FlexGridSizer(rows=2)
            SelectionSizer.Add(cmdText, 0, wx.LEFT, 5)
            SelectionSizer.Add(remoteText, 0, wx.LEFT, 5)
            SelectionSizer.Add(actionText, 0, wx.LEFT, 5)
            SelectionSizer.Add(repeatText, 0, wx.LEFT, 5)
            SelectionSizer.Add(cmdCtrl, 0, wx.ALL, 3)
            SelectionSizer.Add(remoteCtrl, 0, wx.ALL, 3)
            SelectionSizer.Add(actionCtrl, 0, wx.ALL, 3)
            SelectionSizer.Add(repeatCtrl, 0, wx.ALL, 3)

            SelectionBox = wx.StaticBox(panel, -1, text.selectiontitle)
            ssbSizer = wx.StaticBoxSizer(SelectionBox)
            ssbSizer.Add(SelectionSizer, 0, wx.ALIGN_CENTER|wx.ALL, 5)

            BoxSizer = wx.BoxSizer(wx.HORIZONTAL)
            BoxSizer.Add(stringText, 0, wx.ALL, 5)
            BoxSizer.Add(textCtrl, 1, wx.EXPAND)

            panel.sizer.Add(ssbSizer, 0, wx.EXPAND)
            panel.sizer.Add(actionhelpText, 0, wx.ALIGN_LEFT|wx.ALL, 10)
            panel.sizer.Add(BoxSizer, 0, wx.EXPAND|wx.ALL, 5)

            cmdCtrl.Bind(wx.EVT_CHOICE, OnCmdChoice)
            remoteCtrl.Bind(wx.EVT_CHOICE, OnRemoteChoice)
            actionCtrl.Bind(wx.EVT_CHOICE, OnActionChoice)
            repeatCtrl.Bind(eg.EVT_VALUE_CHANGED, OnRepeatSpin)

            def UpdateControls():
                items = actionStr.split()
                if len(items) >= 3:
                   if UpdateCtrl(items[0], cmdlist, cmdCtrl):
                      if UpdateCtrl(items[1], remotelist, remoteCtrl):
                         actionCtrl.SetItems(remotes[remoteCtrl.GetSelection()][1])
                         UpdateCtrl(items[2], remotes[remoteCtrl.GetSelection()][1], actionCtrl)
                         if len(items) >= 4:
                            repeat = IsInt(items[3])
                            if 0 < repeat <= 600:
                               repeatCtrl.SetValue(repeat)

            UpdateControls()

            while panel.Affirmed():
                panel.SetResult(textCtrl.GetValue())
                eg.Print(textCtrl.GetValue())






##class Lirc_Reader():
##    text = Text
##
##    ### Initializing all the variables and open the tcp connection..
##    ###
##    def __init__(
##        self, host,    port,    handler, onlyfirst,
##        addremote, addrepeat, ignoretime
##    ):
##        self.handler = handler
##        self.onlyfirst = onlyfirst
##        self.addremote = addremote
##        self.addrepeat = addrepeat
##        self.ignoretime = ignoretime
####        self.sbuffer = ""
##        self.Chat = Lirc_Chat(host,port)
##        eg.RestartAsyncore()
##
####        self.buffer = ""
####        self.delimeter = ''
####        self.receivedresponse = 0
##        self.gracefulclose = 0
##
##    ### Some helper functions..
##    ###
##
##    ### Tell asyncore to monitor when we can send our data
##    ### when there is data in our send-buffer.
##    ###
####    def writable(self):
####        return (len(self.sbuffer) > 0)
##
##    ### Sends data from the buffer when called
####    def handle_write(self):
####        sent = self.send(self.sbuffer)
####        self.sbuffer = self.sbuffer[sent:]
##
##    ### This will be run if the tcp connection is disconnected
##    ### or if we want to close it ourselves.
##    ###
####    def handle_close(self):
####        if self.gracefulclose:
####           #eg.actionThread.Call(self.handler.HandlePrint, self.text.disconnected)
####           self.gracefulclose = 0
####        else:
####           eg.actionThread.Call(self.handler.HandleWarning, self.text.disconnected)
####           self.handler.ReconnectTimer()
####        self.handler.reader = None
####        self.close()
##
##
##    ### This will be run if theres a problem opening the connection
##    ###
##    def handle_expt(self):
##        self.handler.reader = None
##        self.close()
##        eg.actionThread.Call(self.handler.HandleWarning, self.text.startupexception)
##
##    ### This gets run whenever asyncore detects there is data waiting
##    ### for us to be read at the socket, so this is where it's all at..
##    ###
##    def handle_read(self):
##        # Append data from the socket onto a buffer
##        self.buffer += self.recv(4096)
##        # Attempt to detect delimeter used..
##        if self.delimeter == '':
##            if self.buffer.count('\r\n'):
##                self.delimeter = '\r\n'
##            elif self.buffer.count('\n'):
##                self.delimeter = '\n'
##            elif self.buffer.count('\r'):
##                self.delimeter = '\r'
##            else:
##                self.delimeter = '\r\n'
##        # (if theres anything on the right of the last linebreak, it must be
##        #  some incomplete data caused by tcp/ip fragmenting our strings..)
##        # hopefully the rest of it will be there on the next run..
##        self.events = self.buffer.split(self.delimeter)
##        self.buffer = self.events.pop()
##        eg.Print(self.events)
##        
##
##
##        # loop through all the received events, incase there are
##        # more than one to be processed
##        #
##        # skip processing any listings or error messages.. (BEGIN -> END messages)
##        i = -1
##        skipit = 0
##        for self.event in self.events:
##            eg.Print(self.event, " ", str(len(self.event)))
##            i += 1
##            if skipit == 1:
##               if self.event == "END":
##                  skipit = 0
##               continue
##
##            # If we receive BEGIN it may be a response to some of the commands
##            # we sent.. so parse it and data following it for useful information
##            if self.event == "BEGIN":
##               eg.Print("self.event = BEGIN")
##               skipit = 1
##               try:
##                  # If our input is is BEGIN,<any>,ERROR
##                  if self.events[i + 2] == "ERROR":
##                     self.receivedresponse = 1
##                     if len(self.events) > int(self.events[i + 4]) + 4:
##                        eg.actionThread.Call(self.handler.HandleWarning, self.text.erroneousresponse + \
##                        "\nMessage data: " + str(self.events[i + 5:i + int(self.events[i + 4]) + 5]))
##                     else:
##                        eg.actionThread.Call(self.handler.HandleWarning, self.text.erroneousresponse)
##                  # If our input is is BEGIN,LIST,SUCCESS
##                  if [self.events[i + 1], self.events[i + 2]] == ["LIST","SUCCESS"]:
##                     if len(self.events) > int(self.events[i + 4]) + 4:
##                        self.handler.Send.remotelist = self.events[i + 5:(int(self.events[i + 4]) + 5)]
##                        for remote in self.handler.Send.remotelist:
##                           self.sbuffer += "LIST " + remote + "\n"
##
##                  else:
##                     # If our input is BEGIN,LIST <remote>,SUCCESS
##                     if [self.events[i + 1].split()[0], self.events[i + 2]] == ["LIST","SUCCESS"]:
##                        self.remote = self.events[i + 1].split()[1]
##                        if self.remote != "":
##
##                           # Sanity check.. if there is not enough data skip it..
##                           if len(self.events) > int(self.events[i + 4]) + 4:
##                              self.checknum = 0
##                              self.checkmatch = 0
##
##                              # Check if we want to update an old one or if we have a new remote list
##                              for self.check in self.handler.Send.remotes:
##                                 # Flush out any N/A remotes (config dialog has been opened before getting a listing)
##                                 if self.check[0] == 'N/A':
##                                    self.handler.Send.remotes = []
##                                 if self.remote == self.check[0]:
##                                    self.handler.Send.remotes[self.checknum] = [
##                                        self.remote,
##                                        self.events[i + 5:(int(self.events[i + 4]) + i + 5)]
##                                    ]
##                                    self.checkmatch = 1
##                                 self.checknum += 1
##                              if self.checkmatch == 0:
##                                 self.handler.Send.remotes.append(
##                                     [
##                                         self.remote, 
##                                         self.events[i + 5:(int(self.events[i + 4]) + i + 5)]
##                                     ]
##                                 )
##               except IndexError:
##                  self.receivedresponse = 1
##                  eg.Print("Exception called")
##                  eg.actionThread.Call(self.handler.HandleWarning, self.text.malformedresponse)
##
##            # split a single event into atoms
##            self.event = self.event.split()
##            # some checking never hurts..
##            if len(self.event) != 4: continue
##
##            # shape the eventstring the way the user wants it
##            # (add remote name, add is-repeat-tag, discard repeat events..)
##            if self.addremote:
##                self.egevent = self.event[3] + ":" + self.event[2]
##            else:
##                self.egevent = self.event[2]
##
##            if self.event[1] == "00":
##                if not self.onlyfirst:
##                    if self.ignoretime:
##                        self.recvtime = time.time()
##                self.handler.TriggerEvent(self.egevent)
##            else:
##                if self.onlyfirst:
##                    break
##                if self.addrepeat:
##                    self.egevent = self.egevent + "++"
##                if self.ignoretime:
##                    if self.mscounter():
##                        self.handler.TriggerEvent(self.egevent)
##                else:
##                    self.handler.TriggerEvent(self.egevent)
##
##
##    ### mandatory, but we won't need these..
##    ###
##    def handle_connect(self):
##       pass
