From e401bd9c78a82b8290ec524e56b7c832631725e6 Mon Sep 17 00:00:00 2001
From: Dennis Real <github@tildepipe.org>
Date: Wed, 21 Mar 2012 19:47:15 +0100
Subject: [PATCH] 1. Own module for nikon maker notes 2. Support for AFInfo2

---
 src/exif.c       |  99 ++++--------------
 src/exif.h       |   5 +
 src/exif_nikon.c | 265 +++++++++++++++++++++++++++++++++++++++++++++++
 src/exif_nikon.h |  14 +--
 4 files changed, 296 insertions(+), 87 deletions(-)
 create mode 100644 src/exif_nikon.c

diff --git a/src/exif.c b/src/exif.c
index 6f6440f..91e1735 100644
--- a/src/exif.c
+++ b/src/exif.c
@@ -28,6 +28,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <stdio.h>
 #include <string.h>
 #include <libexif/exif-data.h>
+#include <limits.h>
 
 #include "feh.h"
 #include "options.h"
@@ -36,15 +37,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "exif_nikon.h"
 #include "exif_cfg.h"
 
-static void exif_trim_spaces(char *str);
-static void exif_get_tag(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, unsigned int maxsize);
-static void exif_get_tag_content(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, unsigned int maxsize);
-static void exif_get_mnote_tag(ExifData *d, unsigned int tag, char* buffer, unsigned int maxsize);
-static void exif_get_mnote_nikon_tags(ExifData *ed, char * buffer, unsigned int maxsize);
-static void exif_get_gps_coords(ExifData * ed, char *buffer, unsigned int maxsize);
 
 /* remove all spaces on the right end of a string */
-static void exif_trim_spaces(char *str)
+void exif_trim_spaces(char *str)
 {
   char *end;
   
@@ -52,20 +47,21 @@ static void exif_trim_spaces(char *str)
   {
     if (*str != ' ')
     {
-      end = str+1;
+      end = str + 1;
     }
   }
   *end = '\0';
 }
 
 
+
 /* show given exif tag content with tag name */
