commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] r5730 - in grc/trunk: . data license notes src src/Ele


From: jblum
Subject: [Commit-gnuradio] r5730 - in grc/trunk: . data license notes src src/Elements src/Graphics src/SignalBlockDefs
Date: Wed, 6 Jun 2007 23:57:26 -0600 (MDT)

Author: jblum
Date: 2007-06-06 23:57:25 -0600 (Wed, 06 Jun 2007)
New Revision: 5730

Added:
   grc/trunk/README.txt
   grc/trunk/data/preferences.grc.dtd
   grc/trunk/src/Editor.py
   grc/trunk/src/ExecFlowGraph.py
   grc/trunk/src/ExecFlowGraphGUI.py
Removed:
   grc/trunk/license/README.txt
   grc/trunk/notes/stock_id.lst
   grc/trunk/src/FlowGraphApp.py
   grc/trunk/src/Run.py
Modified:
   grc/trunk/notes/clean.sh
   grc/trunk/notes/notes.txt
   grc/trunk/src/ActionHandler.py
   grc/trunk/src/Actions.py
   grc/trunk/src/Constants.py
   grc/trunk/src/DataType.py
   grc/trunk/src/Elements/Element.py
   grc/trunk/src/Elements/GraphicalParam.py
   grc/trunk/src/Elements/SignalBlock.py
   grc/trunk/src/Elements/Socket.py
   grc/trunk/src/Elements/__init__.py
   grc/trunk/src/Graphics/Bars.py
   grc/trunk/src/Graphics/Dialogs.py
   grc/trunk/src/Graphics/FlowGraph.py
   grc/trunk/src/Graphics/MainWindow.py
   grc/trunk/src/Graphics/__init__.py
   grc/trunk/src/MathExprParser.py
   grc/trunk/src/Messages.py
   grc/trunk/src/Preferences.py
   grc/trunk/src/SignalBlockDefs/Conversions.py
   grc/trunk/src/SignalBlockDefs/Filters.py
   grc/trunk/src/SignalBlockDefs/GraphicalSinks.py
   grc/trunk/src/SignalBlockDefs/Misc.py
   grc/trunk/src/SignalBlockDefs/Modulators.py
   grc/trunk/src/SignalBlockDefs/SignalBlockConstants.py
   grc/trunk/src/SignalBlockDefs/SignalBlockTree.py
   grc/trunk/src/SignalBlockDefs/Sinks.py
   grc/trunk/src/SignalBlockDefs/__init__.py
   grc/trunk/src/Variables.py
Log:
merged developer branch into trunk

Copied: grc/trunk/README.txt (from rev 5729, grc/branches/jblum_work/README.txt)
===================================================================
--- grc/trunk/README.txt                                (rev 0)
+++ grc/trunk/README.txt        2007-06-07 05:57:25 UTC (rev 5730)
@@ -0,0 +1,13 @@
+Hello!
+
+Thank you for downloading GNU Radio Companion.
+This program is free software. 
+A GPL license is distributed with this program.
+This license covers all the source code/python files. 
+You will also find a "creative common license" for the grc icon.
+
+Intructions for GRC are available at:
+http://gnuradio.org/trac/wiki/GNURadioCompanion
+
+If you have questions, problems, suggestions, or want to contribute,
+please email me at jblum at jhu dot edu

