VariableText.__init__(self)
GUIComponent.__init__(self)
self.doClock()
+
+ self.clockTimer = eTimer()
+ self.clockTimer.timeout.get().append(self.doClock)
+ self.clockTimer.start(1000)
# "funktionalitaet"
def doClock(self):
TUXBOX_APPS_LIB_PKGCONFIG(SIGC,sigc++-1.2)
TUXBOX_APPS_LIB_PKGCONFIG(XMLTREE,tuxbox-xmltree)
-CPPFLAGS="$CPPFLAGS $FREETYPE_CFLAGS $FRIBIDI_CFLAGS $ID3TAG_CFLAGS $MAD_CFLAGS $PLUGINS_CFLAGS $PNG_CFLAGS $SIGC_CFLAGS $XMLTREE_CFLAGS"
+# fixme: decent python stuff
+CPPFLAGS="$CPPFLAGS $FREETYPE_CFLAGS $FRIBIDI_CFLAGS $ID3TAG_CFLAGS $MAD_CFLAGS $PLUGINS_CFLAGS $PNG_CFLAGS $SIGC_CFLAGS $XMLTREE_CFLAGS -I/usr/include/python2.3"
CXXFLAGS="$CXXFLAGS -fno-rtti -fno-exceptions -Wall"
TUXBOX_APPS_GETTEXT
#include <fcntl.h>
#include <unistd.h>
+#include <errno.h>
#include <lib/base/eerror.h>
}
void eTimer::stop()
-{
+{
+ eDebug("stop timer");
if (bActive)
{
bActive=false;
context.addTimer(this); // add Timer to context TimerList
}
-void eTimer::activate() // Internal Funktion... called from eApplication
+void eTimer::activate() // Internal Function... called from eApplication
{
timeval now;
gettimeofday(&now, 0);
void eMainloop::processOneEvent()
{
-// process pending timers...
+ /* notes:
+ - we should use epoll(4)
+ - timer are checked twice. there was a strong reason for it, but i can't remember. (FIXME)
+ - for each time, we gettimeofday() and check wether the timer should fire.
+ we should do this all better - we know how long the poll last, so we know which
+ timers should fire. Problem is that a timer handler could have required so
+ much time that another timer fired.
+
+ A probably structure could look
+
+ while (1)
+ {
+ time = gettimeofday()
+ timeout = calculate_pending_timers(time);
+
+ doPoll(timeout or infinite);
+
+ if (poll_had_results)
+ handle_poll_handler();
+ else
+ fire_timers(time + timeout)
+ }
+
+ the gettimeofday() call is required because fire_timers could last more
+ than nothing.
+
+ when poll did no timeout, we don't handle timers, as this will be done
+ in the next iteration (without adding overhead - we had to get the new
+ time anyway
+ */
+
+ // first, process pending timers...
long usec=0;
while (TimerList && (usec = timeout_usec( TimerList.begin()->getNextActivation() ) ) <= 0 )
TimerList.begin()->activate();
+ // build the poll aray
int fdAnz = notifiers.size();
pollfd* pfd = new pollfd[fdAnz]; // make new pollfd array
-// fill pfd array
std::map<int,eSocketNotifier*>::iterator it(notifiers.begin());
for (int i=0; i < fdAnz; i++, it++)
{
pfd[i].events = it->second->getRequested();
}
- int ret=poll(pfd, fdAnz, TimerList ? usec / 1000 : -1); // milli .. not micro seks
+ // to the poll. When there are no timers, we have an infinite timeout
+ int ret=poll(pfd, fdAnz, TimerList ? usec / 1000 : -1); // convert to us
if (ret>0)
{
-// eDebug("bin aussem poll raus und da war was");
for (int i=0; i < fdAnz ; i++)
{
if( notifiers.find(pfd[i].fd) == notifiers.end())
if (!--ret)
break;
} else if (pfd[i].revents & (POLLERR|POLLHUP|POLLNVAL))
- eDebug("poll: unhandled POLLERR/HUP/NVAL for fd %d(%d)", pfd[i].fd,pfd[i].revents);
+ eFatal("poll: unhandled POLLERR/HUP/NVAL for fd %d(%d) -> FIX YOUR CODE", pfd[i].fd,pfd[i].revents);
}
- }
- else if (ret<0)
- eDebug("poll made error");
+ } else if (ret<0)
+ {
+ /* when we got a signal, we get EINTR. we do not care,
+ because we check current time in timers anyway. */
+ if (errno != EINTR)
+ eDebug("poll made error (%m)");
+ }
- // check Timers...
+ // check timer...
while ( TimerList && timeout_usec( TimerList.begin()->getNextActivation() ) <= 0 )
TimerList.begin()->activate();
return retval;
}
+ /* use with care! better: don't use it anymore. it was used for gui stuff, but
+ doesn't allow multiple paths (or active dialogs, if you want it that way.) */
void eMainloop::enter_loop()
{
loop_level++;
#include <time.h>
#include <lib/base/eptrlist.h>
+#include <lib/python/connections.h>
#include <libsig_comp.h>
class eApplication;
eSocketNotifier(eMainloop *context, int fd, int req, bool startnow=true);
~eSocketNotifier();
- Signal1<void, int> activated;
+ PSignal1<void, int> activated;
void activate(int what) { /*emit*/ activated(what); }
void start();
eTimer(eMainloop *context): context(*context), bActive(false) { }
~eTimer() { if (bActive) stop(); }
- Signal0<void> timeout;
+ PSignal0<void> timeout;
void activate();
bool isActive() { return bActive; }
goto nolfb;
}
- showConsole(0);
+// showConsole(0);
return;
nolfb:
lfb=0;
#include <lib/gui/ewidgetdesktop.h>
#include <lib/gui/ewidget.h>
+#include <lib/base/ebase.h>
void eWidgetDesktop::addRootWidget(eWidget *root, int top)
{
void eWidgetDesktop::invalidate(const gRegion ®ion)
{
+ if (m_timer && m_dirty_region.empty())
+ m_timer->start(0, 1); // start singleshot redraw timer
m_dirty_region |= region;
}
m_dc = dc;
}
-eWidgetDesktop::eWidgetDesktop(eSize size): m_screen_size(size)
+void eWidgetDesktop::setRedrawTask(eMainloop &ml)
+{
+ if (m_mainloop)
+ {
+ delete m_timer;
+ m_timer = 0;
+ m_mainloop = 0;
+ }
+ m_mainloop = &ml;
+ m_timer = new eTimer(m_mainloop);
+ CONNECT(m_timer->timeout, eWidgetDesktop::paint);
+
+ if (!m_dirty_region.empty())
+ m_timer->start(0, 1);
+}
+
+eWidgetDesktop::eWidgetDesktop(eSize size): m_screen_size(size), m_mainloop(0), m_timer(0)
{
}
#include <lib/base/eptrlist.h>
class eWidget;
+class eMainloop;
+class eTimer;
-class eWidgetDesktop
+class eWidgetDesktop: public Object
{
public: // weil debug
eSize m_screen_size;
void invalidate(const gRegion ®ion);
void paint();
void setDC(gDC *dc);
+
+ void setRedrawTask(eMainloop &ml);
private:
ePtrList<eWidget> m_root;
void calcWidgetClipRegion(eWidget *widget, gRegion &parent_visible);
+
+ eMainloop *m_mainloop;
+ eTimer *m_timer;
};
#endif
void eWindowStyleSimple::paintBackground(gPainter &painter, const ePoint &offset, const eSize &size)
{
- eDebug("eWindowStyleSimple::paintBackground");
painter.setBackgroundColor(m_background_color);
painter.clear();
}
INCLUDES = \
-I$(top_srcdir)/include \
- -I$(top_srcdir)/src \
- -I/usr/include/python2.3
+ -I$(top_srcdir)/src
noinst_LIBRARIES = libenigma_python.a
libenigma_python_a_SOURCES = \
- python.cpp enigma_python_wrap.cxx
+ python.cpp enigma_python_wrap.cxx connections.cpp
enigma_python_wrap.cxx: enigma_python.i
swig -I$(top_srcdir)/ -c++ -python enigma_python.i
+/*
+ NOTE: you have two options when adding classes so that
+ they are callable *from* python.
+
+ - either you %include the header file
+ - or you re-declare it
+
+ In both cases, you must #include the required
+ header file (i.e. the header file itself), otherwise
+ enigma_python_wrap.cxx won't build.
+
+ In case you import the whole header file,
+ please make sure that no unimportant stuff
+ is wrapped, as this makes the wrapper stuff
+ much more complex and it can probably break
+ very easily because of missing typemaps etc.
+
+ you could make use of dizzy macros to ensure
+ that some stuff is left out when parsed as SWIG
+ definitions, but be sure to not modify the binary
+ representation. DON'T USE #ifdef SWIG_COMPILE
+ for leaving out stuff (unless you *really* know
+ what you are doing,of course!). you WILL break it.
+
+ The better way (with more work) is to re-declare
+ the class. It won't be compiled, so you can
+ leave out stuff as you like.
+
+
+
+Oh, things like "operator= is private in this context" etc.
+is usually caused by not marking PSignals as immutable.
+
+*/
+
+
%module enigma
%{
#define SWIG_COMPILE
+#include <lib/base/ebase.h>
#include <lib/base/smartptr.h>
#include <lib/base/eerror.h>
#include <lib/base/econfig.h>
#include <lib/gui/ewidgetdesktop.h>
#include <lib/gui/eslider.h>
#include <lib/python/connections.h>
+
+extern void runMainloop();
%}
#define DEBUG
$1 = $input->get();
}
+
+/************** base **************/
+
+%immutable eTimer::timeout;
+
+class eTimer
+{
+public:
+ eTimer(eMainloop *context = eApp);
+ PSignal0<void> timeout;
+
+ void start(long msec, bool singleShot=false);
+ void stop();
+ void changeInterval(long msek);
+};
+
+/************** debug **************/
+
+void runMainloop();
pValue = PyObject_CallObject(pFunc, pArgs);
if (pValue != NULL)
{
- printf("Result of call: %ld\n", PyInt_AsLong(pValue));
+// printf("Result of call: %ld\n", PyInt_AsLong(pValue));
Py_DECREF(pValue);
} else
{
INCLUDES = \
- -I$(top_srcdir)/include
+ -I$(top_srcdir)/include \
+ -I/usr/include/python2.3
bin_PROGRAMS = enigma2
#include <lib/gui/ewindow.h>
#include <lib/python/python.h>
+#include <lib/python/connections.h>
#ifdef OBJECT_DEBUG
int object_total_remaining;
printf("%d items left\n", object_total_remaining);
}
#endif
-using namespace std;
- void print(const string &str, const char *c)
- {
- printf("%s (%s)\n", str.c_str(), c);
- }
void dumpRegion(const gRegion ®ion)
{
eWidgetDesktop *wdsk;
+// typedef struct _object PyObject;
+
+void print(int i)
+{
+ printf("C++ says: it's a %d!!!\n", i);
+}
+
int main(int argc, char **argv)
{
#ifdef OBJECT_DEBUG
wdsk = &dsk;
dsk.setDC(my_dc);
-
- eWindow *wnd = new eWindow(&dsk);
- wnd->move(ePoint(100, 100));
- wnd->resize(eSize(200, 200));
- wnd->show();
-
- eLabel *label = new eButton(wnd);
- label->setText("Hello!!");
- label->move(ePoint(40, 40));
- label->resize(eSize(100, 40));
-
- label = new eButton(wnd);
- label->setText("2nd!!");
- label->move(ePoint(40, 90));
- label->resize(eSize(100, 40));
-
-#if 0
- eWidget *bla2 = new eWidget(0);
- dsk.addRootWidget(bla2, 0);
-
- bla2->move(ePoint(160, 160));
- bla2->resize(eSize(200, 200));
- bla2->show();
#endif
-// dsk.recalcClipRegions();
-// dsk.paint();
-// dsk.invalidate(gRegion(eRect(0, 0, 720, 576)));
-
-// dumpRegion(wnd->m_visible_region);
-// dumpRegion(label->m_visible_region);
-// dumpRegion(label->m_visible_region);
+ /* redrawing is done in an idle-timer, so we have to set the context */
+ dsk.setRedrawTask(main);
- eDebug("painting!");
-
-
ePython python;
- printf("about to execute TEST :)\n");
- python.execute("mytest", "test");
-
- sleep(2);
-#endif
-
-#if 0
-
- // connections mit parametern: geht! :)
- using namespace std;
- using namespace SigC;
-
-
- Signal1<void,const string &> printer;
- int i;
- for (i=1; i<argc; ++i)
- printer.connect(bind(slot(print), argv[i]));
- printer("hello world\n");
-#endif
+ printf("executing main\n");
+ python.execute("mytest", "__main__");
return 0;
}
return wdsk;
}
+void runMainloop()
+{
+ eApp->exec();
+}
def create(self, comp):
comp.createGUIScreen(self.parent)
-
-
-def test():
+def runScreenTest():
desktop = getDesktop()
- print "desktop: " + str(desktop)
wnd = eWindow(desktop)
- print "window " + str(wnd)
- wnd.setTitle("python")
+ mainwnd = wnd
+ wnd.setTitle("Screen from python!")
wnd.move(ePoint(300, 100))
wnd.resize(eSize(300, 300))
gui = GUIOutputDevice()
gui.parent = wnd
gui.create(components["$002"])
-# for (x,y) in components["$001"].data.items():
-# print str(x) + " -> " + str(y) + " (" + y["instance"].getText() + ")"
-# print components["$001"].data["okbutton"]["instance"].doClick()
-
-# diese sachen gehoeren in den skin! :)
applyGUIskin(components["$002"], None, "clockDialog")
-
-# das ist dann schon die echte funktionalitaet ;)
- components["clock"].doClock()
- components["clock"].doClock()
-
-
-# output as html
- print "--------------------------------------"
- html.create(components["$001"])
- print "--------------------------------------"
- html.create(components["$002"])
- print "--------------------------------------"
-
-
-# direkter test der GUI aus python:
-# label1 = eLabel(wnd)
-# label1.setText("hello world!\nfrom python!")
-# label1.move(ePoint(10, 10))
-# label1.resize(eSize(80, 50))
-#
-# label2 = eLabel(wnd)
-# label2.setText("the second\nlabel works\nas well!")
-# label2.move(ePoint(90, 10))
-# label2.resize(eSize(80, 50))
-#
-# button = eButton(wnd)
-# button.setText("OK")
-# button.move(ePoint(200, 10))
-# button.resize(eSize(80, 50))
wnd.show()
- components["$002"].data["okbutton"]["instance"].push()
-
- for x in range(200):
- time.sleep(0.1)
- components["clock"].doClock()
- if x > 100:
- r = 200 - x
- else:
- r = x
-# components["$002"]["okbutton"].setValue(r)
- desktop.paint()
-
-#
-# print "delete label1"
-# del button
-# del label2
-# del label1
-# print "delete wnd"
-# del wnd
-# print "bye"
-
-
+# components["$002"].data["okbutton"]["instance"].push()
+ runMainloop()
return 0
-def testI2(a):
- print "PYTHON says: it's a " + str(a) + "!!!"
- return 0
-def testI(a = 0):
- print "magic integer is " + str(a)
-
- list = testsignal.get()
- print "list -> " + str(list)
- list.append(testI2)
- return 1
+# first, setup a screen
+runScreenTest()
+
+# now, run the mainloop