servicemp3.cpp: more simple/flexible streaming detection
[enigma2.git] / lib / base / console.cpp
index b1502d7e6baaa830b26ee14c8dda97b2b5cb36e6..00187683258be0e8348e1d7ad9e07ff074504915 100644 (file)
@@ -55,8 +55,10 @@ int bidirpipe(int pfd[], const char *cmd , const char * const argv[], const char
        return(pid);
 }
 
+DEFINE_REF(eConsoleAppContainer);
+
 eConsoleAppContainer::eConsoleAppContainer()
-:pid(-1), killstate(0), in(0), out(0), err(0)
+:pid(-1), killstate(0)
 {
        for (int i=0; i < 3; ++i)
        {
@@ -107,14 +109,18 @@ int eConsoleAppContainer::execute(const char *cmdline, const char * const argv[]
 
 //     eDebug("pipe in = %d, out = %d, err = %d", fd[0], fd[1], fd[2]);
 
+       ::fcntl(fd[0], F_SETFL, O_NONBLOCK);
        ::fcntl(fd[1], F_SETFL, O_NONBLOCK);
        ::fcntl(fd[2], F_SETFL, O_NONBLOCK);
-       in = new eSocketNotifier(eApp, fd[0], eSocketNotifier::Read|eSocketNotifier::Priority|eSocketNotifier::Hungup );
-       out = new eSocketNotifier(eApp, fd[1], eSocketNotifier::Write, false);  
-       err = new eSocketNotifier(eApp, fd[2], eSocketNotifier::Read|eSocketNotifier::Priority );
+       in = eSocketNotifier::create(eApp, fd[0], eSocketNotifier::Read|eSocketNotifier::Priority|eSocketNotifier::Hungup );
+       out = eSocketNotifier::create(eApp, fd[1], eSocketNotifier::Write, false);  
+       err = eSocketNotifier::create(eApp, fd[2], eSocketNotifier::Read|eSocketNotifier::Priority );
        CONNECT(in->activated, eConsoleAppContainer::readyRead);
        CONNECT(out->activated, eConsoleAppContainer::readyWrite);
        CONNECT(err->activated, eConsoleAppContainer::readyErrRead);
+       in->m_clients.push_back(this);
+       out->m_clients.push_back(this);
+       err->m_clients.push_back(this);
 
        return 0;
 }
@@ -143,10 +149,9 @@ void eConsoleAppContainer::kill()
                outbuf.pop();
                delete [] d.data;
        }
-       delete in;
-       delete out;
-       delete err;
-       in=out=err=0;
+       in = 0;
+       out = 0;
+       err = 0;
 
        for (int i=0; i < 3; ++i)
        {
@@ -209,6 +214,7 @@ void eConsoleAppContainer::closePipes()
                outbuf.pop();
                delete [] d.data;
        }
+       in = 0; out = 0; err = 0;
        pid = -1;
 }
 
@@ -333,152 +339,6 @@ struct eConsolePy
        PyObject *in_weakreflist; /* List of weak references */
 };
 
