2016-03-20 23:09:01 -04:00
#!/usr/bin/php
< ? php
2016-03-21 14:06:51 -04:00
## USAGE
#
2016-03-24 17:02:38 -04:00
## generate doc/luadoc.json.gz (lua binding doc)
2016-03-21 14:06:51 -04:00
# ./waf configure --luadoc ....
# ./waf
2016-03-24 17:02:38 -04:00
# ./gtk2_ardour/arluadoc > doc/luadoc.json.gz
2016-03-21 14:06:51 -04:00
#
2016-03-24 17:02:38 -04:00
## generate doc/ardourapi.json.gz (ardour header doxygen doc)
# cd ../../tools/doxy2json
# ./ardourdoc.sh
# cd -
#
## format HTML (using this scripterl)
2016-03-21 14:06:51 -04:00
# php tools/fmt-luadoc.php > /tmp/luadoc.html
#
2016-04-06 12:23:25 -04:00
$options = getopt ( " m " );
if ( isset ( $options [ 'm' ])) {
$HTMLOUTPUT = false ; ## set to false to output ardour-manual
} else {
$HTMLOUTPUT = true ; ## set to false to output ardour-manual
}
2016-03-21 14:06:51 -04:00
################################################################################
################################################################################
2016-03-20 23:09:01 -04:00
2016-03-24 17:02:38 -04:00
$json = gzdecode ( file_get_contents ( dirname ( __FILE__ ) . '/../doc/luadoc.json.gz' ));
2016-03-21 14:06:51 -04:00
$doc = array ();
2016-03-26 09:55:16 -04:00
$ardourversion = '' ;
2016-03-21 14:06:51 -04:00
foreach ( json_decode ( $json , true ) as $b ) {
2016-03-26 09:55:16 -04:00
if ( ! isset ( $b [ 'type' ])) {
if ( isset ( $b [ 'version' ])) { $ardourversion = $b [ 'version' ]; }
continue ;
}
2016-04-12 07:53:02 -04:00
# reserved lua words
2016-04-10 17:34:00 -04:00
$b [ 'lua' ] = preg_replace ( '/:_end/' , ':end' , $b [ 'lua' ]);
2016-04-12 07:53:02 -04:00
$b [ 'lua' ] = preg_replace ( '/:_type/' , ':type' , $b [ 'lua' ]);
2016-03-24 17:02:38 -04:00
$b [ 'ldec' ] = preg_replace ( '/ const/' , '' , preg_replace ( '/ const&/' , '' , $b [ 'decl' ]));
2016-10-03 22:45:35 -04:00
$b [ 'ldec' ] = preg_replace ( '/_VampHost::/' , '' , $b [ 'ldec' ]);
$b [ 'decl' ] = preg_replace ( '/_VampHost::/' , '' , $b [ 'decl' ]);
2016-03-24 17:02:38 -04:00
if ( isset ( $b [ 'ret' ])) {
$b [ 'ret' ] = preg_replace ( '/ const/' , '' , preg_replace ( '/ const&/' , '' , $b [ 'ret' ]));
2016-10-03 22:45:35 -04:00
$b [ 'ret' ] = preg_replace ( '/_VampHost::/' , '' , $b [ 'ret' ]);
}
if ( isset ( $b [ 'parent' ])) {
$b [ 'parent' ] = preg_replace ( '/_VampHost::/' , '' , $b [ 'parent' ]);
2016-03-24 17:02:38 -04:00
}
2016-03-20 23:09:01 -04:00
$doc [] = $b ;
}
2016-03-21 14:06:51 -04:00
if ( count ( $doc ) == 0 ) {
fwrite ( STDERR , " Failed to read luadoc.json \n " );
2019-07-04 16:21:14 -04:00
exit ( EXIT_FAILURE );
2016-03-21 14:06:51 -04:00
}
################################################################################
## Global result variables
2016-03-20 23:09:01 -04:00
################################################################################
2016-03-21 14:06:51 -04:00
$classlist = array ();
$constlist = array ();
2016-03-20 23:09:01 -04:00
2016-03-21 14:06:51 -04:00
################################################################################
## Pre-process the data, collect functions, parse arguments, cross reference
2016-03-20 23:09:01 -04:00
################################################################################
2016-03-21 14:06:51 -04:00
################################################################################
# some internal helper functions first
2016-03-21 16:15:26 -04:00
$funclist = array ();
2016-03-21 14:06:51 -04:00
$classes = array ();
$consts = array ();
2016-03-20 23:09:01 -04:00
function my_die ( $msg ) {
2016-03-21 14:06:51 -04:00
fwrite ( STDERR , $msg . " \n " );
exit ( 1 );
2016-03-20 23:09:01 -04:00
}
##function ptr_strip ($ctype) {
# # boost::shared_ptr<std::list<boost::shared_ptr<ARDOUR::Route>> > >
# # -> std::list<ARDOUR::Route>
# $ctype = preg_replace ('/boost::shared_ptr<([^>]*)[ ]*>/', '$1', $ctype);
# return preg_replace ('/boost::shared_ptr<([^>]*)[ ]*>/', '$1', $ctype);
#}
2016-03-24 17:02:38 -04:00
function arg2lua ( $argtype , $flags = 0 ) {
2016-03-20 23:09:01 -04:00
global $classes ;
global $consts ;
# LuaBridge abstracts C++ references
2016-03-24 17:02:38 -04:00
$flags |= preg_match ( '/&$/' , $argtype );
2016-03-20 23:09:01 -04:00
$arg = preg_replace ( '/&$/' , '' , $argtype );
2016-03-24 17:02:38 -04:00
$arg = preg_replace ( '/ $/' , '' , $arg );
2016-03-20 23:09:01 -04:00
# filter out basic types
2016-08-15 18:21:59 -04:00
$builtin = array ( 'float' , 'double' , 'bool' , 'std::string' , 'int' , 'short' , 'long' , 'unsigned int' , 'unsigned short' , 'unsigned long' , 'unsigned char' , 'char' , 'void' , 'char*' , 'unsigned char*' , 'void*' );
2016-03-21 14:06:51 -04:00
if ( in_array ( $arg , $builtin )) {
return array ( $arg => $flags );
}
2016-03-20 23:09:01 -04:00
2016-10-04 22:21:09 -04:00
if ( $arg == 'luabridge::LuaRef' ) {
return array ( 'Lua-Function' => $flags | 4 );
}
2019-08-23 20:38:14 -04:00
if ( $arg == 'LTC_TV_STANDARD' ) {
$arg = 'ARDOUR::DSP::LTC_TV_STANDARD' ;
}
2016-10-04 22:21:09 -04:00
2016-03-20 23:09:01 -04:00
# check Class declarations first
foreach ( array_merge ( $classes , $consts ) as $b ) {
2016-03-24 17:02:38 -04:00
if ( $b [ 'ldec' ] == $arg ) {
2016-03-21 14:06:51 -04:00
return array ( $b [ 'lua' ] => $flags );
2016-03-20 23:09:01 -04:00
}
}
# strip class pointers -- TODO Check C'tor for given class
$arg = preg_replace ( '/[&*]*$/' , '' , $argtype );
foreach ( array_merge ( $classes , $consts ) as $b ) {
2016-03-24 17:02:38 -04:00
if ( $b [ 'ldec' ] == $arg ) {
2016-03-21 14:06:51 -04:00
return array ( $b [ 'lua' ] => $flags );
2016-03-20 23:09:01 -04:00
}
}
2016-03-24 17:02:38 -04:00
if ( $flags & 2 ) {
return array ( $argtype => ( $flags | 4 ));
} else {
return array ( '--MISSING (' . $argtype . ')--' => ( $flags | 4 ));
}
2016-03-20 23:09:01 -04:00
}
function stripclass ( $classname , $name ) {
$classname .= ':' ;
2016-03-21 14:06:51 -04:00
if ( strpos ( $name , $classname ) !== 0 ) {
my_die ( 'invalid class prefix: ' . $classname . ' -- ' . $name );
2016-03-20 23:09:01 -04:00
}
return substr ( $name , strlen ( $classname ));
}
function datatype ( $decl ) {
# TODO handle spaces in type. Works because
# we don't yet have templated types (with_space <here >)
2016-04-10 17:34:00 -04:00
return substr ( $decl , 0 , strrpos ( $decl , ' ' ));
2016-03-20 23:09:01 -04:00
}
function luafn2class ( $lua ) {
2016-03-21 14:06:51 -04:00
return substr ( $lua , 0 , strrpos ( $lua , ':' ));
2016-03-20 23:09:01 -04:00
}
2016-04-06 11:01:53 -04:00
function luafn2name ( $lua ) {
$fn = strrpos ( $lua , ':' );
if ( $fn !== 0 && strlen ( $lua ) > $fn + 1 ) {
return substr ( $lua , $fn + 1 );
}
my_die ( 'invalid class prefix: ' . $name );
}
2016-03-20 23:09:01 -04:00
function checkclass ( $b ) {
global $classlist ;
2016-03-21 14:06:51 -04:00
if ( ! isset ( $classlist [ luafn2class ( $b [ 'lua' ])])) {
my_die ( 'MISSING CLASS FOR ' . print_r ( $b [ 'lua' ], true ));
2016-03-20 23:09:01 -04:00
}
}
# parse functions argument list to lua-names
function decl2args ( $decl ) {
$start = strrpos ( $decl , '(' );
$end = strrpos ( $decl , ')' );
$args = substr ( $decl , $start + 1 , $end - $start - 1 );
$arglist = preg_split ( '/, */' , $args );
$rv = array ();
foreach ( $arglist as $a ) {
if ( empty ( $a )) { continue ; }
2016-03-21 14:06:51 -04:00
$rv [] = arg2lua ( $a );
2016-03-20 23:09:01 -04:00
}
return $rv ;
}
2016-03-24 17:02:38 -04:00
function canonical_ctor ( $b ) {
$rv = '' ;
if ( preg_match ( '/[^(]*\(([^)*]*)\*\)(\(.*\))/' , $b [ 'decl' ], $matches )) {
$lc = luafn2class ( $b [ 'lua' ]);
$cn = str_replace ( ':' , '::' , $lc );
$fn = substr ( $lc , 1 + strrpos ( $lc , ':' ));
$rv = $cn . '::' . $fn . $matches [ 2 ];
}
return $rv ;
}
function canonical_decl ( $b ) {
$rv = '' ;
2016-03-24 19:43:15 -04:00
$pfx = '' ;
2016-03-24 17:02:38 -04:00
# match clang's declatation format
if ( preg_match ( '/[^(]*\(([^)*]*)\*\)\((.*)\)/' , $b [ 'decl' ], $matches )) {
2016-03-24 19:43:15 -04:00
if ( strpos ( $b [ 'type' ], 'Free Function' ) !== false ) {
$pfx = str_replace ( ':' , '::' , luafn2class ( $b [ 'lua' ])) . '::' ;
}
2016-03-24 17:02:38 -04:00
$fn = substr ( $b [ 'lua' ], 1 + strrpos ( $b [ 'lua' ], ':' ));
$rv = $matches [ 1 ] . $fn . '(' ;
$arglist = preg_split ( '/, */' , $matches [ 2 ]);
$first = true ;
foreach ( $arglist as $a ) {
if ( ! $first ) { $rv .= ', ' ; }; $first = false ;
if ( empty ( $a )) { continue ; }
$a = preg_replace ( '/([^>]) >/' , '$1>' , $a );
2016-03-24 19:43:15 -04:00
$a = preg_replace ( '/^Cairo::/' , '' , $a ); // special case cairo enums
2016-03-24 17:02:38 -04:00
$a = preg_replace ( '/([^ ])&/' , '$1 &' , $a );
2016-10-04 22:21:09 -04:00
$a = preg_replace ( '/std::vector<([^>]*)> const/' , 'const std::vector<$1>' , $a );
$a = str_replace ( 'std::vector' , 'vector' , $a );
2016-03-24 17:02:38 -04:00
$a = str_replace ( 'vector' , 'std::vector' , $a );
2016-03-24 19:43:15 -04:00
$a = str_replace ( 'std::string' , 'string' , $a );
2016-03-24 17:02:38 -04:00
$a = str_replace ( 'string const' , 'const string' , $a );
$a = str_replace ( 'string' , 'std::string' , $a );
$rv .= $a ;
}
$rv .= ')' ;
}
2016-03-24 19:43:15 -04:00
return $pfx . $rv ;
2016-03-24 17:02:38 -04:00
}
2016-03-20 23:09:01 -04:00
################################################################################
# step 1: build class indices
foreach ( $doc as $b ) {
if ( strpos ( $b [ 'type' ], " [C] " ) === 0 ) {
$classes [] = $b ;
2016-03-21 14:06:51 -04:00
$classlist [ $b [ 'lua' ]] = $b ;
if ( strpos ( $b [ 'type' ], 'Pointer Class' ) === false ) {
2016-03-24 17:02:38 -04:00
$classdecl [ $b [ 'ldec' ]] = $b ;
2016-03-21 14:06:51 -04:00
}
2016-03-20 23:09:01 -04:00
}
}
2016-03-21 14:06:51 -04:00
2016-03-20 23:09:01 -04:00
foreach ( $classes as $c ) {
2016-03-21 14:06:51 -04:00
if ( strpos ( $c [ 'type' ], 'Pointer Class' ) !== false ) { continue ; }
2016-03-20 23:09:01 -04:00
if ( isset ( $c [ 'parent' ])) {
if ( isset ( $classdecl [ $c [ 'parent' ]])) {
2016-03-21 14:06:51 -04:00
$classlist [ $c [ 'lua' ]][ 'luaparent' ][] = $classdecl [ $c [ 'parent' ]][ 'lua' ];
2016-03-20 23:09:01 -04:00
} else {
2016-03-21 14:06:51 -04:00
my_die ( 'unknown parent class: ' . print_r ( $c , true ));
2016-03-20 23:09:01 -04:00
}
}
}
# step 2: extract constants/enum
foreach ( $doc as $b ) {
switch ( $b [ 'type' ]) {
case " Constant/Enum " :
case " Constant/Enum Member " :
2016-03-24 17:02:38 -04:00
if ( strpos ( $b [ 'ldec' ], '::' ) === false ) {
2016-03-20 23:09:01 -04:00
# for extern c enums, use the Lua Namespace
2016-03-24 17:02:38 -04:00
$b [ 'ldec' ] = str_replace ( ':' , '::' , luafn2class ( $b [ 'lua' ]));
2016-03-20 23:09:01 -04:00
}
2016-03-24 17:02:38 -04:00
$ns = str_replace ( '::' , ':' , $b [ 'ldec' ]);
2016-03-21 14:06:51 -04:00
$constlist [ $ns ][] = $b ;
# arg2lua lookup
2016-03-20 23:09:01 -04:00
$b [ 'lua' ] = $ns ;
$consts [] = $b ;
break ;
default :
break ;
}
}
# step 3: process functions
foreach ( $doc as $b ) {
switch ( $b [ 'type' ]) {
case " Constructor " :
case " Weak/Shared Pointer Constructor " :
checkclass ( $b );
2016-03-21 14:06:51 -04:00
$classlist [ luafn2class ( $b [ 'lua' ])][ 'ctor' ][] = array (
'name' => luafn2class ( $b [ 'lua' ]),
2016-03-24 17:02:38 -04:00
'args' => decl2args ( $b [ 'ldec' ]),
2017-02-14 08:43:29 -05:00
'cand' => canonical_ctor ( $b ),
'nil' => false
);
break ;
case " Weak/Shared Pointer NIL Constructor " :
checkclass ( $b );
$classlist [ luafn2class ( $b [ 'lua' ])][ 'ctor' ][] = array (
'name' => luafn2class ( $b [ 'lua' ]),
'args' => decl2args ( $b [ 'ldec' ]),
'cand' => canonical_ctor ( $b ),
'nil' => true
2016-03-20 23:09:01 -04:00
);
break ;
2016-08-15 18:21:59 -04:00
case " Property " :
checkclass ( $b );
$classlist [ luafn2class ( $b [ 'lua' ])][ 'props' ][] = array (
'name' => $b [ 'lua' ],
'ret' => arg2lua ( datatype ( $b [ 'ldec' ]))
);
break ;
2016-03-20 23:09:01 -04:00
case " Data Member " :
checkclass ( $b );
2016-03-21 14:06:51 -04:00
$classlist [ luafn2class ( $b [ 'lua' ])][ 'data' ][] = array (
2016-03-20 23:09:01 -04:00
'name' => $b [ 'lua' ],
2016-03-24 17:02:38 -04:00
'ret' => arg2lua ( datatype ( $b [ 'ldec' ]))
2016-03-20 23:09:01 -04:00
);
break ;
2016-04-06 11:01:53 -04:00
case " Static C Function " :
checkclass ( $b );
if ( strpos ( $b [ 'lua' ], 'ARDOUR:DataType:' ) === 0 ) {
# special case ARDOUR:DataType convenience c'tor
$args = array ();
$ret = array ( luafn2class ( $b [ 'lua' ]) => 0 );
$canon = 'ARDOUR::LuaAPI::datatype_ctor_' . strtolower ( luafn2name ( $b [ 'lua' ])) . '(lua_State*)' ;
} else {
my_die ( 'unhandled Static C: ' . print_r ( $b , true ));
}
$classlist [ luafn2class ( $b [ 'lua' ])][ 'func' ][] = array (
'bind' => $b ,
'name' => $b [ 'lua' ],
'args' => $args ,
'ret' => $ret ,
'ref' => false ,
'ext' => false ,
'cand' => $canon
);
break ;
2016-03-20 23:09:01 -04:00
case " C Function " :
# we required C functions to be in a class namespace
case " Ext C Function " :
checkclass ( $b );
2016-03-24 17:02:38 -04:00
$args = array ( array ( '--lua--' => 0 ));
2016-03-21 16:15:26 -04:00
$ret = array ( '...' => 0 );
$ns = luafn2class ( $b [ 'lua' ]);
$cls = $classlist [ $ns ];
2016-03-24 17:02:38 -04:00
if ( preg_match ( '/.*<([^>]*)[ ]*>/' , $cls [ 'ldec' ], $templ )) {
2016-04-06 11:01:53 -04:00
# std::vector, std::list types
2016-03-21 16:15:26 -04:00
switch ( stripclass ( $ns , $b [ 'lua' ])) {
case 'add' :
2016-03-24 17:02:38 -04:00
#$args = array (array ('LuaTable {'.$templ[1].'}' => 0));
$args = array ( arg2lua ( $templ [ 1 ], 2 ));
2016-03-21 19:50:14 -04:00
$ret = array ( 'LuaTable' => 0 );
2016-03-21 16:15:26 -04:00
break ;
case 'iter' :
$args = array ();
$ret = array ( 'LuaIter' => 0 );
break ;
case 'table' :
$args = array ();
$ret = array ( 'LuaTable' => 0 );
break ;
default :
break ;
}
} else if ( strpos ( $cls [ 'type' ], ' Array' ) !== false ) {
2016-04-06 11:01:53 -04:00
# catches C:FloatArray, C:IntArray
2016-03-24 17:02:38 -04:00
$templ = preg_replace ( '/[&*]*$/' , '' , $cls [ 'ldec' ]);
2016-03-21 16:15:26 -04:00
switch ( stripclass ( $ns , $b [ 'lua' ])) {
case 'array' :
$args = array ();
$ret = array ( 'LuaMetaTable' => 0 );
break ;
case 'get_table' :
$args = array ();
$ret = array ( 'LuaTable' => 0 );
break ;
case 'set_table' :
$args = array ( array ( 'LuaTable {' . $templ . '}' => 0 ));
$ret = array ( 'void' => 0 );
break ;
default :
break ;
}
}
2016-03-21 14:06:51 -04:00
$classlist [ luafn2class ( $b [ 'lua' ])][ 'func' ][] = array (
2016-03-21 19:50:14 -04:00
'bind' => $b ,
2016-03-20 23:09:01 -04:00
'name' => $b [ 'lua' ],
2016-03-21 16:15:26 -04:00
'args' => $args ,
'ret' => $ret ,
2016-03-21 14:06:51 -04:00
'ref' => true ,
2016-03-24 17:02:38 -04:00
'ext' => true ,
'cand' => canonical_decl ( $b )
2016-03-20 23:09:01 -04:00
);
break ;
2016-04-10 17:34:00 -04:00
case " Free C Function " :
$funclist [ luafn2class ( $b [ 'lua' ])][] = array (
'bind' => $b ,
'name' => $b [ 'lua' ],
'args' => $args ,
'ret' => $ret ,
'ref' => false ,
'ext' => true ,
'cand' => str_replace ( ':' , '::' , $b [ 'lua' ]) . '(lua_State*)'
);
break ;
2016-03-20 23:09:01 -04:00
case " Free Function " :
case " Free Function RefReturn " :
2016-03-21 14:06:51 -04:00
$funclist [ luafn2class ( $b [ 'lua' ])][] = array (
2016-03-21 19:50:14 -04:00
'bind' => $b ,
2016-03-20 23:09:01 -04:00
'name' => $b [ 'lua' ],
2016-03-24 17:02:38 -04:00
'args' => decl2args ( $b [ 'ldec' ]),
2016-03-20 23:09:01 -04:00
'ret' => arg2lua ( $b [ 'ret' ]),
2016-03-24 17:02:38 -04:00
'ref' => ( strpos ( $b [ 'type' ], " RefReturn " ) !== false ),
'cand' => canonical_decl ( $b )
2016-03-20 23:09:01 -04:00
);
break ;
case " Member Function " :
2016-03-21 14:06:51 -04:00
case " Member Function RefReturn " :
2016-03-20 23:09:01 -04:00
case " Member Pointer Function " :
case " Weak/Shared Pointer Function " :
case " Weak/Shared Pointer Function RefReturn " :
case " Weak/Shared Null Check " :
case " Static Member Function " :
checkclass ( $b );
2016-03-21 14:06:51 -04:00
$classlist [ luafn2class ( $b [ 'lua' ])][ 'func' ][] = array (
2016-03-21 19:50:14 -04:00
'bind' => $b ,
2016-03-20 23:09:01 -04:00
'name' => $b [ 'lua' ],
2016-03-24 17:02:38 -04:00
'args' => decl2args ( $b [ 'ldec' ]),
2016-03-20 23:09:01 -04:00
'ret' => arg2lua ( $b [ 'ret' ]),
2016-03-24 17:02:38 -04:00
'ref' => ( strpos ( $b [ 'type' ], " RefReturn " ) !== false ),
'cand' => canonical_decl ( $b )
2016-03-20 23:09:01 -04:00
);
break ;
2016-06-01 07:59:31 -04:00
case " Cast " :
2016-04-12 07:53:02 -04:00
case " Weak/Shared Pointer Cast " :
checkclass ( $b );
$classlist [ luafn2class ( $b [ 'lua' ])][ 'cast' ][] = array (
'bind' => $b ,
'name' => $b [ 'lua' ],
'args' => decl2args ( $b [ 'ldec' ]),
'ret' => arg2lua ( $b [ 'ret' ]),
'ref' => ( strpos ( $b [ 'type' ], " RefReturn " ) !== false ),
'cand' => canonical_decl ( $b )
);
break ;
2016-03-20 23:09:01 -04:00
case " Constant/Enum " :
case " Constant/Enum Member " :
# already handled -> $consts
break ;
default :
if ( strpos ( $b [ 'type' ], " [C] " ) !== 0 ) {
my_die ( 'unhandled type: ' . $b [ 'type' ]);
}
break ;
}
}
2016-03-21 14:06:51 -04:00
# step 4: collect/group/sort
2016-03-20 23:09:01 -04:00
# step 4a: unify weak/shared Ptr classes
2016-03-21 14:06:51 -04:00
foreach ( $classlist as $ns => $cl ) {
if ( strpos ( $cl [ 'type' ], ' Array' ) !== false ) {
$classlist [ $ns ][ 'arr' ] = true ;
2016-04-25 07:49:43 -04:00
$classlist [ $ns ][ 'cdecl' ] = $cl [ 'decl' ];
2016-03-21 14:06:51 -04:00
continue ;
}
foreach ( $classes as $c ) {
if ( $c [ 'lua' ] == $ns ) {
if ( strpos ( $c [ 'type' ], 'Pointer Class' ) !== false ) {
$classlist [ $ns ][ 'ptr' ] = true ;
2016-04-12 18:48:39 -04:00
$classlist [ $ns ][ 'cdecl' ] = 'boost::shared_ptr< ' . $c [ 'decl' ] . ' >, boost::weak_ptr< ' . $c [ 'decl' ] . ' >' ;
2016-03-21 14:06:51 -04:00
break ;
2016-04-12 18:48:39 -04:00
} else {
$classlist [ $ns ][ 'cdecl' ] = $c [ 'decl' ];
2016-03-21 14:06:51 -04:00
}
}
}
}
# step4b: sanity check
foreach ( $classlist as $ns => $cl ) {
if ( isset ( $classes [ $ns ][ 'parent' ]) && ! isset ( $classlist [ $ns ][ 'luaparent' ])) {
my_die ( 'missing parent class: ' . print_r ( $cl , true ));
}
}
# step 4c: merge free functions into classlist
foreach ( $funclist as $ns => $fl ) {
if ( isset ( $classlist [ $ns ])) {
my_die ( 'Free Funcion in existing namespace: ' . $ns . ' ' . print_r ( $ns , true ));
}
$classlist [ $ns ][ 'func' ] = $fl ;
$classlist [ $ns ][ 'free' ] = true ;
}
# step 4d: order to chaos
# no array_multisort() here, sub-types are sorted after merging parents
ksort ( $classlist );
2016-03-21 16:15:26 -04:00
################################################################################
################################################################################
################################################################################
#### -- split here -- ####
# from here on, only $classlist and $constlist arrays are relevant.
2016-03-26 09:55:16 -04:00
# we also pull in C++ header annotation from doxygen to $api
2016-03-21 16:15:26 -04:00
2016-03-26 09:55:16 -04:00
# read documentation from doxygen
2016-03-24 17:02:38 -04:00
$json = gzdecode ( file_get_contents ( dirname ( __FILE__ ) . '/../doc/ardourapi.json.gz' ));
$api = array ();
foreach ( json_decode ( $json , true ) as $a ) {
if ( ! isset ( $a [ 'decl' ])) { continue ; }
if ( empty ( $a [ 'decl' ])) { continue ; }
$canon = str_replace ( ' *' , '*' , $a [ 'decl' ]);
$api [ $canon ] = $a ;
}
2016-03-21 16:15:26 -04:00
2016-03-26 09:55:16 -04:00
# keep track of found/missing doc
2016-03-24 17:02:38 -04:00
$dox_found = 0 ;
$dox_miss = 0 ;
2016-03-26 09:55:16 -04:00
# retrive a value from $api
2016-03-24 17:02:38 -04:00
function doxydoc ( $canonical_declaration ) {
global $api ;
global $dox_found ;
global $dox_miss ;
if ( isset ( $api [ $canonical_declaration ])) {
$dox_found ++ ;
return $api [ $canonical_declaration ][ 'doc' ];
}
2016-04-12 18:48:39 -04:00
// remove template namespace e.g.
// "ARDOUR::Track::bounceable(boost::shared_ptr<ARDOUR::Processor>"
// "ARDOUR::Track::bounceable(boost::shared_ptr<Processor>"
$cn = preg_replace ( '/<[^>]*::([^>]*)>/' , '<$1>' , $canonical_declaration );
if ( isset ( $api [ $cn ])) {
$dox_found ++ ;
return $api [ $cn ][ 'doc' ];
}
#fwrite (STDERR, $canonical_declaration."\n"); # XXX DEBUG
$dox_miss ++ ;
return '' ;
2016-03-24 17:02:38 -04:00
}
2016-03-21 16:15:26 -04:00
2016-03-21 14:06:51 -04:00
################################################################################
# OUTPUT
################################################################################
2016-03-20 23:09:01 -04:00
2016-03-21 14:06:51 -04:00
################################################################################
# Helper functions
2016-03-20 23:09:01 -04:00
define ( 'NL' , " \n " );
2016-03-26 09:55:16 -04:00
# constructors, enums (constants) use a dot. (e.g. "LuaOSC.Address" -> "LuaOSC.Address" )
2016-03-21 14:06:51 -04:00
function ctorname ( $name ) {
return htmlentities ( str_replace ( ':' , '.' , $name ));
}
2016-03-26 09:55:16 -04:00
# strip class prefix (e.g "Evoral:MidiEvent:channel" -> "channel")
2016-03-21 16:15:26 -04:00
function shortname ( $name ) {
return htmlentities ( substr ( $name , strrpos ( $name , ':' ) + 1 ));
}
2016-03-26 09:55:16 -04:00
# retrieve variable name from array["VARNAME"] => FLAGS
2016-03-21 14:06:51 -04:00
function varname ( $a ) {
return array_keys ( $a )[ 0 ];
}
2016-03-26 09:55:16 -04:00
# recusively collect class parents (derived classes)
2016-03-21 16:15:26 -04:00
function traverse_parent ( $ns , & $inherited ) {
global $classlist ;
$rv = '' ;
if ( isset ( $classlist [ $ns ][ 'luaparent' ])) {
$parents = array_unique ( $classlist [ $ns ][ 'luaparent' ]);
asort ( $parents );
foreach ( $parents as $p ) {
if ( ! empty ( $rv )) { $rv .= ', ' ; }
2016-12-05 17:49:05 -05:00
if ( $p == $ns ) { continue ; }
2016-03-21 16:15:26 -04:00
$rv .= typelink ( $p );
$inherited [ $p ] = $classlist [ $p ];
traverse_parent ( $p , $inherited );
}
}
return $rv ;
}
2016-03-26 09:55:16 -04:00
# create a cross-reference to a type (class or enum)
# *all* <a> links are generated here, currently anchors on a single page.
2016-03-21 16:15:26 -04:00
function typelink ( $a , $short = false , $argcls = '' , $linkcls = '' , $suffix = '' ) {
2016-03-21 14:06:51 -04:00
global $classlist ;
global $constlist ;
2016-03-21 19:50:14 -04:00
if ( isset ( $classlist [ $a ][ 'free' ])) {
return '<a class="' . $linkcls . '" href="#' . htmlentities ( $a ) . '">' . ( $short ? shortname ( $a ) : ctorname ( $a )) . $suffix . '</a>' ;
} else if ( in_array ( $a , array_keys ( $classlist ))) {
2016-03-21 16:15:26 -04:00
return '<a class="' . $linkcls . '" href="#' . htmlentities ( $a ) . '">' . ( $short ? shortname ( $a ) : htmlentities ( $a )) . $suffix . '</a>' ;
2016-03-21 14:06:51 -04:00
} else if ( in_array ( $a , array_keys ( $constlist ))) {
2016-03-21 16:15:26 -04:00
return '<a class="' . $linkcls . '" href="#' . ctorname ( $a ) . '">' . ( $short ? shortname ( $a ) : ctorname ( $a )) . $suffix . '</a>' ;
2016-03-21 14:06:51 -04:00
} else {
2016-03-21 16:15:26 -04:00
return '<span class="' . $argcls . '">' . htmlentities ( $a ) . $suffix . '</span>' ;
2016-03-21 14:06:51 -04:00
}
}
2016-03-20 23:09:01 -04:00
2016-03-26 09:55:16 -04:00
# output format function arguments
2016-03-20 23:09:01 -04:00
function format_args ( $args ) {
2016-03-21 14:06:51 -04:00
$rv = '<span class="functionargs"> (' ;
2016-03-20 23:09:01 -04:00
$first = true ;
foreach ( $args as $a ) {
2016-03-21 14:06:51 -04:00
if ( ! $first ) { $rv .= ', ' ; }; $first = false ;
$flags = $a [ varname ( $a )];
2016-10-04 22:21:09 -04:00
if ( $flags & 4 ) {
$rv .= '<span>' . varname ( $a ) . '</span>' ;
}
else if ( $flags & 2 ) {
2016-03-24 17:02:38 -04:00
$rv .= '<em>LuaTable</em> {' . typelink ( varname ( $a ), true , 'em' ) . '}' ;
}
elseif ( $flags & 1 ) {
2016-03-21 16:15:26 -04:00
$rv .= typelink ( varname ( $a ), true , 'em' , '' , '&' );
2016-03-24 17:02:38 -04:00
}
else {
2016-03-21 16:15:26 -04:00
$rv .= typelink ( varname ( $a ), true , 'em' );
2016-03-21 14:06:51 -04:00
}
2016-03-20 23:09:01 -04:00
}
2016-03-21 14:06:51 -04:00
$rv .= ')</span>' ;
2016-03-20 23:09:01 -04:00
return $rv ;
}
2016-03-26 09:55:16 -04:00
# format doxygen documentation for class-definition
2016-03-24 17:02:38 -04:00
function format_doxyclass ( $cl ) {
$rv = '' ;
if ( isset ( $cl [ 'decl' ])) {
$doc = doxydoc ( $cl [ 'decl' ]);
if ( ! empty ( $doc )) {
$rv .= '<div class="classdox">' . $doc . '</div>' . NL ;
}
}
return $rv ;
}
2016-03-26 09:55:16 -04:00
# format doxygen documentation for class-members
2016-03-24 17:02:38 -04:00
function format_doxydoc ( $f ) {
$rv = '' ;
if ( isset ( $f [ 'cand' ])) {
$doc = doxydoc ( $f [ 'cand' ]);
if ( ! empty ( $doc )) {
$rv .= '<tr><td></td><td class="doc" colspan="2"><div class="dox">' . $doc ;
$rv .= '</div></td></tr>' . NL ;
2016-03-24 20:22:23 -04:00
} else if ( 0 ) { # debug
2016-03-24 17:02:38 -04:00
$rv .= '<tr><td></td><td class="doc" colspan="2"><p>' . htmlentities ( $f [ 'cand' ]) . '</p>' ;
$rv .= '</td></tr>' . NL ;
}
}
return $rv ;
}
2016-03-26 09:55:16 -04:00
# usort() callback for class-members
function name_sort_cb ( $a , $b ) {
return strcmp ( $a [ 'name' ], $b [ 'name' ]);
}
# main output function for every class
2016-03-21 14:06:51 -04:00
function format_class_members ( $ns , $cl , & $dups ) {
$rv = '' ;
2016-03-26 09:55:16 -04:00
# print contructor - if any
2016-03-20 23:09:01 -04:00
if ( isset ( $cl [ 'ctor' ])) {
2016-03-21 14:06:51 -04:00
usort ( $cl [ 'ctor' ], 'name_sort_cb' );
$rv .= ' <tr><th colspan="3">Constructor</th></tr>' . NL ;
2016-03-20 23:09:01 -04:00
foreach ( $cl [ 'ctor' ] as $f ) {
2017-02-14 08:43:29 -05:00
$rv .= ' <tr>' ;
if ( $f [ 'nil' ]) {
$rv .= '<td class="def"><abbr title="Nil Pointer Constructor">ℵ</abbr></td>' ;
} else {
$rv .= '<td class="def">ℂ</td>' ;
}
$rv .= '<td class="decl">' ;
2016-03-21 14:06:51 -04:00
$rv .= '<span class="functionname">' . ctorname ( $f [ 'name' ]) . '</span>' ;
$rv .= format_args ( $f [ 'args' ]);
$rv .= '</td><td class="fill"></td></tr>' . NL ;
2016-03-26 09:55:16 -04:00
# doxygen documentation (may be empty)
2016-03-24 17:02:38 -04:00
$rv .= format_doxydoc ( $f );
2016-03-20 23:09:01 -04:00
}
}
2016-03-26 09:55:16 -04:00
# strip duplicates (inherited or derived methods)
# e.g AudioTrack -> Track -> Route -> SessionObject -> Stateful
# all 5 have "isnil()"
2016-03-21 14:06:51 -04:00
$nondups = array ();
2016-03-20 23:09:01 -04:00
if ( isset ( $cl [ 'func' ])) {
foreach ( $cl [ 'func' ] as $f ) {
2016-03-21 14:06:51 -04:00
if ( in_array ( stripclass ( $ns , $f [ 'name' ]), $dups )) { continue ; }
$nondups [] = $f ;
2016-03-20 23:09:01 -04:00
}
2016-03-21 14:06:51 -04:00
}
2016-03-26 09:55:16 -04:00
# print methods - if any
2016-03-21 14:06:51 -04:00
if ( count ( $nondups ) > 0 ) {
usort ( $nondups , 'name_sort_cb' );
$rv .= ' <tr><th colspan="3">Methods</th></tr>' . NL ;
foreach ( $nondups as $f ) {
$dups [] = stripclass ( $ns , $f [ 'name' ]);
2016-03-26 09:55:16 -04:00
# return value/type
2016-03-21 14:06:51 -04:00
$rv .= ' <tr><td class="def">' ;
if ( $f [ 'ref' ] && isset ( $f [ 'ext' ])) {
# external C functions
2016-03-21 16:15:26 -04:00
$rv .= '<em>' . varname ( $f [ 'ret' ]) . '</em>' ;
2016-03-21 14:06:51 -04:00
} elseif ( $f [ 'ref' ] && varname ( $f [ 'ret' ]) == 'void' ) {
2016-03-26 09:55:16 -04:00
# void functions with reference args
2016-03-21 14:06:51 -04:00
$rv .= '<em>LuaTable</em>(...)' ;
} elseif ( $f [ 'ref' ]) {
2016-03-26 09:55:16 -04:00
# functions with reference args and return value
2016-03-24 17:02:38 -04:00
$rv .= '<em>LuaTable</em>(' . typelink ( varname ( $f [ 'ret' ]), true , 'em' ) . ', ...)' ;
2016-03-21 14:06:51 -04:00
} else {
2016-03-26 09:55:16 -04:00
# normal class members
2016-03-21 16:15:26 -04:00
$rv .= typelink ( varname ( $f [ 'ret' ]), true , 'em' );
2016-03-21 14:06:51 -04:00
}
2016-03-26 09:55:16 -04:00
# function declaration and arguments
2016-03-21 14:06:51 -04:00
$rv .= '</td><td class="decl">' ;
2016-03-21 19:50:14 -04:00
$rv .= '<span class="functionname"><abbr title="' . htmlentities ( $f [ 'bind' ][ 'decl' ]) . '">' . stripclass ( $ns , $f [ 'name' ]) . '</abbr></span>' ;
2016-03-21 14:06:51 -04:00
$rv .= format_args ( $f [ 'args' ]);
$rv .= '</td><td class="fill"></td></tr>' . NL ;
2016-03-26 09:55:16 -04:00
# doxygen documentation (may be empty)
2016-03-24 17:02:38 -04:00
$rv .= format_doxydoc ( $f );
2016-03-21 16:15:26 -04:00
}
2016-03-20 23:09:01 -04:00
}
2016-04-12 07:53:02 -04:00
# print cast - if any
if ( isset ( $cl [ 'cast' ])) {
usort ( $cl [ 'cast' ], 'name_sort_cb' );
$rv .= ' <tr><th colspan="3">Cast</th></tr>' . NL ;
foreach ( $cl [ 'cast' ] as $f ) {
$rv .= ' <tr><td class="def">' ;
$rv .= typelink ( varname ( $f [ 'ret' ]), true , 'em' );
# function declaration and arguments
$rv .= '</td><td class="decl">' ;
$rv .= '<span class="functionname"><abbr title="' . htmlentities ( $f [ 'bind' ][ 'decl' ]) . '">' . stripclass ( $ns , $f [ 'name' ]) . '</abbr></span>' ;
$rv .= format_args ( $f [ 'args' ]);
$rv .= '</td><td class="fill"></td></tr>' . NL ;
# doxygen documentation (may be empty)
$rv .= format_doxydoc ( $f );
}
}
2016-08-15 18:21:59 -04:00
# print properties - if any
if ( isset ( $cl [ 'props' ])) {
usort ( $cl [ 'props' ], 'name_sort_cb' );
$rv .= ' <tr><th colspan="3">Properties</th></tr>' . NL ;
foreach ( $cl [ 'props' ] as $f ) {
$rv .= ' <tr><td class="def">' . typelink ( array_keys ( $f [ 'ret' ])[ 0 ], false , 'em' ) . '</td><td class="decl">' ;
$rv .= '<span class="functionname">' . stripclass ( $ns , $f [ 'name' ]) . '</span>' ;
$rv .= '</td><td class="fill"></td></tr>' . NL ;
}
}
2016-08-15 19:01:36 -04:00
2016-03-26 09:55:16 -04:00
# print data members - if any
2016-03-20 23:09:01 -04:00
if ( isset ( $cl [ 'data' ])) {
2016-03-21 14:06:51 -04:00
usort ( $cl [ 'data' ], 'name_sort_cb' );
$rv .= ' <tr><th colspan="3">Data Members</th></tr>' . NL ;
2016-03-20 23:09:01 -04:00
foreach ( $cl [ 'data' ] as $f ) {
2016-03-21 16:15:26 -04:00
$rv .= ' <tr><td class="def">' . typelink ( array_keys ( $f [ 'ret' ])[ 0 ], false , 'em' ) . '</td><td class="decl">' ;
2016-03-21 14:06:51 -04:00
$rv .= '<span class="functionname">' . stripclass ( $ns , $f [ 'name' ]) . '</span>' ;
$rv .= '</td><td class="fill"></td></tr>' . NL ;
2016-10-03 22:45:35 -04:00
$f [ 'cand' ] = str_replace ( ':' , '::' , $f [ 'name' ]);
$rv .= format_doxydoc ( $f );
2016-03-20 23:09:01 -04:00
}
}
2016-03-21 14:06:51 -04:00
return $rv ;
2016-03-20 23:09:01 -04:00
}
2016-03-21 14:06:51 -04:00
################################################################################
# Start Output
2016-03-21 16:15:26 -04:00
2016-04-06 12:23:25 -04:00
if ( $HTMLOUTPUT ) {
2016-03-21 14:06:51 -04:00
?> <!DOCTYPE html>
< html xmlns = " http://www.w3.org/1999/xhtml " lang = " en " xml : lang = " en " >
< head >
< title > Ardour Lua Bindings </ title >
< meta http - equiv = " Content-Type " content = " text/html; charset=UTF-8 " />
< style type = " text/css " >
2016-03-26 16:27:13 -04:00
div . header { text - align : center ; }
div . header h2 { margin : 0 ; }
div . header p { margin :. 25 em ; text - align : center ; }
div . luafooter { text - align : center ; font - size : 80 % ; color : #888; margin: 2em 0; }
#luaref { max-width:60em; margin: 1em auto; }
#luaref h2 { margin:2em 0 0 0; padding:0em; border-bottom: 1px solid black; }
#luaref h3.cls { margin:2em 0 0 0; padding: 0 0 0 1em; border: 1px dashed #6666ee; }
#luaref h3.cls abbr { text-decoration:none; cursor:default; }
#luaref h4.cls { margin:1em 0 0 0; }
#luaref h3.class { background-color: #aaee66; }
#luaref h3.enum { background-color: #aaaaaa; }
#luaref h3.pointerclass { background-color: #eeaa66; }
#luaref h3.array { background-color: #66aaee; }
#luaref h3.opaque { background-color: #6666aa; }
#luaref p { text-align: justify; }
#luaref p.cdecl { text-align: right; float:right; font-size:90%; margin:0; padding: 0 0 0 1em; }
#luaref ul.classindex { columns: 2; -webkit-columns: 2; -moz-columns: 2; }
#luaref div.clear { clear:both; }
#luaref p.classinfo { margin: .25em 0; }
#luaref div.code { width:80%; margin:.5em auto; }
#luaref div.code div { width:45%; }
#luaref div.code pre { line-height: 1.2em; margin: .25em 0; }
#luaref div.code samp { color: green; font-weight: bold; background-color: #eee; }
#luaref div.classdox { padding: .1em 1em; }
#luaref div.classdox p { margin: .5em 0 .5em .6em; }
#luaref div.classdox p { margin: .5em 0 .5em .6em; }
#luaref div.classdox { padding: .1em 1em; }
#luaref div.classdox p { margin: .5em 0 .5em .6em; }
#luaref table.classmembers { width: 100%; }
#luaref table.classmembers th { text-align:left; border-bottom:1px solid black; padding-top:1em; }
#luaref table.classmembers td.def { text-align:right; padding-right:.5em; white-space: nowrap; }
#luaref table.classmembers td.decl { text-align:left; padding-left:.5em; white-space: nowrap; }
#luaref table.classmembers td.doc { text-align:left; padding-left:.6em; line-height: 1.2em; font-size:80%; }
#luaref table.classmembers td.doc div.dox {background-color:#eee; padding: .1em 1em; }
#luaref table.classmembers td.doc p { margin: .5em 0; }
#luaref table.classmembers td.doc p.para-brief { font-size:120%; }
#luaref table.classmembers td.doc p.para-returns { font-size:120%; }
#luaref table.classmembers td.doc dl { font-size:120%; line-height: 1.3em; }
#luaref table.classmembers td.doc dt { font-style: italic; }
#luaref table.classmembers td.fill { width: 99%; }
#luaref table.classmembers span.em { font-style: italic; }
#luaref span.functionname abbr { text-decoration:none; cursor:default; }
2017-02-14 08:43:29 -05:00
#luaref table.classmembers td.def abbr { text-decoration:none; cursor:default; }
2016-03-21 14:06:51 -04:00
</ style >
</ head >
< body >
< div class = " header " >
2016-03-26 16:27:13 -04:00
< h2 > Ardour Lua Bindings </ h2 >
2016-03-21 14:06:51 -04:00
< p >
< a href = " #h_classes " > Class Documentation </ a >
& nbsp ; |& nbsp ;
< a href = " #h_enum " > Enum / Constants </ a >
& nbsp ; |& nbsp ;
< a href = " #h_index " > Index </ a >
</ p >
</ div >
2016-03-26 16:27:13 -04:00
2016-04-06 12:23:25 -04:00
<!-- #### SNIP #### !-->
< ? php
} else {
?>
< p class = " warning " >
2016-04-15 17:06:11 -04:00
This documentation is far from complete may be inaccurate and subject to change .
2016-04-06 12:23:25 -04:00
</ p >
< ? php
}
?>
2016-03-26 16:27:13 -04:00
< div id = " luaref " >
2016-03-21 14:06:51 -04:00
2016-03-26 09:55:16 -04:00
< ? php
################################################################################
# some general documentation -- should really go elsehere
?>
2016-03-26 16:27:13 -04:00
< h2 id = " h_intro " > Overview </ h2 >
2016-03-21 16:15:26 -04:00
< p >
2016-03-23 18:46:19 -04:00
The top - level entry point are < ? = typelink ( 'ARDOUR:Session' ) ?> and <?=typelink('ArdourUI:Editor')?>.
2016-03-21 16:15:26 -04:00
Most other Classes are used indirectly starting with a Session function . e . g . Session : get_routes () .
</ p >
< p >
A few classes are dedicated to certain script types , e . g . Lua DSP processors have exclusive access to
< ? = typelink ( 'ARDOUR:DSP' ) ?> and <?=typelink('ARDOUR:ChanMapping')?>. Action Hooks Scripts to
< ? = typelink ( 'LuaSignal:Set' ) ?> etc.
</ p >
< p >
Detailed documentation ( parameter names , method description ) is not yet available . Please stay tuned .
</ p >
2016-03-26 16:27:13 -04:00
< h3 > Short introduction to Ardour classes </ h3 >
2016-03-23 18:46:19 -04:00
< p >
Ardour ' s structure is object oriented . The main object is the Session . A Session contains Audio Tracks , Midi Tracks and Busses .
Audio and Midi tracks are derived from a more general " Track " Object , which in turn is derived from a " Route " ( aka Bus ) .
( We say " An Audio Track <em>is-a</em> Track <em>is-a</em> Route " ) .
Tracks contain specifics . For Example a track < em > has - a </ em > diskstream ( for file i / o ) .
</ p >
< p >
Operations are performed on objects . One gets a reference to an object and then calls a method .
2016-03-25 11:31:16 -04:00
e . g < code > obj = Session : route_by_name ( " Audio " ) obj : set_name ( " Guitar " ) </ code >.
2016-03-23 18:46:19 -04:00
</ p >
< p >
2019-08-23 20:38:14 -04:00
Lua automatically follows C ++ class inheritance . e . g one can directly call all SessionObject and Route methods on Track object . However lua does not automatically promote objects . A Route object which just happens to be a Track needs to be explicitly cast to a Track . Methods for casts are provided with each class . Note that the cast may fail and return a < em > nil </ em > reference .
2016-04-12 07:53:02 -04:00
</ p >
< p >
2019-08-23 20:38:14 -04:00
Likewise multiple inheritance is a < a href = " http://www.lua.org/pil/16.3.html " > non - trivial issue </ a > in Lua . To avoid performance penalties involved with lookups , explicit casts are required in this case . One example is < ? = typelink ( 'ARDOUR:SessionObject' ) ?> which is-a StatefulDestructible which inherits from both Stateful and Destructible.
2016-04-12 07:53:02 -04:00
</ p >
< p >
2016-03-23 18:46:19 -04:00
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 :
you cannot simply remove a track that is currently processing audio . There are various < em > factory </ em > methods for object creation or removal .
</ p >
2016-03-26 16:27:13 -04:00
< h3 > Pass by Reference </ h3 >
2016-03-25 11:31:16 -04:00
< p >
2019-08-23 20:38:14 -04:00
Since Lua functions are closures , C ++ methods that pass arguments by reference cannot be used as - is .
2016-03-25 11:31:16 -04:00
All parameters passed to a C ++ method which uses references are returned as Lua Table .
If the C ++ method also returns a value it is prefixed . Two parameters are returned : the value and a Lua Table holding the parameters .
</ p >
< div class = " code " >
< div style = " float:left; " > C ++
< pre >< code class = " cxx " > void set_ref ( int & amp ; var , long & amp ; val )
{
printf ( " %d %ld \n " , var , val );
var = 5 ;
val = 7 ;
}
</ code ></ pre >
2016-03-26 09:55:16 -04:00
</ div >
2016-03-25 11:31:16 -04:00
< div style = " float:right; " > Lua
< pre >< code class = " lua " > local var = 0 ;
ref = set_ref ( var , 2 );
-- output from C ++ printf ()
</ code >< samp class = " lua " > 0 2 </ samp >< code >
-- var is still 0 here
print ( ref [ 1 ], ref [ 2 ])
</ code >< samp class = " lua " > 5 7 </ samp ></ pre >
2016-03-26 09:55:16 -04:00
</ div >
2016-03-25 11:31:16 -04:00
</ div >
< div class = " clear " ></ div >
< div class = " code " >
< div style = " float:left; " >
< pre >< code class = " cxx " > int set_ref2 ( int & amp ; var , std :: string unused )
{
var = 5 ;
return 3 ;
}
</ code ></ pre >
2016-03-26 09:55:16 -04:00
</ div >
< div style = " float:right; " >
2016-03-25 11:31:16 -04:00
< pre >< code class = " lua " > rv , ref = set_ref2 ( 0 , " hello " );
print ( rv , ref [ 1 ], ref [ 2 ])
</ code >< samp class = " lua " > 3 5 hello </ samp ></ pre >
2016-03-26 09:55:16 -04:00
</ div >
2016-03-25 11:31:16 -04:00
</ div >
< div class = " clear " ></ div >
2016-03-26 16:27:13 -04:00
< h3 > Pointer Classes </ h3 >
2016-03-25 11:31:16 -04:00
< p >
Libardour makes extensive use of reference counted < code > boost :: shared_ptr </ code > to manage lifetimes .
2019-08-23 20:38:14 -04:00
The Lua bindings provide a complete abstraction of this . There are no pointers in Lua .
For example a < ? = typelink ( 'ARDOUR:Route' ) ?> is a pointer in C++, but Lua functions operate on it like it was a class instance.
2016-03-25 11:31:16 -04:00
</ p >
< p >
2019-08-23 20:38:14 -04:00
< code > shared_ptr </ code > are reference counted . Once assigned to a Lua variable , the C ++ object will be kept and remains valid .
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 .
2016-03-25 11:31:16 -04:00
</ p >
< p >
All pointer classes have a < code > isnil () </ code > method . This is for two cases :
Construction may fail . e . g . < code >< ? = typelink ( 'ARDOUR:LuaAPI' ) ?> .newplugin()</code>
may not be able to find the given plugin and hence cannot create an object .
</ p >
< p >
The second case if for < code > boost :: weak_ptr </ code >. As opposed to < code > boost :: shared_ptr </ code > weak - pointers are not reference counted .
The object may vanish at any time .
2019-08-23 20:38:14 -04:00
If Lua code calls a method on a nil object , the interpreter will raise an exception and the script will not continue .
2016-03-25 11:31:16 -04:00
This is not unlike < code > a = nil a : test () </ code > which results in en error " <em>attempt to index a nil value</em> " .
</ p >
< p >
2019-08-23 20:38:14 -04:00
From the Lua side of things there is no distinction between weak and shared pointers . They behave identically .
Below they ' re indicated in orange and have an arrow to indicate the pointer type .
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 .
2016-03-25 11:31:16 -04:00
</ p >
2016-03-21 16:15:26 -04:00
2016-03-21 14:06:51 -04:00
< ? php
2016-03-26 09:55:16 -04:00
#################################
# Main output function -- Classes
2016-03-26 16:27:13 -04:00
echo '<h2 id="h_classes">Class Documentation</h2>' . NL ;
2016-03-21 14:06:51 -04:00
foreach ( $classlist as $ns => $cl ) {
$dups = array ();
$tbl = format_class_members ( $ns , $cl , $dups );
2016-03-26 09:55:16 -04:00
# format class title - depending on type
2016-03-21 14:06:51 -04:00
if ( empty ( $tbl )) {
2016-03-26 09:55:16 -04:00
# classes with no members (no ctor, no methods, no data)
2016-03-26 16:27:13 -04:00
echo '<h3 id="' . htmlentities ( $ns ) . '" class="cls opaque"><abbr title="Opaque Object">∅</abbr> ' . htmlentities ( $ns ) . '</h3>' . NL ;
2016-03-21 14:06:51 -04:00
}
else if ( isset ( $classlist [ $ns ][ 'free' ])) {
2016-03-26 09:55:16 -04:00
# free functions (no class)
2016-03-26 16:27:13 -04:00
echo '<h3 id="' . htmlentities ( $ns ) . '" class="cls freeclass"><abbr title="Namespace">ℕ</abbr> ' . ctorname ( $ns ) . '</h3>' . NL ;
2016-03-21 14:06:51 -04:00
}
else if ( isset ( $classlist [ $ns ][ 'arr' ])) {
2016-03-26 09:55:16 -04:00
# C Arrays
2016-03-26 16:27:13 -04:00
echo '<h3 id="' . htmlentities ( $ns ) . '" class="cls array"><abbr title="C Array">⋯</abbr> ' . htmlentities ( $ns ) . '</h3>' . NL ;
2016-03-21 14:06:51 -04:00
}
else if ( isset ( $classlist [ $ns ][ 'ptr' ])) {
2016-03-26 09:55:16 -04:00
# Pointer Classes
2016-03-26 16:27:13 -04:00
echo '<h3 id="' . htmlentities ( $ns ) . '" class="cls pointerclass"><abbr title="Pointer Class">↠</abbr> ' . htmlentities ( $ns ) . '</h3>' . NL ;
2016-03-26 09:55:16 -04:00
}
else {
# Normal Class
2016-03-26 16:27:13 -04:00
echo '<h3 id="' . htmlentities ( $ns ) . '" class="cls class"><abbr title="Class">∁</abbr> ' . htmlentities ( $ns ) . '</h3>' . NL ;
2016-03-21 14:06:51 -04:00
}
2016-03-26 09:55:16 -04:00
# show original C++ declaration
2016-04-25 07:49:43 -04:00
if ( isset ( $cl [ 'cdecl' ])) {
2016-04-12 18:48:39 -04:00
echo '<p class="cdecl"><em>C‡</em>: ' . htmlentities ( $cl [ 'cdecl' ]) . '</p>' . NL ;
2016-03-21 14:06:51 -04:00
}
2016-03-26 09:55:16 -04:00
# print class inheritance (direct parent *name* only)
2016-03-21 14:06:51 -04:00
$inherited = array ();
2016-03-21 16:15:26 -04:00
$isa = traverse_parent ( $ns , $inherited );
if ( ! empty ( $isa )) {
2016-03-24 17:02:38 -04:00
echo ' <p class="classinfo">is-a: ' . $isa . '</p>' . NL ;
2016-03-21 14:06:51 -04:00
}
echo '<div class="clear"></div>' . NL ;
2016-03-26 09:55:16 -04:00
# class documentation (if any)
2016-03-24 17:02:38 -04:00
echo format_doxyclass ( $cl );
2016-03-21 16:15:26 -04:00
# member documentation
2016-03-21 14:06:51 -04:00
if ( empty ( $tbl )) {
2016-03-24 17:02:38 -04:00
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 ;
2016-03-21 14:06:51 -04:00
} else {
echo '<table class="classmembers">' . NL ;
echo $tbl ;
echo ' </table>' . NL ;
2016-03-20 23:09:01 -04:00
}
2016-03-21 14:06:51 -04:00
2016-03-26 09:55:16 -04:00
# traverse parent classes (all inherited members)
2016-03-21 14:06:51 -04:00
foreach ( $inherited as $pns => $pcl ) {
$tbl = format_class_members ( $pns , $pcl , $dups );
if ( ! empty ( $tbl )) {
2016-03-26 16:27:13 -04:00
echo '<h4 class="cls">Inherited from ' . $pns . '</h4>' . NL ;
2016-03-21 14:06:51 -04:00
echo '<table class="classmembers">' . NL ;
echo $tbl ;
echo '</table>' . NL ;
}
}
}
2016-03-26 09:55:16 -04:00
####################
# Enum and Constants
2016-03-26 16:27:13 -04:00
echo '<h2 id="h_enum">Enum/Constants</h2>' . NL ;
2016-03-21 14:06:51 -04:00
foreach ( $constlist as $ns => $cs ) {
2016-03-26 16:27:13 -04:00
echo '<h3 id="' . ctorname ( $ns ) . '" class="cls enum"><abbr title="Enum">∈</abbr> ' . ctorname ( $ns ) . '</h3>' . NL ;
2016-03-21 14:06:51 -04:00
echo '<ul class="enum">' . NL ;
foreach ( $cs as $c ) {
echo '<li class="const">' . ctorname ( $c [ 'lua' ]) . '</li>' . NL ;
}
echo '</ul>' . NL ;
2016-03-20 23:09:01 -04:00
}
2016-03-26 09:55:16 -04:00
######################
# Index of all classes
2016-03-26 16:27:13 -04:00
echo '<h2 id="h_index" >Class Index</h2>' . NL ;
2016-03-21 16:15:26 -04:00
echo '<ul class="classindex">' . NL ;
2016-03-21 14:06:51 -04:00
foreach ( $classlist as $ns => $cl ) {
2016-03-21 16:15:26 -04:00
echo '<li>' . typelink ( $ns ) . '</li>' . NL ;
2016-03-21 14:06:51 -04:00
}
echo '</ul>' . NL ;
2016-03-26 09:55:16 -04:00
# see how far there is still to go...
2016-03-24 17:02:38 -04:00
fwrite ( STDERR , " Found $dox_found annotations. missing: $dox_miss\n " );
2016-04-10 17:34:00 -04:00
echo '<!-- ' . $dox_found . ' / ' . $dox_miss . ' !-->' . NL ;
2016-03-26 09:55:16 -04:00
2016-03-21 14:06:51 -04:00
?>
</ div >
2016-03-26 16:27:13 -04:00
< div class = " luafooter " > Ardour < ? = $ardourversion ?> - <?=date('r')?></div>
2016-04-06 12:23:25 -04:00
< ? php
2016-03-26 16:27:13 -04:00
2016-04-06 12:23:25 -04:00
if ( $HTMLOUTPUT ) {
echo '<!-- #### SNIP #### !-->' . NL ;
echo '</body>' . NL ;
echo '</html>' . NL ;
}