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 ... utils import ParseXML
22 from Element import Element as _Element
23 from FlowGraph import FlowGraph as _FlowGraph
24 from Connection import Connection as _Connection
25 from Block import Block as _Block
26 from Port import Port as _Port
27 from Param import Param as _Param
28 from Constants import BLOCK_TREE_DTD
30 class Platform(_Element):
32 def __init__(self, name, key, block_paths, block_dtd, block_tree, default_flow_graph, generator):
34 Make a platform from the arguments.
35 @param name the platform name
36 @param key the unique platform key
37 @param block_paths the file paths to blocks in this platform
38 @param block_dtd the dtd validator for xml block wrappers
39 @param block_tree the nested tree of block keys and categories
40 @param default_flow_graph the default flow graph file path
41 @param load_one a single file to load into this platform or None
42 @return a platform object
44 _Element.__init__(self)
47 self._block_paths = block_paths
48 self._block_dtd = block_dtd
49 self._block_tree = block_tree
50 self._default_flow_graph = default_flow_graph
51 self._generator = generator
52 #create a dummy flow graph for the blocks
53 self._flow_graph = _Element(self)
56 self._blocks_n = dict()
57 for block_path in self._block_paths:
58 if os.path.isfile(block_path): self._load_blocks(block_path)
59 elif os.path.isdir(block_path):
60 for dirpath, dirnames, filenames in os.walk(block_path):
61 for filename in filter(lambda f: f.endswith('.xml'), filenames):
62 self._load_blocks(os.path.join(dirpath, filename))
64 def _load_blocks(self, f):
66 Load the block wrappers from the file path.
67 The block wrapper must pass validation.
68 If any of the checks fail, exit with error.
69 @param f the file path
71 try: ParseXML.validate_dtd(f, self._block_dtd)
72 except ParseXML.XMLSyntaxError, e: self._exit_with_error('Block definition "%s" failed: \n\t%s'%(f, e))
73 n = ParseXML.from_file(f).find('block')
74 #inject block wrapper path
75 n['block_wrapper_path'] = f
76 block = self.Block(self._flow_graph, n)
78 #test against repeated keys
79 try: assert(key not in self.get_block_keys())
80 except AssertionError: self._exit_with_error('Key "%s" already exists in blocks'%key)
82 self._blocks[key] = block
83 self._blocks_n[key] = n
85 def load_block_tree(self, block_tree):
87 Load a block tree with categories and blocks.
88 Step 1: Load all blocks from the xml specification.
89 Step 2: Load blocks with builtin category specifications.
90 @param block_tree the block tree object
92 #recursive function to load categories and blocks
93 def load_category(cat_n, parent=[]):
95 parent = parent + [cat_n.find('name')]
96 block_tree.add_block(parent)
97 #recursive call to load sub categories
98 map(lambda c: load_category(c, parent), cat_n.findall('cat'))
99 #add blocks in this category
100 for block_key in cat_n.findall('block'):
101 block_tree.add_block(parent, self.get_block(block_key))
104 try: ParseXML.validate_dtd(f, BLOCK_TREE_DTD)
105 except ParseXML.XMLSyntaxError, e: self._exit_with_error('Block tree "%s" failed: \n\t%s'%(f, e))
106 #add all blocks in the tree
107 load_category(ParseXML.from_file(f).find('cat'))
108 #add all other blocks, use the catgory
109 for block in self.get_blocks():
110 #blocks with empty categories are in the xml block tree or hidden
111 if block.get_category(): block_tree.add_block(block.get_category(), block)
113 def __str__(self): return 'Platform - %s(%s)'%(self.get_key(), self.get_name())
115 def is_platform(self): return True
117 def get_new_flow_graph(self): return self.FlowGraph(self)
119 def get_default_flow_graph(self): return self._default_flow_graph
121 def get_generator(self): return self._generator
123 ##############################################
125 ##############################################
126 def get_block_keys(self): return self._blocks.keys()
127 def get_block(self, key): return self._blocks[key]
128 def get_blocks(self): return self._blocks.values()
129 def get_new_block(self, flow_graph, key): return self.Block(flow_graph, n=self._blocks_n[key])
131 def get_name(self): return self._name
133 def get_key(self): return self._key
135 ##############################################
137 ##############################################
138 FlowGraph = _FlowGraph
139 Connection = _Connection