/* -LICENSE-START-
** Copyright (c) 2020 Blackmagic Design
**
** Permission is hereby granted, free of charge, to any person or organization
** obtaining a copy of the software and accompanying documentation covered by
** this license (the "Software") to use, reproduce, display, distribute,
** execute, and transmit the Software, and to prepare derivative works of the
** Software, and to permit third-parties to whom the Software is furnished to
** do so, all subject to the following:
**
** The copyright notices in the Software and this entire statement, including
** the above license grant, this restriction and the following disclaimer,
** must be included in all copies of the Software, in whole or in part, and
** all derivative works of the Software, unless such copies or derivative
** works are solely in the form of machine-executable object code generated by
** a source language processor.
**
** 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
** DEALINGS IN THE SOFTWARE.
** -LICENSE-END-
*/


#ifndef BMD_CONST
    #if defined(_MSC_VER)
        #define BMD_CONST __declspec(selectany) static const
    #else
        #define BMD_CONST static const
    #endif
#endif

// Type Declarations


// Enumeration Mapping

cpp_quote("typedef unsigned int BMDDeckControlStatusFlags;")
cpp_quote("typedef unsigned int BMDDeckControlExportModeOpsFlags;")
cpp_quote("#if 0")
typedef enum _BMDDeckControlStatusFlags BMDDeckControlStatusFlags;
typedef enum _BMDDeckControlExportModeOpsFlags BMDDeckControlExportModeOpsFlags;
cpp_quote("#endif")

/* Enum BMDDeckControlMode - DeckControl mode */

typedef [v1_enum] enum _BMDDeckControlMode {
    bmdDeckControlNotOpened                                      = /* 'ntop' */ 0x6E746F70,
    bmdDeckControlVTRControlMode                                 = /* 'vtrc' */ 0x76747263,
    bmdDeckControlExportMode                                     = /* 'expm' */ 0x6578706D,
    bmdDeckControlCaptureMode                                    = /* 'capm' */ 0x6361706D
} BMDDeckControlMode;

/* Enum BMDDeckControlEvent - DeckControl event */

typedef [v1_enum] enum _BMDDeckControlEvent {
    bmdDeckControlAbortedEvent                                   = /* 'abte' */ 0x61627465,	// This event is triggered when a capture or edit-to-tape operation is aborted.

    /* Export-To-Tape events */

    bmdDeckControlPrepareForExportEvent                          = /* 'pfee' */ 0x70666565,	// This event is triggered a few frames before reaching the in-point. IDeckLinkInput::StartScheduledPlayback should be called at this point.
    bmdDeckControlExportCompleteEvent                            = /* 'exce' */ 0x65786365,	// This event is triggered a few frames after reaching the out-point. At this point, it is safe to stop playback. Upon reception of this event the deck's control mode is set back to bmdDeckControlVTRControlMode.

    /* Capture events */

    bmdDeckControlPrepareForCaptureEvent                         = /* 'pfce' */ 0x70666365,	// This event is triggered a few frames before reaching the in-point. The serial timecode attached to IDeckLinkVideoInputFrames is now valid.
    bmdDeckControlCaptureCompleteEvent                           = /* 'ccev' */ 0x63636576	// This event is triggered a few frames after reaching the out-point. Upon reception of this event the deck's control mode is set back to bmdDeckControlVTRControlMode.
} BMDDeckControlEvent;

/* Enum BMDDeckControlVTRControlState - VTR Control state */

typedef [v1_enum] enum _BMDDeckControlVTRControlState {
    bmdDeckControlNotInVTRControlMode                            = /* 'nvcm' */ 0x6E76636D,
    bmdDeckControlVTRControlPlaying                              = /* 'vtrp' */ 0x76747270,
    bmdDeckControlVTRControlRecording                            = /* 'vtrr' */ 0x76747272,
    bmdDeckControlVTRControlStill                                = /* 'vtra' */ 0x76747261,
    bmdDeckControlVTRControlShuttleForward                       = /* 'vtsf' */ 0x76747366,
    bmdDeckControlVTRControlShuttleReverse                       = /* 'vtsr' */ 0x76747372,
    bmdDeckControlVTRControlJogForward                           = /* 'vtjf' */ 0x76746A66,
    bmdDeckControlVTRControlJogReverse                           = /* 'vtjr' */ 0x76746A72,
    bmdDeckControlVTRControlStopped                              = /* 'vtro' */ 0x7674726F
} BMDDeckControlVTRControlState;

