commit-gnuradio
[Top][All Lists]
Advanced

[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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]