Skip to content

Commit

Permalink
Merge pull request #23 from FlachyJoe/dev
Browse files Browse the repository at this point in the history
Run PDServer in a QTimer
  • Loading branch information
FlachyJoe authored Oct 1, 2021
2 parents bc4d0b8 + b1d52d4 commit 699788e
Show file tree
Hide file tree
Showing 10 changed files with 188 additions and 142 deletions.
13 changes: 7 additions & 6 deletions InitGui.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,13 @@
#
###################################################################################

import fcpdwb_locator as locator

def QT_TRANSLATE_NOOP(scope, text):
return text

class FCPDWorkbench(Workbench):

global QT_TRANSLATE_NOOP
global locator
def QT_TRANSLATE_NOOP(scope, text):
return text

import fcpdwb_locator as locator

MenuText = "FCPD"
ToolTip = QT_TRANSLATE_NOOP("FCPDWorkbench", "Pure-Data connection")
Expand All @@ -40,6 +38,7 @@ class FCPDWorkbench(Workbench):

def __init__(self):
self.pdProcess = None
self.pdServer = None

def Initialize(self):
"This function is executed when FreeCAD starts"
Expand Down Expand Up @@ -78,6 +77,8 @@ def userPref(self):

def Activated(self):
"This function is executed when the workbench is activated"
if self.pdServer is None:
self.Initialize()
return

def Deactivated(self):
Expand Down
21 changes: 14 additions & 7 deletions fcpdwb_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,22 +32,26 @@

FCPD = locator.getFCPDWorkbench()


def QT_TRANSLATE_NOOP(scope, text):
return text


# shortcuts of FreeCAD console
Log = App.Console.PrintLog
Msg = App.Console.PrintMessage
Wrn = App.Console.PrintWarning
Err = App.Console.PrintError


class FCPD_CommandLaunch():
"""Launch Pure-Data"""

def GetResources(self):
return {'Pixmap': locator.icon('FCPDLogo.svg'),
'MenuText': QT_TRANSLATE_NOOP("FCPD_Launch", "Launch Pure-Data"),
'ToolTip': QT_TRANSLATE_NOOP("FCPD_Launch", "Launch Pure-Data and connect it to the internal server.")}
'ToolTip': QT_TRANSLATE_NOOP("FCPD_Launch", "Launch Pure-Data and connect it"
" to the internal server.")}

def Activated(self):
if FCPD.pdProcess is None or FCPD.pdProcess.poll() is not None:
Expand All @@ -65,8 +69,10 @@ def Activated(self):

with open(os.path.join(locator.PATH, clientTemplate), 'r') as f:
clientContents = f.read()
clientContents = clientContents.replace('%FCLISTEN%', str(FCPD.userPref().GetInt('fc_listenport')))
clientContents = clientContents.replace('%PDLISTEN%', str(FCPD.userPref().GetInt('pd_defaultport')))
clientContents = clientContents.replace('%FCLISTEN%',
str(FCPD.userPref().GetInt('fc_listenport')))
clientContents = clientContents.replace('%PDLISTEN%',
str(FCPD.userPref().GetInt('pd_defaultport')))

clientFilePath = os.path.join(locator.PATH, 'client.pd')
with open(clientFilePath, 'w') as f:
Expand Down Expand Up @@ -94,15 +100,15 @@ class FCPD_CommandRun():
def GetResources(self):
return {'Pixmap': locator.icon('start.png'),
'MenuText': QT_TRANSLATE_NOOP("FCPD_Run", "Run Pure-Data server"),
'ToolTip': QT_TRANSLATE_NOOP("FCPD_Run", "Run the internal server and let Pure-Data to connect to.")}
'ToolTip': QT_TRANSLATE_NOOP("FCPD_Run", "Run the internal server and let"
" Pure-Data to connect to.")}

def Activated(self):
serv = FCPD.pdServer
if not serv.isRunning:
serv.setConnectParameters(FCPD.userPref().GetString('fc_listenaddress', 'localhost'),
FCPD.userPref().GetInt('fc_listenport', 8888))
serv.run(withDialog=False)
# WARNING Doesn't return until server termination !
serv.run()
return

