2 Copyright 2008, 2009 Free Software Foundation, Inc.
3 This file is part of GNU Radio
5 GNU Radio Companion is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 GNU Radio Companion is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
21 from Element import Element
22 from Param import Param
25 from Cheetah.Template import Template
26 from UserDict import UserDict
28 class TemplateArg(UserDict):
30 A cheetah template argument created from a param.
31 The str of this class evaluates to the param's to code method.
32 The use of this class as a dictionary (enum only) will reveal the enum opts.
33 The __call__ or () method can return the param evaluated to a raw python data type.
36 def __init__(self, param):
37 UserDict.__init__(self)
40 for key in param.get_opt_keys():
41 self[key] = str(param.get_opt(key))
44 return str(self._param.to_code())
47 return self._param.get_evaluated()
49 def _get_keys(lst): return [elem.get_key() for elem in lst]
50 def _get_elem(lst, key):
51 try: return lst[_get_keys(lst).index(key)]
52 except ValueError: raise ValueError, 'Key "%s" not found in %s.'%(key, _get_keys(lst))
56 def __init__(self, flow_graph, n):
58 Make a new block from nested data.
59 @param flow graph the parent element
60 @param n the nested odict
61 @return block a new block
64 Element.__init__(self, flow_graph)
66 params = n.findall('param')
67 sources = n.findall('source')
68 sinks = n.findall('sink')
69 self._name = n.find('name')
70 self._key = n.find('key')
71 self._category = n.find('category') or ''
72 self._block_wrapper_path = n.find('block_wrapper_path')
73 #create the param objects
76 self.get_params().append(self.get_parent().get_parent().Param(
84 self.get_params().append(self.get_parent().get_parent().Param(
94 for param in map(lambda n: self.get_parent().get_parent().Param(self, n), params):
96 #test against repeated keys
97 try: assert key not in self.get_param_keys()
98 except AssertionError: raise Exception, 'Key "%s" already exists in params'%key
100 self.get_params().append(param)
101 #create the source objects
102 self._sources = list()
103 for source in map(lambda n: self.get_parent().get_parent().Port(self, n, dir='source'), sources):
104 key = source.get_key()
105 #test against repeated keys
106 try: assert key not in self.get_source_keys()
107 except AssertionError: raise Exception, 'Key "%s" already exists in sources'%key
109 self.get_sources().append(source)
110 #create the sink objects
112 for sink in map(lambda n: self.get_parent().get_parent().Port(self, n, dir='sink'), sinks):
114 #test against repeated keys
115 try: assert key not in self.get_sink_keys()
116 except AssertionError: raise Exception, 'Key "%s" already exists in sinks'%key
118 self.get_sinks().append(sink)
124 Call test on all children.
126 map(lambda c: c.test(), self.get_params() + self.get_sinks() + self.get_sources())
128 def get_enabled(self):
130 Get the enabled state of the block.
131 @return true for enabled
133 try: return eval(self.get_param('_enabled').get_value())
136 def set_enabled(self, enabled):
138 Set the enabled state of the block.
139 @param enabled true for enabled
141 self.get_param('_enabled').set_value(str(enabled))
146 All ports and params must be valid.
147 All checks must evaluate to true.
148 Validate the params, ports, and the connections to this block.
150 Element.validate(self)
151 for c in self.get_params() + self.get_ports() + self.get_connections():
154 for msg in c.get_error_messages():
155 self.add_error_message('>>> %s:\n\t%s'%(c, msg))
157 def __str__(self): return 'Block - %s - %s(%s)'%(self.get_id(), self.get_name(), self.get_key())
159 def get_id(self): return self.get_param('id').get_value()
160 def is_block(self): return True
161 def get_name(self): return self._name
162 def get_key(self): return self._key
163 def get_category(self): return self._category
164 def get_doc(self): return ''
165 def get_ports(self): return self.get_sources() + self.get_sinks()
166 def get_block_wrapper_path(self): return self._block_wrapper_path
168 ##############################################
170 ##############################################
171 def get_param_keys(self): return _get_keys(self._params)
172 def get_param(self, key): return _get_elem(self._params, key)
173 def get_params(self): return self._params
175 ##############################################
177 ##############################################
178 def get_sink_keys(self): return _get_keys(self._sinks)
179 def get_sink(self, key): return _get_elem(self._sinks, key)
180 def get_sinks(self): return self._sinks
182 ##############################################
184 ##############################################
185 def get_source_keys(self): return _get_keys(self._sources)
186 def get_source(self, key): return _get_elem(self._sources, key)
187 def get_sources(self): return self._sources
189 def get_connections(self):
190 return sum([port.get_connections() for port in self.get_ports()], [])
192 def resolve_dependencies(self, tmpl):
194 Resolve a paramater dependency with cheetah templates.
195 @param tmpl the string with dependencies
196 @return the resolved value
199 if '$' not in tmpl: return tmpl
200 n = dict((p.get_key(), TemplateArg(p)) for p in self.get_params())
201 try: return str(Template(tmpl, n))
202 except Exception, e: return "-------->\n%s: %s\n<--------"%(e, tmpl)
204 ##############################################
206 ##############################################
207 def type_controller_modify(self, direction):
209 Change the type controller.
210 @param direction +1 or -1
211 @return true for change
215 for param in filter(lambda p: p.is_enum(), self.get_params()):
216 children = self.get_ports() + self.get_params()
217 #priority to the type controller
218 if param.get_key() in ' '.join(map(lambda p: p._type, children)): type_param = param
219 #use param if type param is unset
220 if not type_param: type_param = param
222 #try to increment the enum by direction
224 keys = type_param.get_option_keys()
225 old_index = keys.index(type_param.get_value())
226 new_index = (old_index + direction + len(keys))%len(keys)
227 type_param.set_value(keys[new_index])
232 def port_controller_modify(self, direction):
234 Change the port controller.
235 @param direction +1 or -1
236 @return true for change
240 ##############################################
241 ## Import/Export Methods
242 ##############################################
243 def export_data(self):
245 Export this block's params to nested data.
246 @return a nested data odict
249 n['key'] = self.get_key()
250 n['param'] = map(lambda p: p.export_data(), self.get_params())
253 def import_data(self, n):
255 Import this block's params from nested data.
256 Any param keys that do not exist will be ignored.
257 @param n the nested data odict
259 params_n = n.findall('param')
260 for param_n in params_n:
261 key = param_n.find('key')
262 value = param_n.find('value')
263 #the key must exist in this block's params
264 if key in self.get_param_keys():
265 self.get_param(key).set_value(value)