/* Enum BMDDeckControlStatusFlags - Deck Control status flags */

[v1_enum] enum _BMDDeckControlStatusFlags {
    bmdDeckControlStatusDeckConnected                            = 1 << 0,
    bmdDeckControlStatusRemoteMode                               = 1 << 1,
    bmdDeckControlStatusRecordInhibited                          = 1 << 2,
    bmdDeckControlStatusCassetteOut                              = 1 << 3
};

/* Enum BMDDeckControlExportModeOpsFlags - Export mode flags */

[v1_enum] enum _BMDDeckControlExportModeOpsFlags {
    bmdDeckControlExportModeInsertVideo                          = 1 << 0,
    bmdDeckControlExportModeInsertAudio1                         = 1 << 1,
    bmdDeckControlExportModeInsertAudio2                         = 1 << 2,
    bmdDeckControlExportModeInsertAudio3                         = 1 << 3,
    bmdDeckControlExportModeInsertAudio4                         = 1 << 4,
    bmdDeckControlExportModeInsertAudio5                         = 1 << 5,
    bmdDeckControlExportModeInsertAudio6                         = 1 << 6,
    bmdDeckControlExportModeInsertAudio7                         = 1 << 7,
    bmdDeckControlExportModeInsertAudio8                         = 1 << 8,
    bmdDeckControlExportModeInsertAudio9                         = 1 << 9,
    bmdDeckControlExportModeInsertAudio10                        = 1 << 10,
    bmdDeckControlExportModeInsertAudio11                        = 1 << 11,
    bmdDeckControlExportModeInsertAudio12                        = 1 << 12,
    bmdDeckControlExportModeInsertTimeCode                       = 1 << 13,
    bmdDeckControlExportModeInsertAssemble                       = 1 << 14,
    bmdDeckControlExportModeInsertPreview                        = 1 << 15,
    bmdDeckControlUseManualExport                                = 1 << 16
};

/* Enum BMDDeckControlError - Deck Control error */

typedef [v1_enum] enum _BMDDeckControlError {
    bmdDeckControlNoError                                        = /* 'noer' */ 0x6E6F6572,
    bmdDeckControlModeError                                      = /* 'moer' */ 0x6D6F6572,
    bmdDeckControlMissedInPointError                             = /* 'mier' */ 0x6D696572,
    bmdDeckControlDeckTimeoutError                               = /* 'dter' */ 0x64746572,
    bmdDeckControlCommandFailedError                             = /* 'cfer' */ 0x63666572,
    bmdDeckControlDeviceAlreadyOpenedError                       = /* 'dalo' */ 0x64616C6F,
    bmdDeckControlFailedToOpenDeviceError                        = /* 'fder' */ 0x66646572,
    bmdDeckControlInLocalModeError                               = /* 'lmer' */ 0x6C6D6572,
    bmdDeckControlEndOfTapeError                                 = /* 'eter' */ 0x65746572,
    bmdDeckControlUserAbortError                                 = /* 'uaer' */ 0x75616572,
    bmdDeckControlNoTapeInDeckError                              = /* 'nter' */ 0x6E746572,
    bmdDeckControlNoVideoFromCardError                           = /* 'nvfc' */ 0x6E766663,
    bmdDeckControlNoCommunicationError                           = /* 'ncom' */ 0x6E636F6D,
    bmdDeckControlBufferTooSmallError                            = /* 'btsm' */ 0x6274736D,
    bmdDeckControlBadChecksumError                               = /* 'chks' */ 0x63686B73,
    bmdDeckControlUnknownError                                   = /* 'uner' */ 0x756E6572
} BMDDeckControlError;

// Forward Declarations

interface IDeckLinkDeckControlStatusCallback;
interface IDeckLinkDeckControl;

/* Interface IDeckLinkDeckControlStatusCallback - Deck control state change callback. */