def IsActive(self):
Expand Down Expand Up @@ -138,7 +144,8 @@ class FCPD_CommandAddInclude():
def GetResources(self):
return {'Pixmap': locator.icon('new-include.png'),
'MenuText': QT_TRANSLATE_NOOP("FCPD_AddInclude", "Create a PDInclude object"),
'ToolTip': QT_TRANSLATE_NOOP("FCPD_AddInclude", "Create a PDInclude object to store a PD patch in the FreeCAD document.")}
'ToolTip': QT_TRANSLATE_NOOP("FCPD_AddInclude", "Create a PDInclude object to store"
" a PD patch in the FreeCAD document.")}

def Activated(self):
import pdinclude
Expand Down
2 changes: 2 additions & 0 deletions fcpdwb_locator.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
ICONS_PATH = os.path.join(PATH, 'Icons')
TRANSLATIONS_PATH = os.path.join(PATH, 'Translations')


def icon(filename):
return os.path.join(ICONS_PATH, filename)


def getFCPDWorkbench():
import FreeCADGui
return FreeCADGui.getWorkbench('FCPDWorkbench')
13 changes: 8 additions & 5 deletions pdcontroler.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
Wrn = App.Console.PrintWarning
Err = App.Console.PrintError


class PDControler:
def __init__(self, obj, controlerInput, controlerOutput):

Expand All @@ -48,7 +49,7 @@ def __init__(self, obj, controlerInput, controlerOutput):
def onChanged(self, obj, prop):
if str(prop) == 'Group':
if (hasattr(self, "controlerInput") and
hasattr(self, "controlerOutput")):
hasattr(self, "controlerOutput")):
obj.Group = [self.controlerInput, self.controlerOutput]

def resetIncommingProperties(self):
Expand Down Expand Up @@ -107,7 +108,7 @@ def setProperty(self, ind, typ, value):

# App:PropertyRotation doesn't exist so store it in a placement
if typ == 'rotation':
value = App.Placement(App.Vector(0,0,0), value)
value = App.Placement(App.Vector(0, 0, 0), value)

if not hasattr(self.controlerInput, name):
self.setIncommingPropertyType(ind, typ)
Expand Down Expand Up @@ -176,24 +177,26 @@ def execute(self, obj):
def __getstate__(self):
return None


def isPDControler(obj):
if hasattr(obj, 'Proxy') and hasattr(obj.Proxy, 'Type'):
return obj.Proxy.Type == "PDControler"
return False


def create(pdServer, dollarZero):
# get an existent PDControler or create new one
if hasattr(App.ActiveDocument,"OutgoingData"):
if hasattr(App.ActiveDocument, "OutgoingData"):
pdOut = App.ActiveDocument.OutgoingData
else:
pdOut = App.ActiveDocument.addObject('App::FeaturePython', 'OutgoingData')

if hasattr(App.ActiveDocument,"IncommingData"):
if hasattr(App.ActiveDocument, "IncommingData"):
pdIn = App.ActiveDocument.IncommingData
else:
pdIn = App.ActiveDocument.addObject('App::FeaturePython', 'IncommingData')

if hasattr(App.ActiveDocument,"PDControler"):
if hasattr(App.ActiveDocument, "PDControler"):
obj = App.ActiveDocument.PDControler
else:
obj = App.ActiveDocument.addObject('App::DocumentObjectGroupPython', 'PDControler')
Expand Down
3 changes: 1 addition & 2 deletions pdcontrolertools.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def pdCtrlr(pdServer, words):
pdControler = pdcontroler.create(pdServer, words[0])
_, values = PDMsgTranslator.popValues(words[2:])
# create a list of (ind, ROValue)
duplet = [(values[i].value, values[i+1]) for i in range(0,len(values),2)]
duplet = [(values[i].value, values[i+1]) for i in range(0, len(values), 2)]

for (ind, val) in duplet:
pdControler.Proxy.setProperty(ind, val.type, val.value)
Expand All @@ -71,4 +71,3 @@ def pdNewCtrlr(pdServer, words):
pdControler.Proxy.setIncommingPropertyType(ind, t)
for ind, t in enumerate(outTyp):
pdControler.Proxy.setOutgoingPropertyType(ind, t)

15 changes: 14 additions & 1 deletion pdinclude.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from PyQt5 import QtCore

import FreeCAD as App
import FreeCADGui as Gui

import fcpdwb_locator as locator

Expand All @@ -38,6 +39,7 @@
Wrn = App.Console.PrintWarning
Err = App.Console.PrintError


