7 lv2
= "http://lv2plug.in/ns/lv2core#"
8 lv2evt
= "http://lv2plug.in/ns/ext/event#"
9 rdf
= "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
10 rdfs
= "http://www.w3.org/2000/01/rdf-schema#"
11 epi
= "http://lv2plug.in/ns/dev/extportinfo#"
12 rdf_type
= rdf
+ "type"
13 tinyname_uri
= "http://lv2plug.in/ns/dev/tiny-name"
16 def addTriple(self
, s
, p
, o
):
17 print "%s [%s] %s" % (s
, p
, repr(o
))
23 def getByType(self
, classname
):
24 classes
= self
.bySubject
["$classes"]
25 if classname
in classes
:
26 return classes
[classname
]
28 def getByPropType(self
, propname
):
29 if propname
in self
.byPredicate
:
30 return self
.byPredicate
[propname
]
32 def getProperty(self
, subject
, props
, optional
= False, single
= False):
33 if type(props
) is list:
37 if type(subject
) is str:
38 subject
= self
.bySubject
[subject
]
39 elif type(subject
) is dict:
48 for o
in subject
[prop
]:
50 if type(props
) is list:
55 value
= self
.getProperty(v
, props
[1:], optional
= optional
, single
= True)
59 result |
= set(self
.getProperty(v
, props
[1:], optional
= optional
, single
= False))
67 raise Exception, "More than one value of " + prop
68 return list(anyprops
)[0]
74 def addTriple(self
, s
, p
, o
):
77 if s
not in self
.bySubject
:
78 self
.bySubject
[s
] = {}
79 if p
not in self
.bySubject
[s
]:
80 self
.bySubject
[s
][p
] = []
81 self
.bySubject
[s
][p
].append(o
)
82 if p
not in self
.byPredicate
:
83 self
.byPredicate
[p
] = {}
84 if s
not in self
.byPredicate
[p
]:
85 self
.byPredicate
[p
][s
] = []
86 self
.byPredicate
[p
][s
].append(o
)
88 self
.addTriple("$classes", o
, s
)
89 def copyFrom(self
, src
):
90 for s
in src
.bySubject
:
94 self
.addTriple(s
, p
, o
)
96 for s
in self
.bySubject
.keys():
97 for p
in self
.bySubject
[s
].keys():
98 print "%s %s %s" % (s
, p
, self
.bySubject
[s
][p
])
100 def parseTTL(uri
, content
, model
, debug
):
101 # Missing stuff: translated literals, blank nodes
103 print "Parsing: %s" % uri
109 for x
in calfpytools
.scan_ttl_string(content
):
116 elif (x
[0] == '.' and spo_stack
== []) or x
[0] == ';' or x
[0] == ',':
118 if spo
[0] == "@prefix":
119 prefixes
[spo
[1][:-1]] = spo
[2]
121 model
.addTriple(spo
[0], spo
[1], spo
[2])
122 if x
[0] == '.': item
= 0
123 elif x
[0] == ';': item
= 1
124 elif x
[0] == ',': item
= 2
129 raise Exception, uri
+": Unexpected " + x
[0]
130 elif x
[0] == "prnot" and item
< 3:
131 prnot
= x
[1].split(":")
132 if item
!= 0 and spo
[0] == "@prefix":
134 elif prnot
[0] == "_":
135 spo
[item
] = uri
+ "#" + prnot
[1]
137 spo
[item
] = prefixes
[prnot
[0]] + prnot
[1]
139 elif (x
[0] == 'URI' or x
[0] == "string" or x
[0] == "number" or (x
[0] == "symbol" and x
[1] == "a" and item
== 1)) and (item
< 3):
140 if x
[0] == "URI" and x
[1] == "":
142 elif x
[0] == "URI" and x
[1].find(":") == -1 and x
[1] != "" and x
[1][0] != "/":
143 # This is quite silly
144 x
= ("URI", os
.path
.dirname(uri
) + "/" + x
[1])
149 raise Exception, "Incorrect use of ["
150 uri2
= uri
+ "$anon$" + str(anoncnt
)
152 spo_stack
.append(spo
)
156 elif x
[0] == ']' or x
[0] == ')':
158 model
.addTriple(spo
[0], spo
[1], spo
[2])
161 spo_stack
= spo_stack
[:-1]
165 raise Exception, "Incorrect use of ("
166 uri2
= uri
+ "$anon$" + str(anoncnt
)
168 spo_stack
.append(spo
)
173 print uri
+ ": Unexpected: " + repr(x
)
175 class LV2Port(object):
178 def connectableTo(self
, port
):
179 if not ((self
.isInput
and port
.isOutput
) or (self
.isOutput
and port
.isInput
)):
181 if self
.isAudio
!= port
.isAudio
or self
.isControl
!= port
.isControl
or self
.isEvent
!= port
.isEvent
:
183 if not self
.isAudio
and not self
.isControl
and not self
.isEvent
:
187 class LV2Plugin(object):
192 def __init__(self
, debug
= False):
196 def initManifests(self
):
197 lv2path
= ["/usr/lib/lv2", "/usr/local/lib/lv2"]
198 self
.manifests
= SimpleRDFModel()
200 self
.plugin_info
= dict()
203 for bundle
in glob
.iglob(dir + "/*.lv2"):
204 fn
= bundle
+"/manifest.ttl"
205 if os
.path
.exists(fn
):
206 parseTTL(fn
, file(fn
).read(), self
.manifests
, self
.debug
)
207 # Read all specifications from all manifests
208 if (lv2
+ "Specification" in self
.manifests
.bySubject
["$classes"]):
209 specs
= self
.manifests
.getByType(lv2
+ "Specification")
212 subj
= self
.manifests
.bySubject
[spec
]
213 if rdfs
+"seeAlso" in subj
:
214 for fn
in subj
[rdfs
+"seeAlso"]:
217 parseTTL(fn
, file(fn
).read(), self
.manifests
, self
.debug
)
218 #fn = "/usr/lib/lv2/lv2core.lv2/lv2.ttl"
219 #parseTTL(fn, file(fn).read(), self.manifests)
220 self
.plugins
= self
.manifests
.getByType(lv2
+ "Plugin")
221 self
.categories
= set()
222 self
.category_paths
= []
223 self
.add_category_recursive([], lv2
+ "Plugin")
225 def add_category_recursive(self
, tree_pos
, category
):
226 cat_name
= self
.manifests
.getProperty(category
, rdfs
+ "label", single
= True, optional
= True)
227 self
.category_paths
.append(((tree_pos
+ [cat_name
])[1:], category
))
228 self
.categories
.add(category
)
229 items
= self
.manifests
.byPredicate
[rdfs
+ "subClassOf"]
231 if subj
in self
.categories
:
233 for o
in items
[subj
]:
234 if o
== category
and subj
not in self
.categories
:
235 self
.add_category_recursive(list(tree_pos
) + [cat_name
], subj
)
237 def get_categories(self
):
238 return self
.category_paths
240 def getPluginList(self
):
243 def getPluginInfo(self
, uri
):
244 if uri
not in self
.plugin_info
:
245 world
= SimpleRDFModel()
246 world
.copyFrom(self
.manifests
)
247 seeAlso
= self
.manifests
.bySubject
[uri
]["http://www.w3.org/2000/01/rdf-schema#seeAlso"]
249 # print "Loading " + doc + " for plugin " + uri
250 parseTTL(doc
, file(doc
).read(), world
, self
.debug
)
251 self
.plugin_info
[uri
] = world
252 info
= self
.plugin_info
[uri
]
255 dest
.name
= info
.bySubject
[uri
]['http://usefulinc.com/ns/doap#name'][0]
256 dest
.license
= info
.bySubject
[uri
]['http://usefulinc.com/ns/doap#license'][0]
257 dest
.classes
= info
.bySubject
[uri
]["a"]
258 dest
.requiredFeatures
= info
.getProperty(uri
, lv2
+ "requiredFeature", optional
= True)
259 dest
.optionalFeatures
= info
.getProperty(uri
, lv2
+ "optionalFeature", optional
= True)
260 dest
.microname
= info
.getProperty(uri
, tinyname_uri
, optional
= True)
261 if len(dest
.microname
):
262 dest
.microname
= dest
.microname
[0]
264 dest
.microname
= None
268 "isAudio" : lv2
+ "AudioPort",
269 "isControl" : lv2
+ "ControlPort",
270 "isEvent" : lv2evt
+ "EventPort",
271 "isInput" : lv2
+ "InputPort",
272 "isOutput" : lv2
+ "OutputPort",
275 for port
in info
.bySubject
[uri
][lv2
+ "port"]:
276 psubj
= info
.bySubject
[port
]
279 pdata
.index
= int(info
.getProperty(psubj
, lv2
+ "index")[0])
280 pdata
.symbol
= info
.getProperty(psubj
, lv2
+ "symbol")[0]
281 pdata
.name
= info
.getProperty(psubj
, lv2
+ "name")[0]
282 classes
= set(info
.getProperty(psubj
, "a"))
283 pdata
.classes
= classes
284 for pt
in porttypes
.keys():
285 pdata
.__dict
__[pt
] = porttypes
[pt
] in classes
286 sp
= info
.getProperty(psubj
, lv2
+ "scalePoint")
290 name
= info
.getProperty(pt
, rdfs
+ "label", optional
= True, single
= True)
292 value
= info
.getProperty(pt
, rdf
+ "value", optional
= True, single
= True)
294 splist
.append((name
, value
))
295 pdata
.scalePoints
= splist
297 pdata
.scalePoints
= []
298 pdata
.defaultValue
= info
.getProperty(psubj
, [lv2
+ "default"], optional
= True, single
= True)
299 pdata
.minimum
= info
.getProperty(psubj
, [lv2
+ "minimum"], optional
= True, single
= True)
300 pdata
.maximum
= info
.getProperty(psubj
, [lv2
+ "maximum"], optional
= True, single
= True)
301 pdata
.microname
= info
.getProperty(psubj
, [tinyname_uri
], optional
= True, single
= True)
302 pdata
.properties
= set(info
.getProperty(psubj
, [lv2
+ "portProperty"], optional
= True))
304 portDict
[pdata
.uri
] = pdata
305 ports
.sort(lambda x
, y
: cmp(x
.index
, y
.index
))
307 dest
.portDict
= portDict