python получает сообщение OSC от Макса

Я довольно опытный пользователь Python, но у меня нет опыта работы с протоколом OSC, MAX и SuperCollider.

Я помогаю другу в создании кода Python, который должен делать следующее:

  1. получить сообщение от MAX через OSC
  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)

Это должно так работать?


person brodegon    schedule 07.02.2021    source источник


Ответы (1)


Это код, который выполняет (по крайней мере частично) работу.

Имейте в виду, что в этом случае Макс отправляет строки в 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, portOUT, 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", type=str, default="/filter", help="MAX's URI path")
    parser.add_argument("-PO", "--portOUT", type=int, default=5006, help="The port to send messages to")
    parser.add_argument("-UO", "--uripathOUT", type=str, default="/filter", 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,port,path):
    '''
    set up client
    '''
    # maxmsg = 'Nxe6 f4e6'
    maxmsg = 'e4 e2e4'
    client = udp_client.SimpleUDPClient(ip,port)
    client.send_message(path, 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,port,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")

Сложность заключается в том, чтобы заставить его общаться с Максом. К счастью, я нашел ответ здесь:

  1. отформатируйте каждое сообщение Max как /path "O-O e8g8 8 1"
  2. заставить python слушать указанный /path

Если кто-то хочет, чтобы python прослушивал каждый путь, можно изменить путь по умолчанию в элементе парсера и использовать "*" по умолчанию. Затем

  1. Сообщения Макса могли иметь любой путь
  2. в парсере будет parser.add_argument("-UI", "--uripathIN", type=str, default="*", help="MAX's URI path")

Теперь мне просто нужно исправить часть SuperCollider.

person brodegon    schedule 15.02.2021