Skip to content

Commit 8a52881

Browse files
committed
Most of set_stream_path, and better arg parsing.
1 parent f8ab311 commit 8a52881

File tree

2 files changed

+78
-28
lines changed

2 files changed

+78
-28
lines changed

cec.cpp

+77-27
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,34 @@ using namespace CEC;
5151
// - source activated
5252
//
5353

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+
5482
class CallbackList {
5583
private:
5684
std::list<PyObject*> callbacks;
@@ -155,19 +183,15 @@ static PyObject * init(PyObject * self, PyObject * args) {
155183
PyObject * result = NULL;
156184
const char * dev = NULL;
157185

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+
}
168194
}
169-
} else {
170-
PyArg_ParseTuple(args, "s:init", &dev);
171195
}
172196

173197
if( dev ) {
@@ -239,27 +263,53 @@ static PyObject * add_callback(PyObject * self, PyObject * args) {
239263
}
240264

241265
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;
251269
}
252270

253271
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+
}
255276

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+
}
260310
}
261311

262-
return result;
312+
return NULL;
263313
}
264314

265315
static PyMethodDef CecMethods[] = {

test.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
if len(adapters) > 0:
1313
adapter = adapters[0]
1414
print "Using Adapter %s"%(adapter)
15-
cec.init()
15+
cec.init(adapter)
1616

1717
print "Devices:", cec.list_devices()
1818

0 commit comments

Comments
 (0)