Old 03-01-2017, 02:16 AM   #41
Kyran
Human being with feelings
 
Join Date: Sep 2010
Posts: 49
Default

Thanks for this. Anything specific you had to do to get it to work as a Reaper plugin? Could I just add the two Reaper headers via the Projucer and put the usual Reaper DLL Export function into my main cpp file?

I think I'm already using an old template project of yours, so I don't actually know what goes into building an extension plugin from scratch.

It's kind of a pain to have to add files to the solution via the Projucer, but I guess it's manageable. I assume the jucer file saves the project config and can be archived with Git or whatever. I'd like to make an up-to-date solution template (maybe with unit tests too) that I can clone to start a new plugin.
Kyran is offline   Reply With Quote
Old 03-01-2017, 05:21 AM   #42
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by Kyran View Post
Thanks for this. Anything specific you had to do to get it to work as a Reaper plugin? Could I just add the two Reaper headers via the Projucer and put the usual Reaper DLL Export function into my main cpp file?

I think I'm already using an old template project of yours, so I don't actually know what goes into building an extension plugin from scratch.

It's kind of a pain to have to add files to the solution via the Projucer, but I guess it's manageable. I assume the jucer file saves the project config and can be archived with Git or whatever. I'd like to make an up-to-date solution template (maybe with unit tests too) that I can clone to start a new plugin.
Pretty much the only tricky stuff with this is how to get the JUCE GUI windows to have the Reaper main window as their parent window. Otherwise everything works pretty much the same with regards to both JUCE and Reaper extensions. So if you want to start this from scratch with Projucer, just create a Dynamic Library project and add a .cpp file into your project (either in Projucer or your actual IDE) that defines and exports the Reaper plugin entry point function.

You don't even need to add the Reaper headers into Projucer. The compiler will be able to find them if you just place those headers in some suitable location, like next to your main .cpp files.

It's possible to work so that the Projucer is used only to start the project. Files can later be added and build settings can be changed in the real IDE (Visual Studio or XCode) too. But of course if the Projucer settings need to be changed later and the project files are resaved, the manually done changes in the IDE project files will be lost.
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.

Last edited by Xenakios; 03-01-2017 at 05:27 AM.
Xenakios is offline   Reply With Quote
Old 03-01-2017, 03:24 PM   #43
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

I updated the example to implement an XY fx parameter control instead of using the JUCE web browser, to make the example a bit more relevant for Reaper use. The version with the web browser can of course be retrieved from the Git history.
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
Xenakios is offline   Reply With Quote
Old 03-03-2017, 07:16 AM   #44
Geoff Waddington
Human being with feelings
 
Geoff Waddington's Avatar
 
Join Date: Mar 2009
Location: Dartmouth, Nova Scotia
Posts: 11,183
Default

Hmmm... built a 64 bit version of Xenakios app in Xcode 8.2.1 on OS X 10.12.3 targeted for OS X 10.12.

Running Reaper 5.30/64.

Placed it the correct directory.
This was verified by installing SWS extensions, they work fine in same directory.

Tried signed/unsigned.

No go, would like to place a breakpoint to see what's going on, but can't attach to process, because Reaper has already loaded extensions early during start up, if it sees any.

Any ideas ?
__________________
To install you need the CSI Software and Support Files
For installation instructions and documentation see the Wiki
Donate -- via PayPal to waddingtongeoff@gmail.com
Geoff Waddington is offline   Reply With Quote
Old 03-03-2017, 07:32 AM   #45
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by Geoff Waddington View Post
built a 64 bit version of Xenakios app
Shouldn't be an "app", Reaper extensions are dylibs on macOS. (Have you set Finder to show file extensions so that you can more easily see what kinds of files you are dealing with?)

Quote:
Originally Posted by Geoff Waddington View Post
can't attach to process, because Reaper has already
loaded extensions early during start up, if it sees any.
Don't attempt attaching later, rather use Reaper as the executable to launch when debugging.

You should get to this window from XCode's main menu Product->Scheme :

http://imgur.com/a/vFdNu

I am myself using OS-X 10.11, so I don't know if there's some macOS 10.12 specific problem going on.
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.

Last edited by Xenakios; 03-03-2017 at 08:04 AM.
Xenakios is offline   Reply With Quote
Old 03-03-2017, 10:13 AM   #46
Geoff Waddington
Human being with feelings
 
