Exiftool stay_open / Swift / MacOS

Started by greybeard, August 30, 2024, 10:03:19 AM

Previous topic - Next topic

greybeard

I've searched and there are quite a few posts about stay_open but I've not seen any discussion on running Exiftool as a process within a swift program under MacOS.

The problem I'm having is that when a standard output pipe is read in the program, and you aren't reading to end of file (which you aren't because the pipe stays open in stay_open) then exiftool data are read in chunks. The chunks are read one at a time and you have to know when to stop reading because the read of an empty pipe is blocking.

The techniques I've used are:
- for text data I look for "{ready}" and stop reading
- for binary data (such as a preview image) I first read the size of the image and then read the image size (plus 8 bytes for the "{ready}")

This is not very elegant and prone to possible error.

Can anyone point me to a better solution?

ChatGPT is convinced that there is a low level method to detect when the pipe contains data but the supplied example doesn't work.

Phil Harvey

There must be a way to execute a non-blocking read.  If not, then Swift is a rather pathetic language, and I would drop it entirely and switch to C++.  I have written many data-processing apps on Mac using Objective C and C++, and many of them require this feature, but I've never used Swift.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

greybeard

The answer appears to be to set up an async pipe reading function and look for the "{ready}\n" suffix.

I'd be very reluctant to move away from SwiftUI as that is where all the Apple development effort is going. The new frameworks are written to interface with Swift.

Its also the easiest way to write graphical applications that will work on the Mac and also iPad/iPhone.

Phil Harvey

That will work...  Reading the pipe from another thread.  I should have thought of that.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

FrankB

I recommend a separate thread for reading stderr and stdout.

Experienced hangs in ExiftoolGui when a lot was written to stderr.

greybeard

Quote from: FrankB on August 31, 2024, 12:36:45 PMI recommend a separate thread for reading stderr and stdout.

Experienced hangs in ExiftoolGui when a lot was written to stderr.

Thanks for the tip - I'm assuming that if I get anything on standard error its probably a programming error but I'll monitor it during testing

FrankB

Quote from: greybeard on August 31, 2024, 01:38:34 PMThanks for the tip - I'm assuming that if I get anything on standard error its probably a programming error but I'll monitor it during testing

Not necessarily. Could also be an inconsistency in the file(s) you're processing. Let me explain what happened to me.

I received a lot of JPG's (5000+) from someone else. I wanted to clear some tag by using:

-tag= -r -ext jpg

But ExifTool emitted some warning on nearly every one. (Cant remember exactly which, but it was one that you could skip with -m)

If you only start reading stderr after stdout has completed ({readxxx} is written) then likely it will hang up. The buffer for stderr gets full.

In ExifToolGui this is my approach:

- Write the same ready prompt to stderr and stdout using -echo4 {readyxx} and -executexx.
- start a thread for reading stdout until {readyxx} is found
- start a thread for reading stderr until {readyxx} is found
- wait in the main thread until both are finished.

I dont know it it helps, but for the Delphi Pascal source have a look at:
(Method ET_StayOpen, line:326)

https://github.com/FrankBijnen/ExifToolGui/blob/main/Source/ExifTool.pas

Definition of TSOReadPipeThread

https://github.com/FrankBijnen/ExifToolGui/blob/main/Source/ExifTool_PipeStream.pas