Обмен данными между Pure Data и MATLAB с помощью OSC

Я пытаюсь получить сообщение, отправленное через OSC из Pure Data (или Max / MSP) в MATLAB.

  • Я могу отправлять сообщения OSC из Pure Data в Pure Data
  • Я могу отправлять сообщения из MATLAB в MATLAB
  • Я даже могу отправлять сообщения из MATLAB в Pure Data
  • ... Я действительно изо всех сил пытаюсь заставить Pure Data разговаривать с 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:

Изображение патча Pure Data

Опять же, запуск только вышеуказанного патча успешно отправляет и получает сообщения через Pure Data.

Проблема заключается в том, что я пытаюсь перейти от одной программы к другой. Если я настрою все так, что MATLAB отправляет на порт 3333, а Pure Data получает на 3333, и что Pure Data отправляется на 2222, а MATLAB получает на 2222, я могу сделать Pure Data получать, если MATLAB хост - 127.0.0.1. Но с '127.0.0.1' MATLAB не может отправлять самому себе.

В любом случае, что бы я ни пытался, я не могу заставить Pure Data отправить в MATLAB, несмотря на то, что у меня есть возможность получить его для отправки самому себе. Я подозреваю, что это как-то связано с адресом «хоста».

Мой фактический IPv4-адрес (найденный с помощью ipconfig в командной строке MS) полностью отличается от 127.0.0.1, и использование указанного здесь значения, похоже, не улучшает работу.

Я знаю, что у меня не может быть более одного сервера OSC с одним и тем же открытым портом одновременно, поэтому моя текущая попытка решения включает отправку из MATLAB на один порт и отправку из Pure Data на другой, только с один сервер открыт одновременно на любом из портов.

Обратите внимание: я также знаю, что использую /foo для сообщений от MATLAB и /test от Pure Data. Однако мой код MATLAB без разбора получает все, что отправлено через OSC, так что это не имеет значения.

Любая помощь в том, чтобы заставить PD поговорить с MATLAB, была бы оценена.

Обновление: я решил проблему с "localhost", и это, похоже, не помогло (мне пришлось добавить localhost в мой файл "hosts" Windows). Итак, я, возможно, лаял не на то дерево, беспокоясь о локальном хосте. Но я все еще не могу заставить PD поговорить с MATLAB.

Обновление №2: Amro опубликовал элегантное решение ниже, и я все еще не могу заставить MATLAB получать сообщения от Pure Data. Я установил CloseTheDoor для мониторинга своих UDP-соединений и заметил, что когда MATLAB настраивает сервер, он использует «Интерфейс» [::0], тогда как наборы PD используют «Интерфейс» 0.0.0.0. Поскольку PureData - это тот, который успешно принимает сообщения, возможно, мне нужно заставить MATLAB также прослушивать 0.0.0.0?