Geoff Waddington's Avatar
 
Join Date: Mar 2009
Location: Dartmouth, Nova Scotia
Posts: 11,183
Default

Thanks, it was a dylib that was being built, sorry for using the app word

Set up the Scheme (geeez my Xcode chops are rusty, thanks) and am hitting breakpoints galore, but no "extensions" menu shows in Reaper and no extension GUI shows.

I'm probably doing something stupid as usual.
__________________
To install you need the CSI Software and Support Files
For installation instructions and documentation see the Wiki
Donate -- via PayPal to waddingtongeoff@gmail.com
Geoff Waddington is offline   Reply With Quote
Old 03-03-2017, 10:18 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 Geoff Waddington View Post
no "extensions" menu shows in Reaper and no extension GUI shows.
Not supposed to. The example extension does not add any menus or menu items and the GUI is not shown until called from the action the extension adds. (Search for "juce" in the action list window.)
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
Xenakios is offline   Reply With Quote
Old 03-03-2017, 10:31 AM   #48
Geoff Waddington
Human being with feelings
 
Geoff Waddington's Avatar
 
Join Date: Mar 2009
Location: Dartmouth, Nova Scotia
Posts: 11,183
Default

Doh, can see the GUI now, thanks.

Now just have to figure out how to "connect" it to FX, so that it affects it.
__________________
To install you need the CSI Software and Support Files
For installation instructions and documentation see the Wiki
Donate -- via PayPal to waddingtongeoff@gmail.com
Geoff Waddington is offline   Reply With Quote
Old 03-03-2017, 10:33 AM   #49
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by Geoff Waddington View Post
Doh, can see the GUI now, thanks.

Now just have to figure out how to "connect" it to FX, so that it affects it.
Are you looking at the latest code revision in the Git repo? I changed it to have a custom XY control component that changes effect parameters instead of having the JUCE web browser component. (Admittedly a simpler component that just uses for example the JUCE Slider would probably be more helpful...)

I doubt the web browser component can be connected to control anything in Reaper directly via the API. (Which is why the web browser component was a stupid thing to have in the example in the first place.)
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
Xenakios is offline   Reply With Quote
Old 03-03-2017, 10:38 AM   #50
Geoff Waddington
Human being with feelings
 
Geoff Waddington's Avatar
 
Join Date: Mar 2009
Location: Dartmouth, Nova Scotia
Posts: 11,183
Default

Quote:
Originally Posted by Xenakios View Post
Are you looking at the latest code revision in the Git repo? I changed it to have a custom XY control component that changes effect parameters instead of having the JUCE web browser component. (Admittedly a simpler component that just uses for example the JUCE Slider would probably be more helpful...)

I doubt the web browser component can be connected to control anything in Reaper directly via the API. (Which is why the web browser component was a stupid thing to have in the example in the first place.)
Yes, the XY control, the latest in the Git repo
__________________
To install you need the CSI Software and Support Files
For installation instructions and documentation see the Wiki
Donate -- via PayPal to waddingtongeoff@gmail.com
Geoff Waddington is offline   Reply With Quote
Old 03-03-2017, 10:40 AM   #51
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by Geoff Waddington View Post
Yes, the XY control, the latest in the Git repo
If you meant how to use the plugin, right-clicking on the XY control area brings up some relevant options/actions.
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
Xenakios is offline   Reply With Quote
Old 03-03-2017, 10:49 AM   #52
Geoff Waddington
Human being with feelings
 
Geoff Waddington's Avatar
 
Join Date: Mar 2009
Location: Dartmouth, Nova Scotia
Posts: 11,183
Default

Quote:
Originally Posted by Xenakios View Post
If you meant how to use the plugin, right-clicking on the XY control area brings up some relevant options/actions.
OK, all good, got it working, thanks.

This is a great bit of work, thanks for this.
__________________
To install you need the CSI Software and Support Files
For installation instructions and documentation see the Wiki
Donate -- via PayPal to waddingtongeoff@gmail.com
Geoff Waddington is offline   Reply With Quote
Old 03-03-2017, 10:54 AM   #53
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by Geoff Waddington View Post
OK, all good, got it working, thanks.

