~ubuntu-branches/ubuntu/lucid/pylirc/lucid

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
 /**************************************************************************\
 ** pylircmoduke.c                                                         **
 ****************************************************************************
 **                                                                        **
 ** pyLirc, lirc (remote control) module for python                        **
 ** Copyright (C) 2002 Linus McCabe <pylirc.linus@mccabe.nu>               **
 **                                                                        **
 ** This library is free software; you can redistribute it and/or          **
 ** modify it under the terms of the GNU Lesser General Public             **
 ** License as published by the Free Software Foundation; either           **
 ** version 2.1 of the License, or (at your option) any later version.     **
 **                                                                        **
 ** This library 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      **
 ** Lesser General Public License for more details.                        **
 **                                                                        **
 ** You should have received a copy of the GNU Lesser General Public       **
 ** License along with this library; if not, write to the Free Software    **
 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA **
 **                                                                        **
 \**************************************************************************/
 
// $Id: pylircmodule.c,v 1.7 2005/01/06 18:27:44 mccabe Exp $
// $Log: pylircmodule.c,v $
// Revision 1.7  2005/01/06 18:27:44  mccabe
// applied patch from Soenke Schwardt, prepared for new version
//
// Revision 1.6  2003/02/22 22:51:01  mccabe
// Previous, accidental commit:
// Added Brian J. Murrell's code to fetch repeatcount
//
// This commit:
// Changed Brians code to return a dictionary instead of a list.
// Removed lirc_nextcode_ext() and merged it with lirc_nextcode() - new optional argument controls return type. Old programs should work as
// before and new programs can benefit the new behaviour by passing true as first argument.
//
// Revision 1.5  2003/02/22 22:12:40  mccabe
// Testprogram to test pylirc in multiple threads
//
// Revision 1.4  2002/12/21 20:30:26  mccabe
// Added id and log entries to most files
//
//

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lirc/lirc_client.h"
#include <Python.h>

// Lirc programname
char *progname;

// boolean telling if we're initialized or not
int intInitialized = 0;
int intSocket = 0;

// Pointer to lirc's config
struct lirc_config *config;

// Prototypes - Python functions
static PyObject * pylirc_init(PyObject *, PyObject *);
static PyObject * pylirc_exit(PyObject *, PyObject *);
static PyObject * pylirc_nextcode(PyObject *, PyObject *);
static PyObject * pylirc_blocking(PyObject *, PyObject *);

// Prototypes - internal functions 
int SetMode(int);

// pylirc_init
// Function:   Initialize the lirc communication
// Arguments:  lircname (string), name of program as used in lirc fonig
//             configname (string), optional filename of lirc configuration
//             blocking (int), optional flag wether or not we want blocking mode
// Returns:    lirc socket
//
static PyObject * pylirc_init(self, args)
   PyObject *self;
   PyObject *args; {

   char *lircname;
   char *configname = NULL;
   int intBlocking = 0;
   
   // Just return if already initialized...
   if(intInitialized)
      return NULL;

   // Check if we got the right arguments..
   if (!PyArg_ParseTuple(args, "s|si", &lircname, &configname, &intBlocking)) {
      PyErr_SetString(PyExc_ValueError, "Wrong number of arguments!");
      return NULL;
   }

   // initialize lirc
   intSocket = lirc_init(lircname, 1);
   if(intSocket == -1) {
      PyErr_SetString(PyExc_RuntimeError, "Unable to initialize lirc!");
      return NULL;
   }

   // Set nonblocking mode (now optional)
   SetMode(intBlocking);


   // Read configuration
   if(!lirc_readconfig(configname, &config, NULL) == 0) {
      lirc_deinit();
      PyErr_SetString(PyExc_IOError, "Unable to read configuration!");
      return NULL;
   }
   
   // set flag and return
   intInitialized = 1;
   return Py_BuildValue("i", intSocket);
}


// pylirc_exit
// Function:   Shut down the lirc communication
// Arguments:  none
// Returns:    true on success
//
static PyObject * pylirc_exit(self, args)
   PyObject *self;
   PyObject *args; {

   // Only do this if we're really initialized...
   if(intInitialized) {
      intInitialized = 0;

      // Free the lirc config
      lirc_freeconfig(config);

      // lirc DeInit()
      if(lirc_deinit() == -1) {
         PyErr_SetString(PyExc_RuntimeError, "Unable to deinit!");
         return NULL;
      }
   }

   // Return
   return Py_BuildValue("i", 1);
}


