Hi guys,

lirc definitely doesn't work out of the box and if you get it to work it 
generates to much key events on one key press. I was a little fed up with it so 
I created a fix for lirc_input.py which adds the tweakebility of delay and 
repeat to elisa again. I guess some of you would code a little bit different, 
but it's hack and it works for me.

regards,

Stephan Roolvink

> Date: Tue, 9 Sep 2008 20:20:29 +0200
> From: [EMAIL PROTECTED]
> To: [email protected]
> Subject: Re: [Elisa] Lirc & AC3 passthrough
> 
> Matthias Saou wrote:
> > Ola Thoresen wrote :
> > 
> >> Lirc works 'out of the box' for me - Fedora 9, gnome and Elisa 5.8.
> > 
> > 'Out of the box'!? Where the heck did you get the below file from?
> > I definitely can't find it in my 'box' nor in the elisa sources! :-)
> 
> 
> 
> That's why I said 'out of the box' (in quotes).
> I think that file was generated by the script you found.
> 
> What I ment was that I did not have to play around with .lircrc or 
> /etc/lircd.conf (after I got my remote working with 
> gnome-lirc-properties in the first place).
> 
> 
> > So if I understand correctly, elisa short circuits the ~/.lircrc file?
> > Does anyone know the reason for this? Be able to some day integrate the
> > configuration utility into the UI? (then not have to overwrite
> > ~/.lircrc nor do any ugly parsing of that file)
> 
> They now have standardized the key-names.
> For fedora, there is already a lot of nice lircd.conf-files with the 
> correct names added.
> See http://fedoraproject.org/wiki/Features/BetterLIRCSupport
> 
> And work is underway upstream to fix this everywhere:
> http://thread.gmane.org/gmane.comp.hardware.lirc/6884
> 
> This makes it much easier for apps like Elisa to just bypass .lircrc and 
> use the names directly in the code.
> 
> KEY_MUTE should be the mute-key on all remotes, KEY_VOL_UP is volume up 
> and so on, so there is no need for another abstraction layer for each 
> user any more.
> 
> So I agree that it is not completely out of the box yet, but I think 
> we're getting there.
> 
> 
> 
> Rgds.
> 
> Ola (T)
> 
> 
> 
> -- 
>           _,--',   _._.--._____
>    .--.--';_'-.', ';_      _.,-'   Ola Thoresen
>   .'--'.  _.'    {`'-;_ .-.>.'
>         '-:_      )  / `' '=.      It is easier to fix Unix
>           ) >     {_/,     /~)     than to live with Windows
>           |/               `^ .'
> 

_________________________________________________________________
Express yourself instantly with MSN Messenger! Download today it's FREE!
http://messenger.msn.click-url.com/go/onm00200471ave/direct/01/
# -*- coding: utf-8 -*-
# 
# The LIRC Plugin for elisa
# 
# Copyright (C) 2008 by Benjamin Kampmann <[EMAIL PROTECTED]>
# 
# This program 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 3 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, see <http://www.gnu.org/licenses/>.
# 
# Author: Benjamin Kampmann <[EMAIL PROTECTED]>

if __name__ == '__main__':
    # import and install the glib2reactor is the first thing today in case we
    # execute directly
    from twisted.internet import glib2reactor
    glib2reactor.install()

from twisted.protocols.basic import LineReceiver
from twisted.internet.protocol import Protocol, ClientFactory
from twisted.internet.unix import Client

from elisa.core.components.input_provider import PushInputProvider
from elisa.core.input_event import InputEvent, EventValue, \
        EventSource, EventType

from twisted.internet import reactor, defer

import os
import pkg_resources
import threading
import time

class NoMappingsFound(Exception):
    """
    Raised when the mappings file is not found or if it is empty.
    """

class CallbackProtocol(LineReceiver):
    delimiter = "\n"

    def __init__(self, callback):
        self.callback = callback

    def lineReceived(self, line):
        args = line.split()
        self.callback(*args)

class CallbackConnector(ClientFactory):

    def __init__(self, callback, lostback = None):
        self.callback = callback
        self.lostback = lostback

    def buildProtocol(self, addr):
        return CallbackProtocol(self.callback)

    def connectionLost(self, *args):
        if self.lostback:
            self.lostback()

class LircInput(PushInputProvider):

    default_config = {'input_map' : 'streamzap.map',
                      'device' : '/dev/lircd',
                      'repeat' : '1',
                      'delay' : '0.15'}

    config_doc = {'input_map' : 'Path to the file containing the lirc' \
                  'mapping', 'device' : 'the lirc deamon device'\
                  'repeat', 'number' : 'number of imput event to ignore after initial event'\
                  'delay', 'seconds' : 'seconds of delay between events'}

    repeat_timer = None
    repeat_interval = False
    repeatc = 1
    delay = 0.15

    def __init__(self):
        super(LircInput, self).__init__()
        self.mappings = {}
        self._client = None

    def initialize(self):
        dfr = super(LircInput, self).initialize()

        def initialized(result):
            input_map_file = self.config.get('input_map')
            self.repeatc = self.config.get('repeat')
            self.delay = self.config.get('delay')
            filename = os.path.basename(input_map_file)
            data = ""
            if not os.path.isabs(input_map_file):
                # let's try to use lirc config shipped with the plugin
                path = "map_files/%s" % filename
                if pkg_resources.resource_exists(self.__module__, path):
                    lirc_config = pkg_resources.resource_filename(self.__module__,
                                                                  path)
                    self.info("Using %s lirc map file", lirc_config)
                    data = open(lirc_config).read()
                else:
                    msg = "Given InputMap '%s' not found" % input_map_file
                    return defer.fail(NoMappingsFound(msg))
            else:
                # the user configured an absolute lirc config file location
                self.info("Using %s lirc map file", input_map_file)
                try:
                    data = open(input_map_file).read()
                except IOError:
                    msg = "Given InputMap '%s' not found" % input_map_file
                    return defer.fail(NoMappingsFound(msg))

            if data:
                self._parse_to_mapping(data)

            if not len(self.mappings):
                msg = "No Mappings found in %s" % input_map_file
                return defer.fail(NoMappingsFound(msg))

            self._setup_client()
            return self

        dfr.addCallback(initialized)
        return dfr

    def _setup_client(self):
        connector = CallbackConnector(self._got_event)
        self._client = Client(self.config.get('device'), connector,
                              reactor=reactor)

    def repeat_ok(self):
        self.repeat_interval = False
        self.repeat_timer = None


    def _got_event(self, hex_key, repeat, key_value, remote):
        repeat = int(repeat, 16)
        if not self.repeat_interval and repeat>self.repeatc or repeat==0:
            if repeat==0 and not self.repeat_timer==None:
                self.repeat_timer.cancel()
            self.repeat_interval = True
            self.repeat_timer = threading.Timer(self.delay,self.repeat_ok)
            self.repeat_timer.start()
            if '*' in self.mappings:
                # ignore remote name provided by LIRC and take first remote registered in the
                # mappings
                mappings = self.mappings[self.mappings.keys()[0]]
            elif remote not in self.mappings:
                self.debug("Unknown remote %s", remote)
                return
            else:
                mappings = self.mappings[remote]

            if hex_key in mappings:
                value = mappings[hex_key]
            elif key_value in mappings:
                value = mappings[key_value]
            else:
                self.debug("Can't find '%s' nor '%s' in mappings for '%s'",
                       hex_key, key_value, remote)
                return

            evt = InputEvent(EventSource.REMOTE, EventType.OTHER, value)
            self.input_manager.process_event(evt)

    def _parse_to_mapping(self, data):
        """
        parse the lirc input mappings
        """
        for line in data.split('\n'):
            line = line.strip()
            splitted = line.split()
            if line.startswith('#') or len(splitted) != 3:
                self.info("Skipping %s", line)
                continue

            remote, key, elisa_key = splitted

            if not hasattr(EventValue, elisa_key):
                self.warning("Don't know key '%s'.", elisa_key)
                continue

            event_key = getattr(EventValue, elisa_key)

            if not remote in self.mappings:
                self.mappings[remote] = {}

            self.debug("Adding %s as mapped to %s for the remote %s" %
                    (event_key, key, remote))

            self.mappings[remote][key] = event_key

if __name__ == '__main__':

    res = None

    def setup_done(resource):
        global res
        res = resource
        print """

        You are now in the interactive tests. You have the DaapDebug object
        at *daap_debug* and you can play around with its get_* methods. It is
        holding the connection to your server. The login already worked :) .

        """

    def setup():
        config = LircInput.default_config
        dfr = LircInput.create(config)
        dfr.addCallback(setup_done)

    reactor.callWhenRunning(setup)
    reactor.simulate()
    reactor.startRunning()
    import IPython
    IPython.Shell.IPShellGTK([], locals()).mainloop()

    

Reply via email to