Collection of tools useful for audio production
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

814 lines
27KB

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # LADSPA RDF python support
  4. # Copyright (C) 2011-2012 Filipe Coelho <falktx@gmail.com>
  5. #
  6. # This program is free software; you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 2 of the License, or
  9. # any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # For a full copy of the GNU General Public License see the COPYING file
  17. # -------------------------------------------------------------------------------
  18. # C types
  19. # Imports (Global)
  20. from ctypes import *
  21. from copy import deepcopy
  22. # Base Types
  23. LADSPA_Data = c_float
  24. LADSPA_Property = c_int
  25. LADSPA_PluginType = c_ulonglong
  26. # Unit Types
  27. LADSPA_UNIT_DB = 0x01
  28. LADSPA_UNIT_COEF = 0x02
  29. LADSPA_UNIT_HZ = 0x04
  30. LADSPA_UNIT_S = 0x08
  31. LADSPA_UNIT_MS = 0x10
  32. LADSPA_UNIT_MIN = 0x20
  33. LADSPA_UNIT_CLASS_AMPLITUDE = LADSPA_UNIT_DB|LADSPA_UNIT_COEF
  34. LADSPA_UNIT_CLASS_FREQUENCY = LADSPA_UNIT_HZ
  35. LADSPA_UNIT_CLASS_TIME = LADSPA_UNIT_S|LADSPA_UNIT_MS|LADSPA_UNIT_MIN
  36. # Port Types (Official API)
  37. LADSPA_PORT_INPUT = 0x1
  38. LADSPA_PORT_OUTPUT = 0x2
  39. LADSPA_PORT_CONTROL = 0x4
  40. LADSPA_PORT_AUDIO = 0x8
  41. # Port Hints
  42. LADSPA_PORT_UNIT = 0x1
  43. LADSPA_PORT_DEFAULT = 0x2
  44. LADSPA_PORT_LABEL = 0x4
  45. # Plugin Types
  46. LADSPA_CLASS_UTILITY = 0x000000001
  47. LADSPA_CLASS_GENERATOR = 0x000000002
  48. LADSPA_CLASS_SIMULATOR = 0x000000004
  49. LADSPA_CLASS_OSCILLATOR = 0x000000008
  50. LADSPA_CLASS_TIME = 0x000000010
  51. LADSPA_CLASS_DELAY = 0x000000020
  52. LADSPA_CLASS_PHASER = 0x000000040
  53. LADSPA_CLASS_FLANGER = 0x000000080
  54. LADSPA_CLASS_CHORUS = 0x000000100
  55. LADSPA_CLASS_REVERB = 0x000000200
  56. LADSPA_CLASS_FREQUENCY = 0x000000400
  57. LADSPA_CLASS_FREQUENCY_METER = 0x000000800
  58. LADSPA_CLASS_FILTER = 0x000001000
  59. LADSPA_CLASS_LOWPASS = 0x000002000
  60. LADSPA_CLASS_HIGHPASS = 0x000004000
  61. LADSPA_CLASS_BANDPASS = 0x000008000
  62. LADSPA_CLASS_COMB = 0x000010000
  63. LADSPA_CLASS_ALLPASS = 0x000020000
  64. LADSPA_CLASS_EQ = 0x000040000
  65. LADSPA_CLASS_PARAEQ = 0x000080000
  66. LADSPA_CLASS_MULTIEQ = 0x000100000
  67. LADSPA_CLASS_AMPLITUDE = 0x000200000
  68. LADSPA_CLASS_PITCH = 0x000400000
  69. LADSPA_CLASS_AMPLIFIER = 0x000800000
  70. LADSPA_CLASS_WAVESHAPER = 0x001000000
  71. LADSPA_CLASS_MODULATOR = 0x002000000
  72. LADSPA_CLASS_DISTORTION = 0x004000000
  73. LADSPA_CLASS_DYNAMICS = 0x008000000
  74. LADSPA_CLASS_COMPRESSOR = 0x010000000
  75. LADSPA_CLASS_EXPANDER = 0x020000000
  76. LADSPA_CLASS_LIMITER = 0x040000000
  77. LADSPA_CLASS_GATE = 0x080000000
  78. LADSPA_CLASS_SPECTRAL = 0x100000000
  79. LADSPA_CLASS_NOTCH = 0x200000000
  80. LADSPA_GROUP_DYNAMICS = LADSPA_CLASS_DYNAMICS|LADSPA_CLASS_COMPRESSOR|LADSPA_CLASS_EXPANDER|LADSPA_CLASS_LIMITER|LADSPA_CLASS_GATE
  81. LADSPA_GROUP_AMPLITUDE = LADSPA_CLASS_AMPLITUDE|LADSPA_CLASS_AMPLIFIER|LADSPA_CLASS_WAVESHAPER|LADSPA_CLASS_MODULATOR|LADSPA_CLASS_DISTORTION|LADSPA_GROUP_DYNAMICS
  82. LADSPA_GROUP_EQ = LADSPA_CLASS_EQ|LADSPA_CLASS_PARAEQ|LADSPA_CLASS_MULTIEQ
  83. LADSPA_GROUP_FILTER = LADSPA_CLASS_FILTER|LADSPA_CLASS_LOWPASS|LADSPA_CLASS_HIGHPASS|LADSPA_CLASS_BANDPASS|LADSPA_CLASS_COMB|LADSPA_CLASS_ALLPASS|LADSPA_CLASS_NOTCH
  84. LADSPA_GROUP_FREQUENCY = LADSPA_CLASS_FREQUENCY|LADSPA_CLASS_FREQUENCY_METER|LADSPA_GROUP_FILTER|LADSPA_GROUP_EQ|LADSPA_CLASS_PITCH
  85. LADSPA_GROUP_SIMULATOR = LADSPA_CLASS_SIMULATOR|LADSPA_CLASS_REVERB
  86. LADSPA_GROUP_TIME = LADSPA_CLASS_TIME|LADSPA_CLASS_DELAY|LADSPA_CLASS_PHASER|LADSPA_CLASS_FLANGER|LADSPA_CLASS_CHORUS|LADSPA_CLASS_REVERB
  87. LADSPA_GROUP_GENERATOR = LADSPA_CLASS_GENERATOR|LADSPA_CLASS_OSCILLATOR
  88. # A Scale Point
  89. class LADSPA_RDF_ScalePoint(Structure):
  90. _fields_ = [
  91. ("Value", LADSPA_Data),
  92. ("Label", c_char_p)
  93. ]
  94. # A Port
  95. class LADSPA_RDF_Port(Structure):
  96. _fields_ = [
  97. ("Type", LADSPA_Property),
  98. ("Hints", LADSPA_Property),
  99. ("Label", c_char_p),
  100. ("Default", LADSPA_Data),
  101. ("Unit", LADSPA_Property),
  102. ("ScalePointCount", c_ulong),
  103. ("ScalePoints", POINTER(LADSPA_RDF_ScalePoint))
  104. ]
  105. # The actual plugin descriptor
  106. class LADSPA_RDF_Descriptor(Structure):
  107. _fields_ = [
  108. ("Type", LADSPA_PluginType),
  109. ("UniqueID", c_ulong),
  110. ("Title", c_char_p),
  111. ("Creator", c_char_p),
  112. ("PortCount", c_ulong),
  113. ("Ports", POINTER(LADSPA_RDF_Port))
  114. ]
  115. # -------------------------------------------------------------------------------
  116. # Python compatible C types
  117. PyLADSPA_RDF_ScalePoint = {
  118. 'Value': 0.0,
  119. 'Label': ""
  120. }
  121. PyLADSPA_RDF_Port = {
  122. 'Type': 0x0,
  123. 'Hints': 0x0,
  124. 'Label': "",
  125. 'Default': 0.0,
  126. 'Unit': 0x0,
  127. 'ScalePointCount': 0,
  128. 'ScalePoints': [],
  129. # Only here to help, NOT in the API:
  130. 'index': 0
  131. }
  132. PyLADSPA_RDF_Descriptor = {
  133. 'Type': 0x0,
  134. 'UniqueID': 0,
  135. 'Title': "",
  136. 'Creator': "",
  137. 'PortCount': 0,
  138. 'Ports': []
  139. }
  140. # -------------------------------------------------------------------------------
  141. # RDF data and conversions
  142. # Namespaces
  143. NS_dc = "http://purl.org/dc/elements/1.1/"
  144. NS_rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  145. NS_rdfs = "http://www.w3.org/2000/01/rdf-schema#"
  146. NS_ladspa = "http://ladspa.org/ontology#"
  147. # Prefixes (sorted alphabetically and by type)
  148. rdf_prefix = {
  149. # Base types
  150. 'dc:creator': NS_dc+"creator",
  151. 'dc:rights': NS_dc+"rights",
  152. 'dc:title': NS_dc+"title",
  153. 'rdf:value': NS_rdf+"value",
  154. 'rdf:type': NS_rdf+"type",
  155. # LADSPA Stuff
  156. 'ladspa:forPort': NS_ladspa+"forPort",
  157. 'ladspa:hasLabel': NS_ladspa+"hasLabel",
  158. 'ladspa:hasPoint': NS_ladspa+"hasPoint",
  159. 'ladspa:hasPort': NS_ladspa+"hasPort",
  160. 'ladspa:hasPortValue': NS_ladspa+"hasPortValue",
  161. 'ladspa:hasScale': NS_ladspa+"hasScale",
  162. 'ladspa:hasSetting': NS_ladspa+"hasSetting",
  163. 'ladspa:hasUnit': NS_ladspa+"hasUnit",
  164. # LADSPA Extensions
  165. 'ladspa:NotchPlugin': NS_ladspa+"NotchPlugin",
  166. 'ladspa:SpectralPlugin': NS_ladspa+"SpectralPlugin"
  167. }
  168. def get_c_plugin_class(value):
  169. value_str = value.replace(NS_ladspa,"")
  170. if (value_str == "Plugin"):
  171. return 0
  172. elif (value_str == "UtilityPlugin"):
  173. return LADSPA_CLASS_UTILITY
  174. elif (value_str == "GeneratorPlugin"):
  175. return LADSPA_CLASS_GENERATOR
  176. elif (value_str == "SimulatorPlugin"):
  177. return LADSPA_CLASS_SIMULATOR
  178. elif (value_str == "OscillatorPlugin"):
  179. return LADSPA_CLASS_OSCILLATOR
  180. elif (value_str == "TimePlugin"):
  181. return LADSPA_CLASS_TIME
  182. elif (value_str == "DelayPlugin"):
  183. return LADSPA_CLASS_DELAY
  184. elif (value_str == "PhaserPlugin"):
  185. return LADSPA_CLASS_PHASER
  186. elif (value_str == "FlangerPlugin"):
  187. return LADSPA_CLASS_FLANGER
  188. elif (value_str == "ChorusPlugin"):
  189. return LADSPA_CLASS_CHORUS
  190. elif (value_str == "ReverbPlugin"):
  191. return LADSPA_CLASS_REVERB
  192. elif (value_str == "FrequencyPlugin"):
  193. return LADSPA_CLASS_FREQUENCY
  194. elif (value_str == "FrequencyMeterPlugin"):
  195. return LADSPA_CLASS_FREQUENCY_METER
  196. elif (value_str == "FilterPlugin"):
  197. return LADSPA_CLASS_FILTER
  198. elif (value_str == "LowpassPlugin"):
  199. return LADSPA_CLASS_LOWPASS
  200. elif (value_str == "HighpassPlugin"):
  201. return LADSPA_CLASS_HIGHPASS
  202. elif (value_str == "BandpassPlugin"):
  203. return LADSPA_CLASS_BANDPASS
  204. elif (value_str == "CombPlugin"):
  205. return LADSPA_CLASS_COMB
  206. elif (value_str == "AllpassPlugin"):
  207. return LADSPA_CLASS_ALLPASS
  208. elif (value_str == "EQPlugin"):
  209. return LADSPA_CLASS_EQ
  210. elif (value_str == "ParaEQPlugin"):
  211. return LADSPA_CLASS_PARAEQ
  212. elif (value_str == "MultiEQPlugin"):
  213. return LADSPA_CLASS_MULTIEQ
  214. elif (value_str == "AmplitudePlugin"):
  215. return LADSPA_CLASS_AMPLITUDE
  216. elif (value_str == "PitchPlugin"):
  217. return LADSPA_CLASS_PITCH
  218. elif (value_str == "AmplifierPlugin"):
  219. return LADSPA_CLASS_AMPLIFIER
  220. elif (value_str == "WaveshaperPlugin"):
  221. return LADSPA_CLASS_WAVESHAPER
  222. elif (value_str == "ModulatorPlugin"):
  223. return LADSPA_CLASS_MODULATOR
  224. elif (value_str == "DistortionPlugin"):
  225. return LADSPA_CLASS_DISTORTION
  226. elif (value_str == "DynamicsPlugin"):
  227. return LADSPA_CLASS_DYNAMICS
  228. elif (value_str == "CompressorPlugin"):
  229. return LADSPA_CLASS_COMPRESSOR
  230. elif (value_str == "ExpanderPlugin"):
  231. return LADSPA_CLASS_EXPANDER
  232. elif (value_str == "LimiterPlugin"):
  233. return LADSPA_CLASS_LIMITER
  234. elif (value_str == "GatePlugin"):
  235. return LADSPA_CLASS_GATE
  236. elif (value_str == "SpectralPlugin"):
  237. return LADSPA_CLASS_SPECTRAL
  238. elif (value_str == "NotchPlugin"):
  239. return LADSPA_CLASS_NOTCH
  240. elif (value_str == "MixerPlugin"):
  241. return LADSPA_CLASS_EQ
  242. else:
  243. print("LADSPA_RDF - Got an unknown plugin type '%s'" % (value_str))
  244. return 0
  245. def get_c_port_type(value):
  246. value_str = value.replace(NS_ladspa,"")
  247. if (value_str == "Port"):
  248. return 0
  249. elif (value_str == "ControlPort"):
  250. return LADSPA_PORT_CONTROL
  251. elif (value_str == "AudioPort"):
  252. return LADSPA_PORT_AUDIO
  253. elif (value_str == "InputPort"):
  254. return LADSPA_PORT_INPUT
  255. elif (value_str == "OutputPort"):
  256. return LADSPA_PORT_OUTPUT
  257. elif (value_str in ("ControlInputPort", "InputControlPort")):
  258. return LADSPA_PORT_CONTROL|LADSPA_PORT_INPUT
  259. elif (value_str in ("ControlOutputPort", "OutputControlPort")):
  260. return LADSPA_PORT_CONTROL|LADSPA_PORT_OUTPUT
  261. elif (value_str in ("AudioInputPort", "InputAudioPort")):
  262. return LADSPA_PORT_AUDIO|LADSPA_PORT_INPUT
  263. elif (value_str in ("AudioOutputPort", "OutputAudioPort")):
  264. return LADSPA_PORT_AUDIO|LADSPA_PORT_OUTPUT
  265. else:
  266. print("LADSPA_RDF - Got an unknown port type '%s'" % (value_str))
  267. return 0
  268. def get_c_unit_type(value):
  269. value_str = value.replace(NS_ladspa,"")
  270. if (value_str in ("Unit", "Units", "AmplitudeUnits", "FrequencyUnits", "TimeUnits")):
  271. return 0
  272. elif (value_str == "dB"):
  273. return LADSPA_UNIT_DB
  274. elif (value_str == "coef"):
  275. return LADSPA_UNIT_COEF
  276. elif (value_str == "Hz"):
  277. return LADSPA_UNIT_HZ
  278. elif (value_str == "seconds"):
  279. return LADSPA_UNIT_S
  280. elif (value_str == "milliseconds"):
  281. return LADSPA_UNIT_MS
  282. elif (value_str == "minutes"):
  283. return LADSPA_UNIT_MIN
  284. else:
  285. print("LADSPA_RDF - Got an unknown unit type '%s'" % (value_str))
  286. return 0
  287. # -------------------------------------------------------------------------------
  288. # Global objects
  289. global LADSPA_RDF_PATH, LADSPA_Plugins
  290. LADSPA_RDF_PATH = ("/usr/share/ladspa/rdf", "/usr/local/share/ladspa/rdf")
  291. LADSPA_Plugins = []
  292. # Set LADSPA_RDF_PATH variable
  293. def set_rdf_path(PATH):
  294. global LADSPA_RDF_PATH
  295. LADSPA_RDF_PATH = PATH
  296. # -------------------------------------------------------------------------------
  297. # Helper methods
  298. LADSPA_RDF_TYPE_PLUGIN = 1
  299. LADSPA_RDF_TYPE_PORT = 2
  300. # Check RDF Type
  301. def rdf_is_type(_subject, compare):
  302. if (type(_subject) == URIRef and NS_ladspa in _subject):
  303. if (compare == LADSPA_RDF_TYPE_PLUGIN):
  304. return bool(to_plugin_number(_subject).isdigit())
  305. elif (compare == LADSPA_RDF_TYPE_PORT):
  306. return bool("." in to_plugin_number(_subject))
  307. else:
  308. return False
  309. def to_float(rdf_item):
  310. return float(str(rdf_item).replace("f",""))
  311. # Convert RDF LADSPA subject into a number
  312. def to_plugin_number(_subject):
  313. return str(_subject).replace(NS_ladspa,"")
  314. # Convert RDF LADSPA subject into a plugin and port number
  315. def to_plugin_and_port_number(_subject):
  316. numbers = str(_subject).replace(NS_ladspa,"").split(".")
  317. return (numbers[0], numbers[1])
  318. # Convert RDF LADSPA subject into a port number
  319. def to_plugin_port(_subject):
  320. return to_plugin_and_port_number(_subject)[1]
  321. # -------------------------------------------------------------------------------
  322. # RDF store/retrieve data methods
  323. def check_and_add_plugin(plugin_id):
  324. global LADSPA_Plugins
  325. for i in range(len(LADSPA_Plugins)):
  326. if (LADSPA_Plugins[i]['UniqueID'] == plugin_id):
  327. return i
  328. else:
  329. plugin = deepcopy(PyLADSPA_RDF_Descriptor)
  330. plugin['UniqueID'] = plugin_id
  331. LADSPA_Plugins.append(plugin)
  332. return len(LADSPA_Plugins)-1
  333. def set_plugin_value(plugin_id, key, value):
  334. global LADSPA_Plugins
  335. index = check_and_add_plugin(plugin_id)
  336. LADSPA_Plugins[index][key] = value
  337. def add_plugin_value(plugin_id, key, value):
  338. global LADSPA_Plugins
  339. index = check_and_add_plugin(plugin_id)
  340. LADSPA_Plugins[index][key] += value
  341. def or_plugin_value(plugin_id, key, value):
  342. global LADSPA_Plugins
  343. index = check_and_add_plugin(plugin_id)
  344. LADSPA_Plugins[index][key] |= value
  345. def append_plugin_value(plugin_id, key, value):
  346. global LADSPA_Plugins
  347. index = check_and_add_plugin(plugin_id)
  348. LADSPA_Plugins[index][key].append(value)
  349. def check_and_add_port(plugin_id, port_id):
  350. global LADSPA_Plugins
  351. index = check_and_add_plugin(plugin_id)
  352. Ports = LADSPA_Plugins[index]['Ports']
  353. for i in range(len(Ports)):
  354. if (Ports[i]['index'] == port_id):
  355. return (index, i)
  356. else:
  357. pcount = LADSPA_Plugins[index]['PortCount']
  358. port = deepcopy(PyLADSPA_RDF_Port)
  359. port['index'] = port_id
  360. Ports.append(port)
  361. LADSPA_Plugins[index]['PortCount'] += 1
  362. return (index, pcount)
  363. def set_port_value(plugin_id, port_id, key, value):
  364. global LADSPA_Plugins
  365. i, j = check_and_add_port(plugin_id, port_id)
  366. LADSPA_Plugins[i]['Ports'][j][key] = value
  367. def add_port_value(plugin_id, port_id, key, value):
  368. global LADSPA_Plugins
  369. i, j = check_and_add_port(plugin_id, port_id)
  370. LADSPA_Plugins[i]['Ports'][j][key] += value
  371. def or_port_value(plugin_id, port_id, key, value):
  372. global LADSPA_Plugins
  373. i, j = check_and_add_port(plugin_id, port_id)
  374. LADSPA_Plugins[i]['Ports'][j][key] |= value
  375. def append_port_value(plugin_id, port_id, key, value):
  376. global LADSPA_Plugins
  377. i, j = check_and_add_port(plugin_id, port_id)
  378. LADSPA_Plugins[i]['Ports'][j][key].append(value)
  379. def add_scalepoint(plugin_id, port_id, value, label):
  380. global LADSPA_Plugins
  381. i, j = check_and_add_port(plugin_id, port_id)
  382. Port = LADSPA_Plugins[i]['Ports'][j]
  383. scalepoint = deepcopy(PyLADSPA_RDF_ScalePoint)
  384. scalepoint['Value'] = value
  385. scalepoint['Label'] = label
  386. Port['ScalePoints'].append(scalepoint)
  387. Port['ScalePointCount'] += 1
  388. def set_port_default(plugin_id, port_id, value):
  389. global LADSPA_Plugins
  390. i, j = check_and_add_port(plugin_id, port_id)
  391. Port = LADSPA_Plugins[i]['Ports'][j]
  392. Port['Default'] = value
  393. Port['Hints'] |= LADSPA_PORT_DEFAULT
  394. def get_node_objects(value_nodes, n_subject):
  395. ret_nodes = []
  396. for _subject, _predicate, _object in value_nodes:
  397. if (_subject == n_subject):
  398. ret_nodes.append((_predicate, _object))
  399. return ret_nodes
  400. def append_and_sort(value, vlist):
  401. if (len(vlist) == 0):
  402. vlist.append(value)
  403. elif (value < vlist[0]):
  404. vlist.insert(0, value)
  405. elif (value > vlist[len(vlist)-1]):
  406. vlist.append(value)
  407. else:
  408. for i in range(len(vlist)):
  409. if (value < vlist[i]):
  410. vlist.insert(i, value)
  411. break
  412. else:
  413. print("LADSPA_RDF - CRITICAL ERROR #001")
  414. return vlist
  415. def get_value_index(value, vlist):
  416. for i in range(len(vlist)):
  417. if (vlist[i] == value):
  418. return i
  419. else:
  420. print("LADSPA_RDF - CRITICAL ERROR #002")
  421. return 0
  422. # -------------------------------------------------------------------------------
  423. # RDF sort data methods
  424. # Sort the plugin's port's ScalePoints by value
  425. def SORT_PyLADSPA_RDF_ScalePoints(old_dict_list):
  426. new_dict_list = []
  427. indexes_list = []
  428. for i in range(len(old_dict_list)):
  429. new_dict_list.append(deepcopy(PyLADSPA_RDF_ScalePoint))
  430. append_and_sort(old_dict_list[i]['Value'], indexes_list)
  431. for i in range(len(old_dict_list)):
  432. index = get_value_index(old_dict_list[i]['Value'], indexes_list)
  433. new_dict_list[index]['Value'] = old_dict_list[i]['Value']
  434. new_dict_list[index]['Label'] = old_dict_list[i]['Label']
  435. return new_dict_list
  436. # Sort the plugin's port by index
  437. def SORT_PyLADSPA_RDF_Ports(old_dict_list):
  438. new_dict_list = []
  439. max_index = -1
  440. for i in range(len(old_dict_list)):
  441. if (old_dict_list[i]['index'] > max_index):
  442. max_index = old_dict_list[i]['index']
  443. for i in range(max_index+1):
  444. new_dict_list.append(deepcopy(PyLADSPA_RDF_Port))
  445. for i in range(len(old_dict_list)):
  446. index = old_dict_list[i]['index']
  447. new_dict_list[index]['index'] = old_dict_list[i]['index']
  448. new_dict_list[index]['Type'] = old_dict_list[i]['Type']
  449. new_dict_list[index]['Hints'] = old_dict_list[i]['Hints']
  450. new_dict_list[index]['Unit'] = old_dict_list[i]['Unit']
  451. new_dict_list[index]['Default'] = old_dict_list[i]['Default']
  452. new_dict_list[index]['Label'] = old_dict_list[i]['Label']
  453. new_dict_list[index]['ScalePointCount'] = old_dict_list[i]['ScalePointCount']
  454. new_dict_list[index]['ScalePoints'] = SORT_PyLADSPA_RDF_ScalePoints(old_dict_list[i]['ScalePoints'])
  455. return new_dict_list
  456. # -------------------------------------------------------------------------------
  457. # RDF data parsing
  458. from rdflib import ConjunctiveGraph, URIRef, Literal, BNode
  459. # Fully parse rdf file
  460. def parse_rdf_file(filename):
  461. primer = ConjunctiveGraph()
  462. try:
  463. primer.parse(filename, format='xml')
  464. rdf_list = [(x, y, z) for x, y, z in primer]
  465. except:
  466. rdf_list = []
  467. # For BNodes
  468. index_nodes = [] # Subject [index], Predicate, Plugin, Port
  469. value_nodes = [] # Subject [index], Predicate, Object
  470. # Parse RDF list
  471. for _subject, _predicate, _object in rdf_list:
  472. # Fix broken or old plugins
  473. if (_predicate == URIRef("http://ladspa.org/ontology#hasUnits")):
  474. _predicate = URIRef(rdf_prefix['ladspa:hasUnit'])
  475. # Plugin information
  476. if (rdf_is_type(_subject, LADSPA_RDF_TYPE_PLUGIN)):
  477. plugin_id = int(to_plugin_number(_subject))
  478. if (_predicate == URIRef(rdf_prefix['dc:creator'])):
  479. set_plugin_value(plugin_id, 'Creator', str(_object))
  480. elif (_predicate == URIRef(rdf_prefix['dc:rights'])):
  481. # No useful information here
  482. pass
  483. elif (_predicate == URIRef(rdf_prefix['dc:title'])):
  484. set_plugin_value(plugin_id, 'Title', str(_object))
  485. elif (_predicate == URIRef(rdf_prefix['rdf:type'])):
  486. c_class = get_c_plugin_class(str(_object))
  487. or_plugin_value(plugin_id, 'Type', c_class)
  488. elif (_predicate == URIRef(rdf_prefix['ladspa:hasPort'])):
  489. # No useful information here
  490. pass
  491. elif (_predicate == URIRef(rdf_prefix['ladspa:hasSetting'])):
  492. index_nodes.append((_object, _predicate, plugin_id, None))
  493. else:
  494. print("LADSPA_RDF - Plugin predicate '%s' not handled" % (_predicate))
  495. # Port information
  496. elif (rdf_is_type(_subject, LADSPA_RDF_TYPE_PORT)):
  497. plugin_port = to_plugin_and_port_number(_subject)
  498. plugin_id = int(plugin_port[0])
  499. port_id = int(plugin_port[1])
  500. if (_predicate == URIRef(rdf_prefix['rdf:type'])):
  501. c_class = get_c_port_type(str(_object))
  502. or_port_value(plugin_id, port_id, 'Type', c_class)
  503. elif (_predicate == URIRef(rdf_prefix['ladspa:hasLabel'])):
  504. set_port_value(plugin_id, port_id, 'Label', str(_object))
  505. or_port_value(plugin_id, port_id, 'Hints', LADSPA_PORT_LABEL)
  506. elif (_predicate == URIRef(rdf_prefix['ladspa:hasScale'])):
  507. index_nodes.append((_object, _predicate, plugin_id, port_id))
  508. elif (_predicate == URIRef(rdf_prefix['ladspa:hasUnit'])):
  509. c_unit = get_c_unit_type(str(_object))
  510. set_port_value(plugin_id, port_id, 'Unit', c_unit)
  511. or_port_value(plugin_id, port_id, 'Hints', LADSPA_PORT_UNIT)
  512. else:
  513. print("LADSPA_RDF - Port predicate '%s' not handled" % (_predicate))
  514. # These "extensions" are already implemented
  515. elif (_subject in (URIRef(rdf_prefix['ladspa:NotchPlugin']), URIRef(rdf_prefix['ladspa:SpectralPlugin']))):
  516. pass
  517. elif (type(_subject) == BNode):
  518. value_nodes.append((_subject, _predicate, _object))
  519. else:
  520. print("LADSPA_RDF - Unknown subject type '%s'" % (_subject))
  521. # Parse BNodes, indexes
  522. bnodes_data_dump = []
  523. for n_subject, n_predicate, plugin_id, port_id in index_nodes:
  524. n_objects = get_node_objects(value_nodes, n_subject)
  525. for subn_predicate, subn_subject in n_objects:
  526. subn_objects = get_node_objects(value_nodes, subn_subject)
  527. for real_predicate, real_object in subn_objects:
  528. if (n_predicate == URIRef(rdf_prefix['ladspa:hasScale']) and subn_predicate == URIRef(rdf_prefix['ladspa:hasPoint'])):
  529. bnodes_data_dump.append(("scalepoint", subn_subject, plugin_id, port_id, real_predicate, real_object))
  530. elif (n_predicate == URIRef(rdf_prefix['ladspa:hasSetting']) and subn_predicate == URIRef(rdf_prefix['ladspa:hasPortValue'])):
  531. bnodes_data_dump.append(("port_default", subn_subject, plugin_id, port_id, real_predicate, real_object))
  532. else:
  533. print("LADSPA_RDF - Unknown BNode combo - '%s' + '%s'" % (n_predicate, subn_predicate))
  534. # Process BNodes, values
  535. scalepoints = [] # subject, plugin, port, value, label
  536. port_defaults = [] # subject, plugin, port, def-value
  537. for n_type, n_subject, n_plugin, n_port, n_predicate, n_object in bnodes_data_dump:
  538. if (n_type == "scalepoint"):
  539. for i in range(len(scalepoints)):
  540. if (scalepoints[i][0] == n_subject):
  541. index = i
  542. break
  543. else:
  544. scalepoints.append([n_subject, n_plugin, n_port, None, None])
  545. index = len(scalepoints)-1
  546. if (n_predicate == URIRef(rdf_prefix['rdf:value'])):
  547. scalepoints[index][3] = to_float(n_object)
  548. elif (n_predicate == URIRef(rdf_prefix['ladspa:hasLabel'])):
  549. scalepoints[index][4] = str(n_object)
  550. elif (n_type == "port_default"):
  551. for i in range(len(port_defaults)):
  552. if (port_defaults[i][0] == n_subject):
  553. index = i
  554. break
  555. else:
  556. port_defaults.append([n_subject, n_plugin, None, None])
  557. index = len(port_defaults)-1
  558. if (n_predicate == URIRef(rdf_prefix['ladspa:forPort'])):
  559. port_defaults[index][2] = int(to_plugin_port(n_object))
  560. elif (n_predicate == URIRef(rdf_prefix['rdf:value'])):
  561. port_defaults[index][3] = to_float(n_object)
  562. # Now add the last information
  563. for scalepoint in scalepoints:
  564. index, plugin_id, port_id, value, label = scalepoint
  565. add_scalepoint(plugin_id, port_id, value, label)
  566. for port_default in port_defaults:
  567. index, plugin_id, port_id, value = port_default
  568. set_port_default(plugin_id, port_id, value)
  569. # -------------------------------------------------------------------------------
  570. # LADSPA_RDF main methods
  571. import os
  572. # Main function - check all rdfs for information about ladspa plugins
  573. def recheck_all_plugins(qobject, start_value, percent_value, m_value):
  574. global LADSPA_RDF_PATH, LADSPA_Plugins
  575. LADSPA_Plugins = []
  576. rdf_files = []
  577. rdf_extensions = (".rdf", ".rdF", ".rDF", ".RDF", ".RDf", "Rdf")
  578. # Get all RDF files
  579. for PATH in LADSPA_RDF_PATH:
  580. for root, dirs, files in os.walk(PATH):
  581. for filename in [filename for filename in files if filename.endswith(rdf_extensions)]:
  582. rdf_files.append(os.path.join(root, filename))
  583. # Parse all RDF files
  584. for i in range(len(rdf_files)):
  585. rdf_file = rdf_files[i]
  586. # Tell GUI we're parsing this bundle
  587. if (qobject):
  588. percent = (float(i) / len(rdf_files) ) * percent_value
  589. qobject.pluginLook(start_value + (percent * m_value), rdf_file)
  590. # Parse RDF
  591. parse_rdf_file(rdf_file)
  592. return LADSPA_Plugins
  593. # Convert PyLADSPA_Plugins into ctype structs
  594. def get_c_ladspa_rdfs(PyPluginList):
  595. C_LADSPA_Plugins = []
  596. c_unicode_error_str = "(unicode error)".encode("utf-8")
  597. for plugin in PyPluginList:
  598. # Sort the ports by index
  599. ladspa_ports = SORT_PyLADSPA_RDF_Ports(plugin['Ports'])
  600. # Initial data
  601. desc = LADSPA_RDF_Descriptor()
  602. desc.Type = plugin['Type']
  603. desc.UniqueID = plugin['UniqueID']
  604. try:
  605. if (plugin['Title'])
  606. desc.Title = plugin['Title'].encode("utf-8")
  607. else:
  608. desc.Title = None
  609. except:
  610. desc.Title = c_unicode_error_str
  611. try:
  612. if (plugin['Creator'])
  613. desc.Creator = plugin['Creator'].encode("utf-8")
  614. else:
  615. desc.Creator = None
  616. except:
  617. desc.Creator = c_unicode_error_str
  618. desc.PortCount = plugin['PortCount']
  619. # Ports
  620. _PortType = LADSPA_RDF_Port*desc.PortCount
  621. desc.Ports = _PortType()
  622. for i in range(desc.PortCount):
  623. port = LADSPA_RDF_Port()
  624. py_port = ladspa_ports[i]
  625. port.Type = py_port['Type']
  626. port.Hints = py_port['Hints']
  627. try:
  628. port.Label = py_port['Label'].encode("utf-8")
  629. except:
  630. port.Label = c_unicode_error_str
  631. port.Default = py_port['Default']
  632. port.Unit = py_port['Unit']
  633. # ScalePoints
  634. port.ScalePointCount = py_port['ScalePointCount']
  635. _ScalePointType = LADSPA_RDF_ScalePoint*port.ScalePointCount
  636. port.ScalePoints = _ScalePointType()
  637. for j in range(port.ScalePointCount):
  638. scalepoint = LADSPA_RDF_ScalePoint()
  639. py_scalepoint = py_port['ScalePoints'][j]
  640. try:
  641. scalepoint.Label = py_scalepoint['Label'].encode("utf-8")
  642. except:
  643. scalepoint.Label = c_unicode_error_str
  644. scalepoint.Value = py_scalepoint['Value']
  645. port.ScalePoints[j] = scalepoint
  646. desc.Ports[i] = port
  647. C_LADSPA_Plugins.append(desc)
  648. return C_LADSPA_Plugins
  649. # -------------------------------------------------------------------------------
  650. # Implementation test
  651. #if __name__ == '__main__':
  652. #set_rdf_path(["/home/falktx/Personal/FOSS/GIT/Cadence/lrdf/"])
  653. #plugins = recheck_all_plugins(None, 0)
  654. #for plugin in LADSPA_Plugins:
  655. #print("----------------------")
  656. #print("Type: 0x%X" % (plugin["Type"]))
  657. #print("UniqueID: %i" % (plugin["UniqueID"]))
  658. #print("Title: %s" % (plugin["Title"]))
  659. #print("Creator: %s" % (plugin["Creator"]))
  660. #print("Ports: (%i)" % (plugin["PortCount"]))
  661. #for i in range(plugin["PortCount"]):
  662. #port = plugin["Ports"][i]
  663. #print(" --> Port #%i" % (i+1))
  664. #print(" Type: 0x%X" % (port["Type"]))
  665. #print(" Hints: 0x%X" % (port["Hints"]))
  666. #print(" Label: %s" % (port["Label"]))
  667. #print(" Default: %f" % (port["Default"]))
  668. #print(" Unit: 0x%i" % (port["Unit"]))
  669. #print(" ScalePoints: (%i)" % (port["ScalePointCount"]))
  670. #for j in range(port["ScalePointCount"]):
  671. #scalepoint = port["ScalePoints"][j]
  672. #print(" --> ScalePoint #%i" % (j+1))
  673. #print(" Value: %f" % (scalepoint["Value"]))
  674. #print(" Label: %s" % (scalepoint["Label"]))
  675. #print(len(LADSPA_Plugins))
  676. #get_c_ladspa_rdfs(LADSPA_Plugins)