2 Copyright 2008 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
23 from Element import Element as _Element
24 from FlowGraph import FlowGraph as _FlowGraph
25 from Connection import Connection as _Connection
26 from Block import Block as _Block
27 from Port import Port as _Port
28 from Param import Param as _Param
29 from Constants import DATA_DIR
31 class Platform(_Element):
33 def __init__(self, name, key, block_paths, block_dtd, block_tree, default_flow_graph, generator):
35 Make a platform from the arguments.
36 @param name the platform name
37 @param key the unique platform key
38 @param block_paths the file paths to blocks in this platform
39 @param block_dtd the dtd validator for xml block wrappers
40 @param block_tree the nested tree of block keys and categories
41 @param default_flow_graph the default flow graph file path
42 @param load_one a single file to load into this platform or None
43 @return a platform object
45 _Element.__init__(self)
48 self._block_paths = block_paths
49 self._block_dtd = block_dtd
50 self._block_tree = block_tree
51 self._default_flow_graph = default_flow_graph
52 self._generator = generator
53 #create a dummy flow graph for the blocks
54 self._flow_graph = _Element(self)
57 self._blocks_n = dict()
58 for block_path in self._block_paths:
59 if os.path.isfile(block_path): self._load_block(block_path)
60 elif os.path.isdir(block_path):
61 for dirpath, dirnames, filenames in os.walk(block_path):
62 for filename in filter(lambda f: f.endswith('.xml'), filenames):
63 self._load_block(os.path.join(dirpath, filename))
65 def get_prefs_block(self): return self.get_new_flow_graph().get_new_block('preferences')
67 def _load_block(self, f):
69 Load the block wrapper from the file path.
70 The block wrapper must pass validation, and have a unique block key.
71 If any of the checks fail, exit with error.
72 @param f the file path
74 try: ParseXML.validate_dtd(f, self._block_dtd)
75 except ParseXML.XMLSyntaxError, e: self._exit_with_error('Block definition "%s" failed: \n\t%s'%(f, e))
76 n = ParseXML.from_file(f)['block']
77 block = self.Block(self._flow_graph, n)
79 #test against repeated keys
80 try: assert(key not in self.get_block_keys())
81 except AssertionError: self._exit_with_error('Key "%s" already exists in blocks'%key)
83 self._blocks[key] = block
84 self._blocks_n[key] = n
86 def load_block_tree(self, block_tree):
88 Load a block tree with categories and blocks.
89 Step 1: Load all blocks from the xml specification.
90 Step 2: Load blocks with builtin category specifications.
91 @param block_tree the block tree object
93 #recursive function to load categories and blocks
94 def load_category(cat_n, parent=''):
96 parent = '%s/%s'%(parent, cat_n['name'])
97 block_tree.add_block(parent)
98 #recursive call to load sub categories
99 map(lambda c: load_category(c, parent), utils.listify(cat_n, 'cat'))
100 #add blocks in this category
101 for block_key in utils.listify(cat_n, 'block'):
102 block_tree.add_block(parent, self.get_block(block_key))
105 try: ParseXML.validate_dtd(f, os.path.join(DATA_DIR, 'block_tree.dtd'))
106 except ParseXML.XMLSyntaxError, e: self._exit_with_error('Block tree "%s" failed: \n\t%s'%(f, e))
107 #add all blocks in the tree
108 load_category(ParseXML.from_file(f)['cat'])
109 #add all other blocks, use the catgory
110 for block in self.get_blocks():
111 #blocks with empty categories are in the xml block tree or hidden
112 if block.get_category(): block_tree.add_block(block.get_category(), block)
114 def __str__(self): return 'Platform - %s(%s)'%(self.get_key(), self.get_name())
116 def is_platform(self): return True
118 def get_new_flow_graph(self): return self.FlowGraph(self)
120 def get_default_flow_graph(self): return self._default_flow_graph
122 def get_generator(self): return self._generator
124 ##############################################
126 ##############################################
127 def get_block_keys(self): return self._blocks.keys()
128 def get_block(self, key): return self._blocks[key]
129 def get_blocks(self): return self._blocks.values()
130 def get_new_block(self, flow_graph, key): return self.Block(flow_graph, n=self._blocks_n[key])
132 def get_name(self): return self._name
134 def get_key(self): return self._key
136 ##############################################
138 ##############################################
139 FlowGraph = _FlowGraph
140 Connection = _Connection