/*
 * UVCCamera
 * library and sample to access to UVC web camera on non-rooted Android device
 *
 * Copyright (c) 2014-2017 saki t_saki@serenegiant.com
 *
 * File name: UVCCamera.h
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 * All files in the folder are under this Apache License, Version 2.0.
 * Files in the jni/libjpeg, jni/libusb, jin/libuvc, jni/rapidjson folder may have a different license, see the respective files.
*/

#pragma interface

#ifndef UVCCAMERA_H_
#define UVCCAMERA_H_

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <android/native_window.h>
#include "UVCStatusCallback.h"
#include "UVCButtonCallback.h"
#include "UVCPreview.h"

#define	CTRL_SCANNING		0x000001	// D0:  Scanning Mode
#define	CTRL_AE				0x000002	// D1:  Auto-Exposure Mode
#define	CTRL_AE_PRIORITY	0x000004	// D2:  Auto-Exposure Priority
#define	CTRL_AE_ABS			0x000008	// D3:  Exposure Time (Absolute)
#define	CTRL_AE_REL			0x000010	// D4:  Exposure Time (Relative)
#define CTRL_FOCUS_ABS    	0x000020	// D5:  Focus (Absolute)
#define CTRL_FOCUS_REL		0x000040	// D6:  Focus (Relative)
#define CTRL_IRIS_ABS		0x000080	// D7:  Iris (Absolute)
#define	CTRL_IRIS_REL		0x000100	// D8:  Iris (Relative)
#define	CTRL_ZOOM_ABS		0x000200	// D9:  Zoom (Absolute)
#define CTRL_ZOOM_REL		0x000400	// D10: Zoom (Relative)
#define	CTRL_PANTILT_ABS	0x000800	// D11: PanTilt (Absolute)
#define CTRL_PANTILT_REL	0x001000	// D12: PanTilt (Relative)
#define CTRL_ROLL_ABS		0x002000	// D13: Roll (Absolute)
#define CTRL_ROLL_REL		0x004000	// D14: Roll (Relative)
//#define CTRL_D15			0x008000	// D15: Reserved
//#define CTRL_D16			0x010000	// D16: Reserved
#define CTRL_FOCUS_AUTO		0x020000	// D17: Focus, Auto
#define CTRL_PRIVACY		0x040000	// D18: Privacy
#define CTRL_FOCUS_SIMPLE	0x080000	// D19: Focus, Simple
#define CTRL_WINDOW			0x100000	// D20: Window

#define PU_BRIGHTNESS		0x000001	// D0: Brightness
#define PU_CONTRAST			0x000002	// D1: Contrast
#define PU_HUE				0x000004	// D2: Hue
#define	PU_SATURATION		0x000008	// D3: Saturation
#define PU_SHARPNESS		0x000010	// D4: Sharpness
#define PU_GAMMA			0x000020	// D5: Gamma
#define	PU_WB_TEMP			0x000040	// D6: White Balance Temperature
#define	PU_WB_COMPO			0x000080	// D7: White Balance Component
#define	PU_BACKLIGHT		0x000100	// D8: Backlight Compensation
#define PU_GAIN				0x000200	// D9: Gain
#define PU_POWER_LF			0x000400	// D10: Power Line Frequency
#define PU_HUE_AUTO			0x000800	// D11: Hue, Auto
#define PU_WB_TEMP_AUTO		0x001000	// D12: White Balance Temperature, Auto
#define PU_WB_COMPO_AUTO	0x002000	// D13: White Balance Component, Auto
#define PU_DIGITAL_MULT		0x004000	// D14: Digital Multiplier
#define PU_DIGITAL_LIMIT	0x008000	// D15: Digital Multiplier Limit
#define PU_AVIDEO_STD		0x010000	// D16: Analog Video Standard
#define PU_AVIDEO_LOCK		0x020000	// D17: Analog Video Lock Status
#define PU_CONTRAST_AUTO	0x040000	// D18: Contrast, Auto

typedef struct control_value {
	int res;	// unused
	int min;
	int max;
	int def;
	int current;
} control_value_t;

