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 luafn2name ($lua) {
129 $fn = strrpos ($lua, ':');
130 if ($fn !== 0 && strlen($lua) > $fn + 1) {
131 return substr ($lua, $fn + 1);
133 my_die ('invalid class prefix: '. $name);
137 function checkclass ($b) {
139 if (!isset ($classlist[luafn2class ($b['lua'])])) {
140 my_die ('MISSING CLASS FOR '. print_r ($b['lua'], true));
144 # parse functions argument list to lua-names
145 function decl2args ($decl) {
146 $start = strrpos ($decl, '(');
147 $end = strrpos ($decl, ')');
148 $args = substr ($decl, $start + 1, $end - $start - 1);
149 $arglist = preg_split ('/, */', $args);
151 foreach ($arglist as $a) {
152 if (empty ($a)) { continue; }
153 $rv[] = arg2lua ($a);
158 function canonical_ctor ($b) {
160 if (preg_match('/[^(]*\(([^)*]*)\*\)(\(.*\))/', $b['decl'], $matches)) {
161 $lc = luafn2class ($b['lua']);
162 $cn = str_replace (':', '::', $lc);
163 $fn = substr ($lc, 1 + strrpos ($lc, ':'));
164 $rv = $cn . '::'. $fn . $matches[2];
169 function canonical_decl ($b) {
172 # match clang's declatation format
173 if (preg_match('/[^(]*\(([^)*]*)\*\)\((.*)\)/', $b['decl'], $matches)) {
174 if (strpos ($b['type'], 'Free Function') !== false) {
175 $pfx = str_replace (':', '::', luafn2class ($b['lua'])) . '::';
177 $fn = substr ($b['lua'], 1 + strrpos ($b['lua'], ':'));
178 $rv = $matches[1] . $fn . '(';
179 $arglist = preg_split ('/, */', $matches[2]);
181 foreach ($arglist as $a) {
182 if (!$first) { $rv .= ', '; }; $first = false;
183 if (empty ($a)) { continue; }
184 $a = preg_replace ('/([^>]) >/', '$1>', $a);
185 $a = preg_replace ('/^Cairo::/', '', $a); // special case cairo enums
186 $a = preg_replace ('/([^ ])&/', '$1 &', $a);
187 $a = str_replace ('vector', 'std::vector', $a);
188 $a = str_replace ('std::string', 'string', $a);
189 $a = str_replace ('string const', 'const string', $a);
190 $a = str_replace ('string', 'std::string', $a);
198 ################################################################################
199 # step 1: build class indices
201 foreach ($doc as $b) {
202 if (strpos ($b['type'], "[C] ") === 0) {
204 $classlist[$b['lua']] = $b;
205 if (strpos ($b['type'], 'Pointer Class') === false) {
206 $classdecl[$b['ldec']] = $b;
211 foreach ($classes as $c) {
212 if (strpos ($c['type'], 'Pointer Class') !== false) { continue; }
213 if (isset ($c['parent'])) {
214 if (isset ($classdecl[$c['parent']])) {
215 $classlist[$c['lua']]['luaparent'][] = $classdecl[$c['parent']]['lua'];
217 my_die ('unknown parent class: ' . print_r ($c, true));
222 # step 2: extract constants/enum
223 foreach ($doc as $b) {
224 switch ($b['type']) {
225 case "Constant/Enum":
226 case "Constant/Enum Member":
227 if (strpos ($b['ldec'], '::') === false) {
228 # for extern c enums, use the Lua Namespace
229 $b['ldec'] = str_replace (':', '::', luafn2class ($b['lua']));
231 $ns = str_replace ('::', ':', $b['ldec']);
232 $constlist[$ns][] = $b;
242 # step 3: process functions
243 foreach ($doc as $b) {
244 switch ($b['type']) {
246 case "Weak/Shared Pointer Constructor":
248 $classlist[luafn2class ($b['lua'])]['ctor'][] = array (
249 'name' => luafn2class ($b['lua']),
250 'args' => decl2args ($b['ldec']),
251 'cand' => canonical_ctor ($b)
256 $classlist[luafn2class ($b['lua'])]['data'][] = array (
258 'ret' => arg2lua (datatype ($b['ldec']))
261 case "Static C Function":
263 if (strpos ($b['lua'], 'ARDOUR:DataType:') === 0) {
264 # special case ARDOUR:DataType convenience c'tor
266 $ret = array (luafn2class ($b['lua']) => 0);
267 $canon = 'ARDOUR::LuaAPI::datatype_ctor_'.strtolower (luafn2name ($b['lua'])).'(lua_State*)';
269 my_die ('unhandled Static C: ' . print_r($b, true));
271 $classlist[luafn2class ($b['lua'])]['func'][] = array (
282 # we required C functions to be in a class namespace
283 case "Ext C Function":
285 $args = array (array ('--lua--' => 0));
286 $ret = array ('...' => 0);
287 $ns = luafn2class ($b['lua']);
288 $cls = $classlist[$ns];
289 if (preg_match ('/.*<([^>]*)[ ]*>/', $cls['ldec'], $templ)) {
290 # std::vector, std::list types
291 switch (stripclass($ns, $b['lua'])) {
293 #$args = array (array ('LuaTable {'.$templ[1].'}' => 0));
294 $args = array (arg2lua ($templ[1], 2));
295 $ret = array ('LuaTable' => 0);
299 $ret = array ('LuaIter' => 0);
303 $ret = array ('LuaTable' => 0);
308 } else if (strpos ($cls['type'], ' Array') !== false) {
309 # catches C:FloatArray, C:IntArray
310 $templ = preg_replace ('/[&*]*$/', '', $cls['ldec']);
311 switch (stripclass($ns, $b['lua'])) {
314 $ret = array ('LuaMetaTable' => 0);
318 $ret = array ('LuaTable' => 0);
321 $args = array (array ('LuaTable {'.$templ.'}' => 0));
322 $ret = array ('void' => 0);
328 $classlist[luafn2class ($b['lua'])]['func'][] = array (
335 'cand' => canonical_decl ($b)
338 case "Free Function":
339 case "Free Function RefReturn":
340 $funclist[luafn2class ($b['lua'])][] = array (
343 'args' => decl2args ($b['ldec']),
344 'ret' => arg2lua ($b['ret']),
345 'ref' => (strpos ($b['type'], "RefReturn") !== false),
346 'cand' => canonical_decl ($b)
349 case "Member Function":
350 case "Member Function RefReturn":
351 case "Member Pointer Function":
352 case "Weak/Shared Pointer Function":
353 case "Weak/Shared Pointer Function RefReturn":
354 case "Weak/Shared Null Check":
355 case "Weak/Shared Pointer Cast":
356 case "Static Member Function":
358 $classlist[luafn2class ($b['lua'])]['func'][] = array (
361 'args' => decl2args ($b['ldec']),
362 'ret' => arg2lua ($b['ret']),
363 'ref' => (strpos ($b['type'], "RefReturn") !== false),
364 'cand' => canonical_decl ($b)
367 case "Constant/Enum":
368 case "Constant/Enum Member":
369 # already handled -> $consts
372 if (strpos ($b['type'], "[C] ") !== 0) {
373 my_die ('unhandled type: ' . $b['type']);
380 # step 4: collect/group/sort
382 # step 4a: unify weak/shared Ptr classes
383 foreach ($classlist as $ns => $cl) {
384 if (strpos ($cl['type'], ' Array') !== false) {
385 $classlist[$ns]['arr'] = true;
388 foreach ($classes as $c) {
389 if ($c['lua'] == $ns) {
390 if (strpos ($c['type'], 'Pointer Class') !== false) {
391 $classlist[$ns]['ptr'] = true;
392 $classlist[$ns]['decl'] = 'boost::shared_ptr< '.$c['decl']. ' >, boost::weak_ptr< '.$c['decl']. ' >';
399 # step4b: sanity check
400 foreach ($classlist as $ns => $cl) {
401 if (isset ($classes[$ns]['parent']) && !isset ($classlist[$ns]['luaparent'])) {
402 my_die ('missing parent class: ' . print_r ($cl, true));
406 # step 4c: merge free functions into classlist
407 foreach ($funclist as $ns => $fl) {
408 if (isset ($classlist[$ns])) {
409 my_die ('Free Funcion in existing namespace: '.$ns.' '. print_r ($ns, true));
411 $classlist[$ns]['func'] = $fl;
412 $classlist[$ns]['free'] = true;
415 # step 4d: order to chaos
416 # no array_multisort() here, sub-types are sorted after merging parents
420 ################################################################################
421 ################################################################################
422 ################################################################################
425 #### -- split here -- ####
427 # from here on, only $classlist and $constlist arrays are relevant.
428 # we also pull in C++ header annotation from doxygen to $api
431 # read documentation from doxygen
432 $json = gzdecode (file_get_contents (dirname (__FILE__).'/../doc/ardourapi.json.gz'));
434 foreach (json_decode ($json, true) as $a) {
435 if (!isset ($a['decl'])) { continue; }
436 if (empty ($a['decl'])) { continue; }
437 $canon = str_replace (' *', '*', $a['decl']);
441 # keep track of found/missing doc
445 # retrive a value from $api
446 function doxydoc ($canonical_declaration) {
450 if (isset ($api[$canonical_declaration])) {
452 return $api[$canonical_declaration]['doc'];
459 ################################################################################
461 ################################################################################
464 ################################################################################
468 # constructors, enums (constants) use a dot. (e.g. "LuaOSC.Address" -> "LuaOSC.Address" )
469 function ctorname ($name) {
470 return htmlentities (str_replace (':', '.', $name));
473 # strip class prefix (e.g "Evoral:MidiEvent:channel" -> "channel")
474 function shortname ($name) {
475 return htmlentities (substr ($name, strrpos ($name, ':') + 1));
478 # retrieve variable name from array["VARNAME"] => FLAGS
479 function varname ($a) {
480 return array_keys ($a)[0];
483 # recusively collect class parents (derived classes)
484 function traverse_parent ($ns, &$inherited) {
487 if (isset ($classlist[$ns]['luaparent'])) {
488 $parents = array_unique ($classlist[$ns]['luaparent']);
490 foreach ($parents as $p) {
491 if (!empty ($rv)) { $rv .= ', '; }
492 $rv .= typelink ($p);
493 $inherited[$p] = $classlist[$p];
494 traverse_parent ($p, $inherited);
500 # create a cross-reference to a type (class or enum)
501 # *all* <a> links are generated here, currently anchors on a single page.
502 function typelink ($a, $short = false, $argcls = '', $linkcls = '', $suffix = '') {
505 if (isset($classlist[$a]['free'])) {
506 return '<a class="'.$linkcls.'" href="#'.htmlentities ($a).'">'.($short ? shortname($a) : ctorname($a)).$suffix.'</a>';
507 } else if (in_array ($a, array_keys ($classlist))) {
508 return '<a class="'.$linkcls.'" href="#'.htmlentities($a).'">'.($short ? shortname($a) : htmlentities($a)).$suffix.'</a>';
509 } else if (in_array ($a, array_keys ($constlist))) {
510 return '<a class="'.$linkcls.'" href="#'.ctorname ($a).'">'.($short ? shortname($a) : ctorname($a)).$suffix.'</a>';
512 return '<span class="'.$argcls.'">'.htmlentities($a).$suffix.'</span>';
516 # output format function arguments
517 function format_args ($args) {
518 $rv = '<span class="functionargs"> (';
520 foreach ($args as $a) {
521 if (!$first) { $rv .= ', '; }; $first = false;
522 $flags = $a[varname ($a)];
524 $rv .= '<em>LuaTable</em> {'.typelink (varname ($a), true, 'em').'}';
526 elseif ($flags & 1) {
527 $rv .= typelink (varname ($a), true, 'em', '', '&');
530 $rv .= typelink (varname ($a), true, 'em');
537 # format doxygen documentation for class-definition
538 function format_doxyclass ($cl) {
540 if (isset ($cl['decl'])) {
541 $doc = doxydoc ($cl['decl']);
543 $rv.= '<div class="classdox">'.$doc.'</div>'.NL;
549 # format doxygen documentation for class-members
550 function format_doxydoc ($f) {
552 if (isset ($f['cand'])) {
553 $doc = doxydoc ($f['cand']);
555 $rv.= '<tr><td></td><td class="doc" colspan="2"><div class="dox">'.$doc;
556 $rv.= '</div></td></tr>'.NL;
557 } else if (0) { # debug
558 $rv.= '<tr><td></td><td class="doc" colspan="2"><p>'.htmlentities($f['cand']).'</p>';
559 $rv.= '</td></tr>'.NL;
565 # usort() callback for class-members
566 function name_sort_cb ($a, $b) {
567 return strcmp ($a['name'], $b['name']);
570 # main output function for every class
571 function format_class_members ($ns, $cl, &$dups) {
573 # print contructor - if any
574 if (isset ($cl['ctor'])) {
575 usort ($cl['ctor'], 'name_sort_cb');
576 $rv.= ' <tr><th colspan="3">Constructor</th></tr>'.NL;
577 foreach ($cl['ctor'] as $f) {
578 $rv.= ' <tr><td class="def">ℂ</td><td class="decl">';
579 $rv.= '<span class="functionname">'.ctorname ($f['name']).'</span>';
580 $rv.= format_args ($f['args']);
581 $rv.= '</td><td class="fill"></td></tr>'.NL;
582 # doxygen documentation (may be empty)
583 $rv.= format_doxydoc($f);
587 # strip duplicates (inherited or derived methods)
588 # e.g AudioTrack -> Track -> Route -> SessionObject -> Stateful
589 # all 5 have "isnil()"
591 if (isset ($cl['func'])) {
592 foreach ($cl['func'] as $f) {
593 if (in_array (stripclass ($ns, $f['name']), $dups)) { continue; }
598 # print methods - if any
599 if (count ($nondups) > 0) {
600 usort ($nondups, 'name_sort_cb');
601 $rv.= ' <tr><th colspan="3">Methods</th></tr>'.NL;
602 foreach ($nondups as $f) {
603 $dups[] = stripclass ($ns, $f['name']);
605 $rv.= ' <tr><td class="def">';
606 if ($f['ref'] && isset ($f['ext'])) {
607 # external C functions
608 $rv.= '<em>'.varname ($f['ret']).'</em>';
609 } elseif ($f['ref'] && varname ($f['ret']) == 'void') {
610 # void functions with reference args
611 $rv.= '<em>LuaTable</em>(...)';
612 } elseif ($f['ref']) {
613 # functions with reference args and return value
614 $rv.= '<em>LuaTable</em>('.typelink (varname ($f['ret']), true, 'em').', ...)';
616 # normal class members
617 $rv.= typelink (varname ($f['ret']), true, 'em');
619 # function declaration and arguments
620 $rv.= '</td><td class="decl">';
621 $rv.= '<span class="functionname"><abbr title="'.htmlentities($f['bind']['decl']).'">'.stripclass ($ns, $f['name']).'</abbr></span>';
622 $rv.= format_args ($f['args']);
623 $rv.= '</td><td class="fill"></td></tr>'.NL;
624 # doxygen documentation (may be empty)
625 $rv.= format_doxydoc($f);
628 # print data members - if any
629 if (isset ($cl['data'])) {
630 usort ($cl['data'], 'name_sort_cb');
631 $rv.= ' <tr><th colspan="3">Data Members</th></tr>'.NL;
632 foreach ($cl['data'] as $f) {
633 $rv.= ' <tr><td class="def">'.typelink (array_keys ($f['ret'])[0], false, 'em').'</td><td class="decl">';
634 $rv.= '<span class="functionname">'.stripclass ($ns, $f['name']).'</span>';
635 $rv.= '</td><td class="fill"></td></tr>'.NL;
642 ################################################################################
646 <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
648 <title>Ardour Lua Bindings</title>
649 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
650 <style type="text/css">
651 div.header { text-align:center; }
652 div.header h2 { margin:0; }
653 div.header p { margin:.25em; text-align:center; }
654 div.luafooter { text-align:center; font-size:80%; color: #888; margin: 2em 0; }
655 #luaref { max-width:60em; margin: 1em auto; }
657 #luaref h2 { margin:2em 0 0 0; padding:0em; border-bottom: 1px solid black; }
658 #luaref h3.cls { margin:2em 0 0 0; padding: 0 0 0 1em; border: 1px dashed #6666ee; }
659 #luaref h3.cls abbr { text-decoration:none; cursor:default; }
660 #luaref h4.cls { margin:1em 0 0 0; }
661 #luaref h3.class { background-color: #aaee66; }
662 #luaref h3.enum { background-color: #aaaaaa; }
663 #luaref h3.pointerclass { background-color: #eeaa66; }
664 #luaref h3.array { background-color: #66aaee; }
665 #luaref h3.opaque { background-color: #6666aa; }
666 #luaref p { text-align: justify; }
667 #luaref p.cdecl { text-align: right; float:right; font-size:90%; margin:0; padding: 0 0 0 1em; }
668 #luaref ul.classindex { columns: 2; -webkit-columns: 2; -moz-columns: 2; }
669 #luaref div.clear { clear:both; }
670 #luaref p.classinfo { margin: .25em 0; }
671 #luaref div.code { width:80%; margin:.5em auto; }
672 #luaref div.code div { width:45%; }
673 #luaref div.code pre { line-height: 1.2em; margin: .25em 0; }
674 #luaref div.code samp { color: green; font-weight: bold; background-color: #eee; }
675 #luaref div.classdox { padding: .1em 1em; }
676 #luaref div.classdox p { margin: .5em 0 .5em .6em; }
677 #luaref div.classdox p { margin: .5em 0 .5em .6em; }
678 #luaref div.classdox { padding: .1em 1em; }
679 #luaref div.classdox p { margin: .5em 0 .5em .6em; }
680 #luaref table.classmembers { width: 100%; }
681 #luaref table.classmembers th { text-align:left; border-bottom:1px solid black; padding-top:1em; }
682 #luaref table.classmembers td.def { text-align:right; padding-right:.5em; white-space: nowrap; }
683 #luaref table.classmembers td.decl { text-align:left; padding-left:.5em; white-space: nowrap; }
684 #luaref table.classmembers td.doc { text-align:left; padding-left:.6em; line-height: 1.2em; font-size:80%; }
685 #luaref table.classmembers td.doc div.dox {background-color:#eee; padding: .1em 1em; }
686 #luaref table.classmembers td.doc p { margin: .5em 0; }
687 #luaref table.classmembers td.doc p.para-brief { font-size:120%; }
688 #luaref table.classmembers td.doc p.para-returns { font-size:120%; }
689 #luaref table.classmembers td.doc dl { font-size:120%; line-height: 1.3em; }
690 #luaref table.classmembers td.doc dt { font-style: italic; }
691 #luaref table.classmembers td.fill { width: 99%; }
692 #luaref table.classmembers span.em { font-style: italic; }
693 #luaref span.functionname abbr { text-decoration:none; cursor:default; }
698 <h2>Ardour Lua Bindings</h2>
700 <a href="#h_classes">Class Documentation</a>
702 <a href="#h_enum">Enum/Constants</a>
704 <a href="#h_index">Index</a>
708 <!-- #### SNIP #### !-->
714 ################################################################################
715 # some general documentation -- should really go elsehere
719 <h2 id="h_intro">Overview</h2>
721 The top-level entry point are <?=typelink('ARDOUR:Session')?> and <?=typelink('ArdourUI:Editor')?>.
722 Most other Classes are used indirectly starting with a Session function. e.g. Session:get_routes().
725 A few classes are dedicated to certain script types, e.g. Lua DSP processors have exclusive access to
726 <?=typelink('ARDOUR:DSP')?> and <?=typelink('ARDOUR:ChanMapping')?>. Action Hooks Scripts to
727 <?=typelink('LuaSignal:Set')?> etc.
730 Detailed documentation (parameter names, method description) is not yet available. Please stay tuned.
732 <h3>Short introduction to Ardour classes</h3>
734 Ardour's structure is object oriented. The main object is the Session. A Session contains Audio Tracks, Midi Tracks and Busses.
735 Audio and Midi tracks are derived from a more general "Track" Object, which in turn is derived from a "Route" (aka Bus).
736 (We say "An Audio Track <em>is-a</em> Track <em>is-a</em> Route").
737 Tracks contain specifics. For Example a track <em>has-a</em> diskstream (for file i/o).
740 Operations are performed on objects. One gets a reference to an object and then calls a method.
741 e.g <code>obj = Session:route_by_name("Audio") obj:set_name("Guitar")</code>.
744 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:
745 you cannot simply remove a track that is currently processing audio. There are various <em>factory</em> methods for object creation or removal.
747 <h3>Pass by Reference</h3>
749 Since lua functions are closures, C++ methods that pass arguments by reference cannot be used as-is.
750 All parameters passed to a C++ method which uses references are returned as Lua Table.
751 If the C++ method also returns a value it is prefixed. Two parameters are returned: the value and a Lua Table holding the parameters.
755 <div style="float:left;">C++
757 <pre><code class="cxx">void set_ref (int& var, long& val)
759 printf ("%d %ld\n", var, val);
766 <div style="float:right;">Lua
768 <pre><code class="lua">local var = 0;
769 ref = set_ref (var, 2);
770 -- output from C++ printf()
771 </code><samp class="lua">0 2</samp><code>
772 -- var is still 0 here
773 print (ref[1], ref[2])
774 </code><samp class="lua">5 7</samp></pre>
778 <div class="clear"></div>
780 <div style="float:left;">
782 <pre><code class="cxx">int set_ref2 (int &var, std::string unused)
790 <div style="float:right;">
791 <pre><code class="lua">rv, ref = set_ref2 (0, "hello");
792 print (rv, ref[1], ref[2])
793 </code><samp class="lua">3 5 hello</samp></pre>
796 <div class="clear"></div>
798 <h3>Pointer Classes</h3>
800 Libardour makes extensive use of reference counted <code>boost::shared_ptr</code> to manage lifetimes.
801 The Lua bindings provide a complete abstration of this. There are no pointers in lua.
802 For example a <?=typelink('ARDOUR:Route')?> is a pointer in C++, but lua functions operate on it like it was a class instance.
805 <code>shared_ptr</code> are reference counted. Once assigned to a lua variable, the C++ object will be kept and remains valid.
806 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.
809 All pointer classes have a <code>isnil ()</code> method. This is for two cases:
810 Construction may fail. e.g. <code><?=typelink('ARDOUR:LuaAPI')?>.newplugin()</code>
811 may not be able to find the given plugin and hence cannot create an object.
814 The second case if for <code>boost::weak_ptr</code>. As opposed to <code>boost::shared_ptr</code> weak-pointers are not reference counted.
815 The object may vanish at any time.
816 If lua code calls a method on a nil object, the interpreter will raise an exception and the script will not continue.
817 This is not unlike <code>a = nil a:test()</code> which results in en error "<em>attempt to index a nil value</em>".
820 From the lua side of things there is no distinction between weak and shared pointers. They behave identically.
821 Below they're inidicated in orange and have an arrow to indicate the pointer type.
822 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.
828 #################################
829 # Main output function -- Classes
831 echo '<h2 id="h_classes">Class Documentation</h2>'.NL;
832 foreach ($classlist as $ns => $cl) {
834 $tbl = format_class_members ($ns, $cl, $dups);
836 # format class title - depending on type
838 # classes with no members (no ctor, no methods, no data)
839 echo '<h3 id="'.htmlentities ($ns).'" class="cls opaque"><abbr title="Opaque Object">∅</abbr> '.htmlentities ($ns).'</h3>'.NL;
841 else if (isset ($classlist[$ns]['free'])) {
842 # free functions (no class)
843 echo '<h3 id="'.htmlentities ($ns).'" class="cls freeclass"><abbr title="Namespace">ℕ</abbr> '.ctorname($ns).'</h3>'.NL;
845 else if (isset ($classlist[$ns]['arr'])) {
847 echo '<h3 id="'.htmlentities ($ns).'" class="cls array"><abbr title="C Array">⋯</abbr> '.htmlentities ($ns).'</h3>'.NL;
849 else if (isset ($classlist[$ns]['ptr'])) {
851 echo '<h3 id="'.htmlentities ($ns).'" class="cls pointerclass"><abbr title="Pointer Class">↠</abbr> '. htmlentities ($ns).'</h3>'.NL;
855 echo '<h3 id="'.htmlentities ($ns).'" class="cls class"><abbr title="Class">∁</abbr> '.htmlentities ($ns).'</h3>'.NL;
858 # show original C++ declaration
859 if (isset ($cl['decl'])) {
860 echo '<p class="cdecl"><em>C‡</em>: '.htmlentities ($cl['decl']).'</p>'.NL;
863 # print class inheritance (direct parent *name* only)
864 $inherited = array ();
865 $isa = traverse_parent ($ns, $inherited);
867 echo ' <p class="classinfo">is-a: '.$isa.'</p>'.NL;
869 echo '<div class="clear"></div>'.NL;
872 # class documentation (if any)
873 echo format_doxyclass ($cl);
875 # member documentation
877 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;
879 echo '<table class="classmembers">'.NL;
884 # traverse parent classes (all inherited members)
885 foreach ($inherited as $pns => $pcl) {
886 $tbl = format_class_members ($pns, $pcl, $dups);
888 echo '<h4 class="cls">Inherited from '.$pns.'</h4>'.NL;
889 echo '<table class="classmembers">'.NL;
899 echo '<h2 id="h_enum">Enum/Constants</h2>'.NL;
900 foreach ($constlist as $ns => $cs) {
901 echo '<h3 id="'.ctorname ($ns).'" class="cls enum"><abbr title="Enum">∈</abbr> '.ctorname ($ns).'</h3>'.NL;
902 echo '<ul class="enum">'.NL;
903 foreach ($cs as $c) {
904 echo '<li class="const">'.ctorname ($c['lua']).'</li>'.NL;
909 ######################
910 # Index of all classes
912 echo '<h2 id="h_index" >Class Index</h2>'.NL;
913 echo '<ul class="classindex">'.NL;
914 foreach ($classlist as $ns => $cl) {
915 echo '<li>'.typelink($ns).'</li>'.NL;
920 # see how far there is still to go...
921 fwrite (STDERR, "Found $dox_found annotations. missing: $dox_miss\n");
925 <div class="luafooter">Ardour <?=$ardourversion?> - <?=date('r')?></div>
927 <!-- #### SNIP #### !-->