rendered paste body/*
* ====================================================================
* e32module.cpp
*
* Basic EPOC facilities for Python
*
* Implements currently (23.11.2004) following Python classes / methods:
*
* Ao_lock -- Symbian active object -based synchronization
* Ao_lock()
* wait()
* signal()
*
* Ao_timer -- Symbian active object -based timer
* Ao_timer()
* after()
* cancel()
*
* ao_yield()
*
* ao_sleep(float [,callable])
*
* callable ao_callgate(callable)
*
* file_copy(unicode_string OR string, unicode_string OR string)
*
* start_server(unicode_string OR string)
*
* start_exe(unicode_string OR string, unicode_string OR string [,int])
*
* [unicode_string] drive_list()
*
* bool is_ui_thread()
*
*
* Copyright (c) 2005-2006 Nokia Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
#include <e32std.h>
#include <e32uid.h> // e32_uidcrc_app()
#include <eikapp.h>
#include <f32file.h>
#include <bautils.h> // e32_file_copy()
#include <apmstd.h>
#include <hal.h> // e32_clock()
#include "Python.h"
#include "symbian_python_ext_util.h"
#include "CSPyInterpreter.h" // e32_stdo(), e32_mem_info()
/*
*
* Utilities for e32.start_server() and e32.start_exe()
*
*/
class CE32ProcessWait : public CActive
{
public:
CE32ProcessWait():CActive(EPriorityStandard) {
CActiveScheduler::Add(this);
}
#if defined(__WINS__) && !defined(EKA2)
TInt Wait(RThread& aProcess) {
#else
TInt Wait(RProcess& aProcess) {
#endif
aProcess.Logon(iStatus);
aProcess.Resume();
SetActive();
#ifdef HAVE_ACTIVESCHEDULERWAIT
iWait.Start();
#else
CActiveScheduler::Start();
#endif
return iStatus.Int();
}
private:
void DoCancel() {;}
void RunL() {
#ifdef HAVE_ACTIVESCHEDULERWAIT
iWait.AsyncStop();
#else
CActiveScheduler::Stop();
#endif
}
#ifdef HAVE_ACTIVESCHEDULERWAIT
CActiveSchedulerWait iWait;
#endif
};
static TInt ProcessLaunch(const TDesC& aFileName, const TDesC& aCommand,
TInt aWaitFlag=0)
{
TInt error;
Py_BEGIN_ALLOW_THREADS
#if defined(__WINS__) && !defined(EKA2)
RThread proc;
RLibrary lib;
HBufC* pcommand = aCommand.Alloc();
error = lib.Load(aFileName);
if (error == KErrNone) {
TThreadFunction func = (TThreadFunction)(lib.Lookup(1));
error = proc.Create(_L(""), func, 0x1000, (TAny*) pcommand, &lib,
RThread().Heap(), 0x1000, 0x100000, EOwnerProcess);
lib.Close();
}
else
delete pcommand;
#else
RProcess proc;
error = proc.Create(aFileName, aCommand);
#endif
if (error == KErrNone)
if (aWaitFlag) {
CE32ProcessWait* w = new CE32ProcessWait();
if (w) {
error = w->Wait(proc);
delete w;
}
else
error = KErrNoMemory;
}
else
proc.Resume();
proc.Close();
Py_END_ALLOW_THREADS
return error;
}
/*
*
* Implementation of e32.start_server()
*
*/
extern "C" PyObject *
e32_start_server(PyObject* /*self*/, PyObject* args)
{
PyObject* it;
if (!PyArg_ParseTuple(args, "O", &it))
return NULL;
PyObject* fn = PyUnicode_FromObject(it);
if (!fn)
return NULL;
TPtrC name(PyUnicode_AsUnicode(fn), PyUnicode_GetSize(fn));
TParse p;
p.Set(name, NULL, NULL);
if (!(p.Ext().CompareF(_L(".py")) == 0)) {
Py_DECREF(fn);
PyErr_SetString(PyExc_TypeError, "Python script name expected");
return NULL;
}
TInt error;
error =
#if defined(__WINS__) && !defined(EKA2)
ProcessLaunch(_L("\\system\\programs\\Python_launcher.dll"), name);
#else
ProcessLaunch(_L("python_launcher.exe"), name);
#endif
Py_DECREF(fn);
RETURN_ERROR_OR_PYNONE(error);
}
/*
*
* Implementation of e32.start_exe()
*
*/
extern "C" PyObject *
e32_start_exe(PyObject* /*self*/, PyObject* args)
{
PyObject *it0, *it1;
int wait_flag = 0;
if (!PyArg_ParseTuple(args, "OO|i", &it0, &it1, &wait_flag))
return NULL;
PyObject* n = PyUnicode_FromObject(it0);
if (!n)
return NULL;
TPtrC name(PyUnicode_AsUnicode(n), PyUnicode_GetSize(n));
TParse p;
p.Set(name, NULL, NULL);
#if defined(__WINS__) && !defined(EKA2)
if (!(p.Ext().CompareF(_L(".dll")) == 0)) {
#else
if (!(p.Ext().CompareF(_L(".exe")) == 0)) {
#endif
Py_DECREF(n);
PyErr_SetString(PyExc_TypeError, "Executable expected");
return NULL;
}
PyObject* a = PyUnicode_FromObject(it1);
if (!a) {
Py_DECREF(n);
return NULL;
}
TInt error = ProcessLaunch(name,
TPtrC(PyUnicode_AsUnicode(a),
PyUnicode_GetSize(a)),
wait_flag);
Py_DECREF(n);
Py_DECREF(a);
if (wait_flag && (error >= 0))
return Py_BuildValue("i", error);
else
RETURN_ERROR_OR_PYNONE(error);
}
/*
*
* Implementation of e32.drive_list()
*
*/
extern "C" PyObject *
e32_drive_list(PyObject* /*self*/)
{
TInt error;
RFs rfs;
if ((error = rfs.Connect()) != KErrNone)
return SPyErr_SetFromSymbianOSErr(error);
PyObject* r;
TDriveList l;
error = rfs.DriveList(l);
if (error == KErrNone) {
if (r = PyList_New(0)) {
for (int i = 0; i < KMaxDrives; i++) {
if (l[i]) {
char d[2];
d[0] = 'A'+i; d[1] = ':';
PyObject* v = PyUnicode_Decode(d, 2, NULL, NULL);
if ((v == NULL) || (PyList_Append(r, v) != 0)) {
Py_XDECREF(v);
Py_DECREF(r);
r = NULL;
break;
}
Py_DECREF(v);
}
}
}
}
else
r = SPyErr_SetFromSymbianOSErr(error);
rfs.Close();
return r;
}
/*
*
* Implementation of e32.file_copy()
*
*/
extern "C" PyObject *
e32_file_copy(PyObject* /*self*/, PyObject* args)
{
PyObject *it0, *it1;
if (!PyArg_ParseTuple(args, "OO", &it0, &it1))
return NULL;
PyObject *t, *s;
if (!((t = PyUnicode_FromObject(it0)) &&
(s = PyUnicode_FromObject(it1)))) {
Py_XDECREF(t);
return NULL;
}
TPtrC target(PyUnicode_AsUnicode(t), PyUnicode_GetSize(t));
TPtrC source(PyUnicode_AsUnicode(s), PyUnicode_GetSize(s));
TInt error;
RFs rfs;
if ((error = rfs.Connect()) == KErrNone) {
error = BaflUtils::CopyFile(rfs, source, target);
rfs.Close();
}
Py_DECREF(t); Py_DECREF(s);
RETURN_ERROR_OR_PYNONE(error);
}
/*
*
* Implementation of e32.Ao_lock
*
*/
#define Ao_lock_type ((PYTHON_GLOBALS->tobj).t_Ao)
#ifndef EKA2
class Ao_lock : public CActive {
#else
NONSHARABLE_CLASS(Ao_lock) : public CActive {
#endif
public:
Ao_lock();
TInt Signal(TUint aTid);
void Wait();
private:
void RunL();
void DoCancel() {;}
TRequestStatus* iPst;
#ifdef HAVE_ACTIVESCHEDULERWAIT
CActiveSchedulerWait iWait;
#endif
};
Ao_lock::Ao_lock():CActive(0)
{
iStatus = KErrCancel;
iPst = &iStatus;
CActiveScheduler::Add(this);
}
void Ao_lock::Wait()
{
if (iStatus != KErrNone) {
iStatus = KRequestPending;
iPst = &iStatus;
SetActive();
Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_ACTIVESCHEDULERWAIT
iWait.Start();
#else
CActiveScheduler::Start();
#endif
Py_END_ALLOW_THREADS
}
iStatus = KErrCancel;
return;
}
TInt Ao_lock::Signal(TUint aTid)
{
TInt error = KErrNone;
if (iStatus != KRequestPending) {
iStatus = KErrNone;
return error;
}
RThread t;
error = t.Open(aTid);
if (error == KErrNone) {
//iStatus = KErrNone; // Doing this will panic the 3.0 emulator with E32USER-CBase 46 "Stray signal".
t.RequestComplete(iPst, 0);
t.Close();
}
return error;
}
void Ao_lock::RunL()
{
#ifdef HAVE_ACTIVESCHEDULERWAIT
iWait.AsyncStop();
#else
CActiveScheduler::Stop();
#endif
}
struct Ao_lock_object {
PyObject_VAR_HEAD
Ao_lock* ob_data;
unsigned int ob_tid;
};
extern "C" PyObject *
new_e32_ao_object(PyObject* /*self*/)
{
if (!CActiveScheduler::Current()) {
PyErr_SetString(PyExc_AssertionError, "no ao scheduler");
return NULL;
}
Ao_lock_object *op = PyObject_New(Ao_lock_object, &Ao_lock_type);
if (op == NULL)
return PyErr_NoMemory();
op->ob_data = new Ao_lock();
if (op->ob_data == NULL) {
PyObject_Del(op);
return PyErr_NoMemory();
}
op->ob_tid = RThread().Id();
return (PyObject *) op;
}
extern "C" PyObject *
ao_wait(Ao_lock_object *self, PyObject* /*args*/)
{
if ((TUint)RThread().Id() != self->ob_tid) {
PyErr_SetString(PyExc_AssertionError,
"Ao_lock.wait must be called from lock creator thread");
return NULL;
}
if (self->ob_data->iStatus == KRequestPending) {
PyErr_SetString(PyExc_AssertionError, "wait() called on Ao_lock while another wait() on the same lock is in progress");
return NULL;
}
self->ob_data->Wait();
Py_INCREF(Py_None);
return Py_None;
}
extern "C" PyObject *
ao_signal(Ao_lock_object *self, PyObject* /*args*/)
{
TInt error = self->ob_data->Signal(self->ob_tid);
RETURN_ERROR_OR_PYNONE(error);
}
extern "C" {
static void
ao_dealloc(Ao_lock_object *op)
{
if ((TUint)RThread().Id() == op->ob_tid) {
delete op->ob_data;
op->ob_data = NULL;
}
PyObject_Del(op);
}
static const PyMethodDef ao_methods[] = {
{"wait", (PyCFunction)ao_wait, METH_NOARGS},
{"signal", (PyCFunction)ao_signal, METH_NOARGS},
{NULL, NULL} /* sentinel */
};
static PyObject *
ao_getattr(Ao_lock_object *p, char *name)
{
return Py_FindMethod((PyMethodDef*)ao_methods,
(PyObject *)p, name);
}
static const PyTypeObject c_Ao_lock_type = {
PyObject_HEAD_INIT(NULL)
0,
"e32.Ao_lock",
sizeof(Ao_lock_object),
0,
/* methods */
(destructor)ao_dealloc, /* tp_dealloc */
0, /* tp_print */
(getattrfunc)ao_getattr, /* 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 */
};
} /* extern "C" */
/*
*
* Implementation of e32.ao_yield
*
*/
class CE32AoYield : public CActive
{
public:
CE32AoYield():CActive(EPriorityStandard) {
CActiveScheduler::Add(this);
}
void DoYield() {
iStatus = KRequestPending;
SetActive();
//iStatus = KErrNone; // Doing this will panic the 3.0 emulator with E32USER-CBase 46 "Stray signal".
TRequestStatus* pstatus = &iStatus;
RThread().RequestComplete(pstatus, 0);
#ifdef HAVE_ACTIVESCHEDULERWAIT
iWait.Start();
#else
CActiveScheduler::Start();
#endif
}
private:
void DoCancel() {;}
void RunL() {
#ifdef HAVE_ACTIVESCHEDULERWAIT
iWait.AsyncStop();
#else
CActiveScheduler::Stop();
#endif
}
#ifdef HAVE_ACTIVESCHEDULERWAIT
CActiveSchedulerWait iWait;
#endif
};
extern "C" PyObject *
e32_ao_yield(PyObject* /*self*/)
{
CE32AoYield* y = new CE32AoYield();
if (!y)
return PyErr_NoMemory();
Py_BEGIN_ALLOW_THREADS
y->DoYield();
delete y;
Py_END_ALLOW_THREADS
Py_INCREF(Py_None);
return Py_None;
}
/*
*
* Implementation of e32.ao_sleep
*
*/
class CE32AoSleep : public CActive
{
public:
CE32AoSleep(PyObject* aCb=0):CActive(EPriorityStandard) {
iCb = aCb;
Py_XINCREF(iCb);
//iMaxTime(in seconds) is max integer where (2147*10exp6< 2exp31)
//This restriction is needed to avoid overflow at
//RTimer.After(TTimeIntervalMicroSeconds32)
iMaxTime = 2147;
}
~CE32AoSleep() {
Cancel();
iTimer.Close();
Py_XDECREF(iCb);
}
TInt Construct() {
TInt error = iTimer.CreateLocal();
if (error == KErrNone)
CActiveScheduler::Add(this);
return error;
}
void DoSleep(TReal aDelay /*time in seconds*/) {
TInt timeMultiplier = aDelay / iMaxTime;
TReal timeLeft = aDelay - (iMaxTime * timeMultiplier);
if (timeMultiplier > 0) {
for (TInt i = 0; i< timeMultiplier; i++)
{
StartTimer(iMaxTime);
}
}
if (timeLeft > 0) {
StartTimer(timeLeft);
}
}
private:
void DoCancel() {
iTimer.Cancel();
}
void RunL() {
if (!iCb) {
#ifdef HAVE_ACTIVESCHEDULERWAIT
iWait.AsyncStop();
#else
CActiveScheduler::Stop();
#endif
}
else {
PyEval_RestoreThread(PYTHON_TLS->thread_state);
PyObject* tmp_r = NULL;
tmp_r = PyEval_CallObject(iCb, NULL);
Py_XDECREF(tmp_r);
if (PyErr_Occurred())
PyErr_Print();
PyEval_SaveThread();
}
}
void StartTimer(TReal aDelay) {
TTimeIntervalMicroSeconds32 delay;
#ifndef EKA2
delay = TTimeIntervalMicroSeconds32(TInt64(aDelay*1000*1000).GetTInt());
#else
delay = TTimeIntervalMicroSeconds32(TInt64(aDelay*1000*1000));
#endif
iTimer.After(iStatus, delay);
SetActive();
if (!iCb) {
Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_ACTIVESCHEDULERWAIT
iWait.Start();
#else
CActiveScheduler::Start();
#endif
Py_END_ALLOW_THREADS
}
}
RTimer iTimer;
TInt iMaxTime;
#ifdef HAVE_ACTIVESCHEDULERWAIT
CActiveSchedulerWait iWait;
#endif
PyObject* iCb;
};
extern "C" PyObject *
e32_ao_sleep(PyObject* /*self*/, PyObject* args)
{
TReal d;
PyObject* c=NULL;
if (!PyArg_ParseTuple(args, "d|O", &d, &c))
return NULL;
if (c && !PyCallable_Check(c)) {
PyErr_SetString(PyExc_TypeError, "callable expected for 2nd argument");
return NULL;
}
if (d < 0) {
PyErr_SetString(PyExc_RuntimeError, "negative number not allowed");
return NULL;
}
CE32AoSleep* s = new CE32AoSleep(c);
if (!s)
return PyErr_NoMemory();
TInt error = s->Construct();
if (error != KErrNone) {
delete s;
return SPyErr_SetFromSymbianOSErr(error);
}
s->DoSleep(d);
delete s;
Py_INCREF(Py_None);
return Py_None;
}
/*
*
* Implementation of e32.Ao_timer
*
*/
#define Ao_timer_type (PYTHON_GLOBALS->t_Ao_timer)
#ifndef EKA2
class Ao_timer : public CActive {
#else
NONSHARABLE_CLASS(Ao_timer) : public CActive {
#endif
public:
Ao_timer();
void After(TTimeIntervalMicroSeconds32 aSleep, PyObject* aCb);
TInt Construct();
~Ao_timer();
private:
void RunL();
void DoCancel();
RTimer iTimer;
PyObject* iCb;
#ifdef HAVE_ACTIVESCHEDULERWAIT
CActiveSchedulerWait iWait;
#endif
};
Ao_timer::Ao_timer():CActive(EPriorityStandard) {;}
void Ao_timer::After(TTimeIntervalMicroSeconds32 aDelay, PyObject* aCb=0)
{
iCb = aCb;
Py_XINCREF(iCb);
iTimer.After(iStatus, aDelay);
SetActive();
if (!iCb) {
Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_ACTIVESCHEDULERWAIT
iWait.Start();
#else
CActiveScheduler::Start();
#endif
Py_END_ALLOW_THREADS
}
}
TInt Ao_timer::Construct()
{
TInt error = iTimer.CreateLocal();
if (error == KErrNone)
CActiveScheduler::Add(this);
return error;
}
Ao_timer::~Ao_timer()
{
Cancel();
iTimer.Close();
Py_XDECREF(iCb);
}
void Ao_timer::RunL()
{
if (!iCb) {
#ifdef HAVE_ACTIVESCHEDULERWAIT
iWait.AsyncStop();
#else
CActiveScheduler::Stop();
#endif
}
else {
PyEval_RestoreThread(PYTHON_TLS->thread_state);
PyObject* tmp_r = NULL;
tmp_r = PyEval_CallObject(iCb, NULL);
Py_XDECREF(tmp_r);
if (PyErr_Occurred())
PyErr_Print();
PyEval_SaveThread();
}
}
void Ao_timer::DoCancel()
{
iTimer.Cancel();
}
struct Ao_timer_object {
PyObject_VAR_HEAD
Ao_timer* ob_data;
};
extern "C" PyObject *
new_e32_ao_timer_object(PyObject* /*self*/, PyObject /**args*/)
{
if (!CActiveScheduler::Current()) {
PyErr_SetString(PyExc_AssertionError, "no ao scheduler");
return NULL;
}
Ao_timer_object *op = PyObject_New(Ao_timer_object, &Ao_timer_type);
if (op == NULL)
return PyErr_NoMemory();
op->ob_data = new Ao_timer();
if (op->ob_data == NULL) {
PyObject_Del(op);
return PyErr_NoMemory();
}
TInt error = op->ob_data->Construct();
if (error != KErrNone) {
PyObject_Del(op);
return SPyErr_SetFromSymbianOSErr(error);
}
return (PyObject *) op;
}
extern "C" PyObject *
ao_timer_after(Ao_timer_object *self, PyObject* args)
{
TReal d;
PyObject* c=NULL;
if (!PyArg_ParseTuple(args, "d|O", &d, &c))
return NULL;
if (c && !PyCallable_Check(c)) {
PyErr_SetString(PyExc_TypeError, "callable expected for 2nd argument");
return NULL;
}
if(self->ob_data->IsActive()) {
PyErr_SetString(PyExc_RuntimeError, "Timer pending - cancel first");
return NULL;
}
if (d < 0) {
PyErr_SetString(PyExc_RuntimeError, "negative number not allowed");
return NULL;
}
#ifndef EKA2
self->ob_data->After(TTimeIntervalMicroSeconds32(TInt64(d*1000*1000).GetTInt()), c);
#else
self->ob_data->After(TTimeIntervalMicroSeconds32(TInt64(d*1000*1000)), c);
#endif /*EKA2*/
Py_INCREF(Py_None);
return Py_None;
}
extern "C" PyObject *
ao_timer_cancel(Ao_timer_object *self, PyObject* /*args*/)
{
self->ob_data->Cancel();
Py_INCREF(Py_None);
return Py_None;
}
extern "C" {
static void
ao_timer_dealloc(Ao_timer_object *op)
{
delete op->ob_data;
op->ob_data = NULL;
PyObject_Del(op);
}
static const PyMethodDef ao_timer_methods[] = {
{"after", (PyCFunction)ao_timer_after, METH_VARARGS},
{"cancel", (PyCFunction)ao_timer_cancel, METH_NOARGS},
{NULL, NULL} /* sentinel */
};
static PyObject *
ao_timer_getattr(Ao_timer_object *p, char *name)
{
return Py_FindMethod((PyMethodDef*)ao_timer_methods,
(PyObject *)p, name);
}
static const PyTypeObject c_Ao_timer_type = {
PyObject_HEAD_INIT(NULL)
0,
"e32.Ao_timer",
sizeof(Ao_timer_object),
0,
/* methods */
(destructor)ao_timer_dealloc, /* tp_dealloc */
0, /* tp_print */
(getattrfunc)ao_timer_getattr, /* 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 */
};
} /* extern "C" */
/*
*
* Implementation of e32.ao_callgate
*
*/
#define Ao_callgate_type ((PYTHON_GLOBALS->tobj).t_Ao_callgate)
struct Ao_callgate_call_item {
PyObject* arg;
Ao_callgate_call_item* next;
};
#ifndef EKA2
class Ao_callgate;
#else
NONSHARABLE_CLASS(Ao_callgate);
#endif
struct Ao_callgate_object {
PyObject_VAR_HEAD
Ao_callgate* ob_data;
unsigned int ob_tid;
Ao_callgate_call_item ob_args;
};
#ifndef EKA2
class Ao_callgate : public CActive {
#else
NONSHARABLE_CLASS(Ao_callgate) : public CActive {
#endif
public:
Ao_callgate(Ao_callgate_object* aOb, PyObject* aCb, TInt aTid);
~Ao_callgate() {
Cancel();
Py_DECREF(iCb);
}
TInt Signal(TInt aStatus=KErrNone);
private:
void RunL();
void DoCancel() {
Signal(KErrCancel);
}
TRequestStatus* iPst;
PyObject* iCb;
Ao_callgate_object* iOb;
TInt iTid;
};
Ao_callgate::Ao_callgate(Ao_callgate_object* aOb, PyObject* aCb, TInt aTid):
CActive(0),iTid(aTid),iOb(aOb)
{
iCb = aCb;
Py_INCREF(iCb);
CActiveScheduler::Add(this);
iStatus = KRequestPending;
iPst = &iStatus;
SetActive();
}
TInt Ao_callgate::Signal(TInt aReason)
{
if (iStatus != KRequestPending)
return KErrNone;
RThread t;
TInt error = t.Open(iTid);
if (error == KErrNone) {
t.RequestComplete(iPst, aReason);
t.Close();
}
return error;
}
void Ao_callgate::RunL()
{
PyEval_RestoreThread(PYTHON_TLS->thread_state);
Ao_callgate_call_item* p = iOb->ob_args.next;
iOb->ob_args.next = NULL;
while (p) {
PyObject* tmp_r = NULL;
tmp_r = PyEval_CallObject(iCb, p->arg);
Py_XDECREF(tmp_r);
if (PyErr_Occurred())
PyErr_Print();
Ao_callgate_call_item* tmp = p->next;
Py_XDECREF(p->arg);
PyMem_Free(p);
p = tmp;
}
PyEval_SaveThread();
iStatus = KRequestPending;
iPst = &iStatus;
SetActive();
}
extern "C" PyObject *
e32_ao_callgate(PyObject* /*self*/, PyObject* args)
{
if (!CActiveScheduler::Current()) {
PyErr_SetString(PyExc_AssertionError, "no ao scheduler");
return NULL;
}
PyObject* c;
if (!PyArg_ParseTuple(args, "O", &c) || !PyCallable_Check(c))
return NULL;
Ao_callgate_object *op = PyObject_New(Ao_callgate_object,
&Ao_callgate_type);
if (op == NULL)
return PyErr_NoMemory();
op->ob_args.arg = NULL;
op->ob_args.next = NULL;
op->ob_tid = RThread().Id();
if (!(op->ob_data = new Ao_callgate(op, c, op->ob_tid))) {
PyObject_Del(op);
return PyErr_NoMemory();
}
return (PyObject *) op;
}
extern "C" PyObject *
ao_cg_call(PyObject* self, PyObject* arg, PyObject* /*kw*/)
{
Ao_callgate_object *op = (Ao_callgate_object*)self;
Ao_callgate_call_item* n =
(Ao_callgate_call_item*)PyMem_Malloc(sizeof(Ao_callgate_call_item));
if (!n)
return PyErr_NoMemory();
n->arg = arg;
Py_XINCREF(arg);
n->next = NULL;
Ao_callgate_call_item* p = &(op->ob_args);
while (p->next) p = p->next;
p->next = n;
TInt error = op->ob_data->Signal();
if (error != KErrNone) {
p->next = NULL;
Py_XDECREF(n->arg);
PyMem_Free(n);
}
RETURN_ERROR_OR_PYNONE(error);
}
extern "C" {
static void
ao_cg_dealloc(Ao_callgate_object *op)
{
if ((TUint)RThread().Id() == op->ob_tid) {
delete op->ob_data;
op->ob_data = NULL;
}
Ao_callgate_call_item* p = op->ob_args.next;
while (p) {
Ao_callgate_call_item* tmp = p->next;
Py_XDECREF(p->arg);
PyMem_Free(p);
p = tmp;
}
PyObject_Del(op);
}
static const PyTypeObject c_Ao_callgate_type = {
PyObject_HEAD_INIT(NULL)
0,
"e32.Ao_callgate",
sizeof(Ao_callgate_object),
0,
/* methods */
(destructor)ao_cg_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 */
ao_cg_call, /* tp_call */
};
} /* extern "C" */
/*
*
* Implementation of e32._as_level
*
*/
class CMyAccessor : public CActiveScheduler
{
public:
TInt MyLevel() {return Level();}
};
extern "C" PyObject *
e32__as_level(PyObject* /*self*/, PyObject* /*args*/)
{
TInt l =
STATIC_CAST(CMyAccessor*, CActiveScheduler::Current())->MyLevel();
return Py_BuildValue("i", l);
}
/*
* This does not work on target (!?)
*
* extern "C" double
* e32_clock()
* {
* TTimeIntervalMicroSeconds cpu_time(0.0);
*
* RThread().GetCpuTime(cpu_time);
*
* return ((cpu_time.Int64().GetTReal()) / (1000.0 * 1000.0));
* }
*/
extern "C" double
e32_clock()
{
TInt period = 1000*1000;
HAL::Get(HALData::ESystemTickPeriod, period);
return (((double)(((double)User::TickCount())*
(((double)period)/1000.0)))/1000.0);
}
extern "C" double
e32_UTC_offset()
{
#ifndef EKA2
TLocale loc;
return TInt64(loc.UniversalTimeOffset().Int()).GetTReal();
#else
TLocale loc;
return TReal64(loc.UniversalTimeOffset().Int());
#endif /*EKA2*/
}
extern "C" int
e32_check_stack()
{
#ifndef EKA2
TInt heap_sz, stack_sz;
if (RThread().GetRamSizes(heap_sz, stack_sz) == KErrNone) {
if (((TUint)&heap_sz-(TUint)((RThread().Heap())->Base()-stack_sz)) > 0x800)
return 0;
}
else
return 0;
return (-1);
#else
return 0; // XXX Hard coded stack ok
#endif /*EKA2*/
}
/*
*
* Implementation of e32.is_ui_thread
*
*/
static TBool is_main_thread()
{
return ((PYTHON_GLOBALS->main_thread == 0) ||
(PYTHON_GLOBALS->main_thread == PyThread_get_thread_ident()));
}
extern "C" PyObject *
e32_is_ui_thread(PyObject* /*self*/, PyObject* /*args*/)
{
PyObject* rval = (is_main_thread() ? Py_True : Py_False);
Py_INCREF(rval);
return rval;
}
/*
*
* Implementation of e32.in_emulator
*
*/
extern "C" PyObject *
e32_in_emulator(PyObject* /*self*/, PyObject* /*args*/)
{
#ifdef __WINS__
PyObject* rval = Py_True;
#else
PyObject* rval = Py_False;
#endif
Py_INCREF(rval);
return rval;
}
/*
*
* Implementation of e32.set_home_time
*
*/
extern "C" PyObject *
e32_set_home_time(PyObject* /*self*/, PyObject* args)
{
TInt error = KErrNone;
TReal time = 0;
if (!PyArg_ParseTuple(args, "d", &time)){
return NULL;
}
TTime conv_time;
pythonRealAsTTime(time, conv_time);
error = User::SetHomeTime(conv_time);
RETURN_ERROR_OR_PYNONE(error);
}
#ifdef USE_GLOBAL_DATA_HACK
extern "C" PyObject *
e32_globcnt(PyObject* /*self*/, PyObject* /*args*/)
{
PyObject* rval = Py_BuildValue("i", *(PYTHON_GLOBALS->globptr));
return rval;
}
#endif
/*
*
* Implementation of e32._uidcrc_app
*
*/
class TMyCheckedAppUid : public TCheckedUid
{
public:
TMyCheckedAppUid(TUint uid):
TCheckedUid(TUidType(TUid::Uid(KDynamicLibraryUidValue),
TUid::Uid(KAppUidValue16),
TUid::Uid(uid))) {;}
TUint CheckSum() {return Check();}
};
extern "C" PyObject *
e32_uidcrc_app(PyObject* /*self*/, PyObject *args)
{
TUint uid;
if (!PyArg_ParseTuple(args, "i", &uid))
return NULL;
TMyCheckedAppUid chk(uid);
return Py_BuildValue("l", chk.CheckSum());
}
static int call_stdo(const char *buf, int n)
{
PyObject* args = Py_BuildValue("(N)",
PyUnicode_Decode(buf, n, NULL, NULL));
PyObject* rval =
PyEval_CallObject(SPyGetGlobalString("e32_stdo"), args);
Py_XDECREF(args);
Py_XDECREF(rval);
return n;
}
static int print_stdo(const char *buf, int n)
{
RFs rfs;
if (rfs.Connect() == KErrNone) {
RFile f;
SPy_Python_globals* pg = PYTHON_GLOBALS;
TPtrC fn((TUint16*)pg->stdo_buf, pg->stdo_buf_len);
TInt error = f.Open(rfs, fn, EFileWrite);
if (error == KErrNotFound)
error = f.Create(rfs, fn, EFileWrite);
TInt dummy;
if ((error == KErrNone) && (f.Seek(ESeekEnd, dummy) == KErrNone))
f.Write(TPtrC8((const TUint8*)buf, n));
f.Close();
rfs.Close();
}
return n;
}
extern "C" PyObject *
e32_stdo(PyObject* /*self*/, PyObject* args)
{
PyObject* c;
if (!PyArg_ParseTuple(args, "O", &c))
return NULL;
SPy_Python_globals* pg = PYTHON_GLOBALS;
if (PyCallable_Check(c)) {
if (SPyAddGlobalString("e32_stdo", c))
return NULL;
((CSPyInterpreter*)pg->interpreter)->iStdO = &call_stdo;
}
else if (PyUnicode_Check(c)) {
TPtr buf((TUint16*)pg->stdo_buf, 0x100);
buf.Copy(PyUnicode_AsUnicode(c), PyUnicode_GetSize(c));
pg->stdo_buf_len = PyUnicode_GetSize(c);
((CSPyInterpreter*)pg->interpreter)->iStdO = &print_stdo;
}
else if (c == Py_None) {
((CSPyInterpreter*)pg->interpreter)->iStdO = NULL;
}
else {
PyErr_SetString(PyExc_TypeError, "callable or unicode expected");
return NULL;
}
Py_INCREF(Py_None);
return Py_None;
}
#ifndef EKA2
extern "C" PyObject *
e32_mem_info(PyObject* /*self*/)
{
TInt error;
TInt heap_sz, stack_sz, current_heap_usage,
max_stack_usage, current_pyheap_usage;
error = RThread().GetRamSizes(heap_sz, stack_sz);
if (error == KErrNone) {
(RThread().Heap())->AllocSize(current_heap_usage);
((CSPyInterpreter*)PYTHON_GLOBALS->interpreter)->
iPyheap->AllocSize(current_pyheap_usage);
}
if (error == KErrNone) {
TUint8* pbase = (RThread().Heap())->Base();
TUint8* pstacklast = pbase - stack_sz;
while (*pstacklast == 0x29)
pstacklast++;
max_stack_usage = pbase - pstacklast;
}
if (error != KErrNone)
return SPyErr_SetFromSymbianOSErr(error);
else
return Py_BuildValue("(iiiii)", heap_sz, stack_sz,
current_heap_usage, max_stack_usage,
current_pyheap_usage);
}
#endif /*EKA2*/
extern "C" PyObject *
e32_strerror(PyObject* /*self*/, PyObject* args)
{
int errcode;
if (!PyArg_ParseTuple(args, "i", &errcode))
return NULL;
return SPyErr_SymbianOSErrAsString(errcode);
}
extern "C" {
static const PyMethodDef e32_methods[] = {
{"Ao_lock", (PyCFunction)new_e32_ao_object, METH_NOARGS, NULL},
{"Ao_timer", (PyCFunction)new_e32_ao_timer_object, METH_NOARGS, NULL},
{"ao_yield", (PyCFunction)e32_ao_yield, METH_NOARGS, NULL},
{"ao_sleep", (PyCFunction)e32_ao_sleep, METH_VARARGS, NULL},
{"ao_callgate", (PyCFunction)e32_ao_callgate, METH_VARARGS, NULL},
{"_as_level", (PyCFunction)e32__as_level, METH_NOARGS, NULL},
{"start_server", (PyCFunction)e32_start_server, METH_VARARGS, NULL},
{"start_exe", (PyCFunction)e32_start_exe, METH_VARARGS, NULL},
{"drive_list", (PyCFunction)e32_drive_list, METH_NOARGS, NULL},
{"file_copy", (PyCFunction)e32_file_copy, METH_VARARGS, NULL},
{"is_ui_thread", (PyCFunction)e32_is_ui_thread, METH_NOARGS, NULL},
{"in_emulator", (PyCFunction)e32_in_emulator, METH_NOARGS, NULL},
{"set_home_time", (PyCFunction)e32_set_home_time, METH_VARARGS, NULL},
{"_uidcrc_app", (PyCFunction)e32_uidcrc_app, METH_VARARGS, NULL},
{"_stdo", (PyCFunction)e32_stdo, METH_VARARGS, NULL},
#ifndef EKA2
{"_mem_info", (PyCFunction)e32_mem_info, METH_NOARGS, NULL},
#endif /*EKA2*/
{"strerror", (PyCFunction)e32_strerror, METH_VARARGS, NULL},
#ifdef USE_GLOBAL_DATA_HACK
{"_globcnt", (PyCFunction)e32_globcnt, METH_NOARGS, NULL},
#endif
{NULL, NULL} /* sentinel */
};
DL_EXPORT(void) inite32(void)
{
PyObject *m, *d;
Ao_lock_type = c_Ao_lock_type;
Ao_lock_type.ob_type = &PyType_Type;
Ao_timer_type = c_Ao_timer_type;
Ao_timer_type.ob_type = &PyType_Type;
Ao_callgate_type = c_Ao_callgate_type;
Ao_callgate_type.ob_type = &PyType_Type;
m = Py_InitModule("e32", (PyMethodDef*)e32_methods);
d = PyModule_GetDict(m);
PyDict_SetItemString(d,"pys60_version_info",
Py_BuildValue("(iiisi)", PYS60_VERSION_MAJOR, PYS60_VERSION_MINOR, PYS60_VERSION_MICRO,
PYS60_VERSION_TAG, PYS60_VERSION_SERIAL));
PyDict_SetItemString(d,"pys60_version", Py_BuildValue("s", PYS60_VERSION_STRING));
PyDict_SetItemString(d,"s60_version_info", Py_BuildValue("(ii)",
#if SERIES60_VERSION==12
1, 2
#endif
#if SERIES60_VERSION==20
2, 0
#endif
#if SERIES60_VERSION==26
2, 6
#endif
#if SERIES60_VERSION==28
2, 8
#endif
#if SERIES60_VERSION==30
3, 0
#endif
));
}
} /* extern "C" */