This is a great bit of work, thanks for this.
To make it more obvious there are options, I added an options button to the window in the latest code revision. (edit : also added code to show tooltips.)
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.

Last edited by Xenakios; 03-03-2017 at 11:25 AM.
Xenakios is offline   Reply With Quote
Old 03-08-2017, 05:01 AM   #54
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Added a filtering line edit for the FX parameter treeview.
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
Xenakios is offline   Reply With Quote
Old 03-18-2017, 05:36 PM   #55
ceanganb
Human being with feelings
 
Join Date: May 2009
Location: Brazil
Posts: 323
Default

Hi, Xenakios. Pretty nice work here.

Toggle state

Code:
add_action("JUCE test : action template", "ACTION_TEMPLATE", ToggleOn,  [](action_entry& ae)
doesn't seem to work. I want to make an action that starts with a shortcut and closes with the same shortcut. Isn't it ´ToggleOn´ supposed to do?
__________________
Ceanganb
ceanganb is offline   Reply With Quote
Old 03-20-2017, 07:30 PM   #56
ceanganb
Human being with feelings
 
Join Date: May 2009
Location: Brazil
Posts: 323
Default

I guess I misunderstood the concept. What I want is to understand the path of an action since it's registered to the point it is executed, but it seems too techy too me.

I see that what is in the lambda above is what's executed when action is run from Reaper. But the action doesn't ´finish´, it's not released from memory when I run it again. In your example, only the Window toggles its state. I do not understand how to exit from the action. I'm investigating the code and I suspect I have to unregister something. Reading code and following its logic melts some areas of my brain
__________________
Ceanganb
ceanganb is offline   Reply With Quote
Old 03-21-2017, 04:21 AM   #57
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by ceanganb View Post
I guess I misunderstood the concept. What I want is to understand the path of an action since it's registered to the point it is executed, but it seems too techy too me.

But the action doesn't ´finish´, it's not released from memory when I run it again.
You will have to deal with the action toggle state(s) yourself.

So implement the action as a function/lambda like :

Code:
void MyAction(action_entry& ae)
{
	if (ae.m_togglestate == ToggleOff)
	{
		ae.m_togglestate = ToggleOn;
		ShowConsoleMsg("The action is on\n");
	}
	else
	{
		ae.m_togglestate = ToggleOff;
		ShowConsoleMsg("The action is off\n");
	}
}
If you have some custom state that needs to be allocated/deallocated etc, you will need to use global or static variables or the void* m_data member of the action_entry passed into the action function.

The toggle stuff doesn't currently report the toggle state back to Reaper, but that's just a visual thing anyway for the toolbar buttons and the action list. (I suppose I could add support for that... edit : Now added.)

Quote:
Originally Posted by ceanganb View Post
In your example, only the Window toggles its state. I do not understand how to exit from the action.
Hmm, I wonder if you are attempting something like this :
Code:
void MyAction(action_entry& ae)
{
  while (ae.m_togglestate == ToggleOn)
  {
     // do stuff
  }
}
That is most certainly not going to work. That would just hang the whole GUI thread (and Reaper) when the action is run. All the action handling stuff runs in the GUI thread. So if you do something like long or infinite loops at any point, that will be bad.
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.

Last edited by Xenakios; 03-21-2017 at 04:42 AM.
Xenakios is offline   Reply With Quote
Old 03-21-2017, 04:45 AM   #58
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Probably buried in the previous reply, so mentioning here : the plugin code now shows a way to deal with the visual action toggle states in Reaper. (Mainly, whether an action toolbar button will be lit or not.)
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
Xenakios is offline   Reply With Quote
Old 03-21-2017, 07:04 PM   #59
ceanganb
Human being with feelings
 
Join Date: May 2009
Location: Brazil
Posts: 323
Default

I really thought that defining the toggle state would automatically reflect in the actions list and also had something to do with the plugin state. Wish there was a better documentation of what can be registered, I couldn't even find information on "hookcommand" but in the forum. I have a lot of work to do to go deeper, but I already learned quite some stuff with your help and guidance.

Thanks, Xenakios.
__________________
Ceanganb
ceanganb is offline   Reply With Quote
Old 03-21-2017, 07:12 PM   #60
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by ceanganb View Post
Wish there was a better documentation of what can be registered, I couldn't even find information on "hookcommand" but in the forum.
If you want to dig in deeper into that stuff, the SWS plugin source code might be more useful. It probably uses most of the available but undocumented/underdocumented things in the API.

The purpose of this JUCE based plugin is mainly just to show a way to get a JUCE GUI window running inside Reaper and have that interacting with the Reaper API.

"hookcommand" is a basic thing to register though, an example of which can be found from the official but severely outdated Reaper extension plugin examples.
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.

Last edited by Xenakios; 03-21-2017 at 07:19 PM.
Xenakios is offline   Reply With Quote
Old 03-21-2017, 07:18 PM   #61
ceanganb
Human being with feelings
 
Join Date: May 2009
Location: Brazil
Posts: 323
Default

Quote:
Originally Posted by Xenakios View Post
If you want to dig in deeper into that stuff, the SWS plugin source code might be more useful. (It probably uses most of the available but undocumented/underdocumented things in the API.) The purpose of this JUCE based plugin is mainly just to show a way to get a JUCE GUI window running inside Reaper and have that interacting with the Reaper API.
Yep, you're right, it's that it got me curious about the details (I can't help!). Apparently, I have enough now to integrate JUCE and Reaper actions, but who knows, I have this disease, a strong desire to know more than it's necessary to accomplish a simple mission
__________________
Ceanganb
ceanganb is offline   Reply With Quote
Old 03-21-2017, 07:35 PM   #62
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by ceanganb View Post
I really thought that defining the toggle state would automatically reflect in the actions list and also had something to do with the plugin state.
Well, the example code was confusing because it didn't do anything with the action toggle state since the toggle state was determined from the window visible property.

The hookcommandproc could toggle the state for the toggleable actions but it would need to take into account that the action callback might not want to allow changing the state immediately etc, so the responsibility of keeping track of the toggle state was left to the action callback functions. Many ways to do these things...
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
Xenakios is offline   Reply With Quote
Old 03-21-2017, 08:00 PM   #63
ceanganb
Human being with feelings
 
Join Date: May 2009
Location: Brazil
Posts: 323
Default

Quote:
Originally Posted by Xenakios View Post
Well, the example code was confusing because it didn't do anything with the action toggle state since the toggle state was determined from the window visible property.

The hookcommandproc could toggle the state for the toggleable actions but it would need to take into account that the action callback might not want to allow changing the state immediately etc, so the responsibility of keeping track of the toggle state was left to the action callback functions. Many ways to do these things...
I was confused for it was too much information for me at once and my first impressions on the code and concept were totally wrong. I can implement it myself now, since I understand better (better only, not well yet) what happens when you register the action and run it.
__________________
Ceanganb
ceanganb is offline   Reply With Quote
Old 03-25-2017, 05:50 AM   #64
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Added another action/window for the plugin. ("JUCE test : Show/hide RubberBand") Possibly useful to get an idea how to implement running time consuming operations in the background without locking up the GUI.
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
Xenakios is offline   Reply With Quote
Old 03-25-2017, 01:55 PM   #65
ceanganb
Human being with feelings
 
Join Date: May 2009
Location: Brazil
Posts: 323
Default

Hi, Xenakios. I have one issue that I really don't know where to research the solution. I'm using your main.cpp code, replacing window names with something meaningful to me. SO I have:

void create_action1_Window(action_entry& ae)
{
(...)
g_action1_window = makeWindow("Action 1 Window", new MainComponent, 600, 400, true, Colours::slategrey);
g_action1_window->m_assoc_action = &ae;
(...)
}

I create a class ´MainComponent´. Now for the strange part, MainComponent derives from Timer. I override timerCallback()and define.

void MainComponent::timerCallback()
{
telogger.setText("something", sendNotification);
};

telogger is a Label. Now the timerCallback is only called when I compile a ´Debug´. If I compile a ´Release´, timerCallback is never called.

do you have any idea why? (Visual Studio 2015 and 2017)
__________________
Ceanganb
ceanganb is offline   Reply With Quote
Old 03-25-2017, 02:04 PM   #66
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by ceanganb View Post
the timerCallback is only called when I compile a ´Debug´. If I compile a ´Release´, timerCallback is never called.

do you have any idea why? (Visual Studio 2015 and 2017)
Maybe you have some uninitialized variable somewhere that really remains uninitialized in release builds. (Debug builds initialize variables to zero or other magic values useful for debugging.) Can't think of anything else really.
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
Xenakios is offline   Reply With Quote
Old 03-26-2017, 04:43 AM   #67
ceanganb
Human being with feelings
 
Join Date: May 2009
Location: Brazil
Posts: 323
Default

Quote:
Originally Posted by Xenakios View Post
Maybe you have some uninitialized variable somewhere that really remains uninitialized in release builds. (Debug builds initialize variables to zero or other magic values useful for debugging.) Can't think of anything else really.
Now the weirdest: neither MultiTimer in your plugin works in release mode here, timers are ignored. Totally lost, guess a new install is mandatory.
__________________
Ceanganb
ceanganb is offline   Reply With Quote
Old 03-26-2017, 04:52 AM   #68
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by ceanganb View Post
Now the weirdest: neither MultiTimer in your plugin works in release mode here, timers are ignored. Totally lost, guess a new install is mandatory.
Oh damn, I am getting the same problem here. I haven't ran the plugin much in release mode, so I've missed this...OK, this is going to be "interesting" to sort out.
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
Xenakios is offline   Reply With Quote
Old 03-26-2017, 05:08 AM   #69
ceanganb
Human being with feelings
 
Join Date: May 2009
Location: Brazil
Posts: 323
Default

Quote:
Originally Posted by Xenakios View Post
Oh damn, I am getting the same problem here. I haven't ran the plugin much in release mode, so I've missed this...OK, this is going to be "interesting" to sort out.
It's interesting because JUCE Vst plugins present no problem with timers in releases.
__________________
Ceanganb
ceanganb is offline   Reply With Quote
Old 03-26-2017, 05:41 AM   #70
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by ceanganb View Post
It's interesting because JUCE Vst plugins present no problem with timers in releases.
Found the bug. The latest git revision has the fix. Thanks for spotting!

The problem was because these are creating the components with the timers before the Juce GUI init calls were made :

Code:
g_xy_wnd = makeWindow("XY Control", new XYContainer, 500, 520, true, Colours::darkgrey);
I don't really understand why there would be a difference how that line behaves in debug and release builds, but it is as if somehow in debug builds the makeWindow function gets to execute the Juce GUI initing before the function call makes the "new XYContainer" call...Or maybe in debug builds Juce does its own GUI initing automatically. Or something.

The reason why the plugin doesn't just simply init the JUCE GUI right in the plugin initialization function is to avoid unnecessary use of memory and CPU resources until they are actually needed.
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
Xenakios is offline   Reply With Quote
Old 03-26-2017, 06:59 AM   #71
ceanganb
Human being with feelings
 
Join Date: May 2009
Location: Brazil
Posts: 323
Default

Quote:
Originally Posted by Xenakios View Post
Found the bug. The latest git revision has the fix. Thanks for spotting!
That was fast, thank you!

Quote:
The reason why the plugin doesn't just simply init the JUCE GUI right in the plugin initialization function is to avoid unnecessary use of memory and CPU resources until they are actually needed.
I agree with that, and also actions with no GUI can be made without waste of resources.
__________________
Ceanganb
ceanganb is offline   Reply With Quote
Old 03-27-2017, 08:08 AM   #72
ceanganb
Human being with feelings
 
Join Date: May 2009
Location: Brazil
Posts: 323
Default

Hi, Xenakios. I was thinking about the commit 1ebde2e, ´Added field to action_entry to tell if the action uses GUI´. I don't know if this is for some future implementation, but it seems not to work as expected for now. If you add an action with a ´false´ flag, it doesn't prevent the function to make a window, but to Window::initGUIifNeeded(). So if I set the flag to ´false´, the only effect it does now is preventing the timers to work again in releases. Looks like the function that's added with ´add_action´ already defines if the action will have a GUI or not. So, for example, I could add an extra check in

Code:
void toggleRubberBandWindow(action_entry& ae)
{
	if ( (g_rubberband_wnd == nullptr) && (ae.m_uses_gui == true) )
	{
		g_rubberband_wnd = makeWindow("RubberBand", new RubberBandGUI, 400, 120, true, Colours::lightgrey);
		g_rubberband_wnd->m_assoc_action = &ae;
	}
	if  (g_rubberband_wnd != nullptr) 
		g_rubberband_wnd->setVisible(!g_rubberband_wnd->isVisible());
}
But then it looks unnecessary, since I did not have to makeWindow in the first place.

Am I missing something?
__________________
Ceanganb
ceanganb is offline   Reply With Quote
Old 03-27-2017, 08:20 AM   #73
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by ceanganb View Post
Am I missing something?
The flag is there simply to avoid doing the JUCE GUI initialization when running actions that don't need it. (In the previous hookcommandproc code, now in on_value_action.) It doesn't enforce anything.

The whole thing is probably kind of redundant, extension plugins using JUCE likely will want to use the JUCE GUI stuff at some point anyway, so avoiding hard making the initialiseJuce_GUI call is probably not that necessary...

edit : Still, it's really a bug in your code if you tell add_action the action is not going to use the GUI and you still do GUI stuff without the initialiseJuce_GUI call...

edit2 : I removed the uses_gui member from action_entry. I actually myself probably introduced a bug previously in the action that doesn't use a window but still would rely on the MessageManager being around. The cost is now that actions that really don't do anything with the JUCE GUI/messagemanager stuff will still initialize those when first run...
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.

Last edited by Xenakios; 03-27-2017 at 08:36 AM.
Xenakios is offline   Reply With Quote
Old 04-01-2017, 09:54 PM   #74
ceanganb
Human being with feelings
 
Join Date: May 2009
Location: Brazil
Posts: 323
Default

Xenakios, I made some changes in ´action_entry´ to embrace other keyboard sections (MIDI Editor, mainly). Looking at SWS code, I made the following changes:

Code:
action_entry::action_entry(string description, string idstring, toggle_state togst, function<void(action_entry&)> func, int kbSecId):
	m_desc(description), m_id_string(idstring), m_func(func), m_togglestate(togst)
{
	if (g_plugin_info != nullptr)
	{
		m_accel_reg.accel = { 0,0,0 };
		if (kbSecId == KS_MAIN)
		{
			m_accel_reg.desc = m_desc.c_str();
			m_command_id = g_plugin_info->Register("command_id", (void*)m_id_string.c_str());
			m_accel_reg.accel.cmd = m_command_id;
			g_plugin_info->Register("gaccel", &m_accel_reg);
		}
		else
		{
			static custom_action_register_t s;
			memset(&s, 0, sizeof(custom_action_register_t));
			s.name = m_desc.c_str();
			s.idStr = m_id_string.c_str();
			s.uniqueSectionId = kbSecId;
			m_command_id = g_plugin_info->Register("custom_action", &s);
		}
	}
}
It works, apparently, first tests went ok. Is it the right way of handling it? Any observations?

I still don't understand why a non-static ´custom_action_register_t´ doesn't work.

Thanks.
__________________
Ceanganb
ceanganb is offline   Reply With Quote
Old 04-02-2017, 05:07 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 ceanganb View Post
Xenakios, I made some changes in ´action_entry´ to embrace other keyboard sections (MIDI Editor, mainly). Looking at SWS code, I made the following changes:

Code:
action_entry::action_entry(string description, string idstring, toggle_state togst, function<void(action_entry&)> func, int kbSecId):
	m_desc(description), m_id_string(idstring), m_func(func), m_togglestate(togst)
{
	if (g_plugin_info != nullptr)
	{
		m_accel_reg.accel = { 0,0,0 };
		if (kbSecId == KS_MAIN)
		{
			m_accel_reg.desc = m_desc.c_str();
			m_command_id = g_plugin_info->Register("command_id", (void*)m_id_string.c_str());
			m_accel_reg.accel.cmd = m_command_id;
			g_plugin_info->Register("gaccel", &m_accel_reg);
		}
		else
		{
			static custom_action_register_t s;
			memset(&s, 0, sizeof(custom_action_register_t));
			s.name = m_desc.c_str();
			s.idStr = m_id_string.c_str();
			s.uniqueSectionId = kbSecId;
			m_command_id = g_plugin_info->Register("custom_action", &s);
		}
	}
}
It works, apparently, first tests went ok. Is it the right way of handling it? Any observations?

I still don't understand why a non-static ´custom_action_register_t´ doesn't work.

Thanks.
I haven't myself worked with the other keyboard sections stuff. However, if I have to guess, Reaper expects the custom_action_register_t object to stay around after the call to Register. (Which it wouldn't if you had just an automatic local variable.) In that case I would expect your static variable is not going to work when you have more than one action using the custom_action_register_t...But does it, is the SWS plugin doing it the same way?
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
Xenakios is offline   Reply With Quote
Old 04-02-2017, 08:47 AM   #76
ceanganb
Human being with feelings
 
Join Date: May 2009
Location: Brazil
Posts: 323
Default

This is where I borrowed the logic from.

Code:
// sws_extension.cpp

int SWSRegisterCmd(COMMAND_T* pCommand, const char* cFile, int cmdId, bool localize)
{
(...)
  if (!pCommand || !pCommand->id || !pCommand->accel.desc || (!pCommand->doCommand && !pCommand->onAction)) return 0;
	if (!pCommand->uniqueSectionId && pCommand->doCommand)
	{
		if (!cmdId) cmdId = plugin_register("command_id", (void*)pCommand->id);
		if (cmdId)
		{
			pCommand->accel.accel.cmd = cmdId; // need to this before registering "gaccel"
			cmdId = (plugin_register("gaccel", &pCommand->accel) ? cmdId : 0);
		}
	}
	else if (pCommand->onAction)
	{
		static custom_action_register_t s;
		memset(&s, 0, sizeof(custom_action_register_t));
		s.idStr = pCommand->id;
		s.name = pCommand->accel.desc;
		s.uniqueSectionId = pCommand->uniqueSectionId;
		cmdId = plugin_register("custom_action", (void*)&s); // will re-use the known cmd ID, if any
	}
	else
		cmdId = 0;
	pCommand->accel.accel.cmd = cmdId;
(...)
SWS plugins sent this COMMAND_T with these two fields:
Code:
void (*doCommand)(COMMAND_T*);
void (*onAction)(COMMAND_T*, int, int, int, HWND);
BR is the only which I found references to onAction, where he uses:

Code:
// BR.cpp
if (nextActionApplyer->doCommand)
    nextActionApplyer->doCommand(nextActionApplyer);
else if (nextActionApplyer->onAction)
    nextActionApplyer->onAction(nextActionApplyer, val, valhw, relmode, hwnd);
A lot of code to check, I can follow the basic path but the whole logic is way beyond me.
__________________
Ceanganb
ceanganb is offline   Reply With Quote
Old 04-02-2017, 09:04 AM   #77
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Well, if the SWS developers have done it that way, I can only guess that's the way it should be done...(And my guess could be wrong.)
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
Xenakios is offline   Reply With Quote
Old 04-02-2017, 09:34 AM   #78
ceanganb
Human being with feelings
 
Join Date: May 2009
Location: Brazil
Posts: 323
Default

C'mon, Xenakios, the guys are good, but you are the codemaster.

Show me the way
__________________
Ceanganb
ceanganb is offline   Reply With Quote
Old 04-02-2017, 09:53 AM   #79
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by ceanganb View Post
C'mon, Xenakios, the guys are good, but you are the codemaster.

Show me the way
Without knowing anything more about how the things are supposed work, I'd myself add the custom_action_register_t instance as a member variable of the action_entry class instead of using the static variable. Static and global variables always have the danger they will mess up things when something needs to have properly separated states...
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
Xenakios is offline   Reply With Quote
Old 04-02-2017, 10:10 AM   #80
ceanganb
Human being with feelings
 
Join Date: May 2009
Location: Brazil
Posts: 323
Default

Quote:
Originally Posted by Xenakios View Post
Without knowing anything more about how the things are supposed work, I'd myself add the custom_action_register_t instance as a member variable of the action_entry class instead of using the static variable. Static and global variables always have the danger they will mess up things when something needs to have properly separated states...
Yes, I did it, but it did not register the action (odd, it seems). I was just kidding, you've done so much already.

Time to bug other guys as well, I'm leaving this thread for further developments on your extension. Thanks so much for your support.
__________________
Ceanganb
ceanganb is offline   Reply With Quote
Reply

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 03:53 AM.


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