Old 12-02-2015, 04:35 AM   #281
maranite
Human being with feelings
 
Join Date: Apr 2015
Posts: 10
Default Thanks Xenakios

Xenakios - thanks for your response. Over the past few months, I've studied the SWS source code and managed to produce an extension of my own, but right now I'm stumped...

Is there any way for a reaper extension to:

1) Enumerate the bindings of MIDI CC's to FX parameters for a track?
and/or
2) Intercept in-bound MIDI messages on an open MidiInput, and transmit messages on an in-use MidiOutput?


My use case:
============

Like most MIDI controllers, the Arturia Keylab's driver presents a MIDI in & out port, which reapers uses to communicate with the board.

I want my extension to detect that a knob movement (MIDI CC) is affecting an FX Parameter, so that when automation events / track selection changes occur, that my extension can transmit back to the keyboard what the new "positions" (CC values) for each knob are.

To achieve this, the extension needs:

1) To know what FX parameter is bound to a given Midi CC, for each track.
2) To be able to transmit Midi messages back to the keyboard when an appropriate OSC event occurs.


If there's a different / better way to achieve the desired outcome (i.e. communicating with the board as if it was a bi-directional control surface), I'd love to hear the suggestions.
maranite is offline   Reply With Quote
Old 04-25-2016, 01:38 PM   #282
Renoized
Human being with feelings
 
Join Date: Apr 2016
Posts: 32
Default

Is there any way to ignore play/pause commands?
Renoized is offline   Reply With Quote
Old 09-01-2016, 06:26 PM   #283
trigger303
Human being with feelings
 
Join Date: Nov 2015
Posts: 15
Default Can I send / receive on Fx?

Hi.

I'd like to exchange audio / MIDI between Fx and Tracks.


So, is Fx able to -

- send audio / MIDI to other track?

- fetch audio / MIDI from other track's output channel?


Best regards,

--
trigger303
trigger303 is offline   Reply With Quote
Old 01-18-2017, 05:06 PM   #284
SpiderFox
Human being with feelings
 
Join Date: Jan 2017
Posts: 29
Default

How can I execute a function directly after Reaper was fully loaded?
SpiderFox is offline   Reply With Quote
Old 01-18-2017, 07:09 PM   #285
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by SpiderFox View Post
How can I execute a function directly after Reaper was fully loaded?
That will probably involve some hack with a timer and hoping it will work correctly most of the time. (There is no timer in the Reaper API, you will have to use the operating system API for that.)
__________________
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 01-18-2017, 08:25 PM   #286
karbomusic
Human being with feelings
 
karbomusic's Avatar
 
Join Date: May 2009
Posts: 29,260
Default

Typically in windows GUIs there is a 'loaded' event. I'm assuming the API doesn't expose it but to call a function as soon as fully loaded, that's the way to do it.
__________________
Music is what feelings sound like.
karbomusic is offline   Reply With Quote
Old 01-18-2017, 08:56 PM   #287
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by karbomusic View Post
Typically in windows GUIs there is a 'loaded' event. I'm assuming the API doesn't expose it but to call a function as soon as fully loaded, that's the way to do it.
The API does expose the Reaper main window HWND, so maybe something can be done with that, but argh...What a pain. Also there's no guarantee what works on Windows can easily be made to work on macOS too.

IMHO the Reaper API overall should get more callback/event style functionality. (Also for ReaScript.)
__________________
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 08-13-2017, 12:29 PM   #288
millitone
Human being with feelings
 
Join Date: Nov 2011
Posts: 8
Default

TL;DR. The name of the extension matters. Call your extension "reaper_YourNameHere.dll", or it won't run.

I tried to create my own extension from scratch based on the "ninjamloop" code, and spent hours trying to make it just do *something* - so I changed every bit of the code and every setting in VS to match the ninjamloop code, which ran perfectly btw, and my own project seemingly did not run at all.

So I tried to copy the structure of Xenakios reaper_juce_extension project, which also ran perfectly - and my dll still did not. Very strange.

When I FINALLY understood that reaper only loads dll's with "reaper_" as prefix I think I wanted to throw the computer out the window.. <- (that's a forced smiley!)
millitone is offline   Reply With Quote
Old 01-18-2018, 03:34 PM   #289
sai'ke
Human being with feelings
 
sai'ke's Avatar
 