class PDInclude:
def __init__(self, obj):
obj.Proxy = self
Expand All @@ -48,7 +50,16 @@ def __init__(self, obj):
def startEdit(self):
sFile = self.object.PDFile
pdServer = locator.getFCPDWorkbench().pdServer
if sFile and pdServer.isRunning :
if sFile:
if not pdServer or not pdServer.isRunning:
Gui.activateWorkbench("FCPDWorkbench")
Gui.runCommand("FCPD_Launch")
pdServer = locator.getFCPDWorkbench().pdServer
Log('wait for PureData\n')
while pdServer.isWaiting:
Gui.updateGui()
Log('PureData is ready\n')

_, self.tmpFile = tempfile.mkstemp()
shutil.copyfile(sFile, self.tmpFile)
dirName, fileName = os.path.split(self.tmpFile)
Expand All @@ -69,6 +80,7 @@ def onDocumentRestored(self, obj):
def __getstate__(self):
return None


class PDIncludeViewProvider:
def __init__(self, vobj, obj):
vobj.Proxy = self
Expand All @@ -79,6 +91,7 @@ def doubleClicked(self, vobj):
def __getstate__(self):
return None


def create():
obj = App.ActiveDocument.addObject('App::FeaturePython', 'PDInclude')
PDInclude(obj)
Expand Down
14 changes: 9 additions & 5 deletions pdmsgtranslator.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
Wrn = App.Console.PrintWarning
Err = App.Console.PrintError


class PDMsgTranslator:
NOT_SET = ''
FLOAT = 'App::PropertyFloat'
Expand All @@ -53,7 +54,7 @@ class PDMsgTranslator:
LONG_TYPES = ['empty', 'float', 'integer', 'vector', 'rotation', 'placement', 'list', 'boolean',
'string', 'object', 'quantity', 'angle']

objectsStore = [] # store binary untextable objects to get them back by reference
objectsStore = [] # store binary untextable objects to get them back by reference

## Return a string representation of a value
# @param self
Expand Down Expand Up @@ -100,7 +101,7 @@ def valueFromStr(cls, words):
# float...
retValue = float(words[0])
retType = cls.FLOAT
if int(retValue) == retValue :
if int(retValue) == retValue:
# ...or int
retValue = int(retValue)
retType = cls.INT
Expand All @@ -115,7 +116,8 @@ def valueFromStr(cls, words):
retType = cls.ROTATION
usedWords = 4
elif words[0] == "Placement":
retValue = App.Placement(cls.valueFromStr(words[1:5])[0].value, cls.valueFromStr(words[5:])[0].value)
retValue = App.Placement(cls.valueFromStr(words[1:5])[0].value,
cls.valueFromStr(words[5:])[0].value)
retType = cls.PLACEMENT
usedWords = 9
elif words[0] == "list":
Expand All @@ -141,9 +143,11 @@ def valueFromStr(cls, words):
elif words[0].startswith('"'):
# String
# find closing quote
strLen = [i for (i, w) in enumerate(words) if isinstance(w, str) and w.endswith('"')][0] + 1
strLen = [i for (i, w) in enumerate(words)
if isinstance(w, str) and w.endswith('"')
][0] + 1
# create the string
retValue = ' '.join(map(str, words[:strLen])).replace('"','')
retValue = ' '.join(map(str, words[:strLen])).replace('"', '')
retType = cls.STRING
usedWords = strLen
elif words[0].startswith("^"):
Expand Down
37 changes: 23 additions & 14 deletions pdrawtools.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ def simpleObj(x, y, typ):
return "#X obj %i %i %s;\n" % (x, y, typ)


def canvas(x, y, width, height, label, background, foreground):
return "#X obj {0} {1} cnv {2} {3} {2} empty empty {4} 8 12 0 13 {5} {6} 0;\n".format(
x, y, width, height, label, background, foreground)


def triggerAB(x, y, count):
return "#X obj %i %i t a %s;\n" % (x, y, "b " * count)

Expand Down Expand Up @@ -136,10 +141,10 @@ def getCleanDoc(func):
docstr = docStart + docEnd
else:
docstr = docLines[0]
return docstr.replace(",", " \, ").replace("\n", " \; ")
return docstr.replace(",", " \\, ").replace("\n", " \\; ")