// pylirc_nextcode
// Function:   Reads queued commands
// Arguments:  none
// Returns:    a list of commands (lirc config-strings)
//             or a 'None' if nothing is queued
//
static PyObject * pylirc_nextcode(self, args)
   PyObject *self;
   PyObject *args; {

   char *code, *c;
   PyObject *poTemp;
   int intExtended = 0, intRepeatCount;
   
   // Get arguments
   if (!PyArg_ParseTuple(args, "|i", &intExtended)) {
   
      // I guess this one cannot fail, but for completeness
      PyErr_SetString(PyExc_ValueError, "Wrong number of arguments!");
      return NULL;
   }
   
   // Returnvalue = 'None' (will change upon success)
   poTemp =  Py_BuildValue("");

   // Check if there is anything in the queue
   if(lirc_nextcode(&code) != -1) {

      // If code isn't NULL...
      if(code) {
	
	// Translate the string from configfile
	lirc_code2char(config, code, &c);
	
	if (c) 
	  {
	    // Returnvalue = empty list
	    poTemp = PyList_New(0);
	    
	    // If the list-creation was successful
	    if(poTemp) {
	      
	      // If success...
	      while(c) {
		
		if(intExtended) {
		  // Extended api - returns a list
		  // Thanks alot to Brian J. Murrell for the contribution!
		  
                  // Extract the repeat value from the code
                  if (sscanf(code, "%*llx %x %*s %*s\n", &intRepeatCount) != 1)
                     // some kind of error getting the repeat value, shouldnt happen...
                     intRepeatCount = 0;
                  
                  // Append the read code and repeat tuple to the list
                  PyList_Append(poTemp, Py_BuildValue("{s:s, s:i}", "config", c, "repeat", intRepeatCount));

               } else {
                  // Old api
                  
                  // Appen the read code to the list
                  PyList_Append(poTemp, Py_BuildValue("s", c));
		}
		
		// Read the next code
		lirc_code2char(config, code, &c);
	      }
	    }
	  }
	
	// Free the memory
	free(code);
      }
      

   }
   // Return a list or 'None'
   return poTemp;

}


// pylirc_blocking
// Function:   Set or unset blocking mode
// Arguments:  boolean wether or not to use blocking mode
// Returns:    true on success
//
static PyObject * pylirc_blocking(self, args)
   PyObject *self;
   PyObject *args; {

   int intBlocking = 0;

   // Read arguments
   if (!PyArg_ParseTuple(args, "i", &intBlocking)) {
      PyErr_SetString(PyExc_ValueError, "Wrong arguments!");
      return NULL;
   }
   
   intBlocking = SetMode(intBlocking);
   // Return
   return Py_BuildValue("i", intBlocking);
}

// SetMode
// Function:   Slavefunction, called in pylirc_init() and pylirc_blocking()
//             to set or unset blocking mode
// Arguments:  none
// Returns:    true on success
//
int SetMode(int intBlocking) {
   int flags;

   fcntl(intSocket, F_SETOWN, getpid());
   flags = fcntl(intSocket, F_GETFL, 0);
   if(flags != -1) {
      fcntl(intSocket, F_SETFL, (flags & ~O_NONBLOCK) | (intBlocking ? 0 : O_NONBLOCK));
      return -1;
   }

   return 0;
}

// Python function table
static PyMethodDef pylircMethods[] = {
    {"init",  pylirc_init, METH_VARARGS, "Register a lirc program."},
    {"exit",  pylirc_exit, METH_VARARGS, "Unregister a lirc program."},
    {"blocking",  pylirc_blocking, METH_VARARGS, "Sets wether or not to use blocking mode."},
    {"nextcode",  pylirc_nextcode, METH_VARARGS, "Poll queued codes (or wait until one arrives if in blocking mode)."},
    {NULL, NULL, 0, NULL}        /* Sentinel */
};

// Python init function
void initpylirc(void) {
    (void) Py_InitModule("pylirc", pylircMethods);
}