5 ## generate doc/luadoc.json.gz (lua binding doc)
6 # ./waf configure --luadoc ....
8 # ./gtk2_ardour/arluadoc > doc/luadoc.json.gz
10 ## generate doc/ardourapi.json.gz (ardour header doxygen doc)
11 # cd ../../tools/doxy2json
15 ## format HTML (using this scripterl)
16 # php tools/fmt-luadoc.php > /tmp/luadoc.html
19 ################################################################################
20 ################################################################################
22 $json = gzdecode (file_get_contents (dirname (__FILE__).'/../doc/luadoc.json.gz'));
25 foreach (json_decode ($json, true) as $b) {
26 if (!isset ($b['type'])) {
27 if (isset ($b['version'])) { $ardourversion = $b['version']; }
30 $b ['ldec'] = preg_replace ('/ const/', '', preg_replace ('/ const&/', '', $b['decl']));
31 if (isset ($b['ret'])) {
32 $b['ret'] = preg_replace ('/ const/', '', preg_replace ('/ const&/', '', $b['ret']));
37 if (count ($doc) == 0) {
38 fwrite (STDERR, "Failed to read luadoc.json\n");
42 ################################################################################
43 ## Global result variables
44 ################################################################################
46 $classlist = array ();
47 $constlist = array ();
50 ################################################################################
51 ## Pre-process the data, collect functions, parse arguments, cross reference
52 ################################################################################
55 ################################################################################
56 # some internal helper functions first
62 function my_die ($msg) {
63 fwrite (STDERR, $msg."\n");
67 ##function ptr_strip ($ctype) {
68 # # boost::shared_ptr<std::list<boost::shared_ptr<ARDOUR::Route>> > >
69 # # -> std::list<ARDOUR::Route>
70 # $ctype = preg_replace ('/boost::shared_ptr<([^>]*)[ ]*>/', '$1', $ctype);
71 # return preg_replace ('/boost::shared_ptr<([^>]*)[ ]*>/', '$1', $ctype);
74 function arg2lua ($argtype, $flags = 0) {
78 # LuaBridge abstracts C++ references
79 $flags |= preg_match ('/&$/', $argtype);
80 $arg = preg_replace ('/&$/', '', $argtype);
81 $arg = preg_replace ('/ $/', '', $arg);
83 # filter out basic types
84 $builtin = array ('float', 'double', 'bool', 'std::string', 'int', 'long', 'unsigned long', 'unsigned int', 'unsigned char', 'char', 'void', 'char*', 'unsigned char*', 'void*');
85 if (in_array ($arg, $builtin)) {
86 return array ($arg => $flags);
89 # check Class declarations first
90 foreach (array_merge ($classes, $consts) as $b) {
91 if ($b['ldec'] == $arg) {
92 return array ($b['lua'] => $flags);
96 # strip class pointers -- TODO Check C'tor for given class
97 $arg = preg_replace ('/[&*]*$/', '', $argtype);
98 foreach (array_merge ($classes, $consts) as $b) {
99 if ($b['ldec'] == $arg) {
100 return array ($b['lua'] => $flags);
104 return array ($argtype => ($flags | 4));
106 return array ('--MISSING (' . $argtype . ')--' => ($flags | 4));
110 function stripclass ($classname, $name) {
112 if (strpos ($name, $classname) !== 0) {
113 my_die ('invalid class prefix: ' .$classname. ' -- '. $name);
115 return substr ($name, strlen ($classname));
118 function datatype ($decl) {
119 # TODO handle spaces in type. Works because
120 # we don't yet have templated types (with_space <here >)
121 return substr ($decl, 0, strpos ($decl, ' '));
124 function luafn2class ($lua) {
125 return substr ($lua, 0, strrpos ($lua, ':'));
128 function checkclass ($b) {
130 if (!isset ($classlist[luafn2class ($b['lua'])])) {
131 my_die ('MISSING CLASS FOR '. print_r ($b['lua'], true));
135 # parse functions argument list to lua-names
136 function decl2args ($decl) {
137 $start = strrpos ($decl, '(');
138 $end = strrpos ($decl, ')');
139 $args = substr ($decl, $start + 1, $end - $start - 1);
140 $arglist = preg_split ('/, */', $args);
142 foreach ($arglist as $a) {
143 if (empty ($a)) { continue; }
144 $rv[] = arg2lua ($a);
149 function canonical_ctor ($b) {
151 if (preg_match('/[^(]*\(([^)*]*)\*\)(\(.*\))/', $b['decl'], $matches)) {
152 $lc = luafn2class ($b['lua']);
153 $cn = str_replace (':', '::', $lc);
154 $fn = substr ($lc, 1 + strrpos ($lc, ':'));
155 $rv = $cn . '::'. $fn . $matches[2];
160 function canonical_decl ($b) {
163 # match clang's declatation format
164 if (preg_match('/[^(]*\(([^)*]*)\*\)\((.*)\)/', $b['decl'], $matches)) {
165 if (strpos ($b['type'], 'Free Function') !== false) {
166 $pfx = str_replace (':', '::', luafn2class ($b['lua'])) . '::';
168 $fn = substr ($b['lua'], 1 + strrpos ($b['lua'], ':'));
169 $rv = $matches[1] . $fn . '(';
170 $arglist = preg_split ('/, */', $matches[2]);
172 foreach ($arglist as $a) {
173 if (!$first) { $rv .= ', '; }; $first = false;
174 if (empty ($a)) { continue; }
175 $a = preg_replace ('/([^>]) >/', '$1>', $a);
176 $a = preg_replace ('/^Cairo::/', '', $a); // special case cairo enums
177 $a = preg_replace ('/([^ ])&/', '$1 &', $a);
178 $a = str_replace ('vector', 'std::vector', $a);
179 $a = str_replace ('std::string', 'string', $a);
180 $a = str_replace ('string const', 'const string', $a);
181 $a = str_replace ('string', 'std::string', $a);
189 ################################################################################
190 # step 1: build class indices
192 foreach ($doc as $b) {
193 if (strpos ($b['type'], "[C] ") === 0) {
195 $classlist[$b['lua']] = $b;
196 if (strpos ($b['type'], 'Pointer Class') === false) {
197 $classdecl[$b['ldec']] = $b;
202 foreach ($classes as $c) {
203 if (strpos ($c['type'], 'Pointer Class') !== false) { continue; }
204 if (isset ($c['parent'])) {
205 if (isset ($classdecl[$c['parent']])) {
206 $classlist[$c['lua']]['luaparent'][] = $classdecl[$c['parent']]['lua'];
208 my_die ('unknown parent class: ' . print_r ($c, true));
213 # step 2: extract constants/enum
214 foreach ($doc as $b) {
215 switch ($b['type']) {
216 case "Constant/Enum":
217 case "Constant/Enum Member":
218 if (strpos ($b['ldec'], '::') === false) {
219 # for extern c enums, use the Lua Namespace
220 $b['ldec'] = str_replace (':', '::', luafn2class ($b['lua']));
222 $ns = str_replace ('::', ':', $b['ldec']);
223 $constlist[$ns][] = $b;
233 # step 3: process functions
234 foreach ($doc as $b) {
235 switch ($b['type']) {
237 case "Weak/Shared Pointer Constructor":
239 $classlist[luafn2class ($b['lua'])]['ctor'][] = array (
240 'name' => luafn2class ($b['lua']),
241 'args' => decl2args ($b['ldec']),
242 'cand' => canonical_ctor ($b)
247 $classlist[luafn2class ($b['lua'])]['data'][] = array (
249 'ret' => arg2lua (datatype ($b['ldec']))
253 # we required C functions to be in a class namespace
254 case "Ext C Function":
256 $args = array (array ('--lua--' => 0));
257 $ret = array ('...' => 0);
258 $ns = luafn2class ($b['lua']);
259 $cls = $classlist[$ns];
260 ## std::Vector std::List types
261 if (preg_match ('/.*<([^>]*)[ ]*>/', $cls['ldec'], $templ)) {
262 // XXX -> move to C-source
263 switch (stripclass($ns, $b['lua'])) {
265 #$args = array (array ('LuaTable {'.$templ[1].'}' => 0));
266 $args = array (arg2lua ($templ[1], 2));
267 $ret = array ('LuaTable' => 0);
271 $ret = array ('LuaIter' => 0);
275 $ret = array ('LuaTable' => 0);
280 } else if (strpos ($cls['type'], ' Array') !== false) {
281 $templ = preg_replace ('/[&*]*$/', '', $cls['ldec']);
282 switch (stripclass($ns, $b['lua'])) {
285 $ret = array ('LuaMetaTable' => 0);
289 $ret = array ('LuaTable' => 0);
292 $args = array (array ('LuaTable {'.$templ.'}' => 0));
293 $ret = array ('void' => 0);
299 $classlist[luafn2class ($b['lua'])]['func'][] = array (
306 'cand' => canonical_decl ($b)
309 case "Free Function":
310 case "Free Function RefReturn":
311 $funclist[luafn2class ($b['lua'])][] = array (
314 'args' => decl2args ($b['ldec']),
315 'ret' => arg2lua ($b['ret']),
316 'ref' => (strpos ($b['type'], "RefReturn") !== false),
317 'cand' => canonical_decl ($b)
320 case "Member Function":
321 case "Member Function RefReturn":
322 case "Member Pointer Function":
323 case "Weak/Shared Pointer Function":
324 case "Weak/Shared Pointer Function RefReturn":
325 case "Weak/Shared Null Check":
326 case "Weak/Shared Pointer Cast":
327 case "Static Member Function":
329 $classlist[luafn2class ($b['lua'])]['func'][] = array (
332 'args' => decl2args ($b['ldec']),
333 'ret' => arg2lua ($b['ret']),
334 'ref' => (strpos ($b['type'], "RefReturn") !== false),
335 'cand' => canonical_decl ($b)
338 case "Constant/Enum":
339 case "Constant/Enum Member":
340 # already handled -> $consts
343 if (strpos ($b['type'], "[C] ") !== 0) {
344 my_die ('unhandled type: ' . $b['type']);
351 # step 4: collect/group/sort
353 # step 4a: unify weak/shared Ptr classes
354 foreach ($classlist as $ns => $cl) {
355 if (strpos ($cl['type'], ' Array') !== false) {
356 $classlist[$ns]['arr'] = true;
359 foreach ($classes as $c) {
360 if ($c['lua'] == $ns) {
361 if (strpos ($c['type'], 'Pointer Class') !== false) {
362 $classlist[$ns]['ptr'] = true;
363 $classlist[$ns]['decl'] = 'boost::shared_ptr< '.$c['decl']. ' >, boost::weak_ptr< '.$c['decl']. ' >';
370 # step4b: sanity check
371 foreach ($classlist as $ns => $cl) {
372 if (isset ($classes[$ns]['parent']) && !isset ($classlist[$ns]['luaparent'])) {
373 my_die ('missing parent class: ' . print_r ($cl, true));
377 # step 4c: merge free functions into classlist
378 foreach ($funclist as $ns => $fl) {
379 if (isset ($classlist[$ns])) {
380 my_die ('Free Funcion in existing namespace: '.$ns.' '. print_r ($ns, true));
382 $classlist[$ns]['func'] = $fl;
383 $classlist[$ns]['free'] = true;
386 # step 4d: order to chaos
387 # no array_multisort() here, sub-types are sorted after merging parents
391 ################################################################################
392 ################################################################################
393 ################################################################################
396 #### -- split here -- ####
398 # from here on, only $classlist and $constlist arrays are relevant.
399 # we also pull in C++ header annotation from doxygen to $api
402 # read documentation from doxygen
403 $json = gzdecode (file_get_contents (dirname (__FILE__).'/../doc/ardourapi.json.gz'));
405 foreach (json_decode ($json, true) as $a) {
406 if (!isset ($a['decl'])) { continue; }
407 if (empty ($a['decl'])) { continue; }
408 $canon = str_replace (' *', '*', $a['decl']);
412 # keep track of found/missing doc
416 # retrive a value from $api
417 function doxydoc ($canonical_declaration) {
421 if (isset ($api[$canonical_declaration])) {
423 return $api[$canonical_declaration]['doc'];
430 ################################################################################
432 ################################################################################
435 ################################################################################
439 # constructors, enums (constants) use a dot. (e.g. "LuaOSC.Address" -> "LuaOSC.Address" )
440 function ctorname ($name) {
441 return htmlentities (str_replace (':', '.', $name));
444 # strip class prefix (e.g "Evoral:MidiEvent:channel" -> "channel")
445 function shortname ($name) {
446 return htmlentities (substr ($name, strrpos ($name, ':') + 1));
449 # retrieve variable name from array["VARNAME"] => FLAGS
450 function varname ($a) {
451 return array_keys ($a)[0];
454 # recusively collect class parents (derived classes)
455 function traverse_parent ($ns, &$inherited) {
458 if (isset ($classlist[$ns]['luaparent'])) {
459 $parents = array_unique ($classlist[$ns]['luaparent']);
461 foreach ($parents as $p) {
462 if (!empty ($rv)) { $rv .= ', '; }
463 $rv .= typelink ($p);
464 $inherited[$p] = $classlist[$p];
465 traverse_parent ($p, $inherited);
471 # create a cross-reference to a type (class or enum)
472 # *all* <a> links are generated here, currently anchors on a single page.
473 function typelink ($a, $short = false, $argcls = '', $linkcls = '', $suffix = '') {
476 if (isset($classlist[$a]['free'])) {
477 return '<a class="'.$linkcls.'" href="#'.htmlentities ($a).'">'.($short ? shortname($a) : ctorname($a)).$suffix.'</a>';
478 } else if (in_array ($a, array_keys ($classlist))) {
479 return '<a class="'.$linkcls.'" href="#'.htmlentities($a).'">'.($short ? shortname($a) : htmlentities($a)).$suffix.'</a>';
480 } else if (in_array ($a, array_keys ($constlist))) {
481 return '<a class="'.$linkcls.'" href="#'.ctorname ($a).'">'.($short ? shortname($a) : ctorname($a)).$suffix.'</a>';
483 return '<span class="'.$argcls.'">'.htmlentities($a).$suffix.'</span>';
487 # output format function arguments
488 function format_args ($args) {
489 $rv = '<span class="functionargs"> (';
491 foreach ($args as $a) {
492 if (!$first) { $rv .= ', '; }; $first = false;
493 $flags = $a[varname ($a)];
495 $rv .= '<em>LuaTable</em> {'.typelink (varname ($a), true, 'em').'}';
497 elseif ($flags & 1) {
498 $rv .= typelink (varname ($a), true, 'em', '', '&');
501 $rv .= typelink (varname ($a), true, 'em');
508 # format doxygen documentation for class-definition
509 function format_doxyclass ($cl) {
511 if (isset ($cl['decl'])) {
512 $doc = doxydoc ($cl['decl']);
514 $rv.= '<div class="classdox">'.$doc.'</div>'.NL;
520 # format doxygen documentation for class-members
521 function format_doxydoc ($f) {
523 if (isset ($f['cand'])) {
524 $doc = doxydoc ($f['cand']);
526 $rv.= '<tr><td></td><td class="doc" colspan="2"><div class="dox">'.$doc;
527 $rv.= '</div></td></tr>'.NL;
528 } else if (0) { # debug
529 $rv.= '<tr><td></td><td class="doc" colspan="2"><p>'.htmlentities($f['cand']).'</p>';
530 $rv.= '</td></tr>'.NL;
536 # usort() callback for class-members
537 function name_sort_cb ($a, $b) {
538 return strcmp ($a['name'], $b['name']);
541 # main output function for every class
542 function format_class_members ($ns, $cl, &$dups) {
544 # print contructor - if any
545 if (isset ($cl['ctor'])) {
546 usort ($cl['ctor'], 'name_sort_cb');
547 $rv.= ' <tr><th colspan="3">Constructor</th></tr>'.NL;
548 foreach ($cl['ctor'] as $f) {
549 $rv.= ' <tr><td class="def">ℂ</td><td class="decl">';
550 $rv.= '<span class="functionname">'.ctorname ($f['name']).'</span>';
551 $rv.= format_args ($f['args']);
552 $rv.= '</td><td class="fill"></td></tr>'.NL;
553 # doxygen documentation (may be empty)
554 $rv.= format_doxydoc($f);
558 # strip duplicates (inherited or derived methods)
559 # e.g AudioTrack -> Track -> Route -> SessionObject -> Stateful
560 # all 5 have "isnil()"
562 if (isset ($cl['func'])) {
563 foreach ($cl['func'] as $f) {
564 if (in_array (stripclass ($ns, $f['name']), $dups)) { continue; }
569 # print methods - if any
570 if (count ($nondups) > 0) {
571 usort ($nondups, 'name_sort_cb');
572 $rv.= ' <tr><th colspan="3">Methods</th></tr>'.NL;
573 foreach ($nondups as $f) {
574 $dups[] = stripclass ($ns, $f['name']);
576 $rv.= ' <tr><td class="def">';
577 if ($f['ref'] && isset ($f['ext'])) {
578 # external C functions
579 $rv.= '<em>'.varname ($f['ret']).'</em>';
580 } elseif ($f['ref'] && varname ($f['ret']) == 'void') {
581 # void functions with reference args
582 $rv.= '<em>LuaTable</em>(...)';
583 } elseif ($f['ref']) {
584 # functions with reference args and return value
585 $rv.= '<em>LuaTable</em>('.typelink (varname ($f['ret']), true, 'em').', ...)';
587 # normal class members
588 $rv.= typelink (varname ($f['ret']), true, 'em');
590 # function declaration and arguments
591 $rv.= '</td><td class="decl">';
592 $rv.= '<span class="functionname"><abbr title="'.htmlentities($f['bind']['decl']).'">'.stripclass ($ns, $f['name']).'</abbr></span>';
593 $rv.= format_args ($f['args']);
594 $rv.= '</td><td class="fill"></td></tr>'.NL;
595 # doxygen documentation (may be empty)
596 $rv.= format_doxydoc($f);
599 # print data members - if any
600 if (isset ($cl['data'])) {
601 usort ($cl['data'], 'name_sort_cb');
602 $rv.= ' <tr><th colspan="3">Data Members</th></tr>'.NL;
603 foreach ($cl['data'] as $f) {
604 $rv.= ' <tr><td class="def">'.typelink (array_keys ($f['ret'])[0], false, 'em').'</td><td class="decl">';
605 $rv.= '<span class="functionname">'.stripclass ($ns, $f['name']).'</span>';
606 $rv.= '</td><td class="fill"></td></tr>'.NL;
613 ################################################################################
617 <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
619 <title>Ardour Lua Bindings</title>
620 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
621 <style type="text/css">
622 div.content { max-width:60em; margin: 1em auto; }
623 h1 { margin:2em 0 0 0; padding:0em; border-bottom: 1px solid black;}
624 h2.cls { margin:2em 0 0 0; padding-left:1em; border: 1px dashed #6666ee;}
625 h2.cls abbr { text-decoration:none; cursor:default;}
626 h3.cls { margin:1em 0 0 0;}
627 h2.class { background-color: #aaee66; }
628 h2.enum { background-color: #aaaaaa; }
629 h2.pointerclass { background-color: #eeaa66; }
630 h2.array { background-color: #66aaee; }
631 h2.opaque { background-color: #6666aa; }
632 p { text-align: justify; }
633 p.cdecl { text-align: right; float:right; font-size:90%; margin:0; padding: 0 0 0 1em;}
634 ul.classindex { columns: 2; -webkit-columns: 2; -moz-columns: 2; }
635 div.clear { clear:both; }
636 p.classinfo { margin: .25em 0;}
637 div.code { width:80%; margin:.5em auto; }
638 div.code div { width:45%; }
639 div.code pre { line-height: 1.2em; margin: .25em 0; }
640 div.code samp { color: green; font-weight: bold; background-color: #eee; }
641 div.classdox { padding: .1em 1em;}
642 div.classdox p { margin: .5em 0 .5em .6em;}
643 div.classdox p { margin: .5em 0 .5em .6em;}
644 div.classdox { padding: .1em 1em;}
645 div.classdox p { margin: .5em 0 .5em .6em;}
646 table.classmembers { width: 100%; }
647 table.classmembers th { text-align:left; border-bottom:1px solid black; padding-top:1em; }
648 table.classmembers td.def { text-align:right; padding-right:.5em; white-space: nowrap;}
649 table.classmembers td.decl { text-align:left; padding-left:.5em; white-space: nowrap; }
650 table.classmembers td.doc { text-align:left; padding-left:.6em; line-height: 1.2em; font-size:80%;}
651 table.classmembers td.doc div.dox {background-color:#eee; padding: .1em 1em;}
652 table.classmembers td.doc p { margin: .5em 0; }
653 table.classmembers td.doc p.para-brief { font-size:120%; }
654 table.classmembers td.doc p.para-returns { font-size:120%; }
655 table.classmembers td.doc dl { font-size:120%; line-height: 1.3em; }
656 table.classmembers td.doc dt { font-style: italic; }
657 table.classmembers td.fill { width: 99%;}
658 table.classmembers span.em { font-style: italic;}
659 span.functionname abbr { text-decoration:none; cursor:default;}
660 div.header {text-align:center;}
661 div.header h1 {margin:0;}
662 div.header p {margin:.25em; text-align:center;}
663 div.footer {text-align:center; font-size:80%; color: #888; margin: 2em 0;}
668 <h1>Ardour Lua Bindings</h1>
670 <a href="#h_classes">Class Documentation</a>
672 <a href="#h_enum">Enum/Constants</a>
674 <a href="#h_index">Index</a>
677 <div class="content">
681 ################################################################################
682 # some general documentation -- should really go elsehere
686 <h1 id="h_intro">Overview</h1>
688 The top-level entry point are <?=typelink('ARDOUR:Session')?> and <?=typelink('ArdourUI:Editor')?>.
689 Most other Classes are used indirectly starting with a Session function. e.g. Session:get_routes().
692 A few classes are dedicated to certain script types, e.g. Lua DSP processors have exclusive access to
693 <?=typelink('ARDOUR:DSP')?> and <?=typelink('ARDOUR:ChanMapping')?>. Action Hooks Scripts to
694 <?=typelink('LuaSignal:Set')?> etc.
697 Detailed documentation (parameter names, method description) is not yet available. Please stay tuned.
699 <h2>Short introduction to Ardour classes</h2>
701 Ardour's structure is object oriented. The main object is the Session. A Session contains Audio Tracks, Midi Tracks and Busses.
702 Audio and Midi tracks are derived from a more general "Track" Object, which in turn is derived from a "Route" (aka Bus).
703 (We say "An Audio Track <em>is-a</em> Track <em>is-a</em> Route").
704 Tracks contain specifics. For Example a track <em>has-a</em> diskstream (for file i/o).
707 Operations are performed on objects. One gets a reference to an object and then calls a method.
708 e.g <code>obj = Session:route_by_name("Audio") obj:set_name("Guitar")</code>.
711 Object lifetimes are managed by the Session. Most Objects cannot be directly created, but one asks the Session to create or destroy them. This is mainly due to realtime constrains:
712 you cannot simply remove a track that is currently processing audio. There are various <em>factory</em> methods for object creation or removal.
714 <h2>Pass by Reference</h2>
716 Since lua functions are closures, C++ methods that pass arguments by reference cannot be used as-is.
717 All parameters passed to a C++ method which uses references are returned as Lua Table.
718 If the C++ method also returns a value it is prefixed. Two parameters are returned: the value and a Lua Table holding the parameters.
722 <div style="float:left;">C++
724 <pre><code class="cxx">void set_ref (int& var, long& val)
726 printf ("%d %ld\n", var, val);
733 <div style="float:right;">Lua
735 <pre><code class="lua">local var = 0;
736 ref = set_ref (var, 2);
737 -- output from C++ printf()
738 </code><samp class="lua">0 2</samp><code>
739 -- var is still 0 here
740 print (ref[1], ref[2])
741 </code><samp class="lua">5 7</samp></pre>
745 <div class="clear"></div>
747 <div style="float:left;">
749 <pre><code class="cxx">int set_ref2 (int &var, std::string unused)
757 <div style="float:right;">
758 <pre><code class="lua">rv, ref = set_ref2 (0, "hello");
759 print (rv, ref[1], ref[2])
760 </code><samp class="lua">3 5 hello</samp></pre>
763 <div class="clear"></div>
765 <h2>Pointer Classes</h2>
767 Libardour makes extensive use of reference counted <code>boost::shared_ptr</code> to manage lifetimes.
768 The Lua bindings provide a complete abstration of this. There are no pointers in lua.
769 For example a <?=typelink('ARDOUR:Route')?> is a pointer in C++, but lua functions operate on it like it was a class instance.
772 <code>shared_ptr</code> are reference counted. Once assigned to a lua variable, the C++ object will be kept and remains valid.
773 It is good practice to assign references to lua <code>local</code> variables or reset the variable to <code>nil</code> to drop the ref.
776 All pointer classes have a <code>isnil ()</code> method. This is for two cases:
777 Construction may fail. e.g. <code><?=typelink('ARDOUR:LuaAPI')?>.newplugin()</code>
778 may not be able to find the given plugin and hence cannot create an object.
781 The second case if for <code>boost::weak_ptr</code>. As opposed to <code>boost::shared_ptr</code> weak-pointers are not reference counted.
782 The object may vanish at any time.
783 If lua code calls a method on a nil object, the interpreter will raise an exception and the script will not continue.
784 This is not unlike <code>a = nil a:test()</code> which results in en error "<em>attempt to index a nil value</em>".
787 From the lua side of things there is no distinction between weak and shared pointers. They behave identically.
788 Below they're inidicated in orange and have an arrow to indicate the pointer type.
789 Pointer Classes cannot be created in lua scripts. It always requires a call to C++ to create the Object and obtain a reference to it.
795 #################################
796 # Main output function -- Classes
798 echo '<h1 id="h_classes">Class Documentation</h1>'.NL;
799 foreach ($classlist as $ns => $cl) {
801 $tbl = format_class_members ($ns, $cl, $dups);
803 # format class title - depending on type
805 # classes with no members (no ctor, no methods, no data)
806 echo '<h2 id="'.htmlentities ($ns).'" class="cls opaque"><abbr title="Opaque Object">∅</abbr> '.htmlentities ($ns).'</h2>'.NL;
808 else if (isset ($classlist[$ns]['free'])) {
809 # free functions (no class)
810 echo '<h2 id="'.htmlentities ($ns).'" class="cls freeclass"><abbr title="Namespace">ℕ</abbr> '.ctorname($ns).'</h2>'.NL;
812 else if (isset ($classlist[$ns]['arr'])) {
814 echo '<h2 id="'.htmlentities ($ns).'" class="cls array"><abbr title="C Array">⋯</abbr> '.htmlentities ($ns).'</h2>'.NL;
816 else if (isset ($classlist[$ns]['ptr'])) {
818 echo '<h2 id="'.htmlentities ($ns).'" class="cls pointerclass"><abbr title="Pointer Class">↠</abbr> '. htmlentities ($ns).'</h2>'.NL;
822 echo '<h2 id="'.htmlentities ($ns).'" class="cls class"><abbr title="Class">∁</abbr> '.htmlentities ($ns).'</h2>'.NL;
825 # show original C++ declaration
826 if (isset ($cl['decl'])) {
827 echo '<p class="cdecl"><em>C‡</em>: '.htmlentities ($cl['decl']).'</p>'.NL;
830 # print class inheritance (direct parent *name* only)
831 $inherited = array ();
832 $isa = traverse_parent ($ns, $inherited);
834 echo ' <p class="classinfo">is-a: '.$isa.'</p>'.NL;
836 echo '<div class="clear"></div>'.NL;
839 # class documentation (if any)
840 echo format_doxyclass ($cl);
842 # member documentation
844 echo '<p class="classinfo">This class object is only used indirectly as return-value and function-parameter. It provides no methods by itself.</p>'.NL;
846 echo '<table class="classmembers">'.NL;
851 # traverse parent classes (all inherited members)
852 foreach ($inherited as $pns => $pcl) {
853 $tbl = format_class_members ($pns, $pcl, $dups);
855 echo '<h3 class="cls">Inherited from '.$pns.'</h3>'.NL;
856 echo '<table class="classmembers">'.NL;
866 echo '<h1 id="h_enum">Enum/Constants</h1>'.NL;
867 foreach ($constlist as $ns => $cs) {
868 echo '<h2 id="'.ctorname ($ns).'" class="cls enum"><abbr title="Enum">∈</abbr> '.ctorname ($ns).'</h2>'.NL;
869 echo '<ul class="enum">'.NL;
870 foreach ($cs as $c) {
871 echo '<li class="const">'.ctorname ($c['lua']).'</li>'.NL;
876 ######################
877 # Index of all classes
879 echo '<h1 id="h_index" >Class Index</h1>'.NL;
880 echo '<ul class="classindex">'.NL;
881 foreach ($classlist as $ns => $cl) {
882 echo '<li>'.typelink($ns).'</li>'.NL;
887 # see how far there is still to go...
888 fwrite (STDERR, "Found $dox_found annotations. missing: $dox_miss\n");
892 <div class="footer">Ardour <?=$ardourversion?> - <?=date('r')?></div>