Join Date: Aug 2009
Location: NL
Posts: 1,453
Default

Is there a way to set the "send as channel" option for a MIDI item from script?

P.S. I know how to edit the channel of notes, but I want to set them to different values than what I want to send the MIDI data out as.
sai'ke is offline   Reply With Quote
Old 01-18-2018, 03:41 PM   #290
cfillion
Human being with feelings
 
cfillion's Avatar
 
Join Date: May 2015
Location: Québec, Canada
Posts: 4,937
Default

Yes, by editing the item's chunk manually. The "Send as channel" property from the item properties is stored as "OUTCH" in the chunk.

GetItemStateChunk & SetItemStateChunk
cfillion is offline   Reply With Quote
Old 01-20-2018, 05:12 AM   #291
sai'ke
Human being with feelings
 
sai'ke's Avatar
 
Join Date: Aug 2009
Location: NL
Posts: 1,453
Default

Many thanks! That works great
sai'ke is offline   Reply With Quote
Old 01-20-2018, 10:46 AM   #292
fundorin
Banned
 
Join Date: Feb 2014
Location: Moscow, Russia
Posts: 554
Default

How do I properly add extra Reaper API functions into csurf.h and csurf_main.cpp files?
The official Reaper extentions SDK files are from 2009 and there were lots of api functions added, since.

For example, I need to send
Undo_DoRedo2(ReaProject* proj)
and
Undo_DoUndo2(ReaProject* proj)
on midi commands from the surface.

Simply adding int (*Undo_DoUndo2)(); line to csurf_main.cpp and extern int (*Undo_DoUndo2)(ReaProject *proj); to csurf.h didn't work. I followed the way of how other functions were declared in those files.


UPD. My csurf.h additions:

csurf_main.cpp:

csurf_sl.cpp:


Pressing the assigned button throws exception error in VS:


Calling CSurf_OnPlay() function, that was already present in both .h and .cpp files, works fine, when called by the surface.

Last edited by fundorin; 01-20-2018 at 11:27 AM.
fundorin is offline   Reply With Quote
Old 01-20-2018, 12:14 PM   #293
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by fundorin View Post
How do I properly add extra Reaper API functions into csurf.h and csurf_main.cpp files?
Do you also initialize the function pointers? (With the IMPAPI macro.)
__________________
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 01-20-2018, 12:25 PM   #294
fundorin
Banned
 
Join Date: Feb 2014
Location: Moscow, Russia
Posts: 554
Default

Quote:
Originally Posted by Xenakios View Post
Do you also initialize the function pointers? (With the IMPAPI macro.)
You're right. I've totally forgot about it, though I've checked it in my memory, while making a text search through all files with "CSurf_OnPlay" line. Now, both Undo and Redo commands are working fine. Thanks!
fundorin is offline   Reply With Quote
Old 01-20-2018, 02:08 PM   #295
Lawrence
Human being with feelings
 
Join Date: Mar 2007
Posts: 21,551
Default

Quote:
Originally Posted by karbomusic View Post
Typically in windows GUIs there is a 'loaded' event. I'm assuming the API doesn't expose it but to call a function as soon as fully loaded, that's the way to do it.
You guys are way ahead of me obviously, but I had the same thought and had (in other languages) done much the same, maybe run a loop until the hwnd exists, to trigger something after load.

The only issue (other than not being a good coder) was trying to figure out if that should literally happen as soon as the hwnd exists or if there is another thing to parse for to know if app is "fully loaded", as opposed to it having only just created it's main window.

Am I wrong in assuming (different topic) that the C++ API is no longer really needed in Reaper now with all of the various scripting choices or are there still things that only C++ approach can handle?
Lawrence is offline   Reply With Quote
Old 01-20-2018, 02:17 PM   #296
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by Lawrence View Post
You guys are way ahead of me obviously, but I had the same thought and had (in other languages) done much the same, maybe run a loop until the hwnd exists, to trigger something after load.

Am I wrong in assuming (different topic) that the C++ API is no longer really needed in Reaper now with all of the various scripting choices or are there still things that only C++ approach can handle?
It's not as easy as running a loop because running such a loop in the GUI thread (the extension plugins are loaded in the GUI thread) would block the GUI event loop from running and possibly prevent creating the windows in the first place. (It could be done from another thread but that causes additional problems to deal with.)