person CaptainProg    schedule 13.06.2013    source источник
comment
Вы пробовали 'localhost' в качестве имени хоста? Похоже, это имя, используемое с udpsend на вашей диаграмме, и то, которое работало для MATLAB - ›Связь MATLAB. Не то чтобы это должно иметь значение, но попробовать стоит ...   -  person wakjah    schedule 13.06.2013
comment
Да, 'localhost' - единственное имя хоста (в MATLAB), которое разрешает связь с MATLAB. Однако только '127.0.0.1' разрешает связь от MATLAB к Pure Data. Ни один из них (установленный в патче Pure Data) не разрешает связь от Pure Data с MATLAB.   -  person CaptainProg    schedule 13.06.2013
comment
Вы пытались установить порт отправки на другое значение (на 1 меньше), чем порт приема? Также вы можете попытаться установить адрес принимающего хоста на 0.0.0.0, который прослушивает любой сетевой интерфейс, а не только loopback. Также - что именно вы называете проблемой localhost? Наконец, задействован ли какой-либо брандмауэр?   -  person JeffRSon    schedule 16.06.2013
comment
Спасибо, я попробую это, когда у меня будет возможность. Что касается проблемы «localhost», я имею в виду тот факт, что изначально я не мог заставить MATLAB разговаривать с самим собой, если я не использовал хост «localhost», тогда как я мог разговаривать с PD, используя «127.0.0.1», но не сам MATLAB. Я считаю, что теперь у меня это работает с тех пор, как я изменил свой файл Windows 'hosts', чтобы определить 'localhost' как '127.0.0.1'. Другими словами, я считаю, что местные хозяева - отвлекающий маневр.   -  person CaptainProg    schedule 16.06.2013
comment
Конечно, localhost thing - еще одна проблема, потому что localhost - это обычное DNS-имя для 127.0.0.1. Одно или другое должно работать (некоторые программы могут использовать 127.0.0.1 в качестве имени вместо IP, поэтому это тоже может не сработать), но если вы попробовали оба, возникает другая проблема. Я сам разработал программное обеспечение, которое общается с Pure Data через OSC - к сожалению, сторона Pure Data не была моей частью работы, поэтому я не могу точно сказать, ведет ли она себя как-то особенным. Но я знаю, что это может сработать ;-)   -  person JeffRSon    schedule 16.06.2013
comment
Брандмауэр не работает; проблема не устранена! По какой-то причине теперь я даже не могу заставить MATLAB разговаривать с MATLAB, и я понятия не имею, что изменилось, чтобы это произошло ... Это головная боль ..   -  person CaptainProg    schedule 18.06.2013
comment
См. Обновление к вопросу, объясняющее нюанс в интерфейсе UDP-соединения, который я обнаружил.   -  person CaptainProg    schedule 18.06.2013
comment
@CaptainProg: какая у вас ОС? Вы уверены, что брандмауэр здесь не мешает? Отмените все изменения, внесенные вами в hosts файл. Я тестировал свой код в R2013a, работающем на 32-битной WinXP, и он работает нормально ... Обратите внимание, что адрес 0.0.0.0 означает, что сервер прослушивает все интерфейсы. Адрес с двойным двоеточием - это нотация IPv6, я думаю, может ли это быть проблема IPv4 или IPv6? Обычно ::1 совпадает с 127.0.0.1, а ::0 означает 0.0.0.0.   -  person Amro    schedule 18.06.2013
comment
Модуль OSC-MEX использует библиотеку liblo. Я думаю, вам стоит попробовать скомпилировать его самостоятельно с явно включенной поддержкой IPv6 (глядя на код, в исходном коде есть пара макросов #ifdef ENABLE_IPV6). Насколько я могу судить, двоичные файлы OSC-MEX предоставленные были скомпилированы против liblo v0.22, если это имеет значение. кстати, вы никогда не упоминали разрядность вашей ОС и версии MATLAB, которую вы используете (32-разрядная или 64-разрядная), это может быть фактором.   -  person Amro    schedule 18.06.2013
comment
Вот это да. Однажды я потратил целых два дня на попытки скомпилировать osc-mex, но безуспешно. Поверьте, это не та дорога, по которой я хочу снова идти. Я даже дошел до того, что связался с автором osc-mex за поддержкой, и обнаружил, что в файлах компиляции есть неразрешенные ошибки, и что есть уровни за слоями зависимых библиотек. Я думаю, что здесь я сдаюсь! Я попробую ваше решение в другой системе, чтобы убедиться, что что-то еще не блокирует мои порты. Кстати, я использую 32-битную Win 7, MATLAB 2012a.   -  person CaptainProg    schedule 19.06.2013
comment
@CaptainProg: Мне удалось собрать osc-mex из исходников. Смотрите мою недавнюю правку :) Теперь я уверен, что проблема связана с IPv6, есть даже примечание по _ 1_ стр. об этом. Так что я бы пока придерживался IPv4 .. Возможно, вы можете временно отключить его: informationweek.com/byte/personal-tech/   -  person Amro    schedule 20.06.2013


Ответы (2)


Позвольте мне начать с того, что я никогда раньше не использовал PureData или OSC, и я просто продублировал график / патч для вас Показано, как создать сервер / клиент.

1) сервер в PureData, клиент в MATLAB:

Сначала создадим сервер в PureData:

server_PD: pastebin.com/hwJzxri2

Теперь вот простой клиент, реализованный как графический интерфейс в MATLAB:

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

client_MATLAB

При перемещении ползунка сообщения отправляются на сервер (с использованием интерфейса 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);

2) сервер в MATLAB, клиент в PureData:

Аналогично создаем клиента в PureData:

