python从Max接收OSC消息

问题描述

我是一个相当有经验的 python 用户,但我没有 OSC 协议、MAX 和 SuperCollider 的经验。

我正在帮助一位朋友构建应该执行以下操作的 Python 代码

  1. 通过 OSC 接收来自 MAX 的消息
  2. 在 python 中详细说明消息
  3. 将详细信息发送给 SuperCollider

我不清楚的是第 1 点和第 3 点是什么。

第 0 部分

我导入以下库

from pythonosc import dispatcher
from pythonosc import osc_server
from pythonosc import udp_client

第 1 部分

我尝试为第 1 点设置一个简单的服务器,因为我一次只从 MAX 接收一个字符串:

def listen2Max(ip,port):
    '''
    set up server
    '''
    # dispatcher to receive message
    dispatcher = dispatcher.dispatcher()
    dispatcher.map("/filter",print)
    # server to listen
    server = osc_server.ThreadingOSCUDPServer((ip,port),dispatcher)
    print("Serving on {}".format(server.server_address))
    server.serve_forever()

但我不知道在这函数return 是什么,我也没有在 "/filter" 中使用 map。是否必须在 MAX 中指定?

第 2 部分

这实际上是我的强项:我接受我的 listen2Max 函数返回的字符串消息,做一些 py 的事情并准备一个名为 mymove 的消息发送给 SuperCollider

第 3 部分

对于第 3 点,我设置了一个简单的客户端来将字符串 var mymove 传达给 SuperCollider

def talk2SC(ip,port,mymove):
    '''
    set up client
    '''
    client = udp_client.SimpleUDPClient(ip,port)
    client.send_message("/filter",mymove)

它应该像那样工作吗?

解决方法

这是完成(至少部分)工作的代码。

请记住,在这种情况下,Max 将字符串发送到 python。我收到的消息是这样的:O-O e8g8 8 1

import argparse

from pythonosc import dispatcher 
from pythonosc import osc_server 
from pythonosc import udp_client

def main(path: str,*osc_arguments):
    msg = osc_arguments[-1]
    print("input message: {}".format(msg))
    msgOUT = msg+'whatever'
    # output
    print("output message: {}".format(msgOUT))
    ipOUT = osc_arguments[0][0]
    portOUT = osc_arguments[0][1]
    pathOUT= osc_arguments[0][2]
    talk2SC(ipOUT,portOUT,pathOUT,msgOUT)

def listen2Max(addrIN,addrOUT):
    '''
    set up server
    '''
    # input address
    ipIN   = addrIN[0]
    portIN = addrIN[1]
    pathIN = addrIN[2]
    # output address
    portOUT = addrOUT[0]
    pathOUT = addrOUT[1]
    # dispatcher to receive message
    disp = dispatcher.Dispatcher()
    disp.map(pathIN,main,ipIN,pathOUT)
    # server to listen
    server = osc_server.ThreadingOSCUDPServer((ipIN,portIN),disp)
    print("Serving on {}".format(server.server_address))
    server.serve_forever()

def talk2SC(ip,port,path,mymove):
    '''
    set up client
    '''
    client = udp_client.SimpleUDPClient(ip,port)
    client.send_message(path,mymove)

if __name__ == "__main__":
    # generate parser
    parser = argparse.ArgumentParser(prog='scacchiOSC',formatter_class=argparse.RawDescriptionHelpFormatter,description='Interprete di messaggi OSC da Max\n')
    parser.add_argument("-II","--ipIN",type=str,default="127.0.0.1",help="The ip to listen on")
    parser.add_argument("-PI","--portIN",type=int,default=5005,help="The port to listen on")
    parser.add_argument("-UI","--uripathIN",default="/filter",help="MAX's URI path")
    parser.add_argument("-PO","--portOUT",default=5006,help="The port to send messages to")
    parser.add_argument("-UO","--uripathOUT",help="output URI path")
    args = parser.parse_args()
    # wrap up inputs
    outputAddress = [args.portOUT,args.uripathOUT]
    inputAddress = [args.ipIN,args.portIN,args.uripathIN]
    # listen to max
    listen2Max(inputAddress,outputAddress)

此代码从客户端获取消息,如下所示:

from pythonosc import dispatcher
from pythonosc import osc_server
from pythonosc import udp_client
from typing import List,Any

def talk2SC(ip,path):
    '''
    set up client
    '''
    # maxmsg = 'Nxe6 f4e6'
    maxmsg = 'e4 e2e4'
    client = udp_client.SimpleUDPClient(ip,maxmsg)


if __name__ == '__main__':
    talk2SC("127.0.0.1",5005,"/filter")

并像这样向服务器发送消息:

from pythonosc import dispatcher
from pythonosc import osc_server
from pythonosc import udp_client
from typing import List,Any


def main(address: str,*osc_arguments):
    '''
    prende il messaggio di MAX e lo traduce aggiornando la scacchiera
    '''
    # read message
    msg = osc_arguments[0]
    # initialize board
    print(osc_arguments)
    # outputc

def listen2Max(ip,path):
    '''
    set up server
    '''
    # dispatcher to receive message
    disp = dispatcher.Dispatcher()
    handler = disp.map(path,main)
    # print(handler)
    # server to listen
    server = osc_server.ThreadingOSCUDPServer((ip,port),disp)
    print("Serving on {}".format(server.server_address))
    server.serve_forever()

if __name__ == '__main__':
    listen2Max("127.0.0.1",5006,"/chmove")

棘手的部分是让它与 Max 通信。幸运的是我找到了答案here

  1. 将每条 Max 消息格式化为 /path "O-O e8g8 8 1"
  2. 让 python 监听指定的 /path

如果希望 python 侦听每一条路径,可以更改解析器项中的默认路径并使用 "*" 作为默认路径。那么

  1. Max 的消息可以有任何路径
  2. 在解析器中将有 parser.add_argument("-UI",default="*",help="MAX's URI path")

现在,我只需要修复 SuperCollider 部分。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...