Old 05-26-2014, 04:50 PM   #41
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by WyattRice View Post
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.
Xenakios is offline  
Old 05-26-2014, 04:58 PM   #42
WyattRice
Human being with feelings
 
WyattRice's Avatar
 
Join Date: Sep 2009
Location: Virginia
Posts: 2,067
Default

Quote:
Originally Posted by Xenakios View Post
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.
__________________
DDP To Cue Writer. | DDP Marker Editor.
WyattRice is offline  
Old 05-29-2014, 05:18 PM   #43
WyattRice
Human being with feelings
 
WyattRice's Avatar
 
Join Date: Sep 2009
Location: Virginia
Posts: 2,067
Default

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
__________________
DDP To Cue Writer. | DDP Marker Editor.
WyattRice is offline  
Old 05-30-2014, 05:23 AM   #44
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by WyattRice View Post
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.
Xenakios is offline  
Old 05-30-2014, 09:36 AM   #45
WyattRice
Human being with feelings
 
WyattRice's Avatar
 
Join Date: Sep 2009
Location: Virginia
Posts: 2,067
Default

Quote:
Originally Posted by Xenakios View Post
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?
__________________
DDP To Cue Writer. | DDP Marker Editor.
WyattRice is offline  
Old 05-30-2014, 11:12 AM   #46
WyattRice
Human being with feelings
 
WyattRice's Avatar
 
Join Date: Sep 2009
Location: Virginia
Posts: 2,067
Default

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)
__________________
DDP To Cue Writer. | DDP Marker Editor.
WyattRice is offline  
Old 05-30-2014, 11:27 AM   #47
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by WyattRice View Post
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.
Xenakios is offline  
Old 05-30-2014, 12:06 PM   #48
WyattRice
Human being with feelings
 
WyattRice's Avatar
 
Join Date: Sep 2009
Location: Virginia
Posts: 2,067
Default

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
}
__________________
DDP To Cue Writer. | DDP Marker Editor.
WyattRice is offline  
Old 05-30-2014, 12:45 PM   #49
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by WyattRice View Post
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.
Xenakios is offline  
Old 05-30-2014, 02:49 PM   #50
WyattRice
Human being with feelings
 
WyattRice's Avatar
 
Join Date: Sep 2009
Location: Virginia
Posts: 2,067
Default

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
*/
__________________
DDP To Cue Writer. | DDP Marker Editor.
WyattRice is offline  
Old 06-02-2014, 11:09 AM   #51
WyattRice
Human being with feelings
 
WyattRice's Avatar
 
Join Date: Sep 2009
Location: Virginia
Posts: 2,067
Default

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
__________________
DDP To Cue Writer. | DDP Marker Editor.
WyattRice is offline  
Old 06-02-2014, 01:20 PM   #52
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by WyattRice View Post
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.
Xenakios is offline  
Old 06-04-2014, 02:10 PM   #53
WyattRice
Human being with feelings
 
WyattRice's Avatar
 
Join Date: Sep 2009
Location: Virginia
Posts: 2,067
Default

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;
__________________
DDP To Cue Writer. | DDP Marker Editor.
WyattRice is offline  
Old 06-04-2014, 02:42 PM   #54
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by WyattRice View Post
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.
Xenakios is offline  
Old 11-27-2014, 11:25 PM   #55
Argitoth
Human being with feelings
 
Argitoth's Avatar
 
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
Default

Quote:
Originally Posted by Xenakios View Post
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
Argitoth is offline  
Old 11-28-2014, 04:41 AM   #56
IXix
Human being with feelings
 
Join Date: Jan 2007
Location: mcr:uk
Posts: 3,889
Default

Quote:
Originally Posted by Argitoth View Post
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"};
IXix is offline  
Old 11-28-2014, 06:25 AM   #57
Argitoth
Human being with feelings
 
