summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohnathan Corgan2009-08-15 10:48:39 -0700
committerJohnathan Corgan2009-08-15 10:48:39 -0700
commit4edaf1e7fc05df0628c05785d5ede285a64670b0 (patch)
tree93497b08306b3df6a9a36c4c5adb63c61b5d4f3e
parenta33d7c0df9dab57767c6b9376e6779a23217c1b9 (diff)
parent8e1a2c4ac1a43fd989c06856dae27b0c2559c6b3 (diff)
downloadgnuradio-4edaf1e7fc05df0628c05785d5ede285a64670b0.tar.gz
gnuradio-4edaf1e7fc05df0628c05785d5ede285a64670b0.tar.bz2
gnuradio-4edaf1e7fc05df0628c05785d5ede285a64670b0.zip
Merged branch 'msgq' from http://gnuradio.org/git/jblum.git
This adds the ability to GRC to gave blocks with message ports. Signed-off-by: Johnathan Corgan <jcorgan@corganenterprises.com>
-rw-r--r--Makefile.am13
-rw-r--r--grc/base/Block.py41
-rw-r--r--grc/base/Param.py2
-rw-r--r--grc/blocks/Makefile.am2
-rw-r--r--grc/blocks/block_tree.xml2
-rw-r--r--grc/blocks/gr_message_sink.xml72
-rw-r--r--grc/blocks/gr_message_source.xml58
-rw-r--r--grc/gui/Block.py8
-rw-r--r--grc/python/Block.py26
-rw-r--r--grc/python/Connection.py3
-rw-r--r--grc/python/Constants.py1
-rw-r--r--grc/python/Generator.py4
-rw-r--r--grc/python/Platform.py3
-rw-r--r--grc/python/Port.py43
-rw-r--r--grc/python/flow_graph.tmpl13
-rw-r--r--grc/todo.txt1
16 files changed, 235 insertions, 57 deletions
diff --git a/Makefile.am b/Makefile.am
index e8328c263..ec71be725 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -37,3 +37,16 @@ EXTRA_DIST = \
SUBDIRS = @build_dirs@
DIST_SUBDIRS = @build_dirs@ @skipped_dirs@ @with_dirs@
+
+if PYTHON
+
+export pythondir
+
+install-data-hook:
+ @if ! python -c "import gnuradio" > /dev/null 2>&1; then\
+ printf "\n*** Post-Install Message ***\
+ \nWarning: python could not find the gnuradio module.\
+ \nMake sure that $${pythondir} is in your PYTHONPATH\n\n";\
+ fi
+
+endif
diff --git a/grc/base/Block.py b/grc/base/Block.py
index 867a14f57..d5e104785 100644
--- a/grc/base/Block.py
+++ b/grc/base/Block.py
@@ -46,6 +46,9 @@ class TemplateArg(UserDict):
def __call__(self):
return self._param.get_evaluated()
+def _get_keys(lst): return [elem.get_key() for elem in lst]
+def _get_elem(lst, key): return lst[_get_keys(lst).index(key)]
+
class Block(Element):
def __init__(self, flow_graph, n):
@@ -66,17 +69,17 @@ class Block(Element):
self._category = n.find('category') or ''
self._block_wrapper_path = n.find('block_wrapper_path')
#create the param objects
- self._params = odict()
+ self._params = list()
#add the id param
- self._params['id'] = self.get_parent().get_parent().Param(
+ self.get_params().append(self.get_parent().get_parent().Param(
self,
odict({
'name': 'ID',
'key': 'id',
'type': 'id',
})
- )
- self._params['_enabled'] = self.get_parent().get_parent().Param(
+ ))
+ self.get_params().append(self.get_parent().get_parent().Param(
self,
odict({
'name': 'Enabled',
@@ -85,32 +88,32 @@ class Block(Element):
'value': 'True',
'hide': 'all',
})
- )
+ ))
for param in map(lambda n: self.get_parent().get_parent().Param(self, n), params):
key = param.get_key()
#test against repeated keys
try: assert key not in self.get_param_keys()
except AssertionError: raise Exception, 'Key "%s" already exists in params'%key
#store the param
- self._params[key] = param
+ self.get_params().append(param)
#create the source objects
- self._sources = odict()
+ self._sources = list()
for source in map(lambda n: self.get_parent().get_parent().Source(self, n), sources):
key = source.get_key()
#test against repeated keys
try: assert key not in self.get_source_keys()
except AssertionError: raise Exception, 'Key "%s" already exists in sources'%key
#store the port
- self._sources[key] = source
+ self.get_sources().append(source)
#create the sink objects
- self._sinks = odict()
+ self._sinks = list()
for sink in map(lambda n: self.get_parent().get_parent().Sink(self, n), sinks):
key = sink.get_key()
#test against repeated keys
try: assert key not in self.get_sink_keys()
except AssertionError: raise Exception, 'Key "%s" already exists in sinks'%key
#store the port
- self._sinks[key] = sink
+ self.get_sinks().append(sink)
#begin the testing
self.test()
@@ -164,23 +167,23 @@ class Block(Element):
##############################################
# Access Params
##############################################
- def get_param_keys(self): return self._params.keys()
- def get_param(self, key): return self._params[key]
- def get_params(self): return self._params.values()
+ def get_param_keys(self): return _get_keys(self._params)
+ def get_param(self, key): return _get_elem(self._params, key)
+ def get_params(self): return self._params
##############################################
# Access Sinks
##############################################
- def get_sink_keys(self): return self._sinks.keys()
- def get_sink(self, key): return self._sinks[key]
- def get_sinks(self): return self._sinks.values()
+ def get_sink_keys(self): return _get_keys(self._sinks)
+ def get_sink(self, key): return _get_elem(self._sinks, key)
+ def get_sinks(self): return self._sinks
##############################################
# Access Sources
##############################################
- def get_source_keys(self): return self._sources.keys()
- def get_source(self, key): return self._sources[key]
- def get_sources(self): return self._sources.values()
+ def get_source_keys(self): return _get_keys(self._sources)
+ def get_source(self, key): return _get_elem(self._sources, key)
+ def get_sources(self): return self._sources
def get_connections(self):
return sum([port.get_connections() for port in self.get_ports()], [])
diff --git a/grc/base/Param.py b/grc/base/Param.py
index 8166d54ec..93c1c52bd 100644
--- a/grc/base/Param.py
+++ b/grc/base/Param.py
@@ -165,6 +165,8 @@ class Param(Element):
try: assert self.get_value() in self.get_option_keys()
except AssertionError: raise Exception, 'The value "%s" is not in the possible values of "%s".'%(self.get_value(), self.get_option_keys())
else: self._value = value or ''
+ #begin the testing
+ self.test()
def test(self):
"""
diff --git a/grc/blocks/Makefile.am b/grc/blocks/Makefile.am
index 025c261f4..fbd8f4bb4 100644
--- a/grc/blocks/Makefile.am
+++ b/grc/blocks/Makefile.am
@@ -123,6 +123,8 @@ dist_ourdata_DATA = \
gr_kludge_copy.xml \
gr_map_bb.xml \
gr_max_xx.xml \
+ gr_message_sink.xml \
+ gr_message_source.xml \
gr_moving_average_xx.xml \
gr_mpsk_receiver_cc.xml \
gr_mpsk_sync_cc.xml \
diff --git a/grc/blocks/block_tree.xml b/grc/blocks/block_tree.xml
index 9eda2fdcf..2cedb45a2 100644
--- a/grc/blocks/block_tree.xml
+++ b/grc/blocks/block_tree.xml
@@ -20,6 +20,7 @@
<block>gr_udp_source</block>
<block>audio_source</block>
<block>gr_wavfile_source</block>
+ <block>gr_message_source</block>
<block>pad_source</block>
</cat>
<cat>
@@ -32,6 +33,7 @@
<block>gr_udp_sink</block>
<block>audio_sink</block>
<block>gr_wavfile_sink</block>
+ <block>gr_message_sink</block>
<block>pad_sink</block>
</cat>
<cat>
diff --git a/grc/blocks/gr_message_sink.xml b/grc/blocks/gr_message_sink.xml
new file mode 100644
index 000000000..76537f283
--- /dev/null
+++ b/grc/blocks/gr_message_sink.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Message Sink (the source port is a message)
+###################################################
+ -->
+<block>
+ <name>Message Sink</name>
+ <key>gr_message_sink</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.message_sink($type.size*$vlen, $(id)_msgq, $dont_block)</make>
+ <param>
+ <name>Input Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Don't Block</name>
+ <key>dont_block</key>
+ <value>False</value>
+ <type>enum</type>
+ <option>
+ <name>Don't Block</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>Block</name>
+ <key>False</key>
+ </option>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>msg</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_message_source.xml b/grc/blocks/gr_message_source.xml
new file mode 100644
index 000000000..44378ae83
--- /dev/null
+++ b/grc/blocks/gr_message_source.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Message Source (the sink port is a message)
+###################################################
+ -->
+<block>
+ <name>Message Source</name>
+ <key>gr_message_source</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.message_source($type.size*$vlen, $(id)_msgq)</make>
+ <param>
+ <name>Output Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>msg</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/gui/Block.py b/grc/gui/Block.py
index 0496f0a28..4add3aa19 100644
--- a/grc/gui/Block.py
+++ b/grc/gui/Block.py
@@ -43,7 +43,7 @@ class Block(Element):
Add graphics related params to the block.
"""
#add the position param
- self._params['_coordinate'] = self.get_parent().get_parent().Param(
+ self.get_params().append(self.get_parent().get_parent().Param(
self,
odict({
'name': 'GUI Coordinate',
@@ -52,8 +52,8 @@ class Block(Element):
'value': '(0, 0)',
'hide': 'all',
})
- )
- self._params['_rotation'] = self.get_parent().get_parent().Param(
+ ))
+ self.get_params().append(self.get_parent().get_parent().Param(
self,
odict({
'name': 'GUI Rotation',
@@ -62,7 +62,7 @@ class Block(Element):
'value': '0',
'hide': 'all',
})
- )
+ ))
Element.__init__(self)
def get_coordinate(self):
diff --git a/grc/python/Block.py b/grc/python/Block.py
index 957fee18e..47fe13a3c 100644
--- a/grc/python/Block.py
+++ b/grc/python/Block.py
@@ -66,16 +66,16 @@ class Block(_Block):
except AssertionError: self.add_error_message('Check "%s" failed.'%check)
except: self.add_error_message('Check "%s" did not evaluate.'%check)
#adjust nports
- for ports, Port in (
- (self._sources, self.get_parent().get_parent().Source),
- (self._sinks, self.get_parent().get_parent().Sink),
+ for get_ports, get_port in (
+ (self.get_sources, self.get_source),
+ (self.get_sinks, self.get_sink),
):
- #how many ports?
- num_ports = len(ports)
+ #how many streaming (non-message) ports?
+ num_ports = len(filter(lambda p: p.get_type() != 'msg', get_ports()))
#do nothing for 0 ports
if not num_ports: continue
#get the nports setting
- port0 = ports[str(0)]
+ port0 = get_port(str(0))
nports = port0.get_nports()
#do nothing for no nports
if not nports: continue
@@ -85,19 +85,21 @@ class Block(_Block):
if nports < num_ports:
#remove the connections
for key in map(str, range(nports, num_ports)):
- port = ports[key]
+ port = get_port(key)
for connection in port.get_connections():
self.get_parent().remove_element(connection)
#remove the ports
- for key in map(str, range(nports, num_ports)): ports.pop(key)
+ for key in map(str, range(nports, num_ports)):
+ get_ports().remove(get_port(key))
continue
#add more ports
if nports > num_ports:
for key in map(str, range(num_ports, nports)):
- n = port0._n
- n['key'] = key
- port = Port(self, n)
- ports[key] = port
+ prev_port = get_port(str(int(key)-1))
+ get_ports().insert(
+ get_ports().index(prev_port)+1,
+ prev_port.copy(new_key=key),
+ )
continue
def port_controller_modify(self, direction):
diff --git a/grc/python/Connection.py b/grc/python/Connection.py
index d8a894bb1..5eba9f24d 100644
--- a/grc/python/Connection.py
+++ b/grc/python/Connection.py
@@ -21,6 +21,9 @@ from .. base.Connection import Connection as _Connection
class Connection(_Connection):
+ def is_msg(self):
+ return self.get_source().get_type() == self.get_sink().get_type() == 'msg'
+
def validate(self):
"""
Validate the connections.
diff --git a/grc/python/Constants.py b/grc/python/Constants.py
index 5f203237f..439a52420 100644
--- a/grc/python/Constants.py
+++ b/grc/python/Constants.py
@@ -61,3 +61,4 @@ SHORT_VECTOR_COLOR_SPEC = '#CCCC33'
BYTE_VECTOR_COLOR_SPEC = '#CC66CC'
ID_COLOR_SPEC = '#DDDDDD'
WILDCARD_COLOR_SPEC = '#FFFFFF'
+MSG_COLOR_SPEC = '#777777'
diff --git a/grc/python/Generator.py b/grc/python/Generator.py
index 33be4a726..ed7995716 100644
--- a/grc/python/Generator.py
+++ b/grc/python/Generator.py
@@ -98,7 +98,8 @@ 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 + variables + probes + notebooks), blocks) + probes
#list of connections where each endpoint is enabled
- connections = self._flow_graph.get_enabled_connections()
+ connections = filter(lambda c: not c.is_msg(), self._flow_graph.get_enabled_connections())
+ messages = filter(lambda c: c.is_msg(), self._flow_graph.get_enabled_connections())
#list of variable names
var_ids = [var.get_id() for var in parameters + variables]
#prepend self.
@@ -124,6 +125,7 @@ Add a Misc->Throttle block to your flow graph to avoid CPU congestion.''')
'parameters': parameters,
'blocks': blocks,
'connections': connections,
+ 'messages': messages,
'generate_options': self._generate_options,
'var_id2cbs': var_id2cbs,
}
diff --git a/grc/python/Platform.py b/grc/python/Platform.py
index f56e3fb2d..d55dbf4ce 100644
--- a/grc/python/Platform.py
+++ b/grc/python/Platform.py
@@ -42,7 +42,8 @@ COLORS = (#title, #color spec
('Integer Vector', Constants.INT_VECTOR_COLOR_SPEC),
('Short Vector', Constants.SHORT_VECTOR_COLOR_SPEC),
('Byte Vector', Constants.BYTE_VECTOR_COLOR_SPEC),
- ('Wildcard Type', Constants.WILDCARD_COLOR_SPEC),
+ ('Wildcard', Constants.WILDCARD_COLOR_SPEC),
+ ('Message', Constants.MSG_COLOR_SPEC),
)
class Platform(_Platform):
diff --git a/grc/python/Port.py b/grc/python/Port.py
index 5a2b047f0..daf8f9ca3 100644
--- a/grc/python/Port.py
+++ b/grc/python/Port.py
@@ -23,27 +23,23 @@ import Constants
class Port(_Port):
##possible port types
- TYPES = ['complex', 'float', 'int', 'short', 'byte']
+ TYPES = ['complex', 'float', 'int', 'short', 'byte', 'msg']
def __init__(self, block, n):
"""
Make a new port from nested data.
@param block the parent element
@param n the nested odict
- @return a new port
"""
- vlen = n.find('vlen') or '1'
- nports = n.find('nports') or ''
- optional = n.find('optional') or ''
#build the port
_Port.__init__(
self,
block=block,
n=n,
)
- self._nports = nports
- self._vlen = vlen
- self._optional = bool(optional)
+ self._nports = n.find('nports') or ''
+ self._vlen = n.find('vlen') or ''
+ self._optional = bool(n.find('optional'))
def validate(self):
_Port.validate(self)
@@ -51,6 +47,11 @@ class Port(_Port):
except AssertionError: self.add_error_message('Port is not connected.')
try: assert self.is_source() or len(self.get_enabled_connections()) <= 1
except AssertionError: self.add_error_message('Port has too many connections.')
+ if self.get_type() == 'msg':
+ try: assert not self.get_nports()
+ except AssertionError: self.add_error_message('A port of type "msg" cannot have "nports" set.')
+ try: assert self.get_vlen() == 1
+ except AssertionError: self.add_error_message('A port of type "msg" must have a "vlen" of 1.')
def get_vlen(self):
"""
@@ -94,6 +95,7 @@ class Port(_Port):
'int': Constants.INT_COLOR_SPEC,
'short': Constants.SHORT_COLOR_SPEC,
'byte': Constants.BYTE_COLOR_SPEC,
+ 'msg': Constants.MSG_COLOR_SPEC,
}[self.get_type()]
return {#vlen is non 1
'complex': Constants.COMPLEX_VECTOR_COLOR_SPEC,
@@ -104,26 +106,27 @@ class Port(_Port):
}[self.get_type()]
except: return _Port.get_color(self)
+ def copy(self, new_key=None):
+ n = self._n.copy()
+ if new_key: n['key'] = new_key
+ return self.__class__(self.get_parent(), n)
+
class Source(Port):
def __init__(self, block, n):
self._n = n #save n
- #key is port index
- n['key'] = str(block._source_count)
- block._source_count = block._source_count + 1
+ if n['type'] == 'msg': n['key'] = 'msg'
+ if not n.find('key'):
+ n['key'] = str(block._source_count)
+ block._source_count = block._source_count + 1
Port.__init__(self, block, n)
- def __del__(self):
- self.get_parent()._source_count = self.get_parent()._source_count - 1
-
class Sink(Port):
def __init__(self, block, n):
self._n = n #save n
- #key is port index
- n['key'] = str(block._sink_count)
- block._sink_count = block._sink_count + 1
+ if n['type'] == 'msg': n['key'] = 'msg'
+ if not n.find('key'):
+ n['key'] = str(block._sink_count)
+ block._sink_count = block._sink_count + 1
Port.__init__(self, block, n)
-
- def __del__(self):
- self.get_parent()._sink_count = self.get_parent()._sink_count - 1
diff --git a/grc/python/flow_graph.tmpl b/grc/python/flow_graph.tmpl
index b537c43e2..df346dd16 100644
--- a/grc/python/flow_graph.tmpl
+++ b/grc/python/flow_graph.tmpl
@@ -10,6 +10,7 @@
##@param parameters the paramater blocks
##@param blocks the signal blocks
##@param connections the connections
+##@param messages the msg type connections
##@param generate_options the type of flow graph
##@param var_id2cbs variable id map to callback strings
########################################################
@@ -125,6 +126,18 @@ class $(class_name)(gr.hier_block2):
$indent($ctrl.get_make())
#end for
########################################################
+##Create Message Queues
+########################################################
+#if $messages
+
+ $DIVIDER
+ # Message Queues
+ $DIVIDER
+#end if
+#for $msg in $messages
+ $(msg.get_source().get_parent().get_id())_msgq = $(msg.get_sink().get_parent().get_id())_msgq = gr.msg_queue(2)
+#end for
+########################################################
##Create Blocks
########################################################
#if $blocks
diff --git a/grc/todo.txt b/grc/todo.txt
index f8c8021b6..bb40e1f16 100644
--- a/grc/todo.txt
+++ b/grc/todo.txt
@@ -26,6 +26,7 @@
* callbacks for set average on fft, waterfall, number sinks
* add units to params: Sps, Hz, dB...
* command line options should replace _ with - for the --option
+ * add bool type to command line option store_true or store_false
##################################################
# Features