typedef uvc_error_t (*paramget_func_i8)(uvc_device_handle_t *devh, int8_t *value, enum uvc_req_code req_code);
typedef uvc_error_t (*paramget_func_i16)(uvc_device_handle_t *devh, int16_t *value, enum uvc_req_code req_code);
typedef uvc_error_t (*paramget_func_i32)(uvc_device_handle_t *devh, int32_t *value, enum uvc_req_code req_code);
typedef uvc_error_t (*paramget_func_u8)(uvc_device_handle_t *devh, uint8_t *value, enum uvc_req_code req_code);
typedef uvc_error_t (*paramget_func_u16)(uvc_device_handle_t *devh, uint16_t *value, enum uvc_req_code req_code);
typedef uvc_error_t (*paramget_func_u32)(uvc_device_handle_t *devh, uint32_t *value, enum uvc_req_code req_code);
typedef uvc_error_t (*paramget_func_u8u8)(uvc_device_handle_t *devh, uint8_t *value1, uint8_t *value2, enum uvc_req_code req_code);
typedef uvc_error_t (*paramget_func_i8u8)(uvc_device_handle_t *devh, int8_t *value1, uint8_t *value2, enum uvc_req_code req_code);
typedef uvc_error_t (*paramget_func_i8u8u8)(uvc_device_handle_t *devh, int8_t *value1, uint8_t *value2, uint8_t *value3, enum uvc_req_code req_code);
typedef uvc_error_t (*paramget_func_i32i32)(uvc_device_handle_t *devh, int32_t *value1, int32_t *value2, enum uvc_req_code req_code);

typedef uvc_error_t (*paramset_func_i8)(uvc_device_handle_t *devh, int8_t value);
typedef uvc_error_t (*paramset_func_i16)(uvc_device_handle_t *devh, int16_t value);
typedef uvc_error_t (*paramset_func_i32)(uvc_device_handle_t *devh, int32_t value);
typedef uvc_error_t (*paramset_func_u8)(uvc_device_handle_t *devh, uint8_t value);
typedef uvc_error_t (*paramset_func_u16)(uvc_device_handle_t *devh, uint16_t value);
typedef uvc_error_t (*paramset_func_u32)(uvc_device_handle_t *devh, uint32_t value);
typedef uvc_error_t (*paramset_func_u8u8)(uvc_device_handle_t *devh, uint8_t value1, uint8_t value2);
typedef uvc_error_t (*paramset_func_i8u8)(uvc_device_handle_t *devh, int8_t value1, uint8_t value2);
typedef uvc_error_t (*paramset_func_i8u8u8)(uvc_device_handle_t *devh, int8_t value1, uint8_t value2, uint8_t value3);
typedef uvc_error_t (*paramset_func_i32i32)(uvc_device_handle_t *devh, int32_t value1, int32_t value2);

class UVCCamera {
	char *mUsbFs;
	uvc_context_t *mContext;
	int mFd;
	uvc_device_t *mDevice;
	uvc_device_handle_t *mDeviceHandle;
	UVCStatusCallback *mStatusCallback;
	UVCButtonCallback *mButtonCallback;
	// プレビュー用
	UVCPreview *mPreview;
	uint64_t mCtrlSupports;
	uint64_t mPUSupports;
	control_value_t mScanningMode;
	control_value_t mExposureMode;
	control_value_t mExposurePriority;
	control_value_t mExposureAbs;
	control_value_t mAutoFocus;
	control_value_t mAutoWhiteBlance;
	control_value_t mAutoWhiteBlanceCompo;
	control_value_t mWhiteBlance;
	control_value_t mWhiteBlanceCompo;
	control_value_t mBacklightComp;
	control_value_t mBrightness;
	control_value_t mContrast;
	control_value_t mAutoContrast;
	control_value_t mSharpness;
	control_value_t mGain;
	control_value_t mGamma;
	control_value_t mSaturation;
	control_value_t mHue;
	control_value_t mAutoHue;
	control_value_t mZoom;
	control_value_t mZoomRel;
	control_value_t mFocus;
	control_value_t mFocusRel;
	control_value_t mFocusSimple;
	control_value_t mIris;
	control_value_t mIrisRel;
	control_value_t mPan;
	control_value_t mTilt;
	control_value_t mRoll;
	control_value_t mPanRel;
	control_value_t mTiltRel;
	control_value_t mRollRel;
	control_value_t mPrivacy;
	control_value_t mPowerlineFrequency;
	control_value_t mMultiplier;
	control_value_t mMultiplierLimit;
	control_value_t mAnalogVideoStandard;
	control_value_t mAnalogVideoLockState;