Argitoth's Avatar
 
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
Default

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
Argitoth is offline  
Old 11-28-2014, 07:03 AM   #58
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by Argitoth View Post
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.
Xenakios is offline  
Old 11-28-2014, 07:06 AM   #59
Argitoth
Human being with feelings
 
Argitoth's Avatar
 
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
Default

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.
Argitoth is offline  
Old 11-28-2014, 08:28 AM   #60
Argitoth
Human being with feelings
 
Argitoth's Avatar
 
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
Default

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
Argitoth is offline  
Old 11-28-2014, 08:34 AM   #61
Breeder
Human being with feelings
 
Breeder's Avatar
 
Join Date: Nov 2010
Posts: 2,436
Default

Quote:
Originally Posted by Argitoth View Post
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
Breeder is offline  
Old 11-28-2014, 10:57 AM   #62
Argitoth
Human being with feelings
 
Argitoth's Avatar
 
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
Default

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
Argitoth is offline  
Old 11-28-2014, 10:59 AM   #63
Breeder
Human being with feelings
 
Breeder's Avatar
 
Join Date: Nov 2010
Posts: 2,436
Default

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.
Breeder is offline  
Old 11-28-2014, 12:02 PM   #64
Argitoth
Human being with feelings
 
Argitoth's Avatar
 
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
Default

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
Argitoth is offline  
Old 11-28-2014, 12:09 PM   #65
Breeder
Human being with feelings
 
Breeder's Avatar
 
Join Date: Nov 2010
Posts: 2,436
Default

Quote:
Originally Posted by Argitoth View Post
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.
Breeder is offline  
Old 11-28-2014, 03:22 PM   #66
Argitoth
Human being with feelings
 
Argitoth's Avatar
 
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
Default

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
Argitoth is offline  
Old 11-28-2014, 05:03 PM   #67
Argitoth
Human being with feelings
 
Argitoth's Avatar
 
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
Default

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
Argitoth is offline  
Old 11-28-2014, 09:28 PM   #68
Breeder
Human being with feelings
 
Breeder's Avatar
 
Join Date: Nov 2010
Posts: 2,436
Default

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
Breeder is offline  
Old 11-28-2014, 10:29 PM   #69
Argitoth
Human being with feelings
 
Argitoth's Avatar
 
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
Default

Quote:
Originally Posted by Breeder View Post
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
Argitoth is offline  
Old 11-29-2014, 04:43 PM   #70
Argitoth
Human being with feelings
 
Argitoth's Avatar
 
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
Default

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.
Argitoth is offline  
Old 11-29-2014, 06:39 PM   #71
Lawrence
Human being with feelings
 
Join Date: Mar 2007
Posts: 21,551
Default

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.
Lawrence is offline  
Old 11-29-2014, 06:50 PM   #72
Argitoth
Human being with feelings
 
Argitoth's Avatar
 
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
Default

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
Argitoth is offline  
Old 11-30-2014, 02:13 AM   #73
Argitoth
Human being with feelings
 
Argitoth's Avatar
 
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
Default

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
Argitoth is offline  
Old 11-30-2014, 08:12 AM   #74
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by Argitoth View Post
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.
Xenakios is offline  
Old 11-30-2014, 08:21 AM   #75
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by Argitoth View Post
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.
Xenakios is offline  
Old 11-30-2014, 10:01 AM   #76
Argitoth
Human being with feelings
 
Argitoth's Avatar
 
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
Default

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.
Argitoth is offline  
Old 11-30-2014, 10:12 AM   #77
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by Argitoth View Post

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.
Xenakios is offline  
Old 11-30-2014, 10:14 AM   #78
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

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.
Xenakios is offline  
Old 11-30-2014, 10:36 AM   #79
Argitoth
Human being with feelings
 
Argitoth's Avatar
 
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
Default

Quote:
Originally Posted by Xenakios View Post
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
Argitoth is offline  
Old 11-30-2014, 10:55 AM   #80
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by Argitoth View Post
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.
Xenakios is offline  
Closed Thread

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 04:04 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.