Package elisa :: Package plugins :: Package bad :: Package bluetooth_plugin :: Module bluetooth_input
[hide private]
[frames] | no frames]

Source Code for Module elisa.plugins.bad.bluetooth_plugin.bluetooth_input

  1  # -*- coding: utf-8 -*- 
  2  # Elisa - Home multimedia server 
  3  # Copyright (C) 2006-2008 Fluendo Embedded S.L. (www.fluendo.com). 
  4  # All rights reserved. 
  5  # 
  6  # This file is available under one of two license agreements. 
  7  # 
  8  # This file is licensed under the GPL version 3. 
  9  # See "LICENSE.GPL" in the root of this distribution including a special 
 10  # exception to use Elisa with Fluendo's plugins. 
 11  # 
 12  # The GPL part of Elisa is also available under a commercial licensing 
 13  # agreement from Fluendo. 
 14  # See "LICENSE.Elisa" in the root directory of this distribution package 
 15  # for details on that license. 
 16   
 17  __maintainer__ = 'Florian Boucault <florian@fluendo.com>' 
 18   
 19  from elisa.base_components.input_provider import PushInputProvider 
 20  from elisa.core.input_event import * 
 21   
 22  import socket, errno 
 23  import bluetooth as _bt 
 24   
 25  try: 
 26      import fcntl 
 27  except ImportError: 
 28      fcntl = None 
 29   
 30  from twisted.internet.protocol import Protocol, ServerFactory 
 31  from twisted.internet import reactor, tcp 
 32   
33 -class NormalizedBluetoothSocket(_bt.BluetoothSocket):
34 """Wrapper class for the bluez sockets to make them behave more 35 like the objects they pretend to be. Plus, it works around some 36 bugs.""" 37
38 - def recv(self, *args, **kw):
39 print "Anything" 40 try: 41 return _bt.BluetoothSocket.recv(self, *args, **kw) 42 except _bt.BluetoothError, bterr: 43 # bug in python-bluez, don't ask... 44 import code 45 code.interact(local=locals()) 46 if bterr.args == ("(104, 'Connection reset by peer')",): 47 raise socket.error(errno.ECONNRESET, 48 'Connection reset by peer') 49 raise socket.error(*(bterr.args))
50
51 - def accept(self, *args, **kw):
52 try: 53 return _bt.BluetoothSocket.accept(self, *args, **kw) 54 except _bt.BluetoothError, bterr: 55 # bug in python-bluez, don't ask... 56 if bterr.args == ("(11, 'Resource temporarily unavailable')",): 57 raise socket.error(errno.EWOULDBLOCK, 58 'Resource temporarily unavailable') 59 raise socket.error(*(bterr.args))
60 61
62 -class ElisaBTPort(tcp.Port):
63 """An Elisa-specific Bluetooth Port class.""" 64 addressFamily = socket.AF_BLUETOOTH 65 socketType = socket.SOCK_STREAM 66 uuid = "94f39d29-7d6d-437d-973b-fba39e49d4ee" 67
68 - def createInternetSocket(self):
69 #s = _bt.BluetoothSocket(_bt.RFCOMM) 70 s = NormalizedBluetoothSocket(_bt.RFCOMM) 71 s.setblocking(0) 72 if fcntl and hasattr(fcntl, 'FD_CLOEXEC'): 73 old = fcntl.fcntl(s.fileno(), fcntl.F_GETFD) 74 fcntl.fcntl(s.fileno(), fcntl.F_SETFD, old | fcntl.FD_CLOEXEC) 75 s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 76 77 return s
78
79 - def startReading(self):
80 _bt.advertise_service(self.socket, "Elisa", service_id=self.uuid, 81 service_classes=[self.uuid, 82 _bt.SERIAL_PORT_CLASS], 83 profiles=[_bt.SERIAL_PORT_PROFILE], 84 # protocols = [ OBEX_UUID ] 85 ) 86 #print ("Waiting for connection on RFCOMM channel %d" % 87 # self._realPortNumber) 88 self.numberAccepts = 1 89 tcp.Port.startReading(self)
90 91
92 -class ElisaBTFactory(ServerFactory):
93 - def __init__(self, prot_instance):
94 self._protocol_instance = prot_instance
95
96 - def buildProtocol(self, addr):
97 p = self._protocol_instance 98 # FIXME: possible circular references, add proper cleanup 99 p.factory = self 100 return p
101
102 -class BluetoothInput(PushInputProvider, Protocol):
103 action_map = {'14': EventAction.GO_LEFT, 104 '15': EventAction.GO_RIGHT, 105 '16': EventAction.GO_UP, 106 '17': EventAction.GO_DOWN, 107 '167': EventAction.OK, 108 '196': EventAction.MENU} 109 110 type_map = {'1': EventType.KEY_DOWN, 111 '2': EventType.KEY_UP} 112 # '3': EventType.KEY_DOWN} 113
114 - def __init__(self):
115 PushInputProvider.__init__(self) 116 self._factory = ElisaBTFactory(self) 117 self._port = None
118
119 - def _debug(self, *args, **kw):
120 print '%r,%r' % (args, kw)
121
122 - def bind(self):
123 self.debug("Listening on a ElisaBTPort...") 124 self._port = reactor.listenWith(ElisaBTPort, 0, self._factory)
125
126 - def unbind(self):
127 # FIXME: clean circular references properly...? 128 if self._port: 129 self._port.stopListening()
130
131 - def dataReceived(self, data):
132 self.debug('Received: %r' % data) 133 ev_data = data.split(':')[0:2] 134 e = self.create_input_event(ev_data) 135 if e and self.input_manager: 136 self.input_manager.process_event(e, self.path)
137
138 - def connectionLost(self, reason):
139 self.debug('Connection lost: %r' % reason)
140
141 - def create_input_event(self, data):
142 if len(data) < 2 or data[1] not in self.type_map: 143 return None 144 145 if data[0] in self.action_map and \ 146 self.type_map[data[1]] == EventType.KEY_DOWN: 147 148 event = InputEvent(EventSource.KEYBOARD, 149 EventType.OTHER, 150 self.action_map[data[0]]) 151 event.origin = self.origin 152 else: 153 event = None 154 155 return event
156 157 if __name__ == '__main__':
158 - class FakeManager:
159 up_ok = False 160 down_ok = False 161
162 - def process_event(self, event, input_provider_path):
163 print event
164 165 r = BluetoothInput() 166 m = FakeManager() 167 r.input_manager = m 168 r.bind() 169 reactor.run() 170 r.unbind() 171