client_PD: pastebin.com/P1KcM00m

Опять же, вот сервер, реализованный как графический интерфейс MATLAB:

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

server_MATLAB

Серверная часть в MATLAB была немного сложнее. Идея в том, что мы не хотим, чтобы MATLAB блокировал бесконечное ожидание сообщений. Поэтому я создал таймер, который запускается каждые 0,11 секунды. Внутри функции таймера мы пытаемся получить сообщение блокирующим образом, но с таймаутом 0,1 секунды. Таким образом, и графический интерфейс, и MATLAB IDE остаются отзывчивыми.


3) другие комбинации:

Используя приведенные выше решения, вы также можете открыть и клиент, и сервер в PureData, или и клиент, и сервер в MATLAB. В любом случае это должно сработать.

Наконец, я должен сказать, что не имело значения, использую ли я имя хоста как localhost или указываю IP-адрес напрямую 127.0.0.1.

HTH


РЕДАКТИРОВАТЬ:

Мне удалось скомпилировать пакет OSC-MEX самостоятельно, вот шаги. Сначала загрузите osc-mex sources и его зависимости. Сюда входят: liblo источники, pthreads-win32 двоичные файлы, < исполняемый файл href = "http://industriousone.com/premake/download" rel = "nofollow noreferrer"> premake4.

1) Начнем со сборки библиотеки liblo:

  • Скопируйте "premake4.exe" в каталог "build" и запустите: premake4 --platform=x32 vs2010
  • откройте сгенерированный файл решения "liblo.sln" в VS2010. Выберите проект «liblo» и перейдите в «Проект> Свойства». Добавьте папку include, содержащую файлы заголовков pthreads, в поле «Дополнительные подключаемые каталоги». Аналогичным образом добавьте папку lib для компоновщика и укажите pthreadVC2.lib в качестве дополнительной зависимости.
  • Выберите цель Win32 «ReleaseLib» и соберите проект. Это должно создать конечную цель: lib\ReleaseLib\liblo.lib

Обратите внимание, что по умолчанию, поддержка IPv6 отключена в liblo, поскольку приложения OSC, такие как Pd есть проблемы с IPv6. Если вы все же хотите включить его, добавьте следующую строку в config.h файл:

#define ENABLE_IPV6 1

2) Далее мы компилируем MEX-функции в MATLAB:

  • Перейдите в папку, содержащую C-исходники MEX-функций.
  • скопируйте liblo.lib из предыдущего шага в этот каталог. Также скопируйте pthreadVC2.lib из библиотеки pthreads.
  • скомпилировать каждую функцию, используя:

    mex -largeArrayDims -I../path/to/liblo-0.27 xxxxxx.c pthreadVC2.lib liblo.lib -lwsock32 -lws2_32 -liphlpapi
    
  • У вас должно получиться шесть *.mexw32 файлов для каждого из xxxxxx.c исходных файлов.

  • Наконец, скопируйте DLL pthreads в ту же папку: pthreadVC2.dll

Чтобы избавить вас от некоторых проблем, вот скомпилированные MEX-файлы, созданные на WinXP 32- bit и 64-bit, оба используют VS2010. Вот исходники, если вы хотите скомпилировать его самостоятельно (просто создайте решение в VS2010, затем запустите osc_make.m в MATLAB)

person Amro    schedule 16.06.2013
comment
Амро, большое спасибо за твои усилия. К сожалению, проблема сохраняется: даже с вашим примером «сервер в MATLAB, клиент в PD», никакие данные не проходят в MATLAB. Таким образом, я продолжаю пытаться найти решение ... В настоящее время интересно, не блокирует ли соединение что-то еще (брандмауэр выключен). - person CaptainProg; 18.06.2013
comment
См. Обновление к вопросу, объясняющее нюанс в интерфейсе UDP-соединения, который я обнаружил. - person CaptainProg; 18.06.2013

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);

person umläute    schedule 13.06.2013
comment
Спасибо; да, я пробовал это - я знаю, что у меня не может быть более одного сервера OSC с одним и тем же портом, открытым одновременно, поэтому моя текущая попытка решения включает отправку из MATLAB на один порт и отправку из Pure Данные на другом, при этом только один сервер открыт одновременно на любом порту. - person CaptainProg; 13.06.2013