Copied: grc/trunk/data/preferences.grc.dtd (from rev 5729, 
grc/branches/jblum_work/data/preferences.grc.dtd)
===================================================================
--- grc/trunk/data/preferences.grc.dtd                          (rev 0)
+++ grc/trunk/data/preferences.grc.dtd  2007-06-07 05:57:25 UTC (rev 5730)
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<!-- 
+Copyright 2007 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion 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 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion 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 this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA 
+-->
+<!--
+       preferences.grc.dtd 
+       Josh Blum
+       The document type definitions for grc preferences.
+-->
+<!DOCTYPE preferences [
+       <!-- The preferences contains:
+               identifying information: time stamp, host name, version, 
+               and a list of categories, each with their own preferences.    
-->
+       <!ELEMENT preferences (timestamp?, hostname?, version?, categories>
+               <!ELEMENT timestamp (#PCDATA)>  <!-- The time stamp for the 
modification date. (optional) -->
+               <!ELEMENT hostname (#PCDATA)>   <!-- The hostname of the 
computer. (optional) -->
+               <!ELEMENT version (#PCDATA)>    <!-- The program and program 
version.  (optional) -->
+               <!ELEMENT categories (category*)>       <!-- The list of 
categories. (tag required) -->
+                       <!ELEMENT category (title?, prefs)>     <!-- A 
category. (0 or more) -->
+                               <!ELEMENT title (#PCDATA)>      <!-- The title 
of the category. (optional) -->
+                               <!ELEMENT prefs (pref*)>        <!-- The list 
of preferences for this category. (tag required) -->
+                                       <!ELEMENT pref (#PCDATA)>       <!-- A 
preference. (0 or more) -->
+]>

Deleted: grc/trunk/license/README.txt

Modified: grc/trunk/notes/clean.sh
===================================================================
--- grc/trunk/notes/clean.sh    2007-06-07 05:22:11 UTC (rev 5729)
+++ grc/trunk/notes/clean.sh    2007-06-07 05:57:25 UTC (rev 5730)
@@ -1,8 +1,7 @@
 #!/bin/bash
-cd ../src
+#clean up compliled python files, and temporary files from editing
+cd ..
 pwd
 rm -rf `find ./ -type f -name "*.pyc"`
-rm -rf `find ./ -type f -name "*py~"`
-chmod a-x `find ./ -type f -name "*"`
-chmod a+x Run.py FlowGraphApp.py
-
+rm -rf `find ./ -type f -name "*.py~"`
+rm -rf `find ./ -type f -name "*.bak"`

Modified: grc/trunk/notes/notes.txt
===================================================================
--- grc/trunk/notes/notes.txt   2007-06-07 05:22:11 UTC (rev 5729)
+++ grc/trunk/notes/notes.txt   2007-06-07 05:57:25 UTC (rev 5730)
@@ -3,21 +3,25 @@
 -usrp dual and quad souce 
 -blks blocks, add filesave for message reports
 -combine add/mult with add/mult vector
+-selector blocks
 
 ############   Known Problems: ####################
 -in vars window, stop_editing doesnt work
 -file save, ask for overwrite even when appending file extension
 -blocks need to fix themselves when they go out of bounds, like in a resize
 -socket controllers should be intelligent on shrinkage
+-the nested data variables should indicate that they are nested data -> 
variable_data
+-rearanging variables doesnt have a handler
+-changing an enum doesnt call update for params with variable datatypes 
 
 ############   Features to Add:        ####################
 -save settings after close (working directory)
 -create sub-flow graphs to be used in larger flow graphs
--math expressions, pi, e, sin, cos, tan, log, ln
 -stdin/out communication protocal (non graphical)
--make grc.xml parsers to match the dtd
 -include dtd in saved flow graphs
--create dtd for preferences
+-immediate display of tool tips in entry boxes
+-function to import taps from a file
+-fm demod example with expansion of wfm_recv block
 
 ############   wxPython Features:      ####################
 -dump wx running graph to png?
@@ -28,16 +32,17 @@
         self.Bind(wx.EVT_CHOICE, self.scale, self.scaling_chooser)
         selection = event.GetSelection()
 
-############   User Opts:      ####################
---
+############   User Prefs:     ####################
+--save scrollbar positions (hidden pref)
 
 ############   Uninteresting Features: ####################
 -add the concept of a current working directory
 -auto param to usrp diagnose dialog
--add a trim option for dangling sockets
 -use popen3 once it works in cygwin
 -arrow like images for socket, to replace in/out strings
 -min/max in DataTypes can be other data types
 -press enter to close params
 
+############   Get GTK Stock IDs:      ####################
+       gtk.stock_list_ids()
        
\ No newline at end of file

Deleted: grc/trunk/notes/stock_id.lst

Modified: grc/trunk/src/ActionHandler.py
===================================================================
--- grc/trunk/src/ActionHandler.py      2007-06-07 05:22:11 UTC (rev 5729)
+++ grc/trunk/src/ActionHandler.py      2007-06-07 05:57:25 UTC (rev 5730)
@@ -102,13 +102,13 @@
                        self.handle_states(SOCKET_CONTROLLER_INC)
                elif self.flow_graph.get_focus_flag() and keyname in ('minus', 
'KP_Subtract'): #mouse focus
                        self.handle_states(SOCKET_CONTROLLER_DEC)               
-               ####################    Run/Stop/Print  
###############################
+               ####################    Exec/Stop/Print 
###############################
                elif keyname == 'F5':
-                       self.handle_states(FLOW_GRAPH_RUN)
+                       self.handle_states(FLOW_GRAPH_EXEC)
                elif keyname == 'F7':
                        self.handle_states(FLOW_GRAPH_STOP)
                elif keyname == 'Print':
-                       self.handle_states(FLOW_GRAPH_SNAP_SHOT)
+                       self.handle_states(FLOW_GRAPH_SCREEN_CAPTURE)
                #propagate this if the fg is not in focus or nothing is selected
                return self.flow_graph.get_focus_flag() and 
self.flow_graph.is_selected()
         
@@ -140,8 +140,8 @@
                        # enable a select few actions 
                        Graphics.enable_usrp_diagnostics()      #try to enable 
usrp diagnostics
                        for action in (APPLICATION_QUIT, FLOW_GRAPH_NEW, 
FLOW_GRAPH_OPEN, FLOW_GRAPH_SAVE_AS, 
-                                                                       
ABOUT_WINDOW_DISPLAY, COLORS_WINDOW_DISPLAY, HOTKEYS_WINDOW_DISPLAY,
-                                                                       
FLOW_GRAPH_WINDOW_RESIZE, PREFS_WINDOW_DISPLAY, FLOW_GRAPH_SNAP_SHOT): 
+                                                                       
ABOUT_WINDOW_DISPLAY, COLORS_WINDOW_DISPLAY, HOTKEYS_WINDOW_DISPLAY, 
MATH_EXPR_WINDOW_DISPLAY,
+                                                                       
FLOW_GRAPH_WINDOW_RESIZE, PREFS_WINDOW_DISPLAY, FLOW_GRAPH_SCREEN_CAPTURE): 
                                get_action_from_name(action).set_sensitive(True)
                        if self.flow_graph_file_path == '':
                                initial_state = 
ParseXML.from_xml(ParseXML.from_file(INITIAL_FLOW_GRAPH_FILE))
@@ -152,8 +152,8 @@
                                        self.handle_states(NOTHING_SELECT)
                                        
Messages.send_start_load(self.flow_graph_file_path)
                                        initial_state = 
ParseXML.from_xml(ParseXML.from_file(self.flow_graph_file_path))
-                                       errors = 
self.flow_graph.from_nested_data(initial_state)
-                                       Messages.send_end_load(errors)
+                                       
self.flow_graph.from_nested_data(initial_state)
+                                       Messages.send_end_load()
                                        self.state_cache = 
StateCache(initial_state)
                                except Exception, e:    #if the data is bad, 
display error and call INIT with None for the file path    
                                        Messages.send_fail_load(e)
@@ -233,6 +233,8 @@
                        Graphics.DataTypeColorsDialog()
                elif state == HOTKEYS_WINDOW_DISPLAY:
                        Graphics.HotKeysDialog()
+               elif state == MATH_EXPR_WINDOW_DISPLAY:
+                       Graphics.MathExprDialog()
                elif state == FLOW_GRAPH_WINDOW_RESIZE:
                        dimensions = 
Graphics.FlowGraphWindowSizeDialog(self.flow_graph).run()
                        if dimensions != None:
@@ -294,7 +296,7 @@
                        if file_path != None:                   
                                self.flow_graph_file_path = file_path
                                self.handle_states(FLOW_GRAPH_SAVE)     
-               elif state == FLOW_GRAPH_SNAP_SHOT:
+               elif state == FLOW_GRAPH_SCREEN_CAPTURE:
                        fc = Graphics.FlowGraphFileDialog('save image', 
self.flow_graph_file_path)
                        file_path = fc.run()
                        if file_path != None: 
@@ -306,7 +308,7 @@
                
##############################################################################################
                #       Run/Stop
                
##############################################################################################
          
-               elif state == FLOW_GRAPH_RUN:
+               elif state == FLOW_GRAPH_EXEC:
                        if self.pid_file == None:
                                self.handle_states(FLOW_GRAPH_SAVE)
                                if self.flow_graph_file_path != '': RUN(self)   
                                                        
@@ -317,9 +319,9 @@
                                except: print "could not kill pid file: 
%s"%self.pid_file
                        MUTEX.unlock()
                else: print "!!! State not handled !!!" 
-               # set the running button if the flow graph is valid and is not 
already running  #
+               # set the exec button if the flow graph is valid and is not 
already running     #
                while not MUTEX.testandset(): pass      #try to lock repeatedly 
until lock is aquired
-               
get_action_from_name(FLOW_GRAPH_RUN).set_sensitive(self.flow_graph.is_valid() 
and self.pid_file == None)        
+               
get_action_from_name(FLOW_GRAPH_EXEC).set_sensitive(self.flow_graph.is_valid() 
and self.pid_file == None)       
                MUTEX.unlock()
                # hide/show the reports window based on the preferences #
                
self.main_window.show_reports_window(Preferences.show_reports_window())
@@ -351,7 +353,7 @@
                self.pid_file = self.action_handler.pid_file = 
'/tmp/grc-%d.pid'%os.getpid()
                self.report_file = '/tmp/grc-%d.report'%os.getpid()
                self.flow_graph_file_path = 
self.action_handler.flow_graph_file_path
-               get_action_from_name(FLOW_GRAPH_RUN).set_sensitive(False)
+               get_action_from_name(FLOW_GRAPH_EXEC).set_sensitive(False)
                get_action_from_name(FLOW_GRAPH_STOP).set_sensitive(True)
                Messages.send_start_run(self.flow_graph_file_path)
                self.start()
@@ -371,5 +373,5 @@
                while not MUTEX.testandset(): pass      #try to lock repeatedly 
until lock is aquired
                self.action_handler.pid_file = None     
                get_action_from_name(FLOW_GRAPH_STOP).set_sensitive(False)      
-               get_action_from_name(FLOW_GRAPH_RUN).set_sensitive(True)
+               get_action_from_name(FLOW_GRAPH_EXEC).set_sensitive(True)
                MUTEX.unlock()

Modified: grc/trunk/src/Actions.py
===================================================================
--- grc/trunk/src/Actions.py    2007-06-07 05:22:11 UTC (rev 5729)
+++ grc/trunk/src/Actions.py    2007-06-07 05:57:25 UTC (rev 5730)
@@ -64,15 +64,16 @@
 FLOW_GRAPH_SAVE_AS = 'flow graph save as'
 FLOW_GRAPH_NEW = 'flow graph new'
 FLOW_GRAPH_WINDOW_RESIZE = 'flow graph window resize'
-FLOW_GRAPH_RUN = 'flow graph run'
+FLOW_GRAPH_EXEC = 'flow graph exec'
 FLOW_GRAPH_STOP = 'flow graph stop'
-FLOW_GRAPH_SNAP_SHOT = 'flow graph snap shot'
+FLOW_GRAPH_SCREEN_CAPTURE = 'flow graph screen capture'
 
 ABOUT_WINDOW_DISPLAY = 'about window display'
 COLORS_WINDOW_DISPLAY = 'colors window display'
 HOTKEYS_WINDOW_DISPLAY = 'hotkeys window display'
 USRP_DIAGNOSTICS_DISPLAY = 'usrp diagnostics display'
 PREFS_WINDOW_DISPLAY = 'prefs window display'
+MATH_EXPR_WINDOW_DISPLAY = 'expression window display'
 
 
######################################################################################################
 #      actions
@@ -96,9 +97,10 @@
        gtk.Action(ABOUT_WINDOW_DISPLAY, '_About', 'About this program', 
'gtk-about'),
        gtk.Action(COLORS_WINDOW_DISPLAY, '_Colors', 'Data Type Colors', 
'gtk-select-color'),
        gtk.Action(HOTKEYS_WINDOW_DISPLAY, '_HotKeys', 'Hot Keys', 'gtk-info'),
-       gtk.Action(FLOW_GRAPH_RUN, '_Run', 'Run the flow graph', 'gtk-execute'),
+       gtk.Action(MATH_EXPR_WINDOW_DISPLAY, '_Math Expressions', 'Mathematical 
Expressions', 'gtk-convert'),
+       gtk.Action(FLOW_GRAPH_EXEC, '_Execute', 'Execute the flow graph', 
'gtk-execute'),
        gtk.Action(FLOW_GRAPH_STOP, '_Stop', 'Stop the flow graph', 'gtk-stop'),
-       gtk.Action(FLOW_GRAPH_SNAP_SHOT, 'S_nap Shot', 'Take a snap shot image 
of the flow graph', 'gtk-print'),
+       gtk.Action(FLOW_GRAPH_SCREEN_CAPTURE, 'S_creen Capture', 'Create a 
screen capture of the flow graph', 'gtk-print'),
 ]
                                        
 def get_action_from_name(action_name): 

Modified: grc/trunk/src/Constants.py
===================================================================
--- grc/trunk/src/Constants.py  2007-06-07 05:22:11 UTC (rev 5729)
+++ grc/trunk/src/Constants.py  2007-06-07 05:57:25 UTC (rev 5730)
@@ -152,7 +152,7 @@
 #      A state is recorded for each change to the flow graph, the size 
dictates how many states we can record 
 
######################################################################################################
 
-"""    The size of the state saving cache in the gFloGraph (for undo/redo 
functionality)       """
+"""    The size of the state saving cache in the flow graph (for undo/redo 
functionality)      """
 STATE_CACHE_SIZE = 42
 
 
######################################################################################################
@@ -189,7 +189,7 @@
 if sys.platform == 'darwin': PYEXEC = 'pythonw'
 
 """ The default command to run a flow graph file       """
-DEFAULT_FLOW_GRAPH_EXEC = '%s %s/FlowGraphApp.py'%(PYEXEC, SRC_DIR)
+DEFAULT_FLOW_GRAPH_EXEC = '%s %s/ExecFlowGraphGUI.py'%(PYEXEC, SRC_DIR)
 
 """    The default user preferences file.      """
 PREFERENCES_FILE_PATH = os.path.abspath(DEFAULT_FILE_PATH + '/.grc.xml')

Modified: grc/trunk/src/DataType.py
===================================================================
--- grc/trunk/src/DataType.py   2007-06-07 05:22:11 UTC (rev 5729)
+++ grc/trunk/src/DataType.py   2007-06-07 05:57:25 UTC (rev 5730)
@@ -35,6 +35,7 @@
                self.set_data(data)             
                self.max = max
                self.min = min
+               self.msg = ''
        def set_data(self, data):
                ''' Store the data as a string. '''
                self.data = str(data)           
@@ -49,14 +50,14 @@
                If min or max was specified, 
                the parsed value must be less than or equal to min and/or 
                greater than or equal to max. If the parsed value is a vector, 
-               then the value is the length of the vector.     '''
-               try:
+               then the value is the length of the vector.     '''             
+               try: 
                        value = self.parse() 
-                       # for vector/string data types we check if len(obj) is 
in range
-                       if type(value) in (type(list()),type(str())): value = 
len(value)        
-                       return (self.max == None or (self.max != None and value 
<= self.max)) and\
-                                               (self.min == None or (self.min 
!= None and value >= self.min))
-               except: return False                    
+                       self.msg = ''
+                       return True
+               except Exception, e: 
+                       self.msg = str(e)
+                       return False    
        def get_type(self):
                ''' Get a string describing the specific data type.     '''
                return self.type
@@ -66,6 +67,11 @@
        def get_num_bytes(self):
                ''' How man bytes in this data type?    '''
                return self.num_bytes
+       def verify_bounds(self, value):
+               ''' Is the value within the bounds of this data type.
+                       Raise an exception if not.      '''
+               if self.max != None and value > self.max: raise 
ValueError('Value "%s" was greater than the max "%s".'%(value, self.max))
+               if self.min != None and value < self.min: raise 
ValueError('Value "%s" was greater than the min "%s".'%(value, self.min))
 
 
#############################################################################################
  
 #      Regular Types
@@ -76,15 +82,18 @@
        base_type = 'number'
        def parse(self):
                ''' Evaluate the math expressions in the data type.     '''
-               return 
self.parser(MathExprParser.eval_expr(DataType.parse(self)))
+               num = MathExprParser.eval_expr(DataType.parse(self))
+               parsed = self.parser(num)       
+               self.verify_bounds(parsed)
+               return parsed
 
 class Int(Number):
        ''' The integer data type.      '''
        type = 'int'
        num_bytes = gr.sizeof_int       
        def parser(self, value):
-               ''' Return the real part cast as an int.        '''
-               return int(complex(value).real)
+               ''' Return an int value or raise error. '''
+               return MathExprParser.verify_int(value)
 
 class Byte(Int):
        ''' The byte data type is identical to int in this case.        '''
@@ -101,8 +110,8 @@
        type = 'float'
        num_bytes = gr.sizeof_float
        def parser(self, value):
-               ''' Return the real part cast as a float.       '''
-               return float(complex(value).real)
+               ''' Return a float value or raise error.        '''
+               return MathExprParser.verify_float(value)
 
 class Complex(Number):
        ''' The complex data type.      '''
@@ -110,17 +119,33 @@
        num_bytes = gr.sizeof_gr_complex
        def parser(self, value):
                ''' Return the value as complex.        '''
-               return complex(value)
+               return MathExprParser.verify_complex(value)
        
 
#############################################################################################
  
 #      Special Types
 
#############################################################################################
+class RawExpr(DataType):
+       ''' A raw mathematical expression.      '''
+       type = 'raw'
+       def __init__(self, data=''):
+               ''' Raw data type contructor. Default value is blank string.    
'''
+               DataType.__init__(self, data)
+       def parse(self):
+               ''' Return the raw data returned by the parser  '''
+               data = DataType.parse(self)
+               return MathExprParser.eval_expr(data)
+
 class String(DataType):
        ''' The string data type.       '''
        type = 'string'
        def __init__(self, data='', min=None, max=None):
                ''' String data type contructor. Default value is blank string. 
'''
                DataType.__init__(self, data, min, max)
+       def parse(self):
+               ''' Verify the the string's length is in bounds.        '''
+               string = DataType.parse(self)
+               self.verify_bounds(len(string))
+               return string
                        
 class Hex(DataType):
        ''' The hex data type.  '''
@@ -234,7 +259,7 @@
                var_keys = list()
                for key in Variables.get_keys():
                        # use the key if we specified all variables or the key 
was not for a ranged variable
-                       if self.all_variables or Variables.get_values(key)[3] 
== '': var_keys.append(key)
+                       if self.all_variables or not Variables.is_ranged(key): 
var_keys.append(key)
                return var_keys 
                
 class Bool(Enum):
@@ -254,14 +279,11 @@
        Do not use, this is a base class only.          '''
        base_type = 'vector'
        def parse(self):
-               elements = list()
-               data = DataType.parse(self)
-               while data.strip() != '':
-                       index = data.find(',')
-                       if index == -1: index = len(data)
-                       elements.append(data[:index])
-                       data = data[index+1:]
-               return map(lambda v: self.parser(MathExprParser.eval_expr(v)), 
elements)
+               '''     Verify that the length of the vector is within bounds.  
'''
+               elements = MathExprParser.eval_expr(DataType.parse(self))
+               if type(elements) != type(list()): elements = [elements]        
#ensure that elements is a list         
+               self.verify_bounds(len(elements))
+               return map(lambda v: self.parser(v), elements)
 
 class ByteVector(Vector, Byte):
        ''' A vector of bytes   '''
@@ -303,11 +325,5 @@
        
 if __name__ == '__main__':
        print "put things here to test DataTypes"
-       dt = String('2fsg56', min=3, max=5)
-       print dt.is_valid(),dt.parse()
-       dt = IntVector('2, 3,', min=3, max=5)
-       print dt.is_valid(),dt.parse()
-       dt = Hex('0xfe', min=0, max=254)
-       print dt.is_valid(), dt.parse()
        
        
\ No newline at end of file

Copied: grc/trunk/src/Editor.py (from rev 5729, 
grc/branches/jblum_work/src/Editor.py)
===================================================================
--- grc/trunk/src/Editor.py                             (rev 0)
+++ grc/trunk/src/Editor.py     2007-06-07 05:57:25 UTC (rev 5730)
@@ -0,0 +1,57 @@
+#! /usr/bin/env python
+"""
+Copyright 2007 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion 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 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion 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 this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+"""
+"""
+       Editor.py 
+       Josh Blum
+       Execute the flow graph editor GUI. This file must be called by the 
python interpreter.
+"""
+
+from Constants import VERSION,DEFAULT_FILE_EXTENSION
+from optparse import OptionParser
+
+if __name__ == "__main__": 
+       usage = "usage: %prog optional_flow_graph"+DEFAULT_FILE_EXTENSION
+       version = """
+GNU Radio Companion %s
+
+This file is part of GNU Radio
+GRC comes with ABSOLUTELY NO WARRANTY. 
+This is free software, 
+and you are welcome to redistribute it.
+"""%VERSION
+       parser = OptionParser(usage=usage, version=version)     
+       (options, args) = parser.parse_args()   
+       # "test" import modules that this program will use #
+       try:    
+               import pygtk
+               pygtk.require('2.0')
+               import gtk
+               import xml.dom.minidom
+               import xml.dom.ext
+               import gnuradio
+       except ImportError, e: #print error and exit
+               print '\nMissing critical component: "%s"\nExiting!'%(e,)
+               exit(-1)
+       # end import of modules #
+       from ActionHandler import ActionHandler
+       if len(args): ActionHandler(args[0])
+       else: ActionHandler()
+       exit(0)                 
+

Modified: grc/trunk/src/Elements/Element.py
===================================================================
--- grc/trunk/src/Elements/Element.py   2007-06-07 05:22:11 UTC (rev 5729)
+++ grc/trunk/src/Elements/Element.py   2007-06-07 05:57:25 UTC (rev 5730)
@@ -122,9 +122,7 @@
        def set_rotation(self, rotation):
                """     set the rotation        """
                if rotation not in POSSIBLE_ROTATIONS:
-                       print >>sys.stderr, 'Error: '+str(rotation)+' is not 
one of the \
-                       possible rotations: '+str(POSSIBLE_ROTATIONS)
-                       sys.exit(1)
+                       raise Exception('"%s" is not one of the possible 
rotations: (%s)'%(rotation,POSSIBLE_ROTATIONS))
                self.rotation = rotation                
                
        def update(self): 

Modified: grc/trunk/src/Elements/GraphicalParam.py
===================================================================
--- grc/trunk/src/Elements/GraphicalParam.py    2007-06-07 05:22:11 UTC (rev 
5729)
+++ grc/trunk/src/Elements/GraphicalParam.py    2007-06-07 05:57:25 UTC (rev 
5730)
@@ -47,7 +47,8 @@
                self.label.set_size_request(140,30)
                self.label.show()
                self.pack_start(self.label, False)
-               self.set_markup = lambda m: self.label.set_markup(m)            
        
+               self.set_markup = lambda m: self.label.set_markup(m)    
+               self.tp = None          
                
 class EntryParam(InputParam):
        """ Provide an entry box for strings and numbers.       """
@@ -59,6 +60,10 @@
                input.show()
                self.pack_start(input, False)
                self.get_text = input.get_text
+               # tool tip fun #
+               self.tp = gtk.Tooltips()
+               self.tp.set_tip(self.entry, "")
+               self.tp.enable()
                
 class FileParam(EntryParam):
        """ Provide an entry box for filename and a button to browse for a 
file.        """
@@ -131,9 +136,13 @@
                if old_data != new_data: data_type.set_data(new_data)
                #       Set the markup on the label, red for errors in 
cooresponding data type. #
                cname = self.get_cname()
-               if not data_type.is_valid(): self.input.set_markup('<span 
foreground="red"><b>'+cname+'</b></span>')
-               else: self.input.set_markup(cname)      
-       
+               if not data_type.is_valid(): 
+                       self.input.set_markup('<span 
foreground="red"><b>'+cname+'</b></span>')
+                       if self.input.tp: 
self.input.tp.set_tip(self.input.entry, data_type.msg)
+               else: 
+                       self.input.set_markup(cname)    
+                       if self.input.tp: 
self.input.tp.set_tip(self.input.entry, str(data_type.parse()))
+
        def get_markup(self):
                """ Create a markup to display the Param as a label on the 
SignalBlock. 
                If the data type is an Enum type, use the cname of the Enum's 
current choice.   
@@ -172,13 +181,14 @@
                                        if len(head) >= suggested_length: 
dt_str = head
                                        else: dt_str = 
tail[0:suggested_length-len(head)] + '...' + head
                        elif self.get_data_type().get_base_type() == 
Vector().get_base_type(): #vector types
-                               #       only keep the first X elements of the 
list,                     
-                               X = 4   #display more for non complex vectors   
                                
+                               for i,e in enumerate(data): data[i] = to_str(e)
+                               #       only keep the first X elements of the 
list:                     
+                               X = (100/len(str(data))) + 1    #display more 
for non complex vectors                                   
                                dt_str = '['            #       replace the 
removed elements with a '...' 
-                               for i,e in enumerate(data):
-                                       if i < X or i > len(data)-2:    #leave 
one on the end 
-                                               dt_str = dt_str + to_str(e)
-                                               if i < len(data)-1 and i+1 != 
X: dt_str = dt_str + ', '
+                               for i,f in enumerate(data):
+                                       if i < X or i+1 == len(data):   #leave 
one on the end 
+                                               dt_str = dt_str + f
+                                               if i < len(data)-1 and (i+1 != 
X or X+1 == len(data)): dt_str = dt_str + ', '
                                        elif i == X: dt_str = dt_str + ' ... '
                                dt_str = dt_str + ']'
                        elif self.get_data_type().get_type() == 
Hex().get_type(): dt_str = hex(data) #hex, base 16

Modified: grc/trunk/src/Elements/SignalBlock.py
===================================================================
--- grc/trunk/src/Elements/SignalBlock.py       2007-06-07 05:22:11 UTC (rev 
5729)
+++ grc/trunk/src/Elements/SignalBlock.py       2007-06-07 05:57:25 UTC (rev 
5730)
@@ -156,4 +156,42 @@
                                                
sockets_list.remove(last_socket)                                        
                                        self.get_parent().update()      
#removing sockets could delete a connection, update all blocks
                
+##########################################################################
+##     Import a Signal Block
+##########################################################################
+       def from_nested_data(fg, nested_data, sb_constructor):
+               ''' Create a signal block from the nested data.
+                       Pass the flow graph/parent of the signal block,
+                       the nested data for a signal block, 
+                       and the contructor for the signal block.
+                       Return (the signal block, the runnable signal block) 
tuple.     '''
+               import ParseXML,Messages,SignalBlockDefs
+               find_data = ParseXML.find_data
+               signal_block = find_data([nested_data], 'signal_block')
+               tag = find_data(signal_block, 'tag')
+               id = find_data(signal_block, 'id')
+               #       These graphical parameters are optional and will 
default to 0 if not found      #
+               x_coordinate = find_data(signal_block, 'x_coordinate')
+               if x_coordinate == None: x_coordinate = 0
+               y_coordinate = find_data(signal_block, 'y_coordinate')
+               if y_coordinate == None: y_coordinate = 0
+               rotation = find_data(signal_block, 'rotation')
+               if rotation == None: rotation = 0
+               #       Load Parameters #
+               params = find_data(signal_block, 'params')
+               try:                    
+                       signal_block,runnable_signal_block = 
SignalBlockDefs.get_signal_block(
+                               fg, (int(x_coordinate),int(y_coordinate)), 
int(rotation), tag, id, sb_constructor,
+                       )
+                       for i,param in enumerate(params):
+                               try:
+                                       param = find_data([param], 'param')
+                                       
signal_block.get_params()[i].get_data_type().set_data(param)
+                               except: Messages.send_error_load('An invalid 
parameter was parsed, ignoring parameter "%d" in block "%s".'%(i, id))     
+                       return signal_block, runnable_signal_block              
+               except SignalBlockDefs.TagNotFoundException: 
+                       Messages.send_error_load('The definition for "%s" was 
not found, ignoring block "%s".'%(tag, id))
+               except Exception, e: Messages.send_error_load('Signal block 
"%s" could not be created:\n\t%s'%(id,e))   
+               return None, None       #not found!, return None tuple          
        
+       from_nested_data = staticmethod(from_nested_data)               
                        
\ No newline at end of file

Modified: grc/trunk/src/Elements/Socket.py
===================================================================
--- grc/trunk/src/Elements/Socket.py    2007-06-07 05:22:11 UTC (rev 5729)
+++ grc/trunk/src/Elements/Socket.py    2007-06-07 05:57:25 UTC (rev 5730)
@@ -23,7 +23,7 @@
 """
 
 from Element import Element
-import Utils
+import Utils,DataType
 from Connection import TooManyConnectionsException
 
 class Socket(Element):
@@ -72,7 +72,7 @@
                
        def get_data_type(self):
                ''' Get the data type. If the parsed vlen > 1, then return the 
vectorized data type.'''
-               if self.vlen != None and self.vlen.is_valid() and 
self.vlen.parse() > 1: return vectorize(self.data_type)
+               if self.vlen != None and self.vlen.is_valid() and 
self.vlen.parse() > 1: return DataType.vectorize(self.data_type)
                return self.data_type
                        
        def get_index(self):

Modified: grc/trunk/src/Elements/__init__.py
===================================================================
--- grc/trunk/src/Elements/__init__.py  2007-06-07 05:22:11 UTC (rev 5729)
+++ grc/trunk/src/Elements/__init__.py  2007-06-07 05:57:25 UTC (rev 5730)
@@ -29,8 +29,11 @@
 from Element import Element
 from Param import Param
 
-from GraphicalSignalBlock import GraphicalSignalBlock
-from GraphicalSocket import 
GraphicalSocket,GraphicalOutputSocket,GraphicalInputSocket
-from GraphicalConnection import GraphicalConnection
-from GraphicalElement import GraphicalElement
-from GraphicalParam import GraphicalParam
+try:   #do not import if gtk module dne
+       from GraphicalSignalBlock import GraphicalSignalBlock
+       from GraphicalSocket import 
GraphicalSocket,GraphicalOutputSocket,GraphicalInputSocket
+       from GraphicalConnection import GraphicalConnection
+       from GraphicalElement import GraphicalElement
+       from GraphicalParam import GraphicalParam
+except ImportError: pass
+

Copied: grc/trunk/src/ExecFlowGraph.py (from rev 5729, 
grc/branches/jblum_work/src/ExecFlowGraph.py)
===================================================================
--- grc/trunk/src/ExecFlowGraph.py                              (rev 0)
+++ grc/trunk/src/ExecFlowGraph.py      2007-06-07 05:57:25 UTC (rev 5730)
@@ -0,0 +1,115 @@
+#! /usr/bin/env python
+"""
+Copyright 2007 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion 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 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion 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 this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+"""
+"""
+       ExecFlowGraph.py 
+       Josh Blum
+       Use a xml input file to build and run a gnu radio flow graph without 
graphics.
+"""
+
+import ParseXML
+import Variables
+import SignalBlockDefs
+from Elements import SignalBlock
+from gnuradio import gr
+import os
+from Constants import DEFAULT_FILE_EXTENSION
+from optparse import OptionParser
+
+##############################################################################################
+#      Flow Graph Builder
+##############################################################################################
 
+class FlowGraphBuilder(gr.flow_graph):
+       """ Parse the input file to build the gnuradio flow graph.
+               Register the variables, handle signal block callbacks.  """
+       def __init__(self, file_path):                  
+               nested_data = ParseXML.from_xml(ParseXML.from_file(file_path))
+               gr.flow_graph.__init__(self)
+               self.callbacks = list()
+               self.var_keys = list()
+               self.parse_nested_data(nested_data)     
+                       
+       def add_window(self, window, type='', title=''):
+               ''' Empty method for adding a window in the GUI flow graph.     
'''
+               pass
+               
+       def get_panel(self):
+               ''' Empty method for getting the wx panel in the GUI flow 
graph.        ''' 
+               print '''
+Graphical Sinks are not supported in ExecFlowGraph.py:
+ use ExecFlowGraphGUI.py [-d] or remove the Graphical Sink.
+Exiting!'''
+               exit(-1)
+               
+       def add_callback(self, function, data_type_params):
+               """ Register a callback function with its associated data.      
"""
+               self.callbacks.append((function, data_type_params))
+               
+       def parse_callbacks(self):
+               """ For each call back, parse all of the data and 
+               call the registered callback function on that data.     """
+               for function, data_type_params in self.callbacks:
+                       try:
+                               if type(data_type_params) in (type(list()), 
type(tuple())):
+                                       function(*map(lambda param: 
param.parse(), data_type_params))
+                               else: function(data_type_params.parse())        
        
+                       except: print "error parsing a callback -> ignoring..." 
+               
+       def parse_nested_data(self, nested_data):
+               """ Parse nested data from a flow graph file and build the 
graphics. 
+               This code is partially copied from FlowGraph.py, with 
unnecessary code removed. """
+               find_data = ParseXML.find_data
+               flow_graph = find_data([nested_data], 'flow_graph')     
+               vars = find_data(flow_graph, 'vars')
+               signal_blocks = find_data(flow_graph, 'signal_blocks')
+               connections = find_data(flow_graph, 'connections')
+               self.var_keys = Variables.from_nested_data(vars)
+               signal_blocks_dict = dict()                             
+               for signal_block in signal_blocks:                      
+                       signal_block,runnable_signal_block = 
SignalBlock.from_nested_data(None, signal_block, SignalBlock)                   
   
+                       data_type_params = list()
+                       data_type_params.append(self)#put the flow graph in the 
front of the list
+                       for param in signal_block.get_params(): #load the list 
of arguments to the runnable block               
+                               data_type_params.append(param.get_data_type())  
                
+                       signal_blocks_dict[signal_block.get_id()] = 
runnable_signal_block(*data_type_params)
+               for connection in connections:
+                       connection = find_data([connection], 'connection')
+                       input_signal_block_id = find_data(connection, 
'input_signal_block_id')
+                       input_socket_index = int(find_data(connection, 
'input_socket_index'))
+                       output_signal_block_id = find_data(connection, 
'output_signal_block_id')
+                       output_socket_index = int(find_data(connection, 
'output_socket_index')) 
+                       self.connect(#  use this flow graph's connect method    
#
+                               (signal_blocks_dict[output_signal_block_id], 
output_socket_index),
+                               (signal_blocks_dict[input_signal_block_id], 
input_socket_index))
+                               
+if __name__ == '__main__':     
+       usage = "usage: %prog [-p] flow_graph"+DEFAULT_FILE_EXTENSION
+       parser = OptionParser(usage=usage)
+       parser.add_option("-p", "--pid_file", action="store", type="string", 
dest="pid_file", help="record process id") 
+       (options, args) = parser.parse_args()
+       if options.pid_file:
+               try: open(options.pid_file, 'w').write('%d\n' % os.getpid())
+               except: print "could not create pid file: %s"%options.pid_file
+       if len(args): #only create the flow graph if a file was passed
+               fg = FlowGraphBuilder(args[0])
+               fg.start()
+               raw_input('Flow Graph Running...\nPress Enter to Exit: ')
+               fg.stop()       
+       else: parser.print_help()       
+                       
\ No newline at end of file

Copied: grc/trunk/src/ExecFlowGraphGUI.py (from rev 5729, 
grc/branches/jblum_work/src/ExecFlowGraphGUI.py)
===================================================================
--- grc/trunk/src/ExecFlowGraphGUI.py                           (rev 0)
+++ grc/trunk/src/ExecFlowGraphGUI.py   2007-06-07 05:57:25 UTC (rev 5730)
@@ -0,0 +1,221 @@
+#! /usr/bin/env python
+"""
+Copyright 2007 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion 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 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion 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 this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+"""
+"""
+       ExecFlowGraphGUI.py 
+       Josh Blum       
+       Use a xml input file to build and run a gnu radio flow graph with wx 
GUI elements.
+"""
+
+import Variables
+from ExecFlowGraph import FlowGraphBuilder
+import wx
+import os
+from Constants import *
+import math
+from optparse import OptionParser
+
+##############################################################################################
+#      Variable Control
+##############################################################################################
+class VariableControl(wx.BoxSizer):
+       """ House a Slider and a Text Box for variable control. """
+       def __init__(self, parent, key, parse_callbacks):
+               """ Create the slider, text box, and label given the variable 
key.
+                       parse_callbacks is a method to update the registered 
signal block callback methods.     """
+               self.key = key
+               self.parse_callbacks = parse_callbacks
+               value, min, max, step = Variables.get_values(key)
+               wx.BoxSizer.__init__(self, wx.VERTICAL)
+               label_text_sizer = wx.BoxSizer(wx.HORIZONTAL) #label and text 
box container 
+               label = wx.StaticText(parent, -1, key+' -> ')
+               self.text_box = text_box = wx.TextCtrl(parent, -1, value, 
style=wx.TE_PROCESS_ENTER)
+               text_box.Bind(wx.EVT_TEXT_ENTER, self.handle_enter)     #bind 
this special enter hotkey event
+               for obj in (label, text_box):   #fill the container with label 
and text entry box
+                       label_text_sizer.Add(obj, 0, 
wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL)
+               self.Add(label_text_sizer, 0, wx.ALIGN_CENTER)
+               ###     Determine the slider width based on the number of steps 
###             
+               self.num_steps = num_steps = 
(float(max)-float(min))/float(step)                        
+               if num_steps == DEFAULT_SLIDER_STEPS: slider_width = 
DEFAULT_SLIDER_WIDTH
+               elif num_steps > DEFAULT_SLIDER_STEPS:  # make the slider wider 
than default
+                       slider_width = MAX_SLIDER_WIDTH - 
(MAX_SLIDER_WIDTH-DEFAULT_SLIDER_WIDTH)*DEFAULT_SLIDER_STEPS/num_steps
+               elif num_steps < DEFAULT_SLIDER_STEPS: # make the slider slimer 
then default
+                       slider_width = MIN_SLIDER_WIDTH + 
(DEFAULT_SLIDER_WIDTH-MIN_SLIDER_WIDTH)*num_steps/DEFAULT_SLIDER_STEPS
+               self.slider_width = slider_width = int(slider_width)    #make 
sure width is an integer number of pixels
+               ### make the slider     ###                             
+               self.slider = slider = wx.Slider(parent, -1, 
size=wx.Size(slider_width, SLIDER_HEIGHT), style=wx.SL_HORIZONTAL)              
           
+               try: slider.SetRange(0, num_steps)
+               except Exception, e:
+                       sys.stderr.write('Slider, "%s", has too many 
steps!\n'%key)
+                       sys.exit(1)
+               slider.Bind(wx.EVT_SCROLL, self.handle_scroll)  #bind the 
scrolling event               
+               self.Add(slider, 0, wx.ALIGN_CENTER)
+               self.handle_enter()#sets the slider's value
+       
+       def get_slider_width(self):
+               """ Get the width of the slider in pixels.      """
+               return self.slider_width
+               
+       def get_slider_value(self):
+               """ Read the value from the slider slider. 
+               Translate the slider value into a real numerical value. """
+               slider_value = self.slider.GetValue()           
+               value, min, max, step = Variables.get_values(self.key)          
+               return str(slider_value*(float(max)-float(min))/self.num_steps 
+ float(min))
+               
+       def set_slider_value(self, real_value):
+               """ Translate the real numerical value into a slider value. 
+               Write the value to the slider. """      
+               value, min, max, step = Variables.get_values(self.key)          
+               slider_value = 
(float(real_value)-float(min))*self.num_steps/(float(max)-float(min))
+               self.slider.SetValue(slider_value)
+       
+       def handle_scroll(self, event=None):
+               """ A scroll event is detected. Read the slider. Try to 
register the new entry:
+               If the registration passes, update the text box, and parse the 
callbacks.
+               If the registration fails, restore the slider to the previous 
registered values. """
+               key = self.key          
+               new_value = str(self.get_slider_value())        #the new value 
must be a string!
+               value, min, max, step = Variables.get_values(key)               
+               Variables.unregister(key)
+               try:
+                       Variables.register(key, new_value, min, max, step)
+                       self.text_box.SetValue(str(new_value))
+                       self.parse_callbacks()
+               except: 
+                       Variables.register(key, value, min, max, step)
+                       self.set_slider_value(value)            
+               
+       def handle_enter(self, event=None):
+               """ An enter key was pressed. Read the text box. Try to 
register the new entry: 
+                If the registration passes, move the slider, and parse the 
callbacks.  
+                If the registration fails, restore the text box to the 
previous registered value.      """
+               key = self.key
+               new_value = str(self.text_box.GetValue())       #the new value 
must be a string!        
+               value, min, max, step = Variables.get_values(key)
+               Variables.unregister(key)
+               try:
+                       Variables.register(key, new_value, min, max, step)
+                       self.set_slider_value(new_value)                        
                
+                       self.parse_callbacks()
+               except: 
+                       Variables.register(key, value, min, max, step)          
                
+                       self.text_box.SetValue(value)                   
+
+##############################################################################################
+#      Flow Graph Frame
+##############################################################################################
 
+class FlowGraphFrame(wx.Frame, FlowGraphBuilder):
+       """ A FlowGraphFrame is a wx.Frame and a FlowGraphBuilder. 
+       This flow graph frame parses a saved flow graph file,
+       houses all the sliders and graphical sinks, 
+       and starts the flow graph.      """
+       def __init__(self, file_path):
+               file_path = os.path.abspath(file_path)
+               wx.Frame.__init__(self, None , -1, MAIN_WINDOW_PREFIX+' - 
Executing: '+file_path)
+               if WX_APP_ICON: self.SetIcon(wx.Icon(WX_APP_ICON, 
wx.BITMAP_TYPE_ANY))
+               self.SetSizeHints(200, 100)
+               # create holder for sliders and graphs  #
+               self.sliders_dict = dict()
+               self.sink_windows = dict()
+               graphs_box = wx.GridSizer(1, 1, 0, 0)
+               self.panel = panel = wx.ScrolledWindow(self, -1)
+               panel.SetSizer(graphs_box)
+               #       create the main box for all components  #
+               main_box = wx.BoxSizer(wx.VERTICAL)
+               self.sliders_box = wx.BoxSizer(wx.VERTICAL)
+               main_box.Add(self.sliders_box, 0, wx.ALIGN_CENTER)
+               main_box.Add(panel, 0, wx.EXPAND)               
+               self.Bind(wx.EVT_CLOSE, self.Quit)
+               #       fill in all the sliders and graphs      #               
+               FlowGraphBuilder.__init__(self, file_path)              
+               self.create_sliders()
+               graphs_box.SetCols(int(math.sqrt(len(self.sink_windows))))
+               for key in sorted(self.sink_windows.keys()): 
graphs_box.Add(self.sink_windows[key], 0, wx.EXPAND)               
+               self.SetSizerAndFit(main_box)
+               self.Show()     
+               self.start() #start the flow graph      
+                       
+       def Quit(self, event):
+               '''     Exit the application.   '''
+               self.stop()     #stop the flow graph
+               self.Destroy() #destroy the wx frame
+               sys.exit(0)
+               
+       def add_window(self, window, type='', title=''):
+               ''' Register the scope/fft window with a unique key.    '''
+               key = str(type) + str(title)
+               while self.sink_windows.has_key(key): key = key + '_'   
+               self.sink_windows[key] = window         
+               
+       def get_panel(self):
+               ''' Get the panel that will parent the graphical blocks.        
''' 
+               return self.panel
+               
+       def create_sliders(self):
+               ''' Using the list of variable keys imported by the builder, 
+                       create sliders for those variables with ranges. '''     
+               len = 0         
+               for key in self.var_keys:
+                       value, min, max, step = Variables.get_values(key)
+                       if Variables.is_ranged(key):
+                               variable_control = VariableControl(self, key, 
self.parse_callbacks)
+                               width = variable_control.get_slider_width()     
        
+                               ###     Create a new row of sliders if the 
current row is full  ###
+                               if len == 0 or len + width > MAX_SLIDERS_WIDTH:
+                                       len = 0
+                                       slider_box = wx.BoxSizer(wx.HORIZONTAL)
+                                       self.sliders_box.Add(slider_box, 0, 
wx.ALIGN_CENTER)
+                               slider_box.Add(variable_control, 0, 
wx.ALIGN_CENTER)                            
+                               len = len + width       
+               
+##############################################################################################
+#      Flow Graph App
+##############################################################################################
+class FlowGraphApp(wx.App):
+       """     The FlowGraphApp is the wx.App containing the FlowGraphFrame.   
"""
+       def __init__(self, flow_graph_file_path):
+               self.flow_graph_file_path = flow_graph_file_path
+               wx.App.__init__(self, 0)        
+                       
+       def OnInit(self):
+               """ If the creation of the frame fails, return False so the 
program will exit.  """
+               try:
+                       
self.SetTopWindow(FlowGraphFrame(self.flow_graph_file_path))#first argument is 
the flow graph
+                       return True
+               except Exception, e:
+                       sys.stderr.write(str(e)+'\n')
+                       sys.exit(1)
+
+if __name__ == '__main__':     
+       usage = "usage: %prog [-p] flow_graph"+DEFAULT_FILE_EXTENSION
+       parser = OptionParser(usage=usage)
+       parser.add_option("-p", "--pid_file", action="store", type="string", 
dest="pid_file", help="record process id")
+       parser.add_option("-d", "--disable-wx", action="store_true", 
dest="no_wx", default=False, help="disable the wx gui")
+       (options, args) = parser.parse_args()
+       if options.pid_file:
+               try: open(options.pid_file, 'w').write('%d\n' % os.getpid())
+               except: print "could not create pid file: %s"%options.pid_file
+       if len(args): #only create the wx app if a flow graph was passed
+               app = FlowGraphApp(args[0])
+               if options.no_wx: raw_input('Flow Graph Running...\nPress Enter 
to Exit: ')     #do not start wx
+               else: app.MainLoop()    #start the wxApp MainLoop
+       else: parser.print_help()       
+               
+               
\ No newline at end of file

Deleted: grc/trunk/src/FlowGraphApp.py

Modified: grc/trunk/src/Graphics/Bars.py
===================================================================
--- grc/trunk/src/Graphics/Bars.py      2007-06-07 05:22:11 UTC (rev 5729)
+++ grc/trunk/src/Graphics/Bars.py      2007-06-07 05:57:25 UTC (rev 5730)
@@ -28,68 +28,62 @@
 import gtk
                                        
 TOOLBAR_LIST = [
-                                               FLOW_GRAPH_NEW,
-                                               FLOW_GRAPH_OPEN,
-                                               FLOW_GRAPH_SAVE,
-                                               None,
-                                               FLOW_GRAPH_SNAP_SHOT,
-                                               None,
-                                               FLOW_GRAPH_UNDO,
-                                               FLOW_GRAPH_REDO,
-                                               None,
-                                               FLOW_GRAPH_RUN,
-                                               FLOW_GRAPH_STOP,
-                                               None,
-                                               ELEMENT_DELETE,
-                                               SIGNAL_BLOCK_ROTATE_LEFT,
-                                               SIGNAL_BLOCK_ROTATE_RIGHT,      
                                        
-                                       ]
+       FLOW_GRAPH_NEW,
+       FLOW_GRAPH_OPEN,
+       FLOW_GRAPH_SAVE,
+       None,
+       FLOW_GRAPH_SCREEN_CAPTURE,
+       None,
+       FLOW_GRAPH_UNDO,
+       FLOW_GRAPH_REDO,
+       None,
+       FLOW_GRAPH_EXEC,
+       FLOW_GRAPH_STOP,
+       None,
+       ELEMENT_DELETE,
+       SIGNAL_BLOCK_ROTATE_LEFT,
+       SIGNAL_BLOCK_ROTATE_RIGHT,                                              
+]
                                        
 MENU_BAR_LIST = [
-                                               (gtk.Action('File', '_File', 
None, None), 
-                                                       [
-                                                               FLOW_GRAPH_NEW,
-                                                               FLOW_GRAPH_OPEN,
-                                                               None,
-                                                               FLOW_GRAPH_SAVE,
-                                                               
FLOW_GRAPH_SAVE_AS,
-                                                               None,
-                                                               
FLOW_GRAPH_SNAP_SHOT,
-                                                               None,
-                                                               
APPLICATION_QUIT,
-                                                       ]),
-                                               (gtk.Action('Edit', '_Edit', 
None, None), 
-                                                       [
-                                                               FLOW_GRAPH_UNDO,
-                                                               FLOW_GRAPH_REDO,
-                                                               None,
-                                                               ELEMENT_DELETE,
-                                                               
SIGNAL_BLOCK_ROTATE_LEFT,
-                                                               
SIGNAL_BLOCK_ROTATE_RIGHT,
-                                                               
SIGNAL_BLOCK_PARAM_MODIFY,
-                                                       ]),
-                                               (gtk.Action('Run', '_Run', 
None, None), 
-                                                       [
-                                                               FLOW_GRAPH_RUN,
-                                                               FLOW_GRAPH_STOP,
-                                                       ]),
-                                               (gtk.Action('Options', 
'_Options', None, None), 
-                                                       [
-                                                               
FLOW_GRAPH_WINDOW_RESIZE,       
-                                                               
USRP_DIAGNOSTICS_DISPLAY,
-                                                               
PREFS_WINDOW_DISPLAY,                                   
-                                                        ]),
-                                               (gtk.Action('Help', '_Help', 
None, None), 
-                                                       [
-                                                               
ABOUT_WINDOW_DISPLAY,
-                                                               
COLORS_WINDOW_DISPLAY,
-                                                               
HOTKEYS_WINDOW_DISPLAY,
-                                                       ])
+       (gtk.Action('File', '_File', None, None), [
+               FLOW_GRAPH_NEW,
+               FLOW_GRAPH_OPEN,
+               None,
+               FLOW_GRAPH_SAVE,
+               FLOW_GRAPH_SAVE_AS,
+               None,
+               FLOW_GRAPH_SCREEN_CAPTURE,
+               None,
+               APPLICATION_QUIT,
+       ]),
+       (gtk.Action('Edit', '_Edit', None, None), [
+               FLOW_GRAPH_UNDO,
+               FLOW_GRAPH_REDO,
+               None,
+               ELEMENT_DELETE,
+               SIGNAL_BLOCK_ROTATE_LEFT,
+               SIGNAL_BLOCK_ROTATE_RIGHT,
+               SIGNAL_BLOCK_PARAM_MODIFY,
+       ]),
+       (gtk.Action('Execute', '_Execute', None, None), [
+               FLOW_GRAPH_EXEC,
+               FLOW_GRAPH_STOP,
+       ]),
+       (gtk.Action('Options', '_Options', None, None), [
+               FLOW_GRAPH_WINDOW_RESIZE,       
+               PREFS_WINDOW_DISPLAY,                                   
+       ]),
+       (gtk.Action('Help', '_Help', None, None), [
+               ABOUT_WINDOW_DISPLAY,
+               COLORS_WINDOW_DISPLAY,
+               HOTKEYS_WINDOW_DISPLAY,
+               MATH_EXPR_WINDOW_DISPLAY,
+               USRP_DIAGNOSTICS_DISPLAY,
+       ])
                                                                                
                
-                                        ]
+]
 
-
-
 class Toolbar(gtk.Toolbar):
        """     Toolbar is a gtk Toolbar with actions added from the toolbar 
list       """     
        def __init__(self):

Modified: grc/trunk/src/Graphics/Dialogs.py
===================================================================
--- grc/trunk/src/Graphics/Dialogs.py   2007-06-07 05:22:11 UTC (rev 5729)
+++ grc/trunk/src/Graphics/Dialogs.py   2007-06-07 05:57:25 UTC (rev 5730)
@@ -129,6 +129,13 @@
                self.set_comments("""\
 Thank you to all those from the mailing list who tested GNU Radio Companion 
and offered advice.
 --
+Special Thanks:
+A. Brinton Cooper -> starting the project
+CER Technology Fellowship Grant -> initial funding
+William R. Kenan Jr. Fund -> usrp & computers
+Patrick Strasser -> the GRC icon
+Achilleas Anastasopoulos -> trellis support
+--
 GNU Radio Companion, \
 This file is part of GNU Radio
 GRC comes with ABSOLUTELY NO WARRANTY. \
@@ -191,3 +198,74 @@
                        self.vbox.pack_start(label)
                self.run()
                self.destroy()          
+               
+######################################################################################################
                 
+class MathExprDialog(gtk.Dialog):
+       """ A dialog to test math expressions for the parser.   """
+       HELP_MSG = """\
+<b>Operators - Complex   <i>(complex arguments)</i></b> 
+       + - * / ^       
+<b>Trigonometric Functions   <i>(complex arguments, radians)</i></b> 
+       sin(z) cos(z) tan(z) asin(z) acos(z) atan(z) 
+       sinh(z) cosh(z) tanh(z) asinh(z) acosh(z) atanh(z)      
+<b>Complex Components   <i>(complex arguments)</i></b>
+       mag(z*) real(z*) imag(z*) conj(z*) arg(z)
+<b>Misc Functions   <i>(complex arguments)</i></b> 
+       abs(z*) pow(b, p) sqrt(z) log10(z) log(z, [b=e]) ln(z) exp(z) 
+<b>Misc Functions   <i>(floating point arguments)</i></b> 
+       floor(f) ceil(f) radians(deg) degrees(rad) mod(f1, f2) atan2(y, x) 
sgn(f) min(f*) max(f*)
+<b>Filter Taps Generators   <i>(floating point arguments, rates and 
frequencies in Hz)</i></b> 
+       low_pass(gain, samp_rate, cutoff_freq, width, [window=hamming], 
[beta=6.76])
+       high_pass(gain, samp_rate, cutoff_freq, width, [window=hamming], 
[beta=6.76])   
+       band_pass(gain, samp_rate, low_cutoff_freq, high_cutoff_freq, width, 
[window=hamming], [beta=6.76])
+       complex_band_pass(gain, samp_rate, low_cutoff_freq, high_cutoff_freq, 
width, [window=hamming], [beta=6.76])
+       band_reject(gain, samp_rate, low_cutoff_freq, high_cutoff_freq, width, 
[window=hamming], [beta=6.76])   
+       gaussian(gain, spb, bt, int ntaps)
+       hilbert(int ntaps, [window=rectangular], [beta=6.76])
+       root_raised_cosine(gain, samp_rate, symbol_rate, alpha, int ntaps) 
+       window(window, int ntaps, beta) 
+<b>Window Types for Filters</b>
+       hamming hann blackman rectangular kaiser
+<b>Other Constants</b>
+       pi e j  
+<b>Using Vectors</b>
+       () (num1,) (num2, num2, ...)    
+<b>Test Your Expressions Below:</b>\
+"""
+       def __init__(self):
+               """     Create a new gtk Dialog with a close button, an extry 
box, and an output text box.      """             
+               gtk.Dialog.__init__(self, buttons=('gtk-close', 
gtk.RESPONSE_CLOSE))
+               #       Create the title and label      #
+               self.set_title('Mathematical Expressions')
+               label = gtk.Label()
+               label.set_markup(self.HELP_MSG)
+               label.show()
+               self.vbox.pack_start(label, False)              
+               self.set_size_request(800, 600)
+               # create the entry box and connect it to a new handler #
+               self.param = GraphicalParam('Expression', RawExpr(''))
+               self.input_obj = self.param.get_input_object()
+               self.input_obj.entry.connect("changed", self.handle_changed)
+               self.vbox.pack_start(self.input_obj, False)             
+               #       create a text box for parser output     #
+               self.text_box = TextDisplay()
+               self.text_box.set_text('')                      
+               # add the scrolled window for the text box #
+               scrolled_window = gtk.ScrolledWindow()
+               scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, 
gtk.POLICY_AUTOMATIC)
+               scrolled_window.add_with_viewport(self.text_box)
+               scrolled_window.show()          
+               self.vbox.pack_start(scrolled_window, True)     
+               self.handle_changed()   #initial display
+               self.run()
+               self.destroy()
+               
+       def handle_changed(self, widget=None):
+               ''' Handle changed in the param's entry box.
+                       Call the default change handler and then update the 
text box.   '''
+               self.param.handle_changed()
+               if self.param.get_data_type().is_valid():
+                       text = str(self.param.get_data_type().parse())
+               else: text = self.param.get_data_type().msg
+               self.text_box.set_text(text)    
+               
\ No newline at end of file

Modified: grc/trunk/src/Graphics/FlowGraph.py
===================================================================
--- grc/trunk/src/Graphics/FlowGraph.py 2007-06-07 05:22:11 UTC (rev 5729)
+++ grc/trunk/src/Graphics/FlowGraph.py 2007-06-07 05:57:25 UTC (rev 5730)
@@ -39,6 +39,7 @@
 import Messages
 import Preferences
 import ParseXML
+import Messages
 
 class FlowGraph(gtk.DrawingArea):
        """     FlowGraph is the data structure to store graphical signal 
blocks, their graphical input/output
@@ -327,7 +328,12 @@
                        if self.mouse_pressed and self.selected_element != None:
                                self.selected_element.draw(self.pixmap)
                        self.window.draw_drawable(self.gc, self.pixmap, 0, 0, 
0, 0, -1, -1)      
-                                               
+
+##########################################################################
+##
+##                     Export the Flow Graph
+##
+##########################################################################     
                                        
        def to_nested_data(self):
                '''     Dump all the values in this flow graph into a nested 
data format.       '''
                vars_list = list()
@@ -344,7 +350,10 @@
                        ('vars', vars_list),
                        ('signal_blocks', signal_blocks_list),
                        ('connections', connections_list)
-               ])              
+               ])      
+       
##########################################################################
+       ##      Export the Variables
+       
##########################################################################      
                for key in self.variable_modification_window.to_key_list():
                        row = (key,) + Variables.get_values(key)
                        vars_list.append(('var', [
@@ -354,6 +363,9 @@
                                ('max', row[3]),
                                ('step', row[4]),
                        ]))
+       
##########################################################################
+       ##      Export the Signal Blocks
+       
##########################################################################
                for element in filter(Utils.is_signal_block, self.elements):
                        params_list = list()
                        signal_blocks_list.append(('signal_block', [
@@ -366,6 +378,9 @@
                        ]))
                        for param in element.get_params():
                                params_list.append(('param', 
str(param.get_data_type().get_data()))     )       
+       
##########################################################################
+       ##      Export the Connections
+       
##########################################################################
                for element in filter(Utils.is_connection, self.elements):
                        connections_list.append(('connection', [
                                ('input_signal_block_id', 
str(element.get_input_socket().get_parent().get_id())), 
@@ -375,53 +390,43 @@
                        ]))
                #print 'To',nested_data
                return nested_data
-               
+
+##########################################################################
+##     
+##                     Import the Flow Graph
+##
+##########################################################################     
        
        def from_nested_data(self, nested_data):
-               '''     Set all the values in this flow graph using the nested 
data.    '''
+               '''     Set all the values in this flow graph using the nested 
data.
+                       Return a string of errors, one error per line.  '''
                #print 'From',nested_data
-               errors = ''
                #TODO: use a non-destructive methode to clear the elements list
                self.elements = list()  #clear the elements
                find_data = ParseXML.find_data
                flow_graph = find_data([nested_data], 'flow_graph')
+               #       window width and height are optional    #
                window_width = find_data(flow_graph, 'window_width')
+               if window_width == None: window_width = MAX_WINDOW_WIDTH
                window_height = find_data(flow_graph, 'window_height')
+               if window_height == None: window_height = MAX_WINDOW_HEIGHT
                self.set_size_request(int(window_width),int(window_height))
                vars = find_data(flow_graph, 'vars')
                signal_blocks = find_data(flow_graph, 'signal_blocks')
                connections = find_data(flow_graph, 'connections')
-               Variables.clear_vars()
-               key_list = list()
-               for var in vars:
-                       var = find_data([var], 'var')                           
-                       key = find_data(var, 'key')
-                       value = find_data(var, 'value')
-                       min = find_data(var, 'min')
-                       max = find_data(var, 'max')
-                       step = find_data(var, 'step')
-                       Variables.register(key, value, min, max, step)
-                       key_list.append(key)
-               self.variable_modification_window.from_key_list(key_list)
+       
##########################################################################
+       ##      Import the Variables
+       
##########################################################################
+               keys = Variables.from_nested_data(vars)
+               self.variable_modification_window.from_key_list(keys)
+       
##########################################################################
+       ##      Import the Signal Blocks
+       
##########################################################################
                for signal_block in signal_blocks:
-                       signal_block = find_data([signal_block], 'signal_block')
-                       tag = find_data(signal_block, 'tag')
-                       id = find_data(signal_block, 'id')
-                       x_coordinate = int(find_data(signal_block, 
'x_coordinate'))
-                       y_coordinate = int(find_data(signal_block, 
'y_coordinate'))
-                       rotation = int(find_data(signal_block, 'rotation'))
-                       params = find_data(signal_block, 'params')
-                       try:                    
-                               signal_block = SignalBlockDefs.get_signal_block(
-                                       self, (x_coordinate,y_coordinate), 
rotation, tag, id, GraphicalSignalBlock
-                               )[0]
-                               for i,param in enumerate(params):
-                                       try:
-                                               param = find_data([param], 
'param')
-                                               
signal_block.get_params()[i].get_data_type().set_data(param)
-                                       except: errors = errors + 'An invalid 
parameter was parsed, ignoring parameter "%d" in block "%s".\n'%(i, id)         
  
-                               self.elements.append(signal_block)
-                       except SignalBlockDefs.TagNotFoundException: 
-                               errors = errors + 'The definition for "%s" was 
not found, ignoring block "%s".\n'%(tag, id)
+                       signal_block = 
GraphicalSignalBlock.from_nested_data(self, signal_block, 
GraphicalSignalBlock)[0]       #index 0 for just signal block  
+                       if signal_block: self.elements.append(signal_block)     
                
+       
##########################################################################
+       ##      Import the Connections
+       
##########################################################################
                for connection in connections:
                        connection = find_data([connection], 'connection')
                        input_signal_block_id = find_data(connection, 
'input_signal_block_id')
@@ -434,9 +439,9 @@
                                if element.get_id() == output_signal_block_id: 
output_socket = element.get_output_socket(output_socket_index)
                        try: self.elements.append(GraphicalConnection(self, 
input_socket, output_socket))
                        except (InvalidConnectionException, 
TooManyConnectionsException): 
-                               errors = errors + 'Could not connect "%s" 
input[%d] and "%s" output[%d].\n'%(
-                                       input_signal_block_id, 
input_socket_index, output_signal_block_id, output_socket_index)         
+                               Messages.send_error_load('Could not connect 
"%s" input[%d] and "%s" output[%d].'%(
+                                       input_signal_block_id, 
input_socket_index, output_signal_block_id, output_socket_index))        
                self.selected_element = None            
                self.update()
-               return errors
+               # done importing the flow graph #
 

Modified: grc/trunk/src/Graphics/MainWindow.py
===================================================================
--- grc/trunk/src/Graphics/MainWindow.py        2007-06-07 05:22:11 UTC (rev 
5729)
+++ grc/trunk/src/Graphics/MainWindow.py        2007-06-07 05:57:25 UTC (rev 
5730)
@@ -92,7 +92,7 @@
                                
        def set_title(self, title):
                """     set the title and prepend the program name      """
-               prepend_str = MAIN_WINDOW_PREFIX + ' - '
+               prepend_str = MAIN_WINDOW_PREFIX + ' - Editing: '
                gtk.Window.set_title(self, prepend_str + str(title))    
                
        def show_reports_window(self, show):

Modified: grc/trunk/src/Graphics/__init__.py
===================================================================
--- grc/trunk/src/Graphics/__init__.py  2007-06-07 05:22:11 UTC (rev 5729)
+++ grc/trunk/src/Graphics/__init__.py  2007-06-07 05:57:25 UTC (rev 5730)
@@ -24,5 +24,5 @@
 #      only import the modules that need external access #
 from MainWindow import MainWindow
 from FlowGraphFileDialog import FlowGraphFileDialog
-from Dialogs import 
PreferencesDialog,FlowGraphWindowSizeDialog,LooseChangesMessage,AboutDialog,DataTypeColorsDialog,HotKeysDialog
+from Dialogs import 
PreferencesDialog,FlowGraphWindowSizeDialog,LooseChangesMessage,AboutDialog,DataTypeColorsDialog,HotKeysDialog,MathExprDialog
 from USRPDiagnostics import USRPDiagnosticsDialog,enable_usrp_diagnostics

Modified: grc/trunk/src/MathExprParser.py
===================================================================
--- grc/trunk/src/MathExprParser.py     2007-06-07 05:22:11 UTC (rev 5729)
+++ grc/trunk/src/MathExprParser.py     2007-06-07 05:57:25 UTC (rev 5730)
@@ -19,180 +19,426 @@
 """
        MathExprParser.py 
        Josh Blum
-       Take a sting containing numbers, floats, complex 
-       and operators and parse it into a single answer.
+       This file provides:
+       eval_expr for evaluating string expressions,
+       verify_complex, verify_float, verify_int for casting numbers,
+       and verify_number for picking the best representation.
 """
 
-from math import cos, sin, log, atan2, e
+import math,cmath
+from gnuradio import gr
 
-_ORDER_OF_OPS = ('^', '*', '/', '-', '+')
+_ORDER_OF_OPS = ('^-', '^', '*', '/', '-', '+')
 
-_WHITESPACE = (' ', '\t')
+_WHITESPACE = (' ', '\t', '')
 
-def number(value):
-       ''' The parser method used for numeric entries. '''
-       return complex(value)
+_CONSTANTS = { #constans must be lower case
+       'pi' : cmath.pi,
+       'e' : cmath.e,
+       'j' : 1j,
        
-def complex_pow(base, power):
-       ''' Compute a complex base raised to a complex power.   '''
-       base = complex(base)
-       power = complex(power)
-       r = abs(base)
-       s = atan2(base.imag,base.real)
-       x = power.real
-       y = power.imag
-       if r == 0: return 0
-       else: return pow(r, x)*pow(e, 
-s*y)*(cos(y*log(r)+x*s)+1j*sin(y*log(r)+x*s))
+       'hamming' : gr.firdes.WIN_HAMMING,      #filter windows
+       'hann' : gr.firdes.WIN_HANN,
+       'blackman' : gr.firdes.WIN_BLACKMAN,
+       'rectangular' : gr.firdes.WIN_RECTANGULAR,
+       'kaiser' : gr.firdes.WIN_KAISER,
+}
+       
+#########################################################
+##     Number parsers
+#########################################################
 
-def eval_expr(expr_str):
-       '''     Evaluate a mathematical expression string with numbers, and 
operators.
-       Numbers will all be parsed. Operators are ^, *, /, -, +.        
-       Raise an exception on failue.   '''     
-       expr_list = list()
-       _convert_expr_str_to_list(expr_str, expr_list)
-       #print expr_list
-       _rectify_operators_in_expr_list(expr_list)
-       #print expr_list
-       return _eval_list(expr_list)
+def verify_complex(num):
+       ''' Verify that the number is a complex number.
+               Raise an exception if number cannot be cast to a complex.
+               Return the value as a complex.  '''
+       try: c_num = complex(num)       #ensure that the num can be complex
+       except: raise ValueError('"%s" is not a number.'%(num,))
+       return c_num
 
+def verify_float(num):
+       ''' Verify that the number has no imaginary part.
+               Raise an exception if the imaginary part is non zero.
+               Return the value as a float.    '''
+       c_num = verify_complex(num)     #ensure that the num can be complex
+       if c_num.imag != 0: raise ValueError('Expected a float but found 
"%s".'%(c_num,))
+       return float(c_num.real)
+
+def verify_int(num):
+       ''' Verify that the number has no imaginary part.
+               Verify that the number has no decimal part.
+               Otherwise raise an exception.
+               Return the value as a int       '''
+       f_num = verify_float(num)
+       if f_num - int(f_num) != 0: raise ValueError('Expected an integer but 
found "%s".'%(f_num,))
+       return int(f_num)
        
-def _eval_list(expr_list):
-       '''     Recursivly simplify a nested expression list. Each list will 
contain an
-       operand with 2 arguments or a single argument. An argument can be 
another list
-       to evaluate or a number. Raise an exception on failue.'''       
-       if type(expr_list) != type(list()): return number(expr_list)
-       else:
-               if len(expr_list) == 1: return _eval_list(expr_list[0])         
-               else:
-                       val_before = _eval_list(expr_list[0])
-                       val_after = _eval_list(expr_list[2])
-                       op = expr_list[1]
-                       if op == '^': return complex_pow(val_before,val_after)
-                       elif op == '*': return val_before * val_after
-                       elif op == '/': return val_before / val_after
-                       elif op == '+': return val_before + val_after
-                       elif op == '-': return val_before - val_after
-                       else: raise IllegalSymbolException('should be 
programmed out: '+op)
+def verify_number(num):
+       ''' Try to cast the number into its most primative form.
+               In this order: int, float, or complex. 
+               Raise an exception if num is not a number.
+               Return a number of type listed above. '''
+       try: return verify_int(num)     #try int
+       except:
+               try: return verify_float(num)   #try float
+               except: return verify_complex(num)      #complex or fail
 
-def _rectify_operators_in_expr_list(expr_list):
-       '''     Recursivly interate through a list of operators and arguments. 
Arguments can be
-       a list, or a number. Operators are ^, *, /, -, + and _. The underscore 
is
-       subbed in to represent an attatched negative sign. 
-       This operator will group all operands and arguments into nested lists 
following order of operations. 
-       Each list will have no more than        two arguments and a single 
operator. 
-       Raise an exception on failue (syntax problems). '''     
-       if len(expr_list) == 0: raise IllegalSyntaxException('empty!')
-       for op in _ORDER_OF_OPS:
-               flag = True
-               while op in expr_list and flag:
-                       i = expr_list.index(op)
-                       if i+1 < len(expr_list) and expr_list[i+1] == '_':
-                               if i-2 < len(expr_list) and expr_list[i+2] != 
'_':                                                              
-                                       expr_list.insert(i+3, [int(0), '-', 
expr_list[i+2]])
-                                       del expr_list[i+1:i+3]                  
                                        
-                               else: raise IllegalSyntaxException('should be 
programmed out: - -') 
-                       elif expr_list[i] == op:
-                               if i > 0 and i+1 < len(expr_list) and not 
_is_operator(expr_list[i-1]) and not _is_operator(expr_list[i+1]):
-                                       if len(expr_list) > 3:          
-                                                       expr_list.insert(i+2, 
[expr_list[i-1], op, expr_list[i+1]]) 
-                                                       del expr_list[i-1:i+2]
-                                       else: flag = False                      
        
-                               else: raise IllegalSyntaxException('operators 
missing arguments: '+str(expr_list[i]))
-               #       end while       #
-               for symbol in expr_list:
-                       if type(symbol) == type(list()): 
_rectify_operators_in_expr_list(symbol)        
+#########################################################
+##     Complex mathematical functions 
+#########################################################
+       
+def _complex_abs_v(*args):
+       ''' Compute the abs of a complex number or vector.      '''
+       sum = 0
+       for arg in args: 
+               if _is_list(arg): sum = sum + _complex_abs_v(*arg)
+               else: sum = sum + \
+                       verify_complex(arg).real*verify_complex(arg).real + \
+                       verify_complex(arg).imag*verify_complex(arg).imag
+       return verify_number(cmath.sqrt(sum))                   
 
+def _complex_real_v(*args):
+       ''' Get the real part of a number or vector.    '''
+       result = list()
+       for arg in args: 
+               if _is_list(arg): result.append(_complex_real_v(*arg))
+               else: result.append(verify_number(verify_complex(arg).real))
+       return result
 
-def _convert_expr_str_to_list(expr_str, expr_list,opening_bracket_type = None):
-       '''     Recursivly interate through the expression string. Pick out 
varibles, numbers, and operands.
-       This operation will pay attention to matching bracket pairs and add 
nested loops for each pair.
-       Raise an exception on failue (syntax and bracket problems).     '''     
                        
-       prev_symbol = None
-       while True:
-               symbol, expr_str = _get_next_symbol_from_expr(expr_str)
-               if symbol == None:
-                       if opening_bracket_type != None: raise 
MissingBracketException(_get_oposing_bracket(opening_bracket_type))
-                       return ''
-               elif _is_close_bracket(symbol): 
-                       if opening_bracket_type == None:
-                               raise 
MissingBracketException(_get_oposing_bracket(symbol))                     
-                       elif opening_bracket_type != 
_get_oposing_bracket(symbol):
-                               raise 
MissingBracketException(_get_oposing_bracket(opening_bracket_type))             
          
-                       return expr_str
-               elif _is_open_bracket(symbol):
-                       sub_list = list()                       
-                       expr_list.append(sub_list)
-                       expr_str = _convert_expr_str_to_list(expr_str, 
sub_list, symbol)
-               else:
-                       if symbol == '-' and prev_symbol == None:
-                               expr_list.append(int(0))
-                               expr_list.append('-')
-                               symbol = '_'    #underscore indicates a 
negative sign   
-                       elif symbol == '-' and prev_symbol == '_': raise 
IllegalSyntaxException('- -')
-                       elif symbol == '-' and _is_operator(prev_symbol):
-                               symbol = '_'    #underscore indicates a 
negative sign   
-                               expr_list.append(symbol) 
-                       else:   expr_list.append(symbol)
-               prev_symbol = symbol
-               if len(expr_list) > 1 and not (_is_operator(expr_list[-2]) or 
expr_list[-2] == '_') and not _is_operator(expr_list[-1]):
-                       raise IllegalSyntaxException(str(expr_list[-2])+' 
'+str(expr_list[-1])) 
+def _complex_imag_v(*args):
+       ''' Get the imaginary part of a number or vector.       '''
+       result = list()
+       for arg in args:  
+               if _is_list(arg): result.append(_complex_imag_v(*arg))
+               else: result.append(verify_number(verify_complex(arg).imag))
+       return result
 
-def _get_next_symbol_from_expr(expr_str):
-       '''     Remove the first symbol from an expression string. The symbol 
can be a number,
-       operator, or bracket. Raise an exception on failue (invalid symbols).   
'''     
-       #       remove leading whitespace       #
-       while expr_str != '' and _is_whitespace(expr_str[0]): expr_str = 
expr_str[1:]   
-       symbol = ''
-       if expr_str == '': return None,None
-       elif _is_operator(expr_str[0]) or _is_bracket(expr_str[0]): return 
expr_str[0],expr_str[1:]     
-       elif _is_numeric(expr_str[0]):          
-               while expr_str != '' and not _is_terminating_char(expr_str[0]):
-                       if _is_floating_point(expr_str[0]) and len(expr_str) == 
1: #e is the last char?
-                               raise IllegalSymbolException(symbol+expr_str)
-                       elif _is_floating_point(expr_str[0]) and expr_str[1] == 
'-':#e is followed by a minus?
-                               symbol = symbol + expr_str[0]
-                               expr_str = expr_str[1:]                 
-                       symbol = symbol + expr_str[0]
-                       expr_str = expr_str[1:]         
-               try: return number(symbol),expr_str
-               except: raise IllegalSymbolException(symbol)
-       else: raise IllegalSymbolException(expr_str[0])
+def _complex_conj_v(*args):
+       ''' Get the complex conjugate of a number or vector.    '''
+       result = list()
+       for arg in args:  
+               if _is_list(arg): result.append(_complex_conj_v(*arg))
+               else: 
result.append(verify_number(verify_complex(arg).conjugate()))
+       return result
+
+def _complex_arg(arg):
+       ''' Get the angle of the complex number (radians).      '''
+       return verify_number(math.atan2(verify_complex(arg).imag, 
verify_complex(arg).real))
+
+def _handle_filter(filter, *filter_args):
+       ''' Pass the filter arguments to the filter function. 
+               Format the arguments to floats and ints.
+               Raise errors for invalid filter arguments.
+               Return a list of taps.  '''
+       filter_args = list(filter_args) #make filter args a list
+       filter_props = {        # map a filter to filter argument properties:
+               # (allowed lengths of args), (args that are floats), (args that 
are ints)
+               gr.firdes.band_pass : ((5, 6, 7), (0, 1, 2, 3, 4, 6), ()),
+               gr.firdes.band_reject : ((5, 6, 7), (0, 1, 2, 3, 4, 6), ()),
+               gr.firdes.complex_band_pass : ((5, 6, 7), (0, 1, 2, 3, 4, 6), 
()),
+               
+               gr.firdes.high_pass : ((4, 5, 6), (0, 1, 2, 3, 5), ()),
+               gr.firdes.low_pass : ((4, 5, 6), (0, 1, 2, 3, 5), ()),
+               
+               gr.firdes.gaussian : ((4,), (0, 1, 2), (3,)),
+               gr.firdes.hilbert : ((1, 2, 3), (2,), (0,)),
+               gr.firdes.root_raised_cosine : ((5,), (0, 1, 2, 3), (4,)),
+               gr.firdes.window : ((3,), (2,), (1,)),
+       }
+       arg_lens, floats, ints = filter_props[filter]
+       # handle the filter arguments #
+       if len(filter_args) not in arg_lens: raise SyntaxError('Invalid number 
of arguments for "%s".'%filter)  
+       for i,arg in enumerate(filter_args):
+               if i in floats: filter_args[i] = verify_float(arg)
+               if i in ints: filter_args[i] = verify_int(arg)  
+       taps = list(filter(*filter_args))       #the taps must be a list
+       return taps 
+
+_FUNCTIONS = {
+       'pow' : lambda b, p: verify_number(b**p),       #complex power
+       'sqrt' : cmath.sqrt,
+
+       'abs' : _complex_abs_v,
+       'mag' : _complex_abs_v,
+       'real' : _complex_real_v,
+       'imag' : _complex_imag_v,
+       'conj' : _complex_conj_v,
+       'arg' : _complex_arg,
        
-def _is_terminating_char(char_str): return _is_operator(char_str) or 
_is_bracket(char_str) or _is_whitespace(char_str)
+       'sin' : lambda z: verify_number(cmath.sin(z)),  
+       'cos' : lambda z: verify_number(cmath.cos(z)),
+       'tan' : lambda z: verify_number(cmath.tan(z)),
+       
+       'asin' : lambda z: verify_number(cmath.asin(z)),
+       'acos' : lambda z: verify_number(cmath.acos(z)),
+       'atan' : lambda z: verify_number(cmath.atan(z)),
+       
+       'sinh' : lambda z: verify_number(cmath.sinh(z)),        #hyperbolics
+       'cosh' : lambda z: verify_number(cmath.cosh(z)),
+       'tanh' : lambda z: verify_number(cmath.tanh(z)),
+       
+       'asinh' : lambda z: verify_number(cmath.asinh(z)),
+       'acosh' : lambda z: verify_number(cmath.acosh(z)),
+       'atanh' : lambda z: verify_number(cmath.atanh(z)),
+       
+       'log10' : lambda z: verify_number(cmath.log10(z)),
+       'log' : lambda *z: verify_number(cmath.log(*z)),        #optional 2nd 
argument as base
+       'ln' : lambda z: cmath.log(z), #only allow natural log
+       'exp' : lambda z: verify_number(cmath.exp(z)),  
+       
+       'band_pass' : lambda *args: _handle_filter(gr.firdes.band_pass, *args), 
#taps generators
+       'band_reject' : lambda *args: _handle_filter(gr.firdes.band_reject, 
*args),
+       'complex_band_pass' : lambda *args: 
_handle_filter(gr.firdes.complex_band_pass, *args),
+       'gaussian' : lambda *args: _handle_filter(gr.firdes.gaussian, *args),
+       'high_pass' : lambda *args: _handle_filter(gr.firdes.high_pass, *args),
+       'hilbert' : lambda *args: _handle_filter(gr.firdes.hilbert, *args),
+       'low_pass' : lambda *args: _handle_filter(gr.firdes.low_pass, *args),
+       'root_raised_cosine' : lambda *args: 
_handle_filter(gr.firdes.root_raised_cosine, *args),
+       'window' : lambda *args: _handle_filter(gr.firdes.window, *args),
+       
+       'floor' : lambda f: math.floor(verify_float(f)),
+       'ceil' : lambda f: math.ceil(verify_float(f)),
+       'radians' : lambda f: math.radians(verify_float(f)),
+       'degrees' : lambda f: math.degrees(verify_float(f)),
+       'mod' : lambda f1, f2: math.fmod(verify_float(f1), verify_float(f2)),
+       'atan2' : lambda y, x: math.atan2(verify_float(y), verify_float(x)),
+       'sgn' : lambda f: abs(verify_float(f))/verify_float(f),
+       'min' : lambda *f: verify_number(min(*map(verify_float, f))),
+       'max' : lambda *f: verify_number(max(*map(verify_float, f))),
+}
 
+#########################################################
+##     Boolean tests for special characters and symbols
+#########################################################
+
+def _is_list(symbol): return type(symbol) == type(list())
+
+def _is_function(symbol): return symbol in _FUNCTIONS.keys()
+
+def _is_constant(symbol): return symbol in _CONSTANTS.keys()
+
+def _is_number(symbol):        
+       try: verify_number(symbol)
+       except: return False
+       return True
+       
+def _is_terminating_char(char_str): 
+       return \
+       _is_operator(char_str) or \
+       _is_bracket(char_str) or \
+       _is_whitespace(char_str) or \
+       _is_comma(char_str)
+
+def _is_comma(char_str): return char_str == ','
+
 def _is_whitespace(char_str): return char_str in _WHITESPACE
        
-def _is_floating_point(char_str): return char_str in ('e', 'E')
+def _is_operator(char_str): return char_str in _ORDER_OF_OPS
        
-def _is_operator(char_str): return char_str in ('+', '-', '*', '/', '^')
-       
-def _is_numeric(char_str): return char_str.isdigit() or char_str in ('.')
-       
 def _is_bracket(char_str): return _is_open_bracket(char_str) or 
_is_close_bracket(char_str)
        
 def _is_open_bracket(char_str): return char_str in ('(', '[', '{')
        
 def _is_close_bracket(char_str): return char_str in (')', ']', '}')
        
-def _get_oposing_bracket(bracket): return {
-                                                                               
                '(' : ')',
-                                                                               
                ')' : '(',
-                                                                               
                '[' : ']',
-                                                                               
                ']' : '[',
-                                                                               
                '{' : '}',
-                                                                               
                '}' : '{',
-                                                                               
                None : None
-                                                                               
                }[bracket]
+def _get_oposing_bracket(bracket): 
+       return {
+               '(' : ')',
+               ')' : '(',
+               '[' : ']',
+               ']' : '[',
+               '{' : '}',
+               '}' : '{',
+               '' : ''
+       }[bracket]
+       
+#########################################################
+##     Symbolic operations
+#########################################################              
+       
+def _handle_operation(op, arg1, arg2):
+       ''' Handle basic operations specified in the order of operations.
+               All calculations are complex, some vector operations are 
supported.
+               Return the number/list representing the result. '''
+       if op not in _ORDER_OF_OPS: raise NameError('Unknown operator: 
"%s".'%(op))     
+       arg1_is_list = _is_list(arg1)
+       arg2_is_list = _is_list(arg2)
+       # addition and subtraction of vectors #
+       if arg1_is_list and arg2_is_list and \
+               len(arg1) == len(arg2) and op in ('+', '-'):
+               result = list()
+               for i,arg1_elem in enumerate(arg1):
+                       arg2_elem = arg2[i]
+                       result.append(_handle_operation(op, arg1_elem, 
arg2_elem))
+               return result
+       # scalar times vector #
+       if not arg1_is_list and arg2_is_list and op == '*':
+               return map(lambda elem: _handle_operation(op, arg1, elem), arg2)
+       # vector times/divided scalar #
+       if arg1_is_list and not arg2_is_list and op in ('*', '/'):
+               return map(lambda elem: _handle_operation(op, elem, arg2), arg1)
+       # non vectored operations #
+       if not arg1_is_list and not arg2_is_list and \
+               _is_number(arg1) and _is_number(arg2):  #non vector operations
+               if op == '^-':
+                       return verify_number(arg1**(-1*arg2))
+               elif op == '^':
+                       return verify_number(arg1**arg2)
+               elif op == '*':
+                       return verify_number(arg1 * arg2)
+               elif op == '/':
+                       try: return verify_number(verify_complex(arg1) / 
verify_complex(arg2))  #make sure to use non-integer division
+                       except ZeroDivisionError: raise 
ZeroDivisionError('Cannot divide "%s" by 0.'%(arg1,))
+               elif op == '+':
+                       return verify_number(arg1 + arg2)
+               elif op == '-':
+                       return verify_number(arg1 - arg2)
+       raise ArithmeticError('Operation of "%s" cannot be performed on "%s", 
"%s".'%(op, arg1, arg2))  
+       
+#########################################################
+##     Evaluate the expression string 
+#########################################################      
 
-class IllegalSymbolException(Exception):
-       def __str__(self): return 'Symbol not recognized: 
'+Exception.__str__(self)
-               
-class MissingBracketException(Exception):
-       def __str__(self): return 'Expected bracket: '+Exception.__str__(self)  
-                                               
-class IllegalSyntaxException(Exception):
-       def __str__(self): return 'Bad Syntax: '+Exception.__str__(self)
-               
+def _separate_expression(expr_str):
+       '''     Separate the string into a list of elements.
+               Use only the lower-cased version of the expression string.
+               Terminating characters will dictate the separations.
+               Terminating characters will be included in the list.
+               Whitespace characters will be removed from the list.
+               Return a list of strings representing each element.     '''
+       elements = list()
+       element = ''
+       for char_str in expr_str.lower():
+               if _is_terminating_char(char_str):                      
+                       elements.append(element)
+                       elements.append(char_str)
+                       element = ''
+               else: element = element + char_str              
+       elements.append(element)        #append the remaining characters
+       #       remove whitespace       #
+       return filter(lambda elem: not _is_whitespace(elem), elements)
+
+def _rectify_operators(elements):
+       '''     Rectify the functionality of the minus sign (-),
+               and the plus sign (+) (in the floating point format).
+               Determine if the minus sign is used as a negative, 
+               and replace it with -1* or ^-. Also rejoin floating point 
formats. 
+               Return the list of elements with minus and plus used only as 
operators. '''
+       rectified_elements = list()
+       for i,element in enumerate(elements):
+               if i == 0 and element == '-':   #first element was a minus
+                       rectified_elements.extend(['-1', '*'])
+               elif i != 0 and element == '-' and i+1 != len(elements):        
#minus found!
+                       if _is_operator(elements[i-1]) or \
+                       _is_open_bracket(elements[i-1]) or \
+                       _is_comma(elements[i-1]):       #negative implied
+                               if elements[i-1] != '^': 
rectified_elements.extend(['-1', '*'])
+                               else: #^ proceeds - in order of ops, remove the 
^ and append ^- as a special operator
+                                       rectified_elements.pop()        #remove 
last element
+                                       rectified_elements.append('^-')
+                       elif elements[i-1][-1] == 'e' and 
_is_number(elements[i-1][0:-1]):      #found a -floating point format 
+                               f = rectified_elements.pop()    #remove last 
element
+                               elements[i+1] = "%s-%s"%(f, elements[i+1])
+                       else: rectified_elements.append(element)        
#regular minus
+               elif i != 0 and element == '+' and i+1 != len(elements) and \
+                       elements[i-1][-1] == 'e' and 
_is_number(elements[i-1][0:-1]):   #found a +floating point format 
+                       f = rectified_elements.pop()    #remove last element
+                       elements[i+1] = "%s+%s"%(f, elements[i+1])      
+               else: rectified_elements.append(element)        #non minus
+       return rectified_elements
+
+def _nest_elements(elements, open_bracket=''):
+       '''     Read through the elements, recursing at each open bracket.
+               Put elements inside bracket pairs into a list.  
+               Raise an Error if bracket pairs do not match.   
+               Return the nested elements.     '''
+       nested_elements = list()
+       while elements: #continue until elements is empty
+               element = elements.pop(0)
+               if _is_open_bracket(element):
+                       nested_elements.append(_nest_elements(elements, 
element))
+               elif _is_close_bracket(element):        
+                       if element != _get_oposing_bracket(open_bracket):       
#matching open/close brackets?
+                               raise SyntaxError('Expected "%s", but found 
"%s".'%(_get_oposing_bracket(open_bracket), element))
+                       return nested_elements
+               else: nested_elements.append(element)
+       if open_bracket:        #any unclosed bracket pairs? 
+               raise SyntaxError('Expected "%s", but found 
nothing.'%(_get_oposing_bracket(open_bracket),))
+       return nested_elements
+       
+def _simplify_nested_elements(nested_elements):
+       '''     Read through the nested elements and simplify expressions.
+               Work according to the order of operations specified above.
+               Recurse at each list, substitute constans, parse numbers, 
handle functions.
+               Make comma separated values into lists (represent vectors).
+               Return the final value of the expression.       '''
+       for i,element in enumerate(nested_elements):    
+               # simplify the nested lists #
+               if _is_list(element): nested_elements[i] = 
_simplify_nested_elements(element)
+               # substitute in values for constants #
+               elif _is_constant(element): nested_elements[i] = 
_CONSTANTS[element]
+               # substitute in values for numbers #
+               elif _is_number(element): nested_elements[i] = 
verify_number(element)                   
+       # handle functions #
+       for function in _FUNCTIONS.keys():
+               while function in nested_elements:
+                       i = nested_elements.index(function)                     
        
+                       if i+1 == len(nested_elements): raise 
SyntaxError('Function "%s" has no arguments.'%(function))
+                       args = nested_elements[i+1]
+                       if not _is_list(args): args = [args]
+                       try: ans = _FUNCTIONS[function](*args)
+                       except Exception, e: 
+                               raise ValueError('Function "%s" with arguments 
"%s" failed.\n\t%s'%(function, nested_elements[i+1], e))
+                       if not _is_list(ans): ans = [ans]       # ans must be a 
list
+                       ans_with_commas = list()
+                       for an in ans: ans_with_commas.extend([an, ','])
+                       nested_elements = nested_elements[0:i] + 
ans_with_commas[0:-1] + nested_elements[i+2:]          
+       # simplify operations #
+       for operator in _ORDER_OF_OPS:
+               while operator in nested_elements:
+                       i = nested_elements.index(operator)                     
                
+                       arg1 = arg2 = None
+                       if i > 0: arg1 = nested_elements[i-1]
+                       if i+1 < len(nested_elements): arg2 = 
nested_elements[i+1]
+                       #raise error if arg1 or arg2 is None
+                       if arg1 == None or arg2 == None: raise 
SyntaxError('Operator "%s" is missing argument.'%(operator))
+                       ans = _handle_operation(operator, arg1, arg2)
+                       if not _is_list(ans): ans = [ans]       # ans must be a 
list
+                       ans_with_commas = list()
+                       for an in ans: ans_with_commas.extend([an, ','])
+                       nested_elements = nested_elements[0:i-1] + 
ans_with_commas[0:-1] + nested_elements[i+2:]                
+       # convert comma separated elements into a list #
+       vector = list() 
+       last_element = None
+       for element in nested_elements:
+               if not _is_comma(element): 
+                       if not _is_list(element) and not _is_number(element) 
and element not in _CONSTANTS.values(): 
+                               raise NameError('Unknown symbol 
"%s".'%(element))
+                       if last_element and not _is_comma(last_element): 
+                               raise SyntaxError('Expected comma, but found 
"%s".'%(element))
+                       vector.append(element)
+               elif _is_comma(element) and _is_comma(last_element):
+                       raise SyntaxError('Commas must be separated by 
non-commas.')
+               last_element = element
+       if len(vector) == 1 and not _is_comma(last_element): return vector[0]   
#return single number
+       return vector   #otherwise return vector
+
+def eval_expr(expr_str):
+       '''     Evaluate a mathematical expression string with numbers, and 
operators.
+               Raise an exception on failue.   
+               Return a list containing the parsed expression. '''     
+       separated_elements = _separate_expression(expr_str)
+       #print "separated", separated_elements
+       rectified_elements = _rectify_operators(separated_elements)
+       #print "rectified", rectified_elements
+       nested_elements = _nest_elements(rectified_elements)
+       #print "nested", nested_elements
+       simplified = _simplify_nested_elements(nested_elements)
+       return simplified
+       
 if __name__ == '__main__':
-       print eval_expr('-4j + -(2)^2 ')
+       ''' Evaluate expressions passed by argv(1).     '''
+       import sys
+       if len(sys.argv) > 1: print eval_expr(sys.argv[1])
+       else: print "No expressions passed!"
        
\ No newline at end of file

Modified: grc/trunk/src/Messages.py
===================================================================
--- grc/trunk/src/Messages.py   2007-06-07 05:22:11 UTC (rev 5729)
+++ grc/trunk/src/Messages.py   2007-06-07 05:57:25 UTC (rev 5730)
@@ -48,8 +48,10 @@
                                                        ------------------   
Loading Flow Graph   ------------------\n""")      
        send('Trying to load: "%s"'%file_path + '\n')
                                                        
-def send_end_load(errors):
-       if errors: send('>>>    Errors:\n%s'%errors)
+def send_error_load(error):
+       send('>>> Error: %s\n'%error)
+
+def send_end_load():
        send(">>> Done\n")
        
 def send_fail_load(error):

Modified: grc/trunk/src/Preferences.py
===================================================================
--- grc/trunk/src/Preferences.py        2007-06-07 05:22:11 UTC (rev 5729)
+++ grc/trunk/src/Preferences.py        2007-06-07 05:57:25 UTC (rev 5730)
@@ -118,7 +118,6 @@
        categories = find_data(preferences, 'categories')
        for i,category in enumerate(categories):
                category = find_data([category], 'category')
-               title = find_data(category, 'title')
                prefs = find_data(category, 'prefs')
                for j,pref in enumerate(prefs):
                        pref = find_data([pref], 'pref')

Deleted: grc/trunk/src/Run.py

Modified: grc/trunk/src/SignalBlockDefs/Conversions.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/Conversions.py        2007-06-07 05:22:11 UTC 
(rev 5729)
+++ grc/trunk/src/SignalBlockDefs/Conversions.py        2007-06-07 05:57:25 UTC 
(rev 5730)
@@ -27,14 +27,17 @@
 from SignalBlockConstants import all_choices,all_vector_choices
 from Constants import MAX_NUM_SOCKETS
 
-def ComplexComponents(sb):
-       sb.add_input_socket('in', Complex())
-       sb.add_output_socket('out', Float())
+def ComplexComponents(sb):             
+       vlen = Int(1, min=1)
+       sb.add_input_socket('in', Complex(), vlen=vlen)
+       sb.add_output_socket('out', Float(), vlen=vlen)
        sb.add_param('Output Type', Enum([('Real', gr.complex_to_real),
                                                                                
                ('Imaginary', gr.complex_to_imag),
                                                                                
                ('Magnitude', gr.complex_to_mag),
+                                                                               
                ('Magnitude Squared', gr.complex_to_mag_squared),
                                                                                
                ('Phase Angle', gr.complex_to_arg)]), type=True)        
-       return sb, lambda fg, type: type.parse()(1)
+       sb.add_param('Vector Length', vlen)
+       return sb, lambda fg, type, vlen: type.parse()(vlen.parse())
        
 def ComplexConjugate(sb):
        sb.add_input_socket('in', Complex())
@@ -48,12 +51,14 @@
        sb.set_docs('''The imaginary input socket (jin) can be unconnected.''')
        return sb, lambda fg: gr.float_to_complex()
        
-def ComplexToFloat(sb):
-       sb.add_output_socket('out', Float())
-       sb.add_output_socket('jout', Float(), optional=True)
+def ComplexToFloat(sb):        
+       vlen = Int(1, min=1)
+       sb.add_output_socket('out', Float(), vlen=vlen)
+       sb.add_output_socket('jout', Float(), vlen=vlen, optional=True)
        sb.add_input_socket('in', Complex())            
+       sb.add_param('Vector Length', vlen)
        sb.set_docs('''The imaginary output socket (jout) can be 
unconnected.''')
-       return sb, lambda fg: gr.complex_to_float()
+       return sb, lambda fg, vlen: gr.complex_to_float(vlen.parse())
        
 def ShortToFloat(sb):
        sb.add_input_socket('in', Short())
@@ -158,7 +163,7 @@
        sb.add_param('Num Inputs', Int(3, min=1, max=MAX_NUM_SOCKETS), 
                                        show_label=False, 
input_sockets_controller=True)
        sb.add_param('Vector Length', vlen)
-       sb.set_docs('''2 <= Num Inputs <= %d'''%MAX_NUM_SOCKETS)        
+       sb.set_docs('''1 <= Num Inputs <= %d'''%MAX_NUM_SOCKETS)        
        return sb, lambda fg, type, num_inputs, vlen: 
gr.interleave(type.parse().get_num_bytes()*vlen.parse())
        
 def Deinterleave(sb):
@@ -170,7 +175,7 @@
        sb.add_param('Num Outputs', Int(3, min=1, max=MAX_NUM_SOCKETS), 
                                        show_label=False, 
output_sockets_controller=True)       
        sb.add_param('Vector Length', vlen)
-       sb.set_docs('''2 <= Num Outputs <= %d'''%MAX_NUM_SOCKETS)       
+       sb.set_docs('''1 <= Num Outputs <= %d'''%MAX_NUM_SOCKETS)       
        return sb, lambda fg, type, num_outputs, vlen: 
gr.deinterleave(type.parse().get_num_bytes()*vlen.parse())
        
 def StreamsToStream(sb):
@@ -185,7 +190,7 @@
        sb.add_param('Vector Length', vlen)
        sb.set_docs('''\
 Interleave N streams into a single stream.     
-2 <= Num Streams <= %d'''%MAX_NUM_SOCKETS)     
+1 <= Num Streams <= %d'''%MAX_NUM_SOCKETS)     
        return sb, lambda fg, type, num_streams, vlen: 
fcn(type.parse().get_num_bytes()*vlen.parse(), num_streams.parse())
        
 def StreamToStreams(sb):
@@ -200,7 +205,7 @@
        sb.add_param('Vector Length', vlen)
        sb.set_docs('''\
 Deinterleave a stream into N streams.
-2 <= Num Streams <= %d'''%MAX_NUM_SOCKETS)     
+1 <= Num Streams <= %d'''%MAX_NUM_SOCKETS)     
        return sb, lambda fg, type, num_streams, vlen: 
fcn(type.parse().get_num_bytes()*vlen.parse(), num_streams.parse())
        
 def StreamsToVector(sb):

Modified: grc/trunk/src/SignalBlockDefs/Filters.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/Filters.py    2007-06-07 05:22:11 UTC (rev 
5729)
+++ grc/trunk/src/SignalBlockDefs/Filters.py    2007-06-07 05:57:25 UTC (rev 
5730)
@@ -123,6 +123,23 @@
        sb.add_param('FB Taps', FloatVector())
        return sb, lambda fg, fftaps, fbtaps: fcn(fftaps.parse(), 
fbtaps.parse())
 
+def FilterDelay(sb):
+       fcn = gr.filter_delay_fc
+       sb.add_input_socket('in1', Float())
+       sb.add_input_socket('in2', Float(), optional=True)
+       sb.add_output_socket('out', Complex())
+       sb.add_param('Taps', FloatVector())
+       sb.set_docs('''\
+The block takes one or two float stream and outputs a complex stream. \
+If only one float stream is input, \
+the real output is a delayed version of this input and the imaginary output is 
the filtered output. \
+If two floats are connected to the input, \
+then the real output is the delayed version of the first input, \
+the imaginary output is the filtered output. \
+The delay in the real path accounts for the group delay introduced by the 
filter in the imaginary path.\
+''')
+       return sb, lambda fg, taps: fcn(taps.parse())
+
 ###########################################################################
 #      Special filters using taps generators
 ###########################################################################
@@ -140,7 +157,7 @@
        ('Blackman', gr.firdes.WIN_BLACKMAN),
        ('Rectangular', gr.firdes.WIN_RECTANGULAR),
        ('Kaiser', gr.firdes.WIN_KAISER),
-       ]
+]
 filter_choices = [
        ('FFT: Float->Float', (gr.fft_filter_fff, Float(), Float())),
        ('FIR: Complex->Complex', (gr.fir_filter_ccf, Complex(), Complex())),
@@ -149,7 +166,7 @@
        ('Interp FIR: Complex->Complex', (gr.interp_fir_filter_ccf, Complex(), 
Complex())),
        ('Interp FIR: Float->Float', (gr.interp_fir_filter_fff, Float(), 
Float())),
        ('Interp FIR: Float->Short', (gr.interp_fir_filter_fsf, Float(), 
Short())),
-       ]
+]
                        
 def LowPassFilter(sb):
        taps_maker = gr.firdes.low_pass
@@ -246,6 +263,15 @@
        sb.add_param('Num Taps', Int(10, min=0))
        return sb, lambda fg, num_taps: fcn(num_taps.parse())
        
+def Goertzel(sb):   
+       fcn = gr.goertzel_fc  
+       sb.add_input_socket('in', Float())
+       sb.add_output_socket('out', Complex())
+       sb.add_param('Rate', Int())
+       sb.add_param('Length', Int())
+       sb.add_param('Frequency', Float())   
+       return sb, lambda fg, rate, len, freq: 
fcn(rate.parse(),len.parse(),freq.parse()) 
+       
 def PowerSquelch(sb):
        fcn = gr.simple_squelch_cc
        sb.add_input_socket('in', Complex())
@@ -310,17 +336,6 @@
        sb.set_docs('''Constant Modulus Adaptive Filter.''')
        return sb, lambda fg, num_taps, mod, mu: fcn(num_taps.parse(), 
mod.parse(), mu.parse())
        
-def CostasLoop(sb):
-       fcn = gr.costas_loop_cc
-       sb.add_input_socket('in', Complex())
-       sb.add_output_socket('out', Complex())
-       sb.add_param('Alpha', Float())
-       sb.add_param('Beta', Float())
-       sb.add_param('Max Freq', Float())
-       sb.add_param('Min Freq', Float())
-       sb.add_param('Order', Enum([('2', 2), ('4', 4)]))
-       return sb, lambda fg, *args: fcn(*map(lambda a: a.parse(), args))
-       
 def ClockRecovery(sb):
        type = Enum([('Complex', (gr.clock_recovery_mm_cc, Complex())),
                                        ('Float', (gr.clock_recovery_mm_ff, 
Float())),])

Modified: grc/trunk/src/SignalBlockDefs/GraphicalSinks.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/GraphicalSinks.py     2007-06-07 05:22:11 UTC 
(rev 5729)
+++ grc/trunk/src/SignalBlockDefs/GraphicalSinks.py     2007-06-07 05:57:25 UTC 
(rev 5730)
@@ -86,7 +86,6 @@
                        baseband_freq=baseband_freq.parse(), 
fft_rate=fft_rate.parse())         
                block.set_average(average)                      #set the 
average option outside the contructor
                fg.add_window(block.win, waterfall_display_priority, 
title.parse())
-               fg.add_callback(block.set_sample_rate, samp_rate)
                fg.add_callback(block.set_baseband_freq, baseband_freq)
                th = gr.throttle(type.parse()[1].get_num_bytes(), 
samp_rate.parse())
                fg.connect(th, block)
@@ -115,7 +114,6 @@
                        sample_rate=samp_rate.parse(), 
frame_decim=frame_decim.parse(), 
                        v_scale=v_scale, t_scale=t_scale.parse())
                fg.add_window(block.win, scope_display_priority, title.parse()) 
-               fg.add_callback(block.set_sample_rate, samp_rate)       
                th = gr.throttle(type.parse()[1].get_num_bytes(), 
samp_rate.parse())
                fg.connect(th, block)
                return th
@@ -140,7 +138,6 @@
                elif marker == 1: block.win.set_format_dot()
                elif marker == 2: block.win.set_format_line()
                fg.add_window(block.win, constellation_display_pritority, 
title.parse())        
-               fg.add_callback(block.set_sample_rate, samp_rate)       
                th = gr.throttle(Complex().get_num_bytes(), samp_rate.parse())
                fg.connect(th, block)
                return th

Modified: grc/trunk/src/SignalBlockDefs/Misc.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/Misc.py       2007-06-07 05:22:11 UTC (rev 
5729)
+++ grc/trunk/src/SignalBlockDefs/Misc.py       2007-06-07 05:57:25 UTC (rev 
5730)
@@ -25,6 +25,7 @@
 from DataType import *
 from gnuradio import gr
 from SignalBlockConstants import default_samp_rate,all_choices
+from Constants import MAX_NUM_SOCKETS
 
 def Throttle(sb):
        fcn = gr.throttle
@@ -35,7 +36,7 @@
        sb.add_param('Type', type, False, type=True)
        sb.add_param('Sampling Rate', Float(default_samp_rate)) 
        sb.add_param('Vector Length', vlen)
-       sb.set_docs('''Connect a throttle to control the flow rate of data.''') 
+       sb.set_docs('''Connect a throttle to control the actual rate of the 
data.''')   
        return sb, lambda fg, type, samp_rate, vlen: 
fcn(type.parse().get_num_bytes()*vlen.parse(), samp_rate.parse())
        
 def Head(sb):
@@ -47,9 +48,21 @@
        sb.add_param('Type', type, False, type=True)
        sb.add_param('Num Items', Int(1000, min=0))     
        sb.add_param('Vector Length', vlen)
-       sb.set_docs('''Copies the first num items to the output then signals 
done.''')  
-       return sb, lambda fg, type, samp_rate, vlen: 
fcn(type.parse().get_num_bytes()*vlen.parse(), samp_rate.parse())
+       sb.set_docs('''Copies the first num items to the output then stops.''') 
+       return sb, lambda fg, type, num_items, vlen: 
fcn(type.parse().get_num_bytes()*vlen.parse(), num_items.parse())
        
+def SkipHead(sb):
+       fcn = gr.skiphead
+       type = Enum(all_choices, 1)     
+       vlen = Int(1, min=1)
+       sb.add_input_socket('in', Variable(type), vlen=vlen)
+       sb.add_output_socket('out', Variable(type), vlen=vlen)
+       sb.add_param('Type', type, False, type=True)
+       sb.add_param('Num Items', Int(1000, min=0))     
+       sb.add_param('Vector Length', vlen)
+       sb.set_docs('''Skips the first num items, and then copies input to 
output.''')  
+       return sb, lambda fg, type, num_items, vlen: 
fcn(type.parse().get_num_bytes()*vlen.parse(), num_items.parse())
+       
 def RMS(sb):
        type = Enum([('Complex', (gr.rms_cf, Complex())),
                                        ('Float', (gr.rms_ff, Float())),
@@ -72,5 +85,3 @@
 def Note(sb):
        sb.add_param('Note', String(''))
        return sb, lambda *args: None   
-
-               
\ No newline at end of file

Modified: grc/trunk/src/SignalBlockDefs/Modulators.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/Modulators.py 2007-06-07 05:22:11 UTC (rev 
5729)
+++ grc/trunk/src/SignalBlockDefs/Modulators.py 2007-06-07 05:57:25 UTC (rev 
5730)
@@ -192,4 +192,50 @@
        sb.set_docs('''Mu is the fractional delay between 0 and 1''')
        return sb, lambda fg, *args: fcn(fg, *map(lambda a: a.parse(), args))
        
+###########################################################################
+#      Phase Locked Loops
+###########################################################################    
+       
+def CostasLoop(sb):
+       fcn = gr.costas_loop_cc
+       sb.add_input_socket('in', Complex())
+       sb.add_output_socket('bout', Complex())
+       sb.add_output_socket('nout', Complex(), optional=True)
+       sb.add_param('Alpha', Float())
+       sb.add_param('Beta', Float())
+       sb.add_param('Max Freq', Float())
+       sb.add_param('Min Freq', Float())
+       sb.add_param('Order', Enum([('2', 2), ('4', 4)]))
+       sb.set_docs('''\
+Carrier tracking PLL for QPSK input. \
+The Costas loop has two output streams: \
+"bout" is the baseband I stream, "nout" is the normalized frequency of the 
loop. \
+The "nout" may be left open. ''')
+       return sb, lambda fg, *args: fcn(*map(lambda a: a.parse(), args))
+       
+def PLL(sb):
+       type = Enum([                                           #fcn, output 
type
+               ('Carrier Tracking', (gr.pll_carriertracking_cc, Complex())),
+               ('Freq Det', (gr.pll_freqdet_cf, Float())),
+               ('Ref Out', (gr.pll_refout_cc, Complex())),
+       ])
+       sb.add_input_socket('in', Complex())
+       sb.add_output_socket('out', Variable(type, index=1))
+       sb.add_param('Type', type, type=True)   
+       sb.add_param('Alpha', Float())
+       sb.add_param('Beta', Float())
+       sb.add_param('Max Freq', Float())
+       sb.add_param('Min Freq', Float())
+       sb.set_docs('''\
+All settings max_freq and min_freq are in terms of radians per sample, NOT 
HERTZ. \
+Alpha is the phase gain (first order, units of radians per radian), and \
+beta is the frequency gain (second order, units of radians per sample per 
radian).
+
+Carrier Tracking - This PLL locks onto a [possibly noisy] reference carrier on 
the input and outputs that signal, downconverted to DC.
+
+Freq Det - This PLL locks onto a [possibly noisy] reference carrier on the 
input and outputs an estimate of that frequency in radians per sample.
+
+Ref Out - This PLL locks onto a [possibly noisy] reference carrier on the 
input and outputs a clean version which is phase and frequency aligned to it.
+''')
+       return sb, lambda fg, type, *args: type.parse()[0](*map(lambda a: 
a.parse(), args))             
        
\ No newline at end of file

Modified: grc/trunk/src/SignalBlockDefs/SignalBlockConstants.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/SignalBlockConstants.py       2007-06-07 
05:22:11 UTC (rev 5729)
+++ grc/trunk/src/SignalBlockDefs/SignalBlockConstants.py       2007-06-07 
05:57:25 UTC (rev 5730)
@@ -29,14 +29,16 @@
        ('Float', Float()),
        ('Int', Int()),
        ('Short', Short()),
-       ('Byte', Byte()),]
+       ('Byte', Byte()),
+]
 
 all_vector_choices = [
        ('Complex Vector', (ComplexVector(), Complex())),
        ('Float Vector', (FloatVector(), Float())),
        ('Int Vector', (IntVector(), Int())),
        ('Short Vector', (ShortVector(), Short())),
-       ('Byte Vector', (ByteVector(), Byte()))]
+       ('Byte Vector', (ByteVector(), Byte()))
+]
 
 default_samp_rate = '$samp_rate'
 
@@ -46,7 +48,8 @@
        ('24KHz', int(24e3)),
        ('32KHz', int(32e3)),
        ('44.1KHz', int(44.1e3)),
-       ('48KHz', int(48e3)),]
+       ('48KHz', int(48e3)),
+]
 default_audio_rate_index = 3
 
 default_udp_port = 3456

Modified: grc/trunk/src/SignalBlockDefs/SignalBlockTree.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/SignalBlockTree.py    2007-06-07 05:22:11 UTC 
(rev 5729)
+++ grc/trunk/src/SignalBlockDefs/SignalBlockTree.py    2007-06-07 05:57:25 UTC 
(rev 5730)
@@ -110,6 +110,7 @@
                                ('Freq Xlating FIR Filter', 
Filters.FreqXlatingFIRFilter),              
                                ('Rational Resampler', 
Filters.RationalResampler),      
                                ('IIR Filer', Filters.IIRFiler),        
+                               ('Filter Delay', Filters.FilterDelay),
                        ]),             
                        ('Filters', [                   
                                ('Low Pass Filter', Filters.LowPassFilter),
@@ -119,7 +120,8 @@
                                ('Window', Filters.Window),
                                ('Root Raised Cosine', 
Filters.RootRaisedCosine),                                                      
         
                                ('Single Pole IIR Filter', 
Filters.SinglePoleIIRFilter),
-                               ('Hilbert', Filters.Hilbert),   
+                               ('Hilbert', Filters.Hilbert),
+                               ('Goertzel', Filters.Goertzel), 
                                ('Power Squelch', Filters.PowerSquelch),
                                ('Downsample', Filters.Downsample),
                                ('Upsample', Filters.Upsample),                 
        
@@ -127,7 +129,6 @@
                                ('Automatic Gain Control', 
Filters.AutomaticGainControl),
                                ('Automatic Gain Control2', 
Filters.AutomaticGainControl2),
                                ('CMA Filter', Filters.CMAFilter),
-                               ('Costas Loop', Filters.CostasLoop),
                                ('Clock Recovery', Filters.ClockRecovery),
                                ('FFT', Filters.FFT),
                                ('IFFT', Filters.IFFT),
@@ -136,6 +137,8 @@
                                ('Frequency Modulation', 
Modulators.FrequencyModulation),
                                ('Phase Modulation', 
Modulators.PhaseModulation),
                                ('Quadrature Demodulation', 
Modulators.QuadratureDemodulation),
+                               ('Costas Loop', Modulators.CostasLoop),
+                               ('Phase Locked Loop', Modulators.PLL),
                                ('WFM Receive', Modulators.WFMReceive),         
        
                                ('WFM Transmit', Modulators.WFMTransmit),       
                                ('NBFM Receive', Modulators.NBFMReceive),       
                
@@ -163,13 +166,14 @@
                                ('BCJR Algorithm Combined with Metric', 
Trellis.Soft_In_Soft_Out_Combined),
                                ('Interleaver', Trellis.Interleaver),
                                ('Deinterleaver', Trellis.Deinterleaver),
-         ]),
+                       ]),
                        ('Misc', [      
                                ('Throttle', Misc.Throttle),
-                               ('Head', Misc.Head),                    
+                               ('Head', Misc.Head),    
+                               ('Skip Head', Misc.SkipHead),                   
                                ('RMS', Misc.RMS),      
                                ('About', Misc.About),
-                               ('Note', Misc.Note),            
+                               ('Note', Misc.Note),    
                        ]),
                ] 
                
@@ -189,9 +193,9 @@
                try: 
                        get_signal_block(None, (0,0), 0, tag[0], '')
                        if tag[0] in tags_set:  #       remove redundant tags   
#
-                               print 'Removing redundant tag "%s" in category 
"%s"...'%(tag[0], category)
-                               tags_to_remove.append(tag)      
-                       else: tags_set.add(tag[0])
+                               print 'Removing redundant tag "%s" in category 
"%s"...'%(tag[0], category)
+                               tags_to_remove.append(tag)      
+                       else: tags_set.add(tag[0])
                except (ImportError, AttributeError), e: 
                        print e, " in %s! -> continuing..."%tag[0]      
                        tags_to_remove.append(tag)              
@@ -203,7 +207,7 @@
        if len(tags) == 0: 
                print 'Removing category "%s", it was emptied...'%category
                cats_to_remove.append((category,tags))
-for cat in cats_to_remove: TAGS.remove(cat)
+for cat in cats_to_remove: SB_TREE.remove(cat)
         
 
 class TagNotFoundException(Exception):

Modified: grc/trunk/src/SignalBlockDefs/Sinks.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/Sinks.py      2007-06-07 05:22:11 UTC (rev 
5729)
+++ grc/trunk/src/SignalBlockDefs/Sinks.py      2007-06-07 05:57:25 UTC (rev 
5730)
@@ -96,11 +96,6 @@
                self.fg = fg
                self.var_key = var_key
                self.msgq = msgq
-               #       make sure that the variable exists and that it has no 
range     #
-               if not Variables.has_key(self.var_key):
-                       raise Exception('Error: variable "%s" does not 
exist!'%self.var_key)                    
-               elif Variables.get_values(self.var_key)[1] != '':
-                       raise Exception('Error: variable "%s" has a 
range!'%self.var_key)               
                threading.Thread.__init__(self)
                print 'Created variable sink thread for variable "%s"'%var_key
                                
@@ -117,21 +112,14 @@
                                # If so, we take only the last one
                                if nitems > 1:
                                        start = itemsize * (nitems - 1)
-                                       s = s[start:start+itemsize]
-                               
+                                       s = s[start:start+itemsize]             
                
                                #       parse the data to a complex or 
float/int string #
                                complex_data = Numeric.fromstring (s, 
Numeric.Float32)
                                if len(complex_data) == 2: new_value = "%f + 
%fj"%(complex_data[0], complex_data[1])
                                else: new_value = "%f"%(complex_data[0],) 
-                               
-                               old_value = Variables.get_value(self.var_key)
-                               # write the new value #                 
-                               try: 
-                                       Variables.unregister(self.var_key)
-                                       Variables.register(self.var_key, 
new_value)                             
-                               except: 
-                                       print "error registering"               
                                
-                                       Variables.register(self.var_key, 
old_value)     #error registering, restore variable
+                               # write the new value #         
+                               Variables.unregister(self.var_key)
+                               Variables.register(self.var_key, new_value)     
                        
                                #       parse the call backs    #               
                
                                self.fg.parse_callbacks()       
                        except: break                   

Modified: grc/trunk/src/SignalBlockDefs/__init__.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/__init__.py   2007-06-07 05:22:11 UTC (rev 
5729)
+++ grc/trunk/src/SignalBlockDefs/__init__.py   2007-06-07 05:57:25 UTC (rev 
5730)
@@ -23,4 +23,4 @@
 """
 
 from DataType import *
-from SignalBlockTree import SB_TREE,get_signal_block
+from SignalBlockTree import SB_TREE,get_signal_block,TagNotFoundException

Modified: grc/trunk/src/Variables.py
===================================================================
--- grc/trunk/src/Variables.py  2007-06-07 05:22:11 UTC (rev 5729)
+++ grc/trunk/src/Variables.py  2007-06-07 05:57:25 UTC (rev 5730)
@@ -43,10 +43,6 @@
        Partially completed ranges will be intelligently filled in.
        Partially blanked ranges will be cleared.       
        All parameters must be strings! '''
-       #       if step is None, make it a blank string, for backwards 
compadibility    #
-       if step == None: step = ''
-       #       if min, max, and step are all None, make them blank strings #
-       if step == max == min == None: step = min = max = ''
        #       make sure that all parameters are strings #
        for var in (key, value, min, max, step):
                if type(var) != type(str()): raise TypeError('"%s" var is not 
of type string'%var)
@@ -105,6 +101,11 @@
        ''' Get the tuple for this key, otherwise None. '''
        if has_key(key): return VARS_DICT[key]
        else: return None
+       
+def is_ranged(key):
+       ''' Does this variable have a range:
+               min, max, and step are not blank.       '''
+       return get_values(key)[1] != ''
                
 def get_value(key):
        ''' Get the value for this key, otherwise None. '''
@@ -116,6 +117,43 @@
                with the string representation of the variable. '''
        for key in get_keys(): string = string.replace(VAR_MARKER + key, 
get_value(key))
        return string           
+
+##########################################################################
+##     Import the Variables
+##########################################################################     
+def from_nested_data(nested_data):
+       ''' Clear all of the registered variables,
+               and load all variables from nested data.        
+               Return a list of keys, in the order they were added.    '''
+       import ParseXML,Messages
+       find_data = ParseXML.find_data
+       clear_vars()
+       keys = list()
+       for var in nested_data:
+               var = find_data([var], 'var')                           
+               key = find_data(var, 'key')
+               value = find_data(var, 'value')
+               # min, max, and step are optional       #
+               min = find_data(var, 'min')
+               max = find_data(var, 'max')
+               step = find_data(var, 'step')           
+               #       if min, max, and step are all None, make them blank 
strings #
+               if step == max == min == None: step = min = max = ''    
+               #       if step is None, make it a blank string, for backwards 
compadibility    #
+               if step == None: step = ''              
+               try: 
+                       register(key, value, min, max, step)
+                       keys.append(key)
+               except Exception, e:  
+                       Messages.send_error_load('Could not register variable 
with: "%s, %s, %s, %s, %s":\n\t%s'%(key, value, min, max, step, e))
+                       try: 
+                               register(key, value)    #error!, register only 
the value
+                               keys.append(key)
+                       except Exception, e: 
+                               Messages.send_error_load('Could not register 
variable with: "%s, %s":\n\t%s'%(key, value, e))
+                               Messages.send_error_load('Variable "%s" not 
registered!'%key)
+                               pass    #dont register!         
+       return keys
        
 if __name__ == '__main__':
        print is_key_name_valid('sdfa13_fsf_dsd')               





reply via email to

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