Ejecutar python-osc en OBS como script

Quiero / necesito hacer que este código se ejecute dentro de OBS como un script. Tomé el script llamado “OSC Sender for OBS” del foro de OBS (obsproject . com / forum / threads / osc-sender-for-obs.100618) de OSC para OBS que hace lo que dice el nombre: envía mensajes de OSC. Pero, dentro del código, la parte del servidor está comentada, porque no funciona … esto se debe a un error de OBS que se solucionará con la Pull Request #3335 de la Gitgub de obs-studio (github . com / obsproject / obs-studio / pull / 3335)

Instalé el Pull Request y compilé OBS, modifiqué el código pero, al ejecutar las líneas del servidor, OBS permanece inutilizable, bloqueado. Entonces, probé el “Servidor Async” - “Modo Concurrente” de python-osc. Tomo el ejemplo de su wiki en python-osc . readthedocs . io / en / latest / server . html (que en una cosola funciona 10 puntos) y lo mezclé con el otro script. Hice un hermoso código… pero hace algo extraño. Este es el código:

"""

"""
# osc data

import argparse
import random
import time
import math
import asyncio

from pythonosc import osc_message_builder
from pythonosc import udp_client

from pythonosc.dispatcher import Dispatcher
from pythonosc.osc_server import AsyncIOOSCUDPServer

client = None
server = None

#obs !
import obspython as obs
pleaseLog = False

host = None
serverPort = None
# transport = None

async def loop():
    """Example main loop that only runs for 10 iterations before finishing"""
    for i in range(10):
        print(f"Loop {i}")
        await asyncio.sleep(.5)

async def init_main():
    # global transport
    
    server = AsyncIOOSCUDPServer((host, serverPort), dispatcher, asyncio.get_event_loop())
    transport, protocol = await server.create_serve_endpoint()  # Create datagram endpoint and start serving
    
    await loop()  # Enter main loop of program
    transport.close()  # Clean up serve endpoint

def handleOSC(*args):
    for i in args:
        print(i)

# defines script description 
def script_description():
    return '''Send OSC data when source is activated if source name begins with /'''

# defines user properties
def script_properties():
    global props 
    props = obs.obs_properties_create()
    obs.obs_properties_add_text(props, "host", "Host IP", obs.OBS_TEXT_DEFAULT)
    obs.obs_properties_add_int(props, "clientPort", "Host port", 1, 400000, 1)
    obs.obs_properties_add_bool(props, "logOscOutput", "Log OSC output")
    obs.obs_properties_add_int(props, "serverPort", "Listen port", 1, 400000, 1)
    return props

def script_defaults(settings):
    obs.obs_data_set_default_string(settings, "host", "127.0.0.1")
    obs.obs_data_set_default_int(settings, "clientPort", 10000)
    obs.obs_data_set_default_int(settings, "serverPort", 10001)

def source_activated(cd):
    global pleaseLog
    source = obs.calldata_source(cd, "source")
    if source is not None:
        name = obs.obs_source_get_name(source)
        if name[0] == "/":
            client.send_message(name, 1)
            if (pleaseLog):
                print("send " + name)

def script_load(settings):
    global dispatcher
    global host
    
    sh = obs.obs_get_signal_handler()
    obs.signal_handler_connect(sh, "source_activate", source_activated)

    dispatcher = Dispatcher()
    dispatcher.map("/*", handleOSC)

# def script_unload():
#   global transport
#   print(f'script_unload(settings)')
#   transport.close()  # Clean up serve endpoint

def script_update(settings):
    global host
    global client
    global server
    global clientPort
    global serverPort
    global pleaseLog

    pleaseLog = obs.obs_data_get_bool(settings, "logOscOutput")
    host = obs.obs_data_get_string(settings, "host")
    clientPort = obs.obs_data_get_int(settings, "clientPort")
    serverPort = obs.obs_data_get_int(settings, "serverPort")
    
    # Client
    client = udp_client.SimpleUDPClient(host, clientPort)
    print("target set to "+host+":"+str(clientPort)+"")
    
    # Server
    print("serving in "+host+":"+str(serverPort)+"")
    asyncio.run(init_main())

No soy programador, así que asyncio es un quilombo para mí, no lo entiendo. Pero puede que sepa qué está haciendo… y lo que me gustaría que hiciese.

Cuando se carga el script (en script_update(settings)), abre el servidor y ejecuta la función loop(). Esta función es un bucle de 5 segundos que imprime algún texto. Si me conecto al puerto correcto desde PureData y envío algunos mensajes de OSC, estos mensajes llegan a OBS … pero todos caen juntos cuando finaliza la sentencia for dentro de loop(). Mientras tanto, no hay nada, OBS está bloqueado y no hay nada en Script Log.

Si ejecuto el código de ejemplo de python-osc asyncio en una consola, mientras se ejecuta el bucle, cada Loop 0, Loop 1, etc. y cada mensaje OSC que le mando llegan y todos se imprimen en el momento adecuado.

¿Cómo hago para que este código funcione? Necesito abrir ese servidor y ejecutar mucho más código al mismo tiempo. Estoy usando OBS como un motor de juego.

Como no puedo editar el mensaje de arriba, digo acá que el Pull Request me genera un Segment Fault en cierto momento. Pero me sugirieron que cargue D_PRELOAD=/path/libpython3.7.so antes de ejecutar OBS. De esta manera, parecería que funciona todo 10 puntos. Igualmente, el problema no está resuelto, necesito cargar el server de python-osc y seguir ejectutando Python mientras escucha el puerto. Todavía eso no lo solucioné.