[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] r8042 - gnuradio/branches/developers/michaelld/wxgui/g
From: |
michaelld |
Subject: |
[Commit-gnuradio] r8042 - gnuradio/branches/developers/michaelld/wxgui/gr-wxgui/src/python |
Date: |
Tue, 18 Mar 2008 20:25:56 -0600 (MDT) |
Author: michaelld
Date: 2008-03-18 20:25:56 -0600 (Tue, 18 Mar 2008)
New Revision: 8042
Added:
gnuradio/branches/developers/michaelld/wxgui/gr-wxgui/src/python/gr_input_watcher.py
Modified:
gnuradio/branches/developers/michaelld/wxgui/gr-wxgui/src/python/fftsink2.py
gnuradio/branches/developers/michaelld/wxgui/gr-wxgui/src/python/numbersink2.py
gnuradio/branches/developers/michaelld/wxgui/gr-wxgui/src/python/scopesink2.py
gnuradio/branches/developers/michaelld/wxgui/gr-wxgui/src/python/waterfallsink2.py
Log:
Moved threading into a separate file and classes; allows for code
reuse in the various sinks that require a separate thread to handle
message queueing.
Modified:
gnuradio/branches/developers/michaelld/wxgui/gr-wxgui/src/python/fftsink2.py
===================================================================
---
gnuradio/branches/developers/michaelld/wxgui/gr-wxgui/src/python/fftsink2.py
2008-03-18 20:54:55 UTC (rev 8041)
+++
gnuradio/branches/developers/michaelld/wxgui/gr-wxgui/src/python/fftsink2.py
2008-03-19 02:25:56 UTC (rev 8042)
@@ -21,16 +21,17 @@
#
from gnuradio import gr, gru, window
-from gnuradio.wxgui import stdgui2
-import wx
-import gnuradio.wxgui.plot as plot
-import numpy
-import threading
-import math
+from gnuradio.wxgui import stdgui2, plot
+from gnuradio.wxgui.gr_input_watcher import *
+import wx, numpy, math
-default_fftsink_size = (640,240)
+# programming to handle defaults and user preferences
+
+default_fftsink_size = wx.Size (640,240)
default_fft_rate = gr.prefs().get_long('wxgui', 'fft_rate', 15)
+# classes to handle fft sink
+
class fft_sink_base(object):
def __init__(self, input_is_real=False, baseband_freq=0, y_per_div=10,
y_divs=8, ref_level=50,
@@ -178,50 +179,6 @@
# ------------------------------------------------------------------------
-myDATA_EVENT = wx.NewEventType()
-EVT_DATA_EVENT = wx.PyEventBinder (myDATA_EVENT, 0)
-
-
-class DataEvent(wx.PyEvent):
- def __init__(self, data):
- wx.PyEvent.__init__(self)
- self.SetEventType (myDATA_EVENT)
- self.data = data
-
- def Clone (self):
- self.__class__ (self.GetId())
-
-
-class input_watcher (threading.Thread):
- def __init__ (self, msgq, fft_size, event_receiver, **kwds):
- threading.Thread.__init__ (self, **kwds)
- self.setDaemon (1)
- self.msgq = msgq
- self.fft_size = fft_size
- self.event_receiver = event_receiver
- self.keep_running = True
- self.start ()
-
- def run (self):
- while (self.keep_running):
- msg = self.msgq.delete_head() # blocking read of message queue
- itemsize = int(msg.arg1())
- nitems = int(msg.arg2())
-
- s = msg.to_string() # get the body of the msg as a
string
-
- # There may be more than one FFT frame in the message.
- # If so, we take only the last one
- if nitems > 1:
- start = itemsize * (nitems - 1)
- s = s[start:start+itemsize]
-
- complex_data = numpy.fromstring (s, numpy.float32)
- de = DataEvent (complex_data)
- wx.PostEvent (self.event_receiver, de)
- del de
-
-
class fft_window (plot.PlotCanvas):
def __init__ (self, fftsink, parent, id = -1,
pos = wx.DefaultPosition, size = wx.DefaultSize,
@@ -239,14 +196,32 @@
self.build_popup_menu()
self.set_baseband_freq(0.0)
-
- EVT_DATA_EVENT (self, self.set_data)
- wx.EVT_CLOSE (self, self.on_close_window)
+
self.Bind(wx.EVT_RIGHT_UP, self.on_right_click)
self.Bind(wx.EVT_MOTION, self.evt_motion)
-
- self.input_watcher = input_watcher(fftsink.msgq, fftsink.fft_size,
self)
+ wx.EVT_CLOSE (self, self.on_close_window)
+
+ self.data_event = gr_window_data_event (self, self.set_data)
+ self.input_watcher = gr_input_watcher (fftsink.msgq, self,
+ self.data_event,
+ self.msg_processor)
+
+ def msg_processor (self, msg):
+ itemsize = int (msg.arg1 ())
+ nitems = int (msg.arg2 ())
+
+ # get the body of the msg as a string
+ s = msg.to_string ()
+
+ # There may be more than one FFT frame in the message.
+ # If so, take only the last one.
+ if nitems > 1:
+ start = itemsize * (nitems - 1)
+ s = s[start:(start+itemsize)]
+
+ return numpy.fromstring (s, numpy.float32)
+
def set_scale(self, freq):
x = max(abs(self.fftsink.sample_rate), abs(self.fftsink.baseband_freq))
if x >= 1e9:
@@ -269,10 +244,9 @@
self.fftsink.set_baseband_freq(baseband_freq)
def on_close_window (self, event):
- print "fft_window:on_close_window"
+# print "fft_window:on_close_window"
self.keep_running = False
-
def set_data (self, evt):
dB = evt.data
L = len (dB)
Added:
gnuradio/branches/developers/michaelld/wxgui/gr-wxgui/src/python/gr_input_watcher.py
===================================================================
---
gnuradio/branches/developers/michaelld/wxgui/gr-wxgui/src/python/gr_input_watcher.py
(rev 0)
+++
gnuradio/branches/developers/michaelld/wxgui/gr-wxgui/src/python/gr_input_watcher.py
2008-03-19 02:25:56 UTC (rev 8042)
@@ -0,0 +1,100 @@
+#!/usr/bin/env python
+#
+# Copyright 2008 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+import threading, sys, wx
+
+class gr_window_data_event (wx.PyEvent):
+ """
+ Create a new window data event.
+ Inherit from this class to provide the specific functionality
+ required by the particular application.
+ """
+ def __init__ (self, window, handler, bind_func=None,
+ event_type=wx.NewEventType ()):
+ wx.PyEvent.__init__ (self)
+ if bind_func is None:
+ # if the binding function isn't provided: PyEventBinder()
+ # creates a new function, which takes as arguments the
+ # window and handler to bind together for this particular
+ # event type.
+ wx.PyEventBinder (event_type, 0) (window, handler)
+ else:
+ # use the provided function
+ bind_func (event_type, window, handler)
+ self.SetEventType (event_type)
+ self.set_data (None)
+
+ def Clone (self):
+ self.__class__ (self.GetId ())
+
+ def set_data (self, data):
+ self.data = data
+
+class gr_input_watcher (threading.Thread):
+ def __init__ (self, msgq, event_receiver, data_event,
+ msg_proc_func, **kwds):
+ threading.Thread.__init__ (self, **kwds)
+ self.setDaemon (1)
+ self.msgq = msgq
+ self.event_receiver = event_receiver
+ self.data_event = data_event
+ self.msg_proc_func = msg_proc_func
+ self.running = True
+ self.start ()
+
+ def run (self):
+# print "gr_input_watcher starting"
+ # get a local version of the data_event handler
+ de = self.data_event
+ # loop while running
+ while (self.running):
+ # blocking read of message queue
+ msg = self.msgq.delete_head ()
+
+ # call the provided message processing function
+ records = self.msg_proc_func (msg)
+
+ # if the returned records is empty, just continue
+ if records == []:
+ continue
+
+ # if 'records' were returned, post them as an event;
+ # data processed via the 'PostEvent' is processed
+ # synchronously, so reuse the data event ('de')
+
+ # set the date event's data to the returned records
+ de.set_data (records)
+
+ # post the event
+ wx.PostEvent (self.event_receiver, de)
+
+ # once 'keep_running' is set to False, processing is complete;
+# print "gr_input_watcher finishing"
+
+ def stop (self):
+# print "gr_input_watcher: stop issued"
+ # tell the thread to stop running
+ self.running = False
+ # FIXME: 'abort' the msgq?
+# self.msgq.abort ()
+ # join the thread to wait for it to finish
+ self.join ()
Modified:
gnuradio/branches/developers/michaelld/wxgui/gr-wxgui/src/python/numbersink2.py
===================================================================
---
gnuradio/branches/developers/michaelld/wxgui/gr-wxgui/src/python/numbersink2.py
2008-03-18 20:54:55 UTC (rev 8041)
+++
gnuradio/branches/developers/michaelld/wxgui/gr-wxgui/src/python/numbersink2.py
2008-03-19 02:25:56 UTC (rev 8042)
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2003,2004,2005,2006,2007 Free Software Foundation, Inc.
+# Copyright 2003,2004,2005,2006,2007,2008 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -21,16 +21,17 @@
#
from gnuradio import gr, gru, window
-from gnuradio.wxgui import stdgui2
-import wx
-import gnuradio.wxgui.plot as plot
-import numpy
-import threading
-import math
+from gnuradio.wxgui import stdgui2, plot
+from gnuradio.wxgui.gr_input_watcher import *
+import wx, numpy, math
-default_numbersink_size = (640,240)
+# programming to handle defaults and user preferences
+
+default_numbersink_size = wx.Size (640,240)
default_number_rate = gr.prefs().get_long('wxgui', 'number_rate', 15)
+# classes to handle number sink
+
class number_sink_base(object):
def __init__(self, input_is_real=False, unit='',base_value=0,
minval=-100.0,maxval=100.0,factor=1.0,decimal_places=10, ref_level=50,
sample_rate=1,
@@ -153,50 +154,6 @@
# ------------------------------------------------------------------------
-myDATA_EVENT = wx.NewEventType()
-EVT_DATA_EVENT = wx.PyEventBinder (myDATA_EVENT, 0)
-
-
-class DataEvent(wx.PyEvent):
- def __init__(self, data):
- wx.PyEvent.__init__(self)
- self.SetEventType (myDATA_EVENT)
- self.data = data
-
- def Clone (self):
- self.__class__ (self.GetId())
-
-
-class input_watcher (threading.Thread):
- def __init__ (self, msgq, number_size, event_receiver, **kwds):
- threading.Thread.__init__ (self, **kwds)
- self.setDaemon (1)
- self.msgq = msgq
- self.number_size = number_size
- self.event_receiver = event_receiver
- self.keep_running = True
- self.start ()
-
- def run (self):
- while (self.keep_running):
- msg = self.msgq.delete_head() # blocking read of message queue
- itemsize = int(msg.arg1())
- nitems = int(msg.arg2())
-
- s = msg.to_string() # get the body of the msg as a
string
-
- # There may be more than one number in the message.
- # If so, we take only the last one
- if nitems > 1:
- start = itemsize * (nitems - 1)
- s = s[start:start+itemsize]
-
- complex_data = numpy.fromstring (s, numpy.float32)
- de = DataEvent (complex_data)
- wx.PostEvent (self.event_receiver, de)
- del de
-
-#========================================================================================
class static_text_window (wx.StaticText): #plot.PlotCanvas):
def __init__ (self, parent, numbersink,id = -1,label="number",
pos = wx.DefaultPosition, size = wx.DefaultSize,
@@ -388,11 +345,29 @@
self.numbersink = numbersink
self.peak_hold = False
self.peak_vals = None
-
- EVT_DATA_EVENT (self, self.set_data)
+
wx.EVT_CLOSE (self, self.on_close_window)
- self.input_watcher = input_watcher(numbersink.msgq,
numbersink.number_size, self)
+ self.data_event = gr_window_data_event (self, self.set_data)
+ self.input_watcher = gr_input_watcher (numbersink.msgq, self,
+ self.data_event,
+ self.msg_processor)
+
+ def msg_processor (self, msg):
+ itemsize = int (msg.arg1 ())
+ nitems = int (msg.arg2 ())
+
+ # get the body of the msg as a string
+ s = msg.to_string ()
+
+ # There may be more than one number in the message.
+ # If so, take only the last one.
+ if nitems > 1:
+ start = itemsize * (nitems - 1)
+ s = s[start:(start+itemsize)]
+
+ return numpy.fromstring (s, numpy.float32)
+
def on_close_window (self, event):
# print "number_window:on_close_window"
self.keep_running = False
Modified:
gnuradio/branches/developers/michaelld/wxgui/gr-wxgui/src/python/scopesink2.py
===================================================================
---
gnuradio/branches/developers/michaelld/wxgui/gr-wxgui/src/python/scopesink2.py
2008-03-18 20:54:55 UTC (rev 8041)
+++
gnuradio/branches/developers/michaelld/wxgui/gr-wxgui/src/python/scopesink2.py
2008-03-19 02:25:56 UTC (rev 8042)
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2003,2004,2006,2007 Free Software Foundation, Inc.
+# Copyright 2003,2004,2006,2007,2008 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -21,17 +21,18 @@
#
from gnuradio import gr, gru, eng_notation
-from gnuradio.wxgui import stdgui2
-import wx
-import gnuradio.wxgui.plot as plot
-import numpy
-import threading
-import struct
+from gnuradio.wxgui import stdgui2, plot
+from gnuradio.wxgui.gr_input_watcher import *
+import wx, numpy, struct
-default_scopesink_size = (640, 240)
+# programming to handle defaults and user preferences
+
+default_scopesink_size = wx.Size (640, 240)
default_v_scale = 1000
default_frame_decim = gr.prefs().get_long('wxgui', 'frame_decim', 1)
+# classes to handle scope sink
+
class scope_sink_f(gr.hier_block2):
def __init__(self, parent, title='', sample_rate=1,
size=default_scopesink_size, frame_decim=default_frame_decim,
@@ -133,21 +134,6 @@
]
-wxDATA_EVENT = wx.NewEventType()
-
-def EVT_DATA_EVENT(win, func):
- win.Connect(-1, -1, wxDATA_EVENT, func)
-
-class DataEvent(wx.PyEvent):
- def __init__(self, data):
- wx.PyEvent.__init__(self)
- self.SetEventType (wxDATA_EVENT)
- self.data = data
-
- def Clone (self):
- self.__class__ (self.GetId())
-
-
class win_info (object):
__slots__ = ['msgq', 'sample_rate', 'frame_decim', 'v_scale',
'scopesink', 'title',
@@ -194,51 +180,6 @@
def get_marker (self):
return self.marker
-
-class input_watcher (threading.Thread):
- def __init__ (self, msgq, event_receiver, frame_decim, **kwds):
- threading.Thread.__init__ (self, **kwds)
- self.setDaemon (1)
- self.msgq = msgq
- self.event_receiver = event_receiver
- self.frame_decim = frame_decim
- self.iscan = 0
- self.keep_running = True
- self.start ()
-
- def run (self):
- # print "input_watcher: pid = ", os.getpid ()
- while (self.keep_running):
- msg = self.msgq.delete_head() # blocking read of message queue
- if self.iscan == 0: # only display at frame_decim
- self.iscan = self.frame_decim
-
- nchan = int(msg.arg1()) # number of channels of data in msg
- nsamples = int(msg.arg2()) # number of samples in each channel
-
- s = msg.to_string() # get the body of the msg as a string
-
- bytes_per_chan = nsamples * gr.sizeof_float
-
- records = []
- for ch in range (nchan):
-
- start = ch * bytes_per_chan
- chan_data = s[start:start+bytes_per_chan]
- rec = numpy.fromstring (chan_data, numpy.float32)
- records.append (rec)
-
- # print "nrecords = %d, reclen = %d" % (len (records),nsamples)
-
- de = DataEvent (records)
- wx.PostEvent (self.event_receiver, de)
- records = []
- del de
-
- # end if iscan == 0
- self.iscan -= 1
-
-
class scope_window (wx.Panel):
def __init__ (self, info, parent, id = -1,
@@ -472,10 +413,46 @@
self.avg_x_min = None
self.avg_x_max = None
- EVT_DATA_EVENT (self, self.format_data)
+ self.data_event = gr_window_data_event (
+ self, self.format_data, lambda e, w, h: w.Connect (-1, -1, e, h))
- self.input_watcher = input_watcher (info.msgq, self, info.frame_decim)
+ self.iscan = 0
+ self.input_watcher = gr_input_watcher (info.msgq, self,
+ self.data_event,
+ self.msg_processor)
+ def msg_processor (self, msg):
+ # convert the incoming message to usable data;
+ # return [] or an array of data
+
+ # clear records before appending to them
+ records = []
+
+ # only display at frame_decim
+ if self.iscan <= 0:
+ self.iscan = self.info.frame_decim
+
+ # number of channels of data in msg
+ nchan = int (msg.arg1 ())
+
+ # number of samples in each channel
+ nsamples = int (msg.arg2 ())
+
+ # get the body of the msg as a string
+ s = msg.to_string ()
+
+ bytes_per_chan = nsamples * gr.sizeof_float
+
+ for ch in range (nchan):
+ start = ch * bytes_per_chan
+ chan_data = s[start:start+bytes_per_chan]
+ rec = numpy.fromstring (chan_data, numpy.float32)
+ records.append (rec)
+
+ # print "nrecords = %d, reclen = %d" % (len (records),nsamples)
+ self.iscan -= 1
+ return records
+
def channel_color (self, ch):
return self.channel_colors[ch % len(self.channel_colors)]
Modified:
gnuradio/branches/developers/michaelld/wxgui/gr-wxgui/src/python/waterfallsink2.py
===================================================================
---
gnuradio/branches/developers/michaelld/wxgui/gr-wxgui/src/python/waterfallsink2.py
2008-03-18 20:54:55 UTC (rev 8041)
+++
gnuradio/branches/developers/michaelld/wxgui/gr-wxgui/src/python/waterfallsink2.py
2008-03-19 02:25:56 UTC (rev 8042)
@@ -21,17 +21,17 @@
#
from gnuradio import gr, gru, window
-from gnuradio.wxgui import stdgui2
-import wx
-import gnuradio.wxgui.plot as plot
-import numpy
-import os
-import threading
-import math
+from gnuradio.wxgui import stdgui2, plot
+from gnuradio.wxgui.gr_input_watcher import *
+import wx, numpy, os, math
-default_fftsink_size = (640,240)
+# programming to handle defaults and user preferences
+
+default_fftsink_size = wx.Size (640,240)
default_fft_rate = gr.prefs().get_long('wxgui', 'fft_rate', 15)
+# classes to handle waterfall sink
+
class waterfall_sink_base(object):
def __init__(self, input_is_real=False, baseband_freq=0,
sample_rate=1, fft_size=512,
@@ -136,50 +136,6 @@
# ------------------------------------------------------------------------
-myDATA_EVENT = wx.NewEventType()
-EVT_DATA_EVENT = wx.PyEventBinder (myDATA_EVENT, 0)
-
-
-class DataEvent(wx.PyEvent):
- def __init__(self, data):
- wx.PyEvent.__init__(self)
- self.SetEventType (myDATA_EVENT)
- self.data = data
-
- def Clone (self):
- self.__class__ (self.GetId())
-
-
-class input_watcher (threading.Thread):
- def __init__ (self, msgq, fft_size, event_receiver, **kwds):
- threading.Thread.__init__ (self, **kwds)
- self.setDaemon (1)
- self.msgq = msgq
- self.fft_size = fft_size
- self.event_receiver = event_receiver
- self.keep_running = True
- self.start ()
-
- def run (self):
- while (self.keep_running):
- msg = self.msgq.delete_head() # blocking read of message queue
- itemsize = int(msg.arg1())
- nitems = int(msg.arg2())
-
- s = msg.to_string() # get the body of the msg as a
string
-
- # There may be more than one FFT frame in the message.
- # If so, we take only the last one
- if nitems > 1:
- start = itemsize * (nitems - 1)
- s = s[start:start+itemsize]
-
- complex_data = numpy.fromstring (s, numpy.float32)
- de = DataEvent (complex_data)
- wx.PostEvent (self.event_receiver, de)
- del de
-
-
class waterfall_window (wx.Panel):
def __init__ (self, fftsink, parent, id = -1,
pos = wx.DefaultPosition, size = wx.DefaultSize,
@@ -199,16 +155,32 @@
wx.EVT_PAINT( self, self.OnPaint )
wx.EVT_CLOSE (self, self.on_close_window)
- EVT_DATA_EVENT (self, self.set_data)
self.build_popup_menu()
wx.EVT_CLOSE (self, self.on_close_window)
self.Bind(wx.EVT_RIGHT_UP, self.on_right_click)
- self.input_watcher = input_watcher(fftsink.msgq, fftsink.fft_size,
self)
+ self.data_event = gr_window_data_event (self, self.set_data)
+ self.input_watcher = gr_input_watcher (fftsink.msgq, self,
+ self.data_event,
+ self.msg_processor)
+ def msg_processor (self, msg):
+ itemsize = int (msg.arg1 ())
+ nitems = int (msg.arg2 ())
+ # get the body of the msg as a string
+ s = msg.to_string ()
+
+ # There may be more than one FFT frame in the message.
+ # If so, take only the last one.
+ if nitems > 1:
+ start = itemsize * (nitems - 1)
+ s = s[start:(start+itemsize)]
+
+ return numpy.fromstring (s, numpy.float32)
+
def on_close_window (self, event):
print "waterfall_window: on_close_window"
self.keep_running = False
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Commit-gnuradio] r8042 - gnuradio/branches/developers/michaelld/wxgui/gr-wxgui/src/python,
michaelld <=