#!/usr/bin/env python
import datetime
import glob
import os
import rdflib
import re
import shutil
import subprocess
import sys
import xml.dom
import xml.dom.minidom
sys.path.append("./lv2specgen")
import lv2specgen
out_base = os.path.join('build', 'ns')
try:
shutil.rmtree(out_base)
except:
pass
os.makedirs(out_base)
URIPREFIX = 'http://lv2plug.in/ns/'
DOXPREFIX = 'ns/doc/html/'
SPECGENDIR = './specgen'
STYLEURI = os.path.join('aux', 'style.css')
TAGFILE = './doclinks'
doap = rdflib.Namespace('http://usefulinc.com/ns/doap#')
lv2 = rdflib.Namespace('http://lv2plug.in/ns/lv2core#')
owl = rdflib.Namespace('http://www.w3.org/2002/07/owl#')
rdf = rdflib.Namespace('http://www.w3.org/1999/02/22-rdf-syntax-ns#')
devnull = open(os.devnull, 'w')
# Generate code (headers) documentation
print('** Generating header documentation')
print(' * Calling doxygen in ' + os.getcwd())
subprocess.call('doxygen', stdout=devnull)
# Rescue Doxygen tag file from XML hell
# Return the content of the first child node with a certain tag name
def getChildText(elt, tagname):
elements = elt.getElementsByTagName(tagname)
for e in elements:
if e.parentNode == elt:
return e.firstChild.nodeValue
return ''
tagdoc = xml.dom.minidom.parse('c_tags')
root = tagdoc.documentElement
bettertags = open(TAGFILE, 'w')
for cn in root.childNodes:
if cn.nodeType == xml.dom.Node.ELEMENT_NODE and cn.tagName == 'compound':
if cn.getAttribute('kind') == 'page':
continue
name = getChildText(cn, 'name')
filename = getChildText(cn, 'filename')
# Sometimes the .html is there, sometimes it isn't...
if filename[-5:] != '.html':
filename += '.html'
bettertags.write('%s %s%s\n' % (name, DOXPREFIX, filename))
if cn.getAttribute('kind') == 'file':
prefix = ''
else:
prefix = name + '::'
members = cn.getElementsByTagName('member')
for m in members:
mname = prefix + getChildText(m, 'name')
mafile = getChildText(m, 'anchorfile')
manchor = getChildText(m, 'anchor')
bettertags.write('%s %s%s#%s\n' % (mname, DOXPREFIX, \
mafile, manchor))
bettertags.close()
def subst_file(template, output, dict):
i = open(template, 'r')
o = open(output, 'w')
for line in i:
for key in dict:
line = line.replace(key, dict[key])
o.write(line)
i.close()
o.close()
print('** Generating core documentation')
lv2_outdir = os.path.join(out_base, 'lv2core')
os.mkdir(lv2_outdir)
shutil.copy('core.lv2/lv2.h', lv2_outdir)
shutil.copy('core.lv2/lv2.ttl', lv2_outdir)
shutil.copy('core.lv2/manifest.ttl', lv2_outdir)
oldcwd = os.getcwd()
os.chdir(lv2_outdir)
print(' * Running lv2specgen for lv2core in ' + os.getcwd())
lv2specgen.save('lv2.html',
lv2specgen.specgen('../../../core.lv2/lv2.ttl',
'../../../lv2specgen',
os.path.join('..', '..', 'ns', 'doc'),
STYLEURI,
os.path.join('..', '..'),
os.path.join('..', '..', '..', TAGFILE),
instances=True))
os.chdir(oldcwd)
subst_file('doc/htaccess.in', '%s/lv2core/.htaccess' % out_base,
{ '@NAME@': 'lv2core',
'@BASE@': '/ns/lv2core' })
footer = open('./lv2specgen/footer.html', 'r')
# Generate main (ontology) documentation and indices
for dir in ['ext', 'extensions']:
print("** Generating %s%s documentation" % (URIPREFIX, dir))
outdir = os.path.join(out_base, dir)
shutil.copytree(dir, outdir, ignore=shutil.ignore_patterns('.*', 'waf', 'wscript', '*.in'))
index_html = """
LV2 Extension Index
Name Description Version Date Status \n"""
extensions = []
for bundle in glob.glob(os.path.join(dir, '*.lv2')):
b = bundle.replace('.lv2', '')
b = b[b.find('/') + 1:]
try:
model = rdflib.ConjunctiveGraph()
model.parse('%s/manifest.ttl' % bundle, format='n3')
model.parse('%s/%s.ttl' % (bundle, b), format='n3')
except:
e = sys.exc_info()[1]
print('error parsing %s: %s' % (bundle, str(e)))
continue
# Get extension URI
ext_node = model.value(None, rdf.type, lv2.Specification)
if not ext_node:
continue
ext = str(ext_node)
# Get version
minor = 0
micro = 0
try:
minor = int(model.value(ext_node, lv2.minorVersion, None))
micro = int(model.value(ext_node, lv2.microVersion, None))
except Exception as e:
print "warning: %s: failed to find version for %s" % (bundle, ext)
pass
# Get date
date = None
for r in model.triples([ext_node, doap.release, None]):
revision = model.value(r[2], doap.revision, None)
if revision != ("%d.%d" % (minor, micro)):
print("warning: %s: doap:revision %s != %d.%d" % (
bundle, revision, minor, micro))
continue
date = model.value(r[2], doap.created, None)
break
# Get short description
shortdesc = model.value(ext_node, doap.shortdesc, None)
specgendir = '../../../lv2specgen/'
if (os.access(outdir + '/%s.lv2/%s.ttl' % (b, b), os.R_OK)):
oldcwd = os.getcwd()
os.chdir(outdir)
print(' * Running lv2specgen for %s in %s' % (b, os.getcwd()))
lv2specgen.save('%s.lv2/%s.html' % (b, b),
lv2specgen.specgen('%s.lv2/%s.ttl' % (b, b),
specgendir,
os.path.join('..', '..', '..', 'ns', 'doc'),
STYLEURI,
os.path.join('..', '..', '..'),
os.path.join('..', '..', '..', TAGFILE),
instances=True))
os.chdir(oldcwd)
# Name
row = '%s ' % (b, b)
# Description
if shortdesc:
row += '' + str(shortdesc) + ' '
else:
row += ' '
# Version
version_str = '%s.%s' % (minor, micro)
if minor == 0 or (micro % 2 != 0):
row += '' + version_str + ' dev '
else:
row += '' + version_str + ' '
# Date
row += '%s ' % (str(date) if date else '')
# Status
deprecated = model.value(ext_node, owl.deprecated, None)
if minor == 0:
row += 'Experimental '
elif deprecated and str(deprecated[2]) != "false":
row += 'Deprecated '
elif micro % 2 == 0:
row += 'Stable '
row += ' '
extensions.append(row)
subst_file('doc/htaccess.in', '%s/%s.lv2/.htaccess' % (outdir, b),
{ '@NAME@': b,
'@BASE@': '/ns/%s/%s' % (dir, b) })
# Remove .lv2 suffix from bundle name (to make URI resolvable)
os.rename(outdir + '/%s.lv2' % b, outdir + '/%s' % b)
extensions.sort()
for i in extensions:
index_html += i + '\n'
index_html += '
\n
\n'
index_html += ''
index_html += '\n'
index_file = open(os.path.join(outdir, 'index.html'), 'w')
index_file.write(index_html)
index_file.close()
# Copy stylesheet
try:
os.mkdir(os.path.join('build', 'aux'))
except:
pass
shutil.copy('lv2specgen/style.css', os.path.join('build', STYLEURI))
devnull.close()
footer.close()