Many advanced things still require writing C++ plugins, the scripting API is not a complete replacement.
__________________
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 01-20-2018, 02:29 PM   #297
fundorin
Banned
 
Join Date: Feb 2014
Location: Moscow, Russia
Posts: 554
Default

How do I send a sysex command to the surface from CSurf plugin?
Which part of the cpp file should I use, so that command will always be sent after midi port open/reopen?
fundorin is offline   Reply With Quote
Old 01-21-2018, 04:07 PM   #298
fundorin
Banned
 
Join Date: Feb 2014
Location: Moscow, Russia
Posts: 554
Default

How do I make Reaper to include SWS extension's functions into reaper_plugin_functions header, while generating it with "[developer] Write C++ API functions header" action?

Cause the header doesn't have those extra functions, I get the following error, when trying to compile the csurf plugin:



UPD. Adding those extra functions by hand into csurf_main.cpp (before extern "C" part) solved the issue, but I would like to have those SWS functions generated automatically into the main header or some extra file with an action, in Reaper.


UPD2. Aaaaand... I ended up with thrown exception error, while trying to use that function:



UPD3. Adding the following lines helped:
Code:
#define IMPAPI(x) if (!((*((void **)&(x)) = (void *)rec->GetFunc(#x)))) errcnt++;

	IMPAPI(BR_GetPrevGridDivision)
	IMPAPI(BR_GetNextGridDivision)

Last edited by fundorin; 01-21-2018 at 04:35 PM.
fundorin is offline   Reply With Quote
Old 01-24-2018, 02:43 PM   #299
sai'ke
Human being with feelings
 
sai'ke's Avatar
 
Join Date: Aug 2009
Location: NL
Posts: 1,453
Default

Is there a way to get the resolution of the hosts main screen from LUA? I want to spawn a window in a specific corner of the screen.
sai'ke is offline   Reply With Quote
Old 01-25-2018, 02:31 AM   #300
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by sai'ke View Post
Is there a way to get the resolution of the hosts main screen from LUA? I want to spawn a window in a specific corner of the screen.
Not the greatest solution but you could call this OS command on Windows and parse the resulting text:
Code:
wmic desktopmonitor get screenheight, screenwidth
Which will be like
Code:
ScreenHeight  ScreenWidth
1080          1920
edit : On Mac Os you can use :
Code:
system_profiler SPDisplaysDataType |grep Resolution
Which results in something like :
Code:
Resolution: 2880 x 1800 Retina
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.

Last edited by Xenakios; 01-25-2018 at 06:28 AM.
Xenakios is offline   Reply With Quote
Old 01-25-2018, 09:22 AM   #301
Meo-Ada Mespotine
Human being with feelings
 
Meo-Ada Mespotine's Avatar
 
Join Date: May 2017
Location: Leipzig
Posts: 6,621
Default

Quote:
Originally Posted by sai'ke View Post
Is there a way to get the resolution of the hosts main screen from LUA? I want to spawn a window in a specific corner of the screen.
Maybe the my_getViewport-function might help you. Justin explained in this thread, how it works:

https://forum.cockos.com/showthread.php?t=195629

If you want to know the dimensions of the Reaper-Window itself within Lua, then you're out of luck. You can get the HWND, but can't get it's properties, unfortunately...
Meo-Ada Mespotine is offline   Reply With Quote
Old 01-27-2018, 03:52 PM   #302
sai'ke
Human being with feelings
 
sai'ke's Avatar
 
Join Date: Aug 2009
Location: NL
Posts: 1,453
Default

Thanks Xenakios and mespotine!
sai'ke is offline   Reply With Quote
Old 01-28-2018, 11:07 AM   #303
fundorin
Banned
 
Join Date: Feb 2014
Location: Moscow, Russia
Posts: 554
Default

How do I send and receive sysex midi messages (more than 3 bytes) within CSurf plugin?

I've found some related code inside mini SDK sources (babyhui.cpp) and Padre's Automap csurf plugin.
The thing is that Padre's plugin is tied with Automap SDK, to which I don't have access, and babyhui.cpp confuses me SYSEX_TRACKTITLE_LEN variable, which is set to 13, while the resulting sysex message would be much longer.

Here's the code from babyhui.cpp that I'm trying to adapt to my project.
It should display track's title on the surface's LCD, presumably, though I couldn't find any type of display in Mackie's Baby HUI photos.
Even if I would be able to do that successfully, there would still be a need to not only send sysex messages in my plugin, but also to receive them. I need help from someone experienced, here.

