Go Back   Cockos Incorporated Forums > REAPER Forums > MIDI Hardware, Control Surfaces, and OSC

Reply
 
Thread Tools Display Modes
Old 04-16-2024, 12:18 PM   #25721
Geoff Waddington
Human being with feelings
 
Geoff Waddington's Avatar
 
Join Date: Mar 2009
Location: Dartmouth, Nova Scotia
Posts: 11,473
Default

Some may recall the drag and drop code for the ReMap window was fairly tricky.

In fact, there is separate code for Mac and Windows, PITA.

With the new approach, do we even need drag and drop anymore ?
__________________
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 04-16-2024, 12:19 PM   #25722
jacksoonbrowne
Human being with feelings
 
jacksoonbrowne's Avatar
 
Join Date: Aug 2017
Location: Ottawa, Canada
Posts: 657
Default

Quote:
Originally Posted by Geoff Waddington View Post
Cool, going to do it a bit differently.

Seems strange to have the standalone function int X32GetColorValue(const rgba_color &color) that replaces some of the repeated code, but then in each of the overrides there is this repeated code:

Code:
       lastColor_ = color;

        int surfaceColor = X32GetColorValue(color);

        string oscAddress = "/ch/";
        if (widget_->GetChannelNumber() < 10)   oscAddress += '0';
        oscAddress += int_to_string(widget_->GetChannelNumber()) + "/config/color";
        surface_->SendOSCMessage(this, oscAddress.c_str(), surfaceColor);
No perfect answer here, but I prefer to see all of the code repeated and encapsulated in X32 classes, rather than having it spread out amongst class methods and standalone functions.

Code:
void OSC_X32FeedbackProcessor::SetColorValue(const rgba_color &color)
{
    if (lastColor_ != color)
    {
        lastColor_ = color;

        
        int surfaceColor = 0;
        int r = color.r;
        int g = color.g;
        int b = color.b;
        
        if (r == 64 && g == 64 && b == 64)                               surfaceColor = 8;    // BLACK
        else if (r > g && r > b)                                         surfaceColor = 1;    // RED
        else if (g > r && g > b)                                         surfaceColor = 2;    // GREEN
        else if (abs(r - g) < 30 && r > b && g > b)                      surfaceColor = 3;    // YELLOW
        else if (b > r && b > g)                                         surfaceColor = 4;    // BLUE
        else if (abs(r - b) < 30 && r > g && b > g)                      surfaceColor = 5;    // MAGENTA
        else if (abs(g - b) < 30 && g > r && b > r)                      surfaceColor = 6;    // CYAN
        else if (abs(r - g) < 30 && abs(r - b) < 30 && abs(g - b) < 30)  surfaceColor = 7;    // WHITE
        
        string oscAddress = "/ch/";
        if (widget_->GetChannelNumber() < 10)   oscAddress += '0';
        oscAddress += int_to_string(widget_->GetChannelNumber()) + "/config/color";
        surface_->SendOSCMessage(this, oscAddress.c_str(), surfaceColor);
    }
}
Code:
void OSC_X32IntFeedbackProcessor::SetColorValue(const rgba_color &color)
{
    if (lastColor_ != color)
    {
        lastColor_ = color;

        
        int surfaceColor = 0;
        int r = color.r;
        int g = color.g;
        int b = color.b;
        
        if (r == 64 && g == 64 && b == 64)                               surfaceColor = 8;    // BLACK
        else if (r > g && r > b)                                         surfaceColor = 1;    // RED
        else if (g > r && g > b)                                         surfaceColor = 2;    // GREEN
        else if (abs(r - g) < 30 && r > b && g > b)                      surfaceColor = 3;    // YELLOW
        else if (b > r && b > g)                                         surfaceColor = 4;    // BLUE
        else if (abs(r - b) < 30 && r > g && b > g)                      surfaceColor = 5;    // MAGENTA
        else if (abs(g - b) < 30 && g > r && b > r)                      surfaceColor = 6;    // CYAN
        else if (abs(r - g) < 30 && abs(r - b) < 30 && abs(g - b) < 30)  surfaceColor = 7;    // WHITE
        
        string oscAddress = "/ch/";
        if (widget_->GetChannelNumber() < 10)   oscAddress += '0';
        oscAddress += int_to_string(widget_->GetChannelNumber()) + "/config/color";
        surface_->SendOSCMessage(this, oscAddress.c_str(), surfaceColor);
    }
}
The other alternative would be to put it all in a standalone function, dunno, what do you think ?
What ever you would prefer.
__________________
AKA: Roy Wallingford
jacksoonbrowne is offline   Reply With Quote
Old 04-16-2024, 12:26 PM   #25723
Geoff Waddington
Human being with feelings
 
Geoff Waddington's Avatar
 
Join Date: Mar 2009
Location: Dartmouth, Nova Scotia
Posts: 11,473
Default

Quote:
Originally Posted by jacksoonbrowne View Post
What ever you would prefer.
Yeah, it's a close call, but the standalone function would have to be passed the surface, widget, feedbackProcessor, and colour, so I think the duplicated encapsulated code is slightly better, as it will likely never change, so maintenance isn't really an issue.
__________________
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 04-16-2024, 12:45 PM   #25724
Funkybot
Human being with feelings
 
Funkybot's Avatar
 
Join Date: Jul 2007
Location: New Joisey
Posts: 6,091
Default

Quote:
Originally Posted by Geoff Waddington View Post
Yup, and the option quagmire is sorted too

If you have EnableFocusedFXMapping on (the default), and there is no Zone definition, the ReMap window appears in Learn mode, ready to go.

