diff options
Diffstat (limited to 'grc')
27 files changed, 552 insertions, 9 deletions
diff --git a/grc/base/Block.py b/grc/base/Block.py index fe7ad3c2f..a20be9db9 100644 --- a/grc/base/Block.py +++ b/grc/base/Block.py @@ -67,6 +67,7 @@ class Block(Element): self._name = n.find('name') self._key = n.find('key') self._category = n.find('category') or '' + self._grc_source = n.find('grc_source') or '' self._block_wrapper_path = n.find('block_wrapper_path') #create the param objects self._params = list() diff --git a/grc/base/Platform.py b/grc/base/Platform.py index 94d0077ea..d4b09088b 100644 --- a/grc/base/Platform.py +++ b/grc/base/Platform.py @@ -61,6 +61,10 @@ class Platform(_Element): #create a dummy flow graph for the blocks self._flow_graph = _Element(self) #search for *.xml files in the given search path + + self.loadblocks(); + + def loadblocks(self): xml_files = list() for block_path in self._block_paths: if os.path.isfile(block_path): xml_files.append(block_path) diff --git a/grc/blocks/block_tree.xml b/grc/blocks/block_tree.xml index d7ec82e4a..183883959 100644 --- a/grc/blocks/block_tree.xml +++ b/grc/blocks/block_tree.xml @@ -37,6 +37,15 @@ <block>virtual_sink</block> <block>gr_tag_debug</block> </cat> + <cat> + <name>Message Tools</name> + <block>gr_message_debug</block> + <block>gr_message_strobe</block> + <block>gr_pdu_to_tagged_stream</block> + <block>gr_tagged_stream_to_pdu</block> + <block>gr_tuntap_pdu</block> + <block>gr_socket_pdu</block> + </cat> <cat> <name>Operators</name> <block>gr_add_xx</block> diff --git a/grc/blocks/gr_file_source.xml b/grc/blocks/gr_file_source.xml index fcc7a7040..5f0e16b27 100644 --- a/grc/blocks/gr_file_source.xml +++ b/grc/blocks/gr_file_source.xml @@ -9,6 +9,7 @@ <key>gr_file_source</key> <import>from gnuradio import gr</import> <make>gr.file_source($type.size*$vlen, $file, $repeat)</make> + <callback>open($file, $repeat)</callback> <param> <name>File</name> <key>file</key> diff --git a/grc/blocks/gr_message_debug.xml b/grc/blocks/gr_message_debug.xml new file mode 100644 index 000000000..4d73fbd9c --- /dev/null +++ b/grc/blocks/gr_message_debug.xml @@ -0,0 +1,27 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Message Debug +################################################### + --> +<block> + <name>Message Debug</name> + <key>gr_message_debug</key> + <import>from gnuradio import gr</import> + <make>gr.message_debug()</make> + <sink> + <name>print</name> + <type>message</type> + <optional>1</optional> + </sink> + <sink> + <name>store</name> + <type>message</type> + <optional>1</optional> + </sink> + <sink> + <name>print_pdu_verbose</name> + <type>message</type> + <optional>1</optional> + </sink> +</block> diff --git a/grc/blocks/gr_message_strobe.xml b/grc/blocks/gr_message_strobe.xml new file mode 100644 index 000000000..60a7724df --- /dev/null +++ b/grc/blocks/gr_message_strobe.xml @@ -0,0 +1,35 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Message Strobe +################################################### + --> +<block> + <name>Message Strobe</name> + <key>gr_message_strobe</key> + <import>from gnuradio import gr</import> + <import>from gruel import pmt</import> + <make>gr.message_strobe($msg, $period)</make> + <param> + <name>Message PMT</name> + <key>msg</key> + <value>pmt.pmt_intern("TEST")</value> + <type>raw</type> + </param> + <param> + <name>Period (ms)</name> + <key>period</key> + <value>1000</value> + <type>real</type> + </param> + <sink> + <name>set_msg</name> + <type>message</type> + <optional>1</optional> + </sink> + <source> + <name>strobe</name> + <type>message</type> + <optional>1</optional> + </source> +</block> diff --git a/grc/blocks/gr_pdu_to_tagged_stream.xml b/grc/blocks/gr_pdu_to_tagged_stream.xml new file mode 100644 index 000000000..fc1c4d16a --- /dev/null +++ b/grc/blocks/gr_pdu_to_tagged_stream.xml @@ -0,0 +1,40 @@ +<?xml version="1.0"?> +<!-- +################################################### +## PDU Message to Tagged Stream +################################################### + --> +<block> + <name>PDU to Tagged Stream</name> + <key>gr_pdu_to_tagged_stream</key> + <import>from gnuradio import gr</import> + <make>gr.pdu_to_tagged_stream($type.tv)</make> + <param> + <name>Item Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Byte</name> + <key>byte</key> + <opt>tv:gr.BYTE</opt> + </option> + <option> + <name>Complex</name> + <key>complex</key> + <opt>tv:gr.COMPLEX</opt> + </option> + <option> + <name>Float</name> + <key>float</key> + <opt>tv:gr.FLOAT</opt> + </option> + </param> + <sink> + <name>pdus</name> + <type>message</type> + </sink> + <source> + <name>out</name> + <type>$type</type> + </source> +</block> diff --git a/grc/blocks/gr_socket_pdu.xml b/grc/blocks/gr_socket_pdu.xml new file mode 100644 index 000000000..a175c3699 --- /dev/null +++ b/grc/blocks/gr_socket_pdu.xml @@ -0,0 +1,62 @@ +<?xml version="1.0"?> +<!-- +################################################### +## Socket PDU Message source/sink +################################################### + --> +<block> + <name>Socket PDU</name> + <key>gr_socket_pdu</key> + <import>from gnuradio import gr</import> + <make>gr.socket_pdu($type, $host, $port, $mtu)</make> + <param> + <name>Type</name> + <key>type</key> + <value>TCP_SERVER</value> + <type>enum</type> + <option> + <name>TCP Server</name> + <key>"TCP_SERVER"</key> + </option> + <option> + <name>TCP Client</name> + <key>"TCP_CLIENT"</key> + </option> + <option> + <name>UDP Server</name> + <key>"UDP_SERVER"</key> + </option> + <option> + <name>UDP Client</name> + <key>"UDP_CLIENT"</key> + </option> + </param> + <param> + <name>Host</name> + <key>host</key> + <value></value> + <type>string</type> + </param> + <param> + <name>Port</name> + <key>port</key> + <value>52001</value> + <type>string</type> + </param> + <param> + <name>MTU</name> + <key>mtu</key> + <value>10000</value> + <type>int</type> + </param> + <sink> + <name>pdus</name> + <type>message</type> + <optional>1</optional> + </sink> + <source> + <name>pdus</name> + <type>message</type> + <optional>1</optional> + </source> +</block> diff --git a/grc/blocks/gr_sub_xx.xml b/grc/blocks/gr_sub_xx.xml index f1f4797e0..c677747da 100644 --- a/grc/blocks/gr_sub_xx.xml +++ b/grc/blocks/gr_sub_xx.xml @@ -48,7 +48,7 @@ <type>int</type> </param> <check>$vlen > 0</check> - <check>$num_inputs >= 2</check> + <check>$num_inputs >= 1</check> <sink> <name>in</name> <type>$type</type> diff --git a/grc/blocks/gr_tagged_stream_to_pdu.xml b/grc/blocks/gr_tagged_stream_to_pdu.xml new file mode 100644 index 000000000..e70a01608 --- /dev/null +++ b/grc/blocks/gr_tagged_stream_to_pdu.xml @@ -0,0 +1,40 @@ +<?xml version="1.0"?> +<!-- +################################################### +## Tagged Stream to PDU Message +################################################### + --> +<block> + <name>Tagged Stream to PDU</name> + <key>gr_tagged_stream_to_pdu</key> + <import>from gnuradio import gr</import> + <make>gr.tagged_stream_to_pdu($type.tv)</make> + <param> + <name>Item Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Byte</name> + <key>byte</key> + <opt>tv:gr.BYTE</opt> + </option> + <option> + <name>Complex</name> + <key>complex</key> + <opt>tv:gr.COMPLEX</opt> + </option> + <option> + <name>Float</name> + <key>float</key> + <opt>tv:gr.FLOAT</opt> + </option> + </param> + <sink> + <name>in</name> + <type>$type</type> + </sink> + <source> + <name>pdus</name> + <type>message</type> + </source> +</block> diff --git a/grc/blocks/gr_tuntap_pdu.xml b/grc/blocks/gr_tuntap_pdu.xml new file mode 100644 index 000000000..f169345af --- /dev/null +++ b/grc/blocks/gr_tuntap_pdu.xml @@ -0,0 +1,34 @@ +<?xml version="1.0"?> +<!-- +################################################### +## Tuntap PDU Message source/sink +################################################### + --> +<block> + <name>TunTap PDU</name> + <key>gr_tuntap_pdu</key> + <import>from gnuradio import gr</import> + <make>gr.tuntap_pdu($ifn, $mtu)</make> + <param> + <name>Interface Name</name> + <key>ifn</key> + <value>tun0</value> + <type>string</type> + </param> + <param> + <name>MTU</name> + <key>mtu</key> + <value>10000</value> + <type>int</type> + </param> + <sink> + <name>pdus</name> + <type>message</type> + <optional>1</optional> + </sink> + <source> + <name>pdus</name> + <type>message</type> + <optional>1</optional> + </source> +</block> diff --git a/grc/blocks/pad_sink.xml b/grc/blocks/pad_sink.xml index 2e9495260..f0e10a339 100644 --- a/grc/blocks/pad_sink.xml +++ b/grc/blocks/pad_sink.xml @@ -7,7 +7,9 @@ <block> <name>Pad Sink</name> <key>pad_sink</key> - <make></make> + <make>#if str($type) == "message" +None;self.message_port_register_hier_in($label) +#end if</make> <param> <name>Label</name> <key>label</key> @@ -43,6 +45,16 @@ <key>byte</key> <opt>size:gr.sizeof_char</opt> </option> + <option> + <name>Message</name> + <key>message</key> + <opt>size:0</opt> + </option> + <option> + <name>Wildcard</name> + <key></key> + <opt>size:0</opt> + </option> </param> <param> <name>Vec Length</name> @@ -50,6 +62,21 @@ <value>1</value> <type>int</type> </param> + <param> + <name>Optional</name> + <key>optional</key> + <value>False</value> + <type>bool</type> + <hide>part</hide> + <option> + <name>Optional</name> + <key>True</key> + </option> + <option> + <name>Required</name> + <key>False</key> + </option> + </param> <check>$vlen > 0</check> <sink> <name>in</name> diff --git a/grc/blocks/pad_source.xml b/grc/blocks/pad_source.xml index 7b2210cbb..a56a65dcc 100644 --- a/grc/blocks/pad_source.xml +++ b/grc/blocks/pad_source.xml @@ -7,7 +7,9 @@ <block> <name>Pad Source</name> <key>pad_source</key> - <make></make> + <make>#if str($type) == "message" +None;self.message_port_register_hier_out($label) +#end if</make> <param> <name>Label</name> <key>label</key> @@ -43,6 +45,16 @@ <key>byte</key> <opt>size:gr.sizeof_char</opt> </option> + <option> + <name>Message</name> + <key>message</key> + <opt>size:0</opt> + </option> + <option> + <name>Wildcard</name> + <key></key> + <opt>size:0</opt> + </option> </param> <param> <name>Vec Length</name> @@ -50,6 +62,21 @@ <value>1</value> <type>int</type> </param> + <param> + <name>Optional</name> + <key>optional</key> + <value>False</value> + <type>bool</type> + <hide>part</hide> + <option> + <name>Optional</name> + <key>True</key> + </option> + <option> + <name>Required</name> + <key>False</key> + </option> + </param> <check>$vlen > 0</check> <source> <name>out</name> diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index 476c82b4f..9fb5e4ebf 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -53,6 +53,7 @@ class ActionHandler: self.clipboard = None for action in Actions.get_all_actions(): action.connect('activate', self._handle_action) #setup the main window + self.platform = platform; self.main_window = MainWindow(platform) self.main_window.connect('delete-event', self._quit) self.main_window.connect('key-press-event', self._handle_key_press) @@ -152,6 +153,134 @@ class ActionHandler: self.get_flow_graph().update() self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) self.get_page().set_saved(False) + ################################################## + # Create heir block + ################################################## + elif action == Actions.BLOCK_CREATE_HIER: + + # keeping track of coordinates for pasting later + coords = self.get_flow_graph().get_selected_blocks()[0].get_coordinate() + x,y = coords + x_min = x + y_min = y + + pads = []; + params = []; + + # Save the state of the leaf blocks + for block in self.get_flow_graph().get_selected_blocks(): + + # Check for string variables within the blocks + for param in block.get_params(): + for variable in self.get_flow_graph().get_variables(): + # If a block parameter exists that is a variable, create a parameter for it + if param.get_value() == variable.get_id(): + params.append(param.get_value()) + for flow_param in self.get_flow_graph().get_parameters(): + # If a block parameter exists that is a parameter, create a parameter for it + if param.get_value() == flow_param.get_id(): + params.append(param.get_value()) + + + # keep track of x,y mins for pasting later + (x,y) = block.get_coordinate() + if x < x_min: + x_min = x + if y < y_min: + y_min = y + + for connection in block.get_connections(): + + # Get id of connected blocks + source_id = connection.get_source().get_parent().get_id() + sink_id = connection.get_sink().get_parent().get_id() + + # If connected block is not in the list of selected blocks create a pad for it + if self.get_flow_graph().get_block(source_id) not in self.get_flow_graph().get_selected_blocks(): + pads.append({'key': connection.get_sink().get_key(), 'coord': connection.get_source().get_coordinate(), 'block_id' : block.get_id(), 'direction': 'source'}) + + if self.get_flow_graph().get_block(sink_id) not in self.get_flow_graph().get_selected_blocks(): + pads.append({'key': connection.get_source().get_key(), 'coord': connection.get_sink().get_coordinate(), 'block_id' : block.get_id(), 'direction': 'sink'}) + + + # Copy the selected blocks and paste them into a new page + # then move the flowgraph to a reasonable position + Actions.BLOCK_COPY() + self.main_window.new_page() + Actions.BLOCK_PASTE() + coords = (x_min,y_min) + self.get_flow_graph().move_selected(coords) + + + # Set flow graph to heir block type + top_block = self.get_flow_graph().get_block("top_block") + top_block.get_param('generate_options').set_value('hb') + + # this needs to be a unique name + top_block.get_param('id').set_value('new_heir') + + # Remove the default samp_rate variable block that is created + remove_me = self.get_flow_graph().get_block("samp_rate") + self.get_flow_graph().remove_element(remove_me) + + + # Add the param blocks along the top of the window + x_pos = 150 + for param in params: + param_id = self.get_flow_graph().add_new_block('parameter',(x_pos,10)) + param_block = self.get_flow_graph().get_block(param_id) + param_block.get_param('id').set_value(param) + x_pos = x_pos + 100 + + for pad in pads: + # Add the pad sources and sinks within the new heir block + if pad['direction'] == 'sink': + + # Add new PAD_SINK block to the canvas + pad_id = self.get_flow_graph().add_new_block('pad_sink', pad['coord']) + + # setup the references to the sink and source + pad_block = self.get_flow_graph().get_block(pad_id) + pad_sink = pad_block.get_sinks()[0] + + source_block = self.get_flow_graph().get_block(pad['block_id']) + source = source_block.get_source(pad['key']) + + # Ensure the port types match + while pad_sink.get_type() != source.get_type(): + + # Special case for some blocks that have non-standard type names, e.g. uhd + if pad_sink.get_type() == 'complex' and source.get_type() == 'fc32': + break; + pad_block.type_controller_modify(1) + + # Connect the pad to the proper sinks + new_connection = self.get_flow_graph().connect(source,pad_sink) + + elif pad['direction'] == 'source': + pad_id = self.get_flow_graph().add_new_block('pad_source', pad['coord']) + + # setup the references to the sink and source + pad_block = self.get_flow_graph().get_block(pad_id) + pad_source = pad_block.get_sources()[0] + + sink_block = self.get_flow_graph().get_block(pad['block_id']) + sink = sink_block.get_sink(pad['key']) + + # Ensure the port types match + while sink.get_type() != pad_source.get_type(): + # Special case for some blocks that have non-standard type names, e.g. uhd + if pad_source.get_type() == 'complex' and sink.get_type() == 'fc32': + break; + pad_block.type_controller_modify(1) + + # Connect the pad to the proper sinks + new_connection = self.get_flow_graph().connect(pad_source,sink) + + # update the new heir block flow graph + self.get_flow_graph().update() + + ################################################## # Move/Rotate/Delete/Create ################################################## @@ -263,6 +392,7 @@ class ActionHandler: else: try: ParseXML.to_file(self.get_flow_graph().export_data(), self.get_page().get_file_path()) + self.get_flow_graph().grc_file_path = self.get_page().get_file_path() self.get_page().set_saved(True) except IOError: Messages.send_fail_save(self.get_page().get_file_path()) @@ -302,6 +432,15 @@ class ActionHandler: except: print "could not kill process: %d"%self.get_page().get_proc().pid elif action == Actions.PAGE_CHANGE: #pass and run the global actions pass + elif action == Actions.RELOAD_BLOCKS: + self.platform.loadblocks() + self.main_window.btwin.clear(); + self.platform.load_block_tree(self.main_window.btwin); + elif action == Actions.OPEN_HIER: + bn = []; + for b in self.get_flow_graph().get_selected_blocks(): + if b._grc_source: + self.main_window.new_page(b._grc_source, show=True); else: print '!!! Action "%s" not handled !!!'%action ################################################## # Global Actions for all States @@ -319,6 +458,9 @@ class ActionHandler: #update enable/disable Actions.BLOCK_ENABLE.set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) Actions.BLOCK_DISABLE.set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) + Actions.BLOCK_CREATE_HIER.set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) + Actions.OPEN_HIER.set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) + Actions.RELOAD_BLOCKS.set_sensitive(True) #set the exec and stop buttons self.update_exec_stop() #saved status diff --git a/grc/gui/Actions.py b/grc/gui/Actions.py index 4d196477e..8087f4955 100644 --- a/grc/gui/Actions.py +++ b/grc/gui/Actions.py @@ -198,6 +198,12 @@ BLOCK_DISABLE = Action( stock_id=gtk.STOCK_DISCONNECT, keypresses=(gtk.keysyms.d, NO_MODS_MASK), ) +BLOCK_CREATE_HIER = Action( + label='C_reate Hier', + tooltip='Create hier block from selected blocks', + stock_id=gtk.STOCK_CONNECT, + keypresses=(gtk.keysyms.c, NO_MODS_MASK), +) BLOCK_CUT = Action( label='Cu_t', tooltip='Cut', @@ -273,3 +279,13 @@ BLOCK_INC_TYPE = Action( BLOCK_DEC_TYPE = Action( keypresses=(gtk.keysyms.Up, NO_MODS_MASK), ) +RELOAD_BLOCKS = Action( + label='Reload _Blocks', + tooltip='Reload Blocks', + stock_id=gtk.STOCK_REFRESH +) +OPEN_HIER = Action( + label='Open H_ier', + tooltip='Open the source of the selected hierarchical block', + stock_id=gtk.STOCK_JUMP_TO, +) diff --git a/grc/gui/Bars.py b/grc/gui/Bars.py index 8fd167869..d95d23f1f 100644 --- a/grc/gui/Bars.py +++ b/grc/gui/Bars.py @@ -49,6 +49,9 @@ TOOLBAR_LIST = ( None, Actions.BLOCK_ENABLE, Actions.BLOCK_DISABLE, + None, + Actions.RELOAD_BLOCKS, + Actions.OPEN_HIER, ) ##The list of actions and categories for the menu bar. diff --git a/grc/gui/BlockTreeWindow.py b/grc/gui/BlockTreeWindow.py index 0175c8bec..62afb6205 100644 --- a/grc/gui/BlockTreeWindow.py +++ b/grc/gui/BlockTreeWindow.py @@ -90,6 +90,11 @@ class BlockTreeWindow(gtk.VBox): #initialize self._update_add_button() + def clear(self): + self.treestore.clear(); + self._categories = {tuple(): None} + + ############################################################ ## Block Tree Methods ############################################################ diff --git a/grc/gui/FlowGraph.py b/grc/gui/FlowGraph.py index 9f3326ada..67e5af97b 100644 --- a/grc/gui/FlowGraph.py +++ b/grc/gui/FlowGraph.py @@ -63,6 +63,8 @@ class FlowGraph(Element): Actions.BLOCK_ENABLE, Actions.BLOCK_DISABLE, Actions.BLOCK_PARAM_MODIFY, + Actions.BLOCK_CREATE_HIER, + Actions.OPEN_HIER, ]: self._context_menu.append(action.create_menu_item()) ########################################################################### @@ -97,6 +99,8 @@ class FlowGraph(Element): block.get_param('id').set_value(id) Actions.ELEMENT_CREATE() + return id + ########################################################################### # Copy Paste ########################################################################### diff --git a/grc/gui/MainWindow.py b/grc/gui/MainWindow.py index 2f761df1f..37a100c94 100644 --- a/grc/gui/MainWindow.py +++ b/grc/gui/MainWindow.py @@ -93,7 +93,8 @@ class MainWindow(gtk.Window): #flow_graph_box.pack_start(self.scrolled_window) self.flow_graph_vpaned.pack1(self.notebook) self.hpaned.pack1(self.flow_graph_vpaned) - self.hpaned.pack2(BlockTreeWindow(platform, self.get_flow_graph), False) #dont allow resize + self.btwin = BlockTreeWindow(platform, self.get_flow_graph); + self.hpaned.pack2(self.btwin, False) #dont allow resize #create the reports window self.text_display = TextDisplay() #house the reports in a scrolled window @@ -169,6 +170,8 @@ class MainWindow(gtk.Window): try: #try to load from file if file_path: Messages.send_start_load(file_path) flow_graph = self._platform.get_new_flow_graph() + flow_graph.grc_file_path = file_path; + #print flow_graph page = NotebookPage( self, flow_graph=flow_graph, diff --git a/grc/python/Connection.py b/grc/python/Connection.py index 218baf074..341dd2d82 100644 --- a/grc/python/Connection.py +++ b/grc/python/Connection.py @@ -31,6 +31,9 @@ class Connection(_Connection, _GUIConnection): def is_msg(self): return self.get_source().get_type() == self.get_sink().get_type() == 'msg' + def is_message(self): + return self.get_source().get_type() == self.get_sink().get_type() == 'message' + def validate(self): """ Validate the connections. diff --git a/grc/python/Constants.py b/grc/python/Constants.py index 1a65caf1c..b8dc9a96a 100644 --- a/grc/python/Constants.py +++ b/grc/python/Constants.py @@ -58,6 +58,7 @@ CORE_TYPES = ( #name, key, sizeof, color ('Integer 16', 's16', 2, '#FFFF66'), ('Integer 8', 's8', 1, '#FF66FF'), ('Message Queue', 'msg', 0, '#777777'), + ('Async Message', 'message', 0, '#C0C0C0'), ('Wildcard', '', 0, '#FFFFFF'), ) diff --git a/grc/python/FlowGraph.py b/grc/python/FlowGraph.py index 89a169355..376c2e337 100644 --- a/grc/python/FlowGraph.py +++ b/grc/python/FlowGraph.py @@ -58,12 +58,15 @@ class FlowGraph(_FlowGraph, _GUIFlowGraph): 'in': self.get_pad_sources(), 'out': self.get_pad_sinks(), }[direction] + # we only want stream ports + sorted_pads = filter(lambda b: b.get_param('type').get_evaluated() != 'message', sorted_pads); #load io signature return [{ 'label': str(pad.get_param('label').get_evaluated()), 'type': str(pad.get_param('type').get_evaluated()), 'vlen': str(pad.get_param('vlen').get_evaluated()), 'size': pad.get_param('type').get_opt('size'), + 'optional': bool(pad.get_param('optional').get_evaluated()), } for pad in sorted_pads] def get_pad_sources(self): @@ -82,6 +85,14 @@ class FlowGraph(_FlowGraph, _GUIFlowGraph): pads = filter(lambda b: b.get_key() == 'pad_sink', self.get_enabled_blocks()) return sorted(pads, lambda x, y: cmp(x.get_id(), y.get_id())) + def get_msg_pad_sources(self): + ps = self.get_pad_sources(); + return filter(lambda b: b.get_param('type').get_evaluated() == 'message', ps); + + def get_msg_pad_sinks(self): + ps = self.get_pad_sinks(); + return filter(lambda b: b.get_param('type').get_evaluated() == 'message', ps); + def get_imports(self): """ Get a set of all import statments in this flow graph namespace. diff --git a/grc/python/Generator.py b/grc/python/Generator.py index 2a6fe51d5..616ea00fc 100644 --- a/grc/python/Generator.py +++ b/grc/python/Generator.py @@ -116,8 +116,9 @@ Add a Misc->Throttle block to your flow graph to avoid CPU congestion.''') #list of regular blocks (all blocks minus the special ones) blocks = filter(lambda b: b not in (imports + parameters), blocks) #list of connections where each endpoint is enabled - connections = filter(lambda c: not c.is_msg(), self._flow_graph.get_enabled_connections()) + connections = filter(lambda c: not (c.is_msg() or c.is_message()), self._flow_graph.get_enabled_connections()) messages = filter(lambda c: c.is_msg(), self._flow_graph.get_enabled_connections()) + messages2 = filter(lambda c: c.is_message(), self._flow_graph.get_enabled_connections()) #list of variable names var_ids = [var.get_id() for var in parameters + variables] #prepend self. @@ -142,6 +143,7 @@ Add a Misc->Throttle block to your flow graph to avoid CPU congestion.''') 'blocks': blocks, 'connections': connections, 'messages': messages, + 'messages2': messages2, 'generate_options': self._generate_options, 'var_id2cbs': var_id2cbs, } diff --git a/grc/python/Port.py b/grc/python/Port.py index 9f8b50d05..738a33ba7 100644 --- a/grc/python/Port.py +++ b/grc/python/Port.py @@ -116,7 +116,7 @@ class Port(_Port, _GUIPort): _Port.validate(self) if not self.get_enabled_connections() and not self.get_optional(): self.add_error_message('Port is not connected.') - if not self.is_source() and len(self.get_enabled_connections()) > 1: + if not self.is_source() and (not self.get_type() == "message") and len(self.get_enabled_connections()) > 1: self.add_error_message('Port has too many connections.') #message port logic if self.get_type() == 'msg': diff --git a/grc/python/block.dtd b/grc/python/block.dtd index 41a744d07..292ea06cb 100644 --- a/grc/python/block.dtd +++ b/grc/python/block.dtd @@ -25,7 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA Top level element. A block contains a name, ...parameters list, and list of IO ports. --> -<!ELEMENT block (name, key, category?, throttle?, import*, var_make?, make, callback*, param*, check*, sink*, source*, doc?)> +<!ELEMENT block (name, key, category?, throttle?, import*, var_make?, make, callback*, param*, check*, sink*, source*, doc?, grc_source?)> <!-- Sub level elements. --> @@ -40,6 +40,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA <!ELEMENT category (#PCDATA)> <!ELEMENT import (#PCDATA)> <!ELEMENT doc (#PCDATA)> +<!ELEMENT grc_source (#PCDATA)> <!ELEMENT name (#PCDATA)> <!ELEMENT key (#PCDATA)> <!ELEMENT check (#PCDATA)> diff --git a/grc/python/convert_hier.py b/grc/python/convert_hier.py index c6ca5b769..508ec63b2 100644 --- a/grc/python/convert_hier.py +++ b/grc/python/convert_hier.py @@ -25,6 +25,8 @@ def convert_hier(flow_graph, python_file): #extract info from the flow graph input_sigs = flow_graph.get_io_signaturev('in') output_sigs = flow_graph.get_io_signaturev('out') + input_msgp = flow_graph.get_msg_pad_sources(); + output_msgp = flow_graph.get_msg_pad_sinks(); parameters = flow_graph.get_parameters() block_key = flow_graph.get_option('id') block_name = flow_graph.get_option('title') or flow_graph.get_option('id').replace('_', ' ').title() @@ -55,24 +57,41 @@ def convert_hier(flow_graph, python_file): param_n['type'] = 'raw' params_n.append(param_n) block_n['param'] = params_n - #sink data + #sink data stream ports block_n['sink'] = list() for input_sig in input_sigs: sink_n = odict() sink_n['name'] = input_sig['label'] sink_n['type'] = input_sig['type'] sink_n['vlen'] = input_sig['vlen'] + if input_sig['optional']: sink_n['optional'] = '1' block_n['sink'].append(sink_n) - #source data + #sink data msg ports + for input_sig in input_msgp: + sink_n = odict() + sink_n['name'] = input_sig.get_param("label").get_value(); + sink_n['type'] = "message" + sink_n['optional'] = input_sig.get_param("optional").get_value(); + block_n['sink'].append(sink_n) + #source data stream ports block_n['source'] = list() for output_sig in output_sigs: source_n = odict() source_n['name'] = output_sig['label'] source_n['type'] = output_sig['type'] source_n['vlen'] = output_sig['vlen'] + if output_sig['optional']: source_n['optional'] = '1' + block_n['source'].append(source_n) + #source data msg ports + for output_sig in output_msgp: + source_n = odict() + source_n['name'] = output_sig.get_param("label").get_value(); + source_n['type'] = "message" + source_n['optional'] = output_sig.get_param("optional").get_value(); block_n['source'].append(source_n) #doc data block_n['doc'] = "%s\n%s\n%s"%(block_author, block_desc, python_file) + block_n['grc_source'] = "%s"%(flow_graph.grc_file_path) #write the block_n to file xml_file = python_file + '.xml' ParseXML.to_file({'block': block_n}, xml_file) diff --git a/grc/python/flow_graph.tmpl b/grc/python/flow_graph.tmpl index 17feb01f6..163e7f76a 100644 --- a/grc/python/flow_graph.tmpl +++ b/grc/python/flow_graph.tmpl @@ -191,6 +191,32 @@ gr.io_signaturev($(len($io_sigs)), $(len($io_sigs)), [$(', '.join($size_strs))]) #end for ######################################################## +##Create Asynch Message Connections +######################################################## +#if $messages2 + $DIVIDER + # Asynch Message Connections + $DIVIDER +#end if +#for $msg in $messages2 + #set $sr = $msg.get_source() + #set $source = "self.%s"%($sr.get_parent().get_id()) + #set $source_port = $sr.get_name(); + #if $sr.get_parent().get_key() == "pad_source" + #set $source = "self" + #set $source_port = $sr.get_parent().get_param("label").get_value(); + #end if + #set $sk = $msg.get_sink() + #set $sink = "self.%s"%($sk.get_parent().get_id()) + #set $sink_port = $sk.get_name(); + #if $sk.get_parent().get_key() == "pad_sink" + #set $sink = "self" + #set $sink_port = $sk.get_parent().get_param("label").get_value(); + #end if + self.msg_connect($source, "$source_port", $sink, "$sink_port") +#end for + +######################################################## ##Create Callbacks ## Write a set method for this variable that calls the callbacks ######################################################## |