Code:
  void SetTrackTitleImpl(int trackid, const char* title)
  {
    if (m_midiout && trackid >= 0 && trackid < 256) {
      #define SYSEX_TRACKTITLE_LEN 13
      unsigned char sysex[SYSEX_TRACKTITLE_LEN] = { 0xF0, 0x00, 0x00, 0x66, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF7 };
      sysex[7] = trackid;
      int i, len = (title?strlen(title):0);
      for (i = 0; i < min(len, 4) && title[i]; ++i) {
        sysex[8+i] = title[i];
      }
      
      char buf[sizeof(MIDI_event_t)+SYSEX_TRACKTITLE_LEN];
      MIDI_event_t* msg = (MIDI_event_t*) buf;
      msg->frame_offset = -1;
      msg->size = SYSEX_TRACKTITLE_LEN;
      memcpy(msg->midi_message, sysex, SYSEX_TRACKTITLE_LEN);
      m_midiout->SendMsg(msg, -1);
    }
  }
fundorin is offline   Reply With Quote
Old 01-28-2018, 07:44 PM   #304
fundorin
Banned
 
Join Date: Feb 2014
Location: Moscow, Russia
Posts: 554
Default

I've created a new method inside csurf_main.cpp's class threadedMIDIOutput and called it SendStr.

Code:
    virtual void SendStr(unsigned char *sysexMsg)
    {
        len = sysexMsg::size;

        MIDI_event_t evt->frame_offset = 0;
        MIDI_event_t evt->size = len;

        for (int i = 0; i <= len; i++)
        {
            MIDI_event_t evt->midi_message[i] = sysexMsg[i];
        }
        SendMsg(&evt, 0);
    }
Code as a picture: https://i.imgur.com/yEDmYFL.png

Then, I'm trying to call this method with the following code:

Code:
unsigned char automapOnline[] = { 0xF0, 0x00, 0x20, 0x29, 0x03, 0x03, 0x12, 0x00, 0x02, 0x00, 0x01, 0x01, 0xF7 };

    m_midiout->SendStr(automapOnline);
As a picture: https://i.imgur.com/tCXo6PO.png


Changed size of midi_message array from 4 to 512.
Code:
typedef struct
{
  int frame_offset;
  int size; // bytes used by midi_message, can be >3, but should never be <3, even if a short 1 or 2 byte msg
  unsigned char midi_message[512]; // size is number of bytes valid -- can be more than 4!
} MIDI_event_t;
As a picture: https://i.imgur.com/lbrsXGN.png

reaper_plugin.h addition at line 1031:
Code:
virtual void SendStr(unsigned char *sysexMsg) = 0; // frame_offset can be <0 for "instant" if supported
As picture: https://i.imgur.com/U3guYnl.png

I'm running it in my csurf plugin at Reaper start.
And immediately getting an error on debug.
The task is to send sysex message from the csurf plugin to the midi controller.
What am I doing wrong here?
fundorin is offline   Reply With Quote
Old 01-30-2018, 05:16 PM   #305
fundorin
Banned
 
Join Date: Feb 2014
Location: Moscow, Russia
Posts: 554
Default

Which Reaper API function will allow me to get metronome enabled/disabled state from Reaper?
fundorin is offline   Reply With Quote
Old 01-30-2018, 05:26 PM   #306
cfillion
Human being with feelings
 
cfillion's Avatar
 
Join Date: May 2015
Location: Québec, Canada
Posts: 4,937
Default

You could check the state of the action Options: Toggle metronome:

Code:
GetToggleCommandState(40364)
cfillion is offline   Reply With Quote
Old 01-31-2018, 09:30 AM   #307
fundorin
Banned
 
Join Date: Feb 2014
Location: Moscow, Russia
Posts: 554
Default

Quote:
Originally Posted by cfillion View Post
You could check the state of the action Options: Toggle metronome:

Code:
GetToggleCommandState(40364)
Thanks. This worked fine. BTW, do you know what does flag argument means in Main_OnCommand method?

I'm also getting exception error when trying to request peak meter value, like:

Code:
int curVU = volToChar(Track_GetPeakInfo(tr, 0));
or simply
Code:
double curVU = Track_GetPeakInfo(tr, 0);
getting tr (track id) before with
Code:
int tid = 1;
MediaTrack *tr = CSurf_TrackFromID(tid, false);
UPD.

