@@ -51,6 +51,34 @@ using namespace CEC;
51
51
// - source activated
52
52
//
53
53
54
+ int parse_physical_addr (char * addr) {
55
+ int a, b, c, d;
56
+ if ( sscanf (addr, " %x.%x.%x.%x" , &a, &b, &c, &d) == 4 ) {
57
+ if ( a > 0xF || b > 0xF || c > 0xF || d > 0xF ) return -1 ;
58
+ if ( a < 0 || b < 0 || c < 0 || d < 0 ) return -1 ;
59
+ return (a << 12 ) | (b << 8 ) | (c << 4 ) | d;
60
+ } else {
61
+ return -1 ;
62
+ }
63
+ }
64
+
65
+ #define RETURN_BOOL (arg ) do { PyObject * ret = (arg)?Py_True:Py_False; Py_INCREF (ret); return ret; } while (0 )
66
+
67
+ int parse_test () {
68
+ assert (parse_physical_addr (" 0.0.0.0" ) == 0 );
69
+ assert (parse_physical_addr (" F.0.0.0" ) == 0xF000 );
70
+ assert (parse_physical_addr (" 0.F.0.0" ) == 0x0F00 );
71
+ assert (parse_physical_addr (" 0.0.F.0" ) == 0x00F0 );
72
+ assert (parse_physical_addr (" 0.0.0.F" ) == 0x000F );
73
+ assert (parse_physical_addr (" -1.0.0.0" ) == -1 );
74
+ assert (parse_physical_addr (" 0.-1.0.0" ) == -1 );
75
+ assert (parse_physical_addr (" 0.0.-1.0" ) == -1 );
76
+ assert (parse_physical_addr (" 0.0.0.-1" ) == -1 );
77
+ assert (parse_physical_addr (" foo" ) == -1 );
78
+ assert (parse_physical_addr (" F.F.F.F" ) == 0xFFFF );
79
+ assert (parse_physical_addr (" f.f.f.f" ) == 0xFFFF );
80
+ }
81
+
54
82
class CallbackList {
55
83
private:
56
84
std::list<PyObject*> callbacks;
@@ -155,19 +183,15 @@ static PyObject * init(PyObject * self, PyObject * args) {
155
183
PyObject * result = NULL ;
156
184
const char * dev = NULL ;
157
185
158
- // this is NOT the right way to parse optional args in C...
159
- // it doesn't produce good error messages; sometimes reports 0 args, other
160
- // time 1 required
161
- // HOWEVER, it works. Bitches.
162
- if ( PyArg_ParseTuple (args, " :init" ) ) {
163
- std::list<cec_adapter_descriptor> devs = get_adapters ();
164
- if ( devs.size () > 0 ) {
165
- dev = devs.front ().strComName ;
166
- } else {
167
- PyErr_SetString (PyExc_Exception, " No default adapter found" );
186
+ if ( PyArg_ParseTuple (args, " |s:init" , &dev) ) {
187
+ if ( !dev ) {
188
+ std::list<cec_adapter_descriptor> devs = get_adapters ();
189
+ if ( devs.size () > 0 ) {
190
+ dev = devs.front ().strComName ;
191
+ } else {
192
+ PyErr_SetString (PyExc_Exception, " No default adapter found" );
193
+ }
168
194
}
169
- } else {
170
- PyArg_ParseTuple (args, " s:init" , &dev);
171
195
}
172
196
173
197
if ( dev ) {
@@ -239,27 +263,53 @@ static PyObject * add_callback(PyObject * self, PyObject * args) {
239
263
}
240
264
241
265
static PyObject * volume_up (PyObject * self, PyObject * args) {
242
- PyObject * result = NULL ;
243
-
244
- if ( PyArg_ParseTuple (args, " :volume_up" ) ) {
245
- CEC_adapter->VolumeUp ();
246
- Py_INCREF (Py_None);
247
- result = Py_None;
248
- }
249
-
250
- return result;
266
+ if ( PyArg_ParseTuple (args, " :volume_up" ) )
267
+ RETURN_BOOL (CEC_adapter->VolumeUp ());
268
+ return NULL ;
251
269
}
252
270
253
271
static PyObject * volume_down (PyObject * self, PyObject * args) {
254
- PyObject * result = NULL ;
272
+ if ( PyArg_ParseTuple (args, " :volume_up" ) )
273
+ RETURN_BOOL (CEC_adapter->VolumeUp ());
274
+ return NULL ;
275
+ }
255
276
256
- if ( PyArg_ParseTuple (args, " :volume_up" ) ) {
257
- CEC_adapter->VolumeUp ();
258
- Py_INCREF (Py_None);
259
- result = Py_None;
277
+ static PyObject * set_stream_path (PyObject * self, PyObject * args) {
278
+ PyObject * arg;
279
+
280
+ if ( PyArg_ParseTuple (args, " O:set_stream_path" , &arg) ) {
281
+ Py_INCREF (arg);
282
+ if (PyInt_Check (arg)) {
283
+ long arg_l = PyInt_AsLong (arg);
284
+ Py_DECREF (arg);
285
+ if ( arg_l < 0 || arg_l > 15 ) {
286
+ PyErr_SetString (PyExc_ValueError, " Logical address must be between 0 and 15" );
287
+ return NULL ;
288
+ } else {
289
+ RETURN_BOOL (CEC_adapter->SetStreamPath ((cec_logical_address)arg_l));
290
+ }
291
+ } else if (PyString_Check (arg)) {
292
+ char * arg_s = PyString_AsString (arg);
293
+ if ( arg_s ) {
294
+ int pa = parse_physical_addr (arg_s);
295
+ Py_DECREF (arg);
296
+ if ( pa < 0 ) {
297
+ PyErr_SetString (PyExc_ValueError, " Invalid physical address" );
298
+ return NULL ;
299
+ } else {
300
+ RETURN_BOOL (CEC_adapter->SetStreamPath ((uint16_t )pa));
301
+ }
302
+ } else {
303
+ Py_DECREF (arg);
304
+ return NULL ;
305
+ }
306
+ } else {
307
+ PyErr_SetString (PyExc_TypeError, " parameter must be string or int" );
308
+ return NULL ;
309
+ }
260
310
}
261
311
262
- return result ;
312
+ return NULL ;
263
313
}
264
314
265
315
static PyMethodDef CecMethods[] = {
0 commit comments