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 $options = getopt("m");
20 if (isset ($options['m'])) {
21 $HTMLOUTPUT = false; ## set to false to output ardour-manual
23 $HTMLOUTPUT = true; ## set to false to output ardour-manual
26 ################################################################################
27 ################################################################################
29 $json = gzdecode (file_get_contents (dirname (__FILE__).'/../doc/luadoc.json.gz'));
32 foreach (json_decode ($json, true) as $b) {
33 if (!isset ($b['type'])) {
34 if (isset ($b['version'])) { $ardourversion = $b['version']; }
37 $b ['lua'] = preg_replace ('/:_end/', ':end', $b ['lua']);
38 $b ['ldec'] = preg_replace ('/ const/', '', preg_replace ('/ const&/', '', $b['decl']));
39 if (isset ($b['ret'])) {
40 $b['ret'] = preg_replace ('/ const/', '', preg_replace ('/ const&/', '', $b['ret']));
45 if (count ($doc) == 0) {
46 fwrite (STDERR, "Failed to read luadoc.json\n");
50 ################################################################################
51 ## Global result variables
52 ################################################################################
54 $classlist = array ();
55 $constlist = array ();
58 ################################################################################
59 ## Pre-process the data, collect functions, parse arguments, cross reference
60 ################################################################################
63 ################################################################################
64 # some internal helper functions first
70 function my_die ($msg) {
71 fwrite (STDERR, $msg."\n");
75 ##function ptr_strip ($ctype) {
76 # # boost::shared_ptr<std::list<boost::shared_ptr<ARDOUR::Route>> > >
77 # # -> std::list<ARDOUR::Route>
78 # $ctype = preg_replace ('/boost::shared_ptr<([^>]*)[ ]*>/', '$1', $ctype);
79 # return preg_replace ('/boost::shared_ptr<([^>]*)[ ]*>/', '$1', $ctype);
82 function arg2lua ($argtype, $flags = 0) {
86 # LuaBridge abstracts C++ references
87 $flags |= preg_match ('/&$/', $argtype);
88 $arg = preg_replace ('/&$/', '', $argtype);
89 $arg = preg_replace ('/ $/', '', $arg);
91 # filter out basic types
92 $builtin = array ('float', 'double', 'bool', 'std::string', 'int', 'long', 'unsigned long', 'unsigned int', 'unsigned char', 'char', 'void', 'char*', 'unsigned char*', 'void*');
93 if (in_array ($arg, $builtin)) {
94 return array ($arg => $flags);
97 # check Class declarations first
98 foreach (array_merge ($classes, $consts) as $b) {
99 if ($b['ldec'] == $arg) {
100 return array ($b['lua'] => $flags);
104 # strip class pointers -- TODO Check C'tor for given class
105 $arg = preg_replace ('/[&*]*$/', '', $argtype);
106 foreach (array_merge ($classes, $consts) as $b) {
107 if ($b['ldec'] == $arg) {
108 return array ($b['lua'] => $flags);
112 return array ($argtype => ($flags | 4));
114 return array ('--MISSING (' . $argtype . ')--' => ($flags | 4));
118 function stripclass ($classname, $name) {
120 if (strpos ($name, $classname) !== 0) {
121 my_die ('invalid class prefix: ' .$classname. ' -- '. $name);
123 return substr ($name, strlen ($classname));
126 function datatype ($decl) {
127 # TODO handle spaces in type. Works because
128 # we don't yet have templated types (with_space <here >)
129 return substr ($decl, 0, strrpos ($decl, ' '));
132 function luafn2class ($lua) {
133 return substr ($lua, 0, strrpos ($lua, ':'));
136 function luafn2name ($lua) {
137 $fn = strrpos ($lua, ':');
138 if ($fn !== 0 && strlen($lua) > $fn + 1) {
139 return substr ($lua, $fn + 1);
141 my_die ('invalid class prefix: '. $name);
145 function checkclass ($b) {
147 if (!isset ($classlist[luafn2class ($b['lua'])])) {
148 my_die ('MISSING CLASS FOR '. print_r ($b['lua'], true));
152 # parse functions argument list to lua-names
153 function decl2args ($decl) {
154 $start = strrpos ($decl, '(');
155 $end = strrpos ($decl, ')');
156 $args = substr ($decl, $start + 1, $end - $start - 1);
157 $arglist = preg_split ('/, */', $args);
159 foreach ($arglist as $a) {
160 if (empty ($a)) { continue; }
161 $rv[] = arg2lua ($a);
166 function canonical_ctor ($b) {
168 if (preg_match('/[^(]*\(([^)*]*)\*\)(\(.*\))/', $b['decl'], $matches)) {
169 $lc = luafn2class ($b['lua']);
170 $cn = str_replace (':', '::', $lc);
171 $fn = substr ($lc, 1 + strrpos ($lc, ':'));
172 $rv = $cn . '::'. $fn . $matches[2];
177 function canonical_decl ($b) {
180 # match clang's declatation format
181 if (preg_match('/[^(]*\(([^)*]*)\*\)\((.*)\)/', $b['decl'], $matches)) {
182 if (strpos ($b['type'], 'Free Function') !== false) {
183 $pfx = str_replace (':', '::', luafn2class ($b['lua'])) . '::';
185 $fn = substr ($b['lua'], 1 + strrpos ($b['lua'], ':'));
186 $rv = $matches[1] . $fn . '(';
187 $arglist = preg_split ('/, */', $matches[2]);
189 foreach ($arglist as $a) {
190 if (!$first) { $rv .= ', '; }; $first = false;
191 if (empty ($a)) { continue; }
192 $a = preg_replace ('/([^>]) >/', '$1>', $a);
193 $a = preg_replace ('/^Cairo::/', '', $a); // special case cairo enums
194 $a = preg_replace ('/([^ ])&/', '$1 &', $a);
195 $a = str_replace ('vector', 'std::vector', $a);
196 $a = str_replace ('std::string', 'string', $a);
197 $a = str_replace ('string const', 'const string', $a);
198 $a = str_replace ('string', 'std::string', $a);
206 ################################################################################
207 # step 1: build class indices
209 foreach ($doc as $b) {
210 if (strpos ($b['type'], "[C] ") === 0) {
212 $classlist[$b['lua']] = $b;
213 if (strpos ($b['type'], 'Pointer Class') === false) {
214 $classdecl[$b['ldec']] = $b;
219 foreach ($classes as $c) {
220 if (strpos ($c['type'], 'Pointer Class') !== false) { continue; }
221 if (isset ($c['parent'])) {
222 if (isset ($classdecl[$c['parent']])) {
223 $classlist[$c['lua']]['luaparent'][] = $classdecl[$c['parent']]['lua'];
225 my_die ('unknown parent class: ' . print_r ($c, true));
230 # step 2: extract constants/enum
231 foreach ($doc as $b) {
232 switch ($b['type']) {
233 case "Constant/Enum":
234 case "Constant/Enum Member":
235 if (strpos ($b['ldec'], '::') === false) {
236 # for extern c enums, use the Lua Namespace
237 $b['ldec'] = str_replace (':', '::', luafn2class ($b['lua']));
239 $ns = str_replace ('::', ':', $b['ldec']);
240 $constlist[$ns][] = $b;
250 # step 3: process functions
251 foreach ($doc as $b) {
252 switch ($b['type']) {
254 case "Weak/Shared Pointer Constructor":
256 $classlist[luafn2class ($b['lua'])]['ctor'][] = array (
257 'name' => luafn2class ($b['lua']),
258 'args' => decl2args ($b['ldec']),
259 'cand' => canonical_ctor ($b)
264 $classlist[luafn2class ($b['lua'])]['data'][] = array (
266 'ret' => arg2lua (datatype ($b['ldec']))
269 case "Static C Function":
271 if (strpos ($b['lua'], 'ARDOUR:DataType:') === 0) {
272 # special case ARDOUR:DataType convenience c'tor
274 $ret = array (luafn2class ($b['lua']) => 0);
275 $canon = 'ARDOUR::LuaAPI::datatype_ctor_'.strtolower (luafn2name ($b['lua'])).'(lua_State*)';
277 my_die ('unhandled Static C: ' . print_r($b, true));
279 $classlist[luafn2class ($b['lua'])]['func'][] = array (
290 # we required C functions to be in a class namespace
291 case "Ext C Function":
293 $args = array (array ('--lua--' => 0));
294 $ret = array ('...' => 0);
295 $ns = luafn2class ($b['lua']);
296 $cls = $classlist[$ns];
297 if (preg_match ('/.*<([^>]*)[ ]*>/', $cls['ldec'], $templ)) {
298 # std::vector, std::list types
299 switch (stripclass($ns, $b['lua'])) {
301 #$args = array (array ('LuaTable {'.$templ[1].'}' => 0));
302 $args = array (arg2lua ($templ[1], 2));
303 $ret = array ('LuaTable' => 0);
307 $ret = array ('LuaIter' => 0);
311 $ret = array ('LuaTable' => 0);
316 } else if (strpos ($cls['type'], ' Array') !== false) {
317 # catches C:FloatArray, C:IntArray
318 $templ = preg_replace ('/[&*]*$/', '', $cls['ldec']);
319 switch (stripclass($ns, $b['lua'])) {
322 $ret = array ('LuaMetaTable' => 0);
326 $ret = array ('LuaTable' => 0);
329 $args = array (array ('LuaTable {'.$templ.'}' => 0));
330 $ret = array ('void' => 0);
336 $classlist[luafn2class ($b['lua'])]['func'][] = array (
343 'cand' => canonical_decl ($b)
346 case "Free C Function":
347 $funclist[luafn2class ($b['lua'])][] = array (
354 'cand' => str_replace (':', '::', $b['lua']).'(lua_State*)'
357 case "Free Function":
358 case "Free Function RefReturn":
359 $funclist[luafn2class ($b['lua'])][] = array (
362 'args' => decl2args ($b['ldec']),
363 'ret' => arg2lua ($b['ret']),
364 'ref' => (strpos ($b['type'], "RefReturn") !== false),
365 'cand' => canonical_decl ($b)
368 case "Member Function":
369 case "Member Function RefReturn":
370 case "Member Pointer Function":
371 case "Weak/Shared Pointer Function":
372 case "Weak/Shared Pointer Function RefReturn":
373 case "Weak/Shared Null Check":
374 case "Weak/Shared Pointer Cast":
375 case "Static Member Function":
377 $classlist[luafn2class ($b['lua'])]['func'][] = array (
380 'args' => decl2args ($b['ldec']),
381 'ret' => arg2lua ($b['ret']),
382 'ref' => (strpos ($b['type'], "RefReturn") !== false),
383 'cand' => canonical_decl ($b)
386 case "Constant/Enum":
387 case "Constant/Enum Member":
388 # already handled -> $consts
391 if (strpos ($b['type'], "[C] ") !== 0) {
392 my_die ('unhandled type: ' . $b['type']);
399 # step 4: collect/group/sort
401 # step 4a: unify weak/shared Ptr classes
402 foreach ($classlist as $ns => $cl) {
403 if (strpos ($cl['type'], ' Array') !== false) {
404 $classlist[$ns]['arr'] = true;
407 foreach ($classes as $c) {
408 if ($c['lua'] == $ns) {
409 if (strpos ($c['type'], 'Pointer Class') !== false) {
410 $classlist[$ns]['ptr'] = true;
411 $classlist[$ns]['decl'] = 'boost::shared_ptr< '.$c['decl']. ' >, boost::weak_ptr< '.$c['decl']. ' >';
418 # step4b: sanity check
419 foreach ($classlist as $ns => $cl) {
420 if (isset ($classes[$ns]['parent']) && !isset ($classlist[$ns]['luaparent'])) {
421 my_die ('missing parent class: ' . print_r ($cl, true));
425 # step 4c: merge free functions into classlist
426 foreach ($funclist as $ns => $fl) {
427 if (isset ($classlist[$ns])) {
428 my_die ('Free Funcion in existing namespace: '.$ns.' '. print_r ($ns, true));
430 $classlist[$ns]['func'] = $fl;
431 $classlist[$ns]['free'] = true;
434 # step 4d: order to chaos
435 # no array_multisort() here, sub-types are sorted after merging parents
439 ################################################################################
440 ################################################################################
441 ################################################################################
444 #### -- split here -- ####
446 # from here on, only $classlist and $constlist arrays are relevant.
447 # we also pull in C++ header annotation from doxygen to $api
450 # read documentation from doxygen
451 $json = gzdecode (file_get_contents (dirname (__FILE__).'/../doc/ardourapi.json.gz'));
453 foreach (json_decode ($json, true) as $a) {
454 if (!isset ($a['decl'])) { continue; }
455 if (empty ($a['decl'])) { continue; }
456 $canon = str_replace (' *', '*', $a['decl']);
460 # keep track of found/missing doc
464 # retrive a value from $api
465 function doxydoc ($canonical_declaration) {
469 if (isset ($api[$canonical_declaration])) {
471 return $api[$canonical_declaration]['doc'];
478 ################################################################################
480 ################################################################################
483 ################################################################################
487 # constructors, enums (constants) use a dot. (e.g. "LuaOSC.Address" -> "LuaOSC.Address" )
488 function ctorname ($name) {
489 return htmlentities (str_replace (':', '.', $name));
492 # strip class prefix (e.g "Evoral:MidiEvent:channel" -> "channel")
493 function shortname ($name) {
494 return htmlentities (substr ($name, strrpos ($name, ':') + 1));
497 # retrieve variable name from array["VARNAME"] => FLAGS
498 function varname ($a) {
499 return array_keys ($a)[0];
502 # recusively collect class parents (derived classes)
503 function traverse_parent ($ns, &$inherited) {
506 if (isset ($classlist[$ns]['luaparent'])) {
507 $parents = array_unique ($classlist[$ns]['luaparent']);
509 foreach ($parents as $p) {
510 if (!empty ($rv)) { $rv .= ', '; }
511 $rv .= typelink ($p);
512 $inherited[$p] = $classlist[$p];
513 traverse_parent ($p, $inherited);
519 # create a cross-reference to a type (class or enum)
520 # *all* <a> links are generated here, currently anchors on a single page.
521 function typelink ($a, $short = false, $argcls = '', $linkcls = '', $suffix = '') {
524 if (isset($classlist[$a]['free'])) {
525 return '<a class="'.$linkcls.'" href="#'.htmlentities ($a).'">'.($short ? shortname($a) : ctorname($a)).$suffix.'</a>';
526 } else if (in_array ($a, array_keys ($classlist))) {
527 return '<a class="'.$linkcls.'" href="#'.htmlentities($a).'">'.($short ? shortname($a) : htmlentities($a)).$suffix.'</a>';
528 } else if (in_array ($a, array_keys ($constlist))) {
529 return '<a class="'.$linkcls.'" href="#'.ctorname ($a).'">'.($short ? shortname($a) : ctorname($a)).$suffix.'</a>';
531 return '<span class="'.$argcls.'">'.htmlentities($a).$suffix.'</span>';
535 # output format function arguments
536 function format_args ($args) {
537 $rv = '<span class="functionargs"> (';
539 foreach ($args as $a) {
540 if (!$first) { $rv .= ', '; }; $first = false;
541 $flags = $a[varname ($a)];
543 $rv .= '<em>LuaTable</em> {'.typelink (varname ($a), true, 'em').'}';
545 elseif ($flags & 1) {
546 $rv .= typelink (varname ($a), true, 'em', '', '&');
549 $rv .= typelink (varname ($a), true, 'em');
556 # format doxygen documentation for class-definition
557 function format_doxyclass ($cl) {
559 if (isset ($cl['decl'])) {
560 $doc = doxydoc ($cl['decl']);
562 $rv.= '<div class="classdox">'.$doc.'</div>'.NL;
568 # format doxygen documentation for class-members
569 function format_doxydoc ($f) {
571 if (isset ($f['cand'])) {
572 $doc = doxydoc ($f['cand']);
574 $rv.= '<tr><td></td><td class="doc" colspan="2"><div class="dox">'.$doc;
575 $rv.= '</div></td></tr>'.NL;
576 } else if (0) { # debug
577 $rv.= '<tr><td></td><td class="doc" colspan="2"><p>'.htmlentities($f['cand']).'</p>';
578 $rv.= '</td></tr>'.NL;
584 # usort() callback for class-members
585 function name_sort_cb ($a, $b) {
586 return strcmp ($a['name'], $b['name']);
589 # main output function for every class
590 function format_class_members ($ns, $cl, &$dups) {
592 # print contructor - if any
593 if (isset ($cl['ctor'])) {
594 usort ($cl['ctor'], 'name_sort_cb');
595 $rv.= ' <tr><th colspan="3">Constructor</th></tr>'.NL;
596 foreach ($cl['ctor'] as $f) {
597 $rv.= ' <tr><td class="def">ℂ</td><td class="decl">';
598 $rv.= '<span class="functionname">'.ctorname ($f['name']).'</span>';
599 $rv.= format_args ($f['args']);
600 $rv.= '</td><td class="fill"></td></tr>'.NL;
601 # doxygen documentation (may be empty)
602 $rv.= format_doxydoc($f);
606 # strip duplicates (inherited or derived methods)
607 # e.g AudioTrack -> Track -> Route -> SessionObject -> Stateful
608 # all 5 have "isnil()"
610 if (isset ($cl['func'])) {
611 foreach ($cl['func'] as $f) {
612 if (in_array (stripclass ($ns, $f['name']), $dups)) { continue; }
617 # print methods - if any
618 if (count ($nondups) > 0) {
619 usort ($nondups, 'name_sort_cb');
620 $rv.= ' <tr><th colspan="3">Methods</th></tr>'.NL;
621 foreach ($nondups as $f) {
622 $dups[] = stripclass ($ns, $f['name']);
624 $rv.= ' <tr><td class="def">';
625 if ($f['ref'] && isset ($f['ext'])) {
626 # external C functions
627 $rv.= '<em>'.varname ($f['ret']).'</em>';
628 } elseif ($f['ref'] && varname ($f['ret']) == 'void') {
629 # void functions with reference args
630 $rv.= '<em>LuaTable</em>(...)';
631 } elseif ($f['ref']) {
632 # functions with reference args and return value
633 $rv.= '<em>LuaTable</em>('.typelink (varname ($f['ret']), true, 'em').', ...)';
635 # normal class members
636 $rv.= typelink (varname ($f['ret']), true, 'em');
638 # function declaration and arguments
639 $rv.= '</td><td class="decl">';
640 $rv.= '<span class="functionname"><abbr title="'.htmlentities($f['bind']['decl']).'">'.stripclass ($ns, $f['name']).'</abbr></span>';
641 $rv.= format_args ($f['args']);
642 $rv.= '</td><td class="fill"></td></tr>'.NL;
643 # doxygen documentation (may be empty)
644 $rv.= format_doxydoc($f);
647 # print data members - if any
648 if (isset ($cl['data'])) {
649 usort ($cl['data'], 'name_sort_cb');
650 $rv.= ' <tr><th colspan="3">Data Members</th></tr>'.NL;
651 foreach ($cl['data'] as $f) {
652 $rv.= ' <tr><td class="def">'.typelink (array_keys ($f['ret'])[0], false, 'em').'</td><td class="decl">';
653 $rv.= '<span class="functionname">'.stripclass ($ns, $f['name']).'</span>';
654 $rv.= '</td><td class="fill"></td></tr>'.NL;
661 ################################################################################
667 <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
669 <title>Ardour Lua Bindings</title>
670 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
671 <style type="text/css">
672 div.header { text-align:center; }
673 div.header h2 { margin:0; }
674 div.header p { margin:.25em; text-align:center; }
675 div.luafooter { text-align:center; font-size:80%; color: #888; margin: 2em 0; }
676 #luaref { max-width:60em; margin: 1em auto; }
678 #luaref h2 { margin:2em 0 0 0; padding:0em; border-bottom: 1px solid black; }
679 #luaref h3.cls { margin:2em 0 0 0; padding: 0 0 0 1em; border: 1px dashed #6666ee; }
680 #luaref h3.cls abbr { text-decoration:none; cursor:default; }
681 #luaref h4.cls { margin:1em 0 0 0; }
682 #luaref h3.class { background-color: #aaee66; }
683 #luaref h3.enum { background-color: #aaaaaa; }
684 #luaref h3.pointerclass { background-color: #eeaa66; }
685 #luaref h3.array { background-color: #66aaee; }
686 #luaref h3.opaque { background-color: #6666aa; }
687 #luaref p { text-align: justify; }
688 #luaref p.cdecl { text-align: right; float:right; font-size:90%; margin:0; padding: 0 0 0 1em; }
689 #luaref ul.classindex { columns: 2; -webkit-columns: 2; -moz-columns: 2; }
690 #luaref div.clear { clear:both; }
691 #luaref p.classinfo { margin: .25em 0; }
692 #luaref div.code { width:80%; margin:.5em auto; }
693 #luaref div.code div { width:45%; }
694 #luaref div.code pre { line-height: 1.2em; margin: .25em 0; }
695 #luaref div.code samp { color: green; font-weight: bold; background-color: #eee; }
696 #luaref div.classdox { padding: .1em 1em; }
697 #luaref div.classdox p { margin: .5em 0 .5em .6em; }
698 #luaref div.classdox p { margin: .5em 0 .5em .6em; }
699 #luaref div.classdox { padding: .1em 1em; }
700 #luaref div.classdox p { margin: .5em 0 .5em .6em; }
701 #luaref table.classmembers { width: 100%; }
702 #luaref table.classmembers th { text-align:left; border-bottom:1px solid black; padding-top:1em; }
703 #luaref table.classmembers td.def { text-align:right; padding-right:.5em; white-space: nowrap; }
704 #luaref table.classmembers td.decl { text-align:left; padding-left:.5em; white-space: nowrap; }
705 #luaref table.classmembers td.doc { text-align:left; padding-left:.6em; line-height: 1.2em; font-size:80%; }
706 #luaref table.classmembers td.doc div.dox {background-color:#eee; padding: .1em 1em; }
707 #luaref table.classmembers td.doc p { margin: .5em 0; }
708 #luaref table.classmembers td.doc p.para-brief { font-size:120%; }
709 #luaref table.classmembers td.doc p.para-returns { font-size:120%; }
710 #luaref table.classmembers td.doc dl { font-size:120%; line-height: 1.3em; }
711 #luaref table.classmembers td.doc dt { font-style: italic; }
712 #luaref table.classmembers td.fill { width: 99%; }
713 #luaref table.classmembers span.em { font-style: italic; }
714 #luaref span.functionname abbr { text-decoration:none; cursor:default; }
719 <h2>Ardour Lua Bindings</h2>
721 <a href="#h_classes">Class Documentation</a>
723 <a href="#h_enum">Enum/Constants</a>
725 <a href="#h_index">Index</a>
729 <!-- #### SNIP #### !-->
739 title: Class Reference
743 This documention is far from complete may be inaccurate and subject to change.
754 ################################################################################
755 # some general documentation -- should really go elsehere
759 <h2 id="h_intro">Overview</h2>
761 The top-level entry point are <?=typelink('ARDOUR:Session')?> and <?=typelink('ArdourUI:Editor')?>.
762 Most other Classes are used indirectly starting with a Session function. e.g. Session:get_routes().
765 A few classes are dedicated to certain script types, e.g. Lua DSP processors have exclusive access to
766 <?=typelink('ARDOUR:DSP')?> and <?=typelink('ARDOUR:ChanMapping')?>. Action Hooks Scripts to
767 <?=typelink('LuaSignal:Set')?> etc.
770 Detailed documentation (parameter names, method description) is not yet available. Please stay tuned.
772 <h3>Short introduction to Ardour classes</h3>
774 Ardour's structure is object oriented. The main object is the Session. A Session contains Audio Tracks, Midi Tracks and Busses.
775 Audio and Midi tracks are derived from a more general "Track" Object, which in turn is derived from a "Route" (aka Bus).
776 (We say "An Audio Track <em>is-a</em> Track <em>is-a</em> Route").
777 Tracks contain specifics. For Example a track <em>has-a</em> diskstream (for file i/o).
780 Operations are performed on objects. One gets a reference to an object and then calls a method.
781 e.g <code>obj = Session:route_by_name("Audio") obj:set_name("Guitar")</code>.
784 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:
785 you cannot simply remove a track that is currently processing audio. There are various <em>factory</em> methods for object creation or removal.
787 <h3>Pass by Reference</h3>
789 Since lua functions are closures, C++ methods that pass arguments by reference cannot be used as-is.
790 All parameters passed to a C++ method which uses references are returned as Lua Table.
791 If the C++ method also returns a value it is prefixed. Two parameters are returned: the value and a Lua Table holding the parameters.
795 <div style="float:left;">C++
797 <pre><code class="cxx">void set_ref (int& var, long& val)
799 printf ("%d %ld\n", var, val);
806 <div style="float:right;">Lua
808 <pre><code class="lua">local var = 0;
809 ref = set_ref (var, 2);
810 -- output from C++ printf()
811 </code><samp class="lua">0 2</samp><code>
812 -- var is still 0 here
813 print (ref[1], ref[2])
814 </code><samp class="lua">5 7</samp></pre>
818 <div class="clear"></div>
820 <div style="float:left;">
822 <pre><code class="cxx">int set_ref2 (int &var, std::string unused)
830 <div style="float:right;">
831 <pre><code class="lua">rv, ref = set_ref2 (0, "hello");
832 print (rv, ref[1], ref[2])
833 </code><samp class="lua">3 5 hello</samp></pre>
836 <div class="clear"></div>
838 <h3>Pointer Classes</h3>
840 Libardour makes extensive use of reference counted <code>boost::shared_ptr</code> to manage lifetimes.
841 The Lua bindings provide a complete abstration of this. There are no pointers in lua.
842 For example a <?=typelink('ARDOUR:Route')?> is a pointer in C++, but lua functions operate on it like it was a class instance.
845 <code>shared_ptr</code> are reference counted. Once assigned to a lua variable, the C++ object will be kept and remains valid.
846 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.
849 All pointer classes have a <code>isnil ()</code> method. This is for two cases:
850 Construction may fail. e.g. <code><?=typelink('ARDOUR:LuaAPI')?>.newplugin()</code>
851 may not be able to find the given plugin and hence cannot create an object.
854 The second case if for <code>boost::weak_ptr</code>. As opposed to <code>boost::shared_ptr</code> weak-pointers are not reference counted.
855 The object may vanish at any time.
856 If lua code calls a method on a nil object, the interpreter will raise an exception and the script will not continue.
857 This is not unlike <code>a = nil a:test()</code> which results in en error "<em>attempt to index a nil value</em>".
860 From the lua side of things there is no distinction between weak and shared pointers. They behave identically.
861 Below they're inidicated in orange and have an arrow to indicate the pointer type.
862 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.
868 #################################
869 # Main output function -- Classes
871 echo '<h2 id="h_classes">Class Documentation</h2>'.NL;
872 foreach ($classlist as $ns => $cl) {
874 $tbl = format_class_members ($ns, $cl, $dups);
876 # format class title - depending on type
878 # classes with no members (no ctor, no methods, no data)
879 echo '<h3 id="'.htmlentities ($ns).'" class="cls opaque"><abbr title="Opaque Object">∅</abbr> '.htmlentities ($ns).'</h3>'.NL;
881 else if (isset ($classlist[$ns]['free'])) {
882 # free functions (no class)
883 echo '<h3 id="'.htmlentities ($ns).'" class="cls freeclass"><abbr title="Namespace">ℕ</abbr> '.ctorname($ns).'</h3>'.NL;
885 else if (isset ($classlist[$ns]['arr'])) {
887 echo '<h3 id="'.htmlentities ($ns).'" class="cls array"><abbr title="C Array">⋯</abbr> '.htmlentities ($ns).'</h3>'.NL;
889 else if (isset ($classlist[$ns]['ptr'])) {
891 echo '<h3 id="'.htmlentities ($ns).'" class="cls pointerclass"><abbr title="Pointer Class">↠</abbr> '. htmlentities ($ns).'</h3>'.NL;
895 echo '<h3 id="'.htmlentities ($ns).'" class="cls class"><abbr title="Class">∁</abbr> '.htmlentities ($ns).'</h3>'.NL;
898 # show original C++ declaration
899 if (isset ($cl['decl'])) {
900 echo '<p class="cdecl"><em>C‡</em>: '.htmlentities ($cl['decl']).'</p>'.NL;
903 # print class inheritance (direct parent *name* only)
904 $inherited = array ();
905 $isa = traverse_parent ($ns, $inherited);
907 echo ' <p class="classinfo">is-a: '.$isa.'</p>'.NL;
909 echo '<div class="clear"></div>'.NL;
912 # class documentation (if any)
913 echo format_doxyclass ($cl);
915 # member documentation
917 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;
919 echo '<table class="classmembers">'.NL;
924 # traverse parent classes (all inherited members)
925 foreach ($inherited as $pns => $pcl) {
926 $tbl = format_class_members ($pns, $pcl, $dups);
928 echo '<h4 class="cls">Inherited from '.$pns.'</h4>'.NL;
929 echo '<table class="classmembers">'.NL;
939 echo '<h2 id="h_enum">Enum/Constants</h2>'.NL;
940 foreach ($constlist as $ns => $cs) {
941 echo '<h3 id="'.ctorname ($ns).'" class="cls enum"><abbr title="Enum">∈</abbr> '.ctorname ($ns).'</h3>'.NL;
942 echo '<ul class="enum">'.NL;
943 foreach ($cs as $c) {
944 echo '<li class="const">'.ctorname ($c['lua']).'</li>'.NL;
949 ######################
950 # Index of all classes
952 echo '<h2 id="h_index" >Class Index</h2>'.NL;
953 echo '<ul class="classindex">'.NL;
954 foreach ($classlist as $ns => $cl) {
955 echo '<li>'.typelink($ns).'</li>'.NL;
960 # see how far there is still to go...
961 fwrite (STDERR, "Found $dox_found annotations. missing: $dox_miss\n");
962 echo '<!-- '.$dox_found.' / '.$dox_miss.' !-->'.NL;
966 <div class="luafooter">Ardour <?=$ardourversion?> - <?=date('r')?></div>
970 echo '<!-- #### SNIP #### !-->'.NL;