Last edited by fundorin; 01-31-2018 at 09:38 AM.
fundorin is offline   Reply With Quote
Old 01-31-2018, 10:40 AM   #308
nofish
Human being with feelings
 
nofish's Avatar
 
Join Date: Oct 2007
Location: home is where the heart is
Posts: 12,096
Default

^^ Regarding the exception, wouldn't you need to check if tr isn't a null pointer there (if project / bank contains less than eight tracks).

edit:
Ok, your last code should work nevertheless if at least one track in project I think.

Last edited by nofish; 01-31-2018 at 10:48 AM.
nofish is offline   Reply With Quote
Old 01-31-2018, 10:49 AM   #309
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by fundorin View Post
I'm also getting exception error when trying to request peak meter value, like:
Maybe Track_GetPeakInfo API function wasn't imported properly?
__________________
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 01-31-2018, 11:09 AM   #310
fundorin
Banned
 
Join Date: Feb 2014
Location: Moscow, Russia
Posts: 554
Default

Quote:
Originally Posted by Xenakios View Post
Maybe Track_GetPeakInfo API function wasn't imported properly?
I've solved this issue by checking if the track, for which I'm requesting peak level, is actually exists in the project.
Code:
        else // Live VU meters
        {
            for (int i = 0; i < 8; i++)
            {
                int tid = (i + 1) + (bankTrackSel * 8);
                
                if (tid <= CountTracks(0))
                {
                    MediaTrack *tr = CSurf_TrackFromID(tid, false);
                    double curVU = volToChar(Track_GetPeakInfo(tr, 0));
                    if (ledE[i] != curVU)
                    {
                        midi_out->Send(0xBF, slR[i], ledRing(curVU, 0), -1);
                        ledE[i] = curVU;
                    }
                }
                else
                {
                    if (ledE[i] != 0)
                    {
                        midi_out->Send(0xBF, slR[i], 0, -1);
                        ledE[i] = 0;
                    }
                }
            }
        }
The if (tid <= CountTracks(0)) part.
fundorin is offline   Reply With Quote
Old 01-31-2018, 11:16 AM   #311
fundorin
Banned
 
Join Date: Feb 2014
Location: Moscow, Russia
Posts: 554
Default

Quote:
Originally Posted by nofish View Post
^^ Regarding the exception, wouldn't you need to check if tr isn't a null pointer there (if project / bank contains less than eight tracks).

edit:
Ok, your last code should work nevertheless if at least one track in project I think.
Sorry, didn't saw your message, so I've solved it myself. 🤠 Anyway, you're right.
I've discovered that loading a project with lots of tracks didn't crash Reaper, during debug, while loading an empty project was a no-no.
So, all is working fine for now.
The next step is to display pan/vol levels, instead of VU, when encoders/faders are touched.
I've already did that in oscii-bot and in С++ is a bit harder to achieve.
Thank you, nofish.
fundorin is offline   Reply With Quote
Old 01-31-2018, 11:59 AM   #312
nofish
Human being with feelings
 
nofish's Avatar
 
Join Date: Oct 2007
Location: home is where the heart is
Posts: 12,096
Default

You're welcome.

Just as alternative, doing

Code:
MediaTrack *tr = CSurf_TrackFromID(tid, false);

if (tr) // or explicit: if (tr != NULL)
{
  double curVU = volToChar(Track_GetPeakInfo(tr, 0));
}
should also work I think (and would reduce the CountTracks(0) call).

https://stackoverflow.com/questions/...pointer-in-c-c

Last edited by nofish; 01-31-2018 at 12:17 PM.
nofish is offline   Reply With Quote
Old 01-31-2018, 12:40 PM   #313
fundorin
Banned
 
Join Date: Feb 2014
Location: Moscow, Russia
Posts: 554
Default

Quote:
Originally Posted by nofish View Post
should also work I think (and would reduce the CountTracks(0) call).
Yep. Works too. I was confused, at first, because requesting volume or pan states for non-existing tracks wasn't leading to crash.
fundorin is offline   Reply With Quote
Old 01-31-2018, 12:46 PM   #314
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by fundorin View Post
Yep. Works too. I was confused, at first, because requesting volume or pan states for non-existing tracks wasn't leading to crash.
Don't expect that the Reaper API functions are that consistent. Many of them do null pointer/invalid object checks for you, but some won't, so it's best to also do at least null pointer checks yourself too. (Unless you know the API tolerates passing in null pointers or other invalid values.)
__________________
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 01-31-2018, 01:24 PM   #315
fundorin
Banned
 
