我正在尝试接收通过OSC从Pure Data(或Max / MSP)发送到MATLAB的消息。
这是我从MATLAB发送消息的代码(我使用的是oscmex协议):
host = 'localhost'; % local host UDP address
sendPort = 3333; % UDP port number to send over
receivePort = 3333; % UDP port number to receive from
oscAddress = osc_new_address(host, sendPort); % open send address
oscServer = osc_new_server(receivePort); % open server
dataPacket = struct('path','/foo','tt','f','data',{num2cell([1.0])}); % create packet
osc_send(oscAddress, dataPacket); % write packet to OSC
oscMessage = osc_recv(oscServer, 0.1); % listen for packet on OSC
% check to see if anything is there...
if length(oscMessage) > 0
fprintf('Found something!')
else
fprintf('Failed to find anything')
end
osc_free_address(oscAddress);
osc_free_server(oscServer);
如果我使用主机'localhost'发送,一切正常,使用上面的代码将从 MATLAB 发送到 MATLAB。如果我将其设置为'127.0.0.1',MATLAB将发送到Pure Data,但MATLAB无法接收自己的消息。
现在为了事情的另一端。这是我的纯数据补丁:
同样,单独运行上述补丁会成功通过Pure Data发送和接收消息。
当我尝试从一个程序谈到另一个程序时,问题就在于此。如果我设置的东西使得MATLAB在端口3333上发送并且Pure Data在3333上接收,并且Pure Data在2222上发送并且MATLAB在2222上接收,那么如果MATLAB的话,我可以使Pure Data 接收主机是'127.0.0.1'。但是,使用'127.0.0.1',MATLAB无法发送给自己。
无论如何,无论我尝试什么,我都无法将纯数据发送发送到MATLAB,尽管能够将其发送给自己。我怀疑它与“主机”地址有关。
我的实际IPv4地址(使用MS命令提示符的'ipconfig'找到)与127.0.0.1完全不同,并且使用此处指定的值似乎不会使事情更好。
我知道我不能在任何时候打开同一个端口的多个OSC服务器,因此我目前尝试解决方案涉及从一个端口上的MATLAB发送,另一个端口上从Pure Data发送,在任一端口上一次只打开一台服务器。
注意我也知道我使用/foo
来自MATLAB的消息和来自Pure Data的/test
。但是,我的MATLAB代码不加选择地接收通过OSC发送的所有内容,因此没有区别。
任何帮助PD与MATLAB交流的帮助都将不胜感激。
更新:我解决了'localhost'问题,似乎没有解决问题(我必须将localhost添加到我的Windows'主机'文件中)。所以,我可能因为担心本地主机事而咆哮错误的树。但是,我仍然无法让PD与MATLAB交谈。
更新#2 :Amro在下面发布了一个优雅的解决方案,而仍然无法让MATLAB接收来自Pure Data的消息。我已安装CloseTheDoor来监控我的UDP连接,并注意到当MATLAB设置服务器时,它使用'Interface'[::0]
,而PD集使用'Interface'0.0.0.0
。由于PureData是成功接收消息的那个,也许我需要让MATLAB监听0.0.0.0
?
答案 0 :(得分:5)
首先我要说我之前从未使用过PureData或OSC,而我只是复制了您创建的用于创建服务器/客户端的图形/补丁。
首先让我们在PureData中创建服务器:
现在这里是一个在MATLAB中作为GUI实现的简单客户端:
function example_osc_client()
handles = createGUI();
osc = [];
function h = createGUI()
h.fig = figure('Menubar','none', 'Resize','off', ...
'CloseRequestFcn',@onClose, ...
'Name','OSC Client', 'Position',[100 100 220 140]);
movegui(h.fig, 'center')
h.conn = uicontrol('Style','pushbutton', 'String','Connect', ...
'Callback',{@onClick,'connect'}, ...
'Parent',h.fig, 'Position',[20 20 80 20]);
h.disconn = uicontrol('Style','pushbutton', 'String','Disconnect', ...
'Callback',{@onClick,'disconnect'}, ...
'Parent',h.fig, 'Position',[120 20 80 20]);
h.slid = uicontrol('Style','slider', 'Callback',@onSlide, ...
'Min',-10, 'Max',10, 'Value',0, ...
'Parent',h.fig, 'Position',[30 60 160 20]);
h.txt = uicontrol('Style','text', 'String','0.0', ...
'Parent',h.fig, 'Position',[80 100 60 20]);
set([h.slid;h.disconn], 'Enable','off');
drawnow
end
function onClick(~,~,action)
switch lower(action)
case 'connect'
osc = osc_new_address('127.0.0.1', 2222);
set(handles.conn, 'Enable','off')
set(handles.disconn, 'Enable','on')
set(handles.slid, 'Enable','on')
case 'disconnect'
osc_free_address(osc); osc = [];
set(handles.conn, 'Enable','on')
set(handles.disconn, 'Enable','off')
set(handles.slid, 'Enable','off')
end
drawnow
end
function onSlide(~,~)
if isempty(osc), return; end
val = single(get(handles.slid,'Value'));
m = struct('path','/test', 'tt','f', 'data',{{val}});
osc_send(osc, m);
set(handles.txt, 'String',num2str(val))
drawnow
end
function onClose(~,~)
if ~isempty(osc)
osc_free_address(osc);
end
delete(handles.fig);
end
end
移动滑块时,消息将发送到服务器(使用OSC-MEX界面),值将显示在PureData模型中。
在测试时,我注意到不支持double
类型,因为我在PD日志窗口中看到以下消息:
unpackOSC:PrintTypeTaggedArgs:[64位浮点数]未实现
因此有必要手动将值转换为single
或在传递给osc_send
OSC-MEX函数的结构中明确指定提示类型:
val = single(1);
m = struct('path','/test', 'tt','f', 'data',{{val}});
osc_send(osc, m);
类似地,我们在PureData中创建客户端:
同样,这里是作为MATLAB GUI实现的服务器:
function example_osc_server()
handles = createGUI();
osc = [];
function h = createGUI()
h.fig = figure('Menubar','none', 'Resize','off', ...
'CloseRequestFcn',@onClose, ...
'Name','OSC Server', 'Position',[100 100 220 140]);
movegui(h.fig, 'center')
h.start = uicontrol('Style','pushbutton', 'String','Start', ...
'Callback',{@onClick,'start'}, ...
'Parent',h.fig, 'Position',[20 20 80 20]);
h.stop = uicontrol('Style','pushbutton', 'String','Stop', ...
'Callback',{@onClick,'stop'}, ...
'Parent',h.fig, 'Position',[120 20 80 20]);
h.txt = uicontrol('Style','text', 'String','', ...
'Parent',h.fig, 'Position',[60 80 100 20]);
set(h.stop, 'Enable','off');
drawnow expose
h.timer = timer('TimerFcn',@receive, 'BusyMode','drop', ...
'ExecutionMode','fixedRate', 'Period',0.11);
end
function onClick(~,~,action)
switch lower(action)
case 'start'
set(handles.start, 'Enable','off')
set(handles.stop, 'Enable','on')
osc = osc_new_server(2222);
start(handles.timer);
case 'stop'
set(handles.start, 'Enable','on')
set(handles.stop, 'Enable','off')
osc_free_server(osc); osc = [];
stop(handles.timer);
end
drawnow expose
end
function receive(~,~)
if isempty(osc), return; end
m = osc_recv(osc, 0.1);
if isempty(m), return; end
set(handles.txt, 'String',num2str(m{1}.data{1}))
drawnow expose
end
function onClose(~,~)
if ~isempty(osc)
osc_free_server(osc);
end
stop(handles.timer); delete(handles.timer);
delete(handles.fig);
clear handles osc
end
end
服务器部分在MATLAB中有点棘手。我们的想法是,我们不希望MATLAB无限期地阻止等待消息。所以我创建了一个每0.11秒执行一次的计时器。在计时器功能内部,我们尝试以阻塞方式接收消息,但超时为0.1秒。这样,GUI和MATLAB IDE都能保持响应。
使用上述解决方案,您还可以在PureData中打开客户端和服务器,或者在MATLAB中打开客户端和服务器。它应该以任何方式工作。
最后,我应该说,无论我使用主机名localhost
还是直接指定IP地址127.0.0.1
,都没有区别。
HTH
我自己编译了OSC-MEX包,以下是步骤。首先下载osc-mex sources及其依赖项。其中包括:liblo sources,pthreads-win32 binaries,premake4可执行文件。
1)我们首先构建liblo库:
premake4 --platform=x32 vs2010
include
文件夹。同样,为链接器添加lib
文件夹,并将pthreadVC2.lib
指定为附加依赖项。lib\ReleaseLib\liblo.lib
请注意,by default,在liblo中禁用了IPv6支持,因为像Pd这样的OSC应用程序存在IPv6问题。如果您仍想启用它,请将以下行添加到config.h
文件:
#define ENABLE_IPV6 1
2)接下来我们在MATLAB中编译MEX函数:
liblo.lib
复制到此目录中。同时从pthreads库中复制pthreadVC2.lib
。使用以下方法编译每个函数:
mex -largeArrayDims -I../path/to/liblo-0.27 xxxxxx.c pthreadVC2.lib liblo.lib -lwsock32 -lws2_32 -liphlpapi
对于每个*.mexw32
源文件,您最终应该有六个xxxxxx.c
个文件
pthreadVC2.dll
为了省去一些麻烦,以下是使用VS2010构建在WinXP 32-bit和Win8 64-bit上的已编译MEX文件。如果您想自己编译(只需在VS2010中构建解决方案,然后在MATLAB中运行osc_make.m
),这里有the sources
答案 1 :(得分:0)
localhost
是127.0.0.1
的别名;它们确实是相同的IP地址。所以如果matlab只收到一些东西,如果它发送到localhost
而不是发送给127.0.0.1
,那么他们可能会有一个错误的OSC实现。
只要您的补丁中有[udpreceive 2222]
,Pd就会阻止端口UDP / 2222,并且matlab将无法在该端口上接收任何内容。
所以简单的解决方案是:在使用[udpreceive 2222]
创建matlab服务器之前删除osc_new_server(2222);