Buttons at the bottom for AutoMap, EraseLastTouched, RemoveZone, Save, and Cancel, done.
I'm thinking about how this will play out and I'm not sure I love the idea of another window popping up on screen with focused FX mapping on. The windows popping up can get annoying in use. We already had a similar pop up window and nixed it.

I think it's better to have the surface in learn mode or AutoMap mode myself. That will be less intrusive and put the users in control. If AutoMap mode, the FX just maps. No action necessary. If Learn Mode you can Learn or do nothing. But on screen windows popping up can be peevish. I would say keep it as a "remap" for remapping things after the fact.

Also, how would this system work with GoFxSlot+NoMap? Same deal? Again, I would rather the surface do something and AutoMap or jump into Learn mode than an on screen pop-up window.

Just my two cents. I'm open to being wrong on this but I feel like we tried this already and nixed it for similar reasons.
__________________
CSI v3 Wiki
Funkybot is online now   Reply With Quote
Old 04-16-2024, 12:53 PM   #25725
Geoff Waddington
Human being with feelings
 
Geoff Waddington's Avatar
 
Join Date: Mar 2009
Location: Dartmouth, Nova Scotia
Posts: 11,473
Default

Quote:
Originally Posted by Funkybot View Post
I'm thinking about how this will play out and I'm not sure I love the idea of another window popping up on screen with focused FX mapping on. The windows popping up can get annoying in use. We already had a similar pop up window and nixed it.

I think it's better to have the surface in learn mode or AutoMap mode myself. That will be less intrusive and put the users in control. If AutoMap mode, the FX just maps. No action necessary. If Learn Mode you can Learn or do nothing. But on screen windows popping up can be peevish. I would say keep it as a "remap" for remapping things after the fact.

Also, how would this system work with GoFxSlot+NoMap? Same deal? Again, I would rather the surface do something and AutoMap or jump into Learn mode than an on screen pop-up window.

Just my two cents. I'm open to being wrong on this but I feel like we tried this already and nixed it for similar reasons.
Good points all !

The thinking is that if you have Focused FX mapping on and there is no map, you would like to map it, so the window only opens if there is a no map.

Same for GoFXSlot.

Another benefit is for surfaces with low, or even nonexistent button counts, like an extender.

The jury is definitely still out on all of this...

[edit] One thing important to note -- in this new approach the Remap window is Learn mode.
__________________
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

Last edited by Geoff Waddington; 04-16-2024 at 01:38 PM.
Geoff Waddington is offline   Reply With Quote
Old 04-16-2024, 01:59 PM   #25726
jacksoonbrowne
Human being with feelings
 
jacksoonbrowne's Avatar
 
Join Date: Aug 2017
Location: Ottawa, Canada
Posts: 657
Default

Found a problem with Shutdown() when OSC messages per slice is active (message queueing active).
This is not X32 specific.

Code:
void Shutdown()
{
    // We want to stop polling
    shouldRun_ = false;
        
    // Zero out all Widgets before shutting down
    if (pages_.Get(currentPageIndex_))
        pages_.Get(currentPageIndex_)->ForceClear();
}
Because OSC message queueing is on, the ForceClear() will cause immediate queueing of all shutdown messages.

And then Shutdown() returns and Reaper exits before all queued messages have been sent.

What we need is a way to ensure all queued message have been flushed out before Shutdown() returns.

Something like this
Code:
void Shutdown()
{
    // We want to stop polling
    shouldRun_ = false;
        
    // Zero out all Widgets before shutting down
    if (pages_.Get(currentPageIndex_))
        pages_.Get(currentPageIndex_)->ForceClear();

    // PSUEDO CODE HERE
    FOR each OSC surface
    {
        IF queue NOT empty
            SLEEP(100)
    }
}
__________________
AKA: Roy Wallingford
jacksoonbrowne is offline   Reply With Quote
Old 04-16-2024, 02:06 PM   #25727
Geoff Waddington
Human being with feelings
 
Geoff Waddington's Avatar
 
Join Date: Mar 2009
Location: Dartmouth, Nova Scotia
Posts: 11,473
Default

Quote:
Originally Posted by jacksoonbrowne View Post
Found a problem with Shutdown() when OSC messages per slice is active (message queueing active).
This is not X32 specific.

Code:
void Shutdown()
{
    // We want to stop polling
    shouldRun_ = false;
        
    // Zero out all Widgets before shutting down
    if (pages_.Get(currentPageIndex_))
        pages_.Get(currentPageIndex_)->ForceClear();
}
Because OSC message queueing is on, the ForceClear() will cause immediate queueing of all shutdown messages.

And then Shutdown() returns and Reaper exits before all queued messages have been sent.

What we need is a way to ensure all queued message have been flushed out before Shutdown() returns.

Something like this
Code:
void Shutdown()
{
    // We want to stop polling
    shouldRun_ = false;
        
    // Zero out all Widgets before shutting down
    if (pages_.Get(currentPageIndex_))
        pages_.Get(currentPageIndex_)->ForceClear();

    // PSUEDO CODE HERE
    FOR each OSC surface
    {
        IF queue NOT empty
            SLEEP(100)
    }
}
Nice catch !!

Will look into 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 04-16-2024, 02:50 PM   #25728
Geoff Waddington
Human being with feelings
 
Geoff Waddington's Avatar
 
Join Date: Mar 2009
Location: Dartmouth, Nova Scotia
Posts: 11,473
Default

Does this flush the queue properly ?

