|
|
|
05-26-2014, 04:50 PM
|
#41
|
Human being with feelings
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
|
Quote:
Originally Posted by WyattRice
Xenakios. Working great! Many thanks!
The Reaper context menu can't be customized, or at least I can't seem to find a way?
Thanks!
|
Nice it's working! But, oh well, right...Looks like the Reaper devs have omitted adding customization to the Help menu. Well, adding the action into that menu from C++ code is IIRC quite tricky...(The purpose of the example plugin wasn't really to have code for something like that.)
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
|
|
|
05-26-2014, 04:58 PM
|
#42
|
Human being with feelings
Join Date: Sep 2009
Location: Virginia
Posts: 2,068
|
Quote:
Originally Posted by Xenakios
Nice it's working! But, oh well, right...Looks like the Reaper devs have omitted adding customization to the Help menu. Well, adding the action into that menu from C++ code is IIRC quite tricky...(The purpose of the example plugin wasn't really to have code for something like that.)
|
No problem at all. You've given me enough to study for a long time.
Thanks, Wyatt
Edit: Glad I was included in your 4000th post.
|
|
|
05-29-2014, 05:18 PM
|
#43
|
Human being with feelings
Join Date: Sep 2009
Location: Virginia
Posts: 2,068
|
Code:
ShellExecuteA(NULL, "open", url_to_launch.c_str(), NULL, NULL, SW_SHOWNORMAL);
Can't seem to get this to work for mac os x. Any ideals?
Thanks, Wyatt
|
|
|
05-30-2014, 05:23 AM
|
#44
|
Human being with feelings
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
|
Quote:
Originally Posted by WyattRice
Code:
ShellExecuteA(NULL, "open", url_to_launch.c_str(), NULL, NULL, SW_SHOWNORMAL);
Can't seem to get this to work for mac os x. Any ideals?
Thanks, Wyatt
|
Maybe ShellExecute instead of ShellExecuteA. (But that won't then compile on Windows if you don't turn Unicode off in the Visual Studio project properties.)
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
|
|
|
05-30-2014, 09:36 AM
|
#45
|
Human being with feelings
Join Date: Sep 2009
Location: Virginia
Posts: 2,068
|
Quote:
Originally Posted by Xenakios
Maybe ShellExecute instead of ShellExecuteA. (But that won't then compile on Windows if you don't turn Unicode off in the Visual Studio project properties.)
|
Hi Xenakios,
I can't get ShellExecute to work at all for osx. I did try and use
Code:
system("open http://www.google.com");
It works to open google, but I can't seem to figure out how to add the resultvec.data() input to that?
|
|
|
05-30-2014, 11:12 AM
|
#46
|
Human being with feelings
Join Date: Sep 2009
Location: Virginia
Posts: 2,068
|
Here's some info from the error using ShellExecute (using Xcode)
Code:
Undefined symbols for architecture i386:
"ShellExecute(HWND__*, char const*, char const*, char const*, char const*, int)", referenced from:
doAction1() in main.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
|
|
|
05-30-2014, 11:27 AM
|
#47
|
Human being with feelings
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
|
Quote:
Originally Posted by WyattRice
Here's some info from the error using ShellExecute (using Xcode)
Code:
Undefined symbols for architecture i386:
"ShellExecute(HWND__*, char const*, char const*, char const*, char const*, int)", referenced from:
doAction1() in main.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
|
I guess you would need to build the relevant WDL/Swell files to get that to work...Can't really offer you much advice on that. (Except that you could try adding the Swell .cpp files into your XCode project, but that might then give errors about missing include files etc...) It's probably best if the system() call is made to work instead.
Maybe something like :
std::string url_to_launch = "open http://www.google.com/search?hl=en&biw=1280&bih=844&as_q=";
... the old stuff here...
system(url_to_launch.c_str());
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
|
|
|
05-30-2014, 12:06 PM
|
#48
|
Human being with feelings
Join Date: Sep 2009
Location: Virginia
Posts: 2,068
|
That was close, but it just opens google home page.
Does this look right?
Code:
void doAction1()
{
const char* dialog_name = "Reaper Google Search";
int howmanyfields = 1;
const char* field_names = "Search Reaper Forums";
int maxreturnlength = 50;
std::vector<char> resultvec(maxreturnlength);
bool proceed=GetUserInputs(dialog_name, howmanyfields, field_names, resultvec.data(), maxreturnlength);
if (proceed == true)
{
std::string url_to_launch = "open http://www.google.com/search?hl=en&biw=1280&bih=844&as_q=";
url_to_launch += resultvec.data();
url_to_launch +="&as_epq=&as_oq=&as_eq=&tbs=&lr=&as_filetype=&ft=i&as_sitesearch=forum.cockos.com&as_qdr=all&as_rights=&as_occt=any&cr=&as_nlo=&as_nhi=&safe=images";
system(url_to_launch.c_str());
}
// resultvec doesn't need to be explicitly freed to avoid a memory leak,
// std::vector cleans up automatically at the end of this function
}
|
|
|
05-30-2014, 12:45 PM
|
#49
|
Human being with feelings
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
|
Quote:
Originally Posted by WyattRice
That was close, but it just opens google home page.
Does this look right?
Code:
void doAction1()
{
const char* dialog_name = "Reaper Google Search";
int howmanyfields = 1;
const char* field_names = "Search Reaper Forums";
int maxreturnlength = 50;
std::vector<char> resultvec(maxreturnlength);
bool proceed=GetUserInputs(dialog_name, howmanyfields, field_names, resultvec.data(), maxreturnlength);
if (proceed == true)
{
std::string url_to_launch = "open http://www.google.com/search?hl=en&biw=1280&bih=844&as_q=";
url_to_launch += resultvec.data();
url_to_launch +="&as_epq=&as_oq=&as_eq=&tbs=&lr=&as_filetype=&ft=i&as_sitesearch=forum.cockos.com&as_qdr=all&as_rights=&as_occt=any&cr=&as_nlo=&as_nhi=&safe=images";
system(url_to_launch.c_str());
}
// resultvec doesn't need to be explicitly freed to avoid a memory leak,
// std::vector cleans up automatically at the end of this function
}
|
Yeah it looks right. Dunno why system() won't do more than open the Google home page.
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
|
|
|
05-30-2014, 02:49 PM
|
#50
|
Human being with feelings
Join Date: Sep 2009
Location: Virginia
Posts: 2,068
|
Don't know exactly what this means, but from the latest WDL swell-functions.h
Code:
** ShellExecute():
** NOTE: currently action is ignored, and it only works on content1 being a URL beginning with http://.
** TODO: finish implementation
*/
|
|
|
06-02-2014, 11:09 AM
|
#51
|
Human being with feelings
Join Date: Sep 2009
Location: Virginia
Posts: 2,068
|
Noobie question again.
I can get the example to build on mac (Xcode) only if I comment out these two lines.
Code:
#include "res.rc_mac_dlg"
#include "res.rc_mac_menu"
Would that have anything to do with shellexecute not working?
Thanks, Wyatt
|
|
|
06-02-2014, 01:20 PM
|
#52
|
Human being with feelings
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
|
Quote:
Originally Posted by WyattRice
Noobie question again.
I can get the example to build on mac (Xcode) only if I comment out these two lines.
Code:
#include "res.rc_mac_dlg"
#include "res.rc_mac_menu"
Would that have anything to do with shellexecute not working?
Thanks, Wyatt
|
No, those lines are junk that I had left by accident in the main.cpp file. If those header files existed to be included, they would be files generated by Justin's little php-script that translates Windows dialog resource files into Cocoa code. But as I intended the example plugin to not use dialogs, those lines are unnecessary.
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
|
|
|
06-04-2014, 02:10 PM
|
#53
|
Human being with feelings
Join Date: Sep 2009
Location: Virginia
Posts: 2,068
|
Another quick question. When I generate a new reaper_plugin_functions header file from the latest Reaper version(4.7pre2) when new api is added, is it correct to add those at the top in the header file?
e.g.
Code:
class WDL_FastString;
class RprMidiTake;
class RprMidiNote;
class screensetNewCallbackFunc;
|
|
|
06-04-2014, 02:42 PM
|
#54
|
Human being with feelings
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
|
Quote:
Originally Posted by WyattRice
Another quick question. When I generate a new reaper_plugin_functions header file from the latest Reaper version(4.7pre2) when new api is added, is it correct to add those at the top in the header file?
e.g.
Code:
class WDL_FastString;
class RprMidiTake;
class RprMidiNote;
class screensetNewCallbackFunc;
|
If the compilation works, it's "correct". screensetNewCallbackFunc is not a class though. I've myself dealt with that by commenting out the line
Code:
REAPERAPI_DECL void (*screenset_registerNew)(char* id, screensetNewCallbackFunc callbackFunc, void* param);
in reaper_plugin_functions.h. This problem should probably be reported to Cockos...
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
|
|
|
11-27-2014, 11:25 PM
|
#55
|
Human being with feelings
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
|
Quote:
Originally Posted by Xenakios
Here's a .zip file that has the earlier version of the main.cpp and a Visual Studio 2013 compatible solution/project file.
http://ge.tt/6MPGEuh1/v/0?c
Hopefully it works...
And sorry, if you are on OS-X, this doesn't really help at all...(I can't produce a working XCode project from my Windows machine.)
|
Sorry if this is a really stupid question. So I downloaded, used Visual Studio to compiled a "release" dll without doing any editing of the code. Where do I place the dll, REAPER main folder? And then how do I test to see if it's working?
__________________
Soundemote - Home of the chaosfly and pretty oscilloscope.
MyReaperPlugin - Easy-to-use cross-platform C++ REAPER extension template
|
|
|
11-28-2014, 04:41 AM
|
#56
|
Human being with feelings
Join Date: Jan 2007
Location: mcr:uk
Posts: 3,891
|
Quote:
Originally Posted by Argitoth
Sorry if this is a really stupid question. So I downloaded, used Visual Studio to compiled a "release" dll without doing any editing of the code. Where do I place the dll, REAPER main folder? And then how do I test to see if it's working?
|
Goes in REAPER/Plugins but I don't know what it does so I don't know how to test it.
Edit: Look to see if the actions were registered.
Code:
// Action default keyboard shortcut and action text set here
// It would be best practice to not assign a default keyboard shortcut
// as the user might already have that same key assigned to something else etc
gaccel_register_t acreg01={{0,0,0},"Simple extension test action"};
gaccel_register_t acreg02={{0,0,0},"Simple extension togglable test action"};
gaccel_register_t acreg03={{0,0,0},"Xenakios : Render variations on selected effect of selected track"};
gaccel_register_t acreg04={{0,0,0},"Xenakios : FX Parameters : Start learn"};
gaccel_register_t acreg05={{0,0,0},"Xenakios : FX Parameters : Finish learn"};
|
|
|
11-28-2014, 06:25 AM
|
#57
|
Human being with feelings
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
|
I compiled the example project, also downloaded the example already-compiled dll, put it in plugins, user plugins, and main folder (to ensure REAPER is seeing it), still don't see "example" or "simple" actions in the action list when I search for those terms.
__________________
Soundemote - Home of the chaosfly and pretty oscilloscope.
MyReaperPlugin - Easy-to-use cross-platform C++ REAPER extension template
|
|
|
11-28-2014, 07:03 AM
|
#58
|
Human being with feelings
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
|
Quote:
Originally Posted by Argitoth
I compiled the example project, also downloaded the example already-compiled dll, put it in plugins, user plugins, and main folder (to ensure REAPER is seeing it), still don't see "example" or "simple" actions in the action list when I search for those terms.
|
As for VST plugins, the rules about 32/64 bit apply, the binary bitness needs to match between the plugin and Reaper. Don't try loading the same plugin dll multiple times, by the way, that might cause more problems instead of solving any...
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
|
|
|
11-28-2014, 07:06 AM
|
#59
|
Human being with feelings
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
|
Oh DUH!
IT'S WORKING!! :') (is there a happycry emote? guess not)
edit: omgomgomg hahahHAHHAAA (insane laughter) *cackle cackle*
HAAHAAAA
__________________
Soundemote - Home of the chaosfly and pretty oscilloscope.
MyReaperPlugin - Easy-to-use cross-platform C++ REAPER extension template
Last edited by Argitoth; 11-28-2014 at 07:25 AM.
|
|
|
11-28-2014, 08:28 AM
|
#60
|
Human being with feelings
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
|
complete Visual Studio noob still... if I run the debugger I get error:
Code:
Unable to start program 'G:\reaperplugin\x64\Debug\reaper_extension_example.dll'.
I just want to do some cout stuff while I code.
__________________
Soundemote - Home of the chaosfly and pretty oscilloscope.
MyReaperPlugin - Easy-to-use cross-platform C++ REAPER extension template
|
|
|
11-28-2014, 08:34 AM
|
#61
|
Human being with feelings
Join Date: Nov 2010
Posts: 2,436
|
Quote:
Originally Posted by Argitoth
complete Visual Studio noob still... if I run the debugger I get error:
Code:
Unable to start program 'G:\reaperplugin\x64\Debug\reaper_extension_example.dll'.
I just want to do some cout stuff while I code.
|
You have to assign it an executable. Go to Solution explorer, right click it to go to Properties->Debugging and set Command to $(REAPER_DIR)\reaper.exe (for REAPER_DIR explanation go to SWS wiki about building...it's always good to have it defined since REAPER will export API into that folder too)
Btw, breakpoints are much better than cout
I hope we see you soon on SWS
|
|
|
11-28-2014, 10:57 AM
|
#62
|
Human being with feelings
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
|
Ok, that solves the error message problem. How about copying the DLL to the REAPER folder?
I did this, but let me know if there's a better way:
create a bat file like this:
Code:
xcopy /y PATH TO DLL GOES HERE\reaper_extension_example.dll PATH TO REAPER FOLDER GOES HERE\reaper_extension_example.dll
Right click on project (e.g. reaper_extension_example) --> properties --> build events --> post build events --> type in path to bat file in Command Line.
__________________
Soundemote - Home of the chaosfly and pretty oscilloscope.
MyReaperPlugin - Easy-to-use cross-platform C++ REAPER extension template
|
|
|
11-28-2014, 10:59 AM
|
#63
|
Human being with feelings
Join Date: Nov 2010
Posts: 2,436
|
If you get SWS from GitHub and check it's properties, under Build Events->Post-Build Event you will see this:
Code:
copy /y "$(OutDir)$(TargetFilename)" "$(REAPER_DIR)\plugins" > NUL
echo Copied to "$(REAPER_DIR)\plugins\$(TargetFilename)"
It's pretty general and it should work for you too.
|
|
|
11-28-2014, 12:02 PM
|
#64
|
Human being with feelings
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
|
Ok, last concern... how do I get started in understanding how to create simple interfaces, like GetUserInputs except... not...?
Edit: More specifically, I'm interested in creating input windows that you don't have to exit to continue working with REAPER. Like imagine Xenakios Auto-Rename dialog except you can re-select items without having to close it and run the action again. Or like Item Properties window. Or any EEL Defer/gui.
__________________
Soundemote - Home of the chaosfly and pretty oscilloscope.
MyReaperPlugin - Easy-to-use cross-platform C++ REAPER extension template
|
|
|
11-28-2014, 12:09 PM
|
#65
|
Human being with feelings
Join Date: Nov 2010
Posts: 2,436
|
Quote:
Originally Posted by Argitoth
Ok, last concern... how do I get started in understanding how to create simple interfaces, like GetUserInputs except... not...?
|
You start by looking and understanding other people's code
Adam.cpp is an excellent place to start since it's simple and small.
But make sure to check other people's code too. I think that BR_TempoDlg.cpp has a lot of useful examples regarding simple win32 dialogs. Not sure if it's beginner friendly, but it has tons of examples.
We also have a separate class for dialogs called SWS_DockWnd from which we inherit and create dockable dialogs. It has a lot of things solved already so it's always a better choice for more complicated dialogs.
|
|
|
11-28-2014, 03:22 PM
|
#66
|
Human being with feelings
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
|
Thanks Breeder! As soon as I can, I would love to contribute to SWS.
__________________
Soundemote - Home of the chaosfly and pretty oscilloscope.
MyReaperPlugin - Easy-to-use cross-platform C++ REAPER extension template
|
|
|
11-28-2014, 05:03 PM
|
#67
|
Human being with feelings
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
|
Translated my read/write EEL scripts to C++. It runs SOOOO much faster (14 seconds compared to 1 second). I am incredibly happy right now. Learning to do this could not have come at a more important time in my career. There is so many things I've been wanting to do that I couldn't (practically) do with python/EEL!!! I'm really excited!
WARNING: noobie code below, and hard-coded file paths.
Code:
void ActionWriteNameList()
{
auto items = CountSelectedMediaItems(0);
if (!items) return;
vector<string> List(items);
auto i = 0; // local counter
for (; i < items; ++i) {
List[i] = GetTakeName(GetActiveTake(GetSelectedMediaItem(0, i)));
List[i] += "\n";
}
List.back().pop_back();
ofstream f("d:\\desktop\\namelist.txt");
for (i = 0; i < items; i++) f << List[i];
f.close();
}
void ActionWriteFileList()
{
auto items = CountSelectedMediaItems(0);
if (!items) return;
vector<string> List(items);
char charbuf[FNLEN];
auto i = 0; //local counter
for (; i < items; ++i) {
GetMediaSourceFileName(GetMediaItemTake_Source(GetActiveTake(GetSelectedMediaItem(0, i))), charbuf, FNLEN);
List[i] = charbuf;
List[i] += "\n";
}
List.back();
ofstream f("d:\\desktop\\filelist.txt");
for (i = 0; i < items; i++) f << List[i];
f.close();
}
void ActionReadList()
{
auto items = CountSelectedMediaItems(0);
if (!items) return;
ifstream f("d:\\desktop\\namelist.txt");
char str[FNLEN];
auto i = 0;
while (!f.eof() && i < items) {
f.getline(str, FNLEN);
GetSetMediaItemTakeInfo_String(GetActiveTake(GetSelectedMediaItem(0,i)),"P_NAME", str, 1);
++i;
}
f.close();
}
__________________
Soundemote - Home of the chaosfly and pretty oscilloscope.
MyReaperPlugin - Easy-to-use cross-platform C++ REAPER extension template
|
|
|
11-28-2014, 09:28 PM
|
#68
|
Human being with feelings
Join Date: Nov 2010
Posts: 2,436
|
I love auto type, it's great for iterators but I'm gonna have to disappoint you - on SWS we can't use C++11 due to OSX compatibility
|
|
|
11-28-2014, 10:29 PM
|
#69
|
Human being with feelings
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
|
Quote:
Originally Posted by Breeder
I love auto type, it's great for iterators but I'm gonna have to disappoint you - on SWS we can't use C++11 due to OSX compatibility
|
not a problem!
Wow, wait... undo points aren't automatically created with plugin extension actions! SWEEET!!!
__________________
Soundemote - Home of the chaosfly and pretty oscilloscope.
MyReaperPlugin - Easy-to-use cross-platform C++ REAPER extension template
|
|
|
11-29-2014, 04:43 PM
|
#70
|
Human being with feelings
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
|
Code:
bool hookCommandProc(int command, int flag) // Reaper calls back to this when it wants to execute an action registered by the extension plugin
{
if (g_registered_command01 && command == g_registered_command01) { ActionWriteNameList(); return true; }
if (g_registered_command02 && command == g_registered_command02) { ActionWriteFileList(); return true; }
if (g_registered_command03 && command == g_registered_command03) { ActionReadList(); return true; }
if (g_registered_command04 && command == g_registered_command04) { ActionNameFilepath(); return true; }
return false; // failed to run relevant action
}
What's going on with this logic? seems redundant.
better question: Should I continue copy/pasting this line of code for every action?
__________________
Soundemote - Home of the chaosfly and pretty oscilloscope.
MyReaperPlugin - Easy-to-use cross-platform C++ REAPER extension template
Last edited by Argitoth; 11-29-2014 at 05:00 PM.
|
|
|
11-29-2014, 06:39 PM
|
#71
|
Human being with feelings
Join Date: Mar 2007
Posts: 21,551
|
Quote:
WARNING: noobie code below, and hard-coded file paths.
|
Hey A,
As someone who failed a few times to get a basic extension running I'm following your adventures with some interest. Can you (if it's not asking too much, I know you have other uses for brain cells at the moment) comment some of those code blocks so I know what I'm looking at? Thanks.
I have a suspicion that if I ever get to that "aha!" moment with C++ I might not get much sleep after that.
|
|
|
11-29-2014, 06:50 PM
|
#72
|
Human being with feelings
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
|
just meet me on skype and I'll help you translate a python or eel script to reaper plugin.
__________________
Soundemote - Home of the chaosfly and pretty oscilloscope.
MyReaperPlugin - Easy-to-use cross-platform C++ REAPER extension template
|
|
|
11-30-2014, 02:13 AM
|
#73
|
Human being with feelings
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
|
QUESTION! In python, if a script fails midway, it screws up the undo block, unless you use the "with undoable" trick. How do you prevent that from happening in C++, or does it just not happen?
Code:
void ActionNameFilepath()
{
items = CountSelectedMediaItems(0);
if (!items) return;
Undo_BeginBlock();
for (i = 0; i < items; ++i) {
take = GetActiveTake(GetSelectedMediaItem(0, i));
GetMediaSourceFileName(GetMediaItemTake_Source(take), charbuf, FNLEN);
GetSetMediaItemTakeInfo_String(take, "P_NAME", charbuf, 1);
}
Undo_EndBlock("Rename selected media item active takes to source filepath", -1);
}
__________________
Soundemote - Home of the chaosfly and pretty oscilloscope.
MyReaperPlugin - Easy-to-use cross-platform C++ REAPER extension template
|
|
|
11-30-2014, 08:12 AM
|
#74
|
Human being with feelings
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
|
Quote:
Originally Posted by Argitoth
QUESTION! In python, if a script fails midway, it screws up the undo block, unless you use the "with undoable" trick. How do you prevent that from happening in C++, or does it just not happen?
Code:
void ActionNameFilepath()
{
items = CountSelectedMediaItems(0);
if (!items) return;
Undo_BeginBlock();
for (i = 0; i < items; ++i) {
take = GetActiveTake(GetSelectedMediaItem(0, i));
GetMediaSourceFileName(GetMediaItemTake_Source(take), charbuf, FNLEN);
GetSetMediaItemTakeInfo_String(take, "P_NAME", charbuf, 1);
}
Undo_EndBlock("Rename selected media item active takes to source filepath", -1);
}
|
The last time (this month) I talked with Justin about the C API undo stuff, he suggested me to use the undo functions that don't use the Undo_BeginBlock() stuff at all. So, for example use just this at the end of a successful action function run :
Code:
Undo_OnStateChange2(0,"Rename selected media item active takes to source filepath");
Note that you have to add the IMPAPI(Undo_OnStateChange2); line into your plugin entrypoint function in order for the function to work.
I think the Undo_BeginBlock/Undo_EndBlock call pairs are mostly useful in the situation when your extension code calls Reaper's built in actions, so that you don't get additional entries into the undo history. If you actually need that, I am not sure how you can cancel the already made Undo_BeginBlock call... :-/ (And I do recall that not making the EndBlock call does cause problems...)
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
|
|
|
11-30-2014, 08:21 AM
|
#75
|
Human being with feelings
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
|
Quote:
Originally Posted by Argitoth
Code:
bool hookCommandProc(int command, int flag) // Reaper calls back to this when it wants to execute an action registered by the extension plugin
{
if (g_registered_command01 && command == g_registered_command01) { ActionWriteNameList(); return true; }
if (g_registered_command02 && command == g_registered_command02) { ActionWriteFileList(); return true; }
if (g_registered_command03 && command == g_registered_command03) { ActionReadList(); return true; }
if (g_registered_command04 && command == g_registered_command04) { ActionNameFilepath(); return true; }
return false; // failed to run relevant action
}
What's going on with this logic? seems redundant.
better question: Should I continue copy/pasting this line of code for every action?
|
The logic is that it first checks the g_registered_command... variable is not zero and then that the command number passed from Reaper matches. (This would just be for safety in case the plugin's action code was not for some reason set properly.) I would these days write this more explicitly : if (g_registered_command01!=0 && command == g_registered_command01) { ... }
If your extension ends up adding tons of new actions, you will probably want to abstract this stuff in some manner. (Have for example a vector of action entries that you then iterate over in the hookCommandProc etc.)
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
|
|
|
11-30-2014, 10:01 AM
|
#76
|
Human being with feelings
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
|
Thanks Xenakios! question stream continues...
I'm trying to use audioaccessor
Code:
// audio accessor
double* buffer = new double[samples];
CreateTakeAudioAccessor(take);
GetAudioAccessorSamples(take, samplerate, channels, skipTime, samples, buffer);
DestroyAudioAccessor(take);
but it seems that CreateTakeAudioAccessor does not return an audioaccessor object, and at the same time if I type "AudioAccessor* accessor" the class AudioAccessor does not exist. So I tried
Code:
PCM_source_transfer_t buffer={0,};
buffer.samplerate = source->GetSampleRate();
buffer.nch = source->GetNumChannels();
buffer.length = source->GetLength();
buffer.samples = new ReaSample[buffer.length * buffer.nch];
buffer.time_s = offset;
source->GetSamples(&buffer);
but i just get an error when running the action.
Code:
Unhandled exception at 0x00007FFEA89A38EC (reaper_extension_example.dll) in reaper.exe: 0xC0000005: Access violation reading location 0x000000000044F000.
The error seems to happen when I try to access the samples.
Code:
v = abs(buffer.samples[s]);
here's the full code:
Code:
void ActionTrimSilence()
{
items = CountSelectedMediaItems(0) ;
if (!items) return;
const u_int n_items = 3;
const char *csv_names = "threshold(dB),threshold(sec),skip first x sec";
char csv_capture[FNLEN] = "-100,.5,.05";
if (GetUserInputs("Trim Silence",n_items,csv_names,csv_capture,FNLEN)) {
vector<string> Input = split(csv_capture, ',');
u_int samplerate, channels, numsamps, speederupper, t, s;
double position, trimSilencePos, length, offset, minAmp, maxTime, skipTime, v;
sprintf(charbuf,"Removing silence of %i items...", items); ShowConsoleMsg(charbuf);
for (i = 0; i < items; ++i) {
// get item info
item = GetSelectedMediaItem(0, i);
position = GetMediaItemInfo_Value(item, "D_POSITION");
length = GetMediaItemInfo_Value(item, "D_LENGTH");
offset = GetMediaItemTakeInfo_Value(take, "D_STARTOFFS");
take = GetActiveTake(item);
source = GetMediaItemTake_Source(take);
// audio accessor
//double* buffer = new double[samples];
//CreateTakeAudioAccessor(take);
// GetAudioAccessorSamples(take, samplerate, channels, skipTime, samples, buffer);
//DestroyAudioAccessor(take);
// Init local transfer block "t" and sum of squares
PCM_source_transfer_t buffer={0,};
buffer.samplerate = source->GetSampleRate();
buffer.nch = source->GetNumChannels();
buffer.length = source->GetLength();
buffer.samples = new ReaSample[buffer.length * buffer.nch];
buffer.time_s = offset;
source->GetSamples(&buffer);
// user values
speederupper = 1;
minAmp = pow(2,stod(Input[0]))/6;
maxTime = stod(Input[1])*buffer.samplerate/speederupper;
skipTime = stod(Input[2]);
numsamps = (length-offset-skipTime)*buffer.samplerate*buffer.nch;
s=0;//sample
t=0;//time
v=0;//value
while (s < numsamps) {
v = abs(buffer.samples[s]);
if (v < minAmp) t+=1;
else t=0;
if (t > maxTime) break;
s+=speederupper;
}
delete[] buffer.samples;
//trimSilencePos = (s-maxTime)/samplerate+offset
trimSilencePos = s/samplerate+offset;
SetMediaItemLength(item, trimSilencePos, 1);
}
ShowConsoleMsg("COMPLETE!\n\n");
}
}
__________________
Soundemote - Home of the chaosfly and pretty oscilloscope.
MyReaperPlugin - Easy-to-use cross-platform C++ REAPER extension template
Last edited by Argitoth; 11-30-2014 at 10:07 AM.
|
|
|
11-30-2014, 10:12 AM
|
#77
|
Human being with feelings
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
|
Quote:
Originally Posted by Argitoth
Code:
PCM_source_transfer_t buffer={0,};
buffer.samplerate = source->GetSampleRate();
buffer.nch = source->GetNumChannels();
buffer.length = source->GetLength();
buffer.samples = new ReaSample[buffer.length * buffer.nch];
buffer.time_s = offset;
source->GetSamples(&buffer);
but i just get an error when running the action.
|
The PCM_source length is in seconds but the length in PCM_source_transfer_t needs to be in samples. (Since the API is designed to read blocks of samples, typically shorter than the whole file.)
So, change it to something like :
buffer.length = source->GetLength()*source->GetSampleRate();
buffer.samples = new ReaSample[buffer.length * buffer.nch];
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
|
|
|
11-30-2014, 10:14 AM
|
#78
|
Human being with feelings
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
|
This thread has gotten quite sidetracked now...I am not sure if these new posts have much to do with the original topic of providing a simple starting point for complete extension programming beginners...
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
|
|
|
11-30-2014, 10:36 AM
|
#79
|
Human being with feelings
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
|
Quote:
Originally Posted by Xenakios
This thread has gotten quite sidetracked now...I am not sure if these new posts have much to do with the original topic of providing a simple starting point for complete extension programming beginners...
|
I didn't need to post all my questions here, I did it on purpose because I figured whoever begins at the first post, and continues to read down will see what I've done, and see the questions I've asked and be better equipped to start creating an extension of their own. If you want me to stop posting questions/info, just say the word!
__________________
Soundemote - Home of the chaosfly and pretty oscilloscope.
MyReaperPlugin - Easy-to-use cross-platform C++ REAPER extension template
|
|
|
11-30-2014, 10:55 AM
|
#80
|
Human being with feelings
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
|
Quote:
Originally Posted by Argitoth
I didn't need to post all my questions here, I did it on purpose because I figured whoever begins at the first post, and continues to read down will see what I've done, and see the questions I've asked and be better equipped to start creating an extension of their own. If you want me to stop posting questions/info, just say the word!
|
Well, you could start a new thread or maybe I'll write about making extension plugins on my blog or somewhere...
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
|
|
|
Thread Tools |
|
Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -7. The time now is 03:49 AM.
|