-#define COMPATIBILITY_MODE
-// with COMPATIBILITY_MODE enabled the callback list is accessed via console.appClosed.get()
-// we remove this code after next enigma2 release... then the list should be accessed via console.appClosed ( without .get() )
-
-#ifdef COMPATIBILITY_MODE
-struct eListCompatibilityWrapper
-{
-       PyObject_HEAD
-       PyObject *list;
-       PyObject *in_weakreflist; /* List of weak references */
-};
-
-static int
-eListCompatibilityWrapper_traverse(eListCompatibilityWrapper *self, visitproc visit, void *arg)
-{
-       Py_VISIT(self->list);
-       return 0;
-}
-
-static int
-eListCompatibilityWrapper_clear(eListCompatibilityWrapper *self)
-{
-       Py_CLEAR(self->list);
-       return 0;
-}
-
-static void
-eListCompatibilityWrapper_dealloc(eListCompatibilityWrapper* self)
-{
-       if (self->in_weakreflist != NULL)
-               PyObject_ClearWeakRefs((PyObject *) self);
-       eListCompatibilityWrapper_clear(self);
-       Org_Py_DECREF(self->list);
-       self->ob_type->tp_free((PyObject*)self);
-}
-
-static PyObject *
-eListCompatibilityWrapper_get(eListCompatibilityWrapper *self, void *closure)
-{
-       Org_Py_INCREF(self->list);
-       return self->list;
-}
-
-static PyMethodDef eListCompatibilityWrapper_methods[] = {
-       {"get", (PyCFunction)eListCompatibilityWrapper_get, METH_NOARGS,
-        "returns the list"
-       },
-       {NULL}  /* Sentinel */
-};
-
-static PyGetSetDef eListCompatibilityWrapper_getseters[] = {
-       {NULL} /* Sentinel */
-};
-
-static PyTypeObject eListCompatibilityWrapperType = {
-       PyObject_HEAD_INIT(NULL)
-       0, /*ob_size*/
-       "eConsoleImpl.eListCompatibilityWrapper", /*tp_name*/
-       sizeof(eListCompatibilityWrapper), /*tp_basicsize*/
-       0, /*tp_itemsize*/
-       (destructor)eListCompatibilityWrapper_dealloc, /*tp_dealloc*/
-       0, /*tp_print*/
-       0, /*tp_getattr*/
-       0, /*tp_setattr*/
-       0, /*tp_compare*/
-       0, /*tp_repr*/
-       0, /*tp_as_number*/
-       0, /*tp_as_sequence*/
-       0, /*tp_as_mapping*/
-       0, /*tp_hash */
-       0, /*tp_call*/
-       0, /*tp_str*/
-       0, /*tp_getattro*/
-       0, /*tp_setattro*/
-       0, /*tp_as_buffer*/
-       Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
-       "eListCompatibilityWrapper objects", /* tp_doc */
-       (traverseproc)eListCompatibilityWrapper_traverse, /* tp_traverse */
-       (inquiry)eListCompatibilityWrapper_clear, /* tp_clear */
-       0, /* tp_richcompare */
-       offsetof(eListCompatibilityWrapper, in_weakreflist), /* tp_weaklistoffset */
-       0, /* tp_iter */
-       0, /* tp_iternext */
-       eListCompatibilityWrapper_methods, /* tp_methods */
-       0, /* tp_members */
-       eListCompatibilityWrapper_getseters, /* tp_getset */
-       0, /* tp_base */
-       0, /* tp_dict */
-       0, /* tp_descr_get */
-       0, /* tp_descr_set */
-       0, /* tp_dictoffset */
-       0, /* tp_init */
-       0, /* tp_alloc */
-       0, /* tp_new */
-};
-
-static PyObject *
-eConsolePy_dataAvail(eConsolePy *self, void *closure)
-{
-       eListCompatibilityWrapper *wrapper = (eListCompatibilityWrapper *)eListCompatibilityWrapperType.tp_alloc(&eListCompatibilityWrapperType, 0);
-       Org_Py_INCREF((PyObject*)wrapper);
-       wrapper->list = self->cont->dataAvail.get();
-       wrapper->in_weakreflist = NULL;
-       return (PyObject*)wrapper;
-}
-
-static PyObject *
-eConsolePy_stdoutAvail(eConsolePy *self, void *closure)
-{
-       eListCompatibilityWrapper *wrapper = (eListCompatibilityWrapper *)eListCompatibilityWrapperType.tp_alloc(&eListCompatibilityWrapperType, 0);
-       Org_Py_INCREF((PyObject*)wrapper);
-       wrapper->list = self->cont->stdoutAvail.get();
-       wrapper->in_weakreflist = NULL;
-       return (PyObject*)wrapper;
-}
-
-static PyObject *
-eConsolePy_stderrAvail(eConsolePy *self, void *closure)
-{
-       eListCompatibilityWrapper *wrapper = (eListCompatibilityWrapper *)eListCompatibilityWrapperType.tp_alloc(&eListCompatibilityWrapperType, 0);
-       Org_Py_INCREF((PyObject*)wrapper);
-       wrapper->list = self->cont->stderrAvail.get();
-       wrapper->in_weakreflist = NULL;
-       return (PyObject*)wrapper;
-}
-
-static PyObject *
-eConsolePy_dataSent(eConsolePy *self, void *closure)
-{
-       eListCompatibilityWrapper *wrapper = (eListCompatibilityWrapper *)eListCompatibilityWrapperType.tp_alloc(&eListCompatibilityWrapperType, 0);
-       Org_Py_INCREF((PyObject*)wrapper);
-       wrapper->list = self->cont->dataSent.get();
-       wrapper->in_weakreflist = NULL;
-       return (PyObject*)wrapper;
-}
-
-static PyObject *
-eConsolePy_appClosed(eConsolePy *self, void *closure)
-{
-       eListCompatibilityWrapper *wrapper = (eListCompatibilityWrapper *)eListCompatibilityWrapperType.tp_alloc(&eListCompatibilityWrapperType, 0);
-       Org_Py_INCREF((PyObject*)wrapper);
-       wrapper->list = self->cont->appClosed.get();
-       wrapper->in_weakreflist = NULL;
-       return (PyObject*)wrapper;
-}
-#else
 static PyObject *
 eConsolePy_dataAvail(eConsolePy *self, void *closure)
 {
@@ -508,7 +368,6 @@ eConsolePy_appClosed(eConsolePy *self, void *closure)
 {
        return self->cont->appClosed.get();
 }
-#endif
 
 static PyGetSetDef eConsolePy_getseters[] = {
        {"dataAvail",
@@ -537,23 +396,23 @@ static PyGetSetDef eConsolePy_getseters[] = {
 static int
 eConsolePy_traverse(eConsolePy *self, visitproc visit, void *arg)
 {
-       PyObject *obj = self->cont->dataAvail.get(true);
+       PyObject *obj = self->cont->dataAvail.getSteal();
        if (obj) {
                Py_VISIT(obj);
        }
-       obj = self->cont->stdoutAvail.get(true);
+       obj = self->cont->stdoutAvail.getSteal();
        if (obj) {
                Py_VISIT(obj);
        }
-       obj = self->cont->stderrAvail.get(true);
+       obj = self->cont->stderrAvail.getSteal();
        if (obj) {
                Py_VISIT(obj);
        }
-       obj = self->cont->dataSent.get(true);
+       obj = self->cont->dataSent.getSteal();
        if (obj) {
                Py_VISIT(obj);
        }
-       obj = self->cont->appClosed.get(true);
+       obj = self->cont->appClosed.getSteal();
        if (obj) {
                Py_VISIT(obj);
        }
@@ -563,23 +422,23 @@ eConsolePy_traverse(eConsolePy *self, visitproc visit, void *arg)
 static int
 eConsolePy_clear(eConsolePy *self)
 {
-       PyObject *obj = self->cont->dataAvail.get(true);
+       PyObject *obj = self->cont->dataAvail.getSteal(true);
        if (obj) {
                Py_CLEAR(obj);
        }
-       obj = self->cont->stdoutAvail.get(true);
+       obj = self->cont->stdoutAvail.getSteal(true);
        if (obj) {
                Py_CLEAR(obj);
        }
-       obj = self->cont->stderrAvail.get(true);
+       obj = self->cont->stderrAvail.getSteal(true);
        if (obj) {
                Py_CLEAR(obj);
        }
-       obj = self->cont->dataSent.get(true);
+       obj = self->cont->dataSent.getSteal(true);
        if (obj) {
                Py_CLEAR(obj);
        }
-       obj = self->cont->appClosed.get(true);
+       obj = self->cont->appClosed.getSteal(true);
        if (obj) {
                Py_CLEAR(obj);
        }
@@ -592,7 +451,7 @@ eConsolePy_dealloc(eConsolePy* self)
        if (self->in_weakreflist != NULL)
                PyObject_ClearWeakRefs((PyObject *) self);
        eConsolePy_clear(self);
-       delete self->cont;
+       self->cont->Release();
        self->ob_type->tp_free((PyObject*)self);
 }
 
@@ -601,6 +460,7 @@ eConsolePy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
        eConsolePy *self = (eConsolePy *)type->tp_alloc(type, 0);
        self->cont = new eConsoleAppContainer();
+       self->cont->AddRef();
        self->in_weakreflist = NULL;
        return (PyObject *)self;
 }
@@ -617,34 +477,36 @@ eConsolePy_running(eConsolePy* self)
 static PyObject *
 eConsolePy_execute(eConsolePy* self, PyObject *argt)
 {
-       if (PyTuple_Size(argt) > 1)
+       Py_ssize_t argc = PyTuple_Size(argt);
+       if (argc > 1)
        {
-               PyObject *cmdline, *args;
-               PyArg_ParseTuple(argt, "OO", &cmdline, &args);
-               if (!PyString_Check(cmdline) || !PySequence_Check(args))
-                       return PyInt_FromLong(-2);
-               else
+               const char *argv[argc + 1];
+               int argpos=0;
+               while(argpos < argc)
                {
-                       PyObject *fast = PySequence_Fast(args, "2nd arg is not a sequence");
-                       Py_ssize_t size = PySequence_Fast_GET_SIZE(fast);
-                       const char *argv[size + 1];
-                       int i=0;
-                       for (; i < size; ++i)
+                       PyObject *arg = PyTuple_GET_ITEM(argt, argpos);
+                       if (!PyString_Check(arg))
                        {
-                               PyObject *arg = PySequence_Fast_GET_ITEM(fast, i); /* borrowed ref */
-                               if (!PyString_Check(arg))
-                                       return PyInt_FromLong(-3);
-                               argv[i] = PyString_AsString(arg); /* borrowed pointer */
+                               char err[255];
+                               if (argpos)
+                                       snprintf(err, 255, "arg %d is not a string", argpos);
+                               else
+                                       snprintf(err, 255, "cmd is not a string!");
+                               PyErr_SetString(PyExc_TypeError, err);
+                               return NULL;
                        }
-                       argv[i] = 0;
-                       return PyInt_FromLong(self->cont->execute(PyString_AsString(cmdline), argv)); /* borrowed pointer */
+                       argv[argpos++] = PyString_AsString(arg);
                }
+               argv[argpos] = 0;
+               return PyInt_FromLong(self->cont->execute(argv[0], argv+1));
        }
        else
        {
                const char *str;
                if (PyArg_ParseTuple(argt, "s", &str))
                        return PyInt_FromLong(self->cont->execute(str));
+               PyErr_SetString(PyExc_TypeError,
+                       "cmd is not a string!");
        }
        return NULL;
 }
@@ -654,14 +516,15 @@ eConsolePy_write(eConsolePy* self, PyObject *args)
 {
        int len;
        char *data;
-       if (PyArg_ParseTuple(args, "si", &data, &len))
-               ;
-       else
+       int ret = -1;
+       Py_ssize_t argc = PyTuple_Size(args);
+       if (argc > 1)
+               ret = !PyArg_ParseTuple(args, "si", &data, &len);
+       else if (argc == 1)
        {
                PyObject *ob;
-               if (!PyArg_ParseTuple(args, "O", &ob) || !PyString_Check(ob))
-                       return NULL;
-               else
+               ret = !PyArg_ParseTuple(args, "O", &ob) || !PyString_Check(ob);
+               if (!ret)
                {
                        Py_ssize_t length;
                        if (!PyString_AsStringAndSize(ob, &data, &length))
@@ -670,6 +533,12 @@ eConsolePy_write(eConsolePy* self, PyObject *args)
                                len = 0;
                }
        }
+       if (ret)
+       {
+               PyErr_SetString(PyExc_TypeError,
+                       "1st arg must be a string, optionaly 2nd arg can be the string length");
+               return NULL;
+       }
        self->cont->write(data, len);
        Py_RETURN_NONE;
 }
@@ -716,7 +585,11 @@ eConsolePy_dumpToFile(eConsolePy* self, PyObject *args)
 {
        char *filename;
        if (!PyArg_ParseTuple(args, "s", &filename))
+       {
+               PyErr_SetString(PyExc_TypeError,
+                       "arg must be a string (filename)");
                return NULL;
+       }
        else
        {
                int fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
@@ -731,7 +604,11 @@ eConsolePy_readFromFile(eConsolePy* self, PyObject *args)
 {
        char *filename;
        if (!PyArg_ParseTuple(args, "s", &filename))
+       {
+               PyErr_SetString(PyExc_TypeError,
+                       "arg must be a string (filename)");
                return NULL;
+       }
        else
        {
                int fd = open(filename, O_RDONLY);
@@ -840,13 +717,6 @@ void eConsoleInit(void)
        if (m == NULL)
                return;
 
-#ifdef COMPATIBILITY_MODE
-       if (!PyType_Ready(&eListCompatibilityWrapperType))
-       {
-               Org_Py_INCREF((PyObject*)&eListCompatibilityWrapperType);
-               PyModule_AddObject(m, "eListCompatibilityWrapper", (PyObject*)&eListCompatibilityWrapperType);
-       }
-#endif
        if (!PyType_Ready(&eConsolePyType))
        {
                Org_Py_INCREF((PyObject*)&eConsolePyType);