Code:
    void Shutdown()
    {
        // GAW -- IMPORTANT
        
        // We want to stop polling
        shouldRun_ = false;
        
        // Zero out all Widgets before shutting down
        if (pages_.Get(currentPageIndex_))
        {
            pages_.Get(currentPageIndex_)->ForceClear();
            pages_.Get(currentPageIndex_)->Run(); // To flush queues
        }
    }
__________________
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 04-16-2024, 02:59 PM   #25729
Geoff Waddington
Human being with feelings
 
Geoff Waddington's Avatar
 
Join Date: Mar 2009
Location: Dartmouth, Nova Scotia
Posts: 11,473
Default

Hmmm...

Wondering what it would be like if we reversed the Learn workflow.

Code:
Focus an FX for which there is no map
Learn Window (Remap) appears
Move a surface control
That control is selected in the Learn Window
Move a gui FX control with the mouse
They are linked
What say you ?
__________________
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 04-16-2024, 03:04 PM   #25730
Funkybot
Human being with feelings
 
Funkybot's Avatar
 
Join Date: Jul 2007
Location: New Joisey
Posts: 6,091
Default

Quote:
Originally Posted by Geoff Waddington View Post
Hmmm...

Wondering what it would be like if we reversed the Learn workflow.

Code:
Focus an FX for which there is no map
Learn Window (Remap) appears
Move a control
That control is selected in the Learn Window
Move a gui FX control with the mouse
They are linked
What say you ?
What does that look like on screen? You wouldn't want users having to scroll through a long list of plugin parameters to find what Fader1 is mapped to. Some plugins have hundreds of parameters. Workflow wise it sounds good with my prior concerns about pop up screens remaining.
__________________
CSI v3 Wiki
Funkybot is online now   Reply With Quote
Old 04-16-2024, 03:04 PM   #25731
jacksoonbrowne
Human being with feelings
 
jacksoonbrowne's Avatar
 
Join Date: Aug 2017
Location: Ottawa, Canada
Posts: 657
Default

Quote:
Originally Posted by Geoff Waddington View Post
Does this flush the queue properly ?

Code:
    void Shutdown()
    {
        // GAW -- IMPORTANT
        
        // We want to stop polling
        shouldRun_ = false;
        
        // Zero out all Widgets before shutting down
        if (pages_.Get(currentPageIndex_))
        {
            pages_.Get(currentPageIndex_)->ForceClear();
            pages_.Get(currentPageIndex_)->Run(); // To flush queues
        }
    }
Nope.

I have my Messages Per run set to 16 and when there are more than 16 messages queued, for example 54,
"pages_.Get(currentPageIndex_)->Run();" will only flush 16 messages

Seems we need a way to do multiple Run()'s if the queue is not empty.

Maye something like this:
Code:
    void Shutdown()
    {
        // GAW -- IMPORTANT
        
        // We want to stop polling
        shouldRun_ = false;
        
        // Zero out all Widgets before shutting down
        if (pages_.Get(currentPageIndex_))
        {
            pages_.Get(currentPageIndex_)->ForceClear();
            
            // PSUEDO CODE
            WHILE queue IS NOT EMPTY
                pages_.Get(currentPageIndex_)->Run(); // To flush queues
        }
    }
__________________
AKA: Roy Wallingford
jacksoonbrowne is offline   Reply With Quote
Old 04-16-2024, 03:29 PM   #25732
Geoff Waddington
Human being with feelings
 
Geoff Waddington's Avatar
 
Join Date: Mar 2009
Location: Dartmouth, Nova Scotia
Posts: 11,473
Default

Quote:
Originally Posted by jacksoonbrowne View Post
Nope.

I have my Messages Per run set to 16 and when there are more than 16 messages queued, for example 54,
"pages_.Get(currentPageIndex_)->Run();" will only flush 16 messages

Seems we need a way to do multiple Run()'s if the queue is not empty.

Maye something like this:
Code:
    void Shutdown()
    {
        // GAW -- IMPORTANT
        
        // We want to stop polling
        shouldRun_ = false;
        
        // Zero out all Widgets before shutting down
        if (pages_.Get(currentPageIndex_))
        {
            pages_.Get(currentPageIndex_)->ForceClear();
            
            // PSUEDO CODE
            WHILE queue IS NOT EMPTY
                pages_.Get(currentPageIndex_)->Run(); // To flush queues
        }
    }
Thanks, got it, will continue thinking.

It's tempting to just call Run over and over until the queue is empty, but that likely leads to packet loss when called back to back like that.

Methinks we'll have to keep responding to the Run calls Reaper issues (every 30 msec or so) until the queues are all flushed.
__________________
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 04-16-2024, 03:40 PM   #25733
Geoff Waddington
Human being with feelings
 
Geoff Waddington's Avatar
 
Join Date: Mar 2009
Location: Dartmouth, Nova Scotia
Posts: 11,473
Default

Quote:
Originally Posted by Funkybot View Post
What does that look like on screen? You wouldn't want users having to scroll through a long list of plugin parameters to find what Fader1 is mapped to. Some plugins have hundreds of parameters. Workflow wise it sounds good with my prior concerns about pop up screens remaining.
Say you have an FXLayout that supports Shift+Alt.

Code:
Engage Shift and Alt
Move Fader
Learn Window scrolls the appropriate line into view
Learn Window highlights the Fader on that line
Move gui FX control with mouse
Done
This isn't really a pop up Window, it is the Learn Window, something that you always use whilst mapping, it is non modal and the centerpiece of the whole operation.
__________________
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 04-16-2024, 05:45 PM   #25734
Funkybot
Human being with feelings
 
Funkybot's Avatar
 
Join Date: Jul 2007
Location: New Joisey
Posts: 6,091
Default

