#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Author: Andreas Büsching <crunchy@bitkipper.net>
#
# wxWindows notifier wrapper
#
# Copyright (C) 2004, 2005, 2006
# Andreas Büsching <crunchy@bitkipper.net>
#
# This library is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License version
# 2.1 as published by the Free Software Foundation.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA
"""wxWindows notifier wrapper"""
from select import select
import time
from wxPython.wx import *
import thread
IO_READ = 1
IO_WRITE = 2
IO_EXCEPT = 4
#------------------------------------------------------------------------------
# Event to communicate with gui-thread (main-thread)
wxEVT_UDPSOCKETEVENT = wxNewEventType()
def EVT_UDPSOCKETEVENT( handler, func ):
"""Bind UDP-Socket events to a callback function"""
handler.Connect( -1, -1, wxEVT_UDPSOCKETEVENT, func )
class UDPSocketEvent( wxPyEvent ):
"""UDP-Socket events. Send from select-thread to gui-thread"""
def __init__( self, socket ):
wxPyEvent.__init__( self )
self.SetEventType( wxEVT_UDPSOCKETEVENT )
self.socket = socket
self.msg, self.sender = socket.recvfrom( 256000 )
def recvfrom( self, size ):
"""this function is to fake a real socket"""
if size >= len( self.msg ):
res = self.msg
self.msg = []
else:
res = self.msg[:size]
self.msg = self.msg[size:]
return ( res, self.sender )
ID_Timer = wxNewId()
class Notifier( wxEvtHandler ):
def __init__( self ):
wxEvtHandler.__init__( self )
self.sockets = {}
self.timers = []
# max seconds till new socket gets "selected"
# decrease this value if you want to add/remove
# sockets often
self.timeout = 5
thread.start_new_thread( self.otherThreadLoop, () )
self.app = wxPySimpleApp()
EVT_UDPSOCKETEVENT( self, self.OnSocket )
self.timer = wxTimer( self, ID_Timer )
EVT_TIMER( self, ID_Timer, self.OnTimer )
def addSocket( self, socket, method ):
"""The first argument specifies a socket, the second argument
has to be a function that is called whenever there is data
ready in the socket. The callback function gets the socket
back as only argument."""
self.sockets[socket] = method
def removeSocket( self, socket ):
"""Remove given socket from scheduler"""
del self.sockets[socket]
def addTimer( self, interval, method, data = None ):
"""The first argument specifies an interval in seconds, the
second argument a function. This is function is called after
interval seconds. If it returns true it's called again after
interval seconds, otherwise it is removed from the
scheduler. The third (optional) argument is a parameter given
to the called function."""
t = time.time()
self.timers.append( (interval, t, method, data) )
if len( self.timers ) == 1:
self.timer.Start( (self.timers[0][0]+self.timers[0][1]-t) )
def removeTimer( self, method ):
"""Removes _all_ functioncalls to the method given as argument
from the scheduler."""
remove = []
for i in range( 0, len( self.timers ) ):
if self.timers[ i ][ 2 ] == method:
remove.append( i )
remove.reverse()
for i in remove: del self.timers[ i ]
def otherThreadLoop( self ):
"""socketloop sits in its own thread and sends events to the
main thread"""
while 1:
if len( self.sockets.keys() ) != 0:
r,w,e = select( self.sockets.keys(), [], [], self.timeout )
for sock in r:
evt = UDPSocketEvent( sock )
wxPostEvent( self, evt )
else: time.sleep( self.timeout )
def OnSocket( self, evt ):
"""this is where the udp-events are send to"""
self.sockets[evt.socket]( evt )
def OnTimer( self, evt ):
"""gets called by wx-mainloop, mbus-timers are handled here"""
remove = []
mindelta = 86400 * 1000 # one day
now = time.time() * 1000
for i in range(0,len(self.timers)):
delta = self.timers[i][1] + self.timers[i][0] - now
if delta < 0:
try:
if not self.timers[i][2]( self.timers[i][3] ):
remove.append( i )
else: self.timers[i] = ( self.timers[i][0], now, \
self.timers[i][2], self.timers[i][3] )
except:
remove.append( i )
delta = self.timers[i][0]
if mindelta > delta: mindelta = delta
remove.reverse()
for r in remove: del self.timers[r]
if mindelta == 86400: self.timer.Stop()
else: self.timer.Start( mindelta )
def loop( self ):
"""Execute main loop forver."""
self.app.MainLoop()
def step( self ):
raise Error, "stepping not supported in wx-Mode"
notifier_instance = Notifier()
socket_add = notifier_instance.addSocket
socket_remove = notifier_instance.removeSocket
timer_add = notifier_instance.addTimer
timer_remove = notifier_instance.removeTimer
step = notifier_instance.step
loop = notifier_instance.loop
dispatcher_add = None
dispatcher_remove = None
syntax highlighted by Code2HTML, v. 0.9.1