|
|
@ -1,13 +1,12 @@ |
|
|
|
#! /usr/bin/env python3 |
|
|
|
# -*- coding: utf-8 -*- |
|
|
|
""" |
|
|
|
PyNSMClient - A Non Session Manager Client-Library in one file. |
|
|
|
PyNSMClient - A New Session Manager Client-Library in one file. |
|
|
|
|
|
|
|
The Non-Session-Manager by Jonathan Moore Liles <male@tuxfamily.org>: http://non.tuxfamily.org/nsm/ |
|
|
|
New Session Manager, by LinuxAudio.org: https://github.com/linuxaudio/new-session-manager |
|
|
|
With help from code fragments from https://github.com/attwad/python-osc ( DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE v2 ) |
|
|
|
|
|
|
|
API documentation: http://non.tuxfamily.org/nsm/API.html |
|
|
|
|
|
|
|
MIT License |
|
|
|
|
|
|
|
Copyright 2014-2020 Nils Hilbricht https://www.laborejo.org |
|
|
@ -276,8 +275,8 @@ class NSMClient(object): |
|
|
|
elif loggingLevel == "error" or loggingLevel == 40: |
|
|
|
logging.basicConfig(level=logging.ERROR) #production |
|
|
|
else: |
|
|
|
raise ValueError("Unknown logging level: {}. Choose 'info' or 'error'".format(loggingLevel)) |
|
|
|
|
|
|
|
logging.warning("Unknown logging level: {}. Choose 'info' or 'error'".format(loggingLevel)) |
|
|
|
logging.basicConfig(level=logging.INFO) #development |
|
|
|
|
|
|
|
#given parameters, |
|
|
|
self.prettyName = prettyName #keep this consistent! Settle for one name. |
|
|
@ -303,7 +302,6 @@ class NSMClient(object): |
|
|
|
#self.discardReactions = set(["/nsm/client/session_is_loaded"]) |
|
|
|
self.discardReactions = set() |
|
|
|
|
|
|
|
|
|
|
|
#Networking and Init |
|
|
|
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #internet, udp |
|
|
|
self.sock.bind(('', 0)) #pick a free port on localhost. |
|
|
@ -324,7 +322,9 @@ class NSMClient(object): |
|
|
|
self.ourClientId = None # the "file extension" of ourClientNameUnderNSM |
|
|
|
self.isVisible = None #set in announceGuiVisibility |
|
|
|
self.saveStatus = True # true is clean. false means we need saving. |
|
|
|
|
|
|
|
self.announceOurselves() |
|
|
|
|
|
|
|
assert self.serverFeatures, self.serverFeatures |
|
|
|
assert self.sessionName, self.sessionName |
|
|
|
assert self.ourPath, self.ourPath |
|
|
@ -336,6 +336,8 @@ class NSMClient(object): |
|
|
|
#We assume we are save at startup. |
|
|
|
self.announceSaveStatus(isClean = True) |
|
|
|
|
|
|
|
logger.info("NSMClient client init complete. Going into listening mode.") |
|
|
|
|
|
|
|
|
|
|
|
def reactToMessage(self): |
|
|
|
"""This is the main loop message. It is added to the clients event loop.""" |
|
|
@ -381,7 +383,7 @@ class NSMClient(object): |
|
|
|
"""Return and save the nsm osc url or raise an error""" |
|
|
|
nsmOSCUrl = getenv("NSM_URL") |
|
|
|
if not nsmOSCUrl: |
|
|
|
raise NSMNotRunningError("Non-Session-Manager environment variable $NSM_URL not found.") |
|
|
|
raise NSMNotRunningError("New-Session-Manager environment variable $NSM_URL not found.") |
|
|
|
else: |
|
|
|
#osc.udp://hostname:portnumber/ |
|
|
|
o = urlparse(nsmOSCUrl) |
|
|
@ -418,6 +420,8 @@ class NSMClient(object): |
|
|
|
else: |
|
|
|
return "" |
|
|
|
|
|
|
|
logger.info("Sending our NSM-announce message") |
|
|
|
|
|
|
|
announce = _OutgoingMessage("/nsm/server/announce") |
|
|
|
announce.add_arg(self.prettyName) #s:application_name |
|
|
|
announce.add_arg(buildClientFeaturesString()) #s:capabilities |
|
|
@ -458,7 +462,7 @@ class NSMClient(object): |
|
|
|
replyToOpen.add_arg("{} is opened or created".format(self.prettyName)) |
|
|
|
self.sock.sendto(replyToOpen.build(), self.nsmOSCUrl) |
|
|
|
else: |
|
|
|
raise ValueError("Unexpected message path after announce".format((msg.oscpath, msg.params))) |
|
|
|
raise ValueError("Unexpected message path after announce: {}".format((msg.oscpath, msg.params))) |
|
|
|
|
|
|
|
def announceGuiVisibility(self, isVisible): |
|
|
|
message = "/nsm/client/gui_is_shown" if isVisible else "/nsm/client/gui_is_hidden" |
|
|
@ -492,8 +496,10 @@ class NSMClient(object): |
|
|
|
|
|
|
|
def _sessionIsLoadedCallback(self, msg): |
|
|
|
if self.sessionIsLoadedCallback: |
|
|
|
logger.info("Telling our client that the session has finished loading") |
|
|
|
logger.info("Received 'Session is Loaded'. Our client supports it. Forwarding message...") |
|
|
|
self.sessionIsLoadedCallback() |
|
|
|
else: |
|
|
|
logger.info("Received 'Session is Loaded'. Our client does not support it, which is the default. Discarding message...") |
|
|
|
|
|
|
|
def sigtermHandler(self, signal, frame): |
|
|
|
"""Wait for the user to quit the program |
|
|
|