That sounds good. I was concerned the param list would be shown then the fader assigned somewhere in the long list. But sounds like that won't be the case. Thanks for explaining.
__________________
CSI v3 Wiki
Funkybot is online now   Reply With Quote
Old 04-16-2024, 06:52 PM   #25735
jacksoonbrowne
Human being with feelings
 
jacksoonbrowne's Avatar
 
Join Date: Aug 2017
Location: Ottawa, Canada
Posts: 657
Default

Quote:
Originally Posted by Geoff Waddington View Post
Thanks, got it, will continue thinking.

It's tempting to just call Run over and over until the queue is empty, but that likely leads to packet loss when called back to back like that.

Methinks we'll have to keep responding to the Run calls Reaper issues (every 30 msec or so) until the queues are all flushed.
Methinks the same
__________________
AKA: Roy Wallingford
jacksoonbrowne is offline   Reply With Quote
Old 04-17-2024, 03:31 AM   #25736
MixMonkey
Human being with feelings
 
MixMonkey's Avatar
 
Join Date: Sep 2017
Location: London, England.
Posts: 4,927
Default

Quote:
Originally Posted by Geoff Waddington View Post
Hmmm...

Wondering what it would be like if we reversed the Learn workflow.

Code:
Focus an FX for which there is no map
Learn Window (Remap) appears
Move a surface control
That control is selected in the Learn Window
Move a gui FX control with the mouse
They are linked
What say you ?
This sounds good to me, providing the ReMap window is going to auto-scroll to the selected control. Then you're setup to do a quick re-name and move on. I'm liking this "Learn from the ReMap window" more and more
MixMonkey is offline   Reply With Quote
Old 04-17-2024, 03:38 AM   #25737
Geoff Waddington
Human being with feelings
 
Geoff Waddington's Avatar
 
Join Date: Mar 2009
Location: Dartmouth, Nova Scotia
Posts: 11,473
Default

Quote:
Originally Posted by MixMonkey View Post
This sounds good to me, providing the ReMap window is going to auto-scroll to the selected control. Then you're setup to do a quick re-name and move on. I'm liking this "Learn from the ReMap window" more and more
Yup it will auto scroll, that's why I'm asking if we can lose drag and drop, the above will be much easier to accomplish if we don't have the added complexity of drag and drop.
__________________
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 04-17-2024, 04:33 AM   #25738
MixMonkey
Human being with feelings
 
MixMonkey's Avatar
 
Join Date: Sep 2017
Location: London, England.
Posts: 4,927
Default

Quote:
Originally Posted by Geoff Waddington View Post
Yup it will auto scroll, that's why I'm asking if we can lose drag and drop, the above will be much easier to accomplish if we don't have the added complexity of drag and drop.
I'm happy to lose drag'n'drop in favor of auto-scroll. Drag'n'drop was never a very efficient way of organising parameters on a surface, because, unless you were very disciplined about it, any change made to the list affected every assignment after it.

To me, auto-scroll on touching a control makes much more sense. A couple of things spring to mind though. If we lose drag'n'drop, then Learn will become the only way to re-organise an AutoMapped plugin. I'm fine with this, providing we have an easy way of deleting a parameter from a control to leave it unassigned (ie NoAction) and that assigning a parameter to an already mapped control overwrites the existing mapping, even if that means you have two controls mapped to the same parameter (unless you want to get into swapping parameters between controls when this condition occurs).
MixMonkey is offline   Reply With Quote
Old 04-17-2024, 05:11 AM   #25739
Geoff Waddington
Human being with feelings
 
Geoff Waddington's Avatar
 
Join Date: Mar 2009
Location: Dartmouth, Nova Scotia
Posts: 11,473
Default

Quote:
Originally Posted by MixMonkey View Post
I'm happy to lose drag'n'drop in favor of auto-scroll. Drag'n'drop was never a very efficient way of organising parameters on a surface, because, unless you were very disciplined about it, any change made to the list affected every assignment after it.

To me, auto-scroll on touching a control makes much more sense. A couple of things spring to mind though. If we lose drag'n'drop, then Learn will become the only way to re-organise an AutoMapped plugin. I'm fine with this, providing we have an easy way of deleting a parameter from a control to leave it unassigned (ie NoAction) and that assigning a parameter to an already mapped control overwrites the existing mapping, even if that means you have two controls mapped to the same parameter (unless you want to get into swapping parameters between controls when this condition occurs).
Cool, I'll put a vote in the yes column for losing drag 'n' drop.

I'm even beginning to question AutoMap itself.

It makes no sense for humongous plugins.

For plugins with a small number of params, it's likely just as quick to Learn as it is to AutoMap and rearrange.

And yes, there will be workflow methods for deleting, editing etc.

We can probably improve editing substantially if there is no drag 'n' drop.

Basically we are switching from surface based mapping Actions, which eat up buttons like crazy, to a purely (mostly ) gui solution.

What do you think ?
__________________
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 04-17-2024, 06:22 AM   #25740
MixMonkey
Human being with feelings
 
MixMonkey's Avatar
 
Join Date: Sep 2017
Location: London, England.
Posts: 4,927
Default

Quote:
Originally Posted by Geoff Waddington View Post
I'm even beginning to question AutoMap itself.
It's a function that's a lot less useful than it initially appears to be. That said, if you get rid of it, you'll be fielding endless requests for its re-instatement, from people who haven't yet realised that it's a lot less useful than it appears to be

Quote:
Basically we are switching from surface based mapping Actions, which eat up buttons like crazy, to a purely (mostly ) gui solution.

What do you think ?
For the purposes of mapping plugins, I think it's fine The buttons are better employed for actually using Reaper, rather than setting it up
MixMonkey is offline   Reply With Quote
Old 04-17-2024, 07:00 AM   #25741
MT4U
Human being with feelings
 
