[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] [gnuradio] 04/10: grc: Added ability to bypass blocks
From: |
git |
Subject: |
[Commit-gnuradio] [gnuradio] 04/10: grc: Added ability to bypass blocks (Suggested by Chris Headley). |
Date: |
Sun, 14 Jun 2015 16:34:15 +0000 (UTC) |
This is an automated email from the git hooks/post-receive script.
jcorgan pushed a commit to branch master
in repository gnuradio.
commit 91dd2fce59ba81d4dc22b9dcdc909211cafe9f5f
Author: Seth Hitefield <address@hidden>
Date: Wed Jun 10 16:04:51 2015 -0400
grc: Added ability to bypass blocks (Suggested by Chris Headley).
Only for blocks that have a single source and sink of the same type.
Feature can be disabled per block using the 'disable_bypass' flag in the
block definition.
---
grc/base/Block.py | 86 ++++++++++++++++++++++++++++++++++++++++++++----
grc/base/Constants.py | 6 ++++
grc/base/FlowGraph.py | 50 ++++++++++++++++++++++++----
grc/gui/ActionHandler.py | 42 +++++++++++++++--------
grc/gui/Actions.py | 6 ++++
grc/gui/Bars.py | 3 ++
grc/gui/Block.py | 2 ++
grc/gui/Colors.py | 1 +
grc/gui/FlowGraph.py | 18 ++++++++--
grc/python/Generator.py | 2 +-
10 files changed, 186 insertions(+), 30 deletions(-)
diff --git a/grc/base/Block.py b/grc/base/Block.py
index d2d7ebf..5e8a717 100644
--- a/grc/base/Block.py
+++ b/grc/base/Block.py
@@ -18,7 +18,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA
"""
from . import odict
-from . Constants import ADVANCED_PARAM_TAB, DEFAULT_PARAM_TAB,
BLOCK_FLAG_THROTTLE
+from . Constants import ADVANCED_PARAM_TAB, DEFAULT_PARAM_TAB
+from . Constants import BLOCK_FLAG_THROTTLE, BLOCK_FLAG_DISABLE_BYPASS
+from . Constants import BLOCK_ENABLED, BLOCK_BYPASSED, BLOCK_DISABLED
from Element import Element
from Cheetah.Template import Template
@@ -82,7 +84,8 @@ class Block(Element):
self._key = n.find('key')
self._category = n.find('category') or ''
self._flags = n.find('flags') or ''
- if n.find('throttle') and BLOCK_FLAG_THROTTLE not in self._flags: #
backwards-compatibility
+ # Backwards compatibility
+ if n.find('throttle') and BLOCK_FLAG_THROTTLE not in self._flags:
self._flags += BLOCK_FLAG_THROTTLE
self._grc_source = n.find('grc_source') or ''
self._block_wrapper_path = n.find('block_wrapper_path')
@@ -154,6 +157,10 @@ class Block(Element):
and (self._key != "pad_sink"))
is_variable = self._key.startswith('variable')
+ # Disable blocks that are virtual/pads or variables
+ if not is_not_virtual_or_pad or is_variable:
+ self._flags += BLOCK_FLAG_DISABLE_BYPASS
+
if is_not_virtual_or_pad and not is_variable:
self.get_params().append(self.get_parent().get_parent().Param(
block=self,
@@ -208,7 +215,6 @@ class Block(Element):
})
))
-
def back_ofthe_bus(self, portlist):
portlist.sort(key=lambda p: p._type == 'bus')
@@ -216,6 +222,35 @@ class Block(Element):
buslist = [p for p in ports if p._type == 'bus']
return buslist or ports
+ # Main functions to get and set the block state
+ # Also kept get_enabled and set_enabled to keep compatibility
+ def get_state(self):
+ """
+ Gets the block's current state.
+
+ Returns:
+ ENABLED - 0
+ BYPASSED - 1
+ DISABLED - 2
+ """
+ try: return int(eval(self.get_param('_enabled').get_value()))
+ except: return BLOCK_ENABLED
+
+ def set_state(self, state):
+ """
+ Sets the state for the block.
+
+ Args:
+ ENABLED - 0
+ BYPASSED - 1
+ DISABLED - 2
+ """
+ if state in [BLOCK_ENABLED, BLOCK_BYPASSED, BLOCK_DISABLED]:
+ self.get_param('_enabled').set_value(str(state))
+ else:
+ self.get_param('_enabled').set_value(str(BLOCK_ENABLED))
+
+ # Enable/Disable Aliases
def get_enabled(self):
"""
Get the enabled state of the block.
@@ -223,8 +258,7 @@ class Block(Element):
Returns:
true for enabled
"""
- try: return eval(self.get_param('_enabled').get_value())
- except: return True
+ return not (self.get_state() == BLOCK_DISABLED)
def set_enabled(self, enabled):
"""
@@ -232,8 +266,45 @@ class Block(Element):
Args:
enabled: true for enabled
+
+ Returns:
+ True if block changed state
+ """
+ old_state = self.get_state()
+ new_state = BLOCK_ENABLED if enabled else BLOCK_DISABLED
+ self.set_state(new_state)
+ return old_state != new_state
+
+ # Block bypassing
+ def get_bypassed(self):
+ """
+ Check if the block is bypassed
+ """
+ return self.get_state() == BLOCK_BYPASSED
+
+ def set_bypassed(self):
+ """
+ Bypass the block
+
+ Returns:
+ True if block chagnes state
"""
- self.get_param('_enabled').set_value(str(enabled))
+ if self.get_state() != BLOCK_BYPASSED and self.can_bypass():
+ self.set_state(BLOCK_BYPASSED)
+ return True
+ return False
+
+ def can_bypass(self):
+ """ Check the number of sinks and sources and see if this block can be
bypassed """
+ # Check to make sure this is a single path block
+ # Could possibly support 1 to many blocks
+ if len(self.get_sources()) != 1 or len(self.get_sinks()) != 1:
+ return False
+ if not (self.get_sources()[0].get_type() ==
self.get_sinks()[0].get_type()):
+ return False
+ if self.bypass_disabled():
+ return False
+ return True
def __str__(self): return 'Block - %s - %s(%s)'%(self.get_id(),
self.get_name(), self.get_key())
@@ -252,7 +323,8 @@ class Block(Element):
def get_comment(self): return self.get_param('comment').get_value()
def get_flags(self): return self._flags
- def throttle(self): return "throttle" in self._flags
+ def throtteling(self): return BLOCK_FLAG_THROTTLE in self._flags
+ def bypass_disabled(self): return BLOCK_FLAG_DISABLE_BYPASS in self._flags
##############################################
# Access Params
diff --git a/grc/base/Constants.py b/grc/base/Constants.py
index 7949708..0c5116c 100644
--- a/grc/base/Constants.py
+++ b/grc/base/Constants.py
@@ -40,3 +40,9 @@ GR_MESSAGE_DOMAIN = "gr_message"
DEFAULT_DOMAIN = GR_STREAM_DOMAIN
BLOCK_FLAG_THROTTLE = 'throttle'
+BLOCK_FLAG_DISABLE_BYPASS = 'disable_bypass'
+
+# Block States
+BLOCK_DISABLED = 0
+BLOCK_ENABLED = 1
+BLOCK_BYPASSED = 2
diff --git a/grc/base/FlowGraph.py b/grc/base/FlowGraph.py
index 790aed0..7fd8df5 100644
--- a/grc/base/FlowGraph.py
+++ b/grc/base/FlowGraph.py
@@ -78,9 +78,6 @@ class FlowGraph(Element):
bus_structure = block.form_bus_structure('sink');
if 'bus' in map(lambda a: a.get_type(), get_p_gui()):
-
-
-
if len(get_p_gui()) > len(bus_structure):
times = range(len(bus_structure),
len(get_p_gui()));
for i in times:
@@ -100,8 +97,6 @@ class FlowGraph(Element):
port =
block.get_parent().get_parent().Port(block=block, n=n, dir=direc);
get_p().append(port);
-
-
for child in self.get_children(): child.rewrite()
refactor_bus_structure();
@@ -159,6 +154,15 @@ class FlowGraph(Element):
"""
return filter(lambda b: b.get_enabled(), self.get_blocks())
+ def get_bypassed_blocks(self):
+ """
+ Get a list of all blocks that are bypassed.
+
+ Returns:
+ a list of blocks
+ """
+ return filter(lambda b: b.get_bypassed(), self.get_blocks())
+
def get_enabled_connections(self):
"""
Get a list of all connections that are enabled.
@@ -166,7 +170,41 @@ class FlowGraph(Element):
Returns:
a list of connections
"""
- return filter(lambda c: c.get_enabled(), self.get_connections())
+ # First get all the enabled connections, then get the bypassed blocks.
+ connections = filter(lambda c: c.get_enabled(), self.get_connections())
+ bypassed_blocks = self.get_bypassed_blocks()
+
+ # Bypassing blocks: Need to find all the enabled connections for the
block using
+ # the *connections* object rather than get_connections(). Create new
connections
+ # that bypass the selected block and remove the existing ones. This
allows adjacent
+ # bypassed blocks to see the newly created connections to downstream
blocks,
+ # allowing them to correctly construct bypass connections.
+
+ for block in bypassed_blocks:
+ # Get the upstream connection (off of the sink ports)
+ # Use *connections* not get_connections()
+ get_source_connection = lambda c: c.get_sink() ==
block.get_sinks()[0]
+ source_connection = filter(get_source_connection, connections)
+ # The source connection should never have more than one element.
+ assert (len(source_connection) == 1)
+
+ # Get the source of the connection.
+ source_port = source_connection[0].get_source()
+
+ # Loop through all the downstream connections
+ get_sink_connections = lambda c: c.get_source() ==
block.get_sources()[0]
+ for sink in filter(get_sink_connections, connections):
+ if not sink.get_enabled():
+ # Ignore disabled connections
+ continue
+ sink_port = sink.get_sink()
+ connection = self.get_parent().Connection(flow_graph=self,
porta=source_port, portb=sink_port)
+ connections.append(connection)
+ # Remove this sink connection
+ connections.remove(sink)
+ # Remove the source connection
+ connections.remove(source_connection[0])
+ return connections
def get_new_block(self, key):
"""
diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py
index fee9662..1ce4aed 100644
--- a/grc/gui/ActionHandler.py
+++ b/grc/gui/ActionHandler.py
@@ -29,7 +29,7 @@ import subprocess
import Preferences
from threading import Thread
import Messages
-from .. base import ParseXML
+from .. base import ParseXML, Constants
from MainWindow import MainWindow
from PropsDialog import PropsDialog
from ParserErrorsDialog import ParserErrorsDialog
@@ -171,6 +171,11 @@ 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)
+ elif action == Actions.BLOCK_BYPASS:
+ if self.get_flow_graph().bypass_selected():
+ 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)
##################################################
# Cut/Copy/Paste
##################################################
@@ -553,23 +558,34 @@ class ActionHandler:
##################################################
# Global Actions for all States
##################################################
+ selected_block = self.get_flow_graph().get_selected_block()
+ selected_blocks = self.get_flow_graph().get_selected_blocks()
+
#update general buttons
Actions.ERRORS_WINDOW_DISPLAY.set_sensitive(not
self.get_flow_graph().is_valid())
Actions.ELEMENT_DELETE.set_sensitive(bool(self.get_flow_graph().get_selected_elements()))
-
Actions.BLOCK_PARAM_MODIFY.set_sensitive(bool(self.get_flow_graph().get_selected_block()))
-
Actions.BLOCK_ROTATE_CCW.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
-
Actions.BLOCK_ROTATE_CW.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
+ Actions.BLOCK_PARAM_MODIFY.set_sensitive(bool(selected_block))
+ Actions.BLOCK_ROTATE_CCW.set_sensitive(bool(selected_blocks))
+ Actions.BLOCK_ROTATE_CW.set_sensitive(bool(selected_blocks))
#update cut/copy/paste
-
Actions.BLOCK_CUT.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
-
Actions.BLOCK_COPY.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
+ Actions.BLOCK_CUT.set_sensitive(bool(selected_blocks))
+ Actions.BLOCK_COPY.set_sensitive(bool(selected_blocks))
Actions.BLOCK_PASTE.set_sensitive(bool(self.clipboard))
- #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.BUSSIFY_SOURCES.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
-
Actions.BUSSIFY_SINKS.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
+ #update enable/disable/bypass
+ can_enable = any(block.get_state() != Constants.BLOCK_ENABLED
+ for block in selected_blocks)
+ can_disable = any(block.get_state() != Constants.BLOCK_DISABLED
+ for block in selected_blocks)
+ can_bypass_all = all(block.can_bypass() for block in selected_blocks) \
+ and any (not block.get_bypassed() for block in
selected_blocks)
+ Actions.BLOCK_ENABLE.set_sensitive(can_enable)
+ Actions.BLOCK_DISABLE.set_sensitive(can_disable)
+ Actions.BLOCK_BYPASS.set_sensitive(can_bypass_all)
+
+ Actions.BLOCK_CREATE_HIER.set_sensitive(bool(selected_blocks))
+ Actions.OPEN_HIER.set_sensitive(bool(selected_blocks))
+ Actions.BUSSIFY_SOURCES.set_sensitive(bool(selected_blocks))
+ Actions.BUSSIFY_SINKS.set_sensitive(bool(selected_blocks))
Actions.RELOAD_BLOCKS.set_sensitive(True)
Actions.FIND_BLOCKS.set_sensitive(True)
#set the exec and stop buttons
diff --git a/grc/gui/Actions.py b/grc/gui/Actions.py
index b2b3a76..a028a33 100644
--- a/grc/gui/Actions.py
+++ b/grc/gui/Actions.py
@@ -247,6 +247,12 @@ BLOCK_DISABLE = Action(
stock_id=gtk.STOCK_DISCONNECT,
keypresses=(gtk.keysyms.d, NO_MODS_MASK),
)
+BLOCK_BYPASS = Action(
+ label='_Bypass',
+ tooltip='Bypass the selected block',
+ stock_id=gtk.STOCK_MEDIA_FORWARD,
+ keypresses=(gtk.keysyms.b, NO_MODS_MASK),
+)
TOGGLE_SNAP_TO_GRID = ToggleAction(
label='_Snap to grid',
tooltip='Snap blocks to a grid for an easier connection alignment',
diff --git a/grc/gui/Bars.py b/grc/gui/Bars.py
index 40ce205..abcc3c6 100644
--- a/grc/gui/Bars.py
+++ b/grc/gui/Bars.py
@@ -49,6 +49,7 @@ TOOLBAR_LIST = (
None,
Actions.BLOCK_ENABLE,
Actions.BLOCK_DISABLE,
+ Actions.BLOCK_BYPASS,
Actions.TOGGLE_HIDE_DISABLED_BLOCKS,
None,
Actions.FIND_BLOCKS,
@@ -85,6 +86,7 @@ MENU_BAR_LIST = (
None,
Actions.BLOCK_ENABLE,
Actions.BLOCK_DISABLE,
+ Actions.BLOCK_BYPASS,
None,
Actions.BLOCK_PARAM_MODIFY,
]),
@@ -134,6 +136,7 @@ CONTEXT_MENU_LIST = [
Actions.BLOCK_ROTATE_CW,
Actions.BLOCK_ENABLE,
Actions.BLOCK_DISABLE,
+ Actions.BLOCK_BYPASS,
None,
(gtk.Action('More', '_More', None, None), [
Actions.BLOCK_CREATE_HIER,
diff --git a/grc/gui/Block.py b/grc/gui/Block.py
index 60f19fc..83706ed 100644
--- a/grc/gui/Block.py
+++ b/grc/gui/Block.py
@@ -145,7 +145,9 @@ class Block(Element):
"""Create the labels for the signal block."""
Element.create_labels(self)
self._bg_color = self.is_dummy_block() and
Colors.MISSING_BLOCK_BACKGROUND_COLOR or \
+ self.get_bypassed() and Colors.BLOCK_BYPASSED_COLOR
or \
self.get_enabled() and Colors.BLOCK_ENABLED_COLOR or
Colors.BLOCK_DISABLED_COLOR
+
layouts = list()
#create the main layout
layout = gtk.DrawingArea().create_pango_layout('')
diff --git a/grc/gui/Colors.py b/grc/gui/Colors.py
index f64106b..52c95e8 100644
--- a/grc/gui/Colors.py
+++ b/grc/gui/Colors.py
@@ -38,6 +38,7 @@ try:
#block color constants
BLOCK_ENABLED_COLOR = get_color('#F1ECFF')
BLOCK_DISABLED_COLOR = get_color('#CCCCCC')
+ BLOCK_BYPASSED_COLOR = get_color('#FFFFE6')
#connection color constants
CONNECTION_ENABLED_COLOR = get_color('black')
CONNECTION_DISABLED_COLOR = get_color('#BBBBBB')
diff --git a/grc/gui/FlowGraph.py b/grc/gui/FlowGraph.py
index 97f814f..bf6e1ee 100644
--- a/grc/gui/FlowGraph.py
+++ b/grc/gui/FlowGraph.py
@@ -211,9 +211,21 @@ class FlowGraph(Element):
"""
changed = False
for selected_block in self.get_selected_blocks():
- if selected_block.get_enabled() != enable:
- selected_block.set_enabled(enable)
- changed = True
+ if selected_block.set_enabled(enable): changed = True
+ return changed
+
+ def bypass_selected(self):
+ """
+ Bypass the selected blocks.
+
+ Args:
+ None
+ Returns:
+ true if changed
+ """
+ changed = False
+ for selected_block in self.get_selected_blocks():
+ if selected_block.set_bypassed(): changed = True
return changed
def move_selected(self, delta_coordinate):
diff --git a/grc/python/Generator.py b/grc/python/Generator.py
index a3f9f10..d9e92cd 100644
--- a/grc/python/Generator.py
+++ b/grc/python/Generator.py
@@ -86,7 +86,7 @@ class TopBlockGenerator(object):
def write(self):
"""generate output and write it to files"""
# do throttle warning
- throttling_blocks = filter(lambda b: b.throttle(),
self._flow_graph.get_enabled_blocks())
+ throttling_blocks = filter(lambda b: b.throtteling(),
self._flow_graph.get_enabled_blocks())
if not throttling_blocks and self._generate_options != 'hb':
Messages.send_warning("This flow graph may not have flow control: "
"no audio or RF hardware blocks found. "
- [Commit-gnuradio] [gnuradio] branch master updated (1dc65e1 -> 7ee2f91), git, 2015/06/14
- [Commit-gnuradio] [gnuradio] 06/10: Merge remote-tracking branch 'skoslowski/top_block_wait', git, 2015/06/14
- [Commit-gnuradio] [gnuradio] 09/10: Merge branch 'maint', git, 2015/06/14
- [Commit-gnuradio] [gnuradio] 01/10: runtime: add flag to wrapped top_block to control SIGINT handling in wait(), git, 2015/06/14
- [Commit-gnuradio] [gnuradio] 08/10: Merge remote-tracking branch 'mbr0wn/uhd/gpios', git, 2015/06/14
- [Commit-gnuradio] [gnuradio] 07/10: Merge remote-tracking branch 'drmpeg/dtv-coverity-cleanup', git, 2015/06/14
- [Commit-gnuradio] [gnuradio] 05/10: uhd: Expose GPIO functions through SWIG, git, 2015/06/14
- [Commit-gnuradio] [gnuradio] 10/10: Merge remote-tracking branch 'gnuradio-wg-grc/master_grcwg', git, 2015/06/14
- [Commit-gnuradio] [gnuradio] 03/10: grc: add <flags> to blocks dtd (<throttle> still supported), git, 2015/06/14
- [Commit-gnuradio] [gnuradio] 04/10: grc: Added ability to bypass blocks (Suggested by Chris Headley).,
git <=
- [Commit-gnuradio] [gnuradio] 02/10: gr-dtv: Clean up minor Coverity Scan issues., git, 2015/06/14