Skip to content

Commit

Permalink
added reascript function export
Browse files Browse the repository at this point in the history
  • Loading branch information
elanhickler committed Dec 14, 2015
1 parent a49ccb5 commit 89bb66c
Show file tree
Hide file tree
Showing 7 changed files with 237 additions and 3 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ binary/**
.vs/
*.sdf
*.opensdf
*.opendb

# XCode
xcuserdata/
1 change: 1 addition & 0 deletions Visual Studio/MyReaperPlugin.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
<ClInclude Include="..\library\reaper plugin\reaper_plugin.h" />
<ClInclude Include="..\library\reaper plugin\reaper_plugin_functions.h" />
<ClInclude Include="..\main.hpp" />
<ClInclude Include="..\reascript.hpp" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
Expand Down
1 change: 1 addition & 0 deletions Visual Studio/MyReaperPlugin.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
<ClInclude Include="..\header\MyLiceWindow.h">
<Filter>header</Filter>
</ClInclude>
<ClInclude Include="..\reascript.hpp" />
</ItemGroup>
<ItemGroup>
<Filter Include="library">
Expand Down
9 changes: 6 additions & 3 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ std::shared_ptr<action_entry> add_action(std::string name, std::string id, toggl
return entry;
}

#include "main.hpp" // *** HERE THE ACTIONS DO THEIR WORK ***
#include "main.hpp" /*** HERE THE ACTIONS DO THEIR WORK ***/
#include "reascript.hpp" /*** HERE WE HANDLE REASCRIPT EXPORT FUNCTIONS ***/

// Reaper calls back to this when it wants to execute an action registered by the extension plugin
bool hookCommandProc(int command, int flag) {
Expand Down Expand Up @@ -150,8 +151,10 @@ extern "C"
{
open_lice_dialog(g_parent);
});
rec->Register("hookcommand", (void*)hookCommandProc);
rec->Register("toggleaction", (void*)toggleActionCallback);
if (!rec->Register("hookcommand", (void*)hookCommandProc)) { /*todo: error*/ }
if (!rec->Register("toggleaction", (void*)toggleActionCallback)) { /*todo: error*/ }
if ((!RegisterExportedFuncs(rec) || !RegisterExportedAPI(rec))) { /*todo: error*/ }


if (togact->m_command_id != 0) {
// restore extension global settings
Expand Down
113 changes: 113 additions & 0 deletions reascript.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/******************************************************************************
/ ReaScript.cpp
/
/ Copyright (c) 2012 Jeffos
/
/
/ Permission is hereby granted, free of charge, to any person obtaining a copy
/ of this software and associated documentation files (the "Software"), to deal
/ in the Software without restriction, including without limitation the rights to
/ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
/ of the Software, and to permit persons to whom the Software is furnished to
/ do so, subject to the following conditions:
/
/ The above copyright notice and this permission notice shall be included in all
/ copies or substantial portions of the Software.
/
/ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
/ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
/ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
/ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
/ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
/ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
/ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
/ OTHER DEALINGS IN THE SOFTWARE.
/
******************************************************************************/

/*DEFINE EXPORT FUNCTIONS HERE*/
int AddTwoNumbers(int n1, int n2) { return n1 + n2; }

// Include generated file from reascript_vararg.php
#ifdef _WIN32
#pragma warning(push, 0)
#pragma warning(disable: 4800) // disable "forcing value to bool..." warnings
#endif
#include "reascript_vararg.h"
#ifdef _WIN32
#pragma warning(pop)
#endif

// Important, keep APIFUNC() as it is defined: both scripts reascript_vararg.php
// and reascript_python.pl parse g_apidefs to generate variable argument wrappers
// for EEL and Lua (reascript_vararg.h, automatically generated at compilation time
// on OSX), as well as python wrappers (sws_python.py, automatically generated at
// compilation time both on Win & OSX).

#define APIFUNC(x) (void*)x,#x,(void*)__vararg_ ## x,"APIvararg_" #x "","API_" #x "","APIdef_" #x ""
#define CAPIFUNC(x) (void*)x,#x,NULL,NULL,"API_" #x "",NULL // export to C/C++ only

struct APIdef {
void* func;
const char* func_name;
void* func_vararg;
const char* regkey_vararg;
const char* regkey_func;
const char* regkey_def;
const char* ret_val;
const char* parm_types;

// if additionnal data are needed, add them below (see top remark)
const char* parm_names;
const char* help;
char* dyn_def; // used for dynamic allocations/cleanups
};

// Add functions to array
APIdef g_apidefs[] =
{
{ APIFUNC(AddTwoNumbers), "int", "int,int", "n1,n2", "Add one to input and return the value", },
{ 0, } // denote end of table
};

///////////////////////////////////////////////////////////////////////////////

// register exported functions
bool RegisterExportedFuncs(reaper_plugin_info_t* _rec) {
bool ok = (_rec!=NULL);
int i=-1;
while (ok && g_apidefs[++i].func) {
ok &= (_rec->Register(g_apidefs[i].regkey_func, g_apidefs[i].func) != 0);
if (g_apidefs[i].regkey_vararg && g_apidefs[i].func_vararg) {
ok &= (_rec->Register(g_apidefs[i].regkey_vararg, g_apidefs[i].func_vararg) != 0);
}
}
return ok;
}

// unregister exported functions
void UnregisterExportedFuncs() {
char tmp[512];
int i=-1;
while (g_apidefs[++i].func) {
snprintf(tmp, sizeof(tmp), "-%s", g_apidefs[i].regkey_func);
plugin_register(tmp, g_apidefs[i].func);
}
}

// register exported function definitions (html documentation)
bool RegisterExportedAPI(reaper_plugin_info_t* _rec) {
bool ok = (_rec!=NULL);
int i=-1;
char tmp[8*1024];
while (ok && g_apidefs[++i].func) {
if (g_apidefs[i].regkey_def) {
memset(tmp, 0, sizeof(tmp));
snprintf(tmp, sizeof(tmp), "%s\r%s\r%s\r%s", g_apidefs[i].ret_val, g_apidefs[i].parm_types, g_apidefs[i].parm_names, g_apidefs[i].help);
char* p = g_apidefs[i].dyn_def = _strdup(tmp);
while (*p) { if (*p=='\r') *p='\0'; p++; }
ok &= (_rec->Register(g_apidefs[i].regkey_def, g_apidefs[i].dyn_def) != 0);
}
}
return ok;
}
5 changes: 5 additions & 0 deletions reascript_vararg.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
static void* __vararg_AddTwoNumbers(void** arglist, int numparms)
{
return (void*)(INT_PTR)AddTwoNumbers((int)(INT_PTR)arglist[0], (int)(INT_PTR)arglist[1]);
}

110 changes: 110 additions & 0 deletions reascript_vararg.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<?php
$fp = fopen("./" . $argv[1],"r");
if (!$fp) die("error opening ReaScript.cpp");
$funcs = array();
while (($x=fgets($fp,4096)))
{
$aroffs=-1;
if (preg_match('/\\s*{\\s*APIFUNC_NAMED\\(\\s*(.+?)\\s*,\\s*(.+?)\\s*\\)\\s*,\\s*"(.*?)"\\s*,\\s*"(.*?)"\\s*,\\s*"(.*?)".*$/',$x,$matches))
{
$aroffs=1;
}
else if (preg_match('/\\s*{\\s*APIFUNC\\(\\s*(.+?)\\s*\\)\\s*,\\s*"(.*?)"\\s*,\\s*"(.*?)"\\s*,\\s*"(.*?)".*$/',$x,$matches))
{
$aroffs=0;
}
if ($aroffs >= 0)
{
if (isset($funcs[$matches[1]]))
{
die("#error APIFUNC $matches[1] has duplicate entries\n");
}
if ($matches[1] == "time_precise")
{
continue;
}


$funcs[$matches[1]] = array("func" => $matches[1+$aroffs],
"ret" => $matches[2+$aroffs],
"types" => $matches[3+$aroffs],
"names" => $matches[4+$aroffs]);
}
}
fclose($fp);
//ksort($funcs);
$fp = fopen("./" . $argv[2],"w");
if (!$fp) die("error opening reascript_varag.h");
foreach ($funcs as $name => &$rec)
{
$cfunc = "__vararg_$name";
$names = explode(",",$rec["names"]);
$types = explode(",",$rec["types"]);
if (count($names) != count($types))
{
die("#error $name has mismatched parmname/types\n");
}
$ret_type = $rec["ret"];
$code = "";
$code .= "static void* " . $cfunc . "(void** arglist, int numparms)\n{\n ";
if ($ret_type != "void")
{
if ($ret_type == "double")
{
$code .= "double* p =(double*)arglist[numparms-1];\n";
$code .= " double d = ";
}
else
{
$code .= "return (void*)(INT_PTR)";
}
}
$code .= $name . "(";
$parm_offs = 0;
$next_sz = 0;
$lastreq = 0;
for ($x=0; $x < count($names); $x++)
{
$nm = trim($names[$x]);
$type = trim($types[$x]);
if ($type == "") continue;
if ($type == "int")
{
$code .= "(" . $type . ")(INT_PTR)arglist[" . $x . "]";
}
else if ($type == "double")
{
$code .= "arglist[" . $x . "] ? *(double*)arglist[" . $x . "] : 0.0";
}
else
{
$code .= "(" . $type . ")arglist[" . $x . "]";
}

if ($x < count($names)-1)
{
$code .= ", ";
}
$parm_offs++;
if ($next_sz) $x++;
}
$code .= ");\n";
if ($ret_type == "void")
{
$code .= " return NULL;\n";
}
else if ($ret_type == "double")
{
$code .= " if (p) *p=d;\n";
$code .= " return p;\n";
}
$code .= "}\n\n";
$rec["ret_type"] = $ret_type;
$rec["cfunc"] = $cfunc;
$rec["np"] = max($lastreq+1,1);
$rec["npf"] = $parm_offs;
//echo $code;
fwrite($fp, $code);
}
fclose($fp);
?>

0 comments on commit 89bb66c

Please sign in to comment.