Posts: 6,340
Threads: 272
Joined: Oct 2016
Reputation:
563
Operating system(s):
Gimp version: 2.10
01-09-2024, 05:31 PM
(This post was last modified: 01-09-2024, 06:11 PM by Ofnuts.)
(01-09-2024, 01:12 PM)JBreckeen Wrote: Thanks for the discussion.
I stepped away from this plugin for a bit - had to do some work. I have gotten the "outbound" part of my integration working by having the Gimp plugin write a command .json and have my bridge script pick it up and do its thing.
But the issue I am having is trying to get the "looping" script to be able to execute an inbound command in Gimp. The simple version would be that I want to have the Gimp plugin (running under Gimp's py2.7) constantly checking the command directory for a .json, and when it finds one it executes something such as
pdb.gimp_file_save(image, drawable, savePath, savePath).
If I setup a static function that checks the directory once during the plugin load, it works. But as soon as I put in checking loop (which is blocking of course), then Gimp will not continue the load. So then I move the checking loop to a thread, but whenever I try to connect the threads, I get a crash. I believe it comes from the two processes being in separate threads.
So what I really need is to have some way that the checking loop can execute the Gimp commands in Gimp's thread.
Hope that makes sense,
JBreckeen.
Looking at my code that runs in parallel with Gimp, the code doesn't use the simplified registration you have for Python-fu plugins with an auto-generated arguments dialog. It runs a registration "closer to the metal".
Posts: 13
Threads: 5
Joined: Jan 2024
Reputation:
0
Operating system(s):
- Windows Vista or 7, 8, 10 (64-bit)
Gimp version: 2.12
Hello all - mainly Ofnuts!. So back at doing some work on this. I was able to get the Gimp->Prism Pipeline outbound comms to work. But now I am trying to get the inbound to work. I had to divide this up into three scripts:
- Prism_Menu: registers the menu items and sends cli command's to the bridge (outbound)
- Prism_Bridge: does not register as a plugin and runs in Py3.11 and communicates with Prism (outbound)
- Prism_Functions: registers as a plugin, starts the script server, and will execute python-fu procedures. (inbound)
I am using 2.99 (yes I know it is in development), but it is working for us and by the time I finally get this finished I don't want to write it again.
So to get my external script coming from Prism to communicate with Gimp, I have started using the script server - I could never get a non-blocking listening script to work.
The external script is sending:
f'(python-fu-prism-saveAction "{filepath}")'
to the script server and is being receiving correctly:
ScriptFu server: received request #0 from IP address 127.0.0.1: (python-fu-prism-saveAction "N:/Data/Projects/Prism Tests/01_Production/Assets/Building/Scenefiles/gimp/Paint/Building_Paint_v003.xcf"),[queue length: 1] on Thu Apr 18 11:15:52 2024
But I need my functions plugin to be able to parse the arg of the file path it receives to use in the procedure (this is just the first bit of functionality - when I get this all working I will add more procedures). As you can see with all the commented-out lines, I have tried a bunch of things I have found around the web. But I cannot get anything to work. If I hardcode the filePath either in the saveAction(), or PrismFunctions(Gimp.PlugIn) it works, but I cannot get it to use the passed argument.
So it boils down to does anybody know how to pass the received argument to the callback function?
FYI: I might either be missing something simple, there may be a completely better way to do this, or it cannot be done in Gimp.
In the below code, the "data" print statement always show "data" is empty.
Prism_Fuctions.py:
...other code...
def saveAction(procedure, run_mode, data):
print("\n*** IN saveAction ***\n") # DEBUG
print("*** data: ", data, "\n\n")
# filePath = data["filePath"]
# print("*** filePath: ", filePath, "\n\n")
# filePath = r"C:\tmp\Building_Paint_v001.xcf" # HARDCODED FOR TESTING
### vvvv WORKING vvvvv ####
# images = pdb.gimp_get_images()
# imageList = images[1]
# currentImage = imageList.data[0]
# file = Gio.File.new_for_path(filePath)
# # Save the image in the .xcf file format
# pdb.gimp_xcf_save(image=currentImage , file=file)
### ^^^^ WORKING ^^^^ ####
return procedure.new_return_values(Gimp.PDBStatusType.SUCCESS, GLib.Error())
class PrismFunctions(Gimp.PlugIn):
def __init__(self):
super().__init__()
self._filePath = "" # NEEDED???
## Parameter: filePath ##
# @GObject.Property(type=str,
# nick= _("File Path"),
# blurb= _("File Path"))
# def filePath(self):
# return self._filePath
# def set_filePath(self, file_path):
# self._filePath = file_path
# @filePath.setter
# def filePath(self, filePath):
# self._filePath = filePath
__gproperties__ = {
"filePath": (
str,
_("filePath"),
"File Path",
"File Path",
GObject.ParamFlags.READWRITE,
)
}
## GimpPlugIn virtual methods ##
def do_set_i18n(self, procname):
return True, 'gimp30-python', None
def do_query_procedures(self):
return [ "python-fu-prism-saveAction" ]
def do_create_procedure(self, name):
procedure = None
if name == 'python-fu-prism-saveAction':
data = {"filePath": None}
procedure = Gimp.Procedure.new(self,
name,
Gimp.PDBProcType.PLUGIN,
# Gimp.PDBProcType.EXTENSION, # Change to EXTENSION ???
saveAction,
data
)
procedure.set_documentation(_("Prism save action"),
help_doc,
"")
procedure.set_attribution("Joshua Breckeen",
"Prism Pipeline",
"2024")
procedure.add_argument_from_property(self, "filePath")
# procedure.set_property("filePath", self._filePath)
# # Get the list of arguments
# arguments = procedure.get_arguments()
# # The first (and only) argument should be the filePath
# file_path = arguments[0]
# # Set the filePath property with the received value
# self.filePath = file_path
else:
procedure = None
return procedure
print("***** Loading Prism Functions ******") # DEBUG
time.sleep(.1)
Gimp.main(PrismFunctions.__gtype__, sys.argv)
Posts: 6,340
Threads: 272
Joined: Oct 2016
Reputation:
563
Operating system(s):
Gimp version: 2.10
Asking the obvious but you have:
Code:
def saveAction(procedure, run_mode, data):
But in script-fu you don't use the run-mode argument, so I wonder if your data wouldn't end up in the run_mode argument.
Also, you have this very complex architecture because you want to use Pythonv3 for your main code, but since you moved to Gimp3 you are now using Python v3 on the Gimp side of things so maybe you can simplify all this?
Posts: 13
Threads: 5
Joined: Jan 2024
Reputation:
0
Operating system(s):
- Windows Vista or 7, 8, 10 (64-bit)
Gimp version: 2.12
But in script-fu you don't use the run-mode argument, so I wonder if your data wouldn't end up in the run_mode argument.
Good point. As you know the docs are pretty scarce and I sorta had to add/remove args until it stopped throwing errors. When you suggested that I got excited and tried. But unfortunately, not. It appears the second arg is:
<__gi__.GimpProcedureConfig-python-fu-prism-saveAction object at 0x000001b7ffd3fec0 (GimpProcedureConfig-python-fu-prism-saveAction at 0x000001b7ff9fdcc0)>
Also, you have this very complex architecture because you want to use Pythonv3 for your main code, but since you moved to Gimp3 you are now using Python v3 on the Gimp side of things so maybe you can simplify all this?
And thought of that. But Gimp's Py3 does not play well with the Qt elements and enviro of the pipeline stuff. And also I thought it best to keep it separate since Gimp's Py and our VFX Py will not necessarily be consistently in sync. This was also since I could not get a listening script to work in Gimp 2 or 3, so chose 3.
But still have the issue of trying to get an argument passed to the procedure. Unless there is another way?
Posts: 13
Threads: 5
Joined: Jan 2024
Reputation:
0
Operating system(s):
- Windows Vista or 7, 8, 10 (64-bit)
Gimp version: 2.12
Just a follow up. I decided to still use a bridge between Gimp and the pipeline (Prism) - to be able to handle different versions of each. I have it mostly working, with a lot of frustration on the way. But found some ways to help in the coding. And I thank you for the suggestions.
The architecture is now:
- a Gimp plugin that registers the menu items, and each menu item will call a subprocess.Popen to the bridge. The bridge will load Prism into its own Py3 enviro.
- another Gimp plugin that launches from the menu that will start a loop that opens a socket between this plugin and Prism. This is inside the Gimp enviro. When a command is received from Prism, it will execute inside Gimp and sends back a response on the socket.
That is actually working pretty well and doesn't seem to fail. A pleasant surprise.
I have this working on Gimp 2.10, but I should be able to adapt it to 2.99(3) as well.
But I do have some other questions that I will put in another thread.
J.
|