Join Date: Feb 2014
Location: Moscow, Russia
Posts: 554
Default

How do I perform some action on Reaper exit or when calling Control surface: Refresh all surfaces (41743).

When I start Reaper before my controller, control surface plugin won't work, until I go to Options/Preferences/"Control/OSC/Web", then press edit on plugin, then press "OK/OK".
Running 41743 action doesn't help.

I would also want to turn down all LEDs and clear the LCD upon Reaper closing.

Tried placing some code into both class destructor CloseNoReset method - no effect.

And I need Reaper to automatically pickup newly created midi ports, like any DAW does on osx (I'm on Win10).
For now, if I turn off my midi controller, it's port disappears from Preferences/Midi devices. When I turn it back on again, I can see controller's port in the list oа еру devices again. But, Reaper won't respond to the controllers commands until I perform Reset all MIDI devices (41175) action.

Is it possible to make Reaper do all this things automatically?
fundorin is offline   Reply With Quote
Old 01-31-2018, 02:49 PM   #316
fundorin
Banned
 
Join Date: Feb 2014
Location: Moscow, Russia
Posts: 554
Default

How do I emulate mouse wheel movement with an encoder on the midi controller? I want to adjust parameters under the mouse cursor (fx knobs, presets, etc) without reaching the mouse itself.
fundorin is offline   Reply With Quote
Old 01-31-2018, 07:29 PM   #317
fundorin
Banned
 
Join Date: Feb 2014
Location: Moscow, Russia
Posts: 554
Default

I want to scroll mixer view to the currently selected bank of tracks (in the control surface), but only if those tracks aren't currently visible in mixer view. The tracks aren't selected, though, but I know their IDs and by "visible" I mean "by the human eye on the physical display".

How do I get rightmost visible track in mixer, so that plugin's logic would decide if it's needed to scroll mixer view or not?
We can already get the leftmost track, but that's not enough for the task.
fundorin is offline   Reply With Quote
Old 02-01-2018, 07:30 AM   #318
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by fundorin View Post
How do I emulate mouse wheel movement with an encoder on the midi controller? I want to adjust parameters under the mouse cursor (fx knobs, presets, etc) without reaching the mouse itself.
That's an operating system API specific thing (how to send fake mouse messages into a window etc), not much to do with Reaper extensions as such.
__________________
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 02-01-2018, 08:54 AM   #319
fundorin
Banned
 
Join Date: Feb 2014
Location: Moscow, Russia
Posts: 554
Default

Quote:
Originally Posted by Xenakios View Post
That's an operating system API specific thing (how to send fake mouse messages into a window etc), not much to do with Reaper extensions as such.
You're right. Actually, I didn't thought about it. I keep forgetting that using C++ gives almost endless possibilities to the programmer. Thanks. What about the other questions, though? Not possible, I guess?
fundorin is offline   Reply With Quote
Old 02-01-2018, 10:37 AM   #320
fundorin
Banned
 
Join Date: Feb 2014
Location: Moscow, Russia
Posts: 554
Default

Solution for mouse emulation. I'm using endless push encoder.

slSb - encoder button
slSd - sends 65++ on CCW encoder rotate and 1++ on CW.

Code:
        // Simulate mouse
        if (msg1 == 0xBF)
        {
            // Left click
            if (msg2 == slSb) (msg3 == 1) ? mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0) : mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
            // Mouse wheel
            else if (msg2 == slSd) (msg3 > 64) ? mouse_event(MOUSEEVENTF_WHEEL, 0, 0, -120, 0) : mouse_event(MOUSEEVENTF_WHEEL, 0, 0, 120, 0);
        }
Button pushes and releases left mouse. Encoder simulates mouse wheel.

UPD. Multiplying delta (120 equals one wheel click) by msg3 gives mouse wheel acceleration:
Code:
mouse_event(MOUSEEVENTF_WHEEL, 0, 0, -120 * (msg3 - 64), 0)

Last edited by fundorin; 02-01-2018 at 11:07 AM.
fundorin 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 12:28 PM.


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