GeIdentifyFile usage

On 19/05/2018 at 21:38, xxxxxxxx wrote:

User Information:
Cinema 4D Version:   R19 
Platform:   Windows  ;   
Language(s) :     C++  ;


I am trying to parse a folder for C4D scene files, checking on the suffix of files being equal to "c4d".
This works fine on Windows systems, but I am not sure the same will work on MacOS as I remember from pre-OSX times that no actual filename extensions were used.

Instead I looked at a more generic solution and found the GeIdentifyFile function in the SDK, however I am not getting any valid results from using it, as it always returns IDENTIFYFILE_0. Which, according the documentation, means the identification failed.

Following is part of the implementation I used:

    AutoAlloc<BrowseFiles> fileBrowser;  
  if (!fileBrowser)  
      return FALSE;  
  Filename path = GetPath(); // custom method  
  Int32 probeSize = 1024;  
  UChar* probe = NewMemClear(UChar, probeSize);  
  while (fileBrowser->GetNext())  
      Filename fn = fileBrowser->GetFilename();  
      IDENTIFYFILE idf = GeIdentifyFile(fn, probe, probeSize, IDENTIFYFILE_SCENE, nullptr);  
      GePrint("File " + fn.GetString() + " = " + String::IntToString(idf));  

On 21/05/2018 at 14:21, xxxxxxxx wrote:

Hi C4DS, thanks for writing us.

With regard to your request, there's a point causing your code to fail: you're allocating an memory chunk filled of zeros instead of grabbing a small chunk of data from the head of the fie as suggested in the GeIdentifyFile documentation.

Fix it and it should work like a charm.

Best, Riccardo

On 22/05/2018 at 00:37, xxxxxxxx wrote:

Since the function requires a filename as first parameter I assumed the function would read the necessary information, and that I only had to provide for a buffer to read.

But apparently I need to read an amount of bytes from the file myself, and pass that to the GeIdentifyFile function. Didn't interpret the documentation that way.

So why should I then still pass a filename? To me that doesn't make much sense.

On 22/05/2018 at 05:50, xxxxxxxx wrote:

Hi C4D, thanks for following up.

Actually the way the GeIndentifyFile has been designed is to provide the best functionality and flexibility even with formats not supported by default by Cinema. Under this scenario GeIdentifyFile() acts as a tunnelling system to SceneLoaderData derived plugins which, implementing the Identify() method, are giving Cinema the ability to identify custom scene-related files.

I also recommend to make use of the BaseFile class to load the initial chunk of the probed file in order to pass the data to GeIdentifyFile().

Best, Riccardo

On 22/05/2018 at 10:00, xxxxxxxx wrote:

Thanks again Riccardo.
Got it working in the end ... once you made me realize I needed to read the data myself.

For current and future readers here's the code I came up with:

// check if a file is a C4D scene file  
// return TRUE when provided filename is C4D scene, FALSE otherwise  
Bool FileIsC4DSCENE(const Filename& filename)  
  // poor man's solution is to check the suffix of the file  
  //return filename.CheckSuffix("c4d");  
  // on MacOS this is probably not sufficient, since  
  // that OS doesn't actually use file extensions  
  // (at least that was the case pre-MacOSX, as far as I remember)  
  // Use the GeIdentifyFile function instead  
  AutoAlloc<BaseFile> file;  
  if (file && file->Open(filename, FILEOPEN_READ, FILEDIALOG_NONE, BYTEORDER_INTEL))  
      Int32 probeSize = 128;  
      UChar* probe = NewMemClear(UChar, probeSize);  
      if (probe)  
          probeSize = (Int32)file->TryReadBytes(probe, probeSize);  
          if (probeSize)  
              idf = GeIdentifyFile(filename, probe, probeSize, IDENTIFYFILE_SCENE, nullptr);  
  return (idf == IDENTIFYFILE_SCENE);  

Note that the "poor man's solution" does detect a regular text file with "c4d" extension as being a C4D scene file ... which it obviously isn't. So, better to use the GeIdentifyFile solution.