Browse Source

Created thread for osc receiver. Created osc message handler (works for int only for now). Many small changes.

tags/0.1
Ludwig Frühschütz 3 years ago
parent
commit
678b0d09a4
3 changed files with 182 additions and 69 deletions
  1. +118
    -57
      OSC2AHK/dllmain.cpp
  2. +7
    -4
      OSC2AHK/dllmain.h
  3. +57
    -8
      msgtest.ahk

+ 118
- 57
OSC2AHK/dllmain.cpp View File

@ -3,79 +3,64 @@
#include "dllmain.h"
#include <string>
#include <vector>
#include <thread>
#include "osc/OscReceivedElements.h"
#include "osc/OscPacketListener.h"
#include "ip/UdpSocket.h"
class ExamplePacketListener : public osc::OscPacketListener {
//Class from OSC library (oscpack). This calls our handleOscMsg() on every new message.
class ThePacketListener : public osc::OscPacketListener {
protected:
virtual void ProcessMessage(const osc::ReceivedMessage& m,
const IpEndpointName& remoteEndpoint)
{
OutputDebugString(L"Got OSC Message!\r\n");
(void)remoteEndpoint; // suppress unused parameter warning
try {
// example of parsing single messages. osc::OsckPacketListener
// handles the bundle traversal.
if (std::strcmp(m.AddressPattern(), "/test1") == 0) {
// example #1 -- argument stream interface
osc::ReceivedMessageArgumentStream args = m.ArgumentStream();
bool a1;
osc::int32 a2;
float a3;
const char* a4;
args >> a1 >> a2 >> a3 >> a4 >> osc::EndMessage;
OutputDebugString(L"received '/test1' message with arguments: ... ");
//std::cout << "received '/test1' message with arguments: "
// << a1 << " " << a2 << " " << a3 << " " << a4 << "\n";
}
else if (std::strcmp(m.AddressPattern(), "/test2") == 0) {
// example #2 -- argument iterator interface, supports
// reflection for overloaded messages (eg you can call
// (*arg)->IsBool() to check if a bool was passed etc).
osc::ReceivedMessage::const_iterator arg = m.ArgumentsBegin();
//bool a1 = (arg++)->AsBool();
//int a2 = (arg++)->AsInt32();
//float a3 = (arg++)->AsFloat();
const char* a4 = (arg++)->AsString();
//if (arg != m.ArgumentsEnd())
//throw osc::ExcessArgumentException();
OutputDebugString(L"received '/test2' message with argument: ");
OutputDebugStringA(a4);
OutputDebugString(L"\r\n");
//std::cout << "received '/test2' message with arguments: "
// << a1 << " " << a2 << " " << a3 << " " << a4 << "\n";
}
try {
handleOscMsg(m);
}
catch (osc::Exception& e) {
// any parsing errors such as unexpected argument types, or
// missing arguments get thrown as exceptions.
OutputDebugString(L"error while parsing message: ...");
//std::cout << "error while parsing message: "
// << m.AddressPattern() << ": " << e.what() << "\n";
OutputDebugString(L"ProcessMessage: Error while parsing message: ...");
}
}
};
/* Definition and declaration of the OSC Listeners.
/* Definition and declaration of the registered OSC Listeners.
* Contains OSC addresses to listen to and OS message ID to send for each
* address */
* address. These are populated from the AHK script! */
struct Listener {
std::string address;
unsigned int dataType;
unsigned int message;
};
std::vector<Listener> listeners;
/* Handle to the calling window */
/* Handle to the calling window, also indicates if this OSC receiver is "opened" by being != NULL*/
HWND hwnd = NULL;
ExamplePacketListener* examplePacketListener;
/* OSC receiving objects and thread.
* From within these, our handleOscMsg() function is called. */
ThePacketListener* thePacketListener;
UdpListeningReceiveSocket* sock;
std::thread* oscThread;
/* The OSC Thread. Has to be another thread, because
* UdpListeningReceiveSocket runs in a blocking loop. [RunUntilSigInt()]*/
void runOscThread(unsigned int port)
{
thePacketListener = new ThePacketListener;
sock = new UdpListeningReceiveSocket(
IpEndpointName(IpEndpointName::ANY_ADDRESS, port),
thePacketListener);
sock->RunUntilSigInt(); //<<--- this is the loop
//Cleanup after sock exited the loop
sock = NULL;
thePacketListener = NULL;
}
/* DLL was loaded */
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
@ -85,7 +70,6 @@ BOOL APIENTRY DllMain( HMODULE hModule,
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
OutputDebugString(L"ATTACH\r\n");
break;
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
@ -97,39 +81,53 @@ BOOL APIENTRY DllMain( HMODULE hModule,
DLLEXPORT int open(HWND targetWindowHandle, unsigned int port)
{
OutputDebugString(L"open()\r\n");
if (!targetWindowHandle || !port) {
if (!targetWindowHandle) OutputDebugString(L"open: targetWindowHandle!!\r\n");
if (!port) OutputDebugString(L"open: port!!\r\n");
return 1;
}
/*Store handle to Autohotkey window globally*/
hwnd = targetWindowHandle;
examplePacketListener = new ExamplePacketListener;
sock = new UdpListeningReceiveSocket(
IpEndpointName(IpEndpointName::ANY_ADDRESS, port),
examplePacketListener);
sock->RunUntilSigInt();
OutputDebugString(L"open\r\n");
/*Start OSC Thread*/
oscThread = new std::thread(runOscThread, port);
OutputDebugString(L"open: Opened.\r\n");
return 0;
}
DLLEXPORT int close()
{
if (sock && sock->IsBound())
{
sock->AsynchronousBreak();
}
oscThread = NULL;
hwnd = NULL;
listeners.clear();
return 0;
}
DLLEXPORT int addListener(std::string address_, unsigned int messageID_, unsigned int dataType_)
DLLEXPORT int addListener(LPCSTR address_, unsigned int messageID_, unsigned int dataType_)
{
listeners.push_back(Listener{ address_, dataType_, messageID_ });
OutputDebugString(L"addListener: address=");
OutputDebugStringA(address_);
OutputDebugString(L"\r\n");
listeners.push_back(Listener{ std::string(address_), dataType_, messageID_ });
return 0;
}
DLLEXPORT int removeListener(std::string address_)
DLLEXPORT int removeListener(LPCSTR address_)
{
UINT result = 1;
std::string addrStr(address_);
//All OSC addresses have to start with a '/'
if (address_[0] != '/') address_.insert(0, "/");
if (addrStr[0] != '/') addrStr.insert(0, "/");
for (UINT i = 0; i < listeners.size(); i++)
{
if (listeners[i].address == address_)
if (listeners[i].address == addrStr)
{
listeners.erase(listeners.begin() + i);
i--; //one step backward, what previously was i+1 is i after erase().
@ -139,11 +137,74 @@ DLLEXPORT int removeListener(std::string address_)
return result;
}
DLLEXPORT int handleOscMsg(const osc::ReceivedMessage& m)
{
int ret = 0;
OutputDebugString(L"handleOscMsg: Address=");
OutputDebugStringA(m.AddressPattern());
OutputDebugString(L"\r\n");
if (!hwnd || !sock->IsBound())
{
OutputDebugString(L"handleOscMsg: Seems open() was not called yet...\r\n");
return -1;
}
//Loop through all registered listener entries
for (UINT i = 0; i < listeners.size(); i++)
{
//Check if incoming OSC address matches current listener entry
if (listeners[i].address.compare(m.AddressPattern()) == 0)
{
//No payload
if (m.ArgumentCount() == 0) {
if (listeners[i].dataType == OSC_TYPE_NONE || listeners[i].dataType == OSC_TYPE_ALL) {
PostMessage(hwnd, listeners[i].message, OSC_TYPE_NONE, 0);
ret++;
}
}
else //Some paylad, only check first one
{
osc::ReceivedMessage::const_iterator arg = m.ArgumentsBegin();
if (arg->IsInt32()) { //Got Int, check if listener is valid for Int or All
if (listeners[i].dataType == OSC_TYPE_ALL || listeners[i].dataType == OSC_TYPE_INT) {
PostMessage(hwnd, listeners[i].message, OSC_TYPE_INT, arg->AsInt32()); //post to message queue
ret++;
}
}
else if (arg->IsFloat()) { //Got Float, check if listener is valid for Float or All
if (listeners[i].dataType == OSC_TYPE_ALL || listeners[i].dataType == OSC_TYPE_FLOAT) {
float floatarg = arg->AsFloat();
LPARAM lParam = *(LPARAM*)&floatarg;
PostMessage(hwnd, listeners[i].message, OSC_TYPE_FLOAT, lParam); //post to message queue
ret++;
}
}
else
OutputDebugString(L"handleOscMsg: Unknown datatype\r\n");
}
}
}
if (ret > 0) OutputDebugString(L"handleOscMsg: Found and posted at least once.\r\n");
return ret;
}
/* Debugging function to test messaging. Probably will be removed later. */
DLLEXPORT int testMsg(HWND windowHandle, unsigned int messageID)
{
OutputDebugString(L"testMsg()\r\n");
if (!windowHandle)
{
OutputDebugString(L"testMsg: windowHandle!!\r\n");
return 1;
}
if (PostMessage(windowHandle, messageID, 42, 43))
return 0;
else
return 1;
}

+ 7
- 4
OSC2AHK/dllmain.h View File

@ -2,16 +2,19 @@
#include <windows.h>
#include <string>
#include <osc/OscReceivedElements.h>
#define DLLEXPORT __declspec(dllexport)
#define OSC_TYPE_ALL 0
#define OSC_TYPE_NONE 0
#define OSC_TYPE_INT 1
#define OSC_TYPE_FLOAT 2
#define OSC_TYPE_STRING 4
#define OSC_TYPE_STRING 3
#define OSC_TYPE_ALL 255
extern "C" DLLEXPORT int open(HWND targetWindowHandle, unsigned int port);
extern "C" DLLEXPORT int close();
extern "C" DLLEXPORT int addListener(std::string address, unsigned int messageID, unsigned int dataType = OSC_TYPE_ALL);
extern "C" DLLEXPORT int removeListener(std::string address);
extern "C" DLLEXPORT int addListener(LPCSTR address, unsigned int messageID, unsigned int dataType = OSC_TYPE_ALL);
extern "C" DLLEXPORT int removeListener(LPCSTR address);
extern "C" DLLEXPORT int handleOscMsg(const osc::ReceivedMessage & m);
extern "C" DLLEXPORT int testMsg(HWND windowHandle, unsigned int messageID);

+ 57
- 8
msgtest.ahk View File

@ -1,25 +1,49 @@
#SingleInstance, Force
SendMode Input
SetWorkingDir, %A_ScriptDir%
Gui +LastFound
hWnd := WinExist()
stdout := FileOpen("tmp.log", "w")
stdout.WriteLine("START")
retOnMsg := OnMessage(0x1000, "msghandler")
stdout.WriteLine("OnMessage:")
stdout.Write("OnMessage: ")
stdout.WriteLine(retOnMsg)
OnExit("exithandler")
hModule := DllCall("LoadLibrary", "Str", "x64\Debug\OSC2AHK.dll", "Ptr") ; Avoids the need for DllCall() in the loop to load the library.
stdout.WriteLine("DLL handle:")
stdout.Write("DLL handle: ")
stdout.WriteLine(hModule)
ret := DllCall("OSC2AHK.dll\testMsg", UInt,hWnd, UInt,0x1000)
stdout.WriteLine("DLL call:")
stdout.WriteLine(ret)
; ret := DllCall("OSC2AHK.dll\testMsg", UInt,hWnd, UInt,0x1000)
; stdout.WriteLine("DLL call:")
; stdout.WriteLine(ret)
DllCall("OSC2AHK.dll\open", UInt, hWnd, UInt, 7002)
ret3 := DllCall("OSC2AHK.dll\open", UInt, hWnd, UInt, 7002)
stdout.Write("DLL open: ")
stdout.WriteLine(ret3)
ret2 := DllCall("OSC2AHK.dll\addListener", AStr, "/test", UInt, 0x1001, UInt, 1)
retOnMsg := OnMessage(0x1001, "msghandler")
stdout.Write("DLL addListener: ")
stdout.WriteLine(ret2)
;ret3 := DllCall("OSC2AHK.dll\close")
;stdout.Write("DLL close: ")
;stdout.WriteLine(ret3)
; ret3 := DllCall("OSC2AHK.dll\open", UInt, hWnd, UInt, 7002)
; stdout.Write("DLL open: ")
; stdout.WriteLine(ret3)
DllCall("OSC2AHK.dll\addListener", AStr, "/test2", UInt, 0x1001, UInt, 1)
DllCall("OSC2AHK.dll\addListener", AStr, "/test3", UInt, 0x1002, UInt, 255)
OnMessage(0x1002, "msghandlerfloat")
DllCall("OSC2AHK.dll\removeListener", AStr, "/test2")
; retOnMsg := OnMessage(0x1001, "msghandler")
; stdout.Write("DLL addListener: ")
; stdout.WriteLine(ret2)
stdout.Close()
@ -27,12 +51,37 @@ return
msghandler(wParam, lParam, msg, hwnd) {
stdout := FileOpen("tmp.log", "a")
stdout.WriteLine("Received MSG!")
stdout.WriteLine(wParam)
stdout.Write("Received MSG: ")
stdout.Write(msg)
stdout.write(" ")
stdout.Write(wParam)
stdout.write(" ")
stdout.WriteLine(lParam)
stdout.Close()
}
msghandlerfloat(wParam, lParam, msg, hwnd) {
stdout := FileOpen("tmp.log", "a")
thefloat := NumGet(lParam, 0, "Float")
stdout.WriteLine(thefloat)
thefloat := NumGet(lParam, 1, "Float")
stdout.WriteLine(thefloat)
thefloat := NumGet(lParam, 2, "Float")
stdout.WriteLine(thefloat)
thefloat := NumGet(lParam, 3, "Float")
stdout.WriteLine(thefloat)
thefloat := NumGet(lParam, 4, "Float")
stdout.WriteLine(thefloat)
thefloat := NumGet(lParam, 5, "Float")
stdout.WriteLine(thefloat)
thefloat := NumGet(lParam, 6, "Float")
stdout.WriteLine(thefloat)
thefloat := NumGet(lParam, 7, "Float")
stdout.WriteLine(thefloat)
thefloat := NumGet(lParam, 8, "Float")
stdout.WriteLine(thefloat)
}
exithandler() {
stdout := FileOpen("tmp.log", "a")
stdout.WriteLine("The End")


Loading…
Cancel
Save