You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
119 lines
4.7 KiB
119 lines
4.7 KiB
#! /usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
Copyright 2022, Nils Hilbricht, Germany ( https://www.hilbricht.net )
|
|
|
|
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ),
|
|
|
|
This application is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
"""
|
|
|
|
import logging; logger = logging.getLogger(__name__); logger.info("import")
|
|
|
|
import os, socket, asyncio
|
|
from signal import signal, SIGTERM, SIGUSR1
|
|
from threading import Thread
|
|
from sys import argv
|
|
|
|
from .nsmclient import _IncomingMessage, _OutgoingMessage
|
|
|
|
|
|
|
|
class NSMProtocol(asyncio.DatagramProtocol):
|
|
directory = None
|
|
addr = None #a cache
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
def connection_made(self, transport):
|
|
self.transport = transport
|
|
def datagram_received(self, data, addr):
|
|
NSMProtocol.addr = addr
|
|
|
|
msg = _IncomingMessage(data)
|
|
if msg.oscpath == "/nsm/server/announce":
|
|
application_name, capabilities, executable_name, api_version_major, api_version_minor, pid = msg.params
|
|
NSMProtocol.pid = pid
|
|
reply = _OutgoingMessage("/reply")
|
|
reply.add_arg("/nsm/server/announce")
|
|
reply.add_arg("Welcome!")
|
|
reply.add_arg("Fake Save Server")
|
|
reply.add_arg("server-control:")
|
|
self.send(reply, addr)
|
|
|
|
#['/home/user/NSM Sessions/dev-example/QtCboxNsm Exämple ツ.nXDBM', 'dev-example', 'QtCboxNsm Exämple ツ.nXDBM']
|
|
openMsg = reply = _OutgoingMessage("/nsm/client/open")
|
|
openMsg.add_arg(NSMProtocol.directory)
|
|
openMsg.add_arg("NOT-A-SESSION")
|
|
openMsg.add_arg(application_name)
|
|
self.send(openMsg, addr)
|
|
|
|
self.send(_OutgoingMessage("/nsm/client/show_optional_gui"), addr)
|
|
|
|
elif msg.oscpath == "/nsm/gui/client/save":
|
|
self.send(_OutgoingMessage("/nsm/client/save"), addr)
|
|
elif msg.oscpath == "/nsm/client/gui_is_hidden":
|
|
os.kill(NSMProtocol.pid, SIGTERM)
|
|
elif msg.oscpath == "/nsm/server/stop":
|
|
os.kill(NSMProtocol.pid, SIGTERM)
|
|
#else:
|
|
# print (msg.oscpath, msg.params)
|
|
|
|
def send(self, message, addr):
|
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
|
|
sock.sendto(message.build(), addr)
|
|
|
|
@staticmethod
|
|
def staticSave(*args):
|
|
NSMProtocol.send(None, _OutgoingMessage("/nsm/client/save"), NSMProtocol.addr)
|
|
|
|
|
|
def startSingleNSMServer(directory):
|
|
"""Set all paths like NSM would receive them and nsmclient.py expects them."""
|
|
|
|
serverSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
serverSock.bind(('', 0)) # Bind to a free port provided by the host.
|
|
SERVER_PORT = serverSock.getsockname()[1]
|
|
NSMProtocol.directory = directory
|
|
serverSock.close()
|
|
|
|
os.environ["NSM_URL"] = f"osc.udp://localhost:{SERVER_PORT}/"
|
|
executableName = os.path.basename(argv[0])
|
|
executableDir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
|
##assert os.path.exists(os.path.join(executableDir, executableName)) not valid anymore with zipapp. But it worked for years, so I guess the code is ok.
|
|
argv[0] = os.path.join(executableDir, executableName) #NSM speciality. nsmclient exlicitely checks for this
|
|
os.environ["PATH"] = os.environ["PATH"] + ":" + executableDir
|
|
#print (argv[0])
|
|
#print (executableName)
|
|
#print (executableDir)
|
|
#print(os.environ["PATH"])
|
|
#print(os.environ["NSM_URL"])
|
|
|
|
#loop = asyncio.get_event_loop()
|
|
#loop.create_task(asyncio.start_server(handle_client, 'localhost', SERVER_PORT))
|
|
#loop.run_forever()
|
|
#asyncio.run(asyncio.start_server(handle_client, 'localhost', SERVER_PORT))
|
|
|
|
logger.info(f"Starting fake NSM server on port {SERVER_PORT}")
|
|
|
|
#For Carla:
|
|
signal(SIGUSR1, NSMProtocol.staticSave)
|
|
|
|
loop = asyncio.get_event_loop()
|
|
def run_loop(loop):
|
|
asyncio.set_event_loop(loop)
|
|
t = loop.create_datagram_endpoint(NSMProtocol,local_addr=('127.0.0.1',SERVER_PORT), family=socket.AF_INET)
|
|
loop.run_until_complete(t)
|
|
loop.run_forever()
|
|
Thread(target=lambda: run_loop(loop), daemon=True).start() #Daemon makes the thread just stop when main thread ends.
|
|
|