[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] r5878 - in grc/trunk: . examples examples/audio exampl
From: |
jblum |
Subject: |
[Commit-gnuradio] r5878 - in grc/trunk: . examples examples/audio examples/xmlrpc notes src src/Elements src/Graphics src/SignalBlockDefs |
Date: |
Fri, 29 Jun 2007 11:41:27 -0600 (MDT) |
Author: jblum
Date: 2007-06-29 11:41:26 -0600 (Fri, 29 Jun 2007)
New Revision: 5878
Added:
grc/trunk/examples/audio/b_flat_scale.grc.xml
grc/trunk/examples/audio/phone_tones.grc.xml
grc/trunk/examples/channel_distortion.grc.xml
grc/trunk/examples/noisy_sinusoid.grc.xml
grc/trunk/examples/null_to_null.grc.xml
grc/trunk/examples/packet_mod_demod.grc.xml
grc/trunk/examples/selector.grc.xml
grc/trunk/examples/valve.grc.xml
grc/trunk/examples/xmlrpc/
grc/trunk/examples/xmlrpc/client.py
grc/trunk/examples/xmlrpc/readme.txt
grc/trunk/examples/xmlrpc/server.sh
grc/trunk/examples/xmlrpc/tone.grc.xml
grc/trunk/notes/programming_style.txt
grc/trunk/readme.txt
grc/trunk/src/DataTypes.py
grc/trunk/src/ExecFlowGraphXMLRPC.py
grc/trunk/src/Graphics/FileDialogs.py
grc/trunk/src/SignalBlockDefs/Custom.py
grc/trunk/src/SignalBlockDefs/Packet.py
Removed:
grc/trunk/README.txt
grc/trunk/examples/audio/B flat.grc.xml
grc/trunk/examples/audio/phone tones.grc.xml
grc/trunk/examples/channel noise.grc.xml
grc/trunk/examples/noisy sinusoid.grc.xml
grc/trunk/examples/null to null.grc.xml
grc/trunk/examples/qam.grc.xml
grc/trunk/examples/xmlrpc/client.py
grc/trunk/examples/xmlrpc/readme.txt
grc/trunk/examples/xmlrpc/server.sh
grc/trunk/examples/xmlrpc/tone.grc.xml
grc/trunk/src/DataType.py
grc/trunk/src/Graphics/FlowGraphFileDialog.py
Modified:
grc/trunk/examples/variable_sink.grc.xml
grc/trunk/notes/notes.txt
grc/trunk/src/
grc/trunk/src/ActionHandler.py
grc/trunk/src/Actions.py
grc/trunk/src/Colors.py
grc/trunk/src/Constants.py
grc/trunk/src/Editor.py
grc/trunk/src/Elements/
grc/trunk/src/Elements/Connection.py
grc/trunk/src/Elements/Element.py
grc/trunk/src/Elements/GraphicalConnection.py
grc/trunk/src/Elements/GraphicalElement.py
grc/trunk/src/Elements/GraphicalParam.py
grc/trunk/src/Elements/GraphicalSignalBlock.py
grc/trunk/src/Elements/GraphicalSocket.py
grc/trunk/src/Elements/Param.py
grc/trunk/src/Elements/SignalBlock.py
grc/trunk/src/Elements/Socket.py
grc/trunk/src/Elements/Utils.py
grc/trunk/src/Elements/__init__.py
grc/trunk/src/ExecFlowGraph.py
grc/trunk/src/ExecFlowGraphGUI.py
grc/trunk/src/Graphics/
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/SignalBlockParamsDialog.py
grc/trunk/src/Graphics/SignalBlockSelectionWindow.py
grc/trunk/src/Graphics/USRPDiagnostics.py
grc/trunk/src/Graphics/VariableModificationWindow.py
grc/trunk/src/Graphics/__init__.py
grc/trunk/src/MathExprParser.py
grc/trunk/src/Messages.py
grc/trunk/src/ParseXML.py
grc/trunk/src/Preferences.py
grc/trunk/src/SignalBlockDefs/
grc/trunk/src/SignalBlockDefs/Coders.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/Operators.py
grc/trunk/src/SignalBlockDefs/SignalBlockConstants.py
grc/trunk/src/SignalBlockDefs/SignalBlockTree.py
grc/trunk/src/SignalBlockDefs/Sinks.py
grc/trunk/src/SignalBlockDefs/Sources.py
grc/trunk/src/SignalBlockDefs/Trellis.py
grc/trunk/src/SignalBlockDefs/USRP.py
grc/trunk/src/SignalBlockDefs/__init__.py
grc/trunk/src/StateCache.py
grc/trunk/src/Variables.py
Log:
merged branch/jblum_work into trunk
Deleted: grc/trunk/README.txt
Deleted: grc/trunk/examples/audio/B flat.grc.xml
Copied: grc/trunk/examples/audio/b_flat_scale.grc.xml (from rev 5877,
grc/branches/jblum_work/examples/audio/b_flat_scale.grc.xml)
===================================================================
--- grc/trunk/examples/audio/b_flat_scale.grc.xml
(rev 0)
+++ grc/trunk/examples/audio/b_flat_scale.grc.xml 2007-06-29 17:41:26 UTC
(rev 5878)
@@ -0,0 +1,116 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<flow_graph>
+ <timestamp>1179256591.06</timestamp>
+ <hostname>bowlcut</hostname>
+ <version>0.70 alpha</version>
+ <valid>True</valid>
+ <window_width>800</window_width>
+ <window_height>600</window_height>
+ <vars>
+ <var>
+ <key>samp_rate</key>
+ <value>32000</value>
+ <min/>
+ <max/>
+ <step/>
+ </var>
+ <var>
+ <key>A</key>
+ <value>440</value>
+ <min/>
+ <max/>
+ <step/>
+ </var>
+ <var>
+ <key>n</key>
+ <value>0</value>
+ <min>-4</min>
+ <max>8</max>
+ <step>1</step>
+ </var>
+ <var>
+ <key>volume</key>
+ <value>.1</value>
+ <min>0</min>
+ <max>.5</max>
+ <step>0.005</step>
+ </var>
+ </vars>
+ <signal_blocks>
+ <signal_block>
+ <tag>About</tag>
+ <id>About0</id>
+ <x_coordinate>91</x_coordinate>
+ <y_coordinate>41</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>B flat</param>
+ <param>Josh Blum</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Note</tag>
+ <id>Note0</id>
+ <x_coordinate>30</x_coordinate>
+ <y_coordinate>136</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>Generate pure musical tones.</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Scope Sink</tag>
+ <id>Scope Sink0</id>
+ <x_coordinate>31</x_coordinate>
+ <y_coordinate>251</y_coordinate>
+ <rotation>180</rotation>
+ <params>
+ <param>1</param>
+ <param>Scope</param>
+ <param>$samp_rate</param>
+ <param>1</param>
+ <param>.1</param>
+ <param>.001</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Audio Sink</tag>
+ <id>Audio Sink0</id>
+ <x_coordinate>27</x_coordinate>
+ <y_coordinate>429</y_coordinate>
+ <rotation>180</rotation>
+ <params>
+ <param>3</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Signal Source</tag>
+ <id>Signal Source0</id>
+ <x_coordinate>411</x_coordinate>
+ <y_coordinate>344</y_coordinate>
+ <rotation>180</rotation>
+ <params>
+ <param>1</param>
+ <param>$samp_rate</param>
+ <param>1</param>
+ <param>$A*2^($n/12)</param>
+ <param>$volume</param>
+ <param>0</param>
+ </params>
+ </signal_block>
+ </signal_blocks>
+ <connections>
+ <connection>
+ <input_signal_block_id>Audio Sink0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Signal Source0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>Scope Sink0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Signal Source0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ </connections>
+</flow_graph>
Deleted: grc/trunk/examples/audio/phone tones.grc.xml
Copied: grc/trunk/examples/audio/phone_tones.grc.xml (from rev 5877,
grc/branches/jblum_work/examples/audio/phone_tones.grc.xml)
===================================================================
--- grc/trunk/examples/audio/phone_tones.grc.xml
(rev 0)
+++ grc/trunk/examples/audio/phone_tones.grc.xml 2007-06-29 17:41:26 UTC
(rev 5878)
@@ -0,0 +1,206 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<flow_graph>
+ <timestamp>1179256705.05</timestamp>
+ <hostname>bowlcut</hostname>
+ <version>0.70 alpha</version>
+ <valid>True</valid>
+ <window_width>1200</window_width>
+ <window_height>800</window_height>
+ <vars>
+ <var>
+ <key>samp_rate</key>
+ <value>32e3</value>
+ <min/>
+ <max/>
+ <step/>
+ </var>
+ <var>
+ <key>volume</key>
+ <value>.1</value>
+ <min>0</min>
+ <max>.5</max>
+ <step>0.005</step>
+ </var>
+ <var>
+ <key>noise</key>
+ <value>.01</value>
+ <min>0</min>
+ <max>.1</max>
+ <step>0.001</step>
+ </var>
+ </vars>
+ <signal_blocks>
+ <signal_block>
+ <tag>Signal Source</tag>
+ <id>Signal Source1</id>
+ <x_coordinate>192</x_coordinate>
+ <y_coordinate>377</y_coordinate>
+ <rotation>90</rotation>
+ <params>
+ <param>1</param>
+ <param>$samp_rate</param>
+ <param>1</param>
+ <param>440</param>
+ <param>1</param>
+ <param>0</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Noise Source</tag>
+ <id>Noise Source0</id>
+ <x_coordinate>335</x_coordinate>
+ <y_coordinate>364</y_coordinate>
+ <rotation>90</rotation>
+ <params>
+ <param>1</param>
+ <param>1</param>
+ <param>$noise</param>
+ <param>71</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>FFT Sink</tag>
+ <id>FFT Sink0</id>
+ <x_coordinate>856</x_coordinate>
+ <y_coordinate>366</y_coordinate>
+ <rotation>270</rotation>
+ <params>
+ <param>1</param>
+ <param>FFT</param>
+ <param>$samp_rate</param>
+ <param>20</param>
+ <param>20</param>
+ <param>512</param>
+ <param>15</param>
+ <param>0</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Signal Source</tag>
+ <id>Signal Source0</id>
+ <x_coordinate>34</x_coordinate>
+ <y_coordinate>366</y_coordinate>
+ <rotation>90</rotation>
+ <params>
+ <param>1</param>
+ <param>$samp_rate</param>
+ <param>1</param>
+ <param>350</param>
+ <param>1</param>
+ <param>0</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Scope Sink</tag>
+ <id>Scope Sink0</id>
+ <x_coordinate>562</x_coordinate>
+ <y_coordinate>387</y_coordinate>
+ <rotation>270</rotation>
+ <params>
+ <param>1</param>
+ <param>Scope</param>
+ <param>$samp_rate</param>
+ <param>1</param>
+ <param>0</param>
+ <param>0.001</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Audio Sink</tag>
+ <id>Audio Sink0</id>
+ <x_coordinate>742</x_coordinate>
+ <y_coordinate>409</y_coordinate>
+ <rotation>270</rotation>
+ <params>
+ <param>3</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Multiply Constant</tag>
+ <id>Multiply Constant0</id>
+ <x_coordinate>594</x_coordinate>
+ <y_coordinate>221</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>1</param>
+ <param>$volume</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Add</tag>
+ <id>Add0</id>
+ <x_coordinate>420</x_coordinate>
+ <y_coordinate>133</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>1</param>
+ <param>3</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Note</tag>
+ <id>Note0</id>
+ <x_coordinate>362</x_coordinate>
+ <y_coordinate>58</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>350 hz + 440 hz + AWGN</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>About</tag>
+ <id>About0</id>
+ <x_coordinate>71</x_coordinate>
+ <y_coordinate>48</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>The Famous Phone Tones</param>
+ <param>Josh Blum</param>
+ </params>
+ </signal_block>
+ </signal_blocks>
+ <connections>
+ <connection>
+ <input_signal_block_id>Add0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Signal Source0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>Add0</input_signal_block_id>
+ <input_socket_index>1</input_socket_index>
+ <output_signal_block_id>Signal Source1</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>Multiply Constant0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Add0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>Audio Sink0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Multiply Constant0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>Add0</input_signal_block_id>
+ <input_socket_index>2</input_socket_index>
+ <output_signal_block_id>Noise Source0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>FFT Sink0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Multiply Constant0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>Scope Sink0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Multiply Constant0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ </connections>
+</flow_graph>
Deleted: grc/trunk/examples/channel noise.grc.xml
Copied: grc/trunk/examples/channel_distortion.grc.xml (from rev 5877,
grc/branches/jblum_work/examples/channel_distortion.grc.xml)
===================================================================
--- grc/trunk/examples/channel_distortion.grc.xml
(rev 0)
+++ grc/trunk/examples/channel_distortion.grc.xml 2007-06-29 17:41:26 UTC
(rev 5878)
@@ -0,0 +1,120 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<flow_graph>
+ <timestamp>1182222914.4</timestamp>
+ <hostname>tiggle</hostname>
+ <version>0.70 alpha</version>
+ <valid>True</valid>
+ <window_width>1200</window_width>
+ <window_height>800</window_height>
+ <vars>
+ <var>
+ <key>samp_rate</key>
+ <value>32e3</value>
+ <min/>
+ <max/>
+ <step/>
+ </var>
+ <var>
+ <key>freq</key>
+ <value>1000</value>
+ <min>0</min>
+ <max>5000</max>
+ <step>50.0</step>
+ </var>
+ </vars>
+ <signal_blocks>
+ <signal_block>
+ <tag>FFT Sink</tag>
+ <id>FFT Sink0</id>
+ <x_coordinate>571</x_coordinate>
+ <y_coordinate>76</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>0</param>
+ <param>FFT - Distorted</param>
+ <param>$samp_rate</param>
+ <param>20</param>
+ <param>20</param>
+ <param>512</param>
+ <param>15</param>
+ <param>0</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>FFT Sink</tag>
+ <id>FFT Sink1</id>
+ <x_coordinate>573</x_coordinate>
+ <y_coordinate>266</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>0</param>
+ <param>FFT - Input</param>
+ <param>$samp_rate</param>
+ <param>20</param>
+ <param>20</param>
+ <param>512</param>
+ <param>15</param>
+ <param>0</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Channel Model</tag>
+ <id>Channel Model0</id>
+ <x_coordinate>317</x_coordinate>
+ <y_coordinate>101</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>.2</param>
+ <param>0.0</param>
+ <param>1.0</param>
+ <param>1.0,0.0</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Signal Source</tag>
+ <id>Signal Source0</id>
+ <x_coordinate>66</x_coordinate>
+ <y_coordinate>193</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>0</param>
+ <param>$samp_rate</param>
+ <param>1</param>
+ <param>$freq</param>
+ <param>1</param>
+ <param>0</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>About</tag>
+ <id>About0</id>
+ <x_coordinate>59</x_coordinate>
+ <y_coordinate>75</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>Channel Distortion</param>
+ <param>Josh Blum</param>
+ </params>
+ </signal_block>
+ </signal_blocks>
+ <connections>
+ <connection>
+ <input_signal_block_id>Channel Model0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Signal Source0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>FFT Sink1</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Signal Source0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>FFT Sink0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Channel Model0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ </connections>
+</flow_graph>
Deleted: grc/trunk/examples/noisy sinusoid.grc.xml
Copied: grc/trunk/examples/noisy_sinusoid.grc.xml (from rev 5877,
grc/branches/jblum_work/examples/noisy_sinusoid.grc.xml)
===================================================================
--- grc/trunk/examples/noisy_sinusoid.grc.xml (rev 0)
+++ grc/trunk/examples/noisy_sinusoid.grc.xml 2007-06-29 17:41:26 UTC (rev
5878)
@@ -0,0 +1,168 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<flow_graph>
+ <timestamp>1179256658.68</timestamp>
+ <hostname>bowlcut</hostname>
+ <version>0.70 alpha</version>
+ <valid>True</valid>
+ <window_width>1000</window_width>
+ <window_height>600</window_height>
+ <vars>
+ <var>
+ <key>samp_rate</key>
+ <value>32000</value>
+ <min/>
+ <max/>
+ <step/>
+ </var>
+ <var>
+ <key>source_freq</key>
+ <value>350</value>
+ <min>300</min>
+ <max>1e3</max>
+ <step>7.0</step>
+ </var>
+ <var>
+ <key>noise_amp</key>
+ <value>.005</value>
+ <min>.005</min>
+ <max>.05</max>
+ <step>0.001</step>
+ </var>
+ </vars>
+ <signal_blocks>
+ <signal_block>
+ <tag>Note</tag>
+ <id>Note0</id>
+ <x_coordinate>514</x_coordinate>
+ <y_coordinate>24</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>An example of additive noise.</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>About</tag>
+ <id>About0</id>
+ <x_coordinate>333</x_coordinate>
+ <y_coordinate>26</y_coordinate>
+ <rotation>180</rotation>
+ <params>
+ <param>Noisy Sinusoid</param>
+ <param>Josh Blum</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Noise Source</tag>
+ <id>Noise Source0</id>
+ <x_coordinate>615</x_coordinate>
+ <y_coordinate>357</y_coordinate>
+ <rotation>90</rotation>
+ <params>
+ <param>1</param>
+ <param>1</param>
+ <param>$noise_amp</param>
+ <param>79</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Audio Sink</tag>
+ <id>Audio Sink0</id>
+ <x_coordinate>280</x_coordinate>
+ <y_coordinate>377</y_coordinate>
+ <rotation>270</rotation>
+ <params>
+ <param>3</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Signal Source</tag>
+ <id>Signal Source0</id>
+ <x_coordinate>625</x_coordinate>
+ <y_coordinate>133</y_coordinate>
+ <rotation>180</rotation>
+ <params>
+ <param>1</param>
+ <param>$samp_rate</param>
+ <param>1</param>
+ <param>$source_freq</param>
+ <param>.1</param>
+ <param>0</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>FFT Sink</tag>
+ <id>FFT Sink0</id>
+ <x_coordinate>71</x_coordinate>
+ <y_coordinate>70</y_coordinate>
+ <rotation>180</rotation>
+ <params>
+ <param>1</param>
+ <param>FFT</param>
+ <param>$samp_rate</param>
+ <param>20</param>
+ <param>20</param>
+ <param>512</param>
+ <param>15</param>
+ <param>0</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Scope Sink</tag>
+ <id>Scope Sink0</id>
+ <x_coordinate>53</x_coordinate>
+ <y_coordinate>238</y_coordinate>
+ <rotation>180</rotation>
+ <params>
+ <param>1</param>
+ <param>Scope</param>
+ <param>$samp_rate</param>
+ <param>1</param>
+ <param>0</param>
+ <param>0.001</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Add</tag>
+ <id>Add0</id>
+ <x_coordinate>427</x_coordinate>
+ <y_coordinate>217</y_coordinate>
+ <rotation>180</rotation>
+ <params>
+ <param>1</param>
+ <param>2</param>
+ </params>
+ </signal_block>
+ </signal_blocks>
+ <connections>
+ <connection>
+ <input_signal_block_id>Add0</input_signal_block_id>
+ <input_socket_index>1</input_socket_index>
+ <output_signal_block_id>Signal Source0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>Add0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Noise Source0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>Audio Sink0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Add0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>FFT Sink0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Add0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>Scope Sink0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Add0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ </connections>
+</flow_graph>
Deleted: grc/trunk/examples/null to null.grc.xml
Copied: grc/trunk/examples/null_to_null.grc.xml (from rev 5877,
grc/branches/jblum_work/examples/null_to_null.grc.xml)
===================================================================
--- grc/trunk/examples/null_to_null.grc.xml (rev 0)
+++ grc/trunk/examples/null_to_null.grc.xml 2007-06-29 17:41:26 UTC (rev
5878)
@@ -0,0 +1,52 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<flow_graph>
+ <timestamp>1179256695.11</timestamp>
+ <hostname>bowlcut</hostname>
+ <version>0.70 alpha</version>
+ <valid>True</valid>
+ <window_width>1200</window_width>
+ <window_height>800</window_height>
+ <vars/>
+ <signal_blocks>
+ <signal_block>
+ <tag>Null Source</tag>
+ <id>Null Source0</id>
+ <x_coordinate>168</x_coordinate>
+ <y_coordinate>250</y_coordinate>
+ <rotation>270</rotation>
+ <params>
+ <param>1</param>
+ <param>1</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Null Sink</tag>
+ <id>Null Sink0</id>
+ <x_coordinate>307</x_coordinate>
+ <y_coordinate>270</y_coordinate>
+ <rotation>270</rotation>
+ <params>
+ <param>1</param>
+ <param>1</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Note</tag>
+ <id>Note0</id>
+ <x_coordinate>172</x_coordinate>
+ <y_coordinate>121</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>Use 100% CPU</param>
+ </params>
+ </signal_block>
+ </signal_blocks>
+ <connections>
+ <connection>
+ <input_signal_block_id>Null Sink0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Null Source0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ </connections>
+</flow_graph>
Copied: grc/trunk/examples/packet_mod_demod.grc.xml (from rev 5877,
grc/branches/jblum_work/examples/packet_mod_demod.grc.xml)
===================================================================
--- grc/trunk/examples/packet_mod_demod.grc.xml (rev 0)
+++ grc/trunk/examples/packet_mod_demod.grc.xml 2007-06-29 17:41:26 UTC (rev
5878)
@@ -0,0 +1,216 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<flow_graph>
+ <timestamp>1182980737.28</timestamp>
+ <hostname>tiggle</hostname>
+ <version>0.70 alpha</version>
+ <valid>True</valid>
+ <window_width>1600</window_width>
+ <window_height>1200</window_height>
+ <vars>
+ <var>
+ <key>samp_rate</key>
+ <value>100e3</value>
+ <min/>
+ <max/>
+ <step/>
+ </var>
+ <var>
+ <key>freq</key>
+ <value>2500</value>
+ <min>0</min>
+ <max>5000</max>
+ <step>50.0</step>
+ </var>
+ <var>
+ <key>amp</key>
+ <value>1</value>
+ <min>0</min>
+ <max>2</max>
+ <step>0.02</step>
+ </var>
+ <var>
+ <key>off</key>
+ <value>0</value>
+ <min>-1</min>
+ <max>1</max>
+ <step>0.02</step>
+ </var>
+ </vars>
+ <signal_blocks>
+ <signal_block>
+ <tag>Note</tag>
+ <id>Note0</id>
+ <x_coordinate>408</x_coordinate>
+ <y_coordinate>270</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>A demonstration of the packet framework.</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Packet Demodulator</tag>
+ <id>Packet Demodulator0</id>
+ <x_coordinate>535</x_coordinate>
+ <y_coordinate>427</y_coordinate>
+ <rotation>180</rotation>
+ <params>
+ <param>1</param>
+ <param/>
+ <param>-1</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Scope Sink</tag>
+ <id>Scope Sink0</id>
+ <x_coordinate>219</x_coordinate>
+ <y_coordinate>402</y_coordinate>
+ <rotation>180</rotation>
+ <params>
+ <param>1</param>
+ <param>Output</param>
+ <param>$samp_rate</param>
+ <param>1</param>
+ <param>0</param>
+ <param>0.001</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Signal Source</tag>
+ <id>Signal Source0</id>
+ <x_coordinate>26</x_coordinate>
+ <y_coordinate>354</y_coordinate>
+ <rotation>90</rotation>
+ <params>
+ <param>1</param>
+ <param>$samp_rate</param>
+ <param>1</param>
+ <param>$freq</param>
+ <param>$amp</param>
+ <param>$off</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Scope Sink</tag>
+ <id>Scope Sink1</id>
+ <x_coordinate>125</x_coordinate>
+ <y_coordinate>178</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>1</param>
+ <param>Input</param>
+ <param>$samp_rate</param>
+ <param>1</param>
+ <param>0</param>
+ <param>0.001</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Packet Modulator</tag>
+ <id>Packet Modulator0</id>
+ <x_coordinate>129</x_coordinate>
+ <y_coordinate>19</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>1</param>
+ <param>0</param>
+ <param>2</param>
+ <param>512</param>
+ <param/>
+ <param>0</param>
+ <param>1</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>GMSK Modulator</tag>
+ <id>GMSK Modulator0</id>
+ <x_coordinate>399</x_coordinate>
+ <y_coordinate>36</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>2</param>
+ <param>0.35</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>About</tag>
+ <id>About0</id>
+ <x_coordinate>480</x_coordinate>
+ <y_coordinate>176</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>Packet Mod/Demod</param>
+ <param>Josh Blum</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>GMSK Demodulator</tag>
+ <id>GMSK Demodulator0</id>
+ <x_coordinate>871</x_coordinate>
+ <y_coordinate>189</y_coordinate>
+ <rotation>270</rotation>
+ <params>
+ <param>2</param>
+ <param>0.05</param>
+ <param>0.5</param>
+ <param>0.005</param>
+ <param>0</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Throttle</tag>
+ <id>Throttle0</id>
+ <x_coordinate>703</x_coordinate>
+ <y_coordinate>36</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>0</param>
+ <param>$samp_rate*25</param>
+ <param>1</param>
+ </params>
+ </signal_block>
+ </signal_blocks>
+ <connections>
+ <connection>
+ <input_signal_block_id>Scope Sink1</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Signal Source0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>Scope Sink0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Packet Demodulator0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>Packet Modulator0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Signal Source0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>GMSK Modulator0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Packet Modulator0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>Packet Demodulator0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>GMSK Demodulator0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>Throttle0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>GMSK Modulator0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>GMSK Demodulator0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Throttle0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ </connections>
+</flow_graph>
Deleted: grc/trunk/examples/qam.grc.xml
Copied: grc/trunk/examples/selector.grc.xml (from rev 5877,
grc/branches/jblum_work/examples/selector.grc.xml)
===================================================================
--- grc/trunk/examples/selector.grc.xml (rev 0)
+++ grc/trunk/examples/selector.grc.xml 2007-06-29 17:41:26 UTC (rev 5878)
@@ -0,0 +1,193 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<flow_graph>
+ <timestamp>1183066964.1</timestamp>
+ <hostname>tiggle</hostname>
+ <version>0.70 alpha</version>
+ <valid>True</valid>
+ <window_width>1400</window_width>
+ <window_height>600</window_height>
+ <vars>
+ <var>
+ <key>samp_rate</key>
+ <value>100e3</value>
+ <min/>
+ <max/>
+ <step/>
+ </var>
+ <var>
+ <key>index</key>
+ <value>1</value>
+ <min>-1</min>
+ <max>1</max>
+ <step>1</step>
+ </var>
+ <var>
+ <key>packet_len</key>
+ <value>128</value>
+ <min/>
+ <max/>
+ <step/>
+ </var>
+ </vars>
+ <signal_blocks>
+ <signal_block>
+ <tag>PSK Modulator</tag>
+ <id>PSK Modulator0</id>
+ <x_coordinate>500</x_coordinate>
+ <y_coordinate>341</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>1</param>
+ <param>2</param>
+ <param>0.35</param>
+ <param>0</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>GMSK Modulator</tag>
+ <id>GMSK Modulator0</id>
+ <x_coordinate>544</x_coordinate>
+ <y_coordinate>58</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>2</param>
+ <param>0.35</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Note</tag>
+ <id>Note0</id>
+ <x_coordinate>485</x_coordinate>
+ <y_coordinate>259</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>0=gmsk, 1=dqpsk, -1=disconnected</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Selector</tag>
+ <id>Selector1</id>
+ <x_coordinate>924</x_coordinate>
+ <y_coordinate>330</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>0</param>
+ <param>$index</param>
+ <param>0</param>
+ <param>2</param>
+ <param>1</param>
+ <param>1</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Selector</tag>
+ <id>Selector0</id>
+ <x_coordinate>264</x_coordinate>
+ <y_coordinate>68</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>4</param>
+ <param>0</param>
+ <param>$index</param>
+ <param>1</param>
+ <param>2</param>
+ <param>1</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Random Source</tag>
+ <id>Random Source0</id>
+ <x_coordinate>170</x_coordinate>
+ <y_coordinate>196</y_coordinate>
+ <rotation>180</rotation>
+ <params>
+ <param>3</param>
+ <param>1000</param>
+ <param>0</param>
+ <param>1</param>
+ <param>422291</param>
+ <param>0</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Constellation Sink</tag>
+ <id>Constellation Sink0</id>
+ <x_coordinate>886</x_coordinate>
+ <y_coordinate>114</y_coordinate>
+ <rotation>180</rotation>
+ <params>
+ <param>Ouput Constellation</param>
+ <param>$samp_rate</param>
+ <param>1</param>
+ <param>0</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Throttle</tag>
+ <id>Throttle0</id>
+ <x_coordinate>5</x_coordinate>
+ <y_coordinate>150</y_coordinate>
+ <rotation>90</rotation>
+ <params>
+ <param>4</param>
+ <param>$samp_rate</param>
+ <param>1</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>About</tag>
+ <id>About0</id>
+ <x_coordinate>504</x_coordinate>
+ <y_coordinate>164</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>Selecting Between Modulators</param>
+ <param>Josh Blum</param>
+ </params>
+ </signal_block>
+ </signal_blocks>
+ <connections>
+ <connection>
+ <input_signal_block_id>Selector1</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>GMSK Modulator0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>Selector1</input_signal_block_id>
+ <input_socket_index>1</input_socket_index>
+ <output_signal_block_id>PSK Modulator0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>Constellation Sink0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Selector1</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>GMSK Modulator0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Selector0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>PSK Modulator0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Selector0</output_signal_block_id>
+ <output_socket_index>1</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>Throttle0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Random Source0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>Selector0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Throttle0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ </connections>
+</flow_graph>
Copied: grc/trunk/examples/valve.grc.xml (from rev 5877,
grc/branches/jblum_work/examples/valve.grc.xml)
===================================================================
--- grc/trunk/examples/valve.grc.xml (rev 0)
+++ grc/trunk/examples/valve.grc.xml 2007-06-29 17:41:26 UTC (rev 5878)
@@ -0,0 +1,146 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<flow_graph>
+ <timestamp>1182897525.03</timestamp>
+ <hostname>tiggle</hostname>
+ <version>0.70 alpha</version>
+ <valid>True</valid>
+ <window_width>800</window_width>
+ <window_height>600</window_height>
+ <vars>
+ <var>
+ <key>samp_rate</key>
+ <value>100e3</value>
+ <min/>
+ <max/>
+ <step/>
+ </var>
+ <var>
+ <key>freq</key>
+ <value>2500</value>
+ <min>0</min>
+ <max>5000</max>
+ <step>50.0</step>
+ </var>
+ <var>
+ <key>amp</key>
+ <value>1</value>
+ <min>0</min>
+ <max>2</max>
+ <step>0.02</step>
+ </var>
+ <var>
+ <key>off</key>
+ <value>0</value>
+ <min>-1</min>
+ <max>1</max>
+ <step>0.02</step>
+ </var>
+ <var>
+ <key>open</key>
+ <value>0</value>
+ <min>-1</min>
+ <max>0</max>
+ <step>1</step>
+ </var>
+ </vars>
+ <signal_blocks>
+ <signal_block>
+ <tag>About</tag>
+ <id>About0</id>
+ <x_coordinate>20</x_coordinate>
+ <y_coordinate>20</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>Valve Demonstration</param>
+ <param>Josh Blum</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Valve</tag>
+ <id>Valve0</id>
+ <x_coordinate>270</x_coordinate>
+ <y_coordinate>150</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>1</param>
+ <param>$open</param>
+ <param>1</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Note</tag>
+ <id>Note0</id>
+ <x_coordinate>255</x_coordinate>
+ <y_coordinate>42</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>The valve is open and the data flow is allowed when open is
0.</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Signal Source</tag>
+ <id>Signal Source0</id>
+ <x_coordinate>47</x_coordinate>
+ <y_coordinate>350</y_coordinate>
+ <rotation>90</rotation>
+ <params>
+ <param>1</param>
+ <param>$samp_rate</param>
+ <param>1</param>
+ <param>$freq</param>
+ <param>$amp</param>
+ <param>$off</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Scope Sink</tag>
+ <id>Scope Sink1</id>
+ <x_coordinate>241</x_coordinate>
+ <y_coordinate>248</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>1</param>
+ <param>Input</param>
+ <param>$samp_rate</param>
+ <param>1</param>
+ <param>0</param>
+ <param>0.001</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Scope Sink</tag>
+ <id>Scope Sink0</id>
+ <x_coordinate>276</x_coordinate>
+ <y_coordinate>405</y_coordinate>
+ <rotation>180</rotation>
+ <params>
+ <param>1</param>
+ <param>Output</param>
+ <param>$samp_rate</param>
+ <param>1</param>
+ <param>0</param>
+ <param>0.001</param>
+ </params>
+ </signal_block>
+ </signal_blocks>
+ <connections>
+ <connection>
+ <input_signal_block_id>Valve0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Signal Source0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>Scope Sink0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Valve0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ <connection>
+ <input_signal_block_id>Scope Sink1</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Signal Source0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ </connections>
+</flow_graph>
Modified: grc/trunk/examples/variable_sink.grc.xml
===================================================================
--- grc/trunk/examples/variable_sink.grc.xml 2007-06-29 17:29:46 UTC (rev
5877)
+++ grc/trunk/examples/variable_sink.grc.xml 2007-06-29 17:41:26 UTC (rev
5878)
@@ -1,11 +1,11 @@
<?xml version='1.0' encoding='UTF-8'?>
<flow_graph>
- <timestamp>1179795210.8</timestamp>
+ <timestamp>1182877130.19</timestamp>
<hostname>tiggle</hostname>
<version>0.70 alpha</version>
<valid>True</valid>
- <window_width>1600</window_width>
- <window_height>1200</window_height>
+ <window_width>800</window_width>
+ <window_height>500</window_height>
<vars>
<var>
<key>samp_rate_out</key>
Copied: grc/trunk/examples/xmlrpc (from rev 5877,
grc/branches/jblum_work/examples/xmlrpc)
Deleted: grc/trunk/examples/xmlrpc/client.py
Copied: grc/trunk/examples/xmlrpc/client.py (from rev 5877,
grc/branches/jblum_work/examples/xmlrpc/client.py)
===================================================================
--- grc/trunk/examples/xmlrpc/client.py (rev 0)
+++ grc/trunk/examples/xmlrpc/client.py 2007-06-29 17:41:26 UTC (rev 5878)
@@ -0,0 +1,33 @@
+#! /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
+"""
+
+from xmlrpclib import ServerProxy,Error
+import time
+
+server = ServerProxy("http://localhost:3030")
+print server
+
+try:
+ for i in list(range(-4, 8))+list(reversed(range(-4, 9))):
+ print server.set_var('freq', 440*2**(i/12.0))
+ time.sleep(1)
+ server.set_var('freq', 0)
+except Error, v:
+ print "ERROR", v
Deleted: grc/trunk/examples/xmlrpc/readme.txt
Copied: grc/trunk/examples/xmlrpc/readme.txt (from rev 5877,
grc/branches/jblum_work/examples/xmlrpc/readme.txt)
===================================================================
--- grc/trunk/examples/xmlrpc/readme.txt (rev 0)
+++ grc/trunk/examples/xmlrpc/readme.txt 2007-06-29 17:41:26 UTC (rev
5878)
@@ -0,0 +1,22 @@
+##############################################
+# XMLRPC
+##############################################
+
+XMLRPC allows a program to make remote function call over tcp.
+ExecFlowGraphXMLRPC.py executes a flow graph with an XMLRPC server.
+Any programing language can control the flow graph by making remote function
calls.
+The functions calls can read and write to the flow graph's variables.
+The functions are documented at the top of ExecFlowGraphXMLRPC.py.
+
+##############################################
+# Executing the example
+##############################################
+
+This example requires audio support in gnuradio!
+
+Start the server by executing server.sh in this directory.
+The server.sh script will execute ExecFlowGraphXMLRPC.py on tone.grc.xml
+
+Start the client by executing client.py.
+The client will change the frequency of the tone once per second.
+The client changes the tone by making XMLRPC calls that set the variable
'freq'.
Deleted: grc/trunk/examples/xmlrpc/server.sh
Copied: grc/trunk/examples/xmlrpc/server.sh (from rev 5877,
grc/branches/jblum_work/examples/xmlrpc/server.sh)
===================================================================
--- grc/trunk/examples/xmlrpc/server.sh (rev 0)
+++ grc/trunk/examples/xmlrpc/server.sh 2007-06-29 17:41:26 UTC (rev 5878)
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+ADDR=localhost
+PORT=3030
+FLOWGRAPH=./tone.grc.xml
+
+python ../../src/ExecFlowGraphXMLRPC.py $FLOWGRAPH -a $ADDR -P $PORT
Deleted: grc/trunk/examples/xmlrpc/tone.grc.xml
Copied: grc/trunk/examples/xmlrpc/tone.grc.xml (from rev 5877,
grc/branches/jblum_work/examples/xmlrpc/tone.grc.xml)
===================================================================
--- grc/trunk/examples/xmlrpc/tone.grc.xml (rev 0)
+++ grc/trunk/examples/xmlrpc/tone.grc.xml 2007-06-29 17:41:26 UTC (rev
5878)
@@ -0,0 +1,60 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<flow_graph>
+ <timestamp>1181338235.34</timestamp>
+ <hostname>tiggle</hostname>
+ <version>0.70 alpha</version>
+ <valid>True</valid>
+ <window_width>1600</window_width>
+ <window_height>1200</window_height>
+ <vars>
+ <var>
+ <key>samp_rate</key>
+ <value>100e3</value>
+ <min/>
+ <max/>
+ <step/>
+ </var>
+ <var>
+ <key>freq</key>
+ <value>0</value>
+ <min>0</min>
+ <max>5000</max>
+ <step>50.0</step>
+ </var>
+ </vars>
+ <signal_blocks>
+ <signal_block>
+ <tag>Audio Sink</tag>
+ <id>Audio Sink0</id>
+ <x_coordinate>529</x_coordinate>
+ <y_coordinate>67</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>3</param>
+ </params>
+ </signal_block>
+ <signal_block>
+ <tag>Signal Source</tag>
+ <id>Signal Source0</id>
+ <x_coordinate>282</x_coordinate>
+ <y_coordinate>227</y_coordinate>
+ <rotation>0</rotation>
+ <params>
+ <param>1</param>
+ <param>$samp_rate</param>
+ <param>1</param>
+ <param>$freq</param>
+ <param>.5</param>
+ <param>0</param>
+ </params>
+ </signal_block>
+ </signal_blocks>
+ <connections>
+ <connection>
+ <input_signal_block_id>Audio Sink0</input_signal_block_id>
+ <input_socket_index>0</input_socket_index>
+ <output_signal_block_id>Signal Source0</output_signal_block_id>
+ <output_socket_index>0</output_socket_index>
+ </connection>
+ </connections>
+</flow_graph>
Modified: grc/trunk/notes/notes.txt
===================================================================
--- grc/trunk/notes/notes.txt 2007-06-29 17:29:46 UTC (rev 5877)
+++ grc/trunk/notes/notes.txt 2007-06-29 17:41:26 UTC (rev 5878)
@@ -1,26 +1,23 @@
############ Blocks to Add: ####################
--blks.pkt mod/demod? (needs an instance of a mod/demod for a param)
+-ofdm
+-usrp misc settings
-usrp dual and quad souce
--blks blocks, add filesave for message reports
+-blks blocks, add filesave for logging
-combine add/mult with add/mult vector
--selector blocks
+-tun/tap block (with input and output)
############ 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: ####################
+-startup tips
+-math expr from file
-save settings after close (working directory)
-create sub-flow graphs to be used in larger flow graphs
--stdin/out communication protocal (non graphical)
-include dtd in saved flow graphs
-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: ####################
@@ -44,5 +41,9 @@
-press enter to close params
############ Get GTK Stock IDs: ####################
- gtk.stock_list_ids()
+gtk.stock_list_ids()
+
+############ connect packet mod to demod: ####################
+gr.packed_to_unpacked_bb(self.bits_per_symbol(), gr.GR_MSB_FIRST)
+gr.unpack_k_bits_bb(self.bits_per_symbol())
\ No newline at end of file
Copied: grc/trunk/notes/programming_style.txt (from rev 5877,
grc/branches/jblum_work/notes/programming_style.txt)
===================================================================
--- grc/trunk/notes/programming_style.txt (rev 0)
+++ grc/trunk/notes/programming_style.txt 2007-06-29 17:41:26 UTC (rev
5878)
@@ -0,0 +1,27 @@
+Programming Style
+
+1) Indentation:
+ Python dependends on correct indentation levels.
+ A tab character equals a single indentation level.
+ Most editors can display a tab as a user-defined width or number of
spaces.
+ The expand command can convert a file with tab indentations to a file
with space indentation.
+
+2) Naming Conventions:
+ CamelCaseNames for files and classes.
+ UPPER_CASE_NAMES for constants.
+ lower_case_names for public methods and all variables.
+ _underscored_lower_case_names for private methods.
+
+3) Documentation:
+ Source code follows the doxygen/javadoc conventions (and will be parsed
by doxygen).
+ Files begin with a ##comment block, a package name, brief description,
and author.
+ Constants follow a ##comment line.
+ All methods and classes require docstrings.
+ Docstrings with javadoc style entries need a leading "!".
+
+4) Blank Lines:
+ Separate all classes and methods with a blank line.
+ Group related constants and separate unrelated constants with a blank
line.
+ Leave 2 blank lines at the end of every file.
+
+
\ No newline at end of file
Copied: grc/trunk/readme.txt (from rev 5877, grc/branches/jblum_work/readme.txt)
===================================================================
--- grc/trunk/readme.txt (rev 0)
+++ grc/trunk/readme.txt 2007-06-29 17:41:26 UTC (rev 5878)
@@ -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
Property changes on: grc/trunk/src
___________________________________________________________________
Name: svn:ignore
- *.pyc
Modified: grc/trunk/src/ActionHandler.py
===================================================================
--- grc/trunk/src/ActionHandler.py 2007-06-29 17:29:46 UTC (rev 5877)
+++ grc/trunk/src/ActionHandler.py 2007-06-29 17:41:26 UTC (rev 5878)
@@ -16,12 +16,10 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- ActionHandler.py
- Josh Blum
- ActionHandler puts the entire application together by setting up all
the windows
- including the flow graph and ActionHandler handles most of the
user inputs.
-"""
address@hidden ActionHandler
+#ActionHandler builds the interface and handles most of the user inputs.
address@hidden Josh Blum
+
import os, sys
from Constants import *
from Actions import *
@@ -36,13 +34,20 @@
import Messages
class ActionHandler:
- """ The action handler will create all the major window components
and handle state changes.
- The action handler also contains methods to handle the action buttons
and state changes. """
+ """
+ The action handler will setup all the major window components,
+ and handle button presses and flow graph operations from the GUI.
+ """
def __init__(self, input_arg_file_path=''):
- """ Parse the config files for signals blocks and gtk actions.
Connect the actions to the handler method.
- Create a new Flow Graph and main_window as well as a few misc
dialog boxes. Enter the gtk main loop. """
+ """!
+ ActionHandler constructor.
+ Parse the config files for signals blocks and gtk actions.
Connect the actions to the handler method.
+ Create a new main window, intialize preferences and the message
handler.
+ Finally, enter the gtk main loop and block
+ @param input_arg_file_path a flow graph file passed from
command line
+ """
if PY_GTK_ICON:
gtk.window_set_default_icon_from_file(PY_GTK_ICON)
- for action in ACTIONS_LIST: action.connect('activate',
self.handle_actions)
+ for action in ACTIONS_LIST: action.connect('activate',
self._handle_actions)
self.pid_file = None
### create the main window and setup the Messages ###
self.main_window = Graphics.MainWindow(self.handle_states)
@@ -50,13 +55,12 @@
Messages.register_messenger(sys.stdout.write)
Messages.send_init()
self.flow_graph = self.main_window.flow_graph
- self.main_window.connect('delete_event', self.quit)
- self.main_window.connect('key_press_event',
self.handle_key_press)
- Preferences.load(self.main_window)
- self.main_window.show()#show after resize in preferences
+ self.main_window.connect('delete_event', self._quit)
+ self.main_window.connect('key_press_event',
self._handle_key_press)
# determine the initial flow graph file, preference to
command line input #
if input_arg_file_path: self.flow_graph_file_path =
os.path.abspath(input_arg_file_path)
else: self.flow_graph_file_path =
Preferences.get_default_flow_graph()
+ self.saved = True
self.handle_states(APPLICATION_INITIALIZE)
# enter the mainloop
gtk.gdk.threads_init()
@@ -64,15 +68,19 @@
gtk.main()
gtk.gdk.threads_leave()
- def handle_key_press(self, widget, event):
- """ Handle key press events and translate key combos into
actions.
- Key combinations that do not include special keys, such
as ctrl or Fcn*,
- require that the flow graph has mouse focus."""
+ def _handle_key_press(self, widget, event):
+ """
+ Handle key presses from the keyboard.
+ Translate key combos into actions.
+ Key combinations that do not include special keys, such as ctrl
or Fcn*,
+ Also, require that the flow graph has mouse focus when choosing
to handle keys.
+ @return true if the flow graph is in active use
+ """
keyname = gtk.gdk.keyval_name(event.keyval)
#print 'Key "%s" (%d) was pressed' % (keyname, event.keyval)
- if event.state & gtk.gdk.CONTROL_MASK: print "Control was being
held down"
- if event.state & gtk.gdk.MOD1_MASK: print "Alt was being held
down"
- if event.state & gtk.gdk.SHIFT_MASK: print "Shift was being
held down"
+ #if event.state & gtk.gdk.CONTROL_MASK: print "Control was
being held down"
+ #if event.state & gtk.gdk.MOD1_MASK: print "Alt was being held
down"
+ #if event.state & gtk.gdk.SHIFT_MASK: print "Shift was being
held down"
#################### save/open/new/undo/redo
###############################
if event.state & gtk.gdk.CONTROL_MASK and keyname == 's':
self.handle_states(FLOW_GRAPH_SAVE)
@@ -112,25 +120,34 @@
#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()
- def quit(self, window, event):
- """ Handle the delete event from the main window, like
pressing X to close, alt+f4, or right click+close.
- This method in turns calls the state handler with a 'quit'
string so all quitting can be handled in one place. """
+ def _quit(self, window, event):
+ """!
+ Handle the delete event from the main window.
+ Generated by pressing X to close, alt+f4, or right click+close.
+ This method in turns calls the state handler to quit.
+ @return true
+ """
self.handle_states(APPLICATION_QUIT)
return True
- def handle_actions(self, event):
- """ Handle all of the activate signals from the gtk actions.
The action signals derive from clicking on a
- toolbar or menu bar button. The name of the action is
passed through the event and a series of
- if/elif statements handle the action appropriately.
"""
- name = event.get_name()
- self.handle_states(name)
+ def _handle_actions(self, event):
+ """
+ Handle all of the activate signals from the gtk actions.
+ The action signals derive from clicking on a toolbar or menu
bar button.
+ Forward the action to the state handler.
+ """
+ self.handle_states(event.get_name())
def handle_states(self, state):
- """ Handle all of the state changes that arise from the action
handler or other Graphics and
- inputs in the application. The state passed to the
handle_states method is a string descriping
- the change. A series of if/elif statements handle the
state by greying out action buttons, causing
- changes in the flow graph, saving/opening files...
The handle_states method is passed to the
- contructors of many of the classes used in this
application enabling them to report any state change. """
+ """!
+ Handle the state changes in the GUI.
+ Handle all of the state changes that arise from the action
handler or other Graphics and
+ inputs in the application. The state passed to the
handle_states method is a string descriping
+ the change. A series of if/elif statements handle the state by
greying out action buttons, causing
+ changes in the flow graph, saving/opening files... The
handle_states method is passed to the
+ contructors of many of the classes used in this application
enabling them to report any state change.
+ @param state a string describing the state change
+ """
print '>>>',state
##############################################################################################
# Initalize/Quit
@@ -139,10 +156,11 @@
for action in ACTIONS_LIST: action.set_sensitive(False)
#set all actions disabled
# 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,
MATH_EXPR_WINDOW_DISPLAY,
-
FLOW_GRAPH_WINDOW_RESIZE, PREFS_WINDOW_DISPLAY, FLOW_GRAPH_SCREEN_CAPTURE):
- get_action_from_name(action).set_sensitive(True)
+ for action in (
+ APPLICATION_QUIT, FLOW_GRAPH_NEW,
FLOW_GRAPH_OPEN, FLOW_GRAPH_SAVE_AS,
+ 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))
self.flow_graph.from_nested_data(initial_state)
@@ -159,9 +177,9 @@
Messages.send_fail_load(e)
self.flow_graph_file_path = ''
self.handle_states(APPLICATION_INITIALIZE)
- self.set_saved_state(True)
+ self.saved = True
elif state == APPLICATION_QUIT:
- if self.loose_changes():
+ if self._loose_changes():
self.handle_states(FLOW_GRAPH_STOP)
Preferences.set_default_flow_graph(self.flow_graph_file_path)
Preferences.save(self.main_window)
@@ -185,40 +203,40 @@
##############################################################################################
elif state == SIGNAL_BLOCK_MOVE:
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
- self.set_saved_state(False)
+ self.saved = False
elif state == SIGNAL_BLOCK_ROTATE_LEFT:
if self.flow_graph.rotate_selected(DIR_LEFT):
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
- self.set_saved_state(False)
+ self.saved = False
elif state == SIGNAL_BLOCK_ROTATE_RIGHT:
if self.flow_graph.rotate_selected(DIR_RIGHT):
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
- self.set_saved_state(False)
+ self.saved = False
elif state == ELEMENT_DELETE:
if self.flow_graph.delete_selected():
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
self.handle_states(NOTHING_SELECT)
- self.set_saved_state(False)
+ self.saved = False
elif state == CONNECTION_CREATE or state ==
SIGNAL_BLOCK_CREATE:
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
self.handle_states(NOTHING_SELECT)
- self.set_saved_state(False)
+ self.saved = False
elif state == SIGNAL_BLOCK_INC_TYPE:
if self.flow_graph.type_controller_modify_selected(1):
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
- self.set_saved_state(False)
+ self.saved = False
elif state == SIGNAL_BLOCK_DEC_TYPE:
if self.flow_graph.type_controller_modify_selected(-1):
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
- self.set_saved_state(False)
+ self.saved = False
elif state == SOCKET_CONTROLLER_INC:
if self.flow_graph.socket_controller_modify_selected(1):
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
- self.set_saved_state(False)
+ self.saved = False
elif state == SOCKET_CONTROLLER_DEC:
if
self.flow_graph.socket_controller_modify_selected(-1):
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
- self.set_saved_state(False)
+ self.saved = False
##############################################################################################
# Window stuff
##############################################################################################
@@ -236,22 +254,25 @@
elif state == MATH_EXPR_WINDOW_DISPLAY:
Graphics.MathExprDialog()
elif state == FLOW_GRAPH_WINDOW_RESIZE:
- dimensions =
Graphics.FlowGraphWindowSizeDialog(self.flow_graph).run()
+ dimensions =
Graphics.FlowGraphWindowSizeDialog(self.flow_graph.get_size_request()).run()
if dimensions != None:
self.flow_graph.set_size_request(dimensions[0],
dimensions[1])
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
- self.set_saved_state(False)
+ self.saved = False
##############################################################################################
# Variable and Param Modifications
##############################################################################################
elif state == SIGNAL_BLOCK_PARAM_MODIFY:
if self.flow_graph.param_modify_selected():
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
- self.set_saved_state(False)
+ self.saved = False
elif state == VARIABLE_MODIFY:
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
- self.set_saved_state(False)
+ self.saved = False
self.flow_graph.update()
+ elif state == VARIABLE_REORDER:
+
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
+ self.saved = False
##############################################################################################
# Undo/Redo
##############################################################################################
@@ -260,24 +281,23 @@
if nested_data != None:
self.handle_states(NOTHING_SELECT)
self.flow_graph.from_nested_data(nested_data)
- self.set_saved_state(False)
+ self.saved = False
elif state == FLOW_GRAPH_REDO:
nested_data = self.state_cache.get_next_state()
if nested_data != None:
self.handle_states(NOTHING_SELECT)
self.flow_graph.from_nested_data(nested_data)
- self.set_saved_state(False)
+ self.saved = False
##############################################################################################
# New/Open/Save
##############################################################################################
elif state == FLOW_GRAPH_NEW:
- if self.loose_changes():
+ if self._loose_changes():
self.flow_graph_file_path = ''
self.handle_states(APPLICATION_INITIALIZE)
elif state == FLOW_GRAPH_OPEN:
- if self.loose_changes():
- fc = Graphics.FlowGraphFileDialog('open',
self.flow_graph_file_path)
- file_path = fc.run()
+ if self._loose_changes():
+ file_path =
Graphics.OpenFlowGraphFileDialog(self.flow_graph_file_path).run()
if file_path != None:
self.flow_graph_file_path = file_path
self.handle_states(APPLICATION_INITIALIZE)
@@ -286,19 +306,17 @@
else:
try:
ParseXML.to_file(ParseXML.to_xml(self.flow_graph.to_nested_data()),
self.flow_graph_file_path)
- self.set_saved_state(True)
+ self.saved = True
except IOError:
Messages.send_fail_save(self.flow_graph_file_path)
- self.set_saved_state(False)
+ self.saved = False
elif state == FLOW_GRAPH_SAVE_AS:
- fc = Graphics.FlowGraphFileDialog('save',
self.flow_graph_file_path)
- file_path = fc.run()
+ file_path =
Graphics.SaveFlowGraphFileDialog(self.flow_graph_file_path).run()
if file_path != None:
self.flow_graph_file_path = file_path
self.handle_states(FLOW_GRAPH_SAVE)
elif state == FLOW_GRAPH_SCREEN_CAPTURE:
- fc = Graphics.FlowGraphFileDialog('save image',
self.flow_graph_file_path)
- file_path = fc.run()
+ file_path =
Graphics.SaveImageFileDialog(self.flow_graph_file_path).run()
if file_path != None:
pixmap = self.flow_graph.pixmap
width, height = pixmap.get_size()
@@ -311,43 +329,48 @@
elif state == FLOW_GRAPH_EXEC:
if self.pid_file == None:
self.handle_states(FLOW_GRAPH_SAVE)
- if self.flow_graph_file_path != '': RUN(self)
+ if self.flow_graph_file_path != '':
ExecFlowGraphThread(self)
elif state == FLOW_GRAPH_STOP:
- while not MUTEX.testandset(): pass #try to lock
repeatedly until lock is aquired
+ MUTEX.lock()
if self.pid_file!= None:
try: os.kill(int(open(self.pid_file,
'r').read()), 9)
except: print "could not kill pid file:
%s"%self.pid_file
MUTEX.unlock()
else: print "!!! State not handled !!!"
- # 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_EXEC).set_sensitive(self.flow_graph.is_valid()
and self.pid_file == None)
+ #set the exec button if the flow graph is valid and is not
already running
+ MUTEX.lock()
+
get_action_from_name(FLOW_GRAPH_EXEC).set_sensitive(self.flow_graph.is_valid()
and self.pid_file == None)
+
get_action_from_name(FLOW_GRAPH_STOP).set_sensitive(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())
-
- def set_saved_state(self, saved):
- ''' If saved is True, disable the save button and modify the
title.
- If saved is False, enable the save button and modify the title
with a *. '''
- if saved:
+ #saved status
+ if self.saved: #set the window title and grey out the save
button
get_action_from_name(FLOW_GRAPH_SAVE).set_sensitive(False)
if self.flow_graph_file_path == '':
self.main_window.set_title(NEW_FLOGRAPH_TITLE)
else:
self.main_window.set_title(self.flow_graph_file_path)
- else:
+ else: #set the window title with a * and activate the save
button
get_action_from_name(FLOW_GRAPH_SAVE).set_sensitive(True)
if self.flow_graph_file_path == '':
self.main_window.set_title(NEW_FLOGRAPH_TITLE +
'*')
- else:
self.main_window.set_title(self.flow_graph_file_path + '*')
+ else:
self.main_window.set_title(self.flow_graph_file_path + '*')
+ #hide/show the reports window based on the preferences
+ Preferences.show_reports_window(self.main_window)
- def loose_changes(self):
- ''' True if the save is disabled or the user says to discard
changes. '''
- return not
get_action_from_name(FLOW_GRAPH_SAVE).get_sensitive() or\
- (Graphics.LooseChangesMessage().run())
+ def _loose_changes(self):
+ """!
+ Loose unsaved changes to flow graph?
+ If the save was not greyed-out, the user is presented with a
dialog.
+ @return true if save is greyed-out, or the user's choice.
+ """
+ return not
get_action_from_name(FLOW_GRAPH_SAVE).get_sensitive() or
Graphics.LooseChangesMessage().run()
-class RUN(Thread):
- ''' Run the flow graph as a new process and wait on it to finish
'''
+class ExecFlowGraphThread(Thread):
+ """Execute the flow graph as a new process and wait on it to finish."""
def __init__ (self, action_handler):
+ """!
+ ExecFlowGraphThread constructor.
+ @param action_handler an instance of an ActionHandler
+ """
Thread.__init__(self)
self.action_handler = action_handler
self.pid_file = self.action_handler.pid_file =
'/tmp/grc-%d.pid'%os.getpid()
@@ -355,22 +378,23 @@
self.flow_graph_file_path =
self.action_handler.flow_graph_file_path
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)
+ Messages.send_start_exec(self.flow_graph_file_path)
self.start()
def run(self):
+ """Execute the flow graph."""
cmd = '%s "%s" --pid_file="%s" 2>
"%s"'%(DEFAULT_FLOW_GRAPH_EXEC, self.flow_graph_file_path, self.pid_file,
self.report_file)
os.system(cmd)
try:
report = open(self.report_file, 'r')
# read all the lines of the report file into a
list #
- Messages.send_end_run(report.readlines())
+ Messages.send_end_exec(report.readlines())
report.close()
os.remove(self.report_file)
except IOError: print "could not read report file:
%s"%self.report_file
try: os.remove(self.pid_file)
except: print "could not remove pid file: %s"%self.pid_file
- while not MUTEX.testandset(): pass #try to lock repeatedly
until lock is aquired
+ MUTEX.lock()
self.action_handler.pid_file = None
get_action_from_name(FLOW_GRAPH_STOP).set_sensitive(False)
get_action_from_name(FLOW_GRAPH_EXEC).set_sensitive(True)
Modified: grc/trunk/src/Actions.py
===================================================================
--- grc/trunk/src/Actions.py 2007-06-29 17:29:46 UTC (rev 5877)
+++ grc/trunk/src/Actions.py 2007-06-29 17:41:26 UTC (rev 5878)
@@ -16,11 +16,9 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Actions.py
- Josh Blum
- Global actions for gui elements to communicate state changes to the
action handler.
-"""
address@hidden Actions
+#Global actions for gui elements to communicate state changes to the action
handler.
address@hidden Josh Blum
import pygtk
pygtk.require('2.0')
@@ -56,6 +54,7 @@
ELEMENT_DELETE = 'element delete'
VARIABLE_MODIFY = 'variable modify'
+VARIABLE_REORDER = 'variable reorder'
FLOW_GRAPH_OPEN = 'flow graph open'
FLOW_GRAPH_UNDO = 'flow graph undo'
@@ -79,7 +78,7 @@
# actions
######################################################################################################
-ACTIONS_LIST = [
+ACTIONS_LIST = (
gtk.Action(FLOW_GRAPH_NEW, '_New', 'Create a new flow graph',
'gtk-new'),
gtk.Action(FLOW_GRAPH_OPEN, '_Open', 'Open a flow graph from file',
'gtk-open'),
gtk.Action(FLOW_GRAPH_SAVE, '_Save', 'Save this flow graph',
'gtk-save'),
@@ -101,12 +100,18 @@
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_SCREEN_CAPTURE, 'S_creen Capture', 'Create a
screen capture of the flow graph', 'gtk-print'),
-]
+)
def get_action_from_name(action_name):
- """ Retrieve the action from the above list given its name. """
+ """!
+ Retrieve the action from the action list.
+ Search the list and find an action with said name.
+ @param action_name the action name(string)
+ @throw KeyError bad action name
+ @return a gtk action object
+ """
for action in ACTIONS_LIST:
if action.get_name() == action_name: return action
- return None
+ raise KeyError('Action Name: "%s" does not exist'%action_name)
\ No newline at end of file
Modified: grc/trunk/src/Colors.py
===================================================================
--- grc/trunk/src/Colors.py 2007-06-29 17:29:46 UTC (rev 5877)
+++ grc/trunk/src/Colors.py 2007-06-29 17:41:26 UTC (rev 5878)
@@ -16,11 +16,9 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Colors.py
- Josh Blum
- Colors and color-specs used to identify a socket's data type.
-"""
address@hidden Colors
+#Colors and color-specs used to identify a socket's data type.
address@hidden Josh Blum
import pygtk
pygtk.require('2.0')
@@ -60,4 +58,3 @@
SHORT_VECTOR_COLOR = COLORMAP.alloc_color(SHORT_VECTOR_COLOR_SPEC, True, True)
#background for shorts (yellowish)
INT_VECTOR_COLOR = COLORMAP.alloc_color(INT_VECTOR_COLOR_SPEC, True, True)
#background for ints (greenish)
BYTE_VECTOR_COLOR = COLORMAP.alloc_color(BYTE_VECTOR_COLOR_SPEC, True, True)
#background for bytes (purplish)
-
Modified: grc/trunk/src/Constants.py
===================================================================
--- grc/trunk/src/Constants.py 2007-06-29 17:29:46 UTC (rev 5877)
+++ grc/trunk/src/Constants.py 2007-06-29 17:41:26 UTC (rev 5878)
@@ -16,76 +16,78 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Constants.py
- Josh Blum
- Global constants
-"""
address@hidden Constants
+#Global constants
address@hidden Josh Blum
import sys, os
import mutex
-MUTEX = mutex.mutex() #mutex used when running a flow graph
+##mutex used when running a flow graph.
+MUTEX = mutex.mutex()
+def lock(mutex):
+ while not mutex.testandset(): pass #try to lock repeatedly until
lock is aquired
+MUTEX.lock = lambda: lock(MUTEX)
+
######################################################################################################
-# Global Titles
+## Global Titles @{
######################################################################################################
-""" The current version of this code """
+##The current version of this code
VERSION = '0.70 alpha'
-""" The name to appear in the main window for a flow graph that has not
been saved to file. """
+##The name to appear in the main window for a flow graph that has not been
saved to file.
NEW_FLOGRAPH_TITLE = 'untitled'
-""" The prefix title on the main window. """
+##The prefix title on the main window.
MAIN_WINDOW_PREFIX = "GRC"
address@hidden
######################################################################################################
-# Length of connector buds on Sockets(s) in pixels and
-# allowable rotation angles for Element(s) in degrees
+## Length of connector buds on Sockets(s) in pixels and
+# allowable rotation angles for Element(s) in degrees @{
######################################################################################################
-""" The length that a connection must extend from the socket
- until the length depends on the index of the socket. """
+##The length that a connection must extend from the socket until the length
depends on the index of the socket.
CONNECTOR_EXTENSION_INITIAL_LENGTH = 11
-""" The length that a connection must extend from the initial
- length times the index of the socket, after this length,
- the connection may have a bend. """
+##The length that a connection must extend from the initial length times the
index of the socket, after this length, the connection may have a bend.
CONNECTOR_EXTENSION_LENGTH = 11
-""" list of possible angles (in degrees) that a signal block and its
parameters
- can be rotated to. """
+##List of possible angles (in degrees) that a signal block and its parameters
can be rotated to.
POSSIBLE_ROTATIONS = (0, 90, 180, 270)
-""" directions of rotation """
+##direction of rotation left.
DIR_LEFT = 'left'
+
+##direction of rotation right.
DIR_RIGHT = 'right'
address@hidden
######################################################################################################
-# Dimension constraints for the various windows (in pixels)
+## Dimension constraints for the various windows (in pixels)
######################################################################################################
-# main window constraints #
-
+##main window constraints @{
DEFAULT_MAIN_WINDOW_WIDTH = 750
DEFAULT_MAIN_WINDOW_HEIGHT = 550
address@hidden
-# flow graph window constraints #
-
+##flow graph window constraints @{
MIN_WINDOW_WIDTH = 600
MAX_WINDOW_WIDTH = 2400
MIN_WINDOW_HEIGHT = 400
MAX_WINDOW_HEIGHT = 1800
address@hidden
-# dialog constraints #
-
+##dialog constraints @{
MIN_DIALOG_WIDTH = 400
MIN_DIALOG_HEIGHT = 500
address@hidden
-# misc window constraints #
-
+##misc window constraints @{
REPORTS_WINDOW_HEIGHT = 80
SIGNAL_BLOCK_SELECTION_WINDOW_WIDTH = 250
@@ -93,27 +95,31 @@
VARIABLE_MODIFICATION_WINDOW_WIDTH = 250
VARIABLE_MODIFICATION_WINDOW_HEIGHT = 150
address@hidden
######################################################################################################
-# Constraints for the sliders in the runnable flow graph
+## Constraints for the sliders in the runnable flow graph @{
######################################################################################################
-''' The number of tics for a slider. '''
+##The number of tics for a slider.
DEFAULT_SLIDER_STEPS = 100
-''' The max width that a row of sliders can use '''
+##The max width that a row of sliders can use.
MAX_SLIDERS_WIDTH = 600
-''' The width in pixels. '''
+##Slider width in pixels
DEFAULT_SLIDER_WIDTH = 200
+##Slider width in pixels
MAX_SLIDER_WIDTH = 300
+##Slider width in pixels
MIN_SLIDER_WIDTH = 100
-''' The height in pixels. '''
+##The height in pixels.
SLIDER_HEIGHT = 20
address@hidden
######################################################################################################
-# Constraints on displayable labels and sockets
+## Constraints on displayable labels and sockets @{
######################################################################################################
LABEL_SEPARATION = 4
@@ -128,70 +134,71 @@
PARAM_FONT = 'Sans 8'
SIGNAL_BLOCK_FONT = 'Sans 9 Bold'
SOCKET_FONT = 'Sans 8'
address@hidden
######################################################################################################
-# Dragging, scrolling, and redrawing constants for the flow graph window
in pixels
+## Dragging, scrolling, and redrawing constants for the flow graph window in
pixels @{
######################################################################################################
-""" How close can the mouse get to the window border before mouse events
are ignored. """
+##How close can the mouse get to the window border before mouse events are
ignored.
BORDER_PROXIMITY_SENSITIVITY = 10
-""" How close can the mouse get to the edge of the visible window before
scrolling is invoked. """
+##How close can the mouse get to the edge of the visible window before
scrolling is invoked.
SCROLL_PROXIMITY_SENSITIVITY = 30
-""" When the window has to be scrolled, move it this distance in the
required direction. """
+##When the window has to be scrolled, move it this distance in the required
direction.
SCROLL_DISTANCE = 15
-""" Do not draw more than this many sockets on one side of a signal block.
"""
-MAX_NUM_SOCKETS = 20
-
-""" The redrawing sensitivity, how many motion detection events must occur
before a redraw? """
+##The redrawing sensitivity, how many motion detection events must occur
before a redraw?
MOTION_DETECT_REDRAWING_SENSITIVITY = 3
address@hidden
######################################################################################################
# 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 flow graph (for undo/redo
functionality) """
+##The size of the state saving cache in the flow graph (for undo/redo
functionality)
STATE_CACHE_SIZE = 42
######################################################################################################
-# Constansts dealing with File Paths
+## Constansts dealing with File Paths @{
######################################################################################################
-""" Location of the python src directory. """
+##Location of the python src directory.
SRC_DIR = os.path.abspath(os.path.dirname(__file__))
-""" Location of external data files """
+##Location of external data files.
DATA_DIR = os.path.abspath(SRC_DIR+'/../data/')
-""" The setting for a blank flow graph """
+##The setting for a blank flow graph.
INITIAL_FLOW_GRAPH_FILE =
os.path.abspath(DATA_DIR+'/initial_flow_graph.grc.xml')
-""" The default file extension for file open and save dialogs. """
-DEFAULT_FILE_EXTENSION = '.grc.xml'
+##The default file extension for flow graphs.
+FLOW_GRAPH_FILE_EXTENSION = '.grc.xml'
-""" The default file extension for saving flow graph snap shots. """
+##The default file extension for saving flow graph snap shots.
IMAGE_FILE_EXTENSION = '.png'
-""" The default path for the open/save dialogs. """
+##The default path for the open/save dialogs.
DEFAULT_FILE_PATH = os.path.expanduser('~')+'/'
-""" The default icon for all windows. """
+##The default icon for the gtk windows.
PY_GTK_ICON = os.path.abspath(DATA_DIR+'/grc-icon-256.png')
+
+##The default icon for the wx windows.
WX_APP_ICON = os.path.abspath(DATA_DIR+'/grc-icon-32.png')
#>>> platform dependency! wx under cygwin has issues with icon paths #
if sys.platform == 'cygwin': WX_APP_ICON = None
-""" The default binary to execute python files. """
+##The default binary to execute python files.
PYEXEC = 'python'
#>>> platform dependency! MacOS requires pythonw to run wx apps #
if sys.platform == 'darwin': PYEXEC = 'pythonw'
-""" The default command to run a flow graph file """
+##The default command to run a flow graph file.
DEFAULT_FLOW_GRAPH_EXEC = '%s %s/ExecFlowGraphGUI.py'%(PYEXEC, SRC_DIR)
-""" The default user preferences file. """
+##The default user preferences file.
PREFERENCES_FILE_PATH = os.path.abspath(DEFAULT_FILE_PATH + '/.grc.xml')
address@hidden
-
Deleted: grc/trunk/src/DataType.py
Copied: grc/trunk/src/DataTypes.py (from rev 5877,
grc/branches/jblum_work/src/DataTypes.py)
===================================================================
--- grc/trunk/src/DataTypes.py (rev 0)
+++ grc/trunk/src/DataTypes.py 2007-06-29 17:41:26 UTC (rev 5878)
@@ -0,0 +1,546 @@
+"""
+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
+"""
address@hidden DataTypes
+#All the data types for sockets and params. Contains parsing and validity
checks.
address@hidden Josh Blum
+
+import MathExprParser
+import Variables
+from gnuradio import gr
+
+class DataType:
+ """
+ The base class for all data types.
+ Hold data and provide parsing.
+ Do not use, this is a base class only.
+ """
+ base_type = None
+
+ def __init__(self, data='0', min=None, max=None):
+ """!
+ DataType constructor.
+ @param data the data
+ @param min the minimum
+ @param max the maximum
+ """
+ self.set_data(data)
+ self.max = max
+ self.min = min
+ ##parser messages
+ self.msg = ''
+
+ def __str__(self):
+ """!
+ Get the string representation of this data type.
+ This will be the parsed value, or an error message if invalid.
+ @return the string representation.
+ """
+ return self.msg
+
+ def set_data(self, data):
+ """!
+ Store the data as a string.
+ @param data the data
+ """
+ self.data = str(data)
+
+ def get_data(self):
+ """!
+ Get the data as a string.
+ @return the data """
+ return self.data
+
+ def parse(self):
+ """!
+ Substitute in variables.
+ Replace all variable instances with the variable's string
representation.
+ @return the data without variables"""
+ return Variables.replace_var_instances(self.get_data())
+
+ def is_valid(self):
+ """!
+ Is this data type valid?
+ True if the data can be parsed, otherwise False.
+ 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.
+ @return boolean, true if valid
+ """
+ try:
+ value = self.parse()
+ self.msg = str(value)
+ return True
+ except Exception, e:
+ self.msg = str(e)
+ return False
+
+ def get_type(self):
+ """!
+ Get a string describing the specific data type.
+ @return type string
+ """
+ return self.type
+
+ def get_base_type(self):
+ """!
+ Get a string describing the base (category) of this data type.
+ @return base type string
+ """
+ return self.base_type
+
+ def get_num_bytes(self):
+ """!
+ How man bytes in this data type?
+ @return number of bytes
+ """
+ return self.num_bytes
+
+ def _verify_bounds(self, value):
+ """!
+ Is the value within the bounds of this data type?
+ @throw ValueError out of bounds.
+ """
+ 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
+#############################################################################################
+class Number(DataType):
+ """
+ A number data type.
+ The base class for numeric data types.
+ Do not use, this is a base class only.
+ """
+ base_type = 'number'
+
+ def parse(self):
+ """!
+ Evaluate the math expressions in the data type.
+ @return a number
+ """
+ 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):
+ """!
+ Parse the data for an integer value or raise an error.
+ @throw Exception non integer
+ @return integer
+ """
+ return MathExprParser.verify_int(value)
+
+class Byte(Int):
+ """The byte data type is identical to int. """
+ type = 'byte'
+ num_bytes = gr.sizeof_char
+
+class Short(Int):
+ """The short data type is identical to int."""
+ type = 'short'
+ num_bytes = gr.sizeof_short
+
+class Float(Number):
+ """The float data type."""
+ type = 'float'
+ num_bytes = gr.sizeof_float
+
+ def parser(self, value):
+ """!
+ Parse the data for an float value or raise an error.
+ @throw Exception non float
+ @return float
+ """
+ return MathExprParser.verify_float(value)
+
+class Complex(Number):
+ """The complex data type."""
+ type = 'complex'
+ num_bytes = gr.sizeof_gr_complex
+
+ def parser(self, value):
+ """!
+ Parse the data for an complex value or raise an error.
+ @throw Exception non complex
+ @return complex
+ """
+ return MathExprParser.verify_complex(value)
+
+#############################################################################################
+# Special Types
+#############################################################################################
+class RawExpr(DataType):
+ """A raw mathematical expression."""
+ type = 'raw'
+
+ def __init__(self, data=''):
+ """!
+ Raw data type contructor.
+ @param data the data
+ """
+ DataType.__init__(self, data)
+
+ def parse(self):
+ """!
+ Get the raw data returned by the math parser.
+ @throw Exception malformed expression
+ @return the evaluated mathematical expression
+ """
+ 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.
+ @param data the data
+ @param min the minimum length of the string
+ @param max the maximum length of the string
+ """
+ DataType.__init__(self, data, min, max)
+
+ def parse(self):
+ """!
+ Get the data as a string.
+ @throw Exception string length out of bounds
+ @return the data
+ """
+ string = DataType.parse(self)
+ self._verify_bounds(len(string))
+ return string
+
+class Hex(DataType):
+ """The hex data type."""
+ type = 'hex'
+
+ def parse(self):
+ """!
+ Get the data as an integer parsed from a hex string.
+ @return the data
+ """
+ return int(DataType.parse(self),16)
+
+class File(String):
+ """A file data type. Do not use, this is a base class only."""
+ base_type = 'file'
+
+ def __init__(self, data='', allow_blank=False):
+ """!
+ File data type contructor.
+ Allow blank lets blank filename pass validation.
+ @param data the file path
+ @param allow_blank allow empty paths(true/false)
+ """
+ String.__init__(self, data)
+ self.allow_blank = allow_blank
+
+class FileOpen(File):
+ """A file data type for choosing existing files."""
+ type = 'fileopen'
+
+ def is_valid(self):
+ """!
+ Does the file path exist?
+ @return true if valid
+ """
+ if self.allow_blank and self.parse() == '': return True
+ from os import path
+ return path.isfile(self.parse())
+
+class FileSave(File):
+ """A file data type for choosing files to save."""
+ type = 'filesave'
+
+ def is_valid(self):
+ """!
+ Is the file path possible?
+ The directory must exist and the filename must not be an
existing directory.
+ @return true if validcannonical name
+ """
+ if self.allow_blank and self.parse() == '': return True
+ from os import path
+ my_path = self.parse()
+ # Return False if the directory does not exist or the path is
just a directory. #
+ if not path.exists(path.dirname(my_path)) or
path.isdir(my_path): return False
+ # True if the basename is not an empty string. #
+ return path.basename(my_path) != ''
+
+class Variable(DataType):
+ """
+ The variable data type.
+ Takes properties from an enumerated data type of data types.
+ """
+
+ def __init__(self, enum_data_type, data='0', index=None, min=None,
max=None):
+ """!
+ Variable constructor.
+ The enumerated type must contain other data types in its
choices.
+ The index is the index of the data type in the enum's tuple.
+ If index is None, enum must parse to a data type.
+ @param enum_data_type an enumerated data type
+ @param data the data
+ @param index the index of the data type in the enum's choice
+ @param min the minimum
+ @param max the maximum
+ """
+ DataType.__init__(self, data, min, max)
+ self.enum_data_type = enum_data_type
+ self.index = index
+
+ def _parse_enum_data_type(self):
+ """!
+ Parse the selected data type.
+ If there is an index, get the data type from a tuple instead.
+ @return the data type
+ """
+ if self.index is None: return self.enum_data_type.parse()
+ else: return self.enum_data_type.parse()[self.index]
+
+ def get_type(self):
+ """!
+ Get the type from the enumerated data type.
+ @return the type
+ """
+ return self._parse_enum_data_type().get_type()
+
+ def get_base_type(self):
+ """!
+ Get the base type from the enumerated data type.
+ @return the base type
+ """
+ return self._parse_enum_data_type().get_base_type()
+
+ def get_num_bytes(self):
+ """!
+ Get the number of bytes from the enumerated data type.
+ @return the number of bytes.
+ """
+ return self._parse_enum_data_type().get_num_bytes()
+
+ def parse(self):
+ """!
+ Use the parser from the enumerated data type.
+ @return the parsed data
+ """
+ data_type = self._parse_enum_data_type()
+ data_type.set_data(self.get_data())
+ return data_type.parse()
+
+class Enum(DataType):
+ """The enumerated data type.
+ The enumerated type holds a finite set of choices.
+ The selected choice is determined by the data.
+ The data must represent an integer index. """
+ type = 'enum'
+ base_type = 'enum'
+
+ def __init__(self, choices=[('',0)], data='0'):
+ """!
+ Enum constructor.
+ choices = [(cname0, choice0),(cname1, choice1),...]
+ @param choices the list of choices
+ @param data the choice index 0-> len(choices)-1
+ """
+ self.choices = choices
+ DataType.__init__(self, data)
+
+ def set_data(self, data):
+ """!
+ Set the data.
+ Try to use data as an index for choices.
+ @param data the data
+ @throw Exception bad index
+ """
+ self.choices[int(data)]
+ DataType.set_data(self, data)
+
+ def parse(self):
+ """!
+ Parse the data by returning the current selection pointed to by
the data.
+ @return the choice at the index held in data
+ """
+ return self.choices[int(self.get_data())][1]
+
+ def get_cname(self):
+ """!
+ Get the cannonical name of the currently selected choice.
+ @return the cannonical name
+ """
+ return self.choices[int(self.get_data())][0]
+
+ def get_cnames_list(self):
+ """!
+ Get a list of the cannonical names from the choices (in order).
+ @return a list of all the cannonical names
+ """
+ cnames = list()
+ for cname,choice in self.choices: cnames.append(cname)
+ return cnames
+
+class VariableKeySelector(DataType):
+ """
+ The variable key selector data type.
+ This data type allows the user to select a variable key in the variable
registry.
+ """
+ type = 'variable enum'
+ base_type = 'variable enum'
+
+ def __init__(self, data='', all_variables=False):
+ """!
+ Variable key selector contructor.
+ If the all variables flag is true, this data type can represent
any variable key.
+ If the all variables flag is false, variables with ranges will
not be allowed.
+ @param data the variable key
+ @param all_variables boolean to allow certain variables
+ """
+ DataType.__init__(self, data)
+ self.all_variables = all_variables
+
+ def parse(self):
+ """!
+ Parse the data by returning the current key.
+ @return the var key
+ """
+ return self.get_data().strip()
+
+ def is_valid(self):
+ """!
+ Is the variable key valid?
+ The data must be in the keys list.
+ @return true if valid"""
+ return self.parse() in self.get_variables_list()
+
+ def get_variables_list(self):
+ """!
+ Get a list of the keys.
+ Use all_variables to restrict the list.
+ @return a list of possible keys
+ """
+ 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 not Variables.is_ranged(key):
var_keys.append(key)
+ return var_keys
+
+class Bool(Enum):
+ """
+ The boolean data type.
+ This boolean type is an Enum with two choices.
+ One choice will parse to True, the other False. """
+ type = 'bool'
+
+ def __init__(self, true='True', false='False', default=True):
+ """!
+ Bool contructor.
+ @param true the cname for the true choice
+ @param false the cname for the false choice
+ @param default the default choice
+ """
+ if default: data = 0 #determine the default index
+ else: data = 1
+ Enum.__init__(self, choices=[(true, True), (false, False)],
data=data)
+
+#############################################################################################
+# Vectors Types
+#############################################################################################
+class Vector(DataType):
+ """
+ A vector data type.
+ The base class for vectors.
+ Do not use, this is a base class only.
+ """
+ base_type = 'vector'
+
+ def parse(self):
+ """!
+ Parse the vector data type.
+ The length of the vector must be within bounds.
+ The data must pass the math expression parser.
+ @throw Exception not in bounds
+ @throw Exception invalid syntax
+ @return the vector
+ """
+ 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."""
+ type = 'byte vector'
+
+class IntVector(Vector, Int):
+ """A vector of ints."""
+ type = 'int vector'
+
+class ShortVector(Vector, Short):
+ """A vector of shorts."""
+ type = 'short vector'
+
+class FloatVector(Vector, Float):
+ """A vector of floats."""
+ type = 'float vector'
+
+class ComplexVector(Vector, Complex):
+ """A vector of complex."""
+ type = 'complex vector'
+
+def can_connect(dt1, dt2):
+ """!
+ Can these data types connect?
+ @param dt1 a data type
+ @param dt2 another data type
+ @return true if the types match
+ """
+ return dt1.get_type() == dt2.get_type()
+
+def vectorize(data_type):
+ """!
+ Take a regular data type and return its vector form.
+ @param data_type a regular data type
+ @return a vector data type
+ """
+ type = data_type.get_type()
+ regular_to_vector_dict = {
+ Byte().get_type() : ByteVector(),
+ Short().get_type() : ShortVector(),
+ Int().get_type() : IntVector(),
+ Float().get_type() : FloatVector(),
+ Complex().get_type() : ComplexVector(),
+ }
+ if type in regular_to_vector_dict.keys():
+ return regular_to_vector_dict[type]
+ return data_type #otherwise return the input data type
+
+if __name__ == '__main__':
+ """Use the main method to test data types."""
+ pass
+
+
\ No newline at end of file
Modified: grc/trunk/src/Editor.py
===================================================================
--- grc/trunk/src/Editor.py 2007-06-29 17:29:46 UTC (rev 5877)
+++ grc/trunk/src/Editor.py 2007-06-29 17:41:26 UTC (rev 5878)
@@ -17,21 +17,19 @@
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.
-"""
address@hidden Editor
+#Execute the flow graph editor GUI. This file must be called by the python
interpreter.
address@hidden Josh Blum
-from Constants import VERSION,DEFAULT_FILE_EXTENSION
+from Constants import VERSION,FLOW_GRAPH_FILE_EXTENSION
from optparse import OptionParser
if __name__ == "__main__":
- usage = "usage: %prog optional_flow_graph"+DEFAULT_FILE_EXTENSION
+ usage = "usage: %prog optional_flow_graph"+FLOW_GRAPH_FILE_EXTENSION
version = """
GNU Radio Companion %s
-This file is part of GNU Radio
+This program is part of GNU Radio
GRC comes with ABSOLUTELY NO WARRANTY.
This is free software,
and you are welcome to redistribute it.
@@ -39,16 +37,11 @@
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)
+ for module in ('pygtk', 'gtk', 'wx', 'numpy', 'xml.dom.minidom',
'xml.dom.ext', 'gnuradio', 'gnuradio.gr.hier_block2'):
+ try: __import__(module)
+ except ImportError: #print error and exit
+ print '\nMissing critical module:
"%s"\nExiting!\n'%module
+ exit(-1)
# end import of modules #
from ActionHandler import ActionHandler
if len(args): ActionHandler(args[0])
Property changes on: grc/trunk/src/Elements
___________________________________________________________________
Name: svn:ignore
- *.pyc
Modified: grc/trunk/src/Elements/Connection.py
===================================================================
--- grc/trunk/src/Elements/Connection.py 2007-06-29 17:29:46 UTC (rev
5877)
+++ grc/trunk/src/Elements/Connection.py 2007-06-29 17:41:26 UTC (rev
5878)
@@ -16,33 +16,33 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Elements/Connection.py
- Josh Blum
- The elemental connection of input and output sockets.
-"""
address@hidden Elements.Connection
+#The elemental connection of input and output sockets.
address@hidden Josh Blum
-from Element import Element
+import Element
import Utils
-class InvalidConnectionException(Exception):
- def __str__(self): return 'A connection requires a valid input and
output socket!'
+class ConnectionException(Exception): pass
-class TooManyConnectionsException(Exception):
- def __str__(self): return 'An input socket may only have one
connection!'
-
-class Connection(Element):
- """ Connection provides elemental interfaces for a connection of
sockets. """
+class Connection(Element.Element):
+ """Connection provides elemental interfaces for a connection of
sockets."""
type = 'connection'
def __init__(self, parent, socket1, socket2):
- """ Initialize the Element and set the parent, coor, and
rotation.
- Try to connect a pair of sockets. The sockets must be an input
and an output.
- Also the input must have no existing connections.
- If an input socket that is already connected is passed to the
constructor,
- the logic will use the output socket that it is connected to.
- This way, a user could try to connect an unconnected input
socket to a signal on another input.
- Then, the program will translate this to the cooresponding
output socket on that signal. """
- Element.__init__(self, parent, (0,0), 0)
+ """!
+ Connection constructor.
+ Initialize the Element with the given parent and a rotation and
coordinate of zeros.
+ Connect a pair of sockets. The sockets must be an input and an
output. The input must have no existing connections.
+ @param parent the flow graph
+ @param socket1 an input/output socket
+ @param socket2 another input/output socket
+ @throw InvalidConnectionException cant connect
+ """
+ Element.Element.__init__(self, parent, (0,0), 0)
+ #If an input socket that is already connected is passed to the
constructor,
+ #the logic will use the output socket that it is connected to.
+ #This way, a user could try to connect an unconnected input
socket to a signal on another input.
+ #Then, the program will translate this to the cooresponding
output socket on that signal.
#>>>I dont like this functionality, uncomment it to pick the
output socket
#if is_input_socket(socket1) and socket1.is_connected():
#socket1 is input and connected
# socket1 =
socket1.get_connections()[0].get_output_socket() #so we use its output
socket
@@ -56,26 +56,38 @@
socket2.connect(self) #order is important, try input
socket first (since input can throw an exception)
socket1.connect(self)
self.sockets = [socket2, socket1]
- else: raise InvalidConnectionException()
+ else: raise ConnectionException, 'A connection requires a valid
input and output socket!'
def get_coordinate(self):
- ''' always get the 0,0 coordinate '''
+ """!Get the 0,0 coordinate.
+ Coordinates are irrelevant in connection.
+ @return 0,0
+ """
return (0,0)
def get_rotation(self):
- ''' always get the 0 degree rotation '''
+ """!Get the 0 degree rotation.
+ Rotations are irrelevant in connection.
+ @return 0
+ """
return 0
def get_input_socket(self):
- """get the input socket"""
+ """!
+ Get the input socket.
+ @return input socket
+ """
return self.sockets[0]
def get_output_socket(self):
- """get the output socket"""
+ """!
+ Get the output socket.
+ @return output socket
+ """
return self.sockets[1]
def disconnect(self):
- """ delete this connection by calling the socket's disconnect
methods. """
+ """Disconnect the sockets by calling each socket's disconnect
methods and removing the sockets from the parent."""
print "disconnecting"
for socket in self.sockets: socket.disconnect(self)
self.get_parent().remove_element(self)
Modified: grc/trunk/src/Elements/Element.py
===================================================================
--- grc/trunk/src/Elements/Element.py 2007-06-29 17:29:46 UTC (rev 5877)
+++ grc/trunk/src/Elements/Element.py 2007-06-29 17:41:26 UTC (rev 5878)
@@ -16,36 +16,41 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Elements/Element.py
- Josh Blum
- The base class for graphical elements such as:
- signal blocks, input sockets, output sockets and connections
-"""
address@hidden Elements.Element
+#The base class for graphical elements such as:
+#signal blocks, input sockets, output sockets and connections.
address@hidden Josh Blum
from Constants import POSSIBLE_ROTATIONS,DIR_LEFT,DIR_RIGHT
class Element:
- """ Element is the base class for all elements. It contains an X,Y
coordinate, a list
- of rectangular areas that the element occupies and methods to detect
selection. """
-
- def rotate(self, direction):
- """ rotate all of the areas by 90 degrees, direction is
"left"/"right" """
- if direction == DIR_LEFT: delta_rotation = 90
- elif direction == DIR_RIGHT: delta_rotation = 270
- self.set_rotation((self.get_rotation() + delta_rotation)%360)
- self.update()
-
+ """Element is the base class for all elements. It contains an X,Y
coordinate, a list
+ of rectangular areas (and lines) that the element occupies and methods
to detect selection."""
def __init__(self, parent, coor, rotation):
- """ make a new list of rectangular areas and lines, and set
the coordinate and the rotation """
+ """!
+ Make a new list of rectangular areas and lines, and set the
coordinate and the rotation.
+ @param parent the parent of this element
+ @param coor the coordinate tuple (x,y)
+ @param rotation an angle in degrees 0, 90, 180, 270
+ """
self.parent = parent
self.set_rotation(rotation)
self.set_coordinate(coor)
self.clear()
- self.highlighted = False
+ self.highlighted = False
+
+ def rotate(self, direction):
+ """!
+ Rotate all of the areas by 90 degrees.
+ @param direction DIR_RIGHT or DIR_LEFT
+ """
+ if direction == DIR_LEFT: delta_rotation = 90
+ elif direction == DIR_RIGHT: delta_rotation = 270
+ self.set_rotation((self.get_rotation() + delta_rotation)%360)
+ self.update()
def clear(self):
- ''' make the lines and areas empty. '''
+ """Empty the lines and areas."""
self.areas_dict = dict()
self.lines_dict = dict()
for rotation in POSSIBLE_ROTATIONS:
@@ -53,48 +58,78 @@
self.lines_dict[rotation] = list()
def set_coordinate(self, coor):
- ''' set the reference coordinate. '''
+ """!
+ Set the reference coordinate.
+ @param coor the coordinate tuple (x,y)
+ """
self.coor = coor
def get_parent(self):
- ''' get the parent '''
+ """!
+ Get the parent of this element.
+ @return the parent
+ """
return self.parent
def set_highlighted(self, highlighted):
- """ set the highlight status """
+ """!
+ Set the highlight status.
+ @param highlighted true to enable highlighting
+ """
self.highlighted = highlighted
def is_highlighted(self):
- """ get the highlight status """
+ """!
+ Get the highlight status.
+ @return true if highlighted
+ """
return self.highlighted
def get_coordinate(self):
- """ get the coordinate (X,Y) pair """
+ """!Get the coordinate.
+ @return the coordinate tuple (x,y)
+ """
return self.coor
def move(self, delta_coor):
- """ we move the element by adding the X and Y values of
deltaCoor to this coordinate """
+ """!
+ Move the element by adding the delta_coor to the current
coordinate.
+ @param delta_coor (delta_x,delta_y) tuple
+ """
deltaX,deltaY = delta_coor
X,Y = self.get_coordinate()
self.coor = (X+deltaX, Y+deltaY)
def add_area(self, rel_coor, area, rotation=None):
- """ add an area to the area list, an area is actually a
coordinate relative to the main coordinate
- with a width/height pair relative to the area coordinate. A
positive width is to the right of the
- coordinate. A positive height is above the coordinate """
+ """!
+ Add an area to the area list.
+ An area is actually a coordinate relative to the main
coordinate with a width/height pair relative to the area coordinate.
+ A positive width is to the right of the coordinate. A positive
height is above the coordinate.
+ The area is associated with a rotation. If rotation is not
specified, the element's current rotation is used.
+ @param rel_coor (x,y) offset from this element's coordinate
+ @param area (width,height) tuple
+ @param rotation rotation in degrees
+ """
if rotation == None: rotation = self.get_rotation()
self.areas_dict[rotation].append((rel_coor, area))
def add_line(self, rel_coor1, rel_coor2, rotation=None):
- """ add a line to the line list. A line is defined by 2
relative coordinates.
- Lines must be horizontal or vertical! """
+ """!
+ Add a line to the line list.
+ A line is defined by 2 relative coordinates. Lines must be
horizontal or vertical.
+ The line is associated with a rotation. If rotation is not
specified, the element's current rotation is used.
+ @param rel_coor1 relative (x1,y1) tuple
+ @param rel_coor2 relative (x2,y2) tuple
+ @param rotation rotation in degrees
+ """
if rotation == None: rotation = self.get_rotation()
self.lines_dict[rotation].append((rel_coor1, rel_coor2))
def what_is_selected(self, coor):
- """ is this Element selected at given coor? Or is coor
encompassed by one of the areas or lines.
- We determine the absolute coordinate of each area and
coordinate on the other diagonal of the area.
- return self if one of the areas/lines encompasses the coor, or
None. """
+ """!
+ Is this Element selected at given coordinate/is the coordinate
encompassed by one of the areas or lines?
+ @return self if one of the areas/lines encompasses coor, else
None.
+ """
in_between = lambda A, B, point: point >= min(A,B) and point <=
max(A,B)
X,Y = self.get_coordinate()
x,y = coor
@@ -116,17 +151,22 @@
return None
def get_rotation(self):
- """ get the rotation """
+ """!
+ Get the rotation in degrees.
+ @return the rotation
+ """
return self.rotation
def set_rotation(self, rotation):
- """ set the rotation """
+ """!
+ Set the rotation in degrees.
+ @param rotation the rotation"""
if rotation not in POSSIBLE_ROTATIONS:
raise Exception('"%s" is not one of the possible
rotations: (%s)'%(rotation,POSSIBLE_ROTATIONS))
self.rotation = rotation
def update(self):
- """ Do nothing for the update. """
+ """Do nothing for the update. Dummy method."""
pass
\ No newline at end of file
Modified: grc/trunk/src/Elements/GraphicalConnection.py
===================================================================
--- grc/trunk/src/Elements/GraphicalConnection.py 2007-06-29 17:29:46 UTC
(rev 5877)
+++ grc/trunk/src/Elements/GraphicalConnection.py 2007-06-29 17:41:26 UTC
(rev 5878)
@@ -16,23 +16,21 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Elements/GraphicalConnection.py
- Josh Blum
- The graphical connection for input/output sockets.
-"""
address@hidden Elements.GraphicalConnection
+#The graphical connection for input/output sockets.
address@hidden Josh Blum
-import DataType
+import DataTypes
import Utils
-from Connection import Connection
-from GraphicalElement import GraphicalElement
+import Connection
+import GraphicalElement
import Colors
-class GraphicalConnection(Connection, GraphicalElement):
- """ Connection is a graphical connection for sockets """
+class GraphicalConnection(Connection.Connection,
GraphicalElement.GraphicalElement):
+ """A graphical connection for sockets."""
def update(self):
- """ add the horizontal and vertical lines that will connect
the two parameters """
+ """Add the horizontal and vertical lines that will connect the
two parameters."""
self.clear()
input_socket = self.get_input_socket()
output_socket = self.get_output_socket()
@@ -70,9 +68,12 @@
self.add_line((x2,y2),p)
def draw(self, window):
- """ draw the Connection """
+ """!
+ Draw the connection.
+ @param window the gtk window to draw on
+ """
self.update()
- GraphicalElement.draw(self, window)
+ GraphicalElement.GraphicalElement.draw(self, window)
gc = self.gc
''' draw error lines around the existing lines when data
types do not match '''
if not self.is_valid():
@@ -86,9 +87,12 @@
window.draw_line(gc, x1, y1+1, x2, y2+1)
def is_valid(self):
- """ is this connection valid, ie: do the input and output data
types match? """
+ """!
+ Is this connection valid, ie: do the input and output data
types match?
+ User preferences can override this validity check.
+ @return true if the data types match or if check connections is
off
+ """
import Preferences #preferences
return not Preferences.check_connections() or\
- DataType.can_connect(self.sockets[0].get_data_type(),
self.sockets[1].get_data_type())
-
+ DataTypes.can_connect(self.sockets[0].get_data_type(),
self.sockets[1].get_data_type())
Modified: grc/trunk/src/Elements/GraphicalElement.py
===================================================================
--- grc/trunk/src/Elements/GraphicalElement.py 2007-06-29 17:29:46 UTC (rev
5877)
+++ grc/trunk/src/Elements/GraphicalElement.py 2007-06-29 17:41:26 UTC (rev
5878)
@@ -16,26 +16,30 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Elements/GraphicalElement.py
- Josh Blum
- base class for graphical elements such as:
- signal blocks, input sockets, output sockets and connections
-"""
address@hidden Elements.GraphicalElement
+#Base class for graphical elements such as:
+#signal blocks, input sockets, output sockets and connections.
address@hidden Josh Blum
+
from Constants import *
-from Element import Element
+import Element
import Colors
import pygtk
pygtk.require('2.0')
import gtk
import pango
-class GraphicalElement(Element):
+class GraphicalElement(Element.Element):
""" Element is the base class for all graphical elements. It
contains an X,Y coordinate, a list
of rectangular areas that the element occupies and methods to detect
selection. """
def draw(self, window, BG_color=Colors.BG_COLOR,
FG_color=Colors.FG_COLOR):
- """ draw in the given window. """
+ """!
+ Draw in the given window.
+ @param window the gtk window to draw on
+ @param BG_color the background color
+ @param FG_color the foreground color
+ """
gc = self.get_parent().gc
self.gc = gc
X,Y = self.get_coordinate()
@@ -51,7 +55,5 @@
if self.is_highlighted(): gc.foreground = Colors.H_COLOR
else: gc.foreground = FG_color
window.draw_line(gc, X+x1, Y+y1, X+x2, Y+y2)
-
-
\ No newline at end of file
Modified: grc/trunk/src/Elements/GraphicalParam.py
===================================================================
--- grc/trunk/src/Elements/GraphicalParam.py 2007-06-29 17:29:46 UTC (rev
5877)
+++ grc/trunk/src/Elements/GraphicalParam.py 2007-06-29 17:41:26 UTC (rev
5878)
@@ -16,14 +16,12 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Elements/GraphicalParam.py
- Josh Blum
- GTK objects for handling input and the signal block parameter class.
-"""
address@hidden Elements.GraphicalParam
+#GTK objects for handling input and the signal block parameter class.
address@hidden Josh Blum
-from Param import Param
-from DataType import *
+import Param
+from DataTypes import *
import pygtk
pygtk.require('2.0')
import gtk
@@ -38,14 +36,12 @@
class InputParam(gtk.HBox):
""" The base class for an input parameter inside the input parameters
dialog. """
- def __init__(self, data_type, handle_changed):
+ def __init__(self, data_type, _handle_changed):
gtk.HBox.__init__(self)
- self.show()
self.data_type = data_type
- self.handle_changed = handle_changed
- self.label = gtk.Label('') #no label, markup is added by
set_markup
- self.label.set_size_request(140,30)
- self.label.show()
+ self._handle_changed = _handle_changed
+ self.label = gtk.Label() #no label, markup is added by
set_markup
+ self.label.set_size_request(140,-1)
self.pack_start(self.label, False)
self.set_markup = lambda m: self.label.set_markup(m)
self.tp = None
@@ -54,11 +50,10 @@
""" Provide an entry box for strings and numbers. """
def __init__(self, *args):
InputParam.__init__(self, *args)
- self.entry = input = gtk.Entry()
+ self.entry = input = gtk.Entry()
input.set_text(self.data_type.get_data())
- input.connect("changed", self.handle_changed)
- input.show()
- self.pack_start(input, False)
+ input.connect("changed", self._handle_changed)
+ self.pack_start(input, True)
self.get_text = input.get_text
# tool tip fun #
self.tp = gtk.Tooltips()
@@ -68,10 +63,9 @@
class FileParam(EntryParam):
""" Provide an entry box for filename and a button to browse for a
file. """
def __init__(self, *args):
- EntryParam.__init__(self, *args)
+ EntryParam.__init__(self, *args)
input = gtk.Button('...')
input.connect('clicked', self.handle_clicked)
- input.show()
self.pack_start(input, False)
def handle_clicked(self, widget=None):
@@ -94,7 +88,7 @@
if gtk.RESPONSE_OK == file_dialog.run(): #run the dialog
file_path = file_dialog.get_filename() #get the file
path
self.entry.set_text(file_path)
- self.handle_changed()
+ self._handle_changed()
file_dialog.destroy() #destroy the dialog
class EnumParam(InputParam):
@@ -107,8 +101,7 @@
input.add_attribute(cell, 'text', 0)
for cname in self.data_type.get_cnames_list():
input.append_text(cname)
input.set_active(int(self.data_type.get_data()))
- input.show()
- input.connect("changed", self.handle_changed)
+ input.connect("changed", self._handle_changed)
self.pack_start(input, False)
self.get_text = lambda: str(input.get_active()) #the get text
parses the selected index to a string
@@ -116,38 +109,54 @@
# A Parameter, hold a data type and a cname
######################################################################################################
-class GraphicalParam(Param):
-
- def get_input_object(self):
- """ Get the graphical gtk class to represent this parameter.
- Create the input object with this data type and the handle
changed method."""
+class GraphicalParam(Param.Param):
+ """The graphical parameter."""
+
+ def update(self):
+ """Called when an external change occurs.
+ Update the graphical input by calling the change handler."""
+ if self.input: self._handle_changed()
+
+ def get_input_object(self, callback=None):
+ """!
+ Get the graphical gtk class to represent this parameter.
+ Create the input object with this data type and the handle
changed method.
+ @param callback a function of one argument(this param) to be
called from the change handler
+ @return gtk input object
+ """
+ self.callback=callback
if self.get_data_type().get_base_type() ==
Enum().get_base_type(): input = EnumParam
elif self.get_data_type().get_base_type() ==
File().get_base_type(): input = FileParam
else: input = EntryParam
- self.input = input(self.get_data_type(), self.handle_changed)
- self.handle_changed()
+ self.input = input(self.get_data_type(), self._handle_changed)
+ self._handle_changed()
return self.input
- def handle_changed(self, widget=None):
- ''' if the input changed, write the inputs to the param.
'''
+ def _handle_changed(self, widget=None):
+ """When the input changes, write the inputs to the data type.
+ Finish by calling the exteral callback."""
data_type = self.get_data_type()
new_data = self.input.get_text()
old_data = data_type.get_data()
if old_data != new_data: data_type.set_data(new_data)
- # Set the markup on the label, red for errors in
cooresponding data type. #
+ #set the markup on the label, red for errors in corresponding
data type.
cname = self.get_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()))
+ if self.variable: cname = '<span
underline="low">%s</span>'%cname #alter format if the param is variable
+ if not data_type.is_valid(): self.input.set_markup('<span
foreground="red"><b>%s</b></span>'%cname)
+ else: self.input.set_markup(cname)
+ #set the tooltip
+ if self.input.tp: self.input.tp.set_tip(self.input.entry,
str(data_type))
+ #execute the external callback
+ if self.callback: self.callback(self)
def get_markup(self):
- """ Create a markup to display the Param as a label on the
SignalBlock.
+ """!
+ 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.
Otherwise, use parsed the data type and use its string
representation.
- If the data type is not valid, use a red foreground color.
"""
+ If the data type is not valid, use a red foreground color.
+ @return pango markup string
+ """
###########################################################################
# display logic for numbers
###########################################################################
@@ -197,7 +206,10 @@
else: return '<span foreground="red"><b>%s:</b>
error</span>'%self.cname
def get_layout(self):
- """ Create a layout based on the current Param's Markup.
"""
+ """!
+ Create a layout based on the current markup.
+ @return the pango layout
+ """
layout = gtk.DrawingArea().create_pango_layout('')
layout.set_markup(self.get_markup())
desc = pango.FontDescription(PARAM_FONT)
Modified: grc/trunk/src/Elements/GraphicalSignalBlock.py
===================================================================
--- grc/trunk/src/Elements/GraphicalSignalBlock.py 2007-06-29 17:29:46 UTC
(rev 5877)
+++ grc/trunk/src/Elements/GraphicalSignalBlock.py 2007-06-29 17:41:26 UTC
(rev 5878)
@@ -16,34 +16,31 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Elements/GraphicalSignalBlock.py
- Josh Blum
- the graphical signal block
-"""
address@hidden Elements.GraphicalSignalBlock
+#The graphical signal block.
address@hidden Josh Blum
-from SignalBlock import SignalBlock
+import SignalBlock
import Utils
import Colors
from GraphicalParam import GraphicalParam
-from GraphicalElement import GraphicalElement
+import GraphicalElement
from GraphicalSocket import GraphicalInputSocket,GraphicalOutputSocket
from Constants import *
-from DataType import Enum,Int
+from DataTypes import Enum,Int
import pygtk
pygtk.require('2.0')
import gtk
import pango
-class GraphicalSignalBlock(SignalBlock, GraphicalElement):
- """ SignalBlock is a graphical signal block. It is a Element with
an index from the list of
- possible signal blocks and graphical input/output elements. """
+class GraphicalSignalBlock(SignalBlock.SignalBlock,
GraphicalElement.GraphicalElement):
+ """The graphical signal block."""
param_constructor = GraphicalParam
input_socket_constructor = GraphicalInputSocket
output_socket_constructor = GraphicalOutputSocket
def update(self):
- """ update the block and parameters and sockets when a change
occurs """
+ """Update the block, parameters, and sockets when a change
occurs."""
self.clear()
self._adjust_sockets()
self._create_labels()
@@ -55,7 +52,7 @@
for socket in self.get_sockets(): socket.update()
def _create_labels(self):
- ''' Create the labels for the signal block. '''
+ """Create the labels for the signal block."""
layouts = list()
# create the main layout #
layout = gtk.DrawingArea().create_pango_layout(self.cname)
@@ -95,8 +92,11 @@
for j in range(height): vimage.put_pixel(j,
width-i-1, image.get_pixel(i, j))
def draw(self, window):
- """ draw the signal block with label and inputs/outputs
"""
- GraphicalElement.draw(self, window)
+ """!
+ Draw the signal block with label and inputs/outputs.
+ @param window the gtk window to draw on
+ """
+ GraphicalElement.GraphicalElement.draw(self, window)
gc = self.gc
gc.foreground = Colors.TXT_COLOR
X,Y = self.get_coordinate()
@@ -107,7 +107,11 @@
for socket in self.get_sockets(): socket.draw(window)
def is_valid(self):
- ''' This block is valid if all the params are valid and all
sockets connected. '''
+ """!
+ Is this block is valid/are all the params valid and all sockets
connected?
+ User preferences can override certain validity checks.
+ @return true if valid
+ """
import Preferences
if Preferences.check_params(): #preferences
for param in self.params:
@@ -118,8 +122,10 @@
return True
def modify_type_controller(self, direction):
- """ If a type controller was set, increment/decrement its index
by 1, use a % to stay in bounds.
- Direction may be +1 or -1"""
+ """!
+ If a type controller was set, increment/decrement its index by
1, use a % to stay in bounds.
+ @param direction +1 or -1
+ """
if self.type_controller != None and
self.type_controller.get_type() == Enum().get_type():
num_choices =
len(self.type_controller.get_cnames_list())
index = int(self.type_controller.get_data())
@@ -129,10 +135,12 @@
return False
def modify_socket_controller(self, direction):
- """ If a socket controller was set, increment/decrement its
data type by 1, DO NOT go out of bounds.
- Return True if operation was done. Return False if
operation could not be completed.
- If there is a controller on input and outputs, show
preference to the output controller.
- Direction may be +1 or -1. """
+ """!
+ If a socket controller was set, increment/decrement its data
type by 1, DO NOT go out of bounds.
+ If there is a controller on input and outputs, show preference
to the output controller.
+ @param direction +1 or -1
+ @return true if operation was done, false if operation could
not be completed.
+ """
# Get the socket controller, if there is an input and output
controller, use output #
socket_controller = None
if self.input_sockets_controller != None: socket_controller =
self.input_sockets_controller
Modified: grc/trunk/src/Elements/GraphicalSocket.py
===================================================================
--- grc/trunk/src/Elements/GraphicalSocket.py 2007-06-29 17:29:46 UTC (rev
5877)
+++ grc/trunk/src/Elements/GraphicalSocket.py 2007-06-29 17:41:26 UTC (rev
5878)
@@ -16,16 +16,14 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Elements/GraphicalSocket.py
- Josh Blum
- the graphical input/output sockets of the signal block
-"""
address@hidden Elements.GraphicalSocket
+#The graphical input/output sockets of the signal block.
address@hidden Josh Blum
import Utils
-from Socket import Socket
-from GraphicalElement import GraphicalElement
-from DataType import *
+import Socket
+import GraphicalElement
+from DataTypes import *
from Constants import *
import Colors
import pygtk
@@ -33,12 +31,11 @@
import gtk
import pango
-class GraphicalSocket(Socket, GraphicalElement):
- """ Socket is a graphical signal block input/output parameter.
- It has an index, input/output setting, and a data type. """
+class GraphicalSocket(Socket.Socket, GraphicalElement.GraphicalElement):
+ """The graphical socket."""
def update(self):
- """ update the coloring, a change may have occured in the
block params """
+ """Create new areas and labels for the socket."""
self.clear()
self.BG_color = {
Complex().get_type():Colors.COMPLEX_COLOR,
@@ -51,7 +48,7 @@
FloatVector().get_type():Colors.FLOAT_VECTOR_COLOR,
IntVector().get_type():Colors.INT_VECTOR_COLOR,
ShortVector().get_type():Colors.SHORT_VECTOR_COLOR,
- ByteVector().get_type():Colors.BYTE_VECTOR_COLOR,
+ ByteVector().get_type():Colors.BYTE_VECTOR_COLOR,
}[self.get_data_type().get_type()]
self._create_labels()
# add the input/output area for each rotation angle
#
@@ -86,7 +83,7 @@
if self.is_connected():
self.__set_connector_coordinates((x+conOff, y+1+SOCKET_WIDTH),(x+conOff,
y+SOCKET_WIDTH+conExtInitLen+conExtLen*index))
def _create_labels(self):
- ''' Create the labels for the socket. '''
+ """Create the labels for the socket."""
# create the layout #
layout = gtk.DrawingArea().create_pango_layout(self.cname)
desc = pango.FontDescription(SOCKET_FONT)
@@ -107,8 +104,11 @@
for j in range(h): vimage.put_pixel(j, w-i-1,
image.get_pixel(i, j))
def draw(self, window):
- """ draw the paramter with labels """
- GraphicalElement.draw(self, window, BG_color=self.BG_color)
+ """!
+ Draw the socket with a label.
+ @param window the gtk window to draw on
+ """
+ GraphicalElement.GraphicalElement.draw(self, window,
BG_color=self.BG_color)
gc = self.gc
gc.foreground = Colors.TXT_COLOR
X,Y = self.get_coordinate()
@@ -117,29 +117,42 @@
elif Utils.is_vertical(self.get_rotation()):
window.draw_image(gc, self.vertical_label, 0, 0, x+X+(SOCKET_HEIGHT-self.h)/2,
y+Y+(SOCKET_WIDTH-self.w)/2, -1, -1)
def __set_connector_coordinates(self, coor_inner, coor_outer,
rotation=None):
- """ Set the coordinates that connectors may attach to. """
+ """!
+ Set the coordinates that connectors may attach to.
+ The connector coordinates are associated with a rotation. If
rotation is not specified, the element's current rotation is used.
+ @param coor_inner the corrdinate on the socket
+ @param coor_outer the coordinate out of the socket
+ @param rotation rotation in degrees
+ """
if rotation == None: rotation = self.get_rotation()
self.connector_coordinates[rotation] = coor_inner, coor_outer
def get_connector_coordinates(self, rotation=None):
- """ Get the coordinates that Connections may attach to.
"""
+ """!
+ Get the coordinates that Connections may attach to.
+ @param rotation rotation in degrees
+ @return the connector coordinates ((xin, yin), (xout, yout))
tuple
+ """
if rotation == None: rotation = self.get_rotation()
X,Y = self.get_coordinate()
(x1,y1),(x2,y2)= self.connector_coordinates[rotation]
return (x1+X, y1+Y), (x2+X, y2+Y)
def get_connector_direction(self):
- """ the direction that the socket points in 0,90,180,270
- this is the rotation degree if the socket is an output or
- the rotation degree + 180 if the socket is an input """
+ """!
+ Get the direction that the socket points: 0,90,180,270.
+ This is the rotation degree if the socket is an output or
+ the rotation degree + 180 if the socket is an input.
+ @return the direction in degrees
+ """
if Utils.is_output_socket(self): return self.get_rotation()
elif Utils.is_input_socket(self): return (self.get_rotation() +
180)%360
class GraphicalInputSocket(GraphicalSocket):
- ''' The socket for input '''
- type = 'input socket'
+ """ The socket for input """
+ type = Socket.InputSocket.type
class GraphicalOutputSocket(GraphicalSocket):
- ''' The socket for output '''
- type = 'output socket'
+ """ The socket for output """
+ type = Socket.OutputSocket.type
\ No newline at end of file
Modified: grc/trunk/src/Elements/Param.py
===================================================================
--- grc/trunk/src/Elements/Param.py 2007-06-29 17:29:46 UTC (rev 5877)
+++ grc/trunk/src/Elements/Param.py 2007-06-29 17:41:26 UTC (rev 5878)
@@ -16,26 +16,36 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Elements/Param.py
- Josh Blum
- A signal block parameter.
-"""
address@hidden Elements.Param
+#A signal block parameter.
address@hidden Josh Blum
class Param:
- """ This class holds a single signal block parameter,
- a data type and a cname. """
- def __init__(self, cname, data_type):
- """ Initialize by setting the data type and cname. """
+ """A param holds a single signal block parameter: a data type and a
canonical name."""
+ def __init__(self, cname, data_type, variable=False):
+ """!
+ Param constructor. Set the data type and cname.
+ @param cname the canonical name
+ @param data_type the data type
+ @param variable true if the param can be changed at runtime
+ """
self.cname = cname
self.data_type = data_type
- self.input = None
+ ##the graphical input object
+ self.input = None
+ self.variable = variable
def get_cname(self):
- """ Get the cname. """
+ """!
+ Get the cname.
+ @return the canonical name
+ """
return self.cname
def get_data_type(self):
- """ Get the data type. """
+ """!
+ Get the data type.
+ @return the data type
+ """
return self.data_type
Modified: grc/trunk/src/Elements/SignalBlock.py
===================================================================
--- grc/trunk/src/Elements/SignalBlock.py 2007-06-29 17:29:46 UTC (rev
5877)
+++ grc/trunk/src/Elements/SignalBlock.py 2007-06-29 17:41:26 UTC (rev
5878)
@@ -16,34 +16,38 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Elements/SignalBlock.py
- Josh Blum
- The elemental signal block
-"""
address@hidden Elements.SignalBlock
+#The elemental signal block.
address@hidden Josh Blum
-from Element import Element
+import Element
import Utils
from Socket import OutputSocket,InputSocket
from Param import Param
-from DataType import Enum,Int,Vector
+from DataTypes import Enum,Int,Vector
-class SignalBlock(Element):
- """ SignalBlock is an Element with an index from the list of
- possible signal blocks and graphical input/output elements. """
+class SignalBlock(Element.Element):
+ """A SignalBlock is an Element with an index from the list of possible
signal blocks and input/output sockets."""
type = 'signal block'
param_constructor = Param
input_socket_constructor = InputSocket
output_socket_constructor = OutputSocket
def __init__(self, parent, coor, rotation, tag, id):
- """ initialize the signalblock, adding lists for sockets,
params """
- Element.__init__(self, parent, coor, rotation)
+ """!
+ SignalBlock constructor.
+ @param parent the flow graph
+ @param coordinate the (x,y) tuple
+ @param rotation the rotation in degrees
+ @param tag a string unique to signal blocks of this type
+ @param id a string unique to this signal block
+ """
+ Element.Element.__init__(self, parent, coor, rotation)
self.tag = tag
self.input_sockets = list()
self.output_sockets = list()
self.params = list()
self.displayed_params = list()
- self.cname = tag #this may change
+ self.cname = tag
self.id = id
self.input_sockets_controller = self.output_sockets_controller
= None
self.type_controller = None
@@ -51,70 +55,120 @@
self.docs = None
def get_docs(self):
- ''' Get a string with helpful hints, suggestions, and
documentation on using this block. '''
+ """!
+ Get a string with helpful hints, suggestions, and documentation
on using this block.
+ @return the documentation string
+ """
return self.docs
def set_docs(self, docs):
- ''' Set the documentation for this block. '''
+ """!
+ Set the documentation for this block.
+ @param docs the documentation string
+ """
self.docs = docs
def get_sockets(self):
- ''' Get a list of all sockets. '''
+ """!
+ Get all sockets for this signal block.
+ @return a list of sockets
+ """
return self.input_sockets + self.output_sockets
def get_input_socket(self, index):
- ''' Get the input socket at index. '''
+ """!
+ Get the input socket at index.
+ @param index the input socket index
+ @return an input socket
+ """
self._adjust_sockets() #a parameter change may have altered the
sockets
for socket in filter(Utils.is_input_socket, self.get_sockets()):
if socket.get_index() == index: return socket
return None
def get_output_socket(self, index):
- ''' Get the output socket at index. '''
+ """!
+ Get the output socket at index.
+ @param index the output socket index
+ @return an output socket
+ """
self._adjust_sockets() #a parameter change may have altered the
sockets
for socket in filter(Utils.is_output_socket,
self.get_sockets()):
if socket.get_index() == index: return socket
return None
def get_id(self):
- ''' Get the id. '''
+ """!
+ Get the id.
+ @return the id string
+ """
return self.id
def get_tag(self):
- ''' Get the tag. '''
+ """!
+ Get the tag.
+ @return the tag string
+ """
return self.tag
def get_cname(self):
- ''' Get the cname. '''
+ """!
+ Get the canonical name.
+ @return the cname string
+ """
return self.cname
def get_params(self):
- ''' Get the params list. '''
+ """!
+ Get all of the parameters for this signal block.
+ @return a list of parameters
+ """
return self.params
def get_num_input_sockets(self):
- ''' Get the number of sockets of input type. '''
+ """!
+ Get the number of sockets of input type.
+ @return an integer number of sockets
+ """
return len(self.input_sockets)
def get_num_output_sockets(self):
- ''' Get the number of sockets of output type. '''
+ """!
+ Get the number of sockets of output type.
+ @return an integer number of sockets
+ """
return len(self.output_sockets)
def add_input_socket(self, cname, data_type, optional=False, vlen=None):
- ''' Append an input socket with its cname and data type.
'''
+ """!
+ Add an input socket with its cname and data type.
+ @param cname the canonical name
+ @param data_type the data type
+ @param optional true if connections are optional
+ @param vlen the width of each sample (how many numbers are in
each sample?)
+ """
self.input_sockets.append(self.input_socket_constructor(self,
cname, self.get_num_input_sockets(), data_type, optional, vlen))
def add_output_socket(self, cname, data_type, optional=False,
vlen=None):
- ''' Append an output socket with its cname and data type.
'''
+ """!
+ Add an output socket with its cname and data type.
+ @param cname the canonical name
+ @param data_type the data type
+ @param optional true if connections are optional
+ @param vlen the width of each sample (how many numbers are in
each sample?)
+ """
self.output_sockets.append(self.output_socket_constructor(self,
cname, self.get_num_output_sockets(), data_type, optional, vlen))
- def add_param(self, cname, data_type, show_label=True, type=False,
output_sockets_controller=False, input_sockets_controller=False):
- ''' Append a param with its cname and data type.
- The show_label boolean flag tells the signal blocks to
display the parameter in its label.
- The type boolean flag registers this parameter to be
controlled via keypress.
- The output_sockets_controller registers this parameter
to set the number of output sockets.
- The input_sockets_controller registers this parameter
to set the number of input sockets. '''
- param = self.param_constructor(cname, data_type)
+ def add_param(self, cname, data_type, show_label=True, type=False,
output_sockets_controller=False, input_sockets_controller=False,
variable=False):
+ """!
+ Add a parameter with its cname and data type.
+ @param show_label true to display the parameter in the signal
block's label
+ @param type true if this param is an enum to be controlled via
a keypress
+ @param output_sockets_controller register this parameter to set
the number of output sockets
+ @param input_sockets_controller register this parameter to set
the number of input sockets
+ @param variable true if the param can be changed at runtime
+ """
+ param = self.param_constructor(cname, data_type, variable)
if show_label: self.displayed_params.append(param)
if type: self.type_controller = data_type
if output_sockets_controller: self.output_sockets_controller =
data_type
@@ -122,20 +176,27 @@
self.params.append(param)
def what_is_selected(self, coor):
- """ get the element that is selected, signal block itself or a
socket """
+ """!
+ Get the element that is selected.
+ @param coor the (x,y) tuple
+ @return this signal block, a socket, or None
+ """
for socket in self.get_sockets():
if socket.what_is_selected(coor) != None:
return socket.what_is_selected(coor)
- return Element.what_is_selected(self, coor)
+ return Element.Element.what_is_selected(self, coor)
def get_connections(self):
- ''' Get a set of all connections from every socket. '''
+ """!
+ Get all connections from every socket.
+ @return a set of connections
+ """
connections = list()
for socket in self.get_sockets(): connections = connections +
socket.get_connections()
return set(connections)
def _adjust_sockets(self):
- ''' Use the input/output socket controllers to adjust the
number of sockets. '''
+ """Use the input/output socket controllers to adjust the number
of sockets."""
for sockets_list,controller,constructor in (
(self.input_sockets, self.input_sockets_controller,
self.input_socket_constructor),
(self.output_sockets, self.output_sockets_controller,
self.output_socket_constructor)
@@ -160,11 +221,16 @@
## 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. '''
+ """!
+ 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.
+ @param fg the flow graph
+ @param nested_data the nested data
+ @param sb_contructor the contructor used to make a new signal
block
+ """
import ParseXML,Messages,SignalBlockDefs
find_data = ParseXML.find_data
signal_block = find_data([nested_data], 'signal_block')
Modified: grc/trunk/src/Elements/Socket.py
===================================================================
--- grc/trunk/src/Elements/Socket.py 2007-06-29 17:29:46 UTC (rev 5877)
+++ grc/trunk/src/Elements/Socket.py 2007-06-29 17:41:26 UTC (rev 5878)
@@ -16,23 +16,30 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Elements/Socket.py
- Josh Blum
- The elemental input and output sockets of a signal block
-"""
address@hidden Elements.Socket
+#The elemental input and output sockets of a signal block.
address@hidden Josh Blum
-from Element import Element
-import Utils,DataType
-from Connection import TooManyConnectionsException
+import Element
+import Utils,DataTypes
+from Connection import ConnectionException
-class Socket(Element):
- """ Socket is an input/output element of a signal block.
- It has an index, input/output setting, and a data type. """
+class Socket(Element.Element):
+ """
+ A Socket is an input/output element of a signal block.
+ It has an index, input/output setting, and a data type.
+ """
type = 'socket'
def __init__(self, parent, cname, index, data_type, optional=False,
vlen=None):
- """ Initialize the Element and set the parent, coor, and
rotation """
- Element.__init__(self, parent, (0,0), 0) #use zeros since the
parent contains this information
+ """!
+ Socket constructor.
+ @param parent the signal block
+ @param coordinate the (x,y) tuple
+ @param rotation the rotation in degrees
+ @param optional true if connections are optional
+ @param vlen the width of each sample (how many numbers are in
each sample?)
+ """
+ Element.Element.__init__(self, parent, (0,0), 0) #use zeros
since the parent contains this information
self.connections = list()
self.w = self.h = 0
self.index = index
@@ -43,71 +50,114 @@
self.vlen = vlen
def move(self, delta_coor):
- ''' Move the parent rather than self. '''
+ """!
+ Move the parent rather than self.
+ @param delta_corr the (delta_x, delta_y) tuple
+ """
self.get_parent().move(delta_coor)
def rotate(self, direction):
- ''' Rotate the parent rather than self. '''
+ """!
+ Rotate the parent rather than self.
+ @param direction degrees to rotate
+ """
self.get_parent().rotate(direction)
def get_coordinate(self):
- ''' Use the parent's coordinate rather th.an self '''
+ """!
+ Get the parent's coordinate rather than self.
+ @return the parents coordinate
+ """
return self.get_parent().get_coordinate()
def set_highlighted(self, highlight):
- ''' Set the parent highlight rather than self. '''
+ """!
+ Set the parent highlight rather than self.
+ @param highlight true to enable highlighting
+ """
self.get_parent().set_highlighted(highlight)
def is_highlighted(self):
- ''' Use the parent's is highlight rather than self. '''
+ """!
+ Get the parent's is highlight rather than self.
+ @return the parent's highlighting status
+ """
return self.get_parent().is_highlighted()
def is_valid(self):
- ''' True if connected or the optional flag is True. '''
+ """!
+ Is this socket valid?
+ @return true if connected or the optional flag is true
+ """
return self.optional or self.is_connected()
def get_rotation(self):
- ''' use the parent's rotation as our own '''
+ """!
+ Get the parent's rotation rather than self.
+ @return the parent's rotation
+ """
return self.get_parent().get_rotation()
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 DataType.vectorize(self.data_type)
+ """!
+ Get the data type. If the parsed vlen > 1, then return the
vectorized data type.
+ @return the data type
+ """
+ if self.vlen != None and self.vlen.is_valid() and
self.vlen.parse() > 1: return DataTypes.vectorize(self.data_type)
return self.data_type
def get_index(self):
- """ get the index 0, 1, 2... """
+ """!
+ Get the index of this socket.
+ @return the index (integer)
+ """
return self.index
def get_cname(self):
- """ get the cname """
+ """!
+ Get the canonical name.
+ @return the cname (string)
+ """
return self.cname
def is_connected(self):
- """ have a Connection (or more)? """
+ """!
+ Have one or more connections?
+ @return true if at least one connection exists
+ """
return len(self.connections) > 0
def connect(self, connection):
- """ Add a Connection to this socket,
- raise exception if this is an input with an existing
connection. """
- if Utils.is_input_socket(self) and self.is_connected(): raise
TooManyConnectionsException()
+ """!
+ Add a connection to this socket.
+ @param connection the connection
+ @throw TooManyConnectionsException input socket with an
existing connection
+ """
+ if Utils.is_input_socket(self) and self.is_connected():
+ raise ConnectionException, 'An input socket may only
have one connection!'
self.connections.append(connection)
self.update()
def disconnect(self, connection):
- """ Remove a Connection from this socket. """
+ """!
+ Remove a Connection from this socket.
+ @param connection the connection
+ """
self.connections.remove(connection)
self.update()
def get_connections(self):
- ''' Get the list of connections. '''
+ """!
+ Get all connections for this socket.
+ @return a list of connections
+ """
return self.connections
class InputSocket(Socket):
- ''' The socket for input '''
+ """ The socket for input """
type = 'input socket'
class OutputSocket(Socket):
- ''' The socket for output '''
+ """ The socket for output """
type = 'output socket'
\ No newline at end of file
Modified: grc/trunk/src/Elements/Utils.py
===================================================================
--- grc/trunk/src/Elements/Utils.py 2007-06-29 17:29:46 UTC (rev 5877)
+++ grc/trunk/src/Elements/Utils.py 2007-06-29 17:41:26 UTC (rev 5878)
@@ -16,24 +16,27 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Elements/Utils.py
- Shared fucntions and exceptions for flow graph elements.
-"""
address@hidden Elements.Utils
+#Shared functions for flow graph elements.
address@hidden Josh Blum
from SignalBlock import SignalBlock
from Socket import OutputSocket,InputSocket
from Connection import Connection
-# True if the rotation is 90 or 270 degrees. #
+## True if the rotation is 90 or 270 degrees.
is_vertical = lambda rot: rot in (90, 270)
-# True if the rotation is 0 or 180 degrees. #
+## True if the rotation is 0 or 180 degrees.
is_horizontal = lambda rot: rot in (0, 180)
def get_angle_from_coordinates((x1,y1), (x2,y2)):
- """ given two points, calculate the vector direction from point1 to
point2,
- directions are multiples of 90 degrees. """
+ """!
+ Given two points, calculate the vector direction from point1 to point2,
directions are multiples of 90 degrees.
+ @param (x1,y1) the coordinate of point 1
+ @param (x2,y2) the coordinate of point 2
+ @return the direction in degrees
+ """
if y1 == y2:#0 or 180
if x2 > x1: return 0
else: return 180
@@ -44,13 +47,14 @@
##################################################################
# Test methods for elements
#################################################################
-# test method for signal blocks #
+## test method for signal blocks
is_signal_block = lambda obj: obj!= None and obj.type == SignalBlock.type
-# test methods for sockets #
+## test methods for sockets @{
is_input_socket = lambda obj: obj!= None and obj.type == InputSocket.type
is_output_socket = lambda obj: obj!= None and obj.type == OutputSocket.type
is_socket = lambda obj: is_input_socket(obj) or is_output_socket(obj)
-# test method for connections #
address@hidden
+## test method for connections
is_connection = lambda obj: obj!= None and obj.type == Connection.type
Modified: grc/trunk/src/Elements/__init__.py
===================================================================
--- grc/trunk/src/Elements/__init__.py 2007-06-29 17:29:46 UTC (rev 5877)
+++ grc/trunk/src/Elements/__init__.py 2007-06-29 17:41:26 UTC (rev 5878)
@@ -16,10 +16,9 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Elements/__init__.py
- All elements used in a flow graph go into this package.
-"""
address@hidden Elements.__init__
+#All elements used in a flow graph go into this package.
address@hidden Josh Blum
import Utils
Modified: grc/trunk/src/ExecFlowGraph.py
===================================================================
--- grc/trunk/src/ExecFlowGraph.py 2007-06-29 17:29:46 UTC (rev 5877)
+++ grc/trunk/src/ExecFlowGraph.py 2007-06-29 17:41:26 UTC (rev 5878)
@@ -17,63 +17,84 @@
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.
-"""
address@hidden ExecFlowGraph
+#Use an xml input file to build and run a gnu radio flow graph without
graphics.
address@hidden Josh Blum
import ParseXML
import Variables
-import SignalBlockDefs
from Elements import SignalBlock
from gnuradio import gr
import os
-from Constants import DEFAULT_FILE_EXTENSION
+from Constants import FLOW_GRAPH_FILE_EXTENSION,MUTEX
from optparse import OptionParser
##############################################################################################
# Flow Graph Builder
##############################################################################################
-class FlowGraphBuilder(gr.flow_graph):
+class FlowGraphBuilder(gr.top_block):
""" 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)
+ def __init__(self, file_path):
+ gr.top_block.__init__(self, file_path)
+ #internal data structures
self.callbacks = list()
- self.var_keys = list()
- self.parse_nested_data(nested_data)
+ self.var_keys = list()
+ self.runtime = gr.runtime(self)
+ self.started = False
+ #build the flow graph
+
self._parse_nested_data(ParseXML.from_xml(ParseXML.from_file(file_path)))
+
+ def start(self):
+ """Start the flow graph."""
+ self.runtime.start()
+ self.started = True
+
+ def stop(self):
+ """Stop the flow graph."""
+ self.runtime.stop()
+ self.started = False
- def add_window(self, window, type='', title=''):
- ''' Empty method for adding a window in the GUI flow graph.
'''
+ def add_window(self, *args):
+ """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 '''
+ """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!'''
+Exiting!"""
exit(-1)
def add_callback(self, function, data_type_params):
- """ Register a callback function with its associated data.
"""
+ """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 each call back, parse all of the data and
+ call the registered callback function on that data."""
+ MUTEX.lock()
+ print "***\n\nCallback Time BEGIN\n\n***"
+ started = self.started
+ if started: self._hb.lock()
for function, data_type_params in self.callbacks:
+ print "***\nBegin A callback\n%s\n\n***"%function
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..."
+ except Exception, e: print "***\n\nerror parsing a
callback -> ignoring\n%s...\n\n***"%e
+ print "***\nEnd A callback\n***"
+ if started: self._hb.unlock()
+ print "***\n\nCallback Time END\n\n***"
+ MUTEX.unlock()
- 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. """
+ def _parse_nested_data(self, nested_data):
+ """!
+ Parse nested data from a flow graph file and build the
graphics.
+ @param nested_data the nested flow graph data
+ """
find_data = ParseXML.find_data
flow_graph = find_data([nested_data], 'flow_graph')
vars = find_data(flow_graph, 'vars')
@@ -94,22 +115,46 @@
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'))
+ input_signal_block =
signal_blocks_dict[input_signal_block_id]
+ output_signal_block =
signal_blocks_dict[output_signal_block_id]
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))
+ (output_signal_block, output_socket_index),
+ (input_signal_block, input_socket_index))
+##############################################################################################
+# Option Parser for running a flow graph
+##############################################################################################
+class FlowGraphOptionParser(OptionParser):
+ """This flow graph option parser provides a basic help,
+ and ensures that a flow graph is passed on the command line."""
+ def __init__(self):
+ """Create the base option parser and add usage and basic
options."""
+ usage = "usage: %prog [options]
flow_graph"+FLOW_GRAPH_FILE_EXTENSION
+ OptionParser.__init__(self, usage=usage)
+ self.add_option("-p", "--pid_file", action="store",
type="string", dest="pid_file", help="record process id")
+
+ def parse_args(self):
+ """Call the base parse_args, handle the basic options,
+ and ensure a flow graph was passed in args. Return the
(options, args)."""
+ (options, args) = OptionParser.parse_args(self)
+ if options.pid_file:
+ try: open(options.pid_file, 'w').write('%d\n' %
os.getpid())
+ except:
+ print '\nCould not create pid file:
"%s".\nExiting!'%options.pid_file
+ exit(-1)
+ if not len(args):
+ self.print_help()
+ exit(-1)
+ return options, args
+
+##############################################################################################
+# Main
+##############################################################################################
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()
+ parser = FlowGraphOptionParser()
+ (options, args) = parser.parse_args()
+ fg = FlowGraphBuilder(args[0])
+ fg.start()
+ raw_input('Flow Graph Running...\nPress Enter to Exit: ')
+ fg.stop()
\ No newline at end of file
Modified: grc/trunk/src/ExecFlowGraphGUI.py
===================================================================
--- grc/trunk/src/ExecFlowGraphGUI.py 2007-06-29 17:29:46 UTC (rev 5877)
+++ grc/trunk/src/ExecFlowGraphGUI.py 2007-06-29 17:41:26 UTC (rev 5878)
@@ -17,28 +17,31 @@
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.
-"""
address@hidden ExecFlowGraphGUI
+#Use an xml input file to build and run a gnu radio flow graph with wx GUI
elements.
address@hidden Josh Blum
import Variables
-from ExecFlowGraph import FlowGraphBuilder
+from ExecFlowGraph import FlowGraphBuilder,FlowGraphOptionParser
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. """
+ """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. """
+ """!
+ VariableControl contructor.
+ Create the slider, text box, and label given the variable key.
+ parse_callbacks is a method to update the registered signal
block callback methods.
+ @param parent the wx parent window
+ @param key the variable key
+ @param parse_callbacksa the callback function for variables
+ """
self.key = key
self.parse_callbacks = parse_callbacks
value, min, max, step = Variables.get_values(key)
@@ -46,7 +49,7 @@
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
+ 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)
@@ -64,69 +67,74 @@
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
+ 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
+ self._set_slider_value(value)#sets the slider's value
def get_slider_width(self):
- """ Get the width of the slider in pixels. """
+ """!
+ Get the width of the slider.
+ @return the slider width 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. """
+ def _get_slider_value(self):
+ """!
+ Read the value from the slider and,
+ translate the slider value into a real numerical value.
+ @return the numeric representation of the slider
+ """
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. """
+ def _set_slider_value(self, real_value):
+ """!
+ Translate the real numerical value into a slider value and,
+ write the value to the slider.
+ @param real_value the numeric value the slider should represent
+ """
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:
+ 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. """
+ 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)
+ new_value = str(self._get_slider_value()) #the new value
must be a string!
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)
+ if Variables.reregister(key, new_value):
self.parse_callbacks()
+ except Exception, e: print 'Error in handle scroll: "%s".'%e
+ self._set_slider_value(Variables.get_value(key))
+ self.text_box.SetValue(Variables.get_value(key))
- 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. """
+ 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)
+ if Variables.reregister(key, new_value):
self.parse_callbacks()
+ except Exception, e: print 'Error in handle enter: "%s".'%e
+ self._set_slider_value(Variables.get_value(key))
+ self.text_box.SetValue(Variables.get_value(key))
##############################################################################################
# Flow Graph Frame
##############################################################################################
class FlowGraphFrame(wx.Frame, FlowGraphBuilder):
- """ A FlowGraphFrame is a wx.Frame and a 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. """
+ and starts the flow graph."""
def __init__(self, file_path):
+ """!
+ FlowGraphFrame contructor.
+ @param file_path the file path to the flow graph
+ """
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))
@@ -142,35 +150,44 @@
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)
+ self.Bind(wx.EVT_CLOSE, self._quit)
# fill in all the sliders and graphs #
FlowGraphBuilder.__init__(self, file_path)
- self.create_sliders()
+ 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. '''
+ 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. '''
+ """!
+ Register the graphical sink window with a unique key.
+ The key is based on the type and title.
+ @param window the new gui window
+ @param type an integer used to categorize the window
+ @param title the title of the window
+ """
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.
'''
+ """!
+ Get the panel that will parent the graphical blocks.
+ @return the wx panel
+ """
return self.panel
- def create_sliders(self):
- ''' Using the list of variable keys imported by the builder,
- create sliders for those variables with ranges. '''
+ 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)
@@ -189,33 +206,38 @@
# Flow Graph App
##############################################################################################
class FlowGraphApp(wx.App):
- """ The FlowGraphApp is the wx.App containing the FlowGraphFrame.
"""
+ """The FlowGraphApp is the wx.App containing the FlowGraphFrame."""
def __init__(self, flow_graph_file_path):
+ """!
+ FlowGraphApp constructor.
+ @param flow_graph_file_path the file path to the flow graph
+ """
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. """
+ """!
+ Create the top level flow graph frame.
+ If the creation of the frame fails, exit with error.
+ @return true if the flow graph frame is created
+ """
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')
+ except Exception:
+ import traceback
+ traceback.print_exc()
sys.exit(1)
-
+
+##############################################################################################
+# Main
+##############################################################################################
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 = FlowGraphOptionParser()
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()
+ 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
\ No newline at end of file
Copied: grc/trunk/src/ExecFlowGraphXMLRPC.py (from rev 5877,
grc/branches/jblum_work/src/ExecFlowGraphXMLRPC.py)
===================================================================
--- grc/trunk/src/ExecFlowGraphXMLRPC.py (rev 0)
+++ grc/trunk/src/ExecFlowGraphXMLRPC.py 2007-06-29 17:41:26 UTC (rev
5878)
@@ -0,0 +1,93 @@
+#! /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
+"""
address@hidden ExecFlowGraphXMLRPC
+#Use a xml input file to build and run a gnu radio flow graph without graphics.
+#Create an XMLRPC sever to control the running flow graph.
address@hidden @n XMLRPC access functions:
address@hidden var_has_range(key): returns true if the variable represented by
key has a range @n
address@hidden var_exists(key): returns true if the variable represented by key
exists @n
address@hidden get_var_key_list(): returns a list of keys representing all
registered variables @n
address@hidden get_var(key): returns the value of the variable represented by
key @n
address@hidden get_var_range(key): returns the (min,max) of the variable
represented by key @n
address@hidden set_var(key, new_value): sets the new value of the variable
represented by key @n
address@hidden start_fg(): starts the flow graph @n
address@hidden stop_fg(): stops the flow graph @n
+#
address@hidden Josh Blum
+
+from SimpleXMLRPCServer import SimpleXMLRPCServer
+from xmlrpclib import Error
+from ExecFlowGraph import FlowGraphBuilder,FlowGraphOptionParser
+import Variables
+
+DEFAULT_ADDR = 'localhost'
+DEFAULT_PORT = 3030
+
+##############################################################################################
+# Flow Graph Access
+##############################################################################################
+class FlowGraphAccess(FlowGraphBuilder):
+ """Implement a flow graph builder, and provide access functions for the
xmlrpc server."""
+
+ def get_var_range(self, key):
+ """!
+ Get the min and the max of a variable (strings).
+ @return the min,max tuple
+ """
+ value, min, max, step = Variables.get_values(key)
+ return str(min), str(max)
+
+ def set_var(self, key, new_value):
+ """!
+ Register the new value and call parse callbacks.
+ Value can be any type (will be cast to a string).
+ @param key the variable key
+ @param new_value the new value for the variable
+ @return the new value as a string or the old value if failed
+ """
+ try:
+ if Variables.reregister(key, str(new_value)):
self.parse_callbacks()
+ except: pass
+ return Variables.get_value(key)
+
+##############################################################################################
+# Main
+##############################################################################################
+if __name__ == '__main__':
+ parser = FlowGraphOptionParser()
+ parser.add_option("-a", "--addr", action="store", type="string",
dest="addr", default=DEFAULT_ADDR, help='bind address for XMLRPC server')
+ parser.add_option("-P", "--port", action="store", type="int",
dest="port", default=DEFAULT_PORT, help='tcp port for XMLRPC server')
+ (options, args) = parser.parse_args()
+ fg = FlowGraphAccess(args[0]) #create the flow graph
+ server = SimpleXMLRPCServer((options.addr, options.port)) #create
the xmlrpc server
+ # register access methods #
+ server.register_function(lambda key: bool(Variables.is_ranged(key)),
"var_has_range")
+ server.register_function(lambda key: bool(Variables.has_key(key)),
"var_exists")
+ server.register_function(lambda: fg.var_keys, "get_var_key_list")
+ server.register_function(lambda key: str(Variables.get_value(key)),
"get_var")
+ server.register_function(fg.get_var_range, "get_var_range")
+ server.register_function(fg.set_var, "set_var")
+ server.register_function(fg.start, "start_fg")
+ server.register_function(fg.stop, "stop_fg")
+ fg.start() #start the flow graph
+ print 'Starting XMLRPC server on address: "%s" and port:
"%d"'%(options.addr, options.port)
+ server.serve_forever() #start the xmlrpc server
+
+
\ No newline at end of file
Property changes on: grc/trunk/src/Graphics
___________________________________________________________________
Name: svn:ignore
- *.pyc
Modified: grc/trunk/src/Graphics/Bars.py
===================================================================
--- grc/trunk/src/Graphics/Bars.py 2007-06-29 17:29:46 UTC (rev 5877)
+++ grc/trunk/src/Graphics/Bars.py 2007-06-29 17:41:26 UTC (rev 5878)
@@ -16,18 +16,17 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Graphics/Bars.py
- Josh Blum
- this file will create the GUI's toolbar and menubar
-"""
address@hidden Graphics.Bars
+#Create the GUI's toolbar and menubar
address@hidden Josh Blum
from Actions import *
import pygtk
pygtk.require('2.0')
import gtk
-TOOLBAR_LIST = [
+##The list of actions for the toolbar.
+TOOLBAR_LIST = (
FLOW_GRAPH_NEW,
FLOW_GRAPH_OPEN,
FLOW_GRAPH_SAVE,
@@ -43,9 +42,10 @@
ELEMENT_DELETE,
SIGNAL_BLOCK_ROTATE_LEFT,
SIGNAL_BLOCK_ROTATE_RIGHT,
-]
-
-MENU_BAR_LIST = [
+)
+
+##The list of actions and categories for the menu bar.
+MENU_BAR_LIST = (
(gtk.Action('File', '_File', None, None), [
FLOW_GRAPH_NEW,
FLOW_GRAPH_OPEN,
@@ -80,15 +80,14 @@
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 """
+ """The gtk toolbar with actions added from the toolbar list."""
def __init__(self):
- """ Parse the list of action names in the toolbar list.
Look up the action for each name
- in the action list and add it to the toolbar """
+ """Parse the list of action names in the toolbar list.
+ Look up the action for each name in the action list and
add it to the toolbar."""
gtk.Toolbar.__init__(self)
self.set_style(gtk.TOOLBAR_ICONS)
for action_name in TOOLBAR_LIST:
@@ -104,11 +103,10 @@
class MenuBar(gtk.MenuBar):
- """ MenuBar is a gtk MenuBar with actions added from the menuBar
list """
+ """The gtk menu bar with actions added from the menu bar list."""
def __init__(self):
- """ Parse the list of submenus from the menubar list. For
each submenu, get a list of action names.
- Look up the action for each name in the action list and add it
to the submenu.
- Add the submenu to the menuBar """
+ """Parse the list of submenus from the menubar list. For each
submenu, get a list of action names.
+ Look up the action for each name in the action list and add it
to the submenu. Add the submenu to the menu bar."""
gtk.MenuBar.__init__(self)
for main_action,action_names in MENU_BAR_LIST:
# Create the MenuItem
Modified: grc/trunk/src/Graphics/Dialogs.py
===================================================================
--- grc/trunk/src/Graphics/Dialogs.py 2007-06-29 17:29:46 UTC (rev 5877)
+++ grc/trunk/src/Graphics/Dialogs.py 2007-06-29 17:41:26 UTC (rev 5878)
@@ -16,25 +16,26 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Graphics/Dialogs.py
- Josh Blum
- Misc Dialogs
-"""
address@hidden Graphics.Dialogs
+#Misc dialogs.
address@hidden Josh Blum
import Colors
import pygtk
pygtk.require('2.0')
import gtk
-from DataType import *
+from DataTypes import *
from Constants import *
from Elements import GraphicalParam
import Preferences
class TextDisplay(gtk.TextView):
- """ A non editable gtk text view. """
+ """A non editable gtk text view."""
def __init__(self, text=''):
- """ Create a new TextDisplay with the given text. """
+ """!
+ TextDisplay constructor.
+ @param text the text to display (string)
+ """
text_buffer = gtk.TextBuffer()
text_buffer.set_text(text)
self.set_text = text_buffer.set_text
@@ -42,23 +43,21 @@
gtk.TextView.__init__(self, text_buffer)
self.set_editable(False)
self.set_cursor_visible(False)
- self.set_wrap_mode(gtk.WRAP_WORD)
- self.show()
+ self.set_wrap_mode(gtk.WRAP_WORD)
######################################################################################################
class PreferencesDialog(gtk.Dialog):
- """ A dialog box to display each preference parameter. """
+ """A dialog box to display the preferences."""
def __init__(self):
+ """PreferencesDialog constructor."""
gtk.Dialog.__init__(self, buttons=('gtk-close',
gtk.RESPONSE_CLOSE))
self.set_title("Preferences")
self.set_size_request(MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT)
vbox = gtk.VBox()
- vbox.show()
for title,notes,params in Preferences.PREFS_LIST:
if title:
label = gtk.Label()
- label.set_markup('<b> ----- '+title+' -----
</b>')
- label.show()
+ label.set_markup('<b> ----- '+title+' -----
</b>')
vbox.pack_start(label, False, padding=5)
for param in params:
vbox.pack_start(param.get_input_object(), False)
if notes: vbox.pack_start(TextDisplay(notes),
False, padding=5)
@@ -66,36 +65,40 @@
scrolled_window = gtk.ScrolledWindow()
scrolled_window.set_policy(gtk.POLICY_AUTOMATIC,
gtk.POLICY_AUTOMATIC)
scrolled_window.add_with_viewport(vbox)
- scrolled_window.show()
self.vbox.pack_start(scrolled_window, True)
+ self.show_all()
self.run()
self.destroy()
######################################################################################################
class FlowGraphWindowSizeDialog(gtk.Dialog):
- """ A dialog box to set the window size, width and heigh in pixels.
"""
- def __init__(self, flow_graph):
+ """A dialog box to set the window size, width and heigh in pixels."""
+ def __init__(self, dimensions):
+ """!
+ FlowGraphWindowSizeDialog constructor.
+ @param dimensions the (width,height) tuple from the flow graph
+ """
gtk.Dialog.__init__(self, buttons=('gtk-close',
gtk.RESPONSE_CLOSE))
- self.flow_graph = flow_graph
self.set_title("Set the Window Size")
# the helpful dimension constraints label #
- windowSizeDesc = '''
+ window_size_label = gtk.Label()
+ window_size_label.set_markup("""<i>
Minimum window (width/height) in pixels is (%d/%d).
Maximum window (width/height) in pixels is (%d/%d).
-'''%(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT, MAX_WINDOW_WIDTH, MAX_WINDOW_HEIGHT)
- windowSizeDescLabel = gtk.Label()
- windowSizeDescLabel.set_markup('<i>'+windowSizeDesc+'</i>')
- windowSizeDescLabel.show()
- self.vbox.pack_end(windowSizeDescLabel, False)
- self.original_dimensions = width,height =
self.flow_graph.get_size_request() # get the window dimensions
+</i>"""%(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT, MAX_WINDOW_WIDTH,
MAX_WINDOW_HEIGHT))
+ self.vbox.pack_end(window_size_label, False)
+ self.original_dimensions = width,height = dimensions
self.width = Int(width, min=MIN_WINDOW_WIDTH,
max=MAX_WINDOW_WIDTH)
self.height = Int(height, min=MIN_WINDOW_HEIGHT,
max=MAX_WINDOW_HEIGHT)
self.vbox.pack_start(GraphicalParam('width (pixels)',
self.width).get_input_object(), False)
self.vbox.pack_start(GraphicalParam('height (pixels)',
self.height).get_input_object(), False)
+ self.show_all()
def run(self):
- ''' Return the new dimensions rather than a response.
- If the dimensions were invalid, return None. '''
+ """!
+ Get the new dimensions.
+ @return the new dimensions (width,height) or None if invalid.
+ """
self.dimensions = None
gtk.Dialog.run(self)
if self.width.is_valid() and self.height.is_valid():
@@ -106,14 +109,18 @@
######################################################################################################
class LooseChangesMessage(gtk.MessageDialog):
- """ This message dialog will ask about discarding unsaved changes.
"""
+ """Message dialog to ask about discarding unsaved changes."""
def __init__(self):
+ """LooseChangesMessage constructor."""
gtk.MessageDialog.__init__(self, None, gtk.DIALOG_MODAL,
gtk.MESSAGE_WARNING,
gtk.BUTTONS_OK_CANCEL, "Would you like to discard your
unsaved changes?")
self.set_title('Unsaved Changes!')
def run(self):
- """ call parent class run(), destroy the dialog. Return
True if OK was clicked, or False. """
+ """!
+ Get the user's response.
+ @return true if ok was clicked, otherwise false
+ """
response = gtk.MessageDialog.run(self)
self.destroy()
if response == gtk.RESPONSE_OK: return True
@@ -121,8 +128,9 @@
######################################################################################################
class AboutDialog(gtk.AboutDialog):
- """ cute little about dialog """
+ """A cute little about dialog."""
def __init__(self):
+ """AboutDialog constructor."""
gtk.AboutDialog.__init__(self)
self.set_version(VERSION)
self.set_name(MAIN_WINDOW_PREFIX)
@@ -146,62 +154,77 @@
######################################################################################################
class DataTypeColorsDialog(gtk.Dialog):
- """ Display each data type with its associated color. """
+ """Display each data type with its associated color."""
def __init__(self):
+ """DataTypeColorsDialog constructor."""
gtk.Dialog.__init__(self, buttons=('gtk-close',
gtk.RESPONSE_CLOSE))
self.set_title('Colors')
self.set_size_request(150, -1)
- for dt_name, color in (('Complex', Colors.COMPLEX_COLOR_SPEC),
-
('Float', Colors.FLOAT_COLOR_SPEC),
-
('Int', Colors.INT_COLOR_SPEC),
-
('Short', Colors.SHORT_COLOR_SPEC),
-
('Byte', Colors.BYTE_COLOR_SPEC),
-
# and for the vectors #
-
('Complex Vector', Colors.COMPLEX_VECTOR_COLOR_SPEC),
-
('Float Vector', Colors.FLOAT_VECTOR_COLOR_SPEC),
-
('Int Vector', Colors.INT_VECTOR_COLOR_SPEC),
-
('Short Vector', Colors.SHORT_VECTOR_COLOR_SPEC),
-
('Byte Vector', Colors.BYTE_VECTOR_COLOR_SPEC),):
- label = gtk.Label('')
- label.set_markup('<span
background="%s">%s</span>'%(color, dt_name))
- label.show()
- self.vbox.pack_start(label)
+ markup = ''
+ for color_spec in (
+ 'Regular Types:',
+ ('Complex', Colors.COMPLEX_COLOR_SPEC),
+ ('Float', Colors.FLOAT_COLOR_SPEC),
+ ('Int', Colors.INT_COLOR_SPEC),
+ ('Short', Colors.SHORT_COLOR_SPEC),
+ ('Byte', Colors.BYTE_COLOR_SPEC),
+ 'Vector Types:',
+ ('Complex Vector', Colors.COMPLEX_VECTOR_COLOR_SPEC),
+ ('Float Vector', Colors.FLOAT_VECTOR_COLOR_SPEC),
+ ('Int Vector', Colors.INT_VECTOR_COLOR_SPEC),
+ ('Short Vector', Colors.SHORT_VECTOR_COLOR_SPEC),
+ ('Byte Vector', Colors.BYTE_VECTOR_COLOR_SPEC),
+ ):
+ width = 20 #width in monospace characters
+ if type(color_spec) == type(str()): markup =
'%s\n\n<b>%s</b>'%(markup, color_spec.center(width, ' '))
+ else:
+ tag,spec = color_spec
+ markup = '%s\n<span
background="%s">%s</span>'%(markup, spec, tag.center(width, ' '))
+ label = gtk.Label()
+ label.set_markup('<tt>%s</tt>\n'%markup[1:]) #strip 1st
newline, append newline
+ self.vbox.pack_start(label, False)
+ self.show_all()
self.run()
self.destroy()
######################################################################################################
class HotKeysDialog(gtk.Dialog):
- """ Display each action with the associated hotkey. """
+ """Display each action with the associated hotkey."""
def __init__(self):
+ """HotKeysDialog constructor."""
gtk.Dialog.__init__(self, buttons=('gtk-close',
gtk.RESPONSE_CLOSE))
self.set_title('Hot Keys')
- for action, hotkey in (('New Flow Graph', 'Ctrl + n'),
-
('Open Flow Graph', 'Ctrl + o'),
-
('Save Flow Graph', 'Ctrl + s'),
-
('Undo Change', 'Ctrl + z'),
-
('Redo Change', 'Ctrl + y'),
-
('Redo Change', 'Ctrl + Z'),
-
('Delete Block', 'Delete'),
-
('Rotate Block', 'Right'),
-
('Rotate Block', 'Left'),
-
('Modify Data Type', 'Up'),
-
('Modify Data Type', 'Down'),
-
('Add a Socket', '+'),
-
('Remove a Socket', '-'),
-
('Close GraphicalParams Dialog', 'Esc'),
-
('Flow Graph Run', 'F5'),
-
('Flow Graph Stop', 'F7'),
-
('Screen Shot', 'PrintScreen'),):
- label = gtk.Label('')
- label.set_markup('<b>%s:</b> %s'%(action, hotkey))
- label.show()
- self.vbox.pack_start(label)
+ markup = ''
+ for action, hotkey in (
+ ('New Flow Graph', 'Ctrl + n'),
+ ('Open Flow Graph', 'Ctrl + o'),
+ ('Save Flow Graph', 'Ctrl + s'),
+ ('Undo Change', 'Ctrl + z'),
+ ('Redo Change', 'Ctrl + y'),
+ ('Redo Change', 'Ctrl + Z'),
+ ('Delete Block', 'Delete'),
+ ('Rotate Block', 'Right'),
+ ('Rotate Block', 'Left'),
+ ('Modify Data Type', 'Up'),
+ ('Modify Data Type', 'Down'),
+ ('Add a Socket', '+'),
+ ('Remove a Socket', '-'),
+ ('Close Dialog', 'Esc'),
+ ('Flow Graph Run', 'F5'),
+ ('Flow Graph Stop', 'F7'),
+ ('Screen Shot', 'PrintScreen'),
+ ): markup = '%s\n<b>%s:</b>%s'%(markup, action,
hotkey.rjust(25-len(action),' '))
+ label = gtk.Label()
+ label.set_markup('<tt>%s</tt>\n'%markup) #append newline
+ self.vbox.pack_start(label, False)
+ self.show_all()
self.run()
self.destroy()
######################################################################################################
class MathExprDialog(gtk.Dialog):
- """ A dialog to test math expressions for the parser. """
+ """A dialog to test math expressions for the parser."""
+ ##the help message
HELP_MSG = """\
<b>Operators - Complex <i>(complex arguments)</i></b>
+ - * / ^
@@ -233,39 +256,31 @@
<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. """
+ """MathExprDialog constrcutor. 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('')
+ # create the entry box and give it the change handler #
+ self.param = GraphicalParam('Expression', RawExpr(''))
+ self.input_obj =
self.param.get_input_object(self._handle_changed)
+ self.vbox.pack_start(self.input_obj, False)
# 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.show_all()
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)
+ def _handle_changed(self, param=None):
+ """Handle changed in the param's entry box by updating the text
box."""
+ self.text_box.set_text(str(self.param.get_data_type()))
\ No newline at end of file
Copied: grc/trunk/src/Graphics/FileDialogs.py (from rev 5877,
grc/branches/jblum_work/src/Graphics/FileDialogs.py)
===================================================================
--- grc/trunk/src/Graphics/FileDialogs.py (rev 0)
+++ grc/trunk/src/Graphics/FileDialogs.py 2007-06-29 17:41:26 UTC (rev
5878)
@@ -0,0 +1,107 @@
+"""
+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
+"""
address@hidden Graphics.FileDialogs
+#The open/save dialog for flow graph fFileDialogiles and screen shots.
address@hidden Josh Blum
+
+import pygtk
+pygtk.require('2.0')
+import gtk
+from Constants import
DEFAULT_FILE_PATH,FLOW_GRAPH_FILE_EXTENSION,IMAGE_FILE_EXTENSION,NEW_FLOGRAPH_TITLE
+from os import path
+
+OPEN_FLOW_GRAPH = 'open flow graph'
+SAVE_FLOW_GRAPH = 'save flow graph'
+SAVE_IMAGE = 'save image'
+
+class FileDialog(gtk.FileChooserDialog):
+ """A dialog box to save or open flow graph files. This is a base class,
do not use."""
+
+ ##the filter for flow graph files
+ flow_graph_files_filter = gtk.FileFilter()
+ flow_graph_files_filter.set_name('FG Files')
+ flow_graph_files_filter.add_pattern('*'+FLOW_GRAPH_FILE_EXTENSION)
+
+ ##the filter for image files
+ image_files_filter = gtk.FileFilter()
+ image_files_filter.set_name('Image Files')
+ image_files_filter.add_pattern('*'+IMAGE_FILE_EXTENSION)
+ #image_files_filter.add_pixbuf_formats()
+
+ ##the filter for all files
+ all_files_filter = gtk.FileFilter()
+ all_files_filter.set_name('All Files')
+ all_files_filter.add_pattern('*')
+
+ def __init__(self, current_file_path):
+ """!
+ FileDialog constructor.
+ Create a new gtk.FileChooserDialog, type specifies what filter
to use:
+ open and save are for flow graphs, save image is for
screenshots.
+ @param current_file_path the current directory
+ """
+ if current_file_path == '': current_file_path =
DEFAULT_FILE_PATH+NEW_FLOGRAPH_TITLE+FLOW_GRAPH_FILE_EXTENSION
+ if self.type == OPEN_FLOW_GRAPH:
+ gtk.FileChooserDialog.__init__(self, 'Open a Flow Graph
from a File...', None,
+ gtk.FILE_CHOOSER_ACTION_OPEN,
('gtk-cancel',gtk.RESPONSE_CANCEL,'gtk-open',gtk.RESPONSE_OK))
+ self.add_filter(self.flow_graph_files_filter)
+ self.set_filter(self.flow_graph_files_filter)
+ self.add_filter(self.all_files_filter)
+ elif self.type == SAVE_FLOW_GRAPH:
+ gtk.FileChooserDialog.__init__(self, 'Save a Flow Graph
to a File...', None,
+ gtk.FILE_CHOOSER_ACTION_SAVE,
('gtk-cancel',gtk.RESPONSE_CANCEL, 'gtk-save',gtk.RESPONSE_OK))
+ #self.set_do_overwrite_confirmation(True) #enable this
when u get it working with auto-extension
+ self.add_filter(self.flow_graph_files_filter)
+ self.set_filter(self.flow_graph_files_filter)
+ self.add_filter(self.all_files_filter)
+ self.set_current_name(path.basename(current_file_path))
#show the current filename
+ elif self.type == SAVE_IMAGE:
+ gtk.FileChooserDialog.__init__(self, 'Save a Flow Graph
Screen Shot...', None,
+ gtk.FILE_CHOOSER_ACTION_SAVE,
('gtk-cancel',gtk.RESPONSE_CANCEL, 'gtk-save',gtk.RESPONSE_OK))
+ #self.set_do_overwrite_confirmation(True) #enable this
when u get it working with auto-extension
+ self.add_filter(self.image_files_filter)
+ self.set_filter(self.image_files_filter)
+ self.add_filter(self.all_files_filter)
+ current_file_path = current_file_path +
IMAGE_FILE_EXTENSION
+ self.set_current_name(path.basename(current_file_path))
#show the current filename
+ self.set_current_folder(path.dirname(current_file_path))
#current directory
+ #self.set_show_hidden(False) #doesnt seem to work ;-)
+ self.set_select_multiple(False)
+ self.set_local_only(True)
+
+ def run(self):
+ """!
+ Call run, wait for user response, and destroy the dialog.
+ @return the filename or None if a close/cancel occured.
+ """
+ response = gtk.FileChooserDialog.run(self)
+ if response == gtk.RESPONSE_OK:
+ filename = self.get_filename()
+ if
filename[len(filename)-len(FLOW_GRAPH_FILE_EXTENSION):] !=
FLOW_GRAPH_FILE_EXTENSION and\
+ self.flow_graph_files_filter ==
self.get_filter(): filename = filename + FLOW_GRAPH_FILE_EXTENSION
+ elif filename[len(filename)-len(IMAGE_FILE_EXTENSION):]
!= IMAGE_FILE_EXTENSION and\
+ self.image_files_filter == self.get_filter():
filename = filename + IMAGE_FILE_EXTENSION
+ else: filename = None
+ self.destroy()
+ return filename
+
+class OpenFlowGraphFileDialog(FileDialog): type = OPEN_FLOW_GRAPH
+class SaveFlowGraphFileDialog(FileDialog): type = SAVE_FLOW_GRAPH
+class SaveImageFileDialog(FileDialog): type = SAVE_IMAGE
+
Modified: grc/trunk/src/Graphics/FlowGraph.py
===================================================================
--- grc/trunk/src/Graphics/FlowGraph.py 2007-06-29 17:29:46 UTC (rev 5877)
+++ grc/trunk/src/Graphics/FlowGraph.py 2007-06-29 17:41:26 UTC (rev 5878)
@@ -16,18 +16,16 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Graphics/FlowGraph.py
- Josh Blum
- flow graph structure for storing signal blocks and their connections
-"""
address@hidden Graphics.FlowGraph
+#A flow graph structure for storing signal blocks and their connections.
address@hidden Josh Blum
from Constants import *
from Actions import *
from Colors import BACKGROUND_COLOR, TXT_COLOR
from Elements import GraphicalSignalBlock,GraphicalConnection
from Elements import Utils
-from Elements.Connection import
InvalidConnectionException,TooManyConnectionsException
+from Elements.Connection import ConnectionException
import Variables
import pygtk
pygtk.require('2.0')
@@ -42,29 +40,34 @@
import Messages
class FlowGraph(gtk.DrawingArea):
- """ FlowGraph is the data structure to store graphical signal
blocks, their graphical input/output
- parameters, and the connections between inputs and outputs. """
+ """FlowGraph is the data structure to store graphical signal blocks,
+ their graphical input/output parameters, and the connections between
inputs and outputs."""
signal_block_constructor = GraphicalSignalBlock
connection_contructor = GraphicalConnection
def __init__(self, handle_states, variable_modification_window):
- """ Create a list for signal blocks and connections. Connect
mouse handlers. """
+ """!
+ FlowGraph contructor.
+ Create a list for signal blocks and connections. Connect mouse
handlers.
+ @param handle_states the callback function
+ @param variable_modification_window var mod window also for
callbacks
+ """
self.elements = list()
self.remove_element = lambda e: self.elements.remove(e)
self.gc = None
self.handle_states = handle_states
self.variable_modification_window = variable_modification_window
gtk.DrawingArea.__init__(self)
- self.connect('expose-event', self.__on_expose)
- self.connect('motion-notify-event',
self.__motion_notify_event_cb)
- self.connect('button-press-event',
self.__button_press_event_cb)
- self.connect('button-release-event',
self.__button_release_event_cb)
+ self.connect('expose-event', self._handle_window_expose)
+ self.connect('motion-notify-event', self._handle_mouse_motion)
+ self.connect('button-press-event',
self._handle_mouse_button_press)
+ self.connect('button-release-event',
self._handle_mouse_button_release)
self.set_events(gtk.gdk.BUTTON_PRESS_MASK |
gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.BUTTON_RELEASE_MASK\
| gtk.gdk.LEAVE_NOTIFY_MASK | gtk.gdk.ENTER_NOTIFY_MASK)
# setup the focus flag #
self.focus_flag = False
self.get_focus_flag = lambda: self.focus_flag
- self.connect("leave-notify-event", self.__handle_focus_event,
False)
- self.connect("enter-notify-event", self.__handle_focus_event,
True)
+ self.connect("leave-notify-event", self._handle_focus_event,
False)
+ self.connect("enter-notify-event", self._handle_focus_event,
True)
# important vars dealing with mouse event tracking
#
self.has_moved = False
self.mouse_pressed = False
@@ -73,14 +76,16 @@
self.is_selected = lambda: self.selected_element != None
self.count = 0
self.pixmap = None
- self.show()
- def __handle_focus_event(self, widget, event, focus_flag):
- """ Record the focus state of the flow graph window. """
+ def _handle_focus_event(self, widget, event, focus_flag):
+ """Record the focus state of the flow graph window."""
self.focus_flag = focus_flag
def add_signal_block(self, tag):
- ''' Add a signal block of the given tag to this flow graph.
'''
+ """!
+ Add a signal block of the given tag to this flow graph.
+ @param tag the signal block tag
+ """
index = 0
while True:
id = tag+str(index)
@@ -104,21 +109,30 @@
return
def type_controller_modify_selected(self, direction):
- """ Change the registered type controller for the selected
signal block.
- direction may be +1 or -1 """
+ """
+ !Change the registered type controller for the selected signal
block.
+ @param direction +1 or -1
+ @return true for success
+ """
if Utils.is_socket(self.selected_element):
self.selected_element = self.selected_element.get_parent()
if Utils.is_signal_block(self.selected_element): return
self.selected_element.modify_type_controller(direction)
return False
def socket_controller_modify_selected(self, direction):
- """ Change socket controller for the selected signal block.
- direction may be +1 or -1 """
+ """!
+ Change socket controller for the selected signal block.
+ @param direction +1 or -1
+ @return true for success
+ """
if Utils.is_socket(self.selected_element):
self.selected_element = self.selected_element.get_parent()
if Utils.is_signal_block(self.selected_element): return
self.selected_element.modify_socket_controller(direction)
return False
def param_modify_selected(self):
- """ Create and show a param modification dialog for the
selected element (socket and signal block only) """
+ """!
+ Create and show a param modification dialog for the selected
element (socket and signal block only).
+ @return true if parameters were changed
+ """
if Utils.is_socket(self.selected_element):
self.selected_element = self.selected_element.get_parent()
if Utils.is_signal_block(self.selected_element):
signal_block_params_dialog =
SignalBlockParamsDialog(self.selected_element)
@@ -128,27 +142,37 @@
return False
def connect_sockets(self, s1, s2):
- """ Connect input and output sockets. Ignore state change
if creation of connection fails. """
+ """!
+ Connect input and output sockets. Ignore state change if
creation of connection fails.
+ @param s1 a socket
+ @param s2 another socket
+ """
try:
connection = GraphicalConnection(self, s1, s2)
self.elements.append(connection)
self.selected_element = None
self.handle_states(CONNECTION_CREATE)
self.update()
- except (InvalidConnectionException,
TooManyConnectionsException), e:
+ except ConnectionException:
Messages.send_fail_connection()
self.handle_states(NOTHING_SELECT)
def move_selected(self, delta_coordinate):
- """ Move the element and by the change in coordinate
(delta_coordinate) """
+ """!
+ Move the element and by the change in coordinates.
+ @param delta_coordinate the change in coordinates
+ """
if self.selected_element != None:
self.selected_element.move(delta_coordinate)
self.has_moved = True
self.draw()
def rotate_selected(self, direction):
- """ Rotate the selected element by 90 degrees, direction
can be "left"/"right"
- True if rotated, otherwise False. Only rotate
SignalBlocks and Sockets. """
+ """!
+ Rotate the selected element by 90 degrees. Only rotate
SignalBlocks and Sockets.
+ @param direction DIR_LEFT or DIR_RIGHT
+ @return true if rotated, otherwise false.
+ """
if self.selected_element != None and
(Utils.is_signal_block(self.selected_element) or
Utils.is_socket(self.selected_element)):
self.selected_element.rotate(direction)
self.draw()
@@ -156,8 +180,10 @@
return False
def delete_selected(self):
- """ If an element is selected, remove it and its attached
parts from the element list.
- True if the element was deleted, otherwise False.
"""
+ """!
+ If an element is selected, remove it and its attached parts
from the element list.
+ @return true if the element was deleted, otherwise false.
+ """
if self.selected_element != None:
if Utils.is_socket(self.selected_element): # found
a socket, set to parent signal block
self.selected_element =
self.selected_element.get_parent()
@@ -173,17 +199,22 @@
return False
def unselect(self):
- """ If an element is selected, un-highlight it and set selected
to None. """
+ """If an element is selected, un-highlight it and set selected
to None."""
if self.selected_element != None:
self.selected_element.set_highlighted(False)
self.selected_element = None
self.update()
def what_is_selected(self, coor):
- """ At the given coordinate, return the first element found
to be selected
+ """!
+ What is selected?
+ At the given coordinate, return the first element found to be
selected
- iterate though the elements backwards since top elements are
at the end of the list
- if an element is selected, place it at the end of the list so
that is is drawn last,
- and hence on top. """
+ and hence on top.
+ @param coor the coordinate of the mouse click
+ @return the selected element or None
+ """
# check the elements #
for i,element in enumerate(reversed(self.elements)):
if element.what_is_selected(coor) != None:
@@ -192,9 +223,51 @@
return element.what_is_selected(coor)
return None
- def __button_press_event_cb(self, widget, event):
- """ A mouse button is pressed. Record the state of the
mouse, find the selected element,
- set the Element highlighted, handle the state change, and
redraw the FlowGraph. """
+ def draw(self, drawable=None):
+ """Draw the background and then all of the Elements in this
FlowGraph on the pixmap,
+ then draw the pixmap to the drawable window of this
FlowGraph."""
+ if self.gc != None:
+ # draw the background #
+ W,H = self.get_size_request()
+ self.gc.foreground = BACKGROUND_COLOR
+ self.pixmap.draw_rectangle(self.gc, True, 0, 0, W, H)
+ if Preferences.show_grid():
+ grid_size = Preferences.get_grid_size()
+ points = list()
+ for i in range(W/grid_size):
+ for j in range(H/grid_size):
+
points.append((i*grid_size,j*grid_size))
+ self.gc.foreground = TXT_COLOR
+ self.pixmap.draw_points(self.gc, points)
+ # draw the foreground #
+ for element in filter(Utils.is_signal_block,
self.elements) + filter(Utils.is_connection, self.elements):
+ element.draw(self.pixmap) # draw signal
blocks first, then connections on the top
+ 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)
+
+ def is_valid(self):
+ """!
+ Is the flow graph valid, ie: are all elements valid?
+ @return true if flow graph is valid
+ """
+ for element in self.elements:
+ if not element.is_valid(): return False
+ return True
+
+ def update(self):
+ """Call update on all elements."""
+ print "Updating entire flow graph..."
+ for element in self.elements: element.update()
+ self.draw()
+
+
##########################################################################
+ ## Handlers
+
##########################################################################
+
+ def _handle_mouse_button_press(self, widget, event):
+ """ A mouse button is pressed. Record the state of the mouse,
find the selected element,
+ set the Element highlighted, handle the state change, and
redraw the FlowGraph."""
# unselect anything in the vars mod window #
self.variable_modification_window.unselect_all()
if event.button == 1:
@@ -221,8 +294,8 @@
self.draw()
return True
- def __button_release_event_cb(self, widget, event):
- """ A mouse button is released, record the state. """
+ def _handle_mouse_button_release(self, widget, event):
+ """A mouse button is released, record the state."""
if event.button == 1:
self.mouse_pressed = False
if self.has_moved:
@@ -240,22 +313,9 @@
self.has_moved = False
return True
- def is_valid(self):
- """ is the flow graph valid, ie: are all elements valid?
"""
- for element in self.elements:
- if not element.is_valid(): return False
- return True
-
- def update(self):
- '''call update on all elements'''
- print "Updating entire flow graph..."
- for element in self.elements: element.update()
- self.draw()
-
- def __motion_notify_event_cb(self, widget, event):
- """ The mouse is moved. If mouse_pressed is true, react to the
motions:
- - if an Element is highlighted, this will move the
Element by
- redrawing it at the new position """
+ def _handle_mouse_motion(self, widget, event):
+ """The mouse has moved. If mouse_pressed is true, react to the
motions:
+ - if an Element is highlighted, this will move the
Element by redrawing it at the new position."""
fgW,fgH = self.get_size_request()
self.count = (1 +
self.count)%MOTION_DETECT_REDRAWING_SENSITIVITY
# to perform a movement, the mouse must be pressed, an
element selected, count of zero. #
@@ -297,37 +357,14 @@
self.move_selected((deltaX, deltaY))
self.coordinate = (x, y)
- def __on_expose(self, widget, event):
- """ The window initially appears or is resized, create a
new pixmap, draw the flow graph. """
+ def _handle_window_expose(self, widget, event):
+ """Called when the window initially appears or is resized:
create a new pixmap, draw the flow graph."""
self.gc = self.window.new_gc()
width, height = self.get_size_request()
if self.pixmap == None or (width, height) !=
self.pixmap.get_size():
self.pixmap = gtk.gdk.Pixmap(self.window, width,
height, -1)
print "Main Pixmap Created!"
self.draw()
-
- def draw(self, drawable=None):
- """ draw the background and then all of the Elements in
this FlowGraph on the pixmap,
- then draw the pixmap to the drawable window of this FlowGraph.
"""
- if self.gc != None:
- # draw the background #
- W,H = self.get_size_request()
- self.gc.foreground = BACKGROUND_COLOR
- self.pixmap.draw_rectangle(self.gc, True, 0, 0, W, H)
- if Preferences.show_grid():
- grid_size = Preferences.get_grid_size()
- points = list()
- for i in range(W/grid_size):
- for j in range(H/grid_size):
-
points.append((i*grid_size,j*grid_size))
- self.gc.foreground = TXT_COLOR
- self.pixmap.draw_points(self.gc, points)
- # draw the foreground #
- for element in filter(Utils.is_signal_block,
self.elements) + filter(Utils.is_connection, self.elements):
- element.draw(self.pixmap) # draw signal
blocks first, then connections on the top
- 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)
##########################################################################
##
@@ -335,7 +372,10 @@
##
##########################################################################
def to_nested_data(self):
- ''' Dump all the values in this flow graph into a nested
data format. '''
+ """!
+ Dump all the values in this flow graph into a nested data
format.
+ @return nested data representing a flow graph
+ """
vars_list = list()
signal_blocks_list = list()
connections_list = list()
@@ -397,10 +437,12 @@
##
##########################################################################
def from_nested_data(self, nested_data):
- ''' Set all the values in this flow graph using the nested
data.
- Return a string of errors, one error per line. '''
+ """!
+ Set all the values in this flow graph using the nested data.
+ @param nested_data nested data representing a flow graph
+ """
#print 'From',nested_data
- #TODO: use a non-destructive methode to clear the elements list
+ #TODO: use a non-destructive method to clear the elements list
self.elements = list() #clear the elements
find_data = ParseXML.find_data
flow_graph = find_data([nested_data], 'flow_graph')
@@ -438,7 +480,7 @@
if element.get_id() == input_signal_block_id:
input_socket = element.get_input_socket(input_socket_index)
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):
+ except ConnectionException:
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
Deleted: grc/trunk/src/Graphics/FlowGraphFileDialog.py
Modified: grc/trunk/src/Graphics/MainWindow.py
===================================================================
--- grc/trunk/src/Graphics/MainWindow.py 2007-06-29 17:29:46 UTC (rev
5877)
+++ grc/trunk/src/Graphics/MainWindow.py 2007-06-29 17:41:26 UTC (rev
5878)
@@ -16,11 +16,9 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Graphics/MainWindow.py
- Josh Blum
- The main window, containing all windows, tool bars, and menu bars.
-"""
address@hidden Graphics.MainWindow
+#The main window, containing all windows, tool bars, and menu bars.
address@hidden Josh Blum
from Constants import *
import pygtk
@@ -31,27 +29,24 @@
from SignalBlockSelectionWindow import SignalBlockSelectionWindow
from VariableModificationWindow import VariableModificationWindow
from Dialogs import TextDisplay
+import Preferences
class MainWindow(gtk.Window):
- """ The main topmost window with menus and toolbars and flow graph
"""
+ """The topmost window with menus, the tool bar, and other major
windows."""
def __init__(self, handle_states):
- """ add menu bar, toolbar, and flowgraph """
+ """!
+ MainWindow contructor.
+ @param handle_states the callback function
+ """
self.handle_states = handle_states
gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
vbox = gtk.VBox()
hbox = gtk.HBox()
- vbox.show()
- hbox.show()
self.add(vbox)
self.set_title("")
- #create the menu bar
- menuBar = Bars.MenuBar()
- menuBar.show()
- vbox.pack_start(menuBar, False)
- #create the toolbar
- toolbar = Bars.Toolbar()
- toolbar.show()
- vbox.pack_start(toolbar, False)
+ #create the menu bar and toolbar
+ vbox.pack_start(Bars.MenuBar(), False)
+ vbox.pack_start(Bars.Toolbar(), False)
# create variable modification window #
variable_modification_window =
VariableModificationWindow(self.handle_states)
# create a flow_graph #
@@ -61,15 +56,12 @@
scrolled_window.set_size_request(MIN_WINDOW_WIDTH,
MIN_WINDOW_HEIGHT)
scrolled_window.set_policy(gtk.POLICY_AUTOMATIC,
gtk.POLICY_AUTOMATIC)
scrolled_window.add_with_viewport(self.flow_graph)
- scrolled_window.show()
fg_and_report_box = gtk.VBox()
- fg_and_report_box.show()
fg_and_report_box.pack_start(scrolled_window)
hbox.pack_start(fg_and_report_box)
vbox.pack_start(hbox)
#create the side windows
side_box = gtk.VBox()
- side_box.show()
hbox.pack_start(side_box, False)
side_box.pack_start(variable_modification_window, False)
#dont allow resize
side_box.pack_start(SignalBlockSelectionWindow(self.flow_graph)) #all resize,
selection window can have more space
@@ -79,25 +71,48 @@
self.reports_scrolled_window = gtk.ScrolledWindow()
self.reports_scrolled_window.set_size_request(-1,
REPORTS_WINDOW_HEIGHT)
self.reports_scrolled_window.set_policy(gtk.POLICY_AUTOMATIC,
gtk.POLICY_AUTOMATIC)
-
self.reports_scrolled_window.add_with_viewport(self.text_display)
- self.show_reports_window(False) #hide the window by default
+
self.reports_scrolled_window.add_with_viewport(self.text_display)
fg_and_report_box.pack_end(self.reports_scrolled_window, False)
#dont allow resize, fg should get all the space
- #self.show()
+ # show all but the main window container and the reports window
+ vbox.show_all()
+ self.show_reports_window(False)
+ # load preferences and show the main window
+ Preferences.load(self)
+ self.show()#show after resize in preferences
+ def _quit(self, window, event):
+ """!
+ Handle the delete event from the main window.
+ Generated by pressing X to close, alt+f4, or right click+close.
+ This method in turns calls the state handler to quit.
+ @return true
+ """
+ self.handle_states(APPLICATION_QUIT)
+ return True
+
def add_report_line(self, line):
- """ place line plus a newline at the end of the text buffer,
then scroll its window all the way down. """
+ """!
+ Place line plus a newline at the end of the text buffer, then
scroll its window all the way down.
+ @param line the new text
+ """
self.text_display.insert(line)
vadj = self.reports_scrolled_window.get_vadjustment()
vadj.set_value(vadj.upper)
def set_title(self, title):
- """ set the title and prepend the program name """
+ """!
+ Set the title and prepend the program name.
+ @param title the window title
+ """
prepend_str = MAIN_WINDOW_PREFIX + ' - Editing: '
gtk.Window.set_title(self, prepend_str + str(title))
def show_reports_window(self, show):
- """ Show the reports window when show is True.
- Hide the reports window when show is False. """
+ """!
+ Show the reports window when show is True.
+ Hide the reports window when show is False.
+ @param show boolean flag
+ """
if show: self.reports_scrolled_window.show()
else: self.reports_scrolled_window.hide()
\ No newline at end of file
Modified: grc/trunk/src/Graphics/SignalBlockParamsDialog.py
===================================================================
--- grc/trunk/src/Graphics/SignalBlockParamsDialog.py 2007-06-29 17:29:46 UTC
(rev 5877)
+++ grc/trunk/src/Graphics/SignalBlockParamsDialog.py 2007-06-29 17:41:26 UTC
(rev 5878)
@@ -16,11 +16,9 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Graphics/SignalBlockParamsDialog.py
- Josh Blum
- A dialog for editing a signal block's parameters.
-"""
address@hidden Graphics.SignalBlockParamsDialog
+#A dialog for editing a signal block's parameters.
address@hidden Josh Blum
import pygtk
pygtk.require('2.0')
@@ -29,42 +27,57 @@
from Constants import MIN_DIALOG_WIDTH,MIN_DIALOG_HEIGHT
class SignalBlockParamsDialog(gtk.Dialog):
- """ A dialog box to set signal block parameters such as sampling
rate and decimation values. """
+ """A dialog box to set signal block parameters."""
def __init__(self, signal_block):
+ """!
+ SignalBlockParamsDialog contructor.
+ @param signal_block the signal block
+ """
gtk.Dialog.__init__(self, buttons=('gtk-close',
gtk.RESPONSE_CLOSE))
self.signal_block = signal_block
- self.set_title(signal_block.get_id()+' properties')
+ self.set_title('Properties: %s'%signal_block.get_id())
self.set_size_request(MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT)
vbox = gtk.VBox()
- vbox.show()
# Create the title label #
label = gtk.Label()
- label.set_markup('<b>'+self.signal_block.get_id()+'
Parameters:</b>')
- label.show()
- self.vbox.pack_start(label, False)
+ label.set_markup('\n<b>Parameters:
%s</b>\n'%self.signal_block.get_id())
+ vbox.pack_start(label, False)
# Create the scrolled window to hold all the parameters #
scrolled_window = gtk.ScrolledWindow()
scrolled_window.set_policy(gtk.POLICY_AUTOMATIC,
gtk.POLICY_AUTOMATIC)
scrolled_window.add_with_viewport(vbox)
- scrolled_window.show()
self.vbox.pack_start(scrolled_window, True)
self.original_data = list()
# Add all the parameters #
for param in self.signal_block.get_params():
self.original_data.append(param.get_data_type().get_data())
- vbox.pack_start(param.get_input_object(), False)
+
vbox.pack_start(param.get_input_object(self._handle_changed), False)
# Done adding parameters #
- if self.signal_block.get_docs() != None:
+ if self.signal_block.get_docs():
# Create the title label #
label = gtk.Label()
- label.set_markup('<b>'+self.signal_block.get_cname()+'
Documentation:</b>')
- label.show()
- self.vbox.pack_start(label, False)
+ label.set_markup('\n\n<b>Documentation:
%s</b>\n'%self.signal_block.get_cname())
+ vbox.pack_start(label, False)
# Create the text box to display notes about the
block #
-
self.vbox.pack_start(TextDisplay(self.signal_block.get_docs()), False)
+
vbox.pack_start(TextDisplay(self.signal_block.get_docs()), False)
+ self.show_all()
+
+ def _handle_changed(self, param):
+ """!
+ A change occured, update any dependent parameters:
+ The enum inside the variable type may have changed and,
+ the variable param will need an external update.
+ @param param the graphical parameter that initiated the
callback
+ """
+ for p in self.signal_block.get_params():
+ if hasattr(p.get_data_type(), 'enum_data_type') and \
+ param.get_data_type() ==
getattr(p.get_data_type(), 'enum_data_type'): p.update()
def run(self):
- ''' Call the parent class run and return True if a change
occured. '''
+ """!
+ Call run().
+ @return true if a change occured.
+ """
gtk.Dialog.run(self)
self.destroy()
self.data = list()
Modified: grc/trunk/src/Graphics/SignalBlockSelectionWindow.py
===================================================================
--- grc/trunk/src/Graphics/SignalBlockSelectionWindow.py 2007-06-29
17:29:46 UTC (rev 5877)
+++ grc/trunk/src/Graphics/SignalBlockSelectionWindow.py 2007-06-29
17:41:26 UTC (rev 5878)
@@ -16,12 +16,9 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Graphics/SignalBlockSelectionWindow.py
- Josh Blum
- The signal block selection window.
- Gives the user a tree selection to choose a signal block.
-"""
address@hidden Graphics.SignalBlockSelectionWindow
+#The signal block selection window gives the user a tree selection to choose a
signal block.
address@hidden Josh Blum
from Constants import *
import pygtk
@@ -31,67 +28,73 @@
from SignalBlockDefs import SB_TREE
class SignalBlockSelectionWindow(gtk.VBox):
- """ The signal block selection window. """
+ """The signal block selection window."""
def __init__(self, flow_graph):
- """ Show all possible signal blocks in this dialog. Each
signal block is represented by a
- gtk label of its CNAME and an add button. The add
button tells the flow graph to add the chosen block. """
+ """!
+ SignalBlockSelectionWindow constructor.
+ Show all possible signal blocks in this dialog.
+ Each signal block is represented by a gtk label of its tag and
an add button.
+ The add button tells the flow graph to create the selected
block. and add it to the flow graph.
+ @param flow_graph the flow graph
+ """
gtk.VBox.__init__(self)
self.flow_graph = flow_graph
#title label
label = gtk.Label()
label.set_markup('<b>Signal Blocks</b>')
- label.show()
self.pack_start(label, False)
- # make the tree model for holding blocks #
+ #make the tree model for holding blocks
self.model = gtk.TreeStore(gobject.TYPE_STRING)
self.treeview = gtk.TreeView(self.model)
self.treeview.set_enable_search(False) #disable pop up search
box
self.treeview.add_events(gtk.gdk.BUTTON_PRESS_MASK)
- self.treeview.connect('button_press_event',
self.handle_button_press)
+ self.treeview.connect('button_press_event',
self._handle_mouse_button_press)
selection = self.treeview.get_selection()
selection.set_mode('single')
- selection.connect('changed', self.handle_selection_change)
+ selection.connect('changed', self._handle_selection_change)
renderer = gtk.CellRendererText()
column = gtk.TreeViewColumn("Category", renderer, text=0)
self.treeview.append_column(column)
- self.treeview.show()
- # make the scrolled window to hold the tree view #
+ #make the scrolled window to hold the tree view
scrolled_window = gtk.ScrolledWindow()
scrolled_window.set_policy(gtk.POLICY_AUTOMATIC,
gtk.POLICY_AUTOMATIC)
scrolled_window.add_with_viewport(self.treeview)
-
scrolled_window.set_size_request(SIGNAL_BLOCK_SELECTION_WINDOW_WIDTH,
-
SIGNAL_BLOCK_SELECTION_WINDOW_HEIGHT)
- scrolled_window.show()
+ scrolled_window.set_size_request(
+ SIGNAL_BLOCK_SELECTION_WINDOW_WIDTH,
+ SIGNAL_BLOCK_SELECTION_WINDOW_HEIGHT,
+ )
self.pack_start(scrolled_window)
- # add button #
+ #add button
self.add_button = gtk.Button(None, 'gtk-add')
- self.add_button.connect('clicked', self.handle_add_button)
- self.add_button.show()
+ self.add_button.connect('clicked', self._handle_add_button)
self.pack_start(self.add_button, False)
- # add blocks and categories #
+ #add blocks and categories
for category, tags in SB_TREE:
iter = self.model.insert_before(None, None)
self.model.set_value(iter, 0, category)
for tag in tags:
new_iter = self.model.insert_before(iter, None)
self.model.set_value(new_iter, 0, tag[0])
- self.handle_selection_change(None)
- self.show()
+ #initialize
+ self._handle_selection_change()
- def handle_button_press(self, widget, event):
- ''' If a left double click is detected, let the handler for the
add button decide to add a block. '''
- if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS:
- self.handle_add_button(widget)
+ def _handle_mouse_button_press(self, widget, event):
+ """Handle the mouse button press.
+ If a left double click is detected,
+ let the handler for the add button decide to add a block."""
+ if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS:
self._handle_add_button(widget)
- def handle_selection_change(self, event):
- ''' If a selection changes, set the add button sensitive.
'''
+ def _handle_selection_change(self, selection=None):
+ """Handle a selection change in the tree view.
+ If a selection changes, set the add button sensitive."""
selection = self.treeview.get_selection()
model, iter = selection.get_selected()
if iter != None and not model.iter_has_child(iter):
self.add_button.set_sensitive(True)
else: self.add_button.set_sensitive(False)
- def handle_add_button(self, widget):
- """ add the signal block to the flow graph and redraw the
flow graph """
+ def _handle_add_button(self, widget):
+ """Handle the add button clicked signal.
+ Add the signal block to the flow graph."""
selection = self.treeview.get_selection()
model, iter = selection.get_selected()
if iter != None and not model.iter_has_child(iter):
self.flow_graph.add_signal_block(model.get_value(iter, 0))
Modified: grc/trunk/src/Graphics/USRPDiagnostics.py
===================================================================
--- grc/trunk/src/Graphics/USRPDiagnostics.py 2007-06-29 17:29:46 UTC (rev
5877)
+++ grc/trunk/src/Graphics/USRPDiagnostics.py 2007-06-29 17:41:26 UTC (rev
5878)
@@ -16,57 +16,58 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Graphics/USRPDiagnostics.py
- Josh Blum
- A dialog for querying USRP subdevices. USRP interfacing methods
encapsulated here.
-"""
address@hidden Graphics.USRPDiagnostics
+#A dialog for querying USRP subdevices. USRP interfacing methods encapsulated
here.
address@hidden Josh Blum
import pygtk
pygtk.require('2.0')
import gtk
from Actions import USRP_DIAGNOSTICS_DISPLAY,get_action_from_name
from Elements import GraphicalParam
-from DataType import *
+from DataTypes import *
from Dialogs import TextDisplay
def enable_usrp_diagnostics():
- """ Only enable the action for USRP diganostics if gnuradio.usrp
can be imported. """
+ """Enable the action for USRP diganostics if gnuradio.usrp can be
imported."""
try:
from gnuradio import usrp
get_action_from_name(USRP_DIAGNOSTICS_DISPLAY).set_sensitive(True)
except ImportError: print "USRP support missing -> USRP diagnostics
disabled..."
class USRPDiagnosticsDialog(gtk.Dialog):
- """ The main dialog window for USRP Dignostics.
- The USRP parameters and feedback will be located inside this dialog.
"""
+ """The main dialog window for USRP Dignostics.
+ The USRP parameters and feedback will be located inside this dialog."""
def __init__(self):
- """ Create a new gtk Dialog with a close button, USRP input
paramaters, and output labels. """
+ """USRPDiagnosticsDialog contructor.
+ Create a new gtk Dialog with a close button, USRP input
paramaters, and output labels."""
gtk.Dialog.__init__(self, buttons=('gtk-close',
gtk.RESPONSE_CLOSE))
# Create the title label #
self.set_title('USRP Diagnostics')
self.USRP_number = Int(0, min=0)
self.USRP_type = Enum([('Receive', 'rx'), ('Transmit', 'tx'),])
- self.USRP_subdev = Enum([('Side A:0', (0, 0)),
-
('Side B:0', (1, 0)),
-
('Side A:1', (0, 1)),
-
('Side B:1', (1, 1)),])
+ self.USRP_subdev = Enum([
+ ('Side A:0', (0, 0)),
+ ('Side B:0', (1, 0)),
+ ('Side A:1', (0, 1)),
+ ('Side B:1', (1, 1)),
+ ])
self.vbox.pack_start(GraphicalParam('Unit Number',
self.USRP_number).get_input_object(), False)
self.vbox.pack_start(GraphicalParam('Transmit/Receive',
self.USRP_type).get_input_object(), False)
self.vbox.pack_start(GraphicalParam('Side:Subdevice',
self.USRP_subdev).get_input_object(), False)
self.diagnose_button = gtk.Button('Query')
- self.diagnose_button.connect('clicked', self.diagnose_usrp)
- self.diagnose_button.show()
+ self.diagnose_button.connect('clicked', self._diagnose_usrp)
self.vbox.pack_start(self.diagnose_button, False)
# Create a text box for USRP queries #
self.query_buffer = TextDisplay()
self.query_buffer.set_text('Press "Query" to retrieve USRP
information...')
- self.vbox.pack_start(self.query_buffer)
+ self.vbox.pack_start(self.query_buffer)
+ self.show_all()
self.run()
self.destroy()
- def diagnose_usrp(self, widget=None):
- """ Query the USRP device and append the results into the query
text box. """
+ def _diagnose_usrp(self, widget=None):
+ """Query the USRP device and copy the results into the query
text box."""
from gnuradio import usrp
type = self.USRP_type.parse()
if type == 'rx': #for the rx query, use the source and
rx methods
Modified: grc/trunk/src/Graphics/VariableModificationWindow.py
===================================================================
--- grc/trunk/src/Graphics/VariableModificationWindow.py 2007-06-29
17:29:46 UTC (rev 5877)
+++ grc/trunk/src/Graphics/VariableModificationWindow.py 2007-06-29
17:41:26 UTC (rev 5878)
@@ -16,15 +16,12 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Graphics/Windows/VariableModificationWindow.py
- Josh Blum
- The variable modification window.
- Allows the user to enter variables and slider information.
-"""
address@hidden Graphics.VariableModificationWindow
+#The variable modification window allows the user to enter variables (keys,
values, ranges).
address@hidden Josh Blum
from Constants import *
-from Actions import VARIABLE_MODIFY, NOTHING_SELECT
+from Actions import VARIABLE_MODIFY,VARIABLE_REORDER,NOTHING_SELECT
import pygtk
pygtk.require('2.0')
import gtk
@@ -32,87 +29,144 @@
import Variables
class VariableModificationWindow(gtk.VBox):
- ''' A scrollable window to add/remove variables in the variable
registry '''
+ """A scrollable window to add/remove variables in the variable
registry."""
def __init__(self, handle_states):
- ''' create a scrolled window, and add buttons and lists '''
+ """!
+ VariableModificationWindow constructor.Create a scrolled
window, and add buttons and lists.
+ @param handle_states callback function to handle the variable
changes
+ """
gtk.VBox.__init__(self)
self.handle_states = handle_states
#title label
label = gtk.Label()
label.set_markup('<b>Variables</b>')
- label.show()
self.pack_start(label, False)
- # create a srolled window to hold the vars #
+ #create a srolled window to hold the tree view
scrolled_window = gtk.ScrolledWindow()
- scrolled_window.show()
scrolled_window.set_policy(gtk.POLICY_AUTOMATIC,
gtk.POLICY_AUTOMATIC)
scrolled_window.set_size_request(
VARIABLE_MODIFICATION_WINDOW_WIDTH,
VARIABLE_MODIFICATION_WINDOW_HEIGHT
)
self.pack_start(scrolled_window)
- # liststore hold the graphical list #
+ #liststore holds the graphical list
self.liststore = gtk.ListStore(
gobject.TYPE_STRING, #key
gobject.TYPE_STRING, #value
gobject.TYPE_STRING, #min
gobject.TYPE_STRING, #max
- gobject.TYPE_STRING #step
+ gobject.TYPE_STRING, #step
)
self.treeview = gtk.TreeView(self.liststore)
self.treeview.set_enable_search(False) #disable pop up search
box
self.renderers = list()
for i,title in enumerate(['Variable', 'Default', 'Min', 'Max',
'Step']): #create each data column
+ #renderer for column i
renderer = gtk.CellRendererText()
renderer.set_property('editable', True)
- renderer.connect('edited',
self.__handle_renderer_edited)
self.renderers.append(renderer)
+ #connect signal handlers
+ renderer.connect('edited', self._handle_renderer_edited)
+ renderer.connect('editing-started',
self._handle_start_editing)
+ renderer.connect('editing-canceled',
self._handle_cancel_editing)
+ #tree view for column i
tree_view_column = gtk.TreeViewColumn(title, renderer,
text=i)
tree_view_column.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE) #allow the column to
shrink
self.treeview.append_column(tree_view_column)
self.treeview.set_reorderable(True)
selection = self.treeview.get_selection()
selection.set_mode('single')
- selection.connect('changed', self.__handle_selection_change)
- self.treeview.show()
+ selection.connect('changed', self._handle_selection_change)
scrolled_window.add_with_viewport(self.treeview)
- # buttons #
+ #buttons add and remove
buttons_hbox = gtk.HBox()
- buttons_hbox.show()
- self.pack_start(buttons_hbox, False)
- # add, edit, and remove buttons #
+ self.pack_start(buttons_hbox, False)
add_button = gtk.Button(None, 'gtk-add')
- add_button.connect('clicked', self.__handle_add_button)
- add_button.show()
+ add_button.connect('clicked', self._handle_add_button)
buttons_hbox.pack_start(add_button, False)
self.remove_button = gtk.Button(None, 'gtk-remove')
- self.remove_button.connect('clicked',
self.__handle_remove_button)
- self.remove_button.show()
+ self.remove_button.connect('clicked',
self._handle_remove_button)
buttons_hbox.pack_start(self.remove_button, False)
- self.treeview.connect("cursor-changed",
self.__handle_cursor_changed)
- self.__handle_selection_change()
- self.show()
+ #connect signal handlers
+ self.treeview.connect("cursor-changed",
self._handle_cursor_changed)
+ self.treeview.connect("drag_begin", self._handle_drag_begin)
+ self.treeview.connect("drag_end", self._handle_drag_end)
+ #initialize
+ self._handle_cancel_editing()
+ self._handle_selection_change()
+
#############################################################################################
+ # Access Methods
+
#############################################################################################
+
+ def to_key_list(self):
+ """!
+ Get a list of the keys in the current order.
+ @return a list of ordered variable keys
+ """
+ key_list = list()
+ for row in self.liststore: key_list.append(row[0])
+ return key_list
+
+ def from_key_list(self, key_list):
+ """!
+ Clear the rows and refill the list with keys from the key list.
+ @param key_list a list of ordered keys
+ """
+ self.liststore.clear()
+ for key in key_list:
self.liststore.append((key,)+Variables.get_values(key))
+
def unselect_all(self):
- ''' Stop editing in each renderer and unselect every row in the
tree view. '''
- #TODO: stop editing doesnt work
- for renderer in self.renderers: renderer.stop_editing(True)
+ """Stop any editing and unselect every row in the tree view."""
+ if self.editable: self.editable.remove_widget()
self.treeview.get_selection().unselect_all()
+
+
#############################################################################################
+ # Row Manipulation Handlers
+
#############################################################################################
- def __handle_cursor_changed(self, event=None):
- ''' Called when the cursor is placed on a row or in a cell.
- Unselect any selected element in the flow graph. '''
+ def _handle_drag_begin(self, drag_context, data):
+ """A drag event has begun, make a backup of the key list."""
+ self.backup_key_list = self.to_key_list()
+
+ def _handle_drag_end(self, drag_context, data):
+ """A drag event has ended.
+ If the backup key list does not match the current key list,
+ handle the variable state change."""
+ if self.backup_key_list != self.to_key_list():
self.handle_states(VARIABLE_REORDER)
+
+ def _handle_cursor_changed(self, treeview):
+ """Called when the cursor is placed on a row or in a cell.
+ Unselect any selected element in the flow graph."""
self.handle_states(NOTHING_SELECT)
- def __handle_selection_change(self, event=None):
- ''' If a selection changes, set the edit and remove buttons
sensitive. '''
+ def _handle_selection_change(self, selection=None):
+ """If a selection changes, set the edit and remove buttons
sensitive."""
selection = self.treeview.get_selection()
model, iter = selection.get_selected()
if iter != None: self.remove_button.set_sensitive(True)
else: self.remove_button.set_sensitive(False)
- def __handle_renderer_edited(self, renderer, row_index, new_text):
- ''' A cell was edited, determine what was edited and how to
handle it. '''
+
#############################################################################################
+ # Cell Editing Handlers
+
#############################################################################################
+
+ def _handle_start_editing(self, cellrenderer, editable, path):
+ """Editing of a cell has begun, record the editable object."""
+ self.editable = editable
+
+ def _handle_cancel_editing(self, cellrenderer=None):
+ """Editing of a cell has been canceled."""
+ self.editable = None
+
+ def _handle_renderer_edited(self, renderer, row_index, new_text):
+ """!
+ A cell was edited, determine what was edited and how to handle
it.
+ @param renderer the renderer
+ @param row_index the index of the row that changes
+ @param new_text the new text in the cell
+ """
+ self._handle_cancel_editing()
column_index = self.renderers.index(renderer)
if new_text == self.liststore[row_index][column_index]: return
#no change
old_list = self.liststore[row_index]
@@ -134,8 +188,12 @@
self.liststore[row_index][i] = value
self.handle_states(VARIABLE_MODIFY)
- def __handle_remove_button(self, widget, data=None):
- ''' Remove the selected element from the list and from the
VarReg. '''
+
#############################################################################################
+ # Button Handlers
+
#############################################################################################
+
+ def _handle_remove_button(self, widget):
+ """Handle the remove button by removing the selected element
from the list and from the variables registry."""
selection = self.treeview.get_selection()
model, iter = selection.get_selected()
if iter != None:
@@ -143,9 +201,9 @@
model.remove(iter)
self.handle_states(VARIABLE_MODIFY)
- def __handle_add_button(self, widget, data=None):
- ''' Handle the add button by adding a variable with key and
value.
- The key will be unique in the form 'new_var' + index.
'''
+ def _handle_add_button(self, widget):
+ """Handle the add button by adding a variable with key and
value.
+ The key will be unique in the form 'new_var' + index."""
new_key_index = 0
while True:
new_key_name = 'new_var'+str(new_key_index)
@@ -157,16 +215,6 @@
self.liststore.append((new_key_name,)+Variables.get_values(new_key_name))
self.handle_states(VARIABLE_MODIFY)
return #leave the while loop
-
- def to_key_list(self):
- ''' Return a list of the keys in the current order.
'''
- key_list = list()
- for row in self.liststore: key_list.append(row[0])
- return key_list
-
- def from_key_list(self, key_list):
- ''' Clear the rows and refill the list with keys from the list.
'''
- self.liststore.clear()
- for key in key_list:
self.liststore.append((key,)+Variables.get_values(key))
+
\ No newline at end of file
Modified: grc/trunk/src/Graphics/__init__.py
===================================================================
--- grc/trunk/src/Graphics/__init__.py 2007-06-29 17:29:46 UTC (rev 5877)
+++ grc/trunk/src/Graphics/__init__.py 2007-06-29 17:41:26 UTC (rev 5878)
@@ -16,13 +16,12 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Graphics/__init__.py
- gtk based classes go into this package
-"""
address@hidden Graphics.__init__
+#GTK based classes go into this package.
address@hidden Josh Blum
# only import the modules that need external access #
from MainWindow import MainWindow
-from FlowGraphFileDialog import FlowGraphFileDialog
+from FileDialogs import
OpenFlowGraphFileDialog,SaveFlowGraphFileDialog,SaveImageFileDialog
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-29 17:29:46 UTC (rev 5877)
+++ grc/trunk/src/MathExprParser.py 2007-06-29 17:41:26 UTC (rev 5878)
@@ -16,14 +16,9 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- MathExprParser.py
- Josh Blum
- 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.
-"""
address@hidden MathExprParser
+#Evaluate mathematical expressions and provide utilties to cast numbers.
address@hidden Josh Blum
import math,cmath
from gnuradio import gr
@@ -32,7 +27,7 @@
_WHITESPACE = (' ', '\t', '')
-_CONSTANTS = { #constans must be lower case
+_CONSTANTS = { #constants must be lower case
'pi' : cmath.pi,
'e' : cmath.e,
'j' : 1j,
@@ -45,50 +40,66 @@
}
#########################################################
-## Number parsers
+# Number parsers
#########################################################
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. '''
+ """!
+ Verify that the number is a complex number.
+ @param num the potential complex number
+ @throw ValueError not a number
+ @return a complex number
+ """
try: c_num = complex(num) #ensure that the num can be complex
- except: raise ValueError('"%s" is not a number.'%(num,))
+ 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. '''
+ """!
+ Verify the number as a float.
+ The number can have no imaginary part.
+ @param num the potential float number
+ @throw ValueError imaginary part is non zero.
+ @return a float number
+ """
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,))
+ 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 '''
+ """!
+ Verify the number as an integer.
+ The number can have no imaginary part.
+ The number can have no decimal part.
+ @param num the potential integer number
+ @throw ValueError imaginary or decimal part is non zero.
+ @return an integer number
+ """
f_num = verify_float(num)
- if f_num - int(f_num) != 0: raise ValueError('Expected an integer but
found "%s".'%(f_num,))
+ if f_num - int(f_num) != 0: raise ValueError, 'Expected an integer but
found "%s".'%(f_num,)
return int(f_num)
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 to cast the number into its most primative form: int, float, or
complex.
+ @throw ValueError num is not a number.
+ @return a number of int, float, or complex type
+ """
try: return verify_int(num) #try int
except:
try: return verify_float(num) #try float
except: return verify_complex(num) #complex or fail
#########################################################
-## Complex mathematical functions
+# Complex mathematical functions
#########################################################
def _complex_abs_v(*args):
- ''' Compute the abs of a complex number or vector. '''
+ """!
+ Compute the abs of a complex number or vector (recursively).
+ @param args list of numbers
+ @return the abs of args
+ """
sum = 0
for arg in args:
if _is_list(arg): sum = sum + _complex_abs_v(*arg)
@@ -98,7 +109,11 @@
return verify_number(cmath.sqrt(sum))
def _complex_real_v(*args):
- ''' Get the real part of a number or vector. '''
+ """!
+ Get the real part of a number or vector (recursively).
+ @param args list of numbers
+ @return the real of args
+ """
result = list()
for arg in args:
if _is_list(arg): result.append(_complex_real_v(*arg))
@@ -106,7 +121,11 @@
return result
def _complex_imag_v(*args):
- ''' Get the imaginary part of a number or vector. '''
+ """!
+ Get the imaginary part of a number or vector (recursively).
+ @param args list of numbers
+ @return the imaginary of args
+ """
result = list()
for arg in args:
if _is_list(arg): result.append(_complex_imag_v(*arg))
@@ -114,7 +133,11 @@
return result
def _complex_conj_v(*args):
- ''' Get the complex conjugate of a number or vector. '''
+ """!
+ Get the conjugate part of a number or vector (recursively).
+ @param args list of numbers
+ @return the conjugate of args
+ """
result = list()
for arg in args:
if _is_list(arg): result.append(_complex_conj_v(*arg))
@@ -122,14 +145,20 @@
return result
def _complex_arg(arg):
- ''' Get the angle of the complex number (radians). '''
+ """!
+ Get the angle of the complex number.
+ @param arg a complex number
+ @return the angle in 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. '''
+ """!
+ Pass the filter arguments to the filter function.
+ Use a look up method to format the arguments to floats and ints before
calling the filter function.
+ @throw Exception 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)
@@ -147,7 +176,7 @@
}
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)
+ 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)
@@ -208,7 +237,7 @@
}
#########################################################
-## Boolean tests for special characters and symbols
+# Boolean tests for special characters and symbols
#########################################################
def _is_list(symbol): return type(symbol) == type(list())
@@ -253,14 +282,22 @@
}[bracket]
#########################################################
-## Symbolic operations
+# 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))
+ """!
+ Handle basic operations specified in the order of operations
(recursively).
+ All calculations are complex, some vector operations are supported.
+ @param op the operator
+ @param arg1 first argument to the operator
+ @param arg2 second argument to the operator
+ @throw NameError unknown operations
+ @throw ZeroDivisionError divide by zero
+ @throw ArithmeticError impossible operations
+ @return the nested data representing the result (numbers and lists)
+ """
+ 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 #
@@ -288,24 +325,27 @@
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,))
+ 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))
+ raise ArithmeticError, 'Operation of "%s" cannot be performed on "%s",
"%s".'%(op, arg1, arg2)
#########################################################
-## Evaluate the expression string
+# Evaluate the expression string
#########################################################
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. '''
+ """!
+ 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.
+ @param expr_str the expression string
+ @return a list of strings representing each element
+ """
elements = list()
element = ''
for char_str in expr_str.lower():
@@ -319,11 +359,14 @@
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. '''
+ """!
+ Rectify operators.
+ Fix the functionality of the minus sign (-) and the plus sign (+)
in the floating point format,
+ which would have been separated by separate_expression.
+ If the minus sign is used as a negative replace it with -1* or ^-.
+ @param elements a list of strings
+ @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
@@ -348,10 +391,15 @@
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. '''
+ """!
+ Put the elements into a nested data format (recursively).
+ Read through the elements, recursing at each open bracket.
+ Put elements inside bracket pairs into a list.
+ @param a list of strings (rectified)
+ @param open_bracket the last open bracket
+ @throw SyntaxError bracket pairs do not match
+ @return the nested elements.
+ """
nested_elements = list()
while elements: #continue until elements is empty
element = elements.pop(0)
@@ -359,19 +407,24 @@
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))
+ 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),))
+ 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. '''
+ """!
+ Read through the nested elements and simplify expressions (recursively).
+ Work according to the order of operations.
+ Recurse at each list, substitute constans, parse numbers, handle
functions.
+ Make comma separated values into lists to represent vectors.
+ @param nested_elements nested elements (strings and lists)
+ @throw SyntaxError bad syntax
+ @throw NameError unknown symbol
+ @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)
@@ -379,20 +432,22 @@
elif _is_constant(element): nested_elements[i] =
_CONSTANTS[element]
# substitute in values for numbers #
elif _is_number(element): nested_elements[i] =
verify_number(element)
+ def comma_separate(ans):
+ if not _is_list(ans): ans = [ans] #must be a list
+ ans_with_commas = list()
+ for an in ans: ans_with_commas.extend([an, ','])
+ return ans_with_commas[0:-1] #remove last comma
# 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))
+ 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:]
+ raise SyntaxError, 'Function "%s" with
arguments "%s" failed.\n\t%s'%(function, nested_elements[i+1], e)
+ nested_elements = nested_elements[0:i] +
comma_separate(ans) + nested_elements[i+2:]
# simplify operations #
for operator in _ORDER_OF_OPS:
while operator in nested_elements:
@@ -401,32 +456,33 @@
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))
+ 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:]
+ nested_elements = nested_elements[0:i-1] +
comma_separate(ans) + 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.')
+ raise NameError, 'Unknown symbol
"%s".'%(element)
+ if last_element and not _is_comma(last_element):
#elements not separated by commas
+ raise SyntaxError, 'Expected comma, but found
"%s".'%(element)
+ vector.append(element) #good syntax, record the element
+ elif _is_comma(element) and _is_comma(last_element): #2
commas in a row
+ raise SyntaxError, 'Commas must be separated by
non-commas.'
+ elif _is_comma(element) and not last_element: #a comma was
the first element
+ raise SyntaxError, 'A non-comma must precede a comma.'
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. '''
+ """!
+ Evaluate a mathematical expression string with numbers, and operators.
+ @throw Exception failue
+ @return nested data (numbers and lists)
+ """
separated_elements = _separate_expression(expr_str)
#print "separated", separated_elements
rectified_elements = _rectify_operators(separated_elements)
@@ -437,8 +493,8 @@
return simplified
if __name__ == '__main__':
- ''' Evaluate expressions passed by argv(1). '''
+ """Evaluate expressions passed by arg1."""
import sys
if len(sys.argv) > 1: print eval_expr(sys.argv[1])
- else: print "No expressions passed!"
+ else: print "The mathematical expression parser will evaluate a string
(in quotes) passed via the command line."
\ No newline at end of file
Modified: grc/trunk/src/Messages.py
===================================================================
--- grc/trunk/src/Messages.py 2007-06-29 17:29:46 UTC (rev 5877)
+++ grc/trunk/src/Messages.py 2007-06-29 17:41:26 UTC (rev 5878)
@@ -16,23 +16,28 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Messages.py
- Josh Blum
- Handle all of the system messages and error reports.
-"""
address@hidden Messages
+#Handle all of the system messages and error reports.
address@hidden Josh Blum
from Constants import VERSION,PREFERENCES_FILE_PATH
+import traceback
-# A list of methods that can receive a message. #
+## A list of methods that can receive a message.
MESSENGERS_LIST = list()
def register_messenger(messenger):
- """ Append the given messenger to the list of messengers. """
+ """!
+ Append the given messenger to the list of messengers.
+ @param messenger a method thats takes a string
+ """
MESSENGERS_LIST.append(messenger)
def send(message):
- """ Give the given message to each of the messengers. """
+ """!
+ Give the message to each of the messengers.
+ @param message a message string
+ """
for messenger in MESSENGERS_LIST: messenger(message)
###########################################################################
@@ -50,6 +55,7 @@
def send_error_load(error):
send('>>> Error: %s\n'%error)
+ traceback.print_exc()
def send_end_load():
send(">>> Done\n")
@@ -57,14 +63,15 @@
def send_fail_load(error):
send('Parser Error: %s\n'%error)
send(">>> Failue\n")
+ traceback.print_exc()
-################# methods for running flow graphs
########################################
-def send_start_run(file_path):
+################# methods for executing flow graphs
########################################
+def send_start_exec(file_path):
send("""\
------------------
Running Flow Graph ------------------\n""")
- send('Trying to run: "%s"'%file_path + '\n')
+ send('Trying to execute: "%s"'%file_path + '\n')
-def send_end_run(verbose):
+def send_end_exec(verbose):
if verbose:
send(">>> Verbose: \n")
for verb in verbose: send(verb)
Modified: grc/trunk/src/ParseXML.py
===================================================================
--- grc/trunk/src/ParseXML.py 2007-06-29 17:29:46 UTC (rev 5877)
+++ grc/trunk/src/ParseXML.py 2007-06-29 17:41:26 UTC (rev 5878)
@@ -16,27 +16,39 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- ParseXML.py
- Josh Blum
- methods for parsing xml files to and from nested data
-"""
address@hidden ParseXML
+#Parse xml files to nested data and vice-versa.
address@hidden Josh Blum
import xml.dom.minidom
import xml.dom.ext
def find_data(nested_data, my_tag):
- """ Helper function for dealing with nested data. """
+ """!
+ Find a tag one level deep.
+ Helper function for dealing with nested data.
+ @param nested_data the data to search
+ @param my_tag the tag to search for
+ @return the data associated with the tag, None if not found
+ """
for tag,data in nested_data:
if tag == my_tag: return data
return None
def from_xml(doc):
- ''' Create nested data from an xml doc using the from xml helper.
'''
+ """!
+ Create nested data from an xml doc using the from xml helper.
+ @param doc the xml doc
+ @return the nested data
+ """
return __from_xml(doc.firstChild)
def __from_xml(doc):
- ''' Recursivly parse the xml doc into nested data format. '''
+ """!
+ Recursivly parse the xml doc into nested data format.
+ @param doc the xml doc
+ @return the nested data
+ """
#print doc.nodeType,doc.localName,doc.nodeValue,doc.childNodes
tag_name = doc.localName
if len(doc.childNodes) == 0:
@@ -50,13 +62,22 @@
return tag_name,nested_data
def to_xml(nested_data):
- ''' Create an xml doc and use the to xml helper method to load it.
'''
+ """!
+ Create an xml doc and use the to xml helper method to load it.
+ @param nested_data the nested data
+ @return the xml doc
+ """
doc = xml.dom.minidom.Document()
doc.appendChild(__to_xml(nested_data, doc))
return doc
def __to_xml(nested_data, doc):
- ''' Recursivly parse the nested data into xml doc format. '''
+ """!
+ Recursivly parse the nested data into xml doc format.
+ @param nested_data the nested data
+ @param the xml doc
+ @return the xml doc
+ """
tag_name,value = nested_data
child = doc.createElementNS(None, tag_name)
if type(value) == type(list()):
@@ -69,16 +90,22 @@
return child
def to_file(doc, file_path):
- ''' Save the xml doc to the file path. '''
+ """!
+ Save the xml doc to the file path.
+ @param doc the xml doc
+ @param file_path the destination xml-file
+ """
xml.dom.ext.PrettyPrint(doc, open(file_path,'w'))
def from_file(file_path):
- ''' Load an xml doc from the file path. '''
+ """!
+ Load an xml doc from the file path.
+ @param file_path the source xml-file
+ @return the xml doc
+ """
return xml.dom.minidom.parse(open(file_path, 'r'))
if __name__ == '__main__':
- nested = ('version', [('one',[('k','l'),('h','y')]),('two','2')])
- xml.dom.ext.PrettyPrint(to_xml(nested), open('test.xml','w'))
- print from_xml(xml.dom.minidom.parse(open('test.xml', 'r')))
- print nested
+ """Use the main method to test parse xml's functions."""
+ pass
\ No newline at end of file
Modified: grc/trunk/src/Preferences.py
===================================================================
--- grc/trunk/src/Preferences.py 2007-06-29 17:29:46 UTC (rev 5877)
+++ grc/trunk/src/Preferences.py 2007-06-29 17:41:26 UTC (rev 5878)
@@ -16,13 +16,11 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Preferences.py
- Josh Blum
- Holds global preferences stored as GraphicalParams.
-"""
address@hidden Preferences
+#Holds global preferences stored as GraphicalParams.
address@hidden Josh Blum
-from DataType import Bool,FileOpen,Enum,Int
+from DataTypes import Bool,FileOpen,Enum,Int
from Elements import GraphicalParam
import time,socket #for tagging saved files
from Constants import *
@@ -55,8 +53,7 @@
# List of Preferences
###########################################################################
-PREFS_LIST = [ #list of all prefs the be saved, restored, and displayed in the
pref's dialog
-#(title, notes, list of preferences)
+PREFS_LIST = [ #(title, notes, list of preferences)
("Verification", '', [
CONNECTION_CHECKING_PREF,
PARAM_CHECKING_PREF,
@@ -91,14 +88,21 @@
# Preference Access Methods
###########################################################################
-def get_value(param):
- """ If the param is valid, return the parsed value of the param.
- Otherwise return a blank string. """
+def _get_value(param):
+ """!
+ Get the value of the given parameter.
+ If the param is valid, return the parsed value of the param, otherwise
return a blank string.
+ @param param the parameter
+ @return the value of the parameter
+ """
if param.get_data_type().is_valid(): return
param.get_data_type().parse()
else: return ''
-def to_nested():
- """ Convert the param's data to nested format """
+def _to_nested():
+ """!
+ Convert the param's data to nested format.
+ @return the nested format
+ """
categories = list()
nested_data = ('preferences', [
('timestamp', str(time.time())),
@@ -111,8 +115,11 @@
for param in params: prefs.append(('pref',
param.get_data_type().get_data()))
return nested_data
-def from_nested(nested_data):
- """ Parse the nested data to retrieve each preference. """
+def _from_nested(nested_data):
+ """!
+ Parse the nested data to retrieve each preference.
+ @param nested_data the nested data
+ """
find_data = ParseXML.find_data
preferences = find_data([nested_data], 'preferences')
categories = find_data(preferences, 'categories')
@@ -125,17 +132,25 @@
except: pass
def load(window=None):
+ """!
+ Load the preferences from the preferences file.
+ @param window optional flow graph window
+ """
try:
-
from_nested(ParseXML.from_xml(ParseXML.from_file(PREFERENCES_FILE_PATH)))
- if window: window.resize(get_value(MAIN_WINDOW_WIDTH_PREF),
get_value(MAIN_WINDOW_HEIGHT_PREF))
+
_from_nested(ParseXML.from_xml(ParseXML.from_file(PREFERENCES_FILE_PATH)))
+ if window: window.resize(_get_value(MAIN_WINDOW_WIDTH_PREF),
_get_value(MAIN_WINDOW_HEIGHT_PREF))
except: Messages.send_fail_load_preferences()
def save(window=None):
+ """!
+ Save the preferences to the preferences file.
+ @param window optional flow graph window
+ """
if window:
width,height = window.get_size()
MAIN_WINDOW_WIDTH_PREF.get_data_type().set_data(width)
MAIN_WINDOW_HEIGHT_PREF.get_data_type().set_data(height)
- try: ParseXML.to_file(ParseXML.to_xml(to_nested()),
PREFERENCES_FILE_PATH)
+ try: ParseXML.to_file(ParseXML.to_xml(_to_nested()),
PREFERENCES_FILE_PATH)
except IOError: Messages.send_fail_save_preferences()
###########################################################################
@@ -143,34 +158,34 @@
###########################################################################
def set_default_flow_graph(file_path):
''' Set the new default flow graph path, only if the restore option is
true. '''
- if get_value(RESTORE_FLOW_GRAPH_PREF):
+ if _get_value(RESTORE_FLOW_GRAPH_PREF):
DEFAULT_FLOW_GRAPH_PREF.get_data_type().set_data(file_path)
def get_default_flow_graph():
''' Get the default flow graph path. Return a blank string if the path
is invalid. '''
if DEFAULT_FLOW_GRAPH_PREF.get_data_type().is_valid():
- return get_value(DEFAULT_FLOW_GRAPH_PREF)
+ return _get_value(DEFAULT_FLOW_GRAPH_PREF)
return ''
def check_connections():
- return get_value(CONNECTION_CHECKING_PREF)
+ return _get_value(CONNECTION_CHECKING_PREF)
def check_sockets():
- return get_value(SOCKET_CHECKING_PREF)
+ return _get_value(SOCKET_CHECKING_PREF)
def check_params():
- return get_value(PARAM_CHECKING_PREF)
+ return _get_value(PARAM_CHECKING_PREF)
-def show_reports_window():
- return get_value(REPORTS_WIN_SHOW_PREF)
+def show_reports_window(window):
+ return window.show_reports_window(_get_value(REPORTS_WIN_SHOW_PREF))
def get_grid_size():
- return get_value(GRID_SIZE_PREF)
+ return _get_value(GRID_SIZE_PREF)
def snap_to_grid():
- return get_value(SNAP_TO_GRID_PREF)
+ return _get_value(SNAP_TO_GRID_PREF)
def show_grid():
- return get_value(SHOW_GRID_PREF)
+ return _get_value(SHOW_GRID_PREF)
\ No newline at end of file
Property changes on: grc/trunk/src/SignalBlockDefs
___________________________________________________________________
Name: svn:ignore
- *.pyc
Modified: grc/trunk/src/SignalBlockDefs/Coders.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/Coders.py 2007-06-29 17:29:46 UTC (rev
5877)
+++ grc/trunk/src/SignalBlockDefs/Coders.py 2007-06-29 17:41:26 UTC (rev
5878)
@@ -16,13 +16,11 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- SignalBlockDefs/Coders.py
- Josh Blum
- Encode and Decode.
-"""
address@hidden SignalBlockDefs.Coders
+#Encode and decode.
address@hidden Josh Blum
-from DataType import *
+from DataTypes import *
from gnuradio import gr
def ConstellationDecoder(sb):
Modified: grc/trunk/src/SignalBlockDefs/Conversions.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/Conversions.py 2007-06-29 17:29:46 UTC
(rev 5877)
+++ grc/trunk/src/SignalBlockDefs/Conversions.py 2007-06-29 17:41:26 UTC
(rev 5878)
@@ -16,26 +16,25 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- SignalBlockDefs/Conversions.py
- Josh Blum
- Convert between data types.
-"""
address@hidden SignalBlockDefs.Conversions
+#Convert between data types.
address@hidden Josh Blum
-from DataType import *
+from DataTypes import *
from gnuradio import gr
-from SignalBlockConstants import all_choices,all_vector_choices
-from Constants import MAX_NUM_SOCKETS
+from SignalBlockConstants import
all_choices,all_vector_choices,default_samp_rate,MAX_NUM_SOCKETS
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)
+ 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)
sb.add_param('Vector Length', vlen)
return sb, lambda fg, type, vlen: type.parse()(vlen.parse())
@@ -103,9 +102,11 @@
return sb, lambda fg: fcn()
def UnpackedToPacked(sb):
- type = Enum([('Byte', (gr.unpacked_to_packed_bb, Byte())),
- ('Short', (gr.unpacked_to_packed_ss,
Short())),
- ('Int', (gr.unpacked_to_packed_ii,
Int())),])
+ type = Enum([
+ ('Byte', (gr.unpacked_to_packed_bb, Byte())),
+ ('Short', (gr.unpacked_to_packed_ss, Short())),
+ ('Int', (gr.unpacked_to_packed_ii, Int())),
+ ])
sb.add_input_socket('in', Variable(type, index=1))
sb.add_output_socket('out', Variable(type, index=1))
sb.add_param('Type', type, False, type=True)
@@ -115,9 +116,11 @@
return sb, lambda fg, type, bits_per_chunk, endianness:
type.parse()[0](bits_per_chunk.parse(), endianness.parse())
def PackedToUnpacked(sb):
- type = Enum([('Byte', (gr.packed_to_unpacked_bb, Byte())),
- ('Short', (gr.packed_to_unpacked_ss,
Short())),
- ('Int', (gr.packed_to_unpacked_ii,
Int())),])
+ type = Enum([
+ ('Byte', (gr.packed_to_unpacked_bb, Byte())),
+ ('Short', (gr.packed_to_unpacked_ss, Short())),
+ ('Int', (gr.packed_to_unpacked_ii, Int())),
+ ])
sb.add_input_socket('in', Variable(type, index=1))
sb.add_output_socket('out', Variable(type, index=1))
sb.add_param('Type', type, False, type=True)
@@ -141,12 +144,14 @@
def ChunksToSymbols(sb):
#name, fcn, input, output, symbol
table, dimensions
- type = Enum([('Byte->Complex', (gr.chunks_to_symbols_bc, Byte(),
Complex(), ComplexVector())),
- ('Byte->Float',
(gr.chunks_to_symbols_bf, Byte(), Float(), FloatVector())),
- ('Int->Complex',
(gr.chunks_to_symbols_ic, Int(), Complex(), ComplexVector())),
- ('Int->Float',
(gr.chunks_to_symbols_if, Int(), Float(), FloatVector())),
- ('Short->Complex',
(gr.chunks_to_symbols_sc, Short(), Complex(), ComplexVector())),
- ('Short->Float',
(gr.chunks_to_symbols_sf, Short(), Float(), FloatVector())),])
+ type = Enum([
+ ('Byte->Complex', (gr.chunks_to_symbols_bc, Byte(), Complex(),
ComplexVector())),
+ ('Byte->Float', (gr.chunks_to_symbols_bf, Byte(), Float(),
FloatVector())),
+ ('Int->Complex', (gr.chunks_to_symbols_ic, Int(), Complex(),
ComplexVector())),
+ ('Int->Float', (gr.chunks_to_symbols_if, Int(), Float(),
FloatVector())),
+ ('Short->Complex', (gr.chunks_to_symbols_sc, Short(),
Complex(), ComplexVector())),
+ ('Short->Float', (gr.chunks_to_symbols_sf, Short(), Float(),
FloatVector())),
+ ])
sb.add_input_socket('in', Variable(type, index=1))
sb.add_output_socket('out', Variable(type, index=2))
sb.add_param('Type', type, type=True)
@@ -161,7 +166,7 @@
sb.add_output_socket('out', Variable(type), vlen=vlen)
sb.add_param('Type', type, False, type=True)
sb.add_param('Num Inputs', Int(3, min=1, max=MAX_NUM_SOCKETS),
- show_label=False,
input_sockets_controller=True)
+ show_label=False, input_sockets_controller=True)
sb.add_param('Vector Length', vlen)
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())
@@ -173,7 +178,7 @@
sb.add_output_socket('out', Variable(type), vlen=vlen)
sb.add_param('Type', type, False, type=True)
sb.add_param('Num Outputs', Int(3, min=1, max=MAX_NUM_SOCKETS),
- show_label=False,
output_sockets_controller=True)
+ show_label=False, output_sockets_controller=True)
sb.add_param('Vector Length', vlen)
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())
@@ -186,7 +191,7 @@
sb.add_output_socket('out', Variable(type), vlen=vlen)
sb.add_param('Type', type, False, type=True)
sb.add_param('Num Streams', Int(3, min=1, max=MAX_NUM_SOCKETS),
- show_label=False,
input_sockets_controller=True)
+ show_label=False, input_sockets_controller=True)
sb.add_param('Vector Length', vlen)
sb.set_docs('''\
Interleave N streams into a single stream.
@@ -201,7 +206,7 @@
sb.add_output_socket('out', Variable(type), vlen=vlen)
sb.add_param('Type', type, False, type=True)
sb.add_param('Num Streams', Int(3, min=1, max=MAX_NUM_SOCKETS),
- show_label=False,
output_sockets_controller=True)
+ show_label=False, output_sockets_controller=True)
sb.add_param('Vector Length', vlen)
sb.set_docs('''\
Deinterleave a stream into N streams.
@@ -216,7 +221,7 @@
sb.add_output_socket('vout', Variable(type, index=0))
sb.add_param('Type', type, False, type=True)
sb.add_param('Num Streams', Int(3, min=1, max=MAX_NUM_SOCKETS),
- show_label=False,
input_sockets_controller=True)
+ show_label=False, input_sockets_controller=True)
sb.add_param('Vector Length', vlen)
sb.set_docs('''\
Convert N streams into a vector-stream of length N.
@@ -231,7 +236,7 @@
sb.add_output_socket('out', Variable(type, index=1), vlen=vlen)
sb.add_param('Type', type, False, type=True)
sb.add_param('Num Streams', Int(3, min=1, max=MAX_NUM_SOCKETS),
- show_label=False,
output_sockets_controller=True)
+ show_label=False, output_sockets_controller=True)
sb.add_param('Vector Length', vlen)
sb.set_docs('''\
Convert a vector-stream of length N into N streams.
@@ -262,4 +267,28 @@
sb.set_docs('''Merge a vector-stream of size N into a single
stream.''')
return sb, lambda fg, type, items_per_block, vlen:
fcn(type.parse()[1].get_num_bytes()*vlen.parse(), items_per_block.parse())
+def Map(sb):
+ fcn = gr.map_bb
+ sb.add_input_socket('in', Byte())
+ sb.add_output_socket('out', Byte())
+ sb.add_param('Vector', IntVector(''))
+ sb.set_docs('''output[i] = map[input[i]]''')
+ return sb, lambda fg, vector: fcn(vector.parse())
+
+def VCO(sb):
+ fcn = gr.vco_f
+ sb.add_input_socket('in', Float())
+ sb.add_output_socket('out', Float())
+ sb.add_param('Sampling Rate', Float(default_samp_rate))
+ sb.add_param('Sensitivity', Float(1))
+ sb.add_param('Amplitude', Float(1))
+ sb.set_docs('''\
+VCO - Voltage controlled oscillator.
+
+Parameters:
+ sampling_rate sampling rate (Hz)
+ sensitivity units are radians/sec/volt
+ amplitude output amplitude
+''')
+ return sb, lambda fg, samp_rate, sense, amp: fcn(samp_rate.parse(),
sense.parse(), amp.parse())
\ No newline at end of file
Copied: grc/trunk/src/SignalBlockDefs/Custom.py (from rev 5877,
grc/branches/jblum_work/src/SignalBlockDefs/Custom.py)
===================================================================
--- grc/trunk/src/SignalBlockDefs/Custom.py (rev 0)
+++ grc/trunk/src/SignalBlockDefs/Custom.py 2007-06-29 17:41:26 UTC (rev
5878)
@@ -0,0 +1,46 @@
+"""
+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
+"""
address@hidden SignalBlockDefs.Custom
+#Create your own custom blocks.
address@hidden You!
+
+from DataTypes import *
+from SignalBlockConstants import *
+from gnuradio import gr,blks
+
+###########################################################################
+#Read "creating_a_signal_block_def.txt" in the notes directory,
+#and add your own signal block definitions below:
+###########################################################################
+
+#def CustomBlockDef1(sb):
+#...
+#...
+
+###########################################################################
+#Add custom blocks to the list below,
+#and the blocks will appear under the "Custom" category:
+###########################################################################
+
+##custom block list
+CUSTOM_BLOCKS = [
+#('Custom Block 1', CustomBlockDef1),
+#('Custom Block 2', CustomBlockDef2),
+]
+
Modified: grc/trunk/src/SignalBlockDefs/Filters.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/Filters.py 2007-06-29 17:29:46 UTC (rev
5877)
+++ grc/trunk/src/SignalBlockDefs/Filters.py 2007-06-29 17:41:26 UTC (rev
5878)
@@ -16,15 +16,13 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- SignalBlockDefs/Filters.py
- Josh Blum
- Taps generators are from gr.firdes. Most FIR filters are implemented
and a few misc ones.
-"""
address@hidden SignalBlockDefs.Filters
+#Taps generators are from gr.firdes. Most FIR filters are implemented and a
few misc ones.
address@hidden Josh Blum
-from DataType import *
-from gnuradio import gr
-from SignalBlockConstants import default_samp_rate,all_choices
+from DataTypes import *
+from gnuradio import gr,gru,blks
+from SignalBlockConstants import default_samp_rate,all_choices,HierHelper
###########################################################################
# Generic filters with taps parameters
@@ -37,13 +35,13 @@
('Float->Float (Float Taps)', (gr.fir_filter_fff,
gr.interp_fir_filter_fff, Float(), Float(), FloatVector())),
('Float->Short (Float Taps)', (gr.fir_filter_fsf,
gr.interp_fir_filter_fsf, Float(), Short(), FloatVector())),
('Short->Complex (Complex Taps)', (gr.fir_filter_scc,
gr.interp_fir_filter_scc, Short(), Complex(), ComplexVector())),
- ])
+ ])
sb.add_input_socket('in', Variable(filters, index=2))
sb.add_output_socket('out', Variable(filters, index=3))
sb.add_param('Filter Type', filters, False, type=True)
sb.add_param('Type', Enum([('Decimating', 0), ('Interpolating', 1)]))
#this parses into an index for the filters Enum
sb.add_param('Decimation', Int(1, min=1))
- sb.add_param('Taps', Variable(filters, index=4, min=1))
+ sb.add_param('Taps', Variable(filters, index=4, min=1), variable=True)
sb.set_docs('''\
The decimation parameter becomes interpolation if the filter type is set to
interpolation. ''')
def make(fg, filter_type, type, decim, taps):
@@ -57,19 +55,19 @@
('Complex', (gr.freq_xlating_fir_filter_ccc,
gr.freq_xlating_fir_filter_ccf, Complex())),
('Float', (gr.freq_xlating_fir_filter_fcc,
gr.freq_xlating_fir_filter_fcf, Float())),
('Short', (gr.freq_xlating_fir_filter_scc,
gr.freq_xlating_fir_filter_scf, Short())),
- ])
+ ])
taps = Enum([
('Complex', (0, ComplexVector())),
('Float', (1, FloatVector())),
- ])
+ ])
sb.add_input_socket('in', Variable(filters, index=2))
sb.add_output_socket('out', Complex())
sb.add_param('Input Type', filters, False, type=True)
sb.add_param('Taps Type', taps) #this parses into an index for the
filters Enum
sb.add_param('Samp Rate', Float(default_samp_rate))
- sb.add_param('Center Freq', Float())
+ sb.add_param('Center Freq', Float(), variable=True)
sb.add_param('Decimation', Int(1, min=1))
- sb.add_param('Taps', Variable(taps, index=1, min=1))
+ sb.add_param('Taps', Variable(taps, index=1, min=1), variable=True)
def make(fg, filter_type, taps_type, samp_rate, center_freq, decim,
taps):
block =
filter_type.parse()[taps_type.parse()[0]](decim.parse(), taps.parse(),
center_freq.parse(), samp_rate.parse())
fg.add_callback(block.set_taps, taps)
@@ -81,12 +79,12 @@
filters = Enum([
('Complex', (gr.fft_filter_ccc, Complex(), ComplexVector())),
('Float', (gr.fft_filter_fff, Float(), FloatVector())),
- ])
+ ])
sb.add_input_socket('in', Variable(filters, index=1))
sb.add_output_socket('out', Variable(filters, index=1))
sb.add_param('Type', filters, False, type=True)
sb.add_param('Decimation', Int(1, min=1))
- sb.add_param('Taps', Variable(filters, index=2, min=1))
+ sb.add_param('Taps', Variable(filters, index=2, min=1), variable=True)
sb.set_docs('''The type selection controls the data type of the input,
output, and taps.''')
def make(fg, type, decim, taps):
block = type.parse()[0](decim.parse(), taps.parse())
@@ -102,13 +100,13 @@
('Float->Float (Float Taps)', (gr.rational_resampler_base_fff,
Float(), Float(), FloatVector())),
('Float->Short (Float Taps)', (gr.rational_resampler_base_fsf,
Float(), Short(), FloatVector())),
('Short->Complex (Complex Taps)',
(gr.rational_resampler_base_scc, Short(), Complex(), ComplexVector())),
- ])
+ ])
sb.add_input_socket('in', Variable(filters, index=1))
sb.add_output_socket('out', Variable(filters, index=2))
sb.add_param('Filter Type', filters, False, type=True)
sb.add_param('Interpolation', Int(1, min=1))
sb.add_param('Decimation', Int(1, min=1))
- sb.add_param('Taps', Variable(filters, index=3, min=1))
+ sb.add_param('Taps', Variable(filters, index=3, min=1), variable=True)
def make(fg, filter_type, interp, decim, taps):
block = filter_type.parse()[0](interp.parse(), decim.parse(),
taps.parse())
fg.add_callback(block.set_taps, taps)
@@ -139,6 +137,22 @@
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())
+
+def ChannelModel(sb):
+ fcn = blks.channel_model
+ sb.add_input_socket('in', Complex())
+ sb.add_output_socket('out', Complex())
+ sb.add_param('Noise Voltage', Float(0.0))
+ sb.add_param('Freq Offset', Float(0.0))
+ sb.add_param('Epsilon', Float(1.0))
+ sb.add_param('Taps', ComplexVector('1.0,0.0'))
+ sb.set_docs('''Simulate channel distortion.''')
+ def make(fg, noise_voltage, frequency_offset, epsilon, taps):
+ return HierHelper(
+ fcn(fg, noise_voltage.parse(),
frequency_offset.parse(), epsilon.parse(), taps.parse()),
+ Complex().get_num_bytes(), Complex().get_num_bytes(),
+ )
+ return sb, make
###########################################################################
# Special filters using taps generators
@@ -206,17 +220,17 @@
sb.add_input_socket('in', Variable(filters, index=1))
sb.add_output_socket('out', Variable(filters, index=2))
sb.add_param('Filter Type', filters, type=True)
- sb.add_param('Gain', Float(1))
- sb.add_param('Sampling Rate', Float(default_samp_rate))
+ sb.add_param('Gain', Float(1), variable=True)
+ sb.add_param('Sampling Rate', Float(default_samp_rate), variable=True)
if taps_maker in (gr.firdes.low_pass, gr.firdes.high_pass):
- sb.add_param('Cutoff Freq', Float(1000))
+ sb.add_param('Cutoff Freq', Float(1000), variable=True)
elif taps_maker in (gr.firdes.band_pass, gr.firdes.band_reject):
- sb.add_param('Low Cutoff Freq', Float(500))
- sb.add_param('High Cutoff Freq', Float(1500))
- sb.add_param('Transition Width', Float(100))
+ sb.add_param('Low Cutoff Freq', Float(500), variable=True)
+ sb.add_param('High Cutoff Freq', Float(1500), variable=True)
+ sb.add_param('Transition Width', Float(100), variable=True)
sb.add_param('Decimation', Int(1, min=1))
sb.add_param('Window Type', windows)
- sb.add_param('Beta', Float(6.76))
+ sb.add_param('Beta', Float(6.76), variable=True)
sb.set_docs('''\
The decimation parameter becomes interpolation if the filter type is set to
interpolation.''')
@@ -229,8 +243,8 @@
sb.add_param('Filter Type', filters, type=True)
sb.add_param('Decimation', Int(1, min=1))
sb.add_param('Window Type', windows)
- sb.add_param('Num Taps', Int(20, min=0))
- sb.add_param('Beta', Float(6.76))
+ sb.add_param('Num Taps', Int(20, min=0), variable=True)
+ sb.add_param('Beta', Float(6.76), variable=True)
def make(fg, filter_type, decimation, window, ntaps, beta):
taps_args = (window, ntaps, beta)
return make_filter(fg, filter_type, decimation, taps_maker,
taps_args)
@@ -243,11 +257,11 @@
sb.add_output_socket('out', Variable(filters, index=2))
sb.add_param('Filter Type', filters, type=True)
sb.add_param('Decimation', Int(1, min=1))
- sb.add_param('Gain', Float(1))
- sb.add_param('Sampling Rate', Float(default_samp_rate), False)
- sb.add_param('Symbol Rate', Float(100))
- sb.add_param('Alpha', Float(6.76))
- sb.add_param('Num Taps', Int(20, min=0))
+ sb.add_param('Gain', Float(1), variable=True)
+ sb.add_param('Sampling Rate', Float(default_samp_rate), variable=True)
+ sb.add_param('Symbol Rate', Float(100), variable=True)
+ sb.add_param('Alpha', Float(6.76), variable=True)
+ sb.add_param('Num Taps', Int(20, min=0), variable=True)
def make(fg, filter_type, decimation, gain, samp_freq, symbol_rate,
alpha, ntaps):
taps_args = (gain, samp_freq, symbol_rate, alpha, ntaps)
return make_filter(fg, filter_type, decimation, taps_maker,
taps_args)
@@ -276,8 +290,8 @@
fcn = gr.simple_squelch_cc
sb.add_input_socket('in', Complex())
sb.add_output_socket('out', Complex())
- sb.add_param('Threshold (dB)', Float(30))
- sb.add_param('Alpha', Float(.5))
+ sb.add_param('Threshold (dB)', Float(30), variable=True)
+ sb.add_param('Alpha', Float(.5), variable=True)
sb.set_docs('''Power levels below the threshold are not passed
through.''')
def make(fg, threshold, alpha):
block = fcn(threshold.parse(), alpha.parse())
@@ -288,12 +302,14 @@
def SinglePoleIIRFilter(sb):
vlen = Int(1, min=1)
- type = Enum([('Float', (gr.single_pole_iir_filter_ff, Float())),
- ('Complex',
(gr.single_pole_iir_filter_cc, Complex())),])
+ type = Enum([
+ ('Float', (gr.single_pole_iir_filter_ff, Float())),
+ ('Complex', (gr.single_pole_iir_filter_cc, Complex())),
+ ])
sb.add_input_socket('in', Variable(type, index=1))
sb.add_output_socket('out', Variable(type, index=1), vlen=vlen)
sb.add_param('Type', type, False, type=True)
- sb.add_param('Alpha', Float(1))
+ sb.add_param('Alpha', Float(1), variable=True)
sb.add_param('Vector Length', vlen)
def make(fg, type, alpha, vlen):
block = type.parse()[0](alpha.parse(), vlen.parse())
@@ -325,6 +341,15 @@
sb.add_param('Max Gain', Float(0))
return sb, lambda fg, type, attack_rate, decay_rate, ref, gain,
max_gain: \
type.parse()[0](attack_rate.parse(), decay_rate.parse(),
ref.parse(), gain.parse(), max_gain.parse())
+
+def FeedForwardAGC(sb):
+ fcn = gr.feedforward_agc_cc
+ sb.add_input_socket('in', Complex())
+ sb.add_output_socket('out', Complex())
+ sb.add_param('Num Samples', Int(100, min=1))
+ sb.add_param('Reference', Float(0))
+ sb.set_docs('''Non-causal AGC which computes required gain based on max
absolute value over nsamples.''')
+ return sb, lambda fg, nsamps, ref: fcn(nsamps.parse(), ref.parse())
def CMAFilter(sb):
fcn = gr.cma_equalizer_cc
@@ -337,15 +362,17 @@
return sb, lambda fg, num_taps, mod, mu: fcn(num_taps.parse(),
mod.parse(), mu.parse())
def ClockRecovery(sb):
- type = Enum([('Complex', (gr.clock_recovery_mm_cc, Complex())),
- ('Float', (gr.clock_recovery_mm_ff,
Float())),])
+ type = Enum([
+ ('Complex', (gr.clock_recovery_mm_cc, Complex())),
+ ('Float', (gr.clock_recovery_mm_ff, Float())),
+ ])
sb.add_input_socket('in', Variable(type, index=1))
sb.add_output_socket('out', Variable(type, index=1))
sb.add_param('Type', type, False, type=True)
- sb.add_param('Omega', Float())
- sb.add_param('Gain Omega', Float())
- sb.add_param('Mu', Float())
- sb.add_param('Gain Mu', Float())
+ sb.add_param('Omega', Float(), variable=True)
+ sb.add_param('Gain Omega', Float(), variable=True)
+ sb.add_param('Mu', Float(), variable=True)
+ sb.add_param('Gain Mu', Float(), variable=True)
sb.add_param('Omega Relative Limit', Float())
sb.set_docs('''Mueller & Mueller clock recovery.''')
def make(fg, type, omega, gain_omega, mu, gain_mu, omega_rel_limit):
@@ -359,16 +386,18 @@
def FFT(sb):
taps_maker = gr.firdes.window
- type = Enum([('Complex', (gr.fft_vcc, ComplexVector())),
- ('Float', (gr.fft_vfc,
FloatVector())),])
+ type = Enum([
+ ('Complex', (gr.fft_vcc, ComplexVector())),
+ ('Float', (gr.fft_vfc, FloatVector())),
+ ])
sb.add_input_socket('vin', Variable(type, index=1))
sb.add_output_socket('vout', ComplexVector())
sb.add_param('Input Type', type, False, type=True)
sb.add_param('FFT Size', Int(512, min=1))
sb.add_param('Window', Enum(window_choices, 1))
sb.add_param('Beta', Float(6.76))
- return sb, lambda fg, type, size, window, beta:
type.parse()[0](size.parse(), True,
-
taps_maker(window.parse(), size.parse(), beta.parse()))
+ return sb, lambda fg, type, size, window, beta: \
+ type.parse()[0](size.parse(), True, taps_maker(window.parse(),
size.parse(), beta.parse()))
def IFFT(sb):
fcn = gr.fft_vcc
@@ -378,14 +407,15 @@
sb.add_param('FFT Size', Int(512, min=1))
sb.add_param('Window', Enum(window_choices, 1), type=True)
sb.add_param('Beta', Float(6.76))
- return sb, lambda fg, size, window, beta: fcn(size.parse(), False,
-
taps_maker(window.parse(),
-
size.parse(), beta.parse()))
+ return sb, lambda fg, size, window, beta: \
+ fcn(size.parse(), False, taps_maker(window.parse(),
size.parse(), beta.parse()))
def Upsample(sb):
taps_maker = gr.firdes.window
- type = Enum([('Complex', (gr.rational_resampler_base_ccf, Complex())),
- ('Float',
(gr.rational_resampler_base_fff, Float())),], 1)
+ type = Enum([
+ ('Complex', (gr.rational_resampler_base_ccf, Complex())),
+ ('Float', (gr.rational_resampler_base_fff, Float())),
+ ], 1)
sb.add_input_socket('in', Variable(type, index=1))
sb.add_output_socket('out', Variable(type, index=1))
sb.add_param('Type', type, False, type=True)
@@ -401,7 +431,7 @@
sb.add_input_socket('in', Variable(type))
sb.add_output_socket('out', Variable(type))
sb.add_param('Type', type, False, type=True)
- sb.add_param('Decimation (M)', Int(1, min=1))
+ sb.add_param('Decimation (M)', Int(1, min=1), variable=True)
sb.set_docs('''\
Reduce the sample rate by keeping every Mth sample.
>>> Implements the gr.keep_one_in_n block.''')
@@ -413,11 +443,11 @@
return sb, make
def FractionalResampler(sb):
- from gnuradio import gru, blks
+ lcm = gru.lcm
filters = Enum([
('Complex', (blks.rational_resampler_ccc, Complex())),
('Float', (blks.rational_resampler_fff, Float())),
- ], 1)
+ ], 1)
sb.add_input_socket('in', Variable(filters, index=1))
sb.add_output_socket('out', Variable(filters, index=1))
sb.add_param('Type', filters, False, type=True)
@@ -431,7 +461,25 @@
def make(fg, filter_type, inrate, outrate, fractional_bw):
in_rate = inrate.parse()
out_rate = outrate.parse()
- interp = int(gru.lcm(in_rate, out_rate)/in_rate)
- decim = int(gru.lcm(in_rate, out_rate)/out_rate)
- return filter_type.parse()[0](fg, interp, decim, taps=None,
fractional_bw=fractional_bw.parse())
+ interp = int(lcm(in_rate, out_rate)/in_rate)
+ decim = int(lcm(in_rate, out_rate)/out_rate)
+ return HierHelper(
+ filter_type.parse()[0](fg, interp, decim, taps=None,
fractional_bw=fractional_bw.parse()),
+ filter_type.parse()[1].get_num_bytes(),
filter_type.parse()[1].get_num_bytes(),
+ )
return sb, make
+
+def FractionalInterpolator(sb):
+ filters = Enum([
+ ('Complex', (gr.fractional_interpolator_cc, Complex())),
+ ('Float', (gr.fractional_interpolator_ff, Float())),
+ ], 1)
+ sb.add_input_socket('in', Variable(filters, index=1))
+ sb.add_output_socket('out', Variable(filters, index=1))
+ sb.add_param('Type', filters, False, type=True)
+ sb.add_param('Phase Shift', Float())
+ sb.add_param('Interp Ratio', Float())
+ def make(fg, filter_type, phase_shit, interp_ratio):
+ return filter_type.parse()[0](phase_shift.parse(),
interp_ratio.parse())
+ return sb, make
+
Modified: grc/trunk/src/SignalBlockDefs/GraphicalSinks.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/GraphicalSinks.py 2007-06-29 17:29:46 UTC
(rev 5877)
+++ grc/trunk/src/SignalBlockDefs/GraphicalSinks.py 2007-06-29 17:41:26 UTC
(rev 5878)
@@ -16,15 +16,13 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- SignalBlockDefs/GraphicalSinks.py
- Josh Blum
- Various graphical sinks.
-"""
address@hidden SignalBlockDefs.GraphicalSinks
+#Various graphical sinks.
address@hidden Josh Blum
-from DataType import *
+from DataTypes import *
from gnuradio import gr
-from SignalBlockConstants import default_samp_rate
+from SignalBlockConstants import default_samp_rate,ThrottleHelper,HierHelper
number_display_pritority = 0
fft_display_priority = 1
@@ -34,14 +32,16 @@
def FFTSink(sb):
from gnuradio.wxgui import fftsink
- type = Enum([('Complex', (fftsink.fft_sink_c, Complex())),
- ('Float', (fftsink.fft_sink_f,
Float())),], 1)
+ type = Enum([
+ ('Complex', (fftsink.fft_sink_c, Complex())),
+ ('Float', (fftsink.fft_sink_f, Float())),
+ ], 1)
sb.add_input_socket('in', Variable(type, index=1))
sb.add_param('Type', type, False, type=True)
sb.add_param('Title', String('FFT'))
sb.add_param('Sampling Rate', Int(default_samp_rate))
- sb.add_param('Y per div', Int(20))
- sb.add_param('Reference Level', Int(20))
+ sb.add_param('Y per div', Int(20), variable=True)
+ sb.add_param('Reference Level', Int(20), variable=True)
sb.add_param('FFT Size', Int(512))
sb.add_param('FFT Rate', Int(15))
sb.add_param('Options', Enum([('Off', None), ('Average Values', 1),
('Peak Hold', 2)]))
@@ -58,20 +58,20 @@
fg.add_window(block.win, fft_display_priority, title.parse())
fg.add_callback(block.set_ref_level, ref_lvl)
fg.add_callback(block.set_y_per_div, y_per_div)
- th = gr.throttle(type.parse()[1].get_num_bytes(),
samp_rate.parse())
- fg.connect(th, block)
- return th
+ return ThrottleHelper(type.parse()[1].get_num_bytes(),
samp_rate.parse(), HierHelper(block, type.parse()[1].get_num_bytes()), True)
return sb, make
def WaterfallSink(sb):
from gnuradio.wxgui import waterfallsink
- type = Enum([('Complex', (waterfallsink.waterfall_sink_c, Complex())),
- ('Float',
(waterfallsink.waterfall_sink_f, Float())),], 1)
+ type = Enum([
+ ('Complex', (waterfallsink.waterfall_sink_c, Complex())),
+ ('Float', (waterfallsink.waterfall_sink_f, Float())),
+ ], 1)
sb.add_input_socket('in', Variable(type, index=1))
sb.add_param('Type', type, False, type=True)
sb.add_param('Title', String('Waterfall'))
sb.add_param('Sampling Rate', Int(default_samp_rate))
- sb.add_param('Baseband Freq', Int(0))
+ sb.add_param('Baseband Freq', Int(0), variable=True)
sb.add_param('Y per div', Int(20))
sb.add_param('Reference Level', Int(20))
sb.add_param('FFT Size', Int(512))
@@ -87,15 +87,15 @@
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_baseband_freq, baseband_freq)
- th = gr.throttle(type.parse()[1].get_num_bytes(),
samp_rate.parse())
- fg.connect(th, block)
- return th
+ return ThrottleHelper(type.parse()[1].get_num_bytes(),
samp_rate.parse(), HierHelper(block, type.parse()[1].get_num_bytes()), True)
return sb, make
def ScopeSink(sb):
from gnuradio.wxgui import scopesink
- type = Enum([('Complex', (scopesink.scope_sink_c, Complex())),
- ('Float', (scopesink.scope_sink_f,
Float())),], 1)
+ type = Enum([
+ ('Complex', (scopesink.scope_sink_c, Complex())),
+ ('Float', (scopesink.scope_sink_f, Float())),
+ ], 1)
sb.add_input_socket('in', Variable(type, index=1))
sb.add_param('Type', type, False, type=True)
sb.add_param('Title', String('Scope'))
@@ -114,14 +114,12 @@
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())
- th = gr.throttle(type.parse()[1].get_num_bytes(),
samp_rate.parse())
- fg.connect(th, block)
- return th
+ return ThrottleHelper(type.parse()[1].get_num_bytes(),
samp_rate.parse(), HierHelper(block, type.parse()[1].get_num_bytes()), True)
return sb, make
def ConstellationSink(sb):
from gnuradio.wxgui import scopesink
- fcn = scopesink.scope_sink_c
+ fcn = scopesink.scope_sink_c #dont tell anyone that its really a
scope sink
sb.add_input_socket('in', Complex())
sb.add_param('Title', String('Constellation'))
sb.add_param('Sampling Rate', Int(default_samp_rate))
@@ -138,26 +136,26 @@
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())
- th = gr.throttle(Complex().get_num_bytes(), samp_rate.parse())
- fg.connect(th, block)
- return th
+ return ThrottleHelper(Complex().get_num_bytes(),
samp_rate.parse(), HierHelper(block, Complex().get_num_bytes()), True)
return sb, make
def NumericalSink(sb):
from gnuradio.wxgui import numbersink
- type = Enum([('Complex', (numbersink.number_sink_c, Complex())),
- ('Float', (numbersink.number_sink_f,
Float())),], 1)
+ type = Enum([
+ ('Complex', (numbersink.number_sink_c, Complex())),
+ ('Float', (numbersink.number_sink_f, Float())),
+ ], 1)
sb.add_input_socket('in', Variable(type, index=1))
sb.add_param('Type', type, False, type=True)
sb.add_param('Title', String('Number'))
sb.add_param('Unit', String('Units'))
sb.add_param('Sampling Rate', Int(default_samp_rate))
- sb.add_param('Base Value', Float(0.0))
+ sb.add_param('Base Value', Float(0.0), variable=True)
sb.add_param('Min Value', Float(-100))
sb.add_param('Max Value', Float(100))
sb.add_param('Factor', Float(1.0))
- sb.add_param('Decimal Places', Int(6))
- sb.add_param('Reference Level', Int(50))
+ sb.add_param('Decimal Places', Int(6), variable=True)
+ sb.add_param('Reference Level', Int(50), variable=True)
sb.add_param('Number Rate', Int(15))
sb.add_param('Options', Enum([('Off', None), ('Average Values', 1),
('Peak Hold', 2)]))
sb.add_param('Gauge', Bool(true='Show', false='Hide', default=True))
@@ -178,9 +176,7 @@
fg.add_callback(block.set_base_value, base)
fg.add_callback(block.set_ref_level, ref_lvl)
fg.add_callback(block.set_decimal_places, decimals)
- th = gr.throttle(type.parse()[1].get_num_bytes(),
samp_rate.parse())
- fg.connect(th, block)
- return th
+ return ThrottleHelper(type.parse()[1].get_num_bytes(),
samp_rate.parse(), HierHelper(block, type.parse()[1].get_num_bytes()), True)
return sb, make
\ No newline at end of file
Modified: grc/trunk/src/SignalBlockDefs/Misc.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/Misc.py 2007-06-29 17:29:46 UTC (rev
5877)
+++ grc/trunk/src/SignalBlockDefs/Misc.py 2007-06-29 17:41:26 UTC (rev
5878)
@@ -16,16 +16,14 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- SignalBlockDefs/Misc.py
- Josh Blum
- These blocks were not categorized. Try to keep the number of misc
blocks small.
-"""
address@hidden SignalBlockDefs.Misc
+#These blocks were not categorized. Try to keep the number of misc blocks
small.
address@hidden Josh Blum
-from DataType import *
-from gnuradio import gr
-from SignalBlockConstants import default_samp_rate,all_choices
-from Constants import MAX_NUM_SOCKETS
+import gnuradio.gr.gr_threading as threading
+from DataTypes import *
+from gnuradio import gr,blks
+from SignalBlockConstants import default_samp_rate,all_choices,MAX_NUM_SOCKETS
def Throttle(sb):
fcn = gr.throttle
@@ -64,13 +62,14 @@
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())),
- ], 1)
+ type = Enum([
+ ('Complex', (gr.rms_cf, Complex())),
+ ('Float', (gr.rms_ff, Float())),
+ ], 1)
sb.add_input_socket('in', Variable(type, index=1))
sb.add_output_socket('out', Float())
sb.add_param('Input Type', type, False, type=True)
- sb.add_param('Alpha', Float(0.0001))
+ sb.add_param('Alpha', Float(0.0001), variable=True)
def make(fg, type, alpha):
block = type.parse()[0](alpha.parse())
fg.add_callback(block.set_alpha, alpha)
@@ -85,3 +84,140 @@
def Note(sb):
sb.add_param('Note', String(''))
return sb, lambda *args: None
+
+#######################################################################################
+## Selector Def, and Helper Block
+#######################################################################################
+
+class SelectorHelper(gr.hier_block2):
+ """A hier2 block with N inputs and M outputs, where data is only
forwarded through input n to output m."""
+ def __init__(self, item_size, num_inputs, num_outputs, input_index,
output_index):
+ """!
+ SelectorHelper constructor.
+ @param item_size the size of the gr data stream in bytes
+ @param num_inputs the number of inputs (integer)
+ @param num_outputs the number of outputs (integer)
+ @param input_index the index for the source data
+ @param output_index the index for the destination data
+ """
+ gr.hier_block2.__init__(
+ self, 'selector',
+ gr.io_signature(num_inputs, num_inputs, item_size),
+ gr.io_signature(num_outputs, num_outputs, item_size)
+ )
+ #terminator blocks for unused inputs and outputs
+ self.input_terminators = [gr.null_sink(item_size) for i in
range(num_inputs)]
+ self.output_terminators = [gr.head(item_size, 0) for i in
range(num_outputs)]
+ self.copy = None
+ #connections
+ for i in range(num_inputs): self.connect((self, i),
self.input_terminators[i])
+ for i in range(num_outputs):
self.connect(gr.null_source(item_size), self.output_terminators[i], (self, i))
+ self.item_size = item_size
+ self.input_index = input_index
+ self.output_index = output_index
+ self.num_inputs = num_inputs
+ self.num_outputs = num_outputs
+ self._connect_current()
+
+ def _indexes_valid(self):
+ """!
+ Are the input and output indexes within range of the number of
inputs and outputs?
+ @return true if input index and output index are in range
+ """
+ return self.input_index in range(self.num_inputs) and
self.output_index in range(self.num_outputs)
+
+ def _connect_current(self):
+ """If the input and output indexes are valid:
+ disconnect the blocks at the input and output index from their
terminators,
+ and connect them to one another. Then connect the terminators
to one another."""
+ if self._indexes_valid():
+ self.disconnect((self, self.input_index),
self.input_terminators[self.input_index])
+
self.disconnect(self.output_terminators[self.output_index], (self,
self.output_index))
+ self.copy = gr.skiphead(self.item_size, 0)
+ self.connect((self, self.input_index), self.copy)
+ self.connect(self.copy, (self, self.output_index))
+
self.connect(self.output_terminators[self.output_index],
self.input_terminators[self.input_index])
+
+ def _disconnect_current(self):
+ """If the input and output indexes are valid:
+ disconnect the blocks at the input and output index from one
another,
+ and the terminators at the input and output index from one
another.
+ Reconnect the blocks to the terminators."""
+ if self._indexes_valid():
+ self.disconnect((self, self.input_index), self.copy)
+ self.disconnect(self.copy, (self, self.output_index))
+
self.disconnect(self.output_terminators[self.output_index],
self.input_terminators[self.input_index])
+ del self.copy
+ self.copy = None
+ self.connect((self, self.input_index),
self.input_terminators[self.input_index])
+
self.connect(self.output_terminators[self.output_index], (self,
self.output_index))
+
+ def set_input_index(self, input_index):
+ """!
+ Change the block to the new input index if the index changed.
+ @param input_index the new input index
+ """
+ if self.input_index != input_index:
+ self._hb.lock()
+ self._disconnect_current()
+ self.input_index = input_index
+ self._connect_current()
+ self._hb.unlock()
+
+ def set_output_index(self, output_index):
+ """!
+ Change the block to the new output index if the index changed.
+ @param output_index the new output index
+ """
+ if self.output_index != output_index:
+ self._hb.lock()
+ self._disconnect_current()
+ self.output_index = output_index
+ self._connect_current()
+ self._hb.unlock()
+
+def Selector(sb):
+ 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('Input Index', Int(0), variable=True)
+ sb.add_param('Output Index', Int(0), variable=True)
+ sb.add_param('Num Inputs', Int(1, min=1, max=MAX_NUM_SOCKETS),
+ show_label=False, input_sockets_controller=True)
+ sb.add_param('Num Outputs', Int(1, min=1, max=MAX_NUM_SOCKETS),
+ show_label=False, output_sockets_controller=True)
+ sb.add_param('Vector Length', vlen)
+ sb.set_docs('''Forward data from the input index to the output
index.''')
+ def make(fg, type, input_index, output_index, num_inputs, num_outputs,
vlen):
+ item_size = type.parse().get_num_bytes()*vlen.parse()
+ block = SelectorHelper(
+ item_size,
+ num_inputs.parse(),
+ num_outputs.parse(),
+ input_index.parse(),
+ output_index.parse(),
+ )
+ fg.add_callback(block.set_input_index, input_index)
+ fg.add_callback(block.set_output_index, output_index)
+ return block
+ return sb, make
+
+def Valve(sb):
+ 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('Open', Int(0), variable=True)
+ sb.add_param('Vector Length', vlen)
+ sb.set_docs('''When open is 0, the valve will forward data.''')
+ def make(fg, type, open, vlen):
+ item_size = type.parse().get_num_bytes()*vlen.parse()
+ block = SelectorHelper(fg, item_size, 1, 1, 0, open.parse())
+ fg.add_callback(block.set_output_index, open)
+ return block
+ return sb, make
+
+
\ No newline at end of file
Modified: grc/trunk/src/SignalBlockDefs/Modulators.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/Modulators.py 2007-06-29 17:29:46 UTC (rev
5877)
+++ grc/trunk/src/SignalBlockDefs/Modulators.py 2007-06-29 17:41:26 UTC (rev
5878)
@@ -16,36 +16,39 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- SignalBlockDefs/Modulations.py
- Josh Blum
- Various modulation schemes.
-"""
address@hidden SignalBlockDefs.Modulations
+#Various modulation schemes.
address@hidden Josh Blum
-from DataType import *
+from DataTypes import *
from gnuradio import gr
+from SignalBlockConstants import HierHelper
-def FrequencyModulation(sb):
+def FrequencyMod(sb):
fcn = gr.frequency_modulator_fc
sb.add_input_socket('in', Float())
sb.add_output_socket('out', Complex())
sb.add_param('Sensitivity', Float(.01))
return sb, lambda fg, sensitivity: fcn(sensitivity.parse())
-def PhaseModulation(sb):
+def PhaseMod(sb):
fcn = gr.phase_modulator_fc
sb.add_input_socket('in', Float())
sb.add_output_socket('out', Complex())
sb.add_param('Sensitivity', Float(.01))
return sb, lambda fg, sensitivity: fcn(sensitivity.parse())
-def QuadratureDemodulation(sb):
+def QuadratureDemod(sb):
fcn = gr.quadrature_demod_cf
sb.add_input_socket('in', Complex())
sb.add_output_socket('out', Float())
sb.add_param('Gain', Float(1))
- return sb, lambda fg, gain: fcn(gain.parse())
+ return sb, lambda fg, gain: fcn(gain.parse())
+###########################################################################
+# Narrow band and Wide band FM
+###########################################################################
+
def WFMReceive(sb):
from gnuradio import blks
fcn = blks.wfm_rcv
@@ -56,7 +59,8 @@
sb.set_docs('''\
Wide Band FM Receiver.
The audio rate is the quad rate/audio decimation.''')
- return sb, lambda fg, quad_rate, audio_dec: fcn(fg, quad_rate.parse(),
audio_dec.parse())
+ return sb, lambda fg, quad_rate, audio_dec: \
+ HierHelper(fcn(fg, quad_rate.parse(), audio_dec.parse()),
Complex().get_num_bytes(), Float().get_num_bytes())
def WFMTransmit(sb):
from gnuradio import blks
@@ -76,7 +80,7 @@
# make sure that the quad rate is an integer multiple of
the audio rate #
audio_rate = quad_rate/audio_decimation
quad_rate = audio_decimation * (quad_rate/audio_decimation)
- return fcn(fg, audio_rate, quad_rate, tau.parse(),
max_dev.parse())
+ return HierHelper(fcn(fg, audio_rate, quad_rate, tau.parse(),
max_dev.parse()), Float().get_num_bytes(), Complex().get_num_bytes())
return sb, make
def NBFMReceive(sb):
@@ -97,7 +101,7 @@
# make sure that the quad rate is an integer multiple of
the audio rate #
audio_rate = quad_rate/audio_decimation
quad_rate = audio_decimation * (quad_rate/audio_decimation)
- return fcn(fg, audio_rate, quad_rate, tau.parse(),
max_dev.parse())
+ return HierHelper(fcn(fg, audio_rate, quad_rate, tau.parse(),
max_dev.parse()), Complex().get_num_bytes(), Float().get_num_bytes())
return sb, make
def NBFMTransmit(sb):
@@ -118,9 +122,13 @@
# make sure that the quad rate is an integer multiple of
the audio rate #
audio_rate = quad_rate/audio_decimation
quad_rate = audio_decimation * (quad_rate/audio_decimation)
- return fcn(fg, audio_rate, quad_rate, tau.parse(),
max_dev.parse())
+ return HierHelper(fcn(fg, audio_rate, quad_rate, tau.parse(),
max_dev.parse()), Float().get_num_bytes(), Complex().get_num_bytes())
return sb, make
+###########################################################################
+# AM and FM demodulation
+###########################################################################
+
def AMDemod(sb):
from gnuradio import blks
fcn = blks.am_demod_cf
@@ -130,7 +138,8 @@
sb.add_param('Audio Decimation', Int(1, min=1))
sb.add_param('Audio Passband (Hz)', Float(5e3))
sb.add_param('Audio Stopband (Hz)', Float(5.5e3))
- return sb, lambda fg, *args: fcn(fg, *map(lambda a: a.parse(), args))
+ return sb, lambda fg, *args: \
+ HierHelper(fcn(fg, *map(lambda a: a.parse(), args)),
Complex().get_num_bytes(), Float().get_num_bytes())
def FMDemod(sb):
from gnuradio import blks
@@ -144,55 +153,114 @@
sb.add_param('Audio Stopband (Hz)', Float(4e3))
sb.add_param('Gain', Float(1))
sb.add_param('Tau', Float(75e-6))
- return sb, lambda fg, *args: fcn(fg, *map(lambda a: a.parse(), args))
+ return sb, lambda fg, *args: \
+ HierHelper(fcn(fg, *map(lambda a: a.parse(), args)),
Complex().get_num_bytes(), Float().get_num_bytes())
+###########################################################################
+# Phase shift keying
+###########################################################################
+
def PSKMod(sb):
from gnuradio import blks
sb.add_input_socket('in', Byte())
sb.add_output_socket('out', Complex())
- sb.add_param('Type', Enum([('DBPSK', blks.dbpsk_mod), ('DQPSK',
blks.dqpsk_mod)]), type=True)
- sb.add_param('Samples/Symbol', Int(2, min=1))
+ sb.add_param('Type', Enum([
+ ('DBPSK', blks.dbpsk_mod),
+ ('DQPSK', blks.dqpsk_mod),
+ ('D8PSK', blks.d8psk_mod),
+ ]), type=True)
+ sb.add_param('Samples/Symbol', Int(2, min=2))
sb.add_param('Excess BW', Float(0.35))
- sb.add_param('Use Gray Code', Enum([('Yes', True), ('No', False)]))
- return sb, lambda fg, type, *args: type.parse()(fg, *map(lambda a:
a.parse(), args))
+ sb.add_param('Use Gray Code', Bool(true='Yes', false='No',
default=True))
+ return sb, lambda fg, type, *args: \
+ HierHelper(type.parse()(fg, *map(lambda a: a.parse(), args)),
Byte().get_num_bytes(), Complex().get_num_bytes())
def PSKDemod(sb):
from gnuradio import blks
sb.add_input_socket('in', Complex())
sb.add_output_socket('out', Byte())
- sb.add_param('Type', Enum([('DBPSK', blks.dbpsk_demod), ('DQPSK',
blks.dqpsk_demod)]), type=True)
- sb.add_param('Samples/Symbol', Int(2, min=1))
+ sb.add_param('Type', Enum([
+ ('DBPSK', blks.dbpsk_demod),
+ ('DQPSK', blks.dqpsk_demod),
+ ('D8PSK', blks.d8psk_demod),
+ ]), type=True)
+ sb.add_param('Samples/Symbol', Int(2, min=2))
sb.add_param('Excess BW', Float(0.35))
sb.add_param('Costas Alpha', Float(0.03))
sb.add_param('Gain Mu', Float(0.05))
sb.add_param('Mu', Float(0.005))
sb.add_param('Omega Relative Limit', Float(0.05))
- sb.add_param('Use Gray Code', Enum([('Yes', True), ('No', False)]))
- return sb, lambda fg, type, *args: type.parse()(fg, *map(lambda a:
a.parse(), args))
+ sb.add_param('Use Gray Code', Bool(true='Yes', false='No',
default=True))
+ return sb, lambda fg, type, *args: \
+ HierHelper(type.parse()(fg, *map(lambda a: a.parse(), args)),
Complex().get_num_bytes(), Byte().get_num_bytes())
+
+###########################################################################
+# Gaussian minimum shift keying
+###########################################################################
def GMSKMod(sb):
from gnuradio import blks
fcn = blks.gmsk_mod
sb.add_input_socket('in', Byte())
sb.add_output_socket('out', Complex())
- sb.add_param('Samples/Symbol', Int(2, min=1))
+ sb.add_param('Samples/Symbol', Int(2, min=2))
sb.add_param('Filter BW', Float(0.35))
- return sb, lambda fg, *args: fcn(fg, *map(lambda a: a.parse(), args))
+ return sb, lambda fg, *args: \
+ HierHelper(fcn(fg, *map(lambda a: a.parse(), args)),
Byte().get_num_bytes(), Complex().get_num_bytes())
def GMSKDemod(sb):
from gnuradio import blks
fcn = blks.gmsk_demod
sb.add_input_socket('in', Complex())
sb.add_output_socket('out', Byte())
- sb.add_param('Samples/Symbol', Int(2, min=1))
+ sb.add_param('Samples/Symbol', Int(2, min=2))
sb.add_param('Gain Mu', Float(0.05))
sb.add_param('Mu', Float(0.5, min=0, max=1))
sb.add_param('Omega Relative Limit', Float(0.005))
sb.add_param('Frequency Error', Float(0))
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))
+ return sb, lambda fg, *args: \
+ HierHelper(fcn(fg, *map(lambda a: a.parse(), args)),
Complex().get_num_bytes(), Byte().get_num_bytes())
###########################################################################
+# Quadrature amplitude modulation
+###########################################################################
+
+def QAMMod(sb):
+ from gnuradio import blks
+ sb.add_input_socket('in', Byte())
+ sb.add_output_socket('out', Complex())
+ sb.add_param('Type', Enum([
+ ('QAM 8', blks.qam8_mod),
+ ('QAM 64', blks.qam64_mod),
+ ('QAM 256', blks.qam256_mod),
+ ]), type=True)
+ sb.add_param('Samples/Symbol', Int(2, min=2))
+ sb.add_param('Excess BW', Float(0.35))
+ sb.add_param('Use Gray Code', Bool(true='Yes', false='No',
default=True))
+ return sb, lambda fg, type, *args: \
+ HierHelper(type.parse()(fg, *map(lambda a: a.parse(), args)),
Byte().get_num_bytes(), Complex().get_num_bytes())
+
+def QAMDemod(sb):
+ from gnuradio import blks
+ sb.add_input_socket('in', Complex())
+ sb.add_output_socket('out', Byte())
+ sb.add_param('Type', Enum([
+ ('QAM 8', blks.qam8_demod),
+ ('QAM 64', blks.qam64_demod),
+ ('QAM 256', blks.qam256_demod),
+ ]), type=True)
+ sb.add_param('Samples/Symbol', Int(2, min=2))
+ sb.add_param('Excess BW', Float(0.35))
+ sb.add_param('Costas Alpha', Float(0.03))
+ sb.add_param('Gain Mu', Float(0.05))
+ sb.add_param('Mu', Float(0.005))
+ sb.add_param('Omega Relative Limit', Float(0.05))
+ sb.add_param('Use Gray Code', Bool(true='Yes', false='No',
default=True))
+ return sb, lambda fg, type, *args: \
+ HierHelper(type.parse()(fg, *map(lambda a: a.parse(), args)),
Complex().get_num_bytes(), Byte().get_num_bytes())
+
+###########################################################################
# Phase Locked Loops
###########################################################################
Modified: grc/trunk/src/SignalBlockDefs/Operators.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/Operators.py 2007-06-29 17:29:46 UTC (rev
5877)
+++ grc/trunk/src/SignalBlockDefs/Operators.py 2007-06-29 17:41:26 UTC (rev
5878)
@@ -16,157 +16,175 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- SignalBlockDefs/Operations.py
- Josh Blum
- These blocks implement basic mathematical operations + - * / log10...
-"""
address@hidden SignalBlockDefs.Operators
+#These blocks implement basic mathematical operations + - * / log10...
address@hidden Josh Blum
-from DataType import *
+from DataTypes import *
from gnuradio import gr
-from Constants import *
+from SignalBlockConstants import MAX_NUM_SOCKETS
variable_inputs_doc_string = '''2 <= Num Inputs <= %d.'''%MAX_NUM_SOCKETS
def Add(sb):
- type = Enum([('Complex', (gr.add_cc, Complex())),
- ('Float', (gr.add_ff, Float())),
- ('Int', (gr.add_ii, Int())),
- ('Short', (gr.add_ss, Short())),], 1)
+ type = Enum([
+ ('Complex', (gr.add_cc, Complex())),
+ ('Float', (gr.add_ff, Float())),
+ ('Int', (gr.add_ii, Int())),
+ ('Short', (gr.add_ss, Short())),
+ ], 1)
sb.add_input_socket('in', Variable(type, index=1))
sb.add_output_socket('out', Variable(type, index=1))
sb.add_param('Type', type, False, type=True)
sb.add_param('Num Inputs', Int(2, min=2, max=MAX_NUM_SOCKETS),
- show_label=False,
input_sockets_controller=True)
+ show_label=False, input_sockets_controller=True)
sb.set_docs(variable_inputs_doc_string)
return sb, lambda fg, type, num_inputs: type.parse()[0]()
def AddVector(sb):
- type = Enum([('Complex Vector', (gr.add_vcc, ComplexVector())),
- ('Float Vector', (gr.add_vff,
FloatVector())),
- ('Int Vector', (gr.add_vii,
IntVector())),
- ('Short Vector', (gr.add_vss,
ShortVector())),], 1)
+ type = Enum([
+ ('Complex Vector', (gr.add_vcc, ComplexVector())),
+ ('Float Vector', (gr.add_vff, FloatVector())),
+ ('Int Vector', (gr.add_vii, IntVector())),
+ ('Short Vector', (gr.add_vss, ShortVector())),
+ ], 1)
sb.add_input_socket('vin', Variable(type, index=1))
sb.add_output_socket('vout', Variable(type, index=1))
sb.add_param('Type', type, False, type=True)
sb.add_param('Num Inputs', Int(2, min=2, max=MAX_NUM_SOCKETS),
- show_label=False,
input_sockets_controller=True)
+ show_label=False, input_sockets_controller=True)
sb.add_param('Items / Block', Int(1, min=1))
sb.set_docs(variable_inputs_doc_string)
return sb, lambda fg, type, num_inputs, items_per_block:
type.parse()[0](items_per_block.parse())
def AddConstant(sb):
- type = Enum([('Complex', (gr.add_const_cc, Complex())),
- ('Float', (gr.add_const_ff, Float())),
- ('Int', (gr.add_const_ii, Int())),
- ('Short', (gr.add_const_ss,
Short())),], 1)
+ type = Enum([
+ ('Complex', (gr.add_const_cc, Complex())),
+ ('Float', (gr.add_const_ff, Float())),
+ ('Int', (gr.add_const_ii, Int())),
+ ('Short', (gr.add_const_ss, Short())),
+ ], 1)
sb.add_input_socket('in', Variable(type, index=1))
sb.add_output_socket('out', Variable(type, index=1))
sb.add_param('Type', type, False, type=True)
- sb.add_param('Constant', Variable(type, 1, index=1))
+ sb.add_param('Constant', Variable(type, 1, index=1), variable=True)
def make(fg, type, constant):
block = type.parse()[0](constant.parse())
- if fg != None: fg.add_callback(block.set_k, constant)
+ fg.add_callback(block.set_k, constant)
return block
return sb, make
def AddConstantVector(sb):
- type = Enum([('Complex Vector', (gr.add_const_vcc, ComplexVector())),
- ('Float Vector', (gr.add_const_vff,
FloatVector())),
- ('Int Vector', (gr.add_const_vii,
IntVector())),
- ('Short Vector', (gr.add_const_vss,
ShortVector())),], 1)
+ type = Enum([
+ ('Complex Vector', (gr.add_const_vcc, ComplexVector())),
+ ('Float Vector', (gr.add_const_vff, FloatVector())),
+ ('Int Vector', (gr.add_const_vii, IntVector())),
+ ('Short Vector', (gr.add_const_vss, ShortVector())),
+ ], 1)
sb.add_input_socket('vin', Variable(type, index=1))
sb.add_output_socket('vout', Variable(type, index=1))
sb.add_param('Type', type, False, type=True)
- sb.add_param('Constant', Variable(type, 1, index=1))
+ sb.add_param('Constant', Variable(type, 1, index=1), variable=True)
def make(fg, type, constant):
block = type.parse()[0](constant.parse())
- if fg != None: fg.add_callback(block.set_k, constant)
+ fg.add_callback(block.set_k, constant)
return block
return sb, make
def Multiply(sb):
- type = Enum([('Complex', (gr.multiply_cc, Complex())),
- ('Float', (gr.multiply_ff, Float())),
- ('Int', (gr.multiply_ii, Int())),
- ('Short', (gr.multiply_ss, Short())),],
1)
+ type = Enum([
+ ('Complex', (gr.multiply_cc, Complex())),
+ ('Float', (gr.multiply_ff, Float())),
+ ('Int', (gr.multiply_ii, Int())),
+ ('Short', (gr.multiply_ss, Short())),
+ ], 1)
sb.add_input_socket('in', Variable(type, index=1))
sb.add_output_socket('out', Variable(type, index=1))
sb.add_param('Type', type, False, type=True)
sb.add_param('Num Inputs', Int(2, min=2, max=MAX_NUM_SOCKETS),
- show_label=False,
input_sockets_controller=True)
+ show_label=False, input_sockets_controller=True)
sb.set_docs(variable_inputs_doc_string)
return sb, lambda fg, type, num_inputs: type.parse()[0]()
def MultiplyVector(sb):
- type = Enum([('Complex Vector', (gr.multiply_vcc, ComplexVector())),
- ('Float Vector', (gr.multiply_vff,
FloatVector())),
- ('Int Vector', (gr.multiply_vii,
IntVector())),
- ('Short Vector', (gr.multiply_vss,
ShortVector())),], 1)
+ type = Enum([
+ ('Complex Vector', (gr.multiply_vcc, ComplexVector())),
+ ('Float Vector', (gr.multiply_vff, FloatVector())),
+ ('Int Vector', (gr.multiply_vii, IntVector())),
+ ('Short Vector', (gr.multiply_vss, ShortVector())),
+ ], 1)
sb.add_input_socket('vin', Variable(type, index=1))
sb.add_output_socket('vout', Variable(type, index=1))
sb.add_param('Type', type, False, type=True)
sb.add_param('Num Inputs', Int(2, min=2, max=MAX_NUM_SOCKETS),
- show_label=False,
input_sockets_controller=True)
+ show_label=False, input_sockets_controller=True)
sb.add_param('Items / Block', Int(1, min=1))
sb.set_docs(variable_inputs_doc_string)
return sb, lambda fg, type, num_inputs, items_per_block:
type.parse()[0](items_per_block.parse())
def MultiplyConstant(sb):
- type = Enum([('Complex', (gr.multiply_const_cc, Complex())),
- ('Float', (gr.multiply_const_ff,
Float())),
- ('Int', (gr.multiply_const_ii, Int())),
- ('Short', (gr.multiply_const_ss,
Short())),], 1)
+ type = Enum([
+ ('Complex', (gr.multiply_const_cc, Complex())),
+ ('Float', (gr.multiply_const_ff, Float())),
+ ('Int', (gr.multiply_const_ii, Int())),
+ ('Short', (gr.multiply_const_ss, Short())),
+ ], 1)
sb.add_input_socket('in', Variable(type, index=1))
sb.add_output_socket('out', Variable(type, index=1))
sb.add_param('Type', type, False, type=True)
- sb.add_param('Constant', Variable(type, 1, index=1))
+ sb.add_param('Constant', Variable(type, 1, index=1), variable=True)
def make(fg, type, constant):
block = type.parse()[0](constant.parse())
- if fg != None: fg.add_callback(block.set_k, constant)
+ fg.add_callback(block.set_k, constant)
return block
return sb, make
def MultiplyConstantVector(sb):
- type = Enum([('Complex Vector', (gr.multiply_const_vcc,
ComplexVector())),
- ('Float Vector',
(gr.multiply_const_vff, FloatVector())),
- ('Int Vector', (gr.multiply_const_vii,
IntVector())),
- ('Short Vector',
(gr.multiply_const_vss, ShortVector())),], 1)
+ type = Enum([
+ ('Complex Vector', (gr.multiply_const_vcc, ComplexVector())),
+ ('Float Vector', (gr.multiply_const_vff, FloatVector())),
+ ('Int Vector', (gr.multiply_const_vii, IntVector())),
+ ('Short Vector', (gr.multiply_const_vss, ShortVector())),
+ ], 1)
sb.add_input_socket('vin', Variable(type, index=1))
sb.add_output_socket('vout', Variable(type, index=1))
sb.add_param('Type', type, False, type=True)
- sb.add_param('Constant', Variable(type, 1, index=1))
+ sb.add_param('Constant', Variable(type, 1, index=1), variable=True)
def make(fg, type, constant):
block = type.parse()[0](constant.parse())
- if fg != None: fg.add_callback(block.set_k, constant)
+ fg.add_callback(block.set_k, constant)
return block
return sb, make
def Subtract(sb):
- type = Enum([('Complex', (gr.sub_cc, Complex())),
- ('Float', (gr.sub_ff, Float())),
- ('Int', (gr.sub_ii, Int())),
- ('Short', (gr.sub_ss, Short())),], 1)
+ type = Enum([
+ ('Complex', (gr.sub_cc, Complex())),
+ ('Float', (gr.sub_ff, Float())),
+ ('Int', (gr.sub_ii, Int())),
+ ('Short', (gr.sub_ss, Short())),
+ ], 1)
sb.add_input_socket('in', Variable(type, index=1))
sb.add_input_socket('-in', Variable(type, index=1))
sb.add_output_socket('out', Variable(type, index=1))
sb.add_param('Type', type, False, type=True)
sb.add_param('Num Inputs', Int(2, min=2, max=MAX_NUM_SOCKETS),
- show_label=False,
input_sockets_controller=True)
+ show_label=False, input_sockets_controller=True)
sb.set_docs(variable_inputs_doc_string)
return sb, lambda fg, type, num_inputs: type.parse()[0]()
def Divide(sb):
- type = Enum([('Complex', (gr.divide_cc, Complex())),
- ('Float', (gr.divide_ff, Float())),
- ('Int', (gr.divide_ii, Int())),
- ('Short', (gr.divide_ss, Short())),],
1)
+ type = Enum([
+ ('Complex', (gr.divide_cc, Complex())),
+ ('Float', (gr.divide_ff, Float())),
+ ('Int', (gr.divide_ii, Int())),
+ ('Short', (gr.divide_ss, Short())),
+ ], 1)
sb.add_input_socket('in', Variable(type, index=1))
sb.add_input_socket('/in', Variable(type, index=1))
sb.add_output_socket('out', Variable(type, index=1))
sb.add_param('Type', type, False, type=True)
sb.add_param('Num Inputs', Int(2, min=2, max=MAX_NUM_SOCKETS),
- show_label=False,
input_sockets_controller=True)
+ show_label=False, input_sockets_controller=True)
sb.set_docs(variable_inputs_doc_string)
return sb, lambda fg, type, num_inputs: type.parse()[0]()
@@ -178,5 +196,5 @@
sb.add_param('k', Float(0))
sb.add_param('Vector Length', vlen)
sb.set_docs('''output = n*log10(input) + k''')
- return sb, lambda fg, n, k, vlen: gr.nlog10_ff(n.parse(), vlen,
k.parse())
+ return sb, lambda fg, n, k, vlen: gr.nlog10_ff(n.parse(), vlen.parse(),
k.parse())
\ No newline at end of file
Copied: grc/trunk/src/SignalBlockDefs/Packet.py (from rev 5877,
grc/branches/jblum_work/src/SignalBlockDefs/Packet.py)
===================================================================
--- grc/trunk/src/SignalBlockDefs/Packet.py (rev 0)
+++ grc/trunk/src/SignalBlockDefs/Packet.py 2007-06-29 17:41:26 UTC (rev
5878)
@@ -0,0 +1,312 @@
+"""
+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
+"""
address@hidden SignalBlockDefs.Packet
+#Support for the gr packet framework.
address@hidden Josh Blum
+
+import struct
+import os
+import gnuradio.gr.gr_threading as threading
+from DataTypes import *
+from gnuradio import gr,blks,packet_utils
+from SignalBlockConstants import all_choices,DEFAULT_QUEUE_LIMIT
+
+MAX_ACCESS_CODE_LENGTH = 64
+MAX_PACKET_LENGTH = len(packet_utils.random_mask_tuple)#4096
+DEFAULT_PACKET_LENGTH = 512
+
+#######################################################################################
+## Packet Modulator and Demodulator Hier Block
+#######################################################################################
+
+class PacketModThread(threading.Thread):
+ """
+ Thread to forward data between the message queue and the packet
modulator.
+ Read messages from the message queue, slice them up to the packet
length,
+ and pass them to the send packet function.
+ """
+ def __init__(self, msgq, send_packet, packet_length):
+ """!
+ PacketModThread contructor.
+ @param msgq the message queue with incoming data
+ @param send_packet a function of one argument to send a packet
+ """
+ self.msgq = msgq
+ self.send_packet = send_packet
+ self.packet_length = packet_length
+ threading.Thread.__init__(self)
+ self.setDaemon(1)
+ self.keep_running = True
+ self.start()
+ print 'Created packet modulator thread.'
+
+ def run(self):
+ """In an endless while loop: read the msgq and call send
packet."""
+ r = '' #residual message
+ while self.keep_running:
+ msg = self.msgq.delete_head() # blocking read of
message queue
+ sr = r + msg.to_string()
+ num_packets = len(sr)/int(self.packet_length) #integer
arithmetic
+ r_index = self.packet_length*num_packets
+ s = sr[0:r_index] #portion of message divisible
by packet size
+ r = sr[r_index:] #residual portion of message
smaller then packet size
+ #print len(s), len(r), msg.type(), msg.arg1(),
msg.arg2()
+ for i in range(num_packets):
self.send_packet(s[i*self.packet_length:(i+1)*self.packet_length])
+
+class PacketModHelper(gr.hier_block2):
+ """Forward data from the gr data stream to the mod packet."""
+ def __init__(self, item_size, packet_length, samples_per_symbol,
bits_per_symbol, access_code, pad_for_usrp, use_whitener_offset):
+ """!
+ PacketModHelper constructor.
+ @param item_size the size in bytes of the input data stream
+ @param packet_length the length in bytes of the packets
+ @param *args the arguments for blks.mod_pkts
+ """
+ #create hier block
+ gr.hier_block2.__init__(
+ self, 'packet_mod',
+ gr.io_signature(1, 1, item_size),
+ gr.io_signature(1, 1, Byte().get_num_bytes())
+ )
+ #dummy modulator with access functions
+ modulator = gr.skiphead(Byte().get_num_bytes(), 0)
+ modulator.samples_per_symbol = lambda: samples_per_symbol
+ modulator.bits_per_symbol = lambda: bits_per_symbol
+ #create the packet modulator (handles the output data stream)
+ packet_mod = blks.mod_pkts(
+ fg=self,
+ modulator=modulator,
+ access_code=access_code,
+ msgq_limit=DEFAULT_QUEUE_LIMIT,
+ pad_for_usrp=pad_for_usrp,
+ use_whitener_offset=use_whitener_offset,
+ )
+ #the message sink (handles the input data stream)
+ msgq = gr.msg_queue(DEFAULT_QUEUE_LIMIT)
+ msg_sink = gr.message_sink(item_size, msgq, False)
+ #connections
+ self.connect(packet_mod.tail, self)
+ self.connect(self, msg_sink)
+ #create/start the thread
+ PacketModThread(msgq, packet_mod.send_pkt, packet_length)
+
+class PacketDemodHelper(gr.hier_block2):
+ """Forward data from demod packet to the gr data stream."""
+ def __init__(self, item_size, access_code, threshold):
+ """!
+ PacketDemodHelper constructor.
+ @param item_size the size in bytes of the output data stream
+ @param *args the arguments for blks.demod_pkts
+ @param msgq_limit the queue limit for the message source
+ """
+ #create hier block
+ gr.hier_block2.__init__(
+ self, 'packet_demod',
+ gr.io_signature(1, 1, Byte().get_num_bytes()),
+ gr.io_signature(1, 1, item_size)
+ )
+ #the message source (handles the output data stream)
+ msg_source = gr.message_source(item_size, DEFAULT_QUEUE_LIMIT)
+ msgq = msg_source.msgq()
+ def callback(ok, payload):
+ if ok: msgq.insert_tail(gr.message_from_string(payload,
0, item_size, len(payload)/item_size))
+ #dummy demodulator
+ demodulator = gr.skiphead(Byte().get_num_bytes(), 0)
+ #create the packet demodulator (handles the input data stream)
+ packet_demod = blks.demod_pkts(
+ fg=self,
+ demodulator=demodulator,
+ access_code=access_code,
+ callback=callback,
+ threshold=threshold,
+ )
+ #connections
+ self.connect(msg_source, self)
+ self.connect(self, packet_demod.head)
+
+#######################################################################################
+## Packet Modulator and Demodulator Defs
+#######################################################################################
+
+def PacketMod(sb):
+ blks.mod_pkts, gr.throttle, gr.message_sink #uses
+ type = Enum(all_choices, 1)
+ sb.add_input_socket('in', Variable(type)) #packet input
+ sb.add_output_socket('out', Byte())
+ sb.add_param('Type', type, False, type=True)
+ sb.add_param('Modulator Type', Enum([
+ ('GMSK', blks.gmsk_mod),
+ ('DBPSK', blks.dbpsk_mod),
+ ('DQPSK', blks.dqpsk_mod),
+ ('D8PSK', blks.d8psk_mod),
+ ('QAM 8', blks.qam8_mod),
+ ('QAM 64', blks.qam64_mod),
+ ('QAM 256', blks.qam256_mod),
+ ]))
+ sb.add_param('Samples/Symbol', Int(2, min=2))
+ sb.add_param('Packet Length', Int(DEFAULT_PACKET_LENGTH, min=1,
max=MAX_PACKET_LENGTH))
+ sb.add_param('Access Code', String('', max=MAX_ACCESS_CODE_LENGTH))
+ sb.add_param('Pad for USRP', Bool(true='Yes', false='No', default=True))
+ sb.add_param('Use Whitener Offset', Bool(true='Yes', false='No',
default=False))
+ sb.set_docs('''\
+The packet modulator wraps a data stream into packets.
+---
+Modulator type: tells the packet modulator how many bits per symbol to use. \
+A modulator block should still be connected to the output of this block.
+
+Packet length: length of a packet in bytes, must be a multiple of the size of
the input data stream, and no greater than %d.
+
+Access code/sync vector: string of 1's and 0's between 1 and %d long. Leave
blank for default.
+
+Pad for USRP: If true, packets are padded such that they end up a multiple of
128 samples.
+
+Use whitener offset: If true, start of whitener XOR string is incremented each
packet.
+'''%(MAX_PACKET_LENGTH, MAX_ACCESS_CODE_LENGTH))
+ def make(fg, type, mod_type, samples_per_symbol, packet_length,
access_code, pad_for_usrp, use_whitener_offset):
+ access_code = access_code.parse()
+ if access_code == '': access_code = None #access code
should be None if blank
+ item_size = type.parse().get_num_bytes()
+ packet_length = packet_length.parse()
+ if packet_length%item_size != 0: #verify that packet
length is a multiple of the stream size
+ raise ValueError('The packet length: "%d" is not a
mutiple of the stream size: "%d".'%(packet_length, item_size))
+ return PacketModHelper(
+ item_size=item_size,
+ packet_length=packet_length,
+ samples_per_symbol=samples_per_symbol.parse(),
+ bits_per_symbol=mod_type.parse().bits_per_symbol(),
+ access_code=access_code,
+ pad_for_usrp=pad_for_usrp.parse(),
+ use_whitener_offset=use_whitener_offset.parse(),
+ ) #build packet modulator
+ return sb, make
+
+def PacketDemod(sb):
+ blks.demod_pkts, gr.throttle, gr.message_source #uses
+ type = Enum(all_choices, 1)
+ sb.add_output_socket('out', Variable(type)) #packet output
+ sb.add_input_socket('in', Byte())
+ sb.add_param('Type', type, False, type=True)
+ sb.add_param('Access Code', String('', max=MAX_ACCESS_CODE_LENGTH))
+ sb.add_param('Threshold', Int(-1))
+ sb.set_docs('''\
+The packet demodulator unwraps packets from a data stream.
+---
+Access code/sync vector: string of 1's and 0's between 1 and %d long. Leave
blank for default.
+
+Threshold: detect access_code with up to threshold bits wrong.
+
+Queue limit: maximum number of messages in message queue.
+'''%MAX_ACCESS_CODE_LENGTH)
+ def make(fg, type, access_code, threshold):
+ access_code = access_code.parse()
+ if access_code == '': access_code = None #access code
should be None if blank
+ return PacketDemodHelper(
+ item_size=type.parse().get_num_bytes(),
+ access_code=access_code,
+ threshold=threshold.parse(),
+ ) #build packet demodulator
+ return sb, make
+
+#######################################################################################
+## TUN/TAP Access Threads
+#######################################################################################
+
+IFF_TUN = 0x0001 # tunnel IP packets
+IFF_TAP = 0x0002 # tunnel ethernet frames
+IFF_NO_PI = 0x1000 # don't pass extra packet info
+IFF_ONE_QUEUE = 0x2000 # beats me ;)
+DEFAULT_TUN_DEVICE = '/dev/net/tun'
+DEFAULT_VIRTUAL_DEVICE = 'tun%d'
+DEFAULT_IP_ADDR = '10.0.0.1'
+
+def open_tun_interface(tun_device_filename=DEFAULT_TUN_DEVICE,
virtual_device_filename=DEFAULT_VIRTUAL_DEVICE):
+ """!
+ Open a virtual ethernet interface via the Tun/Tap framework.
+ An alternative function can be found: "from eunuchs.tuntap import
opentuntap"
+ @param tun_device_filename the path to the tun device
+ @param virtual_device_filename the name of the virtual device (to be
created)
+ @return a file descriptor to rw the device, name of the virtual device
(created)
+ """
+ from fcntl import ioctl
+ mode = IFF_TAP | IFF_NO_PI
+ TUNSETIFF = 0x400454ca
+ tun_fd = os.open(tun_device_filename, os.O_RDWR)
+ ifs = ioctl(tun_fd, TUNSETIFF, struct.pack("16sH",
virtual_device_filename, mode))
+ ifname = ifs[:16].strip("\x00")
+ return tun_fd, ifname
+
+class TunSinkThread(threading.Thread):
+ """
+ Thread to forward data from the message queue and to the virtual device.
+ """
+ def __init__(self, msgq, tun_fd, ifname):
+ """!
+ TunSinkThread contructor.
+ @param msgq the message queue with incoming data
+ @param tun_fd the file descriptor for the virtual device
+ @param ifname the name of virtual interface
+ """
+ self.msgq = msgq
+ self.tun_fd = tun_fd
+ threading.Thread.__init__(self)
+ self.setDaemon(1)
+ self.keep_running = True
+ self.start()
+ print 'Created tun sink thread for device "%s".'%ifname
+
+ def run(self):
+ """In an endless while loop: read the msgq and write to tun."""
+ while self.keep_running:
+ msg = self.msgq.delete_head() # blocking read of
message queue
+ os.write(self.tun_fd, msg.to_string())
+
+#######################################################################################
+## TUN/TAP Block Defs
+#######################################################################################
+
+def TunSink(sb):
+ gr.message_sink #uses
+ type = Enum(all_choices, 1)
+ sb.add_input_socket('in', Variable(type))
+ sb.add_param('Type', type, False, type=True)
+ sb.add_param('Tun Device', String(DEFAULT_TUN_DEVICE))
+ sb.add_param('Virtual Device', String(DEFAULT_VIRTUAL_DEVICE))
+ sb.add_param('IP Address', String(DEFAULT_IP_ADDR))
+ sb.set_docs('''\
+Write data from a gnuradio data stream into a virtual ethernet interface.
+---
+Tun Device: File path to the tun device.
+
+Virtual Device: Desired name for the virtual ethernet device. \
+"%d" will give the device a number starting at zero.
+
+IP Address: IP address for the virtual device, leave blank and device will not
be configured.
+''')
+ def make(fg, type, tun, virt, ip_addr):
+ item_size = type.parse().get_num_bytes()
+ msgq = gr.msg_queue(DEFAULT_QUEUE_LIMIT)
+ tun_fd, ifname = open_tun_interface(tun.parse(), virt.parse())
+ #try to set the ip address
+ ip_addr = ip_addr.parse()
+ if ip_addr: os.system('ifconfig %s %s'%(ifname, ip_addr))
+ TunSinkThread(msgq, tun_fd, ifname)
+ return gr.message_sink(item_size, msgq, False)
+ return sb, make
+
+
\ No newline at end of file
Modified: grc/trunk/src/SignalBlockDefs/SignalBlockConstants.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/SignalBlockConstants.py 2007-06-29
17:29:46 UTC (rev 5877)
+++ grc/trunk/src/SignalBlockDefs/SignalBlockConstants.py 2007-06-29
17:41:26 UTC (rev 5878)
@@ -16,14 +16,60 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- SignalBlockDefs/SignalBlockConstants.py
- Josh Blum
- Constants used by the signal block definitions.
-"""
address@hidden SignalBlockDefs.SignalBlockConstants
+#Constants used by the signal block definitions.
address@hidden Josh Blum
-from DataType import *
+from DataTypes import *
+from gnuradio import gr
+class ThrottleHelper(gr.hier_block2):
+ """A block with a throttle on the input or output."""
+ def __init__(self, item_size, samp_rate, block, position):
+ """!
+ ThrottleHelper contructor.
+ Create a throttle and append it to the block.
+ @param item_size the size of the gr data stream in bytes
+ @param block the gr block
+ @param position if true connect a throttle to the input of
block, otherwise the output
+ """
+ gr.hier_block2.__init__(
+ self, "throttle_helper",
+ gr.io_signature(1, 1, item_size),
+ gr.io_signature(1, 1, item_size)
+ )
+ throttle = gr.throttle(item_size, samp_rate)
+ if position: self.connect(self, throttle, block, self)
+ else: self.connect(self, block, throttle, self)
+
+class HierHelper(gr.hier_block2):
+ """Wrap a hier2 block around a hier block."""
+ def __init__(self, hier_block, item_size_in=0, item_size_out=0):
+ """!
+ HierHelper constructor.
+ An item size of zero means that there is no connection.
+ @param hier_block a regular hier block
+ @param item_size_in the size of the input data stream in bytes
+ @param item_size_out the size of the output data stream in
bytes
+ """
+ #io signatures
+ if item_size_in > 0: io_sig_in = gr.io_signature(1, 1,
item_size_in)
+ else: io_sig_in = gr.io_signature(0, 0, 0)
+ if item_size_out > 0: io_sig_out = gr.io_signature(1, 1,
item_size_out)
+ else: io_sig_out = gr.io_signature(0, 0, 0)
+ #initialize
+ gr.hier_block2.__init__(self, "hier_helper", io_sig_in,
io_sig_out)
+ #connect
+ if item_size_in > 0: self.connect(self, hier_block.head)
+ if item_size_out > 0: self.connect(hier_block.tail, self)
+
+##max number of sockets to draw on one side of a signal block.
+MAX_NUM_SOCKETS = 20
+
+##default message queue limit
+DEFAULT_QUEUE_LIMIT = 1
+
+##choices for an Enum of regular data types
all_choices = [
('Complex', Complex()),
('Float', Float()),
@@ -32,6 +78,7 @@
('Byte', Byte()),
]
+##choices for an Enum of vector data types
all_vector_choices = [
('Complex Vector', (ComplexVector(), Complex())),
('Float Vector', (FloatVector(), Float())),
@@ -40,8 +87,10 @@
('Byte Vector', (ByteVector(), Byte()))
]
+##default sampling rate
default_samp_rate = '$samp_rate'
+##possible audio rates for audio source/sink
audio_rates = [
('16KHz', int(16e3)),
('22.05KHz', int(22.05e3)),
@@ -50,8 +99,11 @@
('44.1KHz', int(44.1e3)),
('48KHz', int(48e3)),
]
+
+##index of the default audio rate
default_audio_rate_index = 3
+##default udp port for udp source/sink
default_udp_port = 3456
\ No newline at end of file
Modified: grc/trunk/src/SignalBlockDefs/SignalBlockTree.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/SignalBlockTree.py 2007-06-29 17:29:46 UTC
(rev 5877)
+++ grc/trunk/src/SignalBlockDefs/SignalBlockTree.py 2007-06-29 17:41:26 UTC
(rev 5878)
@@ -16,12 +16,9 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- SignalBlockDefs/SignalBlockTree.py
- Josh Blum
- The data structure to categorize the signal blocks,
- and to map id tags to block building functions.
-"""
address@hidden SignalBlockDefs.SignalBlockTree
+#The data structure to categorize the signal blocks, and to map id tags to
block building functions.
address@hidden Josh Blum
from Elements import SignalBlock
import Sources
@@ -35,7 +32,10 @@
import USRP
import Coders
import Trellis
+import Packet
+import Custom
+##A categorized list of all signal blocks
SB_TREE = [
('Sources', [
('Signal Source', Sources.SignalSource),
@@ -56,6 +56,7 @@
('Audio Sink', Sinks.AudioSink),
('USRP Sink', USRP.USRPSink),
('USRP Dual Sink', USRP.USRPDualSink),
+ ('Tun Sink', Packet.TunSink),
]),
('Graphical Sinks', [
('Numerical Sink',
GraphicalSinks.NumericalSink),
@@ -64,7 +65,7 @@
('Waterfall Sink',
GraphicalSinks.WaterfallSink),
('Constellation Sink',
GraphicalSinks.ConstellationSink),
]),
- ('Operations', [
+ ('Operators', [
('Add', Operators.Add),
('Subtract', Operators.Subtract),
('Multiply', Operators.Multiply),
@@ -95,6 +96,8 @@
('Unpack k Bits', Conversions.UnpackKBits),
('Binary Slicer', Conversions.BinarySlicer),
('Chunks to Symbols',
Conversions.ChunksToSymbols),
+ ('Map', Conversions.Map),
+ ('VCO', Conversions.VCO),
('Interleave', Conversions.Interleave),
('Deinterleave', Conversions.Deinterleave),
('Streams to Stream',
Conversions.StreamsToStream),
@@ -111,6 +114,7 @@
('Rational Resampler',
Filters.RationalResampler),
('IIR Filer', Filters.IIRFiler),
('Filter Delay', Filters.FilterDelay),
+ ('Channel Model', Filters.ChannelModel),
]),
('Filters', [
('Low Pass Filter', Filters.LowPassFilter),
@@ -126,29 +130,35 @@
('Downsample', Filters.Downsample),
('Upsample', Filters.Upsample),
('Fractional Resampler',
Filters.FractionalResampler),
+ ('Fractional Interpolator',
Filters.FractionalInterpolator),
('Automatic Gain Control',
Filters.AutomaticGainControl),
('Automatic Gain Control2',
Filters.AutomaticGainControl2),
+ ('Feed Forward AGC', Filters.FeedForwardAGC),
('CMA Filter', Filters.CMAFilter),
('Clock Recovery', Filters.ClockRecovery),
('FFT', Filters.FFT),
('IFFT', Filters.IFFT),
]),
('Modulators', [
- ('Frequency Modulation',
Modulators.FrequencyModulation),
- ('Phase Modulation',
Modulators.PhaseModulation),
- ('Quadrature Demodulation',
Modulators.QuadratureDemodulation),
+ ('Frequency Modulator',
Modulators.FrequencyMod),
+ ('Phase Modulator', Modulators.PhaseMod),
+ ('Quadrature Demodulator',
Modulators.QuadratureDemod),
('Costas Loop', Modulators.CostasLoop),
('Phase Locked Loop', Modulators.PLL),
('WFM Receive', Modulators.WFMReceive),
('WFM Transmit', Modulators.WFMTransmit),
('NBFM Receive', Modulators.NBFMReceive),
('NBFM Transmit', Modulators.NBFMTransmit),
- ('AM Demodulation', Modulators.AMDemod),
- ('FM Demodulation', Modulators.FMDemod),
- ('PSK Modulation', Modulators.PSKMod),
- ('PSK Demodulation', Modulators.PSKDemod),
- ('GMSK Modulation', Modulators.GMSKMod),
- ('GMSK Demodulation', Modulators.GMSKDemod),
+ ('AM Demodulator', Modulators.AMDemod),
+ ('FM Demodulator', Modulators.FMDemod),
+ ('PSK Modulator', Modulators.PSKMod),
+ ('PSK Demodulator', Modulators.PSKDemod),
+ ('GMSK Modulator', Modulators.GMSKMod),
+ ('GMSK Demodulator', Modulators.GMSKDemod),
+ ('QAM Modulator', Modulators.QAMMod),
+ ('QAM Demodulator', Modulators.QAMDemod),
+ ('Packet Modulator', Packet.PacketMod),
+ ('Packet Demodulator', Packet.PacketDemod),
]),
('Coders', [
('Constellation Decoder',
Coders.ConstellationDecoder),
@@ -169,16 +179,29 @@
]),
('Misc', [
('Throttle', Misc.Throttle),
+ ('Valve', Misc.Valve),
+ ('Selector', Misc.Selector),
('Head', Misc.Head),
('Skip Head', Misc.SkipHead),
('RMS', Misc.RMS),
('About', Misc.About),
('Note', Misc.Note),
]),
+ ('Custom', Custom.CUSTOM_BLOCKS),
]
-def get_signal_block(parent, coor, rot, lookup_tag, id,
signal_block_constructor=SignalBlock):
- """ Create a new signal based on a few input parameters. """
+def get_signal_block(parent=None, coor=(0,0), rot=0, lookup_tag='', id='',
signal_block_constructor=SignalBlock):
+ """!
+ Create a new signal block.
+ @param parent the flow graph
+ @param coor the (x,y) corrdinate
+ @param rot the rotation in degrees
+ @param lookup_tag the tag of the desired signal block
+ @param id the unique id for the new signal block
+ @param signal_block_constructor the contructor for a new signal block
+ @throw TagNotFoundException tag not found
+ @return (the signal block, a gnuradio signal block builder function)
tuple
+ """
sb = signal_block_constructor(parent, coor, rot, lookup_tag, id)
for category, signal_blocks in SB_TREE:
for tag, builder in signal_blocks:
@@ -191,7 +214,7 @@
tags_to_remove = list()
for tag in tags:
try:
- get_signal_block(None, (0,0), 0, tag[0], '')
+ get_signal_block(lookup_tag=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)
@@ -205,7 +228,7 @@
cats_to_remove = list()
for category,tags in SB_TREE:
if len(tags) == 0:
- print 'Removing category "%s", it was emptied...'%category
+ print 'Removing empty category "%s"...'%category
cats_to_remove.append((category,tags))
for cat in cats_to_remove: SB_TREE.remove(cat)
@@ -214,7 +237,8 @@
def __init__(self, value): self.value = value
def __str__(self): return 'Exception! The tag: %s could not be
found'%repr(self.value)
-def print_tags():
+def print_sb_tree():
+ """Print the signal block tree."""
for category,tags in TAGS:
print category
for tag in tags: print '\t%s'%tag[0]
Modified: grc/trunk/src/SignalBlockDefs/Sinks.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/Sinks.py 2007-06-29 17:29:46 UTC (rev
5877)
+++ grc/trunk/src/SignalBlockDefs/Sinks.py 2007-06-29 17:41:26 UTC (rev
5878)
@@ -16,16 +16,14 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- SignalBlockDefs/Sinks.py
- Josh Blum
- Various data sinks.
-"""
address@hidden SignalBlockDefs.Sinks
+#Various data sinks.
address@hidden Josh Blum
-from DataType import *
+from DataTypes import *
from gnuradio import gr
from SignalBlockConstants import *
-from Constants import DEFAULT_FILE_PATH
+from Constants import DEFAULT_FILE_PATH,MUTEX
def NullSink(sb):
type = Enum(all_choices, 1)
@@ -39,7 +37,6 @@
return sb, lambda fg, type, vlen:
gr.null_sink(type.parse().get_num_bytes()*vlen.parse())
def FileSink(sb):
- import Constants
type = Enum(all_choices, 1)
vlen = Int(1, min=1)
sb.add_input_socket('in', Variable(type), vlen=vlen)
@@ -85,44 +82,55 @@
import threading
import Variables
-import Numeric
+import numpy
class VariableSinkThread(threading.Thread):
- """ This thread will read the vector sink at the sampling rate,
- write the numeric value back to the variable,
- and re-parse the flow graph's callbacks. """
+ """
+ This thread will read the vector sink,
+ write the numeric value back to the variable,
+ and re-parse the flow graph's callbacks.
+ """
def __init__(self, fg, var_key, msgq):
- """ Create a new variable sink thread. """
+ """!
+ VariableSinkThread constructor.
+ @param fg the gr flow graph
+ @param var_key the variable key
+ @param msgq the message queue
+ """
self.fg = fg
self.var_key = var_key
self.msgq = msgq
threading.Thread.__init__(self)
- print 'Created variable sink thread for variable "%s"'%var_key
+ self.setDaemon(1)
+ self.keep_running = True
+ self.start()
+ print 'Created variable sink thread for variable "%s".'%var_key
def run(self):
- """ In a endless while loop: read the vector sink,
- write to the variable, and parse the callbacks. """
- while True:
- try:
- msg = self.msgq.delete_head() # blocking read
of message queue
- itemsize = int(msg.arg1())
- nitems = int(msg.arg2())
- s = msg.to_string() # get the body
of the msg as a string
- # There may be more than one number in the
message.
- # If so, we take only the last one
- if nitems > 1:
- start = itemsize * (nitems - 1)
- s = s[start:start+itemsize]
- # 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],)
- # 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
+ """
+ In an endless while loop: read the vector sink,
+ write to the variable, and parse the callbacks.
+ """
+ while self.keep_running:
+ msg = self.msgq.delete_head() # blocking read of
message queue
+ itemsize = int(msg.arg1())
+ nitems = int(msg.arg2())
+ s = msg.to_string() # get the body of the
msg as a string
+ # There may be more than one number in the message.
+ # If so, we take only the last one
+ if nitems > 1:
+ start = itemsize * (nitems - 1)
+ s = s[start:start+itemsize]
+ # parse the data to a complex or float/int string
#
+ complex_data = numpy.fromstring (s, numpy.float32)
+ if len(complex_data) == 2: new_value = "%f +
%fj"%(complex_data[0], complex_data[1])
+ else: new_value = "%f"%(complex_data[0],)
+ #MUTEX.lock()
+ # write the new value #
+ Variables.reregister(self.var_key, new_value)
+ # parse the call backs #
+ self.fg.parse_callbacks()
+ #MUTEX.unlock()
def VariableSink(sb):
type = Enum(all_choices, 1)
@@ -136,14 +144,11 @@
The variable must be specified using its name without the "$" symbol. \
The variable sink has a throttle automatically attatched to it at runtime to
save the CPU.''')
def make(fg, type, var_key, samp_rate):
- msgq = gr.msg_queue(1) #msg size of 1
- block = gr.message_sink(type.parse().get_num_bytes(), msgq,
True)
+ msgq = gr.msg_queue(DEFAULT_QUEUE_LIMIT)
+ item_size = type.parse().get_num_bytes()
+ block = gr.message_sink(item_size, msgq, True)
var_sink_thread = VariableSinkThread(fg, var_key.parse(), msgq)
- var_sink_thread.start() #the thread begins
- th = gr.throttle(type.parse().get_num_bytes(),
samp_rate.parse())
- fg.connect(th, block)
- return th
- return sb, make
+ return ThrottleHelper(item_size, samp_rate.parse(), block, True)
+ return sb, make
-
\ No newline at end of file
Modified: grc/trunk/src/SignalBlockDefs/Sources.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/Sources.py 2007-06-29 17:29:46 UTC (rev
5877)
+++ grc/trunk/src/SignalBlockDefs/Sources.py 2007-06-29 17:41:26 UTC (rev
5878)
@@ -16,16 +16,15 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- SignalBlockDefs/Sources.py
- Josh Blum
- Various data sources.
-"""
address@hidden SignalBlockDefs.Sources
+#Various data sources.
address@hidden Josh Blum
-from DataType import *
+from DataTypes import *
from gnuradio import gr
from SignalBlockConstants import *
from Constants import DEFAULT_FILE_PATH
+import random
MAX_SEED = 1000000 #constraint for seed generation in noise and random
source
@@ -38,10 +37,12 @@
return sb, lambda fg, type, vlen:
gr.null_source(type.parse().get_num_bytes()*vlen.parse())
def SignalSource(sb):
- type = Enum([('Complex', (gr.sig_source_c, Complex())),
- ('Float', (gr.sig_source_f, Float())),
- ('Int', (gr.sig_source_i, Int())),
- ('Short', (gr.sig_source_s,
Short())),], 1)
+ type = Enum([
+ ('Complex', (gr.sig_source_c, Complex())),
+ ('Float', (gr.sig_source_f, Float())),
+ ('Int', (gr.sig_source_i, Int())),
+ ('Short', (gr.sig_source_s, Short())),
+ ], 1)
wfm_types = [('Constant', gr.GR_CONST_WAVE),
('Cosine', gr.GR_COS_WAVE),
('Sine', gr.GR_SIN_WAVE),]
@@ -51,11 +52,11 @@
except: print ">>> sig source missing sqr, tri, saw waveform types"
sb.add_output_socket('out', Variable(type, index=1))
sb.add_param('Type', type, False, type=True)
- sb.add_param('Sampling Rate', Float(default_samp_rate))
+ sb.add_param('Sampling Rate', Float(default_samp_rate), variable=True)
sb.add_param('Wave Form', Enum(wfm_types, 1))
- sb.add_param('Frequency', Float(1000))
- sb.add_param('Ampliude', Float(1))
- sb.add_param('Offset', Variable(type, index=1))
+ sb.add_param('Frequency', Float(1000), variable=True)
+ sb.add_param('Ampliude', Float(1), variable=True)
+ sb.add_param('Offset', Variable(type, index=1), variable=True)
def make(fg, type, samp_freq, waveform, freq, amplitude, offset):
block = type.parse()[0](samp_freq.parse(), waveform.parse(),
freq.parse(), amplitude.parse(), offset.parse())
fg.add_callback(block.set_sampling_freq, samp_freq)
@@ -66,18 +67,19 @@
return sb, make
def NoiseSource(sb):
- import random
- type = Enum([('Complex', (gr.noise_source_c, Complex())),
- ('Float', (gr.noise_source_f,
Float())),
- ('Int', (gr.noise_source_i, Int())),
- ('Short', (gr.noise_source_s,
Short())),], 1)
+ type = Enum([
+ ('Complex', (gr.noise_source_c, Complex())),
+ ('Float', (gr.noise_source_f, Float())),
+ ('Int', (gr.noise_source_i, Int())),
+ ('Short', (gr.noise_source_s, Short())),
+ ], 1)
sb.add_output_socket('out', Variable(type, index=1))
sb.add_param('Type', type, False, type=True)
sb.add_param('Noise Type', Enum([('Uniform', gr.GR_UNIFORM),
('Gaussian', gr.GR_GAUSSIAN),
('Laplacian', gr.GR_LAPLACIAN),
('Impulse', gr.GR_IMPULSE)],1))
- sb.add_param('Ampliude', Float(.1))
+ sb.add_param('Ampliude', Float(.1), variable=True)
sb.add_param('Seed', Int(random.randint(0, MAX_SEED), min=0,
max=MAX_SEED))
def make(fg, type, noise_type, amplitude, seed):
block = type.parse()[0](noise_type.parse(), amplitude.parse(),
seed.parse())
@@ -86,7 +88,6 @@
return sb, make
def FileSource(sb):
- import Constants
type = Enum(all_choices, 1)
vlen = Int(1, min=1)
sb.add_output_socket('out', Variable(type), vlen=vlen)
@@ -105,11 +106,13 @@
return sb, lambda fg, samp_rate: audio.source(samp_rate.parse())
def VectorSource(sb):
- enum_all_vector_data_types = Enum([('Complex Vector',
(gr.vector_source_c, ComplexVector(), Complex())),
- ('Float
Vector', (gr.vector_source_f, FloatVector(), Float())),
- ('Int
Vector', (gr.vector_source_i, IntVector(), Int())),
- ('Short
Vector', (gr.vector_source_s, ShortVector(), Short())),
- ('Byte
Vector', (gr.vector_source_b, ByteVector(), Byte()))], 1)#index of 1 makes the
default float
+ enum_all_vector_data_types = Enum([
+ ('Complex Vector', (gr.vector_source_c, ComplexVector(),
Complex())),
+ ('Float Vector', (gr.vector_source_f, FloatVector(), Float())),
+ ('Int Vector', (gr.vector_source_i, IntVector(), Int())),
+ ('Short Vector', (gr.vector_source_s, ShortVector(), Short())),
+ ('Byte Vector', (gr.vector_source_b, ByteVector(), Byte()))
+ ], 1)#index of 1 makes the default float
sb.add_output_socket('out', Variable(enum_all_vector_data_types,
index=2))
sb.add_param('Type', enum_all_vector_data_types, False, type=True)
sb.add_param('Vector', Variable(enum_all_vector_data_types, "0, 1",
index=1))
@@ -120,11 +123,12 @@
return sb, lambda fg, type, vector, repeat:
type.parse()[0](vector.parse(), repeat.parse())
def RandomVector(sb):
- import random
- enum_all_vector_data_types = Enum([('Float', (gr.vector_source_f,
Float())),
- ('Int',
(gr.vector_source_i, Int())),
-
('Short', (gr.vector_source_s, Short())),
-
('Byte', (gr.vector_source_b, Byte()))])
+ enum_all_vector_data_types = Enum([
+ ('Float', (gr.vector_source_f, Float())),
+ ('Int', (gr.vector_source_i, Int())),
+ ('Short', (gr.vector_source_s, Short())),
+ ('Byte', (gr.vector_source_b, Byte()))
+ ])
sb.add_output_socket('out', Variable(enum_all_vector_data_types,
index=1))
sb.add_param('Type', enum_all_vector_data_types, False, type=True)
sb.add_param('Vector Length', Int(1000, min=1))
Modified: grc/trunk/src/SignalBlockDefs/Trellis.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/Trellis.py 2007-06-29 17:29:46 UTC (rev
5877)
+++ grc/trunk/src/SignalBlockDefs/Trellis.py 2007-06-29 17:41:26 UTC (rev
5878)
@@ -16,13 +16,11 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- SignalBlockDefs/Trellis.py
- Josh Blum
- Trellis Blocks by: Achilleas Anastasopoulos
-"""
address@hidden SignalBlockDefs.Trellis
+#Trellis blocks.
address@hidden Achilleas Anastasopoulos
-from DataType import *
+from DataTypes import *
from gnuradio import gr
from SignalBlockConstants import all_choices
from Constants import DEFAULT_FILE_PATH
Modified: grc/trunk/src/SignalBlockDefs/USRP.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/USRP.py 2007-06-29 17:29:46 UTC (rev
5877)
+++ grc/trunk/src/SignalBlockDefs/USRP.py 2007-06-29 17:41:26 UTC (rev
5878)
@@ -16,18 +16,21 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- SignalBlockDefs/USRP.py
- Josh Blum
- The source and sink blocks for the USRP.
-"""
address@hidden SignalBlockDefs.USRP
+#The source and sink blocks for the USRP.
address@hidden Josh Blum
-from DataType import *
+from DataTypes import *
from gnuradio import gr
def set_freq(u, which, subdev, freq, verbose=False):
- """ Set the center frequency for the given subdevice.
- The which paramater specifies which DDC/DUC to use """
+ """!
+ Set the carrier frequency for the given subdevice.
+ @param u the usrp source/sink
+ @param which specifies the DDC/DUC number
+ @param freq the carrier frequency in Hz
+ @param verbose if true, print usrp tuning information
+ """
r = u.tune(which, subdev, freq)
if verbose:
if r:
@@ -36,29 +39,24 @@
print " r.dxc_freq =", r.dxc_freq
print " r.residual_freq =", r.residual_freq
print " r.inverted =", r.inverted
- else:
- print " Failed!"
+ else: print " Failed!"
-usrp_rx_choices = [('Auto', None),
- ('Side A:0', (0, 0)),
- ('Side B:0', (1, 0)),
- ('Side A:1', (0, 1)),
- ('Side B:1', (1, 1)),]
-
-usrp_tx_choices = [('Auto', None),
- ('Side A', (0, 0)),
- ('Side B', (1, 0)),]
-
def USRPSource(sb):
from gnuradio import usrp
type = Enum([('Complex', (usrp.source_c, Complex())), ('IShort',
(usrp.source_s, Short()))])
sb.add_output_socket('out', Variable(type, index=1))
sb.add_param('Output Type', type, False, type=True)
sb.add_param('Unit Number', Int(0, min=0))
- sb.add_param('Side:Subdevice', Enum(usrp_rx_choices))
- sb.add_param('Frequency', Float())
+ sb.add_param('Side:Subdevice', Enum([
+ ('Auto', None),
+ ('Side A:0', (0, 0)),
+ ('Side B:0', (1, 0)),
+ ('Side A:1', (0, 1)),
+ ('Side B:1', (1, 1)),
+ ]))
+ sb.add_param('Frequency', Float(), variable=True)
sb.add_param('Decimation', Int(200, min=1))
- sb.add_param('Gain', Float(100))
+ sb.add_param('Gain', Float(100), variable=True)
sb.add_param('Mux', Hex())
sb.set_docs('''\
The USRP source outputs 64 Megasamples per second / decimation.
@@ -88,10 +86,14 @@
sb.add_input_socket('in', Variable(type, index=1))
sb.add_param('Input Type', type, False, type=True)
sb.add_param('Unit Number', Int(0, min=0))
- sb.add_param('Side', Enum(usrp_tx_choices))
- sb.add_param('Frequency', Float())
+ sb.add_param('Side', Enum([
+ ('Auto', None),
+ ('Side A', (0, 0)),
+ ('Side B', (1, 0)),
+ ]))
+ sb.add_param('Frequency', Float(), variable=True)
sb.add_param('Interpolation', Int(200, min=1))
- sb.add_param('Gain', Float(0))
+ sb.add_param('Gain', Float(0), variable=True)
sb.add_param('Mux', Hex())
sb.set_docs('''\
The USRP sink inputs 128 Megasamples per second / interpolation.
@@ -123,11 +125,11 @@
sb.add_input_socket('Bin', Variable(type, index=1))
sb.add_param('Input Type', type, False, type=True)
sb.add_param('Unit Number', Int(0, min=0))
- sb.add_param('FrequencyA', Float())
- sb.add_param('FrequencyB', Float())
+ sb.add_param('FrequencyA', Float(), variable=True)
+ sb.add_param('FrequencyB', Float(), variable=True)
sb.add_param('Interpolation', Int(200, min=1))
- sb.add_param('GainA', Float(0))
- sb.add_param('GainB', Float(0))
+ sb.add_param('GainA', Float(0), variable=True)
+ sb.add_param('GainB', Float(0), variable=True)
sb.add_param('Mux', Hex(default_mux))
sb.set_docs('''\
The USRP sink inputs 128 Megasamples per second / interpolation. \
Modified: grc/trunk/src/SignalBlockDefs/__init__.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/__init__.py 2007-06-29 17:29:46 UTC (rev
5877)
+++ grc/trunk/src/SignalBlockDefs/__init__.py 2007-06-29 17:41:26 UTC (rev
5878)
@@ -16,11 +16,8 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- SignalBlockDefs/__init__.py
- Josh Blum
- Build a signal block represented by a specific tag.
-"""
address@hidden SignalBlockDefs.__init__
+#Package for signal block definitions.
address@hidden Josh Blum
-from DataType import *
from SignalBlockTree import SB_TREE,get_signal_block,TagNotFoundException
Modified: grc/trunk/src/StateCache.py
===================================================================
--- grc/trunk/src/StateCache.py 2007-06-29 17:29:46 UTC (rev 5877)
+++ grc/trunk/src/StateCache.py 2007-06-29 17:41:26 UTC (rev 5878)
@@ -16,23 +16,25 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- StateCache.py
- Josh Blum
- Stores the flow graph states to drive the undo/redo and save interface.
-"""
address@hidden StateCache
+#Stores the flow graph states to drive the undo/redo and save interface.
address@hidden Josh Blum
from Actions import FLOW_GRAPH_UNDO, FLOW_GRAPH_REDO, get_action_from_name
from Constants import STATE_CACHE_SIZE
class StateCache:
- """ The state cache is an interface to a list to record data/states and
to revert to previous states. """
+ """
+ The state cache is an interface to a list to record data/states and to
revert to previous states.
+ States are recorded into the list in a circular fassion by using an
index for the current state,
+ and counters for the range where states are stored.
+ """
def __init__(self, initial_state):
- """ The initial state is given as well as the handler for the
windows
- so that redo/undo/save can be properly handled. """
- self.states = list()
- for i in range(STATE_CACHE_SIZE):
- self.states.append(None)
+ """!
+ StateCache constructor.
+ @param initial_state the intial state (nested data)
+ """
+ self.states = [None for i in range(STATE_CACHE_SIZE)] #fill
states
self.current_state_index = 0
self.num_prev_states = 0
self.num_next_states = 0
@@ -41,40 +43,50 @@
get_action_from_name(FLOW_GRAPH_REDO).set_sensitive(False)
def save_new_state(self, state):
- """ Place the new state at the next index and add one to the
number of previous states. """
+ """!
+ Save a new state.
+ Place the new state at the next index and add one to the number
of previous states.
+ @param state the new state
+ """
self.current_state_index = (self.current_state_index +
1)%STATE_CACHE_SIZE
self.states[self.current_state_index] = state
self.num_prev_states = self.num_prev_states + 1
- if self.num_prev_states == STATE_CACHE_SIZE:
- self.num_prev_states = STATE_CACHE_SIZE - 1
+ if self.num_prev_states == STATE_CACHE_SIZE:
self.num_prev_states = STATE_CACHE_SIZE - 1
self.num_next_states = 0
get_action_from_name(FLOW_GRAPH_UNDO).set_sensitive(True)
get_action_from_name(FLOW_GRAPH_REDO).set_sensitive(False)
def get_current_state(self):
- """ get the state at the current index """
+ """!
+ Get the state at the current index.
+ @return the current state (nested data)
+ """
return self.states[self.current_state_index]
def get_prev_state(self):
- """ get the previous state if possible and decrement the
current index. """
+ """!
+ Get the previous state and decrement the current index.
+ @return the previous state or None
+ """
if self.num_prev_states > 0:
self.current_state_index = (self.current_state_index +
STATE_CACHE_SIZE -1)%STATE_CACHE_SIZE
self.num_next_states = self.num_next_states + 1
self.num_prev_states = self.num_prev_states - 1
- if self.num_prev_states == 0:
-
get_action_from_name(FLOW_GRAPH_UNDO).set_sensitive(False)
+ if self.num_prev_states == 0:
get_action_from_name(FLOW_GRAPH_UNDO).set_sensitive(False)
get_action_from_name(FLOW_GRAPH_REDO).set_sensitive(True)
return self.get_current_state()
return None
def get_next_state(self):
- """ get the next state if possible and increment the
current index. """
+ """!
+ Get the nest state and increment the current index.
+ @return the next state or None
+ """
if self.num_next_states > 0:
self.current_state_index = (self.current_state_index +
1)%STATE_CACHE_SIZE
self.num_next_states = self.num_next_states - 1
self.num_prev_states = self.num_prev_states + 1
- if self.num_next_states == 0:
-
get_action_from_name(FLOW_GRAPH_REDO).set_sensitive(False)
+ if self.num_next_states == 0:
get_action_from_name(FLOW_GRAPH_REDO).set_sensitive(False)
get_action_from_name(FLOW_GRAPH_UNDO).set_sensitive(True)
return self.get_current_state()
return None
Modified: grc/trunk/src/Variables.py
===================================================================
--- grc/trunk/src/Variables.py 2007-06-29 17:29:46 UTC (rev 5877)
+++ grc/trunk/src/Variables.py 2007-06-29 17:41:26 UTC (rev 5878)
@@ -16,40 +16,48 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-"""
- Variables.py
- Josh Blum
- Holds variable names, their values, and ranges.
-"""
address@hidden Variables
+#Holds variable names, their values, and ranges.
address@hidden Josh Blum
from Constants import DEFAULT_SLIDER_STEPS
-''' Hold the current variables for the running program. The dictionary
- maps keys to values,ranges. '''
+##Hold the variables for the executing program. This dictionary maps keys to
values,ranges.
VARS_DICT = dict()
-VAR_MARKER = '$' #place this character before a variable
+##place this character before a variable
+VAR_MARKER = '$'
-get_keys = VARS_DICT.keys #get a list of variable keys
+##get a list of variable keys
+get_keys = VARS_DICT.keys
def clear_vars():
- ''' Call unregister on every var. '''
+ """Call unregister on every var key."""
for key in VARS_DICT.keys(): unregister(key)
def register(key, value, min='', max='', step=''):
- ''' Change/Add the value,range for a given key.
+ """!
+ Register the value and a [range] for a given key.
+ The range is a min, max, and a step size.
If no range is specified, value can be any string.
If a range is specified min, max, and step numbers have to be parsable
as floats.
Partially completed ranges will be intelligently filled in.
Partially blanked ranges will be cleared.
- All parameters must be strings! '''
+ All parameters must be strings!
+ @param key the variable key
+ @param value the value
+ @param min the mimimum of the variable's range
+ @param max the maximum of the variable's range
+ @param step the step size for the variable's range
+ @throw Exception invalid arguments
+ """
# 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)
+ if type(var) != type(str()): raise TypeError, '"%s" var is not
of type string'%var
# make sure that the key does not already exists #
- if has_key(key): raise KeyError('"%s" already exists!'%key)
+ if has_key(key): raise KeyError, '"%s" already exists!'%key
# make sure that the key name is valid #
- if not is_key_name_valid(key): raise KeyError('"%s" is a invalid key
name!'%key)
+ if not is_key_name_valid(key): raise KeyError, '"%s" is a invalid key
name!'%key
# count the number of blank strings in min, max, and step #
num_blanks = 0
for var in (min, max, step):
@@ -57,32 +65,57 @@
if num_blanks == 3: pass #allow the vars to be registered normally
else: #num_blanks is less than 3
try: float(value) #make sure that value is a float
- except ValueError: raise TypeError('"%s" must be parseable to
type float'%value)
+ except ValueError: raise TypeError, '"%s" must be parseable to
type float'%value
if num_blanks == 2: #do something intelligent to fill the
two blanks
# make sure that the non-blank value is a float
#
for var in (min, max, step):
if var != '': #only try to parse the
non-blank variable
try: float(var) #make sure that value
is a float
- except ValueError: raise
TypeError('"%s" must be parseable to type float'%var)
+ except ValueError: raise TypeError,
'"%s" must be parseable to type float'%var
# determine the non-blank var and generate the
other two vars #
if min != '': max = value
elif max != '': min = value
- elif step != '': raise ValueError('step cannot have a
value when min and max are blank')
+ elif step != '': raise ValueError, 'step cannot have a
value when min and max are blank'
elif num_blanks == 1: #clear all vars for min, max, and step
if step != '': min = max = step = '' #only if step was
not the blank one
elif num_blanks == 0: pass #none were blank, move onto the
validity check
# check the values for validity #
if min != '' and max != '': #only check for validity if min and max are
non blank
if float(value) < float(min) or float(value) > float(max) or
float(min) >= float(max):
- raise ValueError('%s is not greater than or equal to %s
and less than and equal to %s'%(value, min, max))
+ raise ValueError, '%s is not greater than or equal to
%s and less than and equal to %s'%(value, min, max)
if step == '': step = str((float(max) -
float(min))/float(DEFAULT_SLIDER_STEPS))
- if (float(max) - float(min))/float(step) < 1: raise
ValueError('%s step size is too large'%step)
+ if (float(max) - float(min))/float(step) < 1: raise ValueError,
'%s step size is too large'%step
### register the values ###
VARS_DICT[key] = (value, min, max, step)
+def reregister(key, new_value):
+ """!
+ Register a new value for variable:
+ Unregister the variable and try to register it with the new values.
+ If an exception is raised, register the old values.
+ @param key the variable key
+ @param new_value the value
+ @throw Exception invalid arguments
+ @return true if the variable was registered
+ """
+ value, min, max, step = get_values(key)
+ if new_value != value:
+ unregister(key)
+ try:
+ register(key, new_value, min, max, step)
+ return True
+ except Exception, e:
+ register(key, value, min, max, step)
+ raise e
+ else: return False
+
def is_key_name_valid(key_name):
- ''' True if the key name is valid. Valid keys start with a letter and
- may contain only letters, numbers, underscrores(_). '''
+ """!
+ Is the key valid?
+ Valid keys start with a letter and may contain only letters, numbers,
underscrores(_).
+ @param key_name the potential key name (string)
+ @return true if the key name is valid
+ """
if len(key_name) == 0 or len(key_name) > 20: return False
for i,char in enumerate(key_name):
if i == 0 and not char.isalpha(): return False
@@ -90,31 +123,52 @@
return True
def unregister(key):
- ''' Remove a key if it exisits '''
+ """!
+ Remove a key if it exisits.
+ @param key the variable key to remove
+ """
if has_key(key): del VARS_DICT[key]
def has_key(key):
- ''' Is the key in this dict? '''
+ """!
+ Is the key in this registry?
+ @param key the variable key potentially in the registry
+ @return true if key is in the registry
+ """
return key in VARS_DICT
def get_values(key):
- ''' Get the tuple for this key, otherwise None. '''
- if has_key(key): return VARS_DICT[key]
- else: return None
+ """!
+ Get the valuesfor this key.
+ @param key the variable key
+ @return the (value,min,max,step) tuple
+ """
+ return VARS_DICT[key]
def is_ranged(key):
- ''' Does this variable have a range:
- min, max, and step are not blank. '''
+ """!
+ Does this variable have a range?
+ The variable has a range if min, max, and step are non-blank.
+ Only check the minimum for non-blankness.
+ @param key the variable key
+ @return true if the variable has a range
+ """
return get_values(key)[1] != ''
def get_value(key):
- ''' Get the value for this key, otherwise None. '''
- if has_key(key): return VARS_DICT[key][0]
- else: return None
+ """!
+ Get the value for this key.
+ @param key the variable key
+ @return the value
+ """
+ return get_values(key)[0]
def replace_var_instances(string):
- ''' Replace every instance of a marker + variable key
- with the string representation of the variable. '''
+ """!
+ Replace every instance of a marker + variable key with the string
representation of the variable.
+ @param string the input string
+ @return the string with variables substituted out
+ """
for key in get_keys(): string = string.replace(VAR_MARKER + key,
get_value(key))
return string
@@ -122,9 +176,13 @@
## 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. '''
+ """!
+ Load the variables from nested data.
+ Clear all of the registered variables,
+ and load all variables from nested data.
+ @param nested_data the nested data for variables
+ @return a list of keys, in the order
+ """
import ParseXML,Messages
find_data = ParseXML.find_data
clear_vars()
@@ -155,9 +213,8 @@
pass #dont register!
return keys
-if __name__ == '__main__':
- print is_key_name_valid('sdfa13_fsf_dsd')
- print is_key_name_valid('2sdfa13_fsf_dsd')
- print is_key_name_valid('sdfa13._fsf_fdsd')
+if __name__ == '__main__':
+ """Use the main method to test variable's functions."""
+ pass
\ No newline at end of file
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Commit-gnuradio] r5878 - in grc/trunk: . examples examples/audio examples/xmlrpc notes src src/Elements src/Graphics src/SignalBlockDefs,
jblum <=