[
    object,
    uuid(53436FFB-B434-4906-BADC-AE3060FFE8EF),
    helpstring("Deck control state change callback.")
] interface IDeckLinkDeckControlStatusCallback : IUnknown
{
    HRESULT TimecodeUpdate ([in] BMDTimecodeBCD currentTimecode);
    HRESULT VTRControlStateChanged ([in] BMDDeckControlVTRControlState newState, [in] BMDDeckControlError error);
    HRESULT DeckControlEventReceived ([in] BMDDeckControlEvent event, [in] BMDDeckControlError error);
    HRESULT DeckControlStatusChanged ([in] BMDDeckControlStatusFlags flags, [in] unsigned int mask);
};

/* Interface IDeckLinkDeckControl - Deck Control main interface */

[
    object,
    uuid(8E1C3ACE-19C7-4E00-8B92-D80431D958BE),
    helpstring("Deck Control main interface")
] interface IDeckLinkDeckControl : IUnknown
{
    HRESULT Open ([in] BMDTimeScale timeScale, [in] BMDTimeValue timeValue, [in] BOOL timecodeIsDropFrame, [out] BMDDeckControlError* error);
    HRESULT Close ([in] BOOL standbyOn);
    HRESULT GetCurrentState ([out] BMDDeckControlMode* mode, [out] BMDDeckControlVTRControlState* vtrControlState, [out] BMDDeckControlStatusFlags* flags);
    HRESULT SetStandby ([in] BOOL standbyOn);
    HRESULT SendCommand ([in] unsigned char* inBuffer, [in] unsigned int inBufferSize, [out] unsigned char* outBuffer, [out] unsigned int* outDataSize, [in] unsigned int outBufferSize, [out] BMDDeckControlError* error);
    HRESULT Play ([out] BMDDeckControlError* error);
    HRESULT Stop ([out] BMDDeckControlError* error);
    HRESULT TogglePlayStop ([out] BMDDeckControlError* error);
    HRESULT Eject ([out] BMDDeckControlError* error);
    HRESULT GoToTimecode ([in] BMDTimecodeBCD timecode, [out] BMDDeckControlError* error);
    HRESULT FastForward ([in] BOOL viewTape, [out] BMDDeckControlError* error);
    HRESULT Rewind ([in] BOOL viewTape, [out] BMDDeckControlError* error);
    HRESULT StepForward ([out] BMDDeckControlError* error);
    HRESULT StepBack ([out] BMDDeckControlError* error);
    HRESULT Jog ([in] double rate, [out] BMDDeckControlError* error);
    HRESULT Shuttle ([in] double rate, [out] BMDDeckControlError* error);
    HRESULT GetTimecodeString ([out] BSTR* currentTimeCode, [out] BMDDeckControlError* error);
    HRESULT GetTimecode ([out] IDeckLinkTimecode** currentTimecode, [out] BMDDeckControlError* error);
    HRESULT GetTimecodeBCD ([out] BMDTimecodeBCD* currentTimecode, [out] BMDDeckControlError* error);
    HRESULT SetPreroll ([in] unsigned int prerollSeconds);
    HRESULT GetPreroll ([out] unsigned int* prerollSeconds);
    HRESULT SetExportOffset ([in] int exportOffsetFields);
    HRESULT GetExportOffset ([out] int* exportOffsetFields);
    HRESULT GetManualExportOffset ([out] int* deckManualExportOffsetFields);
    HRESULT SetCaptureOffset ([in] int captureOffsetFields);
    HRESULT GetCaptureOffset ([out] int* captureOffsetFields);
    HRESULT StartExport ([in] BMDTimecodeBCD inTimecode, [in] BMDTimecodeBCD outTimecode, [in] BMDDeckControlExportModeOpsFlags exportModeOps, [out] BMDDeckControlError* error);
    HRESULT StartCapture ([in] BOOL useVITC, [in] BMDTimecodeBCD inTimecode, [in] BMDTimecodeBCD outTimecode, [out] BMDDeckControlError* error);
    HRESULT GetDeviceID ([out] unsigned short* deviceId, [out] BMDDeckControlError* error);
    HRESULT Abort (void);
    HRESULT CrashRecordStart ([out] BMDDeckControlError* error);
    HRESULT CrashRecordStop ([out] BMDDeckControlError* error);
    HRESULT SetCallback ([in] IDeckLinkDeckControlStatusCallback* callback);
};

/* Coclasses */

importlib("stdole2.tlb");