MT4U's Avatar
 
Join Date: Jan 2022
Location: Unifield
Posts: 396
Default

Quote:
Originally Posted by Geoff Waddington View Post
Say you have an FXLayout that supports Shift+Alt.

Code:
Engage Shift and Alt
Move Fader
Learn Window scrolls the appropriate line into view
Learn Window highlights the Fader on that line
Move gui FX control with mouse
Done
This isn't really a pop up Window, it is the Learn Window, something that you always use whilst mapping, it is non modal and the centerpiece of the whole operation.
I believe it's the best approach we've had so far.
__________________

CSI_FX
: SubZone based GUI/Automapper for CSI.(UPD:2024-01-13)
Video Demo/Tutorial
Scripts for CSI: Reaper EEL2 scripts to use with CSI
MT4U is offline   Reply With Quote
Old 04-17-2024, 09:02 AM   #25742
Funkybot
Human being with feelings
 
Funkybot's Avatar
 
Join Date: Jul 2007
Location: New Joisey
Posts: 6,091
Default

The best reasons in favor of keeping Automap is that: for small plugins on displays with surfaces, it's good enough. But additionally: people don't read manuals or wikis. It sets the bar for entry quite low.

I wouldn't use it myself without intending to but it could be a nice gateway into FX mapping for newbies. Sort of a baby step into full blown mapping.
__________________
CSI v3 Wiki
Funkybot is online now   Reply With Quote
Old 04-17-2024, 09:37 AM   #25743
Geoff Waddington
Human being with feelings
 
Geoff Waddington's Avatar
 
Join Date: Mar 2009
Location: Dartmouth, Nova Scotia
Posts: 11,473
Default

Quote:
Originally Posted by Funkybot View Post
The best reasons in favor of keeping Automap is that: for small plugins on displays with surfaces, it's good enough. But additionally: people don't read manuals or wikis. It sets the bar for entry quite low.

I wouldn't use it myself without intending to but it could be a nice gateway into FX mapping for newbies. Sort of a baby step into full blown mapping.
Cool, are you in favour of keeping AutoMap even if we remove drag 'n' drop ?
__________________
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 04-17-2024, 01:18 PM   #25744
Funkybot
Human being with feelings
 
Funkybot's Avatar
 
Join Date: Jul 2007
Location: New Joisey
Posts: 6,091
Default

The Automap code is there, it works. It can even work great on the right plugin. It would be a shame to waste perfectly good code. I say keep it as an options on the Remap window (we need a new name for that methinks).
__________________
CSI v3 Wiki
Funkybot is online now   Reply With Quote
Old 04-17-2024, 07:12 PM   #25745
jacksoonbrowne
Human being with feelings
 
jacksoonbrowne's Avatar
 
Join Date: Aug 2017
Location: Ottawa, Canada
Posts: 657
Default

Hi Geoff,

Need the change in blue, it was sending a float message before, with the change it sends an int message

Code:
void OSC_IntFeedbackProcessor::ForceValue(const PropertyList &properties, double value)
{
    lastDoubleValue_ = value;
    
    surface_->SendOSCMessage(this, oscAddress_.c_str(), (int)value);
}
__________________
AKA: Roy Wallingford

Last edited by jacksoonbrowne; 04-17-2024 at 10:55 PM.
jacksoonbrowne is offline   Reply With Quote
Old 04-17-2024, 08:02 PM   #25746
jacksoonbrowne
Human being with feelings
 
jacksoonbrowne's Avatar
 
Join Date: Aug 2017
Location: Ottawa, Canada
Posts: 657
Default

Hi Geoff,

I merged with the latest source commits as of today and the OSC flush messages on exit almost worked.

Found the issue and fixed it.

In the code below I derived the sleep time from Reapers default Run() refresh interval of ~30 per second (as observed using WireShark), since the CSI OSC implementation does not change the interval.
I did this since my empirical tuning for maxMessages was done using the default refresh interval .