def generate(func, call, dirname, paramCount = -1):
def generate(func, call, dirname, paramCount=-1):
'''generate a pd patch to overlay a python function'''
func_name = func.__name__
if not func_name.startswith("_"):
Expand Down Expand Up @@ -192,7 +197,7 @@ def generate(func, call, dirname, paramCount = -1):
return False


def generateHelp(func, objectName, dirname, paramCount = -1):
def generateHelp(func, objectName, dirname, paramCount=-1):
'''generate a pd help patch to document a python function'''
func_name = func.__name__
if not func_name.startswith("_"):
Expand All @@ -201,32 +206,36 @@ def generateHelp(func, objectName, dirname, paramCount = -1):
if paramCount == -1:
paramCount = len(params)
hlp = "#N canvas 436 36 550 620 10;\n"
hlp += "#X obj 0 0 cnv 15 550 40 empty empty %s/%s 3 12 0 18 #c4dcdc #000000 0;\n" % (objectName.lower(), pdname)
hlp += simpleObj(400, 10, "%s/%s" % (objectName.lower(), pdname))
hlp += canvas(0, 0, 15, 550,
"{}/{}".format(objectName.lower(), pdname), "#c4dcdc", "#000000")
hlp += simpleObj(400, 10, "{}/{}".format(objectName.lower(), pdname))
# DESC
doc = getCleanDoc(func)
hlp += text(10, 50, doc)
descHeight = 50 + 20 * len(doc.split("\;"))
descHeight = 50 + 20 * len(doc.split("\\;"))
# INLETS
hlp += "#X obj 0 %i cnv 3 550 3 empty empty inlets 8 12 0 13 #dcdcdc #000000 0;\n" % descHeight
hlp += canvas(0, descHeight, 3, 550, "inlets", "#dcdcdc", "#000000")
for i in range(paramCount):
hlp += "#X obj 78 %i cnv 17 3 17 empty \$0-pddp.cnv.let.%i %i 5 9 0 16 #dcdcdc #9c9c9c 0;\n" % (descHeight + 20 + 30*i, i, i)
hlp += canvas(78, descHeight + 20 + 30*i, 17, 3, i, "#dcdcdc", "#9c9c9c")
if i <= len(params):
p = params[i]
else:
p = ''
hlp += text(100, descHeight + 20 + 30*i, p)
# OUTLETS
hlp += "#X obj 0 %i cnv 3 550 3 empty empty outlets 8 12 0 13 #dcdcdc #000000 0;\n" % (descHeight + 20 + 30*paramCount)
hlp += "#X obj 78 %i cnv 17 3 17 empty empty 0 5 9 0 16 #dcdcdc #9c9c9c 0;\n" % (descHeight + 50 + 30*paramCount)
hlp += canvas(0, descHeight + 20 + 30*paramCount, 3, 550, "outlets", "#dcdcdc", "#000000")
hlp += canvas(78, descHeight + 50 + 30*paramCount, 17, 3, "0", "#dcdcdc", "#9c9c9c")
hlp += text(100, descHeight + 50 + 30*paramCount, "Result of the operation")
# ARGUMENTS
hlp += "#X obj 0 %i cnv 3 550 3 empty empty arguments 8 12 0 13 #dcdcdc #000000 0;\n" % (descHeight + 110 + 30*paramCount)
hlp += canvas(0, descHeight + 110 + 30*paramCount, 3, 550,
"arguments", "#dcdcdc", "#000000")
# MORE INFO
hlp += "#X obj 0 %i cnv 3 550 3 empty empty more_info 8 12 0 13 #dcdcdc #000000 0;\n" % (descHeight + 170 + 30*paramCount)
hlp += text(10, descHeight + 190 + 30*paramCount, "This object and its help was autogenerated by FCPD_Workbench")
hlp += canvas(0, descHeight + 170 + 30*paramCount, 3, 550,
"more_info", "#dcdcdc", "#000000")
hlp += text(10, descHeight + 190 + 30*paramCount,
"This object and its help was autogenerated by FCPD_Workbench")
# FOOTER
hlp += "#X obj 0 %i cnv 15 550 15 empty empty empty 20 12 0 14 #dcdcdc #404040 0;\n" % (descHeight + 230 + 30*paramCount)
hlp += canvas(0, descHeight + 230 + 30*paramCount, 15, 550, "", "#dcdcdc", "#404040")

if not os.path.isdir(dirname):
os.makedirs(dirname)
Expand Down
Loading

0 comments on commit 699788e

Please sign in to comment.