/*---------------------------------------------------------------------------*/
/* Eye-One  C-Style  API                                                     */
/* This API provides high-level methods to access the EyeOne device          */
/*                                                                           */
/* Version 3.3.1                                                             */
/*                                                                           */
/* Copyright (c) 2006 by GretagMacbeth AG Switzerland.                       */
/*                                                                           */
/* ALL RIGHTS RESERVED.                                                      */
/*                                                                           */
/* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS         */
/* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED         */
/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE        */
/* ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY           */
/* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL        */
/* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE         */
/* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS             */
/* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,              */
/* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING                 */
/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS        */
/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.              */
/*---------------------------------------------------------------------------*/
#ifndef EYEONE_H
#define EYEONE_H


#if (defined __GNUC__) && (__GNUC__ > 3)
  // gcc 4 hides all symbols by default
  // Throwable classes must always be visible on GCC in all binaries
  #define EYEONE_EXPORT __attribute__ ((visibility("default")))
#else
  #define EYEONE_EXPORT
#endif


#ifdef __cplusplus
  extern "C" {
    namespace I1SDK 
    {
      class EYEONE_EXPORT Exception
      {
        public:
          virtual ~Exception() = 0;
      };

      inline Exception::~Exception() {}
    }
#endif

#include "MeasurementConditions.h"

/* definitions for specific EyeOne key/values used with I1_GetOption() */
/* general key/values */
#define I1_LAST_ERROR                     "LastError"
#define I1_EXTENDED_ERROR_INFORMATION     "ExtendedErrorInformation"

#define I1_YES                            "yes"
#define I1_NO                             "no"

/* Eye-One key/values */
#define I1_VERSION                        "Version"
#define I1_SERIAL_NUMBER                  "SerialNumber"
#define I1_IS_CONNECTED                   "Connection"
#define I1_IS_KEY_PRESSED                 "IsKeyPressed"
#define I1_IS_RECOGNITION_ENABLED         "Recognition"
#define I1_LAST_CALIBRATION_TIME          "LastCalibrationTime"
#define I1_CALIBRATION_COUNT              "LastCalibrationCounter"
#define I1_NUMBER_OF_AVAILABLE_SAMPLES    "AvailableSamples"
#define I1_AVAILABLE_MEASUREMENT_MODES    "AvailableMeasurementModes"
#define I1_IS_BEEP_ENABLED                "Beep"
#define I1_LAST_AUTO_DENSITY_FILTER       "LastAutoDensityFilter"
#define I1_IS_ADAPTIVE_MODE_ENABLED       "AdaptiveMode"
#define I1_IS_NETPROFILER_ENABLED         "NetProfiler"
#define I1_INTEGRATION_TIME               "IntegrationTime"

#define I1_PHYSICAL_FILTER                "PhysicalFilter" /*read only*/
#define I1_UNDEFINED_FILTER               "0"    
#define I1_NO_FILTER                      "1"
#define I1_UV_FILTER                      "2"

#define I1_SCREEN_TYPE                    "ScreenType"    /*mandatory for i1-display*/
#define I1_LCD_SCREEN                     "LCD"
#define I1_CRT_SCREEN                     "CRT"

#define I1_PATCH_INTENSITY                "PatchIntensity" /*used with i1-display*/
#define I1_BLEAK                          "Bleak"
#define I1_BRIGHT                         "Bright"
#define I1_AUTO                           "Auto"
    
#define I1_DEVICE_TYPE                    "DeviceType"
#define I1_EYEONE                         "EyeOne"      /* this is the default device */
#define I1_EYEONE_1                       "EyeOne1"     /* this is the first alternative device found on the USB bus */
#define I1_EYEONE_2                       "EyeOne2"
/* ...                                                     all other defines must be created on demand */
#define I1_EYEONE_127                     "EyeOne127"   /* this is the last device on the bus */
#define I1_DISPLAY                        "EyeOneDisplay"

#define I1_DEVICE_SUBTYPE                 "DeviceSubType"
#define I1_REGULAR                        "Regular"
#define I1_LT                             "Lt"

#define I1_MEASUREMENT_MODE               "MeasurementMode"
#define I1_SINGLE_EMISSION                "SingleEmission"
#define I1_SINGLE_REFLECTANCE             "SingleReflectance"
#define I1_SINGLE_AMBIENT_LIGHT           "SingleAmbientLight"
#define I1_SCANNING_REFLECTANCE           "ScanningReflectance"
#define I1_SCANNING_AMBIENT_LIGHT         "ScanningAmbientLight"

#define I1_RESET                          "Reset" /*reset command parameters: I1_ALL, DeviceTypes, MeasurementModes*/
#define I1_ALL                            "All"


typedef enum I1_ErrorType
{
  eNoError,                               /* no error */
  eDeviceNotReady,                        /* device not ready	*/
  eDeviceNotConnected,                    /* device not connected	*/
  eDeviceNotCalibrated,                   /* device not calibrated */
  eKeyNotPressed,                         /* if no button	has been pressed */
  eNoSubstrateWhite,                      /* no substrate	white reference	set */
  eWrongMeasureMode,                      /* wrong measurement mode */
  eStripRecognitionFailed,                /* if the measurement mode is set to scanning and recognition is enabled */
  eNoDataAvailable,                       /* measurement not triggered, index out	of range (scanning) */
  eException,                             /* internal exception, use GetDeviceInfo(I1_LAST_ERROR)	for more details */
  eInvalidArgument,                       /* if a	passed method argument is invalid (i.e. NULL) */
  eUnknownError,                          /* unknown error occurred */
  eWrongDeviceType                        /* operation not supported by this device type */

  #ifdef I1_ADDITIONAL_ERRORS
    , I1_ADDITIONAL_ERRORS                /* extend error types */
  #endif
} I1_ErrorType;


typedef enum I1_DeviceMessage
{
  eDeviceButtonPressed,                   /* button pressed on device */
  eDeviceDisconnected                     /* device disconnected */

  #ifdef I1_ADDITIONAL_MESSAGES
    , I1_ADDITIONAL_MESSAGES              /* extend messages */
  #endif
} I1_DeviceMessage;


/*--------------------- prototypes of exported functions --------------------*/
/* General remarks:
The FPtr_I1_XXX typedefs (i.e. FPtr_I1_Calibrate) are declared to simplify the
process of getting a reference to the desired method(s) while dynamic loading this library
*/


/*------------------------------ error handling -----------------------------*/
/* void MyErrorHandlerFunction(const char *axContext, I1_ErrorType axCode, const char *axText); */
typedef void (* FPtr_I1_ErrorHandler)(const char*, I1_ErrorType, const char*);
FPtr_I1_ErrorHandler I1_RegisterErrorHandler(FPtr_I1_ErrorHandler);
typedef FPtr_I1_ErrorHandler (* FPtr_I1_RegisterErrorHandler)(FPtr_I1_ErrorHandler);

/* void MyDeviceMessageFunction(const I1_DeviceMessage axMessage, const char *axText); */
typedef void(*FPtr_I1_DeviceMessageHandler)(const I1_DeviceMessage, const char*);
FPtr_I1_DeviceMessageHandler I1_RegisterDeviceMessageHandler(FPtr_I1_DeviceMessageHandler);
typedef FPtr_I1_DeviceMessageHandler (* FPtr_I1_RegisterDeviceMessageHandler)(FPtr_I1_DeviceMessageHandler);


/*-------------------- Information about driver and API ---------------------*/
/*
Test if the Eye-One is connected
return eNoError if connected
return eDeviceNotConnected if no Eye-One is present
*/
I1_ErrorType I1_IsConnected(void);
typedef I1_ErrorType (* FPtr_I1_IsConnected)(void);

/*
Test if the button has been pressed
return eNoError if button was pressed
return eKeyNotPressed if button was not pressed
*/
I1_ErrorType I1_KeyPressed(void);
typedef I1_ErrorType (* FPtr_I1_KeyPressed)(void);

/*
returns amount of currently available samples 
*/
long I1_GetNumberOfAvailableSamples(void);
typedef long (* FPtr_I1_GetNumberOfAvailableSamples)(void);


/*------------------- trigger measurements / calibrations -------------------*/
/*
Calibrate the Eye-One
*/
I1_ErrorType I1_Calibrate(void);
typedef I1_ErrorType (* FPtr_I1_Calibrate)(void);

/*
Trigger measurement

Triggers a meausrement depending on the measurement mode set by I1_SetOption
If the measurement mode is set to I1_SINGLE_EMISSION or I1_SCANNING_REFLECTANCE it is necessary
to calibrate the Eye-One before any measurement can be triggered

use GetSpectrum(index), I1_GetTriStimulus(index) or I1_GetDensity(index) to fetch the result

returns eDeviceNotConnected if no device is available
returns eDeviceNotCalibrated if a (re)calibration is necessary
*/
I1_ErrorType I1_TriggerMeasurement(void);
typedef I1_ErrorType (* FPtr_I1_TriggerMeasurement)(void);


/*------------------------------- get samples -------------------------------*/
/*General remarks:
Use 0 as Index, to fetch the result of a previously triggered single measurement
To fetch a result of a previously triggered scan, specify an index between 0 - (I1_GetNumberOfScannedSamples() - 1)
If no measurement has been triggered or if the specified index is out of range eNoDataAvailable is returned
*/

/* 
Get the spectrum of a previous triggered measurement 
*/
I1_ErrorType I1_GetSpectrum(float spectrum[SPECTRUM_SIZE], long index);
typedef I1_ErrorType (* FPtr_I1_GetSpectrum)(float[SPECTRUM_SIZE], long);

/* 
Get the color vector of a previous triggered measurement 
*/
I1_ErrorType I1_GetTriStimulus(float tristimulus[TRISTIMULUS_SIZE], long index);
typedef I1_ErrorType (* FPtr_I1_GetTriStimulus)(float[TRISTIMULUS_SIZE], long);

/* 
Get the all densities (cyan, magenta, yellow, black) of a previous triggered measurement 
if pxAutoDensity is not null, *pxAutoDensity will be set accordingly
*/
I1_ErrorType I1_GetDensities(float densities[DENSITY_SIZE], long *autoDensityIndex, long index);
typedef I1_ErrorType (* FPtr_I1_GetDensities)(float[DENSITY_SIZE], long*, long);

I1_ErrorType I1_GetDensity(float *density, long index);
typedef I1_ErrorType (* FPtr_I1_GetDensity)(float*, long);


/*--------------------- special functions for Density -----------------------*/
/*
Set the substrate spectrum for density calculations
This method has to be called before the first call to GetDensity()
*/
I1_ErrorType I1_SetSubstrate(const float spectrum[SPECTRUM_SIZE]);
typedef I1_ErrorType (* FPtr_I1_SetSubstrate)(const float[SPECTRUM_SIZE]);


/*------------------ setting measurement mode & conditions ------------------*/
/*
possible options (see MeasurementConditions.h for possible values)
COLOR_SPACE_KEY
ILLUMINATION_KEY
OBSERVER_KEY
DENSITY_STANDARD_KEY
DENSITY_FILTER_MODE_KEY

I1_MEASUREMENT_MODE, possible values : I1_SINGLE_EMISSION, I1_SINGLE_REFLECTANCE, I1_SCANNING_REFLECTANCE
default: I1_SCANNING_REFLECTANCE
I1_IS_RECOGNITION_ENABLED, possible values : I1_YES, I1_NO, default : I1_NO
*/
I1_ErrorType I1_SetOption(const char *key, const char *value);
typedef I1_ErrorType (* FPtr_I1_SetOption)(const char*, const char*);

const char* I1_GetOption(const char *key);
typedef const char* (* FPtr_I1_GetOption)(const char*);


#ifdef __cplusplus
  }
#endif

#endif /*EYEONE_H*/