This is what I have for a working change:
Code:
OSC_ControlSurfaceIO::~OSC_ControlSurfaceIO()
{
    int   refreshRateInMs = (1.0/30.0) * 1000;

    while (packetQueue_.GetSize()>=sizeof(int))
    {
        if (maxPacketsPerRun_ > 0)
            Sleep(refreshRateInMs); // Sleep() must be before BeginRun()
        BeginRun();
    }
__________________
AKA: Roy Wallingford

Last edited by jacksoonbrowne; 04-17-2024 at 11:02 PM.
jacksoonbrowne is offline   Reply With Quote
Old 04-18-2024, 03:42 AM   #25747
Geoff Waddington
Human being with feelings
 
Geoff Waddington's Avatar
 
Join Date: Mar 2009
Location: Dartmouth, Nova Scotia
Posts: 11,473
Default

Quote:
Originally Posted by jacksoonbrowne View Post
Hi Geoff,

I merged with the latest source commits as of today and the OSC flush messages on exit almost worked.

Found the issue and fixed it.

In the code below I derived the sleep time from Reapers default Run() refresh interval of ~30 per second (as observed using WireShark), since the CSI OSC implementation does not change the interval.
I did this since my empirical tuning for maxMessages was done using the default refresh interval .

This is what I have for a working change:
Code:
OSC_ControlSurfaceIO::~OSC_ControlSurfaceIO()
{
    int   refreshRateInMs = (1.0/30.0) * 1000;

    while (packetQueue_.GetSize()>=sizeof(int))
    {
        if (maxPacketsPerRun_ > 0)
            Sleep(refreshRateInMs); // Sleep() must be before BeginRun()
        BeginRun();
    }
I recall you saying you only needed 1-2 msec between sends, does this work:

Code:
OSC_ControlSurfaceIO::~OSC_ControlSurfaceIO()
{
    Sleep(10);
    
    int cnt = 0;
    while (packetQueue_.GetSize()>=sizeof(int) && cnt < 100)
    {
        BeginRun();
        if (cnt++) Sleep(10);
    }
...
__________________
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 04-18-2024, 03:43 AM   #25748
Geoff Waddington
Human being with feelings
 
Geoff Waddington's Avatar
 
Join Date: Mar 2009
Location: Dartmouth, Nova Scotia
Posts: 11,473
Default

Quote:
Originally Posted by jacksoonbrowne View Post
Hi Geoff,

Need the change in blue, it was sending a float message before, with the change it sends an int message

Code:
void OSC_IntFeedbackProcessor::ForceValue(const PropertyList &properties, double value)
{
    lastDoubleValue_ = value;
    
    surface_->SendOSCMessage(this, oscAddress_.c_str(), (int)value);
}
Don't see that here, it already looks like your correct fix, I must be missing something, what line of code ?
__________________
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 04-18-2024, 07:54 AM   #25749
Geoff Waddington
Human being with feelings
 
Geoff Waddington's Avatar
 
Join Date: Mar 2009
Location: Dartmouth, Nova Scotia
Posts: 11,473
Default

VERY EXPERIMENTAL PROOF OF CONCEPT
DO NOT USE FOR ANYTHING REMOTELY RESEMBLING PRODUCTION

MAC ONLY NOW -- WINDOWS TO COME

New Exp build is up.

https://stash.reaper.fm/v/42044/CSI%20Exp.zip

Super excited to see what you folks think of this bare bones proof of concept.

Steps:
Code:
Focus a mapped FX
Press button mapped to ReMap
Notice the colour coded layout
Move a surface control
Oh yeah babay !!
Absolutely love the fundamental workflow ideas here.

If this was working you would then move a control on the focused FX gui -- voila !!

Redesigning this is quite a large task, so want to be sure everyone agrees that we're heading in the right direction as we go along this new journey
__________________
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 04-18-2024, 08:47 AM   #25750
fourdogslong
Human being with feelings
 
Join Date: Sep 2023
Posts: 656
Default

Quote:
Originally Posted by Geoff Waddington View Post
VERY EXPERIMENTAL PROOF OF CONCEPT
DO NOT USE FOR ANYTHING REMOTELY RESEMBLING PRODUCTION

MAC ONLY NOW -- WINDOWS TO COME

New Exp build is up.

https://stash.reaper.fm/v/42044/CSI%20Exp.zip

Super excited to see what you folks think of this bare bones proof of concept.

Steps:
Code:
Focus a mapped FX
Press button mapped to ReMap
Notice the colour coded layout
Move a surface control
Oh yeah babay !!
Absolutely love the fundamental workflow ideas here.

If this was working you would then move a control on the focused FX gui -- voila !!

Redesigning this is quite a large task, so want to be sure everyone agrees that we're heading in the right direction as we go along this new journey
I'll keep an eye open for the windows version! Seems interesting.
Thanks
fourdogslong is offline   Reply With Quote
Old 04-18-2024, 12:57 PM   #25751
jacksoonbrowne
Human being with feelings
 
jacksoonbrowne's Avatar
 
Join Date: Aug 2017
Location: Ottawa, Canada
Posts: 657
Default

Quote:
Originally Posted by Geoff Waddington View Post
Don't see that here, it already looks like your correct fix, I must be missing something, what line of code ?
Ooops,

I pasted the wrong code snippet.
So here it is again.

Line 3467 change
Code:
void OSC_IntFeedbackProcessor::ForceClear()
{
    lastDoubleValue_ = 0.0;
    surface_->SendOSCMessage(this, oscAddress_.c_str(), 0.0);
}
Should be
Code:
svoid OSC_IntFeedbackProcessor::ForceClear()
{
    lastDoubleValue_ = 0.0;
    surface_->SendOSCMessage(this, oscAddress_.c_str(), (int)0);
}
__________________
AKA: Roy Wallingford
jacksoonbrowne is offline   Reply With Quote
Old 04-18-2024, 01:15 PM   #25752
Geoff Waddington
Human being with feelings
 
Geoff Waddington's Avatar
 
Join Date: Mar 2009
Location: Dartmouth, Nova Scotia
Posts: 11,473
Default

Quote:
Originally Posted by jacksoonbrowne View Post
Ooops,

I pasted the wrong code snippet.
So here it is again.

Line 3467 change
Code:
void OSC_IntFeedbackProcessor::ForceClear()
{
    lastDoubleValue_ = 0.0;
    surface_->SendOSCMessage(this, oscAddress_.c_str(), 0.0);
}
Should be
Code:
svoid OSC_IntFeedbackProcessor::ForceClear()
{
    lastDoubleValue_ = 0.0;
    surface_->SendOSCMessage(this, oscAddress_.c_str(), (int)0);
}
Thanks, got it, fixed, will commit with the next batch of changes.
__________________
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 04-18-2024, 03:02 PM   #25753
Geoff Waddington
Human being with feelings
 
Geoff Waddington's Avatar
 
Join Date: Mar 2009
Location: Dartmouth, Nova Scotia
Posts: 11,473
Default

Quote:
Originally Posted by Geoff Waddington View Post
VERY EXPERIMENTAL PROOF OF CONCEPT
DO NOT USE FOR ANYTHING REMOTELY RESEMBLING PRODUCTION

MAC ONLY NOW -- WINDOWS TO COME

New Exp build is up.

https://stash.reaper.fm/v/42044/CSI%20Exp.zip

Super excited to see what you folks think of this bare bones proof of concept.

Steps:
Code:
Focus a mapped FX
Press button mapped to ReMap
Notice the colour coded layout
Move a surface control
Oh yeah babay !!
Absolutely love the fundamental workflow ideas here.

If this was working you would then move a control on the focused FX gui -- voila !!

Redesigning this is quite a large task, so want to be sure everyone agrees that we're heading in the right direction as we go along this new journey
C'mon somebody, fire up a Mac, I want to get going on this, it's exciting
__________________
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 04-18-2024, 05:17 PM   #25754
MixMonkey
Human being with feelings
 
MixMonkey's Avatar
 
Join Date: Sep 2017
Location: London, England.
Posts: 4,927
Default

Quote:
Originally Posted by Geoff Waddington View Post
Super excited to see what you folks think of this bare bones proof of concept.

Steps:
Code:
Focus a mapped FX
Press button mapped to ReMap
Notice the colour coded layout
Move a surface control
Oh yeah babay !!
Not seeing anything in the ReMap window here. The FX maps when focused and the controls appear on the C4, but when I open the ReMap window it's blank except for the plugin name.

EDIT: Ok, I was being a numpty, working now. Control turns red when operated, nice! One thing, I use the macOS dark mode and the Rotary/Parameter/Push/Parameter text is black on the dark grey background (apart from when the control is operated, then it turns red) The first column (B1, B2, etc) is correct though (white on dark grey).

Last edited by MixMonkey; 04-18-2024 at 05:41 PM.
MixMonkey is offline   Reply With Quote
Old 04-18-2024, 05:44 PM   #25755
jacksoonbrowne
Human being with feelings
 
jacksoonbrowne's Avatar
 
Join Date: Aug 2017
Location: Ottawa, Canada
Posts: 657
Default

Quote:
Originally Posted by jacksoonbrowne View Post
Hi Geoff,

I merged with the latest source commits as of today and the OSC flush messages on exit almost worked.

Found the issue and fixed it.

In the code below I derived the sleep time from Reapers default Run() refresh interval of ~30 per second (as observed using WireShark), since the CSI OSC implementation does not change the interval.
I did this since my empirical tuning for maxMessages was done using the default refresh interval .

This is what I have for a working change:
Code:
OSC_ControlSurfaceIO::~OSC_ControlSurfaceIO()
{
    int   refreshRateInMs = (1.0/30.0) * 1000;

    while (packetQueue_.GetSize()>=sizeof(int))
    {
        if (maxPacketsPerRun_ > 0)
            Sleep(refreshRateInMs); // Sleep() must be before BeginRun()
        BeginRun();
    }
I recall you saying you only needed 1-2 msec between sends, does this work:

Code:
OSC_ControlSurfaceIO::~OSC_ControlSurfaceIO()
{
    Sleep(10);
    
    int cnt = 0;
    while (packetQueue_.GetSize()>=sizeof(int) && cnt < 100)
    {
        BeginRun();
        if (cnt++) Sleep(10);
    }
...
That won't work properly.

In my case maxMessages is 16 packets per Run() and this is what happens:

cnt is initialized to 0 (NOTE it is post incremented in the while loop)
In the 1st iteration of the while loop
BeginRun() is invoked and 16 packets are sent
cnt is 0, so Sleep() is not invoked
BeginRun() is invoked again without a delay and another 16 packets are immediatley sent for a total burst of 32 packets
In subsequent iterations cnt is true so Sleep() is invoked and proper delays occur

In short, that sequence is: 32-16-16-16 ....

The burst of 32 violates maxMessages of 16 and so the X32 may not process all packets

That's why I modified the code the way I did.

Now as for the delay amount I used in code:

I emperically determined the optimal X32 maxMessages to avoid unhandled packets was 16
This is based on the fact that Run() is invoked ~30 times a second, and so a delay of ~33 milliseconds occurs between each maxMessages burst.
I reasoned it best to use the same maxMessages delay so as to match the destructor timing with the normal runtime timing.


In the loop I also check for maxMessages being 0, and if so, no delay is required

Clear as mud?
__________________
AKA: Roy Wallingford
jacksoonbrowne is offline   Reply With Quote
Old 04-18-2024, 05:49 PM   #25756
Geoff Waddington
Human being with feelings
 
Geoff Waddington's Avatar
 
Join Date: Mar 2009
Location: Dartmouth, Nova Scotia
Posts: 11,473
Default

Quote:
Originally Posted by MixMonkey View Post
Not seeing anything in the ReMap window here. The FX maps when focused and the controls appear on the C4, but when I open the ReMap window it's blank except for the plugin name.

EDIT: Ok, I was being a numpty, working now. Control turns red when operated, nice! One thing, I use the macOS dark mode and the Rotary/Parameter/Push/Parameter text is black on the dark grey background (apart from when the control is operated, then it turns red) The first column (B1, B2, etc) is correct though (white on dark grey).
Thanks for taking the leap.

Lots of work to do with colours, sizing, etc., but we're in flight

Next I want to propose that we replace that crazy busy Edit Param dialog with one that represents only the double clicked cell.

Instead of the 2 or 3 groups that we previously had, only one group will be shown, the one you double clicked on.

That means that on that dialog we'll have space for what was previously on the Advanced dialog.

Unless anyone screams, that's up next
__________________
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 04-18-2024, 05:54 PM   #25757
Geoff Waddington
Human being with feelings
 
Geoff Waddington's Avatar
 
Join Date: Mar 2009
Location: Dartmouth, Nova Scotia
Posts: 11,473
Default

Quote:
Originally Posted by jacksoonbrowne View Post
That won't work properly.

In my case maxMessages is 16 packets per Run() and this is what happens:

cnt is initialized to 0 (NOTE it is post incremented in the while loop)
In the 1st iteration of the while loop
BeginRun() is invoked and 16 packets are sent
cnt is 0, so Sleep() is not invoked
BeginRun() is invoked again without a delay and another 16 packets are immediatley sent for a total burst of 32 packets
In subsequent iterations cnt is true so Sleep() is invoked and proper delays occur

In short, that sequence is: 32-16-16-16 ....

The burst of 32 violates maxMessages of 16 and so the X32 may not process all packets

That's why I modified the code the way I did.

Now as for the delay amount I used in code:

I emperically determined the optimal X32 maxMessages to avoid unhandled packets was 16
This is based on the fact that Run() is invoked ~30 times a second, and so a delay of ~33 milliseconds occurs between each maxMessages burst.
I reasoned it best to use the same maxMessages delay so as to match the destructor timing with the normal runtime timing.


In the loop I also check for maxMessages being 0, and if so, no delay is required

Clear as mud?
OK, how about this ?

Code:
OSC_ControlSurfaceIO::~OSC_ControlSurfaceIO()
{
    Sleep(33);
    
    int cnt = 0;

    while (packetQueue_.GetSize()>=sizeof(int) && cnt < 100)
    {
        BeginRun();
        cnt++;
        if (cnt) 
           Sleep(33);
    }
...
[edit] or maybe this:

Code:
OSC_ControlSurfaceIO::~OSC_ControlSurfaceIO()
{
    Sleep(33);
    
    int cnt = 0;

    while (packetQueue_.GetSize()>=sizeof(int) && cnt++ < 100)
    {
        BeginRun();
        if (cnt) 
           Sleep(33);
    }
...
__________________
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

Last edited by Geoff Waddington; 04-18-2024 at 06:04 PM.
Geoff Waddington is offline   Reply With Quote
Old 04-18-2024, 06:14 PM   #25758
jacksoonbrowne
Human being with feelings
 
jacksoonbrowne's Avatar
 
Join Date: Aug 2017
Location: Ottawa, Canada
Posts: 657
Default

Quote:
Originally Posted by Geoff Waddington View Post
OK, how about this ?

Code:
OSC_ControlSurfaceIO::~OSC_ControlSurfaceIO()
{
    Sleep(33);
    
    int cnt = 0;

    while (packetQueue_.GetSize()>=sizeof(int) && cnt < 100)
    {
        BeginRun();
        cnt++;
        if (cnt) 
           Sleep(33);
    }
...

In the case where maxMessages==0, there is no queuing and hence no need to flush the queue.

So I propose something like this:
Code:
OSC_ControlSurfaceIO::~OSC_ControlSurfaceIO()
{
    if (maxPacketsPerRun_ > 0)
    {
        Sleep(33);
		
        int cnt = 0;

        while (packetQueue_.GetSize()>=sizeof(int) && cnt < 100)
        {
            BeginRun();
            Sleep(33);
            ++cnt 
        }
    }
...
__________________
AKA: Roy Wallingford
jacksoonbrowne is offline   Reply With Quote
Old 04-18-2024, 06:23 PM   #25759
Geoff Waddington
Human being with feelings
 
Geoff Waddington's Avatar
 
Join Date: Mar 2009
Location: Dartmouth, Nova Scotia
Posts: 11,473
Default

Quote:
Originally Posted by jacksoonbrowne View Post
In the case where maxMessages==0, there is no queuing and hence no need to flush the queue.

So I propose something like this:
Code:
OSC_ControlSurfaceIO::~OSC_ControlSurfaceIO()
{
    if (maxPacketsPerRun_ > 0)
    {
        Sleep(33);
		
        int cnt = 0;

        while (packetQueue_.GetSize()>=sizeof(int) && cnt < 100)
        {
            BeginRun();
            Sleep(33);
            ++cnt 
        }
    }
...
Is that really needed ?

The while loop should bail immediately because packetQueue_.GetSize() will be less than sizeof(int).

The only penalty would be a 33 msec delay on shutdown.

I also like the second version a bit more:

Code:
OSC_ControlSurfaceIO::~OSC_ControlSurfaceIO()
{
    Sleep(33);
    
    int count = 0;

    while (packetQueue_.GetSize()>=sizeof(int) && count++ < 100)
    {
        BeginRun();
        if (count) 
           Sleep(33);
    }
...
__________________
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 04-18-2024, 06:42 PM   #25760
jacksoonbrowne
Human being with feelings
 
jacksoonbrowne's Avatar
 
Join Date: Aug 2017
Location: Ottawa, Canada
Posts: 657
Default

Quote:
Originally Posted by Geoff Waddington View Post
Is that really needed ?

The while loop should bail immediately because packetQueue_.GetSize() will be less than sizeof(int).

The only penalty would be a 33 msec delay on shutdown.

I also like the second version a bit more:

Code:
OSC_ControlSurfaceIO::~OSC_ControlSurfaceIO()
{
    Sleep(33);
    
    int count = 0;

    while (packetQueue_.GetSize()>=sizeof(int) && count++ < 100)
    {
        BeginRun();
        if (count) 
           Sleep(33);
    }
...
That works for me

Tested and working
__________________
AKA: Roy Wallingford

Last edited by jacksoonbrowne; 04-18-2024 at 08:12 PM.
jacksoonbrowne 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 05:06 AM.


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