-static void exif_get_tag(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, unsigned int maxsize)
+void exif_get_tag(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, unsigned int maxsize)
 {
   char s[EXIF_MAX_DATA];
   ExifEntry *entry = NULL;
   
-  if ( (d != NULL) && (buffer != NULL) && (maxsize>0) )
+  if ( (d != NULL) && (buffer != NULL) && (maxsize > 0) )
   {
     entry = exif_content_get_entry(d->ifd[ifd], tag);
     if (entry != NULL) 
@@ -87,12 +83,12 @@ static void exif_get_tag(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, un
 
 
 /* show given exif tag content without tag name */
-static void exif_get_tag_content(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, unsigned int maxsize)
+void exif_get_tag_content(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, unsigned int maxsize)
 {
   char s[EXIF_MAX_DATA];
   ExifEntry *entry = NULL;
 
-  if ( (d != NULL) && (buffer != NULL) && (maxsize>0) )
+  if ( (d != NULL) && (buffer != NULL) && (maxsize > 0) )
   {
     entry = exif_content_get_entry(d->ifd[ifd], tag);
     if (entry != NULL) 
@@ -104,7 +100,7 @@ static void exif_get_tag_content(ExifData *d, ExifIfd ifd, ExifTag tag, char* bu
       exif_trim_spaces(s);
       if (*s != '\0')
       {
-        D(("%s", exif_tag_get_name_in_ifd(tag,ifd), s));
+        D(("%s - %s\n", exif_tag_get_name_in_ifd(tag,ifd), s));
         snprintf(buffer, (size_t)maxsize, "%s", s);
       }
     }
@@ -115,7 +111,7 @@ static void exif_get_tag_content(ExifData *d, ExifIfd ifd, ExifTag tag, char* bu
 
 
 /* Show the given MakerNote tag if it exists */
-static void exif_get_mnote_tag(ExifData *d, unsigned int tag, char* buffer, unsigned int maxsize)
+void exif_get_mnote_tag(ExifData *d, unsigned int tag, char* buffer, unsigned int maxsize)
 {
   ExifMnoteData *mn = NULL; 
   int i, num;
@@ -137,6 +133,11 @@ static void exif_get_mnote_tag(ExifData *d, unsigned int tag, char* buffer, unsi
     /* Loop through all MakerNote tags, searching for the desired one */
     for (i=0; i < num; ++i) 
     {
+      D(("%d/%d %d 0x%2x %s; %s\n", i, num, exif_mnote_data_get_id(mn, i), 
+        exif_mnote_data_get_id(mn, i),
+        exif_mnote_data_get_name(mn,i), 
+        exif_mnote_data_get_title(mn, i) ));
+      
       if (exif_mnote_data_get_id(mn, i) == tag) 
       {
         if (exif_mnote_data_get_value(mn, i, buf, sizeof(buf))) 
@@ -145,6 +146,7 @@ static void exif_get_mnote_tag(ExifData *d, unsigned int tag, char* buffer, unsi
           exif_trim_spaces(buf);
           if (*buf != '\0')
           {
+             D(("%s\n", buf));
              snprintf(buffer, (size_t)maxsize, "%s: %s\n", exif_mnote_data_get_title(mn, i), buf);
           }
         }
@@ -155,63 +157,8 @@ static void exif_get_mnote_tag(ExifData *d, unsigned int tag, char* buffer, unsi
 
 
 
-/* get interesting nikon maker note tags in readable form */
-static void exif_get_mnote_nikon_tags(ExifData *ed, char * buffer, unsigned int maxsize)
-{
-  char buf[EXIF_STD_BUF_LEN];
-  unsigned int exn_fcm = (EXN_FLASH_CONTROL_MODES_MAX-1); /* default to N/A */
-  unsigned int version = 0;
-  unsigned int length = 0;
-
-  buf[0] = '\0';
-  exif_get_tag(ed, EXIF_IFD_EXIF, EXIF_TAG_FLASH, buf, sizeof(buf));
-  exif_trim_spaces(buf);
-
-  if ( !(strcmp("Flash: Flash did not fire\n", buf) == 0) )
-  {
-    /* show extended flash info if flash was fired */
-  
-    /* Flash Setting */
-    exif_get_mnote_tag(ed, 8, buffer + strlen(buffer), maxsize - strlen(buffer));
-    /* Flash Mode */
-    exif_get_mnote_tag(ed, 9, buffer + strlen(buffer), maxsize - strlen(buffer));
-    /* flash exposure bracket value */
-    exif_get_mnote_tag(ed, 24, buffer + strlen(buffer), maxsize - strlen(buffer));
-    /* Flash used */
-    exif_get_mnote_tag(ed, 135, buffer + strlen(buffer), maxsize - strlen(buffer));
-
-    /* Flash info: control mode. */
-    /* libexif does not support flash info 168 yet. so we have to parse the debug data :-( */
-    buf[0] = '\0';
-    exif_get_mnote_tag(ed, 168, buf, sizeof(buf));
-    sscanf(buf, "(null): %u bytes unknown data: 303130%02X%*10s%02X", &length, &version, &exn_fcm);
-    exn_fcm = exn_fcm & EXN_FLASH_CONTROL_MODE_MASK;
-
-    if ( (exn_fcm < EXN_FLASH_CONTROL_MODES_MAX)
-         && ( ((length == 22) && (version == '3'))      /* Nikon FlashInfo0103 */
-              || ((length == 22) && (version == '4'))   /* Nikon FlashInfo0104 */
-              || ((length == 21) && (version == '2'))   /* Nikon FlashInfo0102 */
-              || ((length == 19) && (version == '0'))   /* Nikon FlashInfo0100 */
-            )
-       )
-    {
-      snprintf(buffer + strlen(buffer), maxsize - strlen(buffer), "NikonFlashControlMode: %s\n", 
-      EXN_NikonFlashControlModeValues[exn_fcm]);
-    }
-  }
-
-  /* Lens */
-  exif_get_mnote_tag(ed, 132, buffer + strlen(buffer), maxsize - strlen(buffer));
-  /* Digital Vari-Program */
-  exif_get_mnote_tag(ed, 171, buffer + strlen(buffer), maxsize - strlen(buffer));
-
-  return;
-}
-
-
-
 /* get gps coordinates if available */
-static void exif_get_gps_coords(ExifData * ed, char *buffer, unsigned int maxsize)
+void exif_get_gps_coords(ExifData * ed, char *buffer, unsigned int maxsize)
 {
   char buf[EXIF_STD_BUF_LEN];
   
@@ -297,7 +244,7 @@ void exif_get_info(ExifData * ed, char *buffer, unsigned int maxsize)
 {
   ExifEntry *entry = NULL;
   char buf[EXIF_STD_BUF_LEN];
-  int i = 0;
+  unsigned short int i = 0;
   
   if ( (buffer == NULL) || (maxsize == 0) )
   {
@@ -310,14 +257,14 @@ void exif_get_info(ExifData * ed, char *buffer, unsigned int maxsize)
   }
   else
   {
-    /* normal exif tags */
-    while ( Exif_tag_list[i].ifd != EXIF_IFD_COUNT )
+    /* show normal exif tags. list must be defined in exif_cfg.h  */
+    while ( (Exif_tag_list[i].ifd != EXIF_IFD_COUNT) && (i < USHRT_MAX) )
     {
       exif_get_tag(ed, Exif_tag_list[i].ifd, Exif_tag_list[i].tag, buffer + strlen(buffer), maxsize - strlen(buffer));
       i++; 
     }
 
-    /* vendor specific makernote tags */
+    /* show vendor specific makernote tags */
     entry = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_MAKE);
     if (entry != NULL) 
     {
@@ -332,14 +279,14 @@ void exif_get_info(ExifData * ed, char *buffer, unsigned int maxsize)
            )
         {
           /* this is a nikon camera */
-          exif_get_mnote_nikon_tags(ed, buffer + strlen(buffer), maxsize - strlen(buffer));
+          exn_get_mnote_nikon_tags(ed, buffer + strlen(buffer), maxsize - strlen(buffer));
         }
 
       }
       
     }
     
-    /* gps info */
+    /* show gps coordinates */
     exif_get_gps_coords(ed, buffer + strlen(buffer), maxsize - strlen(buffer));
 
   }
diff --git a/src/exif.h b/src/exif.h
index 5d7def4..79187f4 100644
--- a/src/exif.h
+++ b/src/exif.h
@@ -31,6 +31,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define EXIF_MAX_DATA 1024
 #define EXIF_STD_BUF_LEN 128
 
+extern void exif_trim_spaces(char *str);
+extern void exif_get_tag(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, unsigned int maxsize);
+extern void exif_get_tag_content(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, unsigned int maxsize);
+extern void exif_get_mnote_tag(ExifData *d, unsigned int tag, char* buffer, unsigned int maxsize);
+extern void exif_get_gps_coords(ExifData * ed, char *buffer, unsigned int maxsize);
 extern ExifData * exif_get_data(char *path);
 extern void exif_get_info(ExifData * ed, char *buffer, unsigned int maxsize);
 
diff --git a/src/exif_nikon.c b/src/exif_nikon.c
new file mode 100644
index 0000000..d9e83a1
--- /dev/null
+++ b/src/exif_nikon.c
@@ -0,0 +1,265 @@
+/* exif_nikon.c
+
+Copyright (C) 2012      Dennis Real.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies of the Software and its documentation and acknowledgment shall be
+given in the documentation and software packages that this Software was
+used.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+#ifdef HAVE_LIBEXIF
+
+#include <stdio.h>
+#include <string.h>
+#include <libexif/exif-data.h>
+
+#include "feh.h"
+#include "debug.h"
+#include "exif.h"
+#include "exif_nikon.h"
+
+
+/* Flash control mode */
+/* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#FlashControlMode */
+#define EXN_FLASH_CONTROL_MODES_MAX 9
+char *EXN_NikonFlashControlModeValues[EXN_FLASH_CONTROL_MODES_MAX] = {"Off", 
+                                       "iTTL-BL", "iTTL", "Auto Aperture", 
+                                       "Automatic", "GN (distance priority)", 
+                                       "Manual", "Repeating Flash", 
+                                       "N/A" /* "N/A" is not a nikon setting */
+                                       };
+
+#define EXN_FLASH_CONTROL_MODE_MASK 0x7F
+
+
+/* AFInfo2 */
+/* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#AFInfo2 */
+#define EXN_CONTRAST_DETECT_AF_MAX 2
+char *EXN_NikonContrastDetectAF[EXN_CONTRAST_DETECT_AF_MAX] = {"Off", "On"};
+
+/* AFArea Mode for ContrastDetectAF Off */
+#define EXN_AF_AREA_MODE_P_MAX 13
+char *EXN_NikonAFAreaModePhase[EXN_AF_AREA_MODE_P_MAX] = {
+  "Single Area", "Dynamic Area", "Dynamic Area (closest subject)",
+  "Group Dynamic ", "Dynamic Area (9 points) ", "Dynamic Area (21 points)",
+  "Dynamic Area (51 points) ", "Dynamic Area (51 points, 3D-tracking)",
+  "Auto-area", "Dynamic Area (3D-tracking)", "Single Area (wide)",
+  "Dynamic Area (wide)", "Dynamic Area (wide, 3D-tracking)"};
+
+/* AFArea Mode for ContrastDetectAF On */
+#define EXN_AF_AREA_MODE_C_MAX 5
+char *EXN_NikonAFAreaModeContr[EXN_AF_AREA_MODE_C_MAX] = {
+  "Contrast-detect", 
+  "Contrast-detect (normal area)", 
+  "Contrast-detect (wide area)", 
+  "Contrast-detect (face priority)", 
+  "Contrast-detect (subject tracking)"};
+
+#define EXN_PHASE_DETECT_AF_MAX 4
+char *EXN_NikonPhaseDetectAF[EXN_PHASE_DETECT_AF_MAX] = {"Off", "On (51-point)", 
+                                                         "On (11-point)", "On (39-point)"};
+
+/* PrimaryAFPoint and AFPointsUsed only valid with PhaseDetectAF == On */
+
+#define EXN_PRIM_AF_PT_51_MAX 52
+char * EXN_Prim_AF_Pt_51[EXN_PRIM_AF_PT_51_MAX] = {"(none)", "C6 (Center)", "B6", "A5",
+  "D6", "E5", "C7", "B7", "A6", "D7", "E6", "C5", "B5", "A4", "D5", "E4", "C8", "B8",
+  "A7", "D8", "E7", "C9", "B9", "A8", "D9", "E8", "C10", "B10", "A9", "D10", "E9",
+  "C11", "B11", "D11", "C4", "B4", "A3", "D4", "E3", "C3", "B3", "A2", "D3", "E2",
+  "C2", "B2", "A1", "D2", "E1", "C1", "B1", "D1"};
+  
+#define EXN_PRIM_AF_PT_11_MAX 12
+char * EXN_Prim_AF_Pt_11[EXN_PRIM_AF_PT_11_MAX] = {"(none)", "Center", "Top", "Bottom",
+  "Mid-left", "Upper-left", "Lower-left", "Far Left", "Mid-right", "Upper-right",
+  "Lower-right",  "Far Right"};
+
+#define EXN_PRIM_AF_PT_39_MAX 40
+char * EXN_Prim_AF_Pt_39[EXN_PRIM_AF_PT_39_MAX] = {"(none)", "C6 (Center)", "B6", "A2",
+  "D6", "E2", "C7", "B7", "A3", "D7", "E3", "C5", "B5", "A1", "D5", "E1", "C8", "B8",
+  "D8", "C9", "B9", "D9", "C10", "B10", "D10", "C11", "B11", "D11", "C4", "B4", "D4",
+  "C3", "B3", "D3", "C2", "B2", "D2", "C1", "B1", "D1"};
+
+
+static void exn_get_prim_af_pt(unsigned int phasedetectaf,
+                               unsigned int primafpt,
+                               char * buffer,
+                               unsigned int maxsize);
+                               
+                               
+                               
+
+static void exn_get_prim_af_pt(unsigned int phasedetectaf,
+                               unsigned int primafpt,
+                               char * buffer,
+                               unsigned int maxsize)
+{
+  
+  switch(phasedetectaf)
+  {
+    case 0:
+    {
+      /* phasedetect not used. should not happen */
+      snprintf(buffer, maxsize, "FAIL");
+      return;
+    }
+    break;
+    case 1:
+    {
+      /* 51 pt */
+      if ( primafpt < EXN_PRIM_AF_PT_51_MAX )
+      {
+        snprintf(buffer, maxsize, "%s", EXN_Prim_AF_Pt_51[primafpt]);
+      }
+      return;
+    }
+    break;
+    case 2:
+    {
+      /* 11 pt */
+      if ( primafpt < EXN_PRIM_AF_PT_11_MAX )
+      {
+        snprintf(buffer, maxsize, "%s", EXN_Prim_AF_Pt_11[primafpt]);
+      }
+      return;
+    }
+    break;
+    case 3:
+    {
+      /* 39 pt */
+      if ( primafpt < EXN_PRIM_AF_PT_39_MAX )
+      {
+        snprintf(buffer, maxsize, "%s", EXN_Prim_AF_Pt_39[primafpt]);
+      }
+      return;
+    }
+    break;
+    default:
+    {
+      snprintf(buffer, maxsize, "?");
+      return;    
+    }
+    break;
+  
+  }
+   
+}
+
+
+
+/* get interesting nikon maker note tags in readable form */
+void exn_get_mnote_nikon_tags(ExifData *ed, char * buffer, unsigned int maxsize)
+{
+  char buf[EXIF_STD_BUF_LEN];
+  unsigned int exn_fcm = (EXN_FLASH_CONTROL_MODES_MAX-1); /* default to N/A */
+  unsigned int version = 0;
+  unsigned int length = 0;
+  unsigned int contrastdetectaf = 0;
+  unsigned int afareamode = 0;
+  unsigned int phasedetectaf = 0;
+  unsigned int primaryafpoint = 0;
+
+  buf[0] = '\0';
+  exif_get_tag(ed, EXIF_IFD_EXIF, EXIF_TAG_FLASH, buf, sizeof(buf));
+  exif_trim_spaces(buf);
+
+  if ( !(strcmp("Flash: Flash did not fire\n", buf) == 0) )
+  {
+    /* show extended flash info if flash was fired */
+  
+    /* Flash Setting */
+    exif_get_mnote_tag(ed, 8, buffer + strlen(buffer), maxsize - strlen(buffer));
+    /* Flash Mode */
+    exif_get_mnote_tag(ed, 9, buffer + strlen(buffer), maxsize - strlen(buffer));
+    /* flash exposure bracket value */
+    exif_get_mnote_tag(ed, 24, buffer + strlen(buffer), maxsize - strlen(buffer));
+    /* Flash used */
+    exif_get_mnote_tag(ed, 135, buffer + strlen(buffer), maxsize - strlen(buffer));
+
+    /* Flash info: control mode. */
+    /* libexif does not support flash info 168 yet. so we have to parse the debug data :-( */
+    buf[0] = '\0';
+    exif_get_mnote_tag(ed, 168, buf, sizeof(buf));
+    sscanf(buf, "(null): %u bytes unknown data: 303130%02X%*10s%02X", &length, &version, &exn_fcm);
+    exn_fcm = exn_fcm & EXN_FLASH_CONTROL_MODE_MASK;
+
+    if ( (exn_fcm < EXN_FLASH_CONTROL_MODES_MAX)
+         && ( ((length == 22) && (version == '3'))      /* Nikon FlashInfo0103 */
+              || ((length == 22) && (version == '4'))   /* Nikon FlashInfo0104 */
+              || ((length == 21) && (version == '2'))   /* Nikon FlashInfo0102 */
+              || ((length == 19) && (version == '0'))   /* Nikon FlashInfo0100 */
+            )
+       )
+    {
+      snprintf(buffer + strlen(buffer), maxsize - strlen(buffer), "NikonFlashControlMode: %s\n", 
+        EXN_NikonFlashControlModeValues[exn_fcm]);
+    }
+  }
+
+  /* Lens */
+  exif_get_mnote_tag(ed, 132, buffer + strlen(buffer), maxsize - strlen(buffer));
+  /* Digital Vari-Program */
+  exif_get_mnote_tag(ed, 171, buffer + strlen(buffer), maxsize - strlen(buffer));
+
+  /* AFInfo2 */
+  /* libexif does not support AFInfo2 183 yet. so we have to parse the debug data :-( */
+  buf[0] = '\0';
+  exif_get_mnote_tag(ed, 183, buf, sizeof(buf));
+  sscanf(buf, "(null): %u bytes unknown data: 303130%02X%02X%02X%02X%02X", &length, &version, 
+    &contrastdetectaf,
+    &afareamode,
+    &phasedetectaf,
+    &primaryafpoint
+    );
+
+
+  if ( ((length == 30) && (version == '0'))
+       && (contrastdetectaf < EXN_CONTRAST_DETECT_AF_MAX)
+       && (phasedetectaf < EXN_PHASE_DETECT_AF_MAX)
+       
+     )
+  {
+    if ( (contrastdetectaf != 0) && (afareamode < EXN_AF_AREA_MODE_C_MAX) )
+    {
+      /* Contrast AF (live view) */
+      snprintf(buffer + strlen(buffer), maxsize - strlen(buffer), 
+        "ContrastDetectAF: %s; AFAreaMode: %s\n", 
+        EXN_NikonContrastDetectAF[contrastdetectaf],
+        EXN_NikonAFAreaModeContr[afareamode]);
+      
+    }
+    else if ( (phasedetectaf != 0) && (afareamode < EXN_AF_AREA_MODE_P_MAX) )
+    {
+      /* Phase AF */
+      buf[0] = '\0';
+      exn_get_prim_af_pt(phasedetectaf, primaryafpoint, buf, EXIF_STD_BUF_LEN);
+
+      snprintf(buffer + strlen(buffer), maxsize - strlen(buffer), 
+        "PhaseDetectAF: %s; AreaMode: %s; PrimaryAFPoint: %s\n", 
+        EXN_NikonPhaseDetectAF[phasedetectaf],
+        EXN_NikonAFAreaModePhase[afareamode],
+        buf
+        );
+    }
+    
+  }
+
+  return;
+}
+
+#endif
diff --git a/src/exif_nikon.h b/src/exif_nikon.h
index e2baf0d..f12b5ce 100644
--- a/src/exif_nikon.h
+++ b/src/exif_nikon.h
@@ -26,16 +26,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef EXIF_NIKON_H
 #define EXIF_NIKON_H
 
-/* Flash control mode */
-/* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#FlashControlMode */
-#define EXN_FLASH_CONTROL_MODES_MAX 9
-char *EXN_NikonFlashControlModeValues[EXN_FLASH_CONTROL_MODES_MAX] = {"Off", 
-                                       "iTTL-BL", "iTTL", "Auto Aperture", 
-                                       "Automatic", "GN (distance priority)", 
-                                       "Manual", "Repeating Flash", 
-                                       "N/A" /* "N/A" is not a nikon setting */
-                                       };
-
-#define EXN_FLASH_CONTROL_MODE_MASK 0x7F
+#include <libexif/exif-data.h>
+
+extern void exn_get_mnote_nikon_tags(ExifData *ed, char * buffer, unsigned int maxsize);
 
 #endif
-- 
GitLab