	void clearCameraParams();
    int internalSetCtrlValue(int32_t value, paramset_func_u16 set_func);
	int internalSetCtrlValue(control_value_t &values, int8_t value,
		paramget_func_i8 get_func, paramset_func_i8 set_func);
	int internalSetCtrlValue(control_value_t &values, uint8_t value,
		paramget_func_u8 get_func, paramset_func_u8 set_func);
	int internalSetCtrlValue(control_value_t &values, uint8_t value1, uint8_t value2,
		paramget_func_u8u8 get_func, paramset_func_u8u8 set_func);
	int internalSetCtrlValue(control_value_t &values, int8_t value1, uint8_t value2,
		paramget_func_i8u8 get_func, paramset_func_i8u8 set_func);
	int internalSetCtrlValue(control_value_t &values, int8_t value1, uint8_t value2, uint8_t value3,
		paramget_func_i8u8u8 get_func, paramset_func_i8u8u8 set_func);
	int internalSetCtrlValue(control_value_t &values, int16_t value,
		paramget_func_i16 get_func, paramset_func_i16 set_func);
	int internalSetCtrlValue(control_value_t &values, uint16_t value,
		paramget_func_u16 get_func, paramset_func_u16 set_func);
	int internalSetCtrlValue(control_value_t &values, int32_t value,
		paramget_func_i32 get_func, paramset_func_i32 set_func);
	int internalSetCtrlValue(control_value_t &values, uint32_t value,
		paramget_func_u32 get_func, paramset_func_u32 set_func);
public:
	UVCCamera();
	~UVCCamera();

	int connect(int vid, int pid, int fd, int busnum, int devaddr, const char *usbfs);
	int release();

	int setStatusCallback(JNIEnv *env, jobject status_callback_obj);
	int setButtonCallback(JNIEnv *env, jobject button_callback_obj);

	char *getSupportedSize();
	int setPreviewSize(int width, int height, int min_fps, int max_fps, int mode, float bandwidth = DEFAULT_BANDWIDTH);
	int setPreviewDisplay(ANativeWindow *preview_window);
	int setFrameCallback(JNIEnv *env, jobject frame_callback_obj, int pixel_format);
	int startPreview();
	int stopPreview();
	int setCaptureDisplay(ANativeWindow *capture_window);

	int getCtrlSupports(uint64_t *supports);
	int getProcSupports(uint64_t *supports);

	int updateScanningModeLimit(int &min, int &max, int &def);
	int setScanningMode(int mode);
	int getScanningMode();
	
	int updateExposureModeLimit(int &min, int &max, int &def);
	int setExposureMode(int mode);
	int getExposureMode();

	int updateExposurePriorityLimit(int &min, int &max, int &def);
	int setExposurePriority(int priority);
	int getExposurePriority();
	
	int updateExposureLimit(int &min, int &max, int &def);
	int setExposure(int ae_abs);
	int getExposure();
	
	int updateExposureRelLimit(int &min, int &max, int &def);
	int setExposureRel(int ae_rel);
	int getExposureRel();
	
	int updateAutoFocusLimit(int &min, int &max, int &def);
	int setAutoFocus(bool autoFocus);
	bool getAutoFocus();

	int updateFocusLimit(int &min, int &max, int &def);
	int setFocus(int focus);
	int getFocus();

	int updateFocusRelLimit(int &min, int &max, int &def);
	int setFocusRel(int focus);
	int getFocusRel();
	
/*	int updateFocusSimpleLimit(int &min, int &max, int &def);
	int setFocusSimple(int focus);
	int getFocusSimple(); */
	
	int updateIrisLimit(int &min, int &max, int &def);
	int setIris(int iris);
	int getIris();
	
	int updateIrisRelLimit(int &min, int &max, int &def);
	int setIrisRel(int iris);
	int getIrisRel();
	
	int updatePanLimit(int &min, int &max, int &def);
	int setPan(int pan);
	int getPan();
	
	int updateTiltLimit(int &min, int &max, int &def);
	int setTilt(int tilt);
	int getTilt();
	
	int updateRollLimit(int &min, int &max, int &def);
	int setRoll(int roll);
	int getRoll();
	
	int updatePanRelLimit(int &min, int &max, int &def);
	int setPanRel(int pan_rel);
	int getPanRel();
	
	int updateTiltRelLimit(int &min, int &max, int &def);
	int setTiltRel(int tilt_rel);
	int getTiltRel();
	
	int updateRollRelLimit(int &min, int &max, int &def);
	int setRollRel(int roll_rel);
	int getRollRel();
	
	int updatePrivacyLimit(int &min, int &max, int &def);
	int setPrivacy(int privacy);
	int getPrivacy();
	
	int updateAutoWhiteBlanceLimit(int &min, int &max, int &def);
	int setAutoWhiteBlance(bool autoWhiteBlance);
	bool getAutoWhiteBlance();

	int updateAutoWhiteBlanceCompoLimit(int &min, int &max, int &def);
	int setAutoWhiteBlanceCompo(bool autoWhiteBlanceCompo);
	bool getAutoWhiteBlanceCompo();
	
	int updateWhiteBlanceLimit(int &min, int &max, int &def);
	int setWhiteBlance(int temp);
	int getWhiteBlance();

	int updateWhiteBlanceCompoLimit(int &min, int &max, int &def);
	int setWhiteBlanceCompo(int white_blance_compo);
	int getWhiteBlanceCompo();
	
	int updateBacklightCompLimit(int &min, int &max, int &def);
	int setBacklightComp(int backlight);
	int getBacklightComp();
	
	int updateBrightnessLimit(int &min, int &max, int &def);
	int setBrightness(int brightness);
	int getBrightness();

	int updateContrastLimit(int &min, int &max, int &def);
	int setContrast(uint16_t contrast);
	int getContrast();

	int updateAutoContrastLimit(int &min, int &max, int &def);
	int setAutoContrast(bool autoFocus);
	bool getAutoContrast();

	int updateSharpnessLimit(int &min, int &max, int &def);
	int setSharpness(int sharpness);
	int getSharpness();

	int updateGainLimit(int &min, int &max, int &def);
	int setGain(int gain);
	int getGain();

	int updateGammaLimit(int &min, int &max, int &def);
	int setGamma(int gamma);
	int getGamma();

	int updateSaturationLimit(int &min, int &max, int &def);
	int setSaturation(int saturation);
	int getSaturation();

	int updateHueLimit(int &min, int &max, int &def);
	int setHue(int hue);
	int getHue();

	int updateAutoHueLimit(int &min, int &max, int &def);
	int setAutoHue(bool autoFocus);
	bool getAutoHue();
	
	int updatePowerlineFrequencyLimit(int &min, int &max, int &def);
	int setPowerlineFrequency(int frequency);
	int getPowerlineFrequency();

	int sendCommand(int command);

	int updateZoomLimit(int &min, int &max, int &def);
	int setZoom(int zoom);
	int getZoom();
	
	int updateZoomRelLimit(int &min, int &max, int &def);
	int setZoomRel(int zoom);
	int getZoomRel();
	
	int updateDigitalMultiplierLimit(int &min, int &max, int &def);
	int setDigitalMultiplier(int multiplier);
	int getDigitalMultiplier();
	
	int updateDigitalMultiplierLimitLimit(int &min, int &max, int &def);
	int setDigitalMultiplierLimit(int multiplier_limit);
	int getDigitalMultiplierLimit();
	
	int updateAnalogVideoStandardLimit(int &min, int &max, int &def);
	int setAnalogVideoStandard(int standard);
	int getAnalogVideoStandard();
	
	int updateAnalogVideoLockStateLimit(int &min, int &max, int &def);
	int setAnalogVideoLockState(int status);
	int getAnalogVideoLockState();
};

#endif /* UVCCAMERA_H_ */
