javascriptdom-eventsair

Adobe Air with Javascript, making a program wait while running nativeProcess


I'm trying to extract metadata from video files by running ffprobe using nativeProcess. The code below works just as it should for one file, but causes an error when trying to loop through a series of files.

I know the cause of the problem is that Air tries to start a new nativeProcess before the old one is finished. I know it's something to do with listening to the air.NativeProcessExitEvent.EXIT. I just can't get it to work. Any suggestions would be greatly appreciated.

function fileOpen(){
    
  var directory = air.File.userDirectory;
  
  try
  {
      directory.browseForDirectory("Select Directory");
      directory.addEventListener(air.Event.SELECT, directorySelected);
  }
  catch (error)
  {
      air.trace("Failed:", error.message)
  }
  
  function directorySelected(event) 
  {
      directory = event.target ;
      var files = directory.getDirectoryListing();
      for(i=0; i < files.length; i++){
        getMetadata(files[0].nativePath)
                    //wait here for nativeProcess to finish
        }
      }
  } 

function getMetadata(filePathIn){
    
         
        if(air.NativeProcess.isSupported)
        {
            
        }
        else
        {
            air.trace("NativeProcess not supported.");
        }
    
        fileIn = filePathIn.toString()

        var nativeProcessStartupInfo = new air.NativeProcessStartupInfo();
        var file = air.File.applicationStorageDirectory.resolvePath("ffprobe");
        nativeProcessStartupInfo.executable = file;

        args = new air.Vector["<String>"]();
        args.push("-sexagesimal","-show_format","-loglevel","quiet","-show_streams","-print_format","json",filePathIn)
        nativeProcessStartupInfo.arguments = args;

        process = new air.NativeProcess();
        process.start(nativeProcessStartupInfo); 
        process.addEventListener(air.ProgressEvent.STANDARD_OUTPUT_DATA, onOutputData);
        process.addEventListener(air.ProgressEvent.STANDARD_ERROR_DATA, onErrorData);
        process.addEventListener(air.NativeProcessExitEvent.EXIT, onExit);
        process.addEventListener(air.IOErrorEvent.STANDARD_OUTPUT_IO_ERROR, onIOError);
        process.addEventListener(air.IOErrorEvent.STANDARD_ERROR_IO_ERROR, onIOError);
        
        
    }

    function onOutputData()
    {
      var fileMetadataJSON = process.standardOutput.readUTFBytes(process.standardOutput.bytesAvailable);
      air.trace(fileMetadataJSON)
    }
    
    function onErrorData(event)
    {
        air.trace("ERROR -", process.standardError.readUTFBytes(process.standardError.bytesAvailable)); 
    }
    
    function onExit(event)
    {
        air.trace("Process exited with ", event.exitCode);
    
    }
    
    function onIOError(event)
    {
         air.trace(event.toString());
    }
    

Solution

  • Here an outline that should give you an idea of what to do:

    The idea here is to move the code that runs the native process into a method that you can trigger from two places: once immediately after the user finishes browsing for files, and then again after the native process finishes it's work. The process ends when the files array has no more files in it.