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
20 from ... utils import odict
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.evaluate()
51 def __init__(self, flow_graph, n):
53 Make a new block from nested data.
54 @param flow graph the parent element
55 @param n the nested odict
56 @return block a new block
59 Element.__init__(self, flow_graph)
61 params = n.findall('param')
62 sources = n.findall('source')
63 sinks = n.findall('sink')
64 self._name = n.find('name')
65 self._key = n.find('key')
66 self._category = n.find('category') or ''
67 self._block_wrapper_path = n.find('block_wrapper_path')
68 #create the param objects
69 self._params = odict()
71 self._params['id'] = self.get_parent().get_parent().Param(
79 self._params['_enabled'] = self.get_parent().get_parent().Param(
89 for param in map(lambda n: self.get_parent().get_parent().Param(self, n), params):
91 #test against repeated keys
92 try: assert(key not in self.get_param_keys())
93 except AssertionError: self._exit_with_error('Key "%s" already exists in params'%key)
95 self._params[key] = param
96 #create the source objects
97 self._sources = odict()
98 for source in map(lambda n: self.get_parent().get_parent().Source(self, n), sources):
99 key = source.get_key()
100 #test against repeated keys
101 try: assert(key not in self.get_source_keys())
102 except AssertionError: self._exit_with_error('Key "%s" already exists in sources'%key)
104 self._sources[key] = source
105 #create the sink objects
106 self._sinks = odict()
107 for sink in map(lambda n: self.get_parent().get_parent().Sink(self, n), sinks):
109 #test against repeated keys
110 try: assert(key not in self.get_sink_keys())
111 except AssertionError: self._exit_with_error('Key "%s" already exists in sinks'%key)
113 self._sinks[key] = sink
119 Call test on all children.
121 map(lambda c: c.test(), self.get_params() + self.get_sinks() + self.get_sources())
123 def get_enabled(self):
125 Get the enabled state of the block.
126 @return true for enabled
128 try: return eval(self.get_param('_enabled').get_value())
131 def set_enabled(self, enabled):
133 Set the enabled state of the block.
134 @param enabled true for enabled
136 self.get_param('_enabled').set_value(str(enabled))
141 All ports and params must be valid.
142 All checks must evaluate to true.
144 for c in self.get_params() + self.get_ports() + self.get_connections():
145 try: assert(c.is_valid())
146 except AssertionError:
147 for msg in c.get_error_messages():
148 self._add_error_message('>>> %s:\n\t%s'%(c, msg))
150 def __str__(self): return 'Block - %s - %s(%s)'%(self.get_id(), self.get_name(), self.get_key())
152 def get_id(self): return self.get_param('id').get_value()
153 def is_block(self): return True
154 def get_name(self): return self._name
155 def get_key(self): return self._key
156 def get_category(self): return self._category
157 def get_doc(self): return ''
158 def get_ports(self): return self.get_sources() + self.get_sinks()
159 def get_block_wrapper_path(self): return self._block_wrapper_path
161 ##############################################
163 ##############################################
164 def get_param_keys(self): return self._params.keys()
165 def get_param(self, key): return self._params[key]
166 def get_params(self): return self._params.values()
168 ##############################################
170 ##############################################
171 def get_sink_keys(self): return self._sinks.keys()
172 def get_sink(self, key): return self._sinks[key]
173 def get_sinks(self): return self._sinks.values()
175 ##############################################
177 ##############################################
178 def get_source_keys(self): return self._sources.keys()
179 def get_source(self, key): return self._sources[key]
180 def get_sources(self): return self._sources.values()
182 def get_connections(self):
183 return sum([port.get_connections() for port in self.get_ports()], [])
185 def resolve_dependencies(self, tmpl):
187 Resolve a paramater dependency with cheetah templates.
188 @param tmpl the string with dependencies
189 @return the resolved value
192 if '$' not in tmpl: return tmpl
193 n = dict((p.get_key(), TemplateArg(p)) for p in self.get_params())
194 try: return str(Template(tmpl, n))
195 except Exception, e: return "-------->\n%s: %s\n<--------"%(e, tmpl)
197 ##############################################
199 ##############################################
200 def type_controller_modify(self, direction):
202 Change the type controller.
203 @param direction +1 or -1
204 @return true for change
208 for param in filter(lambda p: p.is_enum(), self.get_params()):
209 children = self.get_ports() + self.get_params()
210 #priority to the type controller
211 if param.get_key() in ' '.join(map(lambda p: p._type, children)): type_param = param
212 #use param if type param is unset
213 if not type_param: type_param = param
215 #try to increment the enum by direction
217 keys = type_param.get_option_keys()
218 old_index = keys.index(type_param.get_value())
219 new_index = (old_index + direction + len(keys))%len(keys)
220 type_param.set_value(keys[new_index])
225 def port_controller_modify(self, direction):
227 Change the port controller.
228 @param direction +1 or -1
229 @return true for change
233 ##############################################
234 ## Import/Export Methods
235 ##############################################
236 def export_data(self):
238 Export this block's params to nested data.
239 @return a nested data odict
242 n['key'] = self.get_key()
243 n['param'] = map(lambda p: p.export_data(), self.get_params())
246 def import_data(self, n):
248 Import this block's params from nested data.
249 Any param keys that do not exist will be ignored.
250 @param n the nested data odict
252 params_n = n.findall('param')
253 for param_n in params_n:
254 key = param_n.find('key')
255 value = param_n.find('value')
256 #the key must exist in this block's params
257 if key in self.get_param_keys():
258 self.get_param(key).set_value(value)