@ -34,7 +34,7 @@ def nothing(*args): pass
class SupportedProgramsDatabase ( object ) :
""" Find all binaries with NSM support. Resources are:
* Argodejo internal program list of known working programs .
* Internal blacklist of known redundant programs ( such as non - daw ) or nonsense entries , like Argodejo itself
* Internal blacklist of known redundant programs ( such as non - daw ) or nonsense entries , like Argodejo itself
* A search through the users path to find stray programs that contain NSM announce messages
* Finally , local to a users system : User whitelist for any program , user blacklist .
Those two have the highest priority .
@ -59,12 +59,12 @@ class SupportedProgramsDatabase(object):
"""
def __init__ ( self ) :
def __init__ ( self ) :
self . progressHook = nothing #prevents the initial programstart from sending meaningless messages for the cached data. Set and reverted in self.build
self . grepexcluded = ( pathlib . Path ( PATHS [ " share " ] , " grepexcluded.txt " ) ) #created by hand. see docstring
#assert self.grepexcluded.exists()
self . blacklist = ( " nsmd " , " non-daw " , " carla " , " argodejo " , " adljack " ) #only programs that have to do with audio and music. There is another general blacklist that speeds up discovery
self . blacklist = ( " nsmd " , " non-daw " , " carla " , " argodejo " , " adljack " , " argodejo.bin " ) #only programs that have to do with audio and music. There is another general blacklist that speeds up discovery
self . whiteList = ( " thisdoesnotexisttest " , " patroneo " , " vico " ,
" fluajho " , " carla-rack " , " carla-patchbay " , " carla-jack-multi " , " carla-jack-single " ,
" ardour5 " , " ardour6 " , " nsm-data " , " jackpatch " , " nsm-proxy " , " ADLplug " , " ams " ,
@ -72,7 +72,7 @@ class SupportedProgramsDatabase(object):
" luppp " , " non-mixer " , " non-timeline " , " non-sequencer " , " non-midi-mapper " , " non-mixer-noui " ,
" OPNplug " , " qmidiarp " , " qtractor " , " zynaddsubfx " , " jack_mixer " ,
" hydrogen " , " mfp " , " shuriken " , " laborejo " , " guitarix " , " radium " ,
" ray-proxy " , " ray-jackpatch " , " amsynth " ,
" ray-proxy " , " ray-jackpatch " , " amsynth " , " midikeyboard " ,
) #shortcut list and programs not found by buildCache_grepExecutablePaths because they are just shellscripts and do not contain /nsm/server/announce.
self . userWhitelist = ( ) #added dynamically to morePrograms. highest priority
self . userBlacklist = ( ) #added dynamically to blacklist. highest priority
@ -111,17 +111,17 @@ class SupportedProgramsDatabase(object):
excludeFromProcessingSet = set ( self . blacklist + self . userBlacklist )
whiteSet = set ( self . whiteList + self . userWhitelist )
excludeFromProcessingSet . update ( whiteSet )
for path in executablePaths :
self . progressHook ( f " { path } " )
command = f " grep --exclude-from { self . grepexcluded } -iRsnl { path } -e /nsm/server/announce "
#command = f"grep -iRsnl {path} -e /nsm/server/announce"
command = f " grep --exclude-from { self . grepexcluded } -iRsnl { path } -e /nsm/server/announce "
#command = f"grep -iRsnl {path} -e /nsm/server/announce"
#Py>=3.7 completedProcess = subprocess.run(command, capture_output=True, text=True, shell=True)
completedProcess = subprocess . run ( command , stdout = subprocess . PIPE , stderr = subprocess . PIPE , universal_newlines = True , shell = True ) #universal_newlines is an alias for text, which was deprecated in 3.7 because text is more understandable. capture_output replaces the two PIPEs in 3.7
for fullPath in completedProcess . stdout . split ( ) :
self . progressHook ( f " { fullPath } " )
exe = pathlib . Path ( fullPath ) . relative_to ( path )
exe = pathlib . Path ( fullPath ) . relative_to ( path )
if not str ( exe ) in excludeFromProcessingSet : #skip over any known file, good or bad
result . append ( ( str ( exe ) , str ( fullPath ) ) )
@ -131,7 +131,7 @@ class SupportedProgramsDatabase(object):
if pathlib . Path ( path , prg ) . is_file ( ) : #check if this actually exists
result . append ( ( str ( prg ) , str ( pathlib . Path ( path , prg ) ) ) )
break #inner loop
return list ( set ( result ) ) #make unique
def buildCache_DesktopEntries ( self ) :
@ -154,12 +154,12 @@ class SupportedProgramsDatabase(object):
entryDict = dict ( config . _sections [ " Desktop Entry " ] )
#Replace simple names in our shortcut list with full data
if f . name in self . knownDesktopFiles . values ( ) :
key = self . _reverseKnownDesktopFiles [ f . name ]
self . knownDesktopFiles [ key ] = entryDict
key = self . _reverseKnownDesktopFiles [ f . name ]
self . knownDesktopFiles [ key ] = entryDict
#in any case:
allDesktopEntries . append ( entryDict ) #_sections 'DesktopEntry':{dictOfActualData)
except : #any bad config means skip
logger . warning ( f " Bad desktop file. Skipping: { f } " )
logger . warning ( f " Bad desktop file. Skipping: { f } " )
return allDesktopEntries
def loadPrograms ( self , listOfDicts ) :
@ -174,8 +174,8 @@ class SupportedProgramsDatabase(object):
#receives one string which indicates what files is currently parsed.
#Just the pure path, this will not get translated!
#The purpose is to show a "we are not frozen!" feedback to the user.
#It doesn't really matter what is reported back as long as it changes often
self . progressHook = progressHook
#It doesn't really matter what is reported back as long as it changes often
self . progressHook = progressHook
logger . info ( " Building launcher database. This might take a minute " )
self . progressHook ( " " )
@ -190,7 +190,7 @@ class SupportedProgramsDatabase(object):
def _exeToDesktopEntry ( self , exe : str ) - > dict :
""" Assumes self.desktopEntries is up to date
Convert one exe ( not full path ! ) to one dict entry . """
if exe in self . knownDesktopFiles : #Shortcut through internal database
if exe in self . knownDesktopFiles : #Shortcut through internal database
entry = self . knownDesktopFiles [ exe ]
return entry
else : #Reverse Search desktop files.
@ -258,7 +258,7 @@ class SupportedProgramsDatabase(object):
result = [ ]
executablePaths = [ pathlib . Path ( p ) for p in os . environ [ " PATH " ] . split ( os . pathsep ) ]
for path in executablePaths :
self . progressHook ( f " { path } " )
self . progressHook ( f " { path } " )
result + = [ str ( pathlib . Path ( f ) . relative_to ( path ) ) for f in path . glob ( " * " ) if isexe ( f ) ]
return sorted ( list ( set ( result ) ) )