View Single Post
Old 09-21-2012, 02:14 PM   #1016
Jeffos's Avatar
Join Date: Dec 2008
Location: France
Posts: 1,969
Default Export functions to ReaScript

Originally Posted by Jeffos View Post
The 2nd step now is to define HOW we will export things to you..
..especially, for reascript, how to deal with that painful state chunk length limitation. I'll post 2 propositions soon.
Ok, so here are 2 propositions to deal with string limitation in ReaScript and offer better interfaces for c++ plugins.
=> ReaScripters, please let us know what you think!

.. and any other idea welcome, of course!

1) Best solution (but complicated/confusing?)

You would have to deal with strings in a different/indirect way (so that the extension can fully manage memory allocations).
=> no more limit + tighter mem alloc (i.e. just allocating what is needed rather than blocks of 4Mb (even when only 16Kb is needed))

The related APIs would look like:
// [S&M extension] Instanciates a new "fast string" (i.e. WDL_FastString).
// Once the job done, you MUST delete this string, see SNM_DeleteObject.
WDL_FastString* SNM_CreateFastString(const char* str)
//[S&M extension] Gets the "fast string" content as a "standard string".
const char* SNM_GetFastString(WDL_FastString* str)
// [S&M extension] Deletes an object instance.
void SNM_DeleteObject(void* obj)

// [S&M extension] Gets or sets a take's source state. Use takeIdx=-1 to get/alter the active take.
bool SNM_GetSetSourceState(MediaItem* item, int takeIdx, WDL_FastString* state, bool setnewvalue)
- check out SNM_GetSetSourceState(), in compraison with the current beta the "state" param is not a char* but a WDL_FastString*
- "WDL_FastString !?#??" => that name is pretty clear and that's the only thing you need to know
- the other funcs just allow you to deal w/ those "fast strings": create, set the string, get it, delete

ReaScript example. Dumping a source state would look like:
fastStr = SNM_CreateFastString("")
ret = SNM_GetSetSourceState(RPR_GetSelectedMediaItem(0, 0), -1, fastStr, False)
f = open('c:\\test.txt', 'w') # test with a file because RPR_ShowConsoleMsg won't support massive data
^^ this code has been tested with a >16Mb string (cheated w/ a track state, not a source state).

This would be the best solution IMO... this could enable some cool stuff too BUT it is not straight-forward (?)
Note: there's a better way to expose "fast strings" but that would complicate things even more (ctype tricks).

2) "Maxlen" solution (more reascript friendly?)

Like RPR_ funcs, the memory still allocated in a brutal way BUT here you can customize the brutality via a variable, say "SWS_STR_MAXLEN".
When a func uses a "maxlen" param, you would use this SWS_STR_MAXLEN, no matter what (internal value used to allocate ALL strings, i.e. "char*" params - note: "const char*" is something else!).
You could also detect and deal with truncated strings too.

The related APIs would look like:
// [S&M extension] Gets or sets a take's source state.
// Returns <= 0 when the function fails or
// - get: the *real* state length, so if > stateMaxlen => failed
// - set: > 0 if ok
int SNM_GetSetSourceState(MediaItem* item, int takeidx, char* state, int statemaxlen, bool setnewvalue)
^^ There is also a SNM_SetStrMaxlen(n) func that will not be documented (in the html reascript doc) for some reasons.
Basically, it does SWS_STR_MAXLEN=n but this instruction is no-op from your scripts (can't alter an exported global var like that in python, and that's not so bad..).

So, in short, you can read SWS_STR_MAXLEN but, to change it, you have to use SNM_SetStrMaxlen(n)

ReaScript example. Sets a state with a bit better mem alloc and skip possible "overflows":
state = open('c:\\test_in.txt', 'r').read() # say this file contains a 16Mb state
ret = SNM_GetSetTakeSourceState(0, state, SNM_STR_MAXLEN, True)
if ret[0]>0:
   # do some stuff
ReaScript example. Gets a state and detect an "overflow":
ret = SNM_GetSetTakeSourceState(0, "", SNM_STR_MAXLEN, False)
if ret[0]>0 and ret[0]<=SNM_STR_MAXLEN:     # ok! we got a proper state
   open('c:\\test_out.txt', 'w').write(ret[2])
   # do some stuff -OR- 2nd try with the needed realloc: SNM_SetStrMaxlen(ret[0])
- slow/less efficient (but more reascript friendly?)
- it would be important to maintain SWS_STR_MAXLEN as low as possible
- this would apply to SWS funcs only ("RPR_" funcs would still be limited to 4Mb)

2bis) Solution for punks


I have the code for both ideas. I can push this stuff in a beta but the 2 solutions are incompatible..
.. want to try? which one?
Jeffos is offline   Reply With Quote