From 25b29495b71e8d3276a9a2f27044524c833772cb Mon Sep 17 00:00:00 2001
From: Josh Blum <josh@joshknows.com>
Date: Sun, 25 Mar 2012 17:52:42 -0700
Subject: grc: resolve down and up stream for empty types

---
 grc/python/Port.py | 57 +++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 50 insertions(+), 7 deletions(-)

(limited to 'grc')

diff --git a/grc/python/Port.py b/grc/python/Port.py
index c2bfd9ccc6..d0ef51b483 100644
--- a/grc/python/Port.py
+++ b/grc/python/Port.py
@@ -1,5 +1,5 @@
 """
-Copyright 2008-2011 Free Software Foundation, Inc.
+Copyright 2008-2012 Free Software Foundation, Inc.
 This file is part of GNU Radio
 
 GNU Radio Companion is free software; you can redistribute it and/or
@@ -24,7 +24,7 @@ import Constants
 def _get_source_from_virtual_sink_port(vsp):
 	"""
 	Resolve the source port that is connected to the given virtual sink port.
-	Use the get source from virtual source to recursively resolve subsequent ports. 
+	Use the get source from virtual source to recursively resolve subsequent ports.
 	"""
 	try: return _get_source_from_virtual_source_port(
 		vsp.get_enabled_connections()[0].get_source())
@@ -50,6 +50,35 @@ def _get_source_from_virtual_source_port(vsp, traversed=[]):
 	)
 	except: raise Exception, 'Could not resolve source for virtual source port %s'%vsp
 
+def _get_sink_from_virtual_source_port(vsp):
+	"""
+	Resolve the sink port that is connected to the given virtual source port.
+	Use the get sink from virtual sink to recursively resolve subsequent ports.
+	"""
+	try: return _get_sink_from_virtual_sink_port(
+		vsp.get_enabled_connections()[0].get_sink())	# Could have many connections, but use first
+	except: raise Exception, 'Could not resolve source for virtual source port %s'%vsp
+
+def _get_sink_from_virtual_sink_port(vsp, traversed=[]):
+	"""
+	Recursively resolve sink ports over the virtual connections.
+	Keep track of traversed sinks to avoid recursive loops.
+	"""
+	if not vsp.get_parent().is_virtual_sink(): return vsp
+	if vsp in traversed: raise Exception, 'Loop found when resolving virtual sink %s'%vsp
+	try: return _get_sink_from_virtual_sink_port(
+		_get_sink_from_virtual_source_port(
+			filter(#get all virtual source with a matching stream id
+				lambda vs: vs.get_param('stream_id').get_value() == vsp.get_parent().get_param('stream_id').get_value(),
+				filter(#get all enabled blocks that are also virtual sinks
+					lambda b: b.is_virtual_source(),
+					vsp.get_parent().get_parent().get_enabled_blocks(),
+				),
+			)[0].get_sources()[0]
+		), traversed + [vsp],
+	)
+	except: raise Exception, 'Could not resolve source for virtual sink port %s'%vsp
+
 class Port(_Port, _GUIPort):
 
 	def __init__(self, block, n, dir):
@@ -81,6 +110,8 @@ class Port(_Port, _GUIPort):
 
 	def get_types(self): return Constants.TYPE_TO_SIZEOF.keys()
 
+	def is_type_empty(self): return not self._n['type']
+
 	def validate(self):
 		_Port.validate(self)
 		if not self.get_enabled_connections() and not self.get_optional():
@@ -99,18 +130,30 @@ class Port(_Port, _GUIPort):
 		Handle the port cloning for virtual blocks.
 		"""
 		_Port.rewrite(self)
-		if self.get_parent().is_virtual_sink() or self.get_parent().is_virtual_source():
+		if self.is_type_empty():
 			try: #clone type and vlen
-				source = self.resolve_virtual_source()
+				source = self.resolve_empty_type()
 				self._type = str(source.get_type())
 				self._vlen = str(source.get_vlen())
 			except: #reset type and vlen
 				self._type = ''
 				self._vlen = ''
 
-	def resolve_virtual_source(self):
-		if self.get_parent().is_virtual_sink(): return _get_source_from_virtual_sink_port(self)
-		if self.get_parent().is_virtual_source(): return _get_source_from_virtual_source_port(self)
+	def resolve_empty_type(self):
+		if self.is_sink():
+			try:
+				src = _get_source_from_virtual_sink_port(self)
+				if not src.is_type_empty(): return src
+			except: pass
+			sink = _get_sink_from_virtual_sink_port(self)
+			if not sink.is_type_empty(): return sink
+		if self.is_source():
+			try:
+				src = _get_source_from_virtual_source_port(self)
+				if not src.is_type_empty(): return src
+			except: pass
+			sink = _get_sink_from_virtual_source_port(self)
+			if not sink.is_type_empty(): return sink
 
 	def get_vlen(self):
 		"""
-- 
cgit v1.2.3