@ -43,19 +43,19 @@ class Callbacks(object):
Or whatever parallel representations we run . """
def __init__ ( self ) :
self . message = [ ]
self . message = [ ]
#Session Management
self . sessionOpenReady = [ ]
self . sessionOpenLoading = [ ]
self . sessionClosed = [ ]
self . sessionOpenReady = [ ]
self . sessionOpenLoading = [ ]
self . sessionClosed = [ ]
self . sessionsChanged = [ ] #update in the file structure. redraw list of sessions.
self . sessionLocked = [ ] # incremental update. Sends the name of the session project and a bool if locked
self . sessionFileChanged = [ ] #incremental update. Reports the session name, not the session file
self . clientStatusChanged = [ ] #every status including GUI and dirty
self . singleInstanceActivateWindow = [ ] #this is for the single-instance feature. Show the GUI window and activate it when this signal comes.
self . dataClientNamesChanged = [ ]
self . dataClientDescriptionChanged = [ ]
self . dataClientNamesChanged = [ ]
self . dataClientDescriptionChanged = [ ]
def _dataClientNamesChanged ( self , data ) :
""" If there is a dataclient in the session it will allow us to read and write metadata.
@ -67,8 +67,8 @@ class Callbacks(object):
dataclient can join and leave at every time , we keep the GUI informed . """
for func in self . dataClientNamesChanged :
func ( data )
def _dataClientDescriptionChanged ( self , data ) :
def _dataClientDescriptionChanged ( self , data ) :
""" see _dataClientNamesChanged.
In short : str for data , None if nsm - data leaves session """
for func in self . dataClientDescriptionChanged :
@ -105,12 +105,12 @@ class Callbacks(object):
Always sends a full update of everything , with no indication of what changed . """
listOfProjectDicts = nsmServerControl . exportSessionsAsDicts ( )
for func in self . sessionsChanged :
for func in self . sessionsChanged :
func ( listOfProjectDicts )
return listOfProjectDicts
def _sessionLocked ( self , name : str , status : bool ) :
""" Called by the Watcher through the event loop
Name is " nsmSessionName " from _nsmServerControl . exportSessionsAsDicts
@ -124,7 +124,7 @@ class Callbacks(object):
Called by the Watcher through the event loop .
Name is " nsmSessionName " from _nsmServerControl . exportSessionsAsDicts .
timestamp has same format as nsmServerControl . exportSessionsAsDicts """
timestamp has same format as nsmServerControl . exportSessionsAsDicts """
for func in self . sessionFileChanged :
func ( name , timestamp )
@ -136,12 +136,12 @@ class Callbacks(object):
func ( clientInfoDict )
def startEngine ( ) :
def startEngine ( ) :
logger . info ( " Start Engine " )
global eventLoop
assert eventLoop
global nsmServerControl
nsmServerControl = NsmServerControl (
sessionOpenReadyHook = callbacks . _sessionOpenReady ,
@ -153,22 +153,22 @@ def startEngine():
dataClientDescriptionHook = callbacks . _dataClientDescriptionChanged ,
parameterNsmOSCUrl = PATHS [ " url " ] ,
sessionRoot = PATHS [ " sessionRoot " ] ,
)
#Watch session tree for changes.
global sessionWatcher
sessionWatcher = Watcher ( nsmServerControl )
sessionWatcher . timeStampHook = callbacks . _sessionFileChanged
sessionWatcher . lockFileHook = callbacks . _sessionLocked
sessionWatcher . sessionsChangedHook = callbacks . _sessionsChanged #This is the main callback that informs of new or updated sessions
callbacks . sessionClosed . append ( sessionWatcher . resume ) #Watcher only active in "Choose a session mode"
)
#Watch session tree for changes.
global sessionWatcher
sessionWatcher = Watcher ( nsmServerControl )
sessionWatcher . timeStampHook = callbacks . _sessionFileChanged
sessionWatcher . lockFileHook = callbacks . _sessionLocked
sessionWatcher . sessionsChangedHook = callbacks . _sessionsChanged #This is the main callback that informs of new or updated sessions
callbacks . sessionClosed . append ( sessionWatcher . resume ) #Watcher only active in "Choose a session mode"
callbacks . sessionOpenReady . append ( sessionWatcher . suspend )
eventLoop . slowConnect ( sessionWatcher . process )
eventLoop . slowConnect ( sessionWatcher . process )
#Start Event Loop Processing
eventLoop . fastConnect ( nsmServerControl . process )
eventLoop . slowConnect ( nsmServerControl . processSingleInstance )
#Send initial data
#The decision if we are already in a session on startup or in "choose a session mode" is handled by callbacks
#This is not to actually gather the data, but only to inform the GUI.
@ -179,8 +179,11 @@ def startEngine():
#of a session-on-load:
if PATHS [ " startupSession " ] :
logger . info ( f " Got start-session as command line parameter. Opening: { PATHS [ ' startupSession ' ] } " )
sessionOpen ( PATHS [ " startupSession " ] )
sessionOpen ( PATHS [ " startupSession " ] )
PATHS [ " continueLastSession " ] = None #just in case
#Info
def sessionRoot ( ) :
return nsmServerControl . sessionRoot
@ -191,12 +194,12 @@ def currentSession():
def sessionList ( ) - > list :
""" Updates the list each call. Use only this from a GUI for active query.
Otherwise sessionRemove and sessionCopy will not have updated the list """
r = nsmServerControl . exportSessionsAsDicts ( )
r = nsmServerControl . exportSessionsAsDicts ( )
return [ s [ " nsmSessionName " ] for s in r ]
def buildSystemPrograms ( ) :
""" Build a list of dicts with the .desktop files (or similar) of all NSM compatible programs
present on the system """
present on the system """
programDatabase . build ( )
def systemProgramsSetWhitelist ( executableNames : tuple ) :
@ -211,14 +214,14 @@ def systemProgramsSetBlacklist(executableNames:tuple):
def getSystemPrograms ( ) - > list :
""" Returns the cached database from buildProgramDatabase. No automatic update. Empty on program
start """
start """
return programDatabase . programs
def setSystemsPrograms ( listOfDicts : list ) :
programDatabase . loadPrograms ( listOfDicts )
def setSystemsPrograms ( listOfDicts : list ) :
programDatabase . loadPrograms ( listOfDicts )
def getNsmExecutables ( ) - > set :
""" Cached access fort fast membership tests. Is this program in the PATH? """
""" Cached access fort fast membership tests. Is this program in the PATH? """
return programDatabase . nsmExecutables
def getUnfilteredExecutables ( ) - > list :
@ -233,7 +236,7 @@ def getUnfilteredExecutables()->list:
#No project running
#There is no callback for _sessionsChanged because we poll that in the event loop.
def sessionNew ( newName : str , startClients : list = [ ] ) :
def sessionNew ( newName : str , startClients : list = [ ] ) :
nsmServerControl . new ( newName , startClients )
def sessionRename ( nsmSessionName : str , newName : str ) :
@ -242,21 +245,21 @@ def sessionRename(nsmSessionName:str, newName:str):
def sessionCopy ( nsmSessionName : str , newName : str ) :
""" Create a copy of the session. Removes the lockfile, if any.
Has some safeguards inside so it will not crash . """
Has some safeguards inside so it will not crash . """
nsmServerControl . copySession ( nsmSessionName , newName )
def sessionOpen ( nsmSessionName : str ) :
""" Saves the current session and loads a different existing session. """
""" Saves the current session and loads a different existing session. """
nsmServerControl . open ( nsmSessionName )
def sessionQuery ( nsmSessionName : str ) :
""" For the occasional out-of-order information query.
Exports a single session project in the format of nsmServerControl . exportSessionsAsDicts """
Exports a single session project in the format of nsmServerControl . exportSessionsAsDicts """
return nsmServerControl . sessionAsDict ( nsmSessionName )
def sessionForceLiftLock ( nsmSessionName : str ) :
nsmServerControl . forceLiftLock ( nsmSessionName )
callbacks . _sessionLocked ( nsmSessionName , False )
callbacks . _sessionLocked ( nsmSessionName , False )
def sessionDelete ( nsmSessionName : str ) :
nsmServerControl . deleteSession ( nsmSessionName )
@ -268,7 +271,7 @@ def sessionSave():
def sessionClose ( blocking = False ) :
""" Saves and closes the current session. """
nsmServerControl . close ( blocking )
nsmServerControl . close ( blocking )
def sessionAbort ( blocking = False ) :
""" Close without saving the current session. """
@ -295,8 +298,8 @@ def clientResume(clientId:str):
nsmServerControl . clientResume ( clientId )
def clientRemove ( clientId : str ) :
""" Client must be already stopped! We will do that without further question.
Remove from the session . Will not delete the save - files , but make them inaccesible """
""" Client must be already stopped! We will do that without further question.
Remove from the session . Will not delete the save - files , but make them inaccesible """
nsmServerControl . clientRemove ( clientId )
def clientSave ( clientId : str ) :
@ -327,8 +330,8 @@ def executableInSession(executable:str)->dict:
else returns a dict with its export - data .
If multiple clients with this exe are in the session only one is returned , whatever Python
thinks is good """
for clientId , dic in nsmServerControl . internalState [ " clients " ] . items ( ) :
if executable == dic [ " executable " ] :
for clientId , dic in nsmServerControl . internalState [ " clients " ] . items ( ) :
if executable == dic [ " executable " ] :
return dic
else :
return None