Plugins (Delphi): A Delphi plugin sample

It's simple!
Opus Delphi Plugin.zip (10.7 KB)

Cool :slight_smile:

There is no Chinese language file for Opus .

I would like to translat to Chinese , How shoud I do ?

Translation offers should be sent to GPSoft directly.

This pascal header has incorrect values of DVPN_*** constants.
0U-2000U should be translated to Integer($FFFFFFFF - 2000 + 1), and types of all DVPN_*** constants must be changed to Integer.

Refer to @ptma @ Sergey_Tkachenko @leo (PNOpusPlugins_drawrap_2016-06-07 viewer plugins.h) Code

unit DOpusViewerPlugins;

interface

uses
  Winapi.ActiveX, Winapi.Windows, Winapi.Messages;

{$DEFINE UNICODE}
{$IFNDEF VIEWER_PLUGIN_VERSION}
{$DEFINE VIEWER_PLUGIN_VERSION}

{$IFDEF VIEWER_PLUGIN_VERSION}
  const VIEWERPLUGINVERSION	= 12000;    // 12000 = v12, 6 = v11, 5 = v10, 4 = v9, 3 = v8
{$ENDIF}

type
  LPSTREAM = ^IStream;
  LPSIZE   = PSize; //^TSize;

const
    // VIEWERPLUGININFO flags
    DVPFIF_CanHandleStreams            = $00000001;    // Plugin can handle IStreams to identify and read files
    DVPFIF_CanHandleBytes              = $00000002;    // Plugin can identify files based on file header
    DVPFIF_CatchAll                    = $00000004;    // 'Catch All' plugin wants to be called last
    DVPFIF_DefaultCatchAll             = $00000008;    // 'Default Catch All' plugin is last unless there's another 'catch all'
    DVPFIF_ExtensionsOnly              = $00000010;    // Plugin only wants to identify files based on file extension
    DVPFIF_ExtensionsOnlyIfSlow        = $00000020;    // Plugin looks only at file extensions if file is 'slow'
    DVPFIF_ExtensionsOnlyIfNoRndSeek   = $00000040;    // Plugin looks only at file extensions if file doesn't support random seeking
    DVPFIF_ExtensionsOnlyForThumbnails = $00000080;    // Plugin looks only at file extensions if generating thumbnails
    DVPFIF_NoSlowFiles                 = $00000100;    // Plugin doesn't handle 'slow' files
    DVPFIF_NeedRandomSeek              = $00000200;    // Plugin needs random seek capability
    DVPFIF_CanConfigure                = $00000400;    // Plugin has a configuration interface
    DVPFIF_CanShowAbout                = $00000800;    // Plugin has an About function
    DVPFIF_NoThumbnails                = $00001000;    // Plugin doesn't want to be called to generate thumbnails
    DVPFIF_NoProperties                = $00002000;    // Don't show 'Properties' item on default context menu
    DVPFIF_ZeroBytesOk                 = $00004000;    // Zero byte files are ok (eg text files)
    DVPFIF_OverrideInternal            = $00008000;    // Plugin can override internal Opus image routines
{$IF VIEWERPLUGINVERSION >= 3 }
    DVPFIF_InitialDisable              = $00010000;    // Plugin is disabled by default
    DVPFIF_NoFileInformation           = $00020000;    // Is not to be called for file information (eg Description field)
    DVPFIF_ProvideFileInfo             = $00040000;    // Provides information without viewing
    DVPFIF_NoMultithreadThumbnails     = $00080000;    // Don't call simultaneously on multiple threads for thumbnails
    DVPFIF_FolderThumbnails            = $00100000;    // Can provide folder thumbnails
    DVPFIF_TrueThumbnailSize           = $00200000;    // Always provide true thumbnail size
{$IFEND}
{$IF VIEWERPLUGINVERSION >= 4 }
    DVPFIF_UseVersionResource          = $00400000;    // Use the plugin's version resource for version information
    DVPFIF_CanShowHex                  = $00800000;    // The plugin can be used as a hex viewer for any type of file
    DVPFIF_OnlyThumbnails              = $01000000;    // Plugin is only to be called for thumbnails
{$IFEND}
{$IF VIEWERPLUGINVERSION >= 5 }
    DVPFIF_ExtensionsOnlyIfSlowSeek    = $02000000;    // Plugin looks only at file extensions if file has slow seeking (usually combined with DVPFIF_ExtensionsOnlyIfSlow and DVPFIF_ExtensionsOnlyIfNoRndSeek).
    DVPFIF_NoSlowSeek                  = $04000000;    // Plugin doesn't handle files with slow seeking (usually combined with DVPFIF_NoSlowFiles and DVPFIF_NeedRandomSeek)
{$IFEND}

// Plugin major types
type
  DOpusViewerPluginFileType = (
    DVPMajorType_Image,
    DVPMajorType_Sound,
    DVPMajorType_Text,
    DVPMajorType_Other,
    DVPMajorType_Movie);

type
  TDOpusViewerPluginInfoW = record
      cbSize               : UINT;                          // Structure size
      dwFlags              : DWORD;                         // Flags
      dwVersionHigh        : DWORD;                         // Version (high)
      dwVersionLow         : DWORD;                         // Version (low)
      lpszHandleExts       : LPWSTR;                        // File extensions the plugin handles, eg ".xxx;.yyy;.zzz"
      lpszName             : LPWSTR;                        // Plugin primary file format name, eg "JPEG"
      lpszDescription      : LPWSTR;                        // Plugin description string, eg "Directory Opus JPEG Viewer"
      lpszCopyright        : LPWSTR;                        // Copyright string, eg "(c) 2001 GP Software"
      lpszURL              : LPWSTR;                        // Reference URL, eg "http: //www.gpsoft.com.au"
      cchHandleExtsMax     : UINT;                          // Max. length of buffer
      cchNameMax           : UINT;                          // Max. length of buffer
      cchDescriptionMax    : UINT;                          // Max. length of buffer
      cchCopyrightMax      : UINT;                          // Max. length of buffer
      cchURLMax            : UINT;                          // Max. length of buffer
      dwlMinFileSize       : DWORDLONG;                     // Minimum size of file that we handle
      dwlMaxFileSize       : DWORDLONG;                     // Maximum size of file that we handle
      dwlMinPreviewFileSize: DWORDLONG;                     // Minimum size of file that we handle in preview mode
      dwlMaxPreviewFileSize: DWORDLONG;                     // Maximum size of file that we handle in preview mode
      uiMajorFileType      : DOpusViewerPluginFileType;    // Primary type of file this plugin handles
      idPlugin             : TGUID;                         // Unique identifier for this plugin
{$IF VIEWERPLUGINVERSION >= 4 }
      dwOpusVerMajor       : DWORD;                         // Opus major version
      dwOpusVerMinor       : DWORD;                         // Opus minor version
      dwInitFlags          : DWORD;                         // Initialisation flags
      hIconSmall           : HICON;                         // Small icon (Opus will call DestroyIcon on this)
      hIconLarge           : HICON;                         // Large icon (Opus will call DestroyIcon on this)
{$IFEND}
  end;
  TViewerPluginInfoW  = TDOpusViewerPluginInfoW;
  LPVIEWERPLUGININFOW = ^TViewerPluginInfoW;

type
  TDOpusViewerPluginInfoA = record
      cbSize               : UINT;                          // Structure size
      dwFlags              : DWORD;                         // Flags
      dwVersionHigh        : DWORD;                         // Version (high)
      dwVersionLow         : DWORD;                         // Version (low)
      lpszHandleExts       : LPSTR;                         // File extensions the plugin handles, eg ".xxx;.yyy;.zzz"
      lpszName             : LPSTR;                         // Plugin primary file format name, eg "JPEG"
      lpszDescription      : LPSTR;                         // Plugin description string, eg "Directory Opus JPEG Viewer"
      lpszCopyright        : LPSTR;                         // Copyright string, eg "(c) 2001 GP Software"
      lpszURL              : LPSTR;                         // Reference URL, eg "http: //www.gpsoft.com.au"
      cchHandleExtsMax     : UINT;                          // Max. length of buffer
      cchNameMax           : UINT;                          // Max. length of buffer
      cchDescriptionMax    : UINT;                          // Max. length of buffer
      cchCopyrightMax      : UINT;                          // Max. length of buffer
      cchURLMax            : UINT;                          // Max. length of buffer
      dwlMinFileSize       : DWORDLONG;                     // Minimum size of file that we handle
      dwlMaxFileSize       : DWORDLONG;                     // Maximum size of file that we handle
      dwlMinPreviewFileSize: DWORDLONG;                     // Minimum size of file that we handle in preview mode
      dwlMaxPreviewFileSize: DWORDLONG;                     // Maximum size of file that we handle in preview mode
      uiMajorFileType      : DOpusViewerPluginFileType;     // Primary type of file this plugin handles
      idPlugin             : TGUID;                         // Unique identifier for this plugin
{$IF VIEWERPLUGINVERSION >= 4 }
      dwOpusVerMajor       : DWORD;                         // Opus major version
      dwOpusVerMinor       : DWORD;                         // Opus minor version
      dwInitFlags          : DWORD;                         // Initialisation flags
      hIconSmall           : HICON;                         // Small icon (Opus will call DestroyIcon on this)
      hIconLarge           : HICON;                         // Large icon (Opus will call DestroyIcon on this)
{$IFEND}
  end;
  TViewerPluginInfoA  = TDOpusViewerPluginInfoA;
  LPVIEWERPLUGININFOA = ^TViewerPluginInfoA;

{$IFDEF UNICODE}
VIEWERPLUGININFO   = TViewerPluginInfoW;
LPVIEWERPLUGININFO = LPVIEWERPLUGININFOW;
{$ELSE}
VIEWERPLUGININFO   = TViewerPluginInfoA;
LPVIEWERPLUGININFO = LPVIEWERPLUGININFOA;
{$IFEND}

const
{$IF VIEWERPLUGINVERSION >= 4 }
  VPINITF_FIRSTTIME              = $00000001; // First time this plugin has been initialised
  VPINITF_USB                    = $00000002; // Opus is running in USB mode
  VPINITF_NOINIT                 = $00000004; // DVP_Init/DVP_InitEx *may not* have been called for the plugin. Set when DVP_Identify called to get plugin's name for list of plugins available for USB export.
  VPINITF_NOSUPPORT	             = $00000008; // The plugin support API is unavailable. (Exception: GetString *may* still be available.) Set when DVP_Identify called to get 32-bit plugin's name for 64-bit Opus. The call comes via a simple proxy process which does not provide the plugin support API. This situation occurs when 64-bit Opus is building the list of available plugins for a 32-bit USB export.
{$IFEND}

    // VIEWERPLUGINFILEINFO flags
    DVPFIF_CanReturnBitmap       = $00000001; // We can return a bitmap for this file type
    DVPFIF_CanReturnViewer       = $00000002; // We can create a viewer for this file type
    DVPFIF_CanReturnThumbnail    = $00000004; // We can return a thumbnail for this filetype (in bitmap form)
    DVPFIF_CanShowProperties     = $00000008; // We can show a Properties dialog for this file
{$IF VIEWERPLUGINVERSION >= 3 }
    DVPFIF_ResolutionInch        = $00000010; // Resolution is given in DPI
    DVPFIF_ResolutionCM          = $00000020; // Resolution is given in CM
    DVPFIF_WantFileInfo          = $00000040; // Being called for file information
    DVPFIF_ReturnsText           = $00000080; // All we return is text
    DVPFIF_HasAlphaChannel       = $00000100; // Bitmap returned is 32 bits and has valid alpha channel
    DVPFIF_HasTransparentColor   = $00000200; // Use transparent color to generate mask
    DVPFIF_HasTransparentPen     = $00000400; // Use transparent pen to generate mask (upper 8 bits of crTransparentColor)
    DVPFIF_CanReturnFileInfo     = $00000800; // Provides file information
    DVPFIF_NoThumbnailBorder     = $00001000; // Don't display a border for this thumbnail
    DVPFIF_NoShowThumbnailIcon   = $00002000; // Don't display filetype icon for this thumbnail
    DVPFIF_ShowThumbnailIcon     = $00004000; // Force display of filetype icon for this thumbnail
    DVPFIF_FolderThumbnail       = $00008000; // Being called for a folder thumbnail
    DVPFIF_RegenerateOnResize    = $00010000; // Regenerate instead of scale for dynamic resizing
{$IFEND}
{$IF VIEWERPLUGINVERSION >= 4 }
    DVPFIF_JPEGStream            = $00020000; // Plugin has returned a JPEG stream allocated with LocalAlloc(LMEM_FIXED)
    DVPFIF_PNGStream             = $00040000; // Plugin has returned a PNG stream allocated with LocalAlloc(LMEM_FIXED);
    DVPFIF_InFolderThumbnail     = $00080000; // Being called for a thumbnail for a folder (on a file within the folder)
    DVPFIF_NoCache               = $00100000; // Never cache the thumbnail.
    DVPFIF_Rotate90              = $00200000; // Returned image should be rotated 90 degrees.
    DVPFIF_Rotate270             = $00400000; // Returned image should be rotated 270 degrees.
    DVPFIF_Rotate180             = $00600000; // Returned image should be rotated 180 degrees.(DVPFIF_Rotate90|DVPFIF_Rotate270)
    DVPFIF_NoThumbnailDimensions = $00800000; // Don't display width/height/depth information for this thumbnail.
    DVPFIF_ForImageConverter     = $01000000; // Set by Opus: Indicates LoadBitmap is being called for the image converter. (Example usage: Enable an ultra-high-quality mode for image conversion that would be too slow for general file viewing.)
    DVPFIF_RotateAutoStream      = $02000000; // When returning a JPEG or PNG stream, ask Opus to auto-rotate it using EXIF data in the stream as a post-processing step. (User's EXIF rotation preferences are ignored; always done regardless.)
{$IFEND}
{$IF VIEWERPLUGINVERSION >= 5 }
    DVPFIF_RotateAutoFile        = $04000000; // When returning an image, ask Opus to auto-rotate it using EXIF data in the file itself for formats Opus can extract EXIF from. (User's EXIF rotation settings are respected.) NOTE: At time of writing, the thumbnail code respects this flag but other areas, such as the viewer and image converter, may act as if it is always set. If you support a format Opus can extract EXIF from and *don't* want to set this flag for some reason, please get in touch with GPSoftware for assistance.
    DVPFIF_Thumbnail             = $08000000; // Set by Opus: Being called for a thumbnail (rather than for the viewer)
    DVPFIF_EnableHexIdent        = $10000000; // Set by Opus: Asks the (text.dll) plugin to identify files even if the only way it can view them is in hex mode.
{$IFEND}
{$IF VIEWERPLUGINVERSION >= 6 }
    DVPFIF_RotateFlipHorizontal  = $20000000; // Returned image should be flipped horizontally.
    DVPFIF_RotateFlipVertical    = $40000000; // Returned image should be flipped veritcally.
    DVPFIF_RotateTranspose       = $80000000; // Returned image should be transposed.
{$IFEND}
{$IF VIEWERPLUGINVERSION >= 12000 }
    // DVPLUGINMSG_SETROTATION lParm flags.
    DVPROTF_FLIPH                = $00000001; // Flip horizontally. Only set if VPCAPABILITY_INITIALFLIP.
    DVPROTF_FLIPV                = $00000002; // Flip vertically.   Only set if VPCAPABILITY_INITIALFLIP.
{$IFEND}

type
  TDVPFITypeHint =(
    DVPFITypeHint_None,
    DVPFITypeHint_PlainText,
    DVPFITypeHint_RichText,
    DVPFITypeHint_HTML
  );


type
  TDVPColorSpace = (
    DVPColorSpace_Unknown,
    DVPColorSpace_Grayscale,
    DVPColorSpace_RGB,
    DVPColorSpace_YCBCR,
    DVPColorSpace_CMYK,
    DVPColorSpace_YCCK
  );

type

    TDOpusViewerPluginFileInfoW = record
        cbSize                   : UINT;
        dwFlags                  : DWORD;
        wMajorType               : WORD;
        wMinorType               : WORD;
        szImageSize              : TSIZE;
        iNumBits                 : Integer;
        lpszInfo                 : LPWSTR;
        cchInfoMax               : UINT;
        dwPrivateData            : Array[0..7] of DWORD;
        {$IF VIEWERPLUGINVERSION >= 2 }
        szResolution             : TSIZE;
        iTypeHint                : Integer;
        {$IFEND}
        {$IF VIEWERPLUGINVERSION >= 3 }
        crTransparentColor       : COLORREF;
        wThumbnailQuality        : WORD;
        dwlFileSize              : DWORDLONG;
        {$IFEDN}
        {$IF VIEWERPLUGINVERSION >= 4 }
        iColorSpace              : Integer;
        {$IFEND}
    end;
    LPVIEWERPLUGINFILEINFOW = ^TDOpusViewerPluginFileInfoW;

    TDOpusViewerPluginFileInfoA     = record
        cbSize                   : UINT;
        dwFlags                  : DWORD;
        wMajorType               : WORD;
        wMinorType               : WORD;
        szImageSize              : TSIZE;
        iNumBits                 : Integer;
        lpszInfo                 : LPSTR;
        cchInfoMax               : UINT;
        dwPrivateData            : Array[0..7] of DWORD;
        {$IF VIEWERPLUGINVERSION >= 2 }
        szResolution             : TSIZE;
        iTypeHint                : Integer;
        {$IFEND}
        {$IF VIEWERPLUGINVERSION >= 3 }
        crTransparentColor       : COLORREF;
        wThumbnailQuality        : WORD;
        dwlFileSize              : DWORDLONG;
        {$IFEND}
        {$IF VIEWERPLUGINVERSION >= 4 }
        iColorSpace              : Integer;
        {$IFEND}
    end;
    LPVIEWERPLUGINFILEINFOA = ^TDOpusViewerPluginFileInfoA;
{$IFDEF UNICODE}
  VIEWERPLUGINFILEINFO   = TDOpusViewerPluginFileInfoW;
  LPVIEWERPLUGINFILEINFO = LPVIEWERPLUGINFILEINFOW;
{$ELSE}
  VIEWERPLUGINFILEINFO   = TDOpusViewerPluginFileInfoA;
  LPVIEWERPLUGINFILEINFO = LPVIEWERPLUGINFILEINFOA;
{$IFEND}

//const
//  VIEWERPLUGINFILEINFOW_V4_SIZE	= sizeof(TDOpusViewerPluginFileInfoW);
//  VIEWERPLUGINFILEINFOA_V4_SIZE	= sizeof(TDOpusViewerPluginFileInfoA);

type
  // Messages sent to a plugin viewer window
  TDOpusViewerPluginMsg = (
      BASE = ($00008000 + $00000F00),  // (WM_APP + 0xf00)
      LOADA,                           // Load picture (lParam: WORD = LPSTR lpszName)
      LOADW,                           // Load picture (lParam: WORD = LPWSTR lpszName)
      LOADSTREAMA,                     // Load picture (wParam: WORD = LPSTR lspzName, lParam: WORD = LPSTREAM lpStream)
      LOADSTREAMW,                     // Load picture (wParam: WORD = LPWSTR lspzName, lParam: WORD = LPSTREAM lpStream)
      GETIMAGEINFOA,                   // Get info for loaded picture (lParam: WORD = LPVIEWERPLUGINFILEINFOA)
      GETIMAGEINFOW,                   // Get info for loaded picture (lParam: WORD = LPVIEWERPLUGINFILEINFOW)
      GETCAPABILITIES,                 // Get viewer capabilities
      RESIZE,                          // Resize window (wParam: WORD = DWORD left,top lParam: WORD = DWORD width, height )
      SETROTATION,                     // Set initial rotation ( wParam: WORD = int rotate_angle )
      ROTATE,                          // Rotate image ( wParam: WORD = int rotate_amount, lParam: WORD = TRUE if window autosize is enabled )
      SETZOOM,                         // Set initial zoom ( wParam: WORD = int zoom_factor )
      ZOOM,                            // Zoom image (wParam: WORD = int zoom_factor )
      GETZOOMFACTOR,                   // Get current zoom factor
      SELECTALL,                       // Select contents
      TESTSELECTION,                   // Is there a selection?
      COPYSELECTION,                   // Copy selection to clipboard
      PRINT,                           // Print picture
      PROPERTIES,                      // Show properties dialog ( wParam: WORD = HWND hWndParent )
      REDRAW,                          // Redraw (if wParam: WORD = TRUE it means the background colour has changed and is supplied in lParam )
      GETPICSIZE,                      // Return size of current image (wParam: WORD = LPINT lpiNumBits (optional), lParam: WORD = LPSIZE)
      GETAUTOBGCOL,                    // Return 'automatic' background colour based on image
      MOUSEWHEEL,                      // Mouse wheel message
      ADDCONTEXTMENUA,                 // Add items to context menu ( wParam: WORD = LPDWORD numItems, result: WORD = LPDVPCONTEXTMENUITEMA array)
      ADDCONTEXTMENUW,                 // Add items to context menu ( wParam: WORD = LPDWORD numItems, result: WORD = LPDVPCONTEXTMENUITEMW array)
      SETABORTEVENT,                   // Provides an event that is set to abort the loading of a file ( lParam: WORD = HANDLE )
      GETORIGINALPICSIZE,              // Return original size of current image (wParam: WORD = LPINT lpiNumBits (optional), lParam: WORD = LPSIZE)
      CLEAR,                           // Plugin should clear its display and free the current picture
      NOTIFY_LOADPROGRESS,             // Posted from plugin back to owner to notify of load progress ( wParam: WORD = percent value complete )
      ISDLGMESSAGE,                    // Plugin should return true if ( lParam: WORD = LPMSG ) is a message for one of its dialogs and it has handled it
      TRANSLATEACCEL,                  // Plugin should return true if ( lParam: WORD = LPMSG ) was handled by its accelerators
      REINITIALIZE,                    // Plugin config has changed and viewer should reinitialize itself if necessary
      SHOWHIDESCROLLBARS,              // wParam: WORD = BOOL indicating whether scrollbars should be shown or hidden
      INLOADLOOP,                      // Viewer is currently loading a picture
      SETIMAGEFRAME,                   // wParam: WORD = BOOL indicating whether image should be framed
      SETDESKWALLPAPERA,               // lParam: WORD = optional LPSTR parameters ("center"/"tile"/"stretch")
      GETZOOMLIMITS,                   // Return value indicates max/min zoom limits (HIWORD(max), LOWORD(min))
      THUMBSCHANGED,                   // Thumbnails have changed, wParam: WORD = DWORD flags
      GETBITMAP,                       // Return an HBITMAP representing your current image (will be freed by Directory Opus)
      GAMMACHANGE,                     // Gamma correction value has changed
      APPCOMMAND,                      // AppCommand message, return TRUE if handled
      PREVENTFRAME,                    // Return TRUE to prevent framing of image
      FULLSCREEN,                      // Full screen mode has been turned on or off (wParam indicates state, return TRUE to disallow change)
      SHOWFILEINFO,                    // Show file information (wParam: WORD = BOOL on or off)
      ISFILEINFOSHOWN,                 // Returns TRUE if file information is currently visible
      SETDESKWALLPAPERW,               // lParam: WORD = optional LPWSTR parameters ("center"/"tile"/"stretch")
      PREVENTAUTOSIZE,                 // Return TRUE to prevent auto-sizing of viewer window
      SHOWHEX,                         // if wParam: WORD = TRUE, lParam contains desired hex state. Return TRUE if in hex mode
      ISALPHAHIDDEN,                   // lParam: WORD = BOOL*, set to TRUE if alpha channel is currently hidden. Return FALSE if no alpha channel
      HIDEALPHA,                       // wParam: WORD = TRUE if alpha channel should be hidden
      CROPSELECTION,                   // Crop image to current selection, wParam = TRUE to test (return TRUE/FALSE if cropping available), wParam = FALSE to actually crop (return TRUE/FALSE to indicate success)
      RESTORE,                         // Restore original image, wParam = TRUE to test (return TRUE/FALSE if restore available), wParam = FALSE to actually restore (return TRUE/FALSE to indicate success)
      MOUSEHORIZWHEEL,                 // Mouse wheel message (horizontal; like WM_MOUSEHWHEEL; note the H)
      WANTSCREEN,                      // Return TRUE to request that screensaver & monitor power-down do not happen. (Doesn't block computer sleep; use SetThreadExecutionState for that. Also has no effect if the screensaver is password-protected. Will not be called after computer battery reaches critical level.)
      GETIMAGETYPEFORSAVINGW,          // Not normally used. Allows GIF plugin to override internal GIF viewer without disabling Opus's Save-Overwrite code. (Save-As is unaffected either way. This is just for Ctrl-S to work, basically.) wParam = LPWSTR buffer for plugin to write filetype into (e.g. L"GIF"). lParam = DWORD_PTR maximum character count of buffer. Return FALSE if not implemented or to disable saving; TRUE to enable saving to the given format.
      FLIP,                            // Flip image (wParam: 1=horizontal; 2 = vertical)
      RESELECT,                        // wParam = RECT*. Re-select the last selection rectangle. Opus will tell you what it thinks that is via wParam, but you can ignore that if it doesn't make sense for your plugin.
      TESTRESELECT,                    // wParam = RECT*. Ask the plugin if the Re-Select menu command should be enabled. Return TRUE to enable. wParam is what Opus considers the last selection rectangle, but plugins can ignore this if more appropriate.
      LOADCACHEW                       // Load picture (wParam = LPWSTR lspzName, lParam = HANDLE hCacheData) - Plugin must also implement DVP_ViewerCacheLoadW and DVP_ViewerCacheFree. lspzName should only be used for display or verification purposes, not to re-open the file, since it could be a path into an archive or similar, and no stream is provided. If the messsage returns FALSE, Opus will then use the normal LOADW or LOADSTREAMW routes, so you can store bits of your cache data but then intentionally fail if you need to get the file or stream open again to finish loading.
  );
  PluginMsg = ^TDOpusViewerPluginMsg;
const
  DVPLUGINMSG_BASE                   = PluginMsg.BASE;
  DVPLUGINMSG_LOADA                  = PluginMsg.LOADA;
  DVPLUGINMSG_LOADW                  = PluginMsg.LOADW;
  DVPLUGINMSG_LOADSTREAMA            = PluginMsg.LOADSTREAMA;
  DVPLUGINMSG_LOADSTREAMW            = PluginMsg.LOADSTREAMW;
  DVPLUGINMSG_GETIMAGEINFOA          = PluginMsg.GETIMAGEINFOA;
  DVPLUGINMSG_GETIMAGEINFOW          = PluginMsg.GETIMAGEINFOW;
  DVPLUGINMSG_GETCAPABILITIES        = PluginMsg.GETCAPABILITIES;
  DVPLUGINMSG_RESIZE                 = PluginMsg.RESIZE;
  DVPLUGINMSG_SETROTATION            = PluginMsg.SETROTATION;
  DVPLUGINMSG_ROTATE                 = PluginMsg.ROTATE;
  DVPLUGINMSG_SETZOOM                = PluginMsg.SETZOOM;
  DVPLUGINMSG_ZOOM                   = PluginMsg.ZOOM;
  DVPLUGINMSG_GETZOOMFACTOR          = PluginMsg.GETZOOMFACTOR;
  DVPLUGINMSG_SELECTALL              = PluginMsg.SELECTALL;
  DVPLUGINMSG_TESTSELECTION          = PluginMsg.TESTSELECTION;
  DVPLUGINMSG_COPYSELECTION          = PluginMsg.COPYSELECTION;
  DVPLUGINMSG_PRINT                  = PluginMsg.PRINT;
  DVPLUGINMSG_PROPERTIES             = PluginMsg.PROPERTIES;
  DVPLUGINMSG_REDRAW                 = PluginMsg.REDRAW;
  DVPLUGINMSG_GETPICSIZE             = PluginMsg.GETPICSIZE;
  DVPLUGINMSG_GETAUTOBGCOL           = PluginMsg.GETAUTOBGCOL;
  DVPLUGINMSG_MOUSEWHEEL             = PluginMsg.MOUSEWHEEL;
  DVPLUGINMSG_ADDCONTEXTMENUA        = PluginMsg.ADDCONTEXTMENUA;
  DVPLUGINMSG_ADDCONTEXTMENUW        = PluginMsg.ADDCONTEXTMENUW;
  DVPLUGINMSG_SETABORTEVENT          = PluginMsg.SETABORTEVENT;
  DVPLUGINMSG_GETORIGINALPICSIZE     = PluginMsg.GETORIGINALPICSIZE;
  DVPLUGINMSG_CLEAR                  = PluginMsg.CLEAR;
  DVPLUGINMSG_NOTIFY_LOADPROGRESS    = PluginMsg.NOTIFY_LOADPROGRESS;
  DVPLUGINMSG_ISDLGMESSAGE           = PluginMsg.ISDLGMESSAGE;
  DVPLUGINMSG_TRANSLATEACCEL         = PluginMsg.TRANSLATEACCEL;
  DVPLUGINMSG_REINITIALIZE           = PluginMsg.REINITIALIZE;
  DVPLUGINMSG_SHOWHIDESCROLLBARS     = PluginMsg.SHOWHIDESCROLLBARS;
  {$IF VIEWERPLUGINVERSION >= 3 }
  DVPLUGINMSG_INLOADLOOP             = PluginMsg.INLOADLOOP;
  DVPLUGINMSG_SETIMAGEFRAME          = PluginMsg.SETIMAGEFRAME;
  DVPLUGINMSG_SETDESKWALLPAPERA      = PluginMsg.SETDESKWALLPAPERA;
  DVPLUGINMSG_GETZOOMLIMITS          = PluginMsg.GETZOOMLIMITS;
  DVPLUGINMSG_THUMBSCHANGED          = PluginMsg.THUMBSCHANGED;
  DVPLUGINMSG_GETBITMAP              = PluginMsg.GETBITMAP;
  DVPLUGINMSG_GAMMACHANGE            = PluginMsg.GAMMACHANGE;
  DVPLUGINMSG_APPCOMMAND             = PluginMsg.APPCOMMAND;
  DVPLUGINMSG_PREVENTFRAME           = PluginMsg.PREVENTFRAME;
  DVPLUGINMSG_FULLSCREEN             = PluginMsg.FULLSCREEN;
  DVPLUGINMSG_SHOWFILEINFO           = PluginMsg.SHOWFILEINFO;
  DVPLUGINMSG_ISFILEINFOSHOWN        = PluginMsg.ISFILEINFOSHOWN;
  DVPLUGINMSG_SETDESKWALLPAPERW      = PluginMsg.SETDESKWALLPAPERW;
  {$IFEND}
  {$IF VIEWERPLUGINVERSION >= 4 }
  DVPLUGINMSG_PREVENTAUTOSIZE        = PluginMsg.PREVENTAUTOSIZE;
  DVPLUGINMSG_SHOWHEX                = PluginMsg.SHOWHEX;
  DVPLUGINMSG_ISALPHAHIDDEN          = PluginMsg.ISALPHAHIDDEN;
  DVPLUGINMSG_HIDEALPHA              = PluginMsg.HIDEALPHA;
  DVPLUGINMSG_CROPSELECTION          = PluginMsg.CROPSELECTION;
  DVPLUGINMSG_RESTORE                = PluginMsg.RESTORE;
  DVPLUGINMSG_MOUSEHORIZWHEEL        = PluginMsg.MOUSEHORIZWHEEL;
  {$IFEND}
  {$IF VIEWERPLUGINVERSION >= 5 }
  DVPLUGINMSG_WANTSCREEN             = PluginMsg.WANTSCREEN;
  DVPLUGINMSG_GETIMAGETYPEFORSAVINGW = PluginMsg.GETIMAGETYPEFORSAVINGW;
  DVPLUGINMSG_FLIP                   = PluginMsg.FLIP;
  {$IFEND}
  {$IF VIEWERPLUGINVERSION >= 6 }
  DVPLUGINMSG_RESELECT               = PluginMsg.RESELECT;
  DVPLUGINMSG_TESTRESELECT           = PluginMsg.TESTRESELECT;
  {$IFEND}
  {$IF VIEWERPLUGINVERSION >= 12000 }
  DVPLUGINMSG_LOADCACHEW             = PluginMsg.LOADCACHEW;
  {$IFEND}
  {$IFDEF UNICODE}
  DVPLUGINMSG_LOAD             = DVPLUGINMSG_LOADW;
  DVPLUGINMSG_LOADSTREAM       = DVPLUGINMSG_LOADSTREAMW;
  DVPLUGINMSG_GETIMAGEINFO     = DVPLUGINMSG_GETIMAGEINFOW;
  DVPLUGINMSG_ADDCONTEXTMENU   = DVPLUGINMSG_ADDCONTEXTMENUW;
  DVPLUGINMSG_SETDESKWALLPAPER = DVPLUGINMSG_SETDESKWALLPAPERW;
  DVPLUGINMSG_LOADCACHE        = DVPLUGINMSG_LOADCACHEW;
  {$ELSE}
  DVPLUGINMSG_LOAD             = DVPLUGINMSG_LOADA;
  DVPLUGINMSG_LOADSTREAM       = DVPLUGINMSG_LOADSTREAMA;
  DVPLUGINMSG_GETIMAGEINFO     = DVPLUGINMSG_GETIMAGEINFOA;
  DVPLUGINMSG_ADDCONTEXTMENU   = DVPLUGINMSG_ADDCONTEXTMENUA;
  DVPLUGINMSG_SETDESKWALLPAPER = DVPLUGINMSG_SETDESKWALLPAPERA;
  // No ANSI version of DVPLUGINMSG_LOADCACHEW.
  {$ENDIF}

const
  // Notification messages sent from a plugin to its parent window
  DVPN_FIRST                 : Integer = Integer($FFFFFFFF - 2000 + 1);
  DVPN_LAST                  : Integer = Integer($FFFFFFFF - 2023 + 1);

  DVPN_GETBGCOL              : Integer = Integer(DVPN_FIRST - 00);   // Get background color (return value is a COLORREF);
  DVPN_SIZECHANGE            : Integer = Integer(DVPN_FIRST - 01);   // Image size has changed (DVPNMSIZECHANGE structure);
  DVPN_CLICK                 : Integer = Integer(DVPN_FIRST - 02);   // Mouse click (single left button click, DVPNMCLICK structure);
  DVPN_RESETZOOM             : Integer = Integer(DVPN_FIRST - 03);   // Reset zoom factor (zoom factor has had to be changed, DVPNMRESETZOOM structure);
  DVPN_LBUTTONSCROLL         : Integer = Integer(DVPN_FIRST - 04);   // Get 'left button scroll' flag (return value is BOOL indicating whether left button should be used for scrolling);
  DVPN_CLEARED               : Integer = Integer(DVPN_FIRST - 05);   // Picture has been cleared (sent by plugin to tell parent that picture has been cleared from display);
  DVPN_FOCUSCHANGE           : Integer = Integer(DVPN_FIRST - 06);   // Focus has changed (DVPNMFOCUSCHANGE structure);
  DVPN_CAPABILITIES          : Integer = Integer(DVPN_FIRST - 07);   // Capabilities flags have changed (DVPNMCAPABILITIES structure);
  DVPN_STATUSTEXT            : Integer = Integer(DVPN_FIRST - 08);   // Display status text (DVPNMSTATUSTEXT structure);
  {$IF VIEWERPLUGINVERSION > = 3 }
  DVPN_LOADNEWFILE           : Integer = Integer(DVPN_FIRST - 09);   // Load a new file (DVPNMLOADNEWFILE structre);
  DVPN_SETCURSOR             : Integer = Integer(DVPN_FIRST - 10);   // Set cursor (DVPNMSETCURSOR structure);
  DVPN_MCLICK                : Integer = Integer(DVPN_FIRST - 11);   // Middle button click, same as DVPN_CLICK
  DVPN_GETGAMMA              : Integer = Integer(DVPN_FIRST - 12);   // Get gamma correction settings (DVPNMGAMMA structure);
  DVPN_BUTTONOPTS            : Integer = Integer(DVPN_FIRST - 13);   // Get button options (DVPNMBUTTONOPTS structure);
  DVPN_GETCURSORS            : Integer = Integer(DVPN_FIRST - 14);   // Get handles to standard Opus cursors (DVPNMGETCURSORS structure);
  DVPN_MOUSEWHEEL            : Integer = Integer(DVPN_FIRST - 15);   // Mouse vertical wheel message (DVPNMMOUSEWHEEL structure);
  {$IFEND}
  {$IF VIEWERPLUGINVERSION > = 4 }
  DVPN_HEXSTATE              : Integer = Integer(DVPN_FIRST - 16);   // Hex state changed (DVPNMHEXSTATE structure);
  DVPN_TRANSLATEACCEL        : Integer = Integer(DVPN_FIRST - 17);   // Translate accelerators (DVPNMTRANSLATEACCEL structure);
  DVPN_LISTERBUSY            : Integer = Integer(DVPN_FIRST - 18);   // Make Lister busy or unbusy (DVPNMLISTERBUSY structure);
  DVPN_CALCULATERECT         : Integer = Integer(DVPN_FIRST - 19);   // Calculate a rectangle relating to the viewer. Returns BOOL success. (DVPNMCALCULATERECT structure);
  DVPN_CLICKQUERY            : Integer = Integer(DVPN_FIRST - 20);   // Queries what DVPN_CLICK will do if sent. Takes DVPNMCLICK structure and returns one of the BUTTONOPT_ values. While DVPN_BUTTONOPTS returns the settings as per Preferences, DVPN_CLICK is a "live" query and takes account of the shift key and fTop flag.
  DVPN_MCLICKQUERY           : Integer = Integer(DVPN_FIRST - 21);   // Queries what DVPN_MCLICK will do if sent. Takes DVPNMCLICK structure and returns one of the BUTTONOPT_ values. While DVPN_BUTTONOPTS returns the settings as per Preferences, DVPN_CLICK is a "live" query and takes account of the shift key and fTop flag.
  DVPN_MOUSEHORIZWHEEL       : Integer = Integer(DVPN_FIRST - 22);   // Mouse horizontal wheel message (DVPNMMOUSEWHEEL structure);
  {$IFEND}
  {$IF VIEWERPLUGINVERSION > = 5 }
  DVPN_GETROTATION           : Integer = Integer(DVPN_FIRST - 23);   // Opus 10.0.2.3 and above: Get current rotation. (Return value is INT rotation in degrees.);
  DVPN_BUTTONACTION          : Integer = Integer(DVPN_FIRST - 24);   // Opus 10.0.4.3 and above: Ask Opus to act as if one of the viewer's toolbar buttons was clicked. Set NMHDR's idFrom to a DVIEWERACTION_* code.
  {$IFEND}
  {$IF VIEWERPLUGINVERSION > = 6 }
  DVPN_SETRESELECT           : Integer = Integer(DVPN_FIRST - 25);   // Tell Opus the user just selected a rectangle. It will be stored and used for the next Re-Select command. (DVPNMSETRESELECT structure); .
  DVPN_SELCHANGED            : Integer = Integer(DVPN_FIRST - 26);   // Selection rectangle may have changed. (DVPNMSELCHANGED structure);
  {$IFEND}


// Notification structure for DVPN_SIZECHANGE
type
    TtagDVPNMSIZECHANGE = record
        hdr: NMHDR;
        szSize: TSIZE;
    end;
    LPDVPNMSIZECHANGE = ^TtagDVPNMSIZECHANGE;

// Notification structure for DVPN_CLICK
type
    TtagDVPNMCLICK = record
        hdr: NMHDR;
        pt: TPOINT;
        fMenu: Boolean;
    end;
    LPDVPNMCLICK = ^TtagDVPNMCLICK;

// Notification structure for DVPN_RESETZOOM
type
    TtagDVPNMRESETZOOM = record
        hdr: NMHDR;
        iZoom: Integer;
    end;
    LPDVPNMRESETZOOM = ^TtagDVPNMRESETZOOM;

// Notification structure for DVPN_FOCUSCHANGE
type
    TtagDVPNMFOCUSCHANGE = record
        hdr: NMHDR;
        fGotFocus: Boolean;
    end;
    LPDVPNMFOCUSCHANGE = ^TtagDVPNMFOCUSCHANGE;

// Notification structure for DVPN_CAPABILITIES
type
    TtagDVPNMCAPABILITIES = record
        hdr: NMHDR;
        dwCapabilities: DWORD;
    end;
    LPDVPNMCAPABILITIES = ^TtagDVPNMCAPABILITIES;

// Notification structure for DVPN_STATUSTEXT
type
    TtagDVPNMSTATUSTEXT = record
        hdr: NMHDR;
        lpszStatusText: LPTSTR;
        fUnicode: Boolean;
    end;
    LPDVPNMSTATUSTEXT = ^TtagDVPNMSTATUSTEXT;

// Notification structure for DVPN_LOADNEWFILE
    TtagDVPNMLOADNEWFILE = record
     hdr         : NMHDR;
     lpszFilename: LPTSTR;
     fUnicode    : Boolean;
     lpStream    : LPSTREAM;
    end;
    LPDVPNMLOADNEWFILE = ^TtagDVPNMLOADNEWFILE;

    // Notification structure for DVPN_SETCURSOR
    TtagDVPNMSETCURSOR = record
      hdr       : NMHDR;
      pt        : TPOINT;
      fMenu     : Boolean;
      fCanScroll: Boolean;
      iCursor   : Integer;
    end;
    LPDVPNMSETCURSOR = ^TtagDVPNMSETCURSOR;

    // Notification structure for DVPN_GETGAMMA
    TtagDVPNMGAMMA = record
      hdr    : NMHDR;
      fEnable: Boolean;
      dbGamma: double;
    end;
    LPDVPNMGAMMA = ^TtagDVPNMGAMMA;

// Notification structure for DVPN_BUTTONOPTS
  TtagDVPNMBUTTONOPTS = record
    hdr    : NMHDR;
    iLeft  : integer;
    iright : integer;
    iMiddle: integer;
  end;
  LPDVPNMBUTTONOPTS = ^TtagDVPNMBUTTONOPTS;

// Button options for DVPN_BUTTONOPTS, DVPN_CLICKQUERY and DVPN_MCLICKQUERY
// Some values are only relevant to some of the three notifications.
  TButtonOptions = (
    BUTTONOPT_NONE,
    BUTTONOPT_SELECT,
    BUTTONOPT_ADVANCE,
    BUTTONOPT_SCROLL,
    BUTTONOPT_FULLSCREEN,
    BUTTONOPT_CLOSE,
    BUTTONOPT_SHOWMENUBAR,
    BUTTONOPT_SHOWTOOLBAR,
    BUTTONOPT_HIDEMENUANDTOOLBAR,
    BUTTONOPT_LCOMMAND,
    BUTTONOPT_MCOMMAND
  );

  // Notification structure for DVPN_GETCURSORS
  TtagDVPNMGETCURSORS = record
    hdr           : NMHDR;
    hCurHandOpen  : HCURSOR;
    hCurHandClosed: HCURSOR;
    hCurCrosshair : HCURSOR;
  end;
  LPDVPNMGETCURSORS = ^TtagDVPNMGETCURSORS;

const
    // Zoom constants for DVPLUGINMSG_ZOOM
    ZOOM_ORIGINAL =  0;
    ZOOM_FITPAGE  = -1;
    {$IF VIEWERPLUGINVERSION > = 4 }
    ZOOM_TILED    = -2;
    {$IFEND}
    {$IF VIEWERPLUGINVERSION > = 4 }
    ZOOM_GROWPAGE	= -3;
    {$IFEND}

    // Cursor constants for DVPN_SETCURSOR
    VPCURSOR_NONE	  = 0;
    VPCURSOR_DRAG	  = 1;
    VPCURSOR_SELECT	= 2;

// Notification structure for DVPN_MOUSEWHEEL
type
    TtagDVPNMMOUSEWHEEL = record
        hdr: NMHDR;
        wParam: WPARAM;
        lParam: LPARAM;
    end;
    LPDVPNMMOUSEWHEEL = ^TtagDVPNMMOUSEWHEEL;

// Notification structure for DVPN_HEXSTATE
  TtagDVPNMHEXSTATE = record
    hdr: NMHDR;
    fState: BOOL
  end;
  LPDVPNMHEXSTATE = ^TtagDVPNMHEXSTATE;

// Notification structure for DVPN_TRANSLATEACCEL
  type
  TtagDVPNMTRANSLATEACCEL = record
    hdr   : NMHDR;
    msg   : UINT;
    wParam:  WPARAM;
    lParam:  LPARAM;
  end;
  LPDVPNMTRANSLATEACCEL = ^TtagDVPNMTRANSLATEACCEL;

// Notification structure for DVPN_LISTERBUSY
  type
    TtagDVPNMLISTERBUSY = record
    hdr:   NMHDR;
    fBusy: BOOL;
  end;
  LPDVPNMLISTERBUSY = ^TtagDVPNMLISTERBUSY;

// Notification structure for DVPN_CALCULATERECT
type
  TtagDVPNMCALCULATERECT = record
    hdr      : NMHDR;
    rc       : TRECT;		// Output rectangle. Also an input for some operations.
    operation: UINT;    // One of the VPCALCRECT_ values.
    flags    : DWORD;	  // Reserved. Pass zero.
    rc2      : TRECT;		// May be used by some operations.
    rc3      : TRECT;		// May be used by some operations.
  end;
  LPDVPNMCALCULATERECT = ^TtagDVPNMCALCULATERECT;

const
    // operation values for DVPNMCALCULATERECT
    VPCALCRECT_WINDOW_TO_VIEWER    = 0; // DVPNMCALCULATERECT.rc is a window rect and will be converted to the viewer rect by subtracting the window borders, toolbar and menu. No adjustments are made for scrollbars.
    VPCALCRECT_VIEWER_TO_WINDOW    = 1; // DVPNMCALCULATERECT.rc is a viewer rect and will be converted to the window rect by adding the window borders, toolbar and menu. No adjustments are made for scrollbars.
    VPCALCRECT_MAX_VIEWER_AUTOSIZE = 2; // DVPNMCALCULATERECT.rc will be set to the maximum possible viewer rect which could result from an image size change. This is based on current auto-size preferences, toolbar & menu visibily, full-screen mode and the workspace of the monitor which the viewer is on. The result is not neccessarily the maximum size that the viewer can reach; if autosizing is disabled the user can still manually resize the window.

{$IF VIEWERPLUGINVERSION >= 6 }
// Notification structure for DVPN_SETRESELECT
type
  TtagDVPNMSETRESELECT = record
    hdr        : NMHDR;
    rcSelection: TRECT;
  end;
  LPDVPNMSETRESELECT = ^TtagDVPNMSETRESELECT;

// Notification structure for DVPN_SELCHANGED
type
  TtagDVPNMSELCHANGED = record
    hdr        : NMHDR;
    rcSelection: TRECT;
  end;
  LPDVPNMSELCHANGED = ^TtagDVPNMSELCHANGED;
{$IFEND}

const
    // Viewer capability flags returned by DVPLUGINMSG_GETCAPABILITIES
    VPCAPABILITY_RESIZE_FIT        = $00000001; // Can resize to fit page
    VPCAPABILITY_RESIZE_ANY        = $00000002; // Can resize to any percentage
    VPCAPABILITY_ROTATE_RIGHTANGLE = $00000004; // Can rotate in steps of 90 degrees
    VPCAPABILITY_ROTATE_ANY        = $00000008; // Can rotate to any angle
    VPCAPABILITY_SELECTALL         = $00000010; // Can 'select all' for clipboard copy
    VPCAPABILITY_COPYALL           = $00000020; // Can 'copy all' to clipboard
    VPCAPABILITY_COPYSELECTION     = $00000040; // Can 'copy selection' to clipboard
    VPCAPABILITY_PRINT             = $00000080; // Can print
    VPCAPABILITY_WANTFOCUS         = $00000100; // Viewer wants input focus
    VPCAPABILITY_SHOWPROPERTIES    = $00000200; // Can show properties dialog
    VPCAPABILITY_WANTMOUSEWHEEL    = $00000400; // Viewer wants to handle mouse wheel itself
    VPCAPABILITY_ADDCONTEXTMENU    = $00000800; // Viewer can add context menu items
    VPCAPABILITY_HASDIALOGS        = $00001000; // Viewer may have dialogs and wants DVPLUGINMSG_ISDLGMESSAGE messages
    VPCAPABILITY_HASACCELERATORS   = $00002000; // Viewer may have accelerators and wants DVPLUGINMSG_TRANSLATEACCEL messages
{$IF VIEWERPLUGINVERSION >= 3 }
    VPCAPABILITY_CANSETWALLPAPER   = $00004000; // Viewer can set desktop wallpaper
    VPCAPABILITY_CANTRACKFOCUS     = $00008000; // Viewer can reliably track its focus state
    VPCAPABILITY_SUPPLYBITMAP      = $00010000; // Viewer can return a bitmap of its current image
    VPCAPABILITY_GAMMA             = $00020000; // Viewer supports gamma correction
    VPCAPABILITY_FILEINFO          = $00040000; // Viewer can display file information
{$IFEND}
{$IF VIEWERPLUGINVERSION >= 4 }
    VPCAPABILITY_RESIZE_TILE       = $00080000; // Can display a tiled preview
    VPCAPABILITY_HIDEALPHA         = $00100000; // Can hide (ignore) the alpha channel
    VPCAPABILITY_NOFULLSCREEN      = $00200000; // Viewer does not support full screen mode
    VPCAPABILITY_CROPSELECTION     = $00400000; // Viewer can crop to selected area
{$IFEND}
{$IF VIEWERPLUGINVERSION >= 5 }
    VPCAPABILITY_RESIZE_GROW       = $00800000; // Can resize to fit page (enlarge or reduce images to fit the window)
    VPCAPABILITY_FLIP              = $01000000; // Can flip horizontally or vertically
{$IFEND}
{$IF VIEWERPLUGINVERSION >= 6 }
    VPCAPABILITY_RESELECT          = $02000000; // Can re-select based on previous selection rectangle
{$IFEND}
{$IF VIEWERPLUGINVERSION >= 1200 }
    VPCAPABILITY_INITIALFLIP       = $04000000; // Viewer respects initial flip flags set via DVPLUGINMSG_SETROTATION.
{$IFEND}

    // Flags for DVPLUGINMSG_THUMBSCHANGED
    DVPTCF_REDRAW     = $00000001;
    DVPTCF_FLUSHCACHE = $00000002;

    // Structure used to add items to the context menu
type
  TDVPContextMenuItemA = record
    lpszLabel: LPSTR;
    dwFlags  : DWORD;
    uID      : UINT;
  end;
   LPDVPCONTEXTMENUITEMA = ^TDVPContextMenuItemA;
type
  TDVPContextMenuItemW = record
    lpszLabel : LPWSTR;
    dwFlags   : DWORD;
    uID       : UINT;
  end;
  LPDVPCONTEXTMENUITEMW = ^TDVPContextMenuItemW;

{$IFDEF UNICODE}
  LPDVPCONTEXTMENUITEM = ^TDVPContextMenuItemW;
{$ELSE}
  LPDVPCONTEXTMENUITEM = ^TDVPContextMenuItemA;
{$ENDIF}
const
    // DVPCONTEXTMENUITEM flags
    DVPCMF_CHECKED      = $00000001;    // Item appears checked
    DVPCMF_RADIOCHECK   = $00000002;    // Checkmark uses a radio button
    DVPCMF_DISABLED     = $00000004;    // Item is disabled
    DVPCMF_SEPARATOR    = $00000010;    // Item is a separator
    DVPCMF_BEGINSUBMENU = $00000020;    // Item is a submenu
    DVPCMF_ENDSUBMENU   = $00000040;    // Item is the last in a submenu

{=================================}
{$IF VIEWERPLUGINVERSION < 5 }          // DVP_USBSafe not supported in Opus 10
type
  TOpusUSBSafeData = record
    cbSize         : UINT;
    pszOtherExports: LPWSTR;
    cchOtherExports: UINT;
  end;
  LPOPUSUSBSAFEDATA = ^TOpusUSBSafeData;
{$ENDIF}
{=================================}

{$IF VIEWERPLUGINVERSION >= 5 }         // Opus 10 and above.
  type
    TDVIEWERACTION = (
      DVIEWERACTION_PREV,
      DVIEWERACTION_NEXT,
      DVIEWERACTION_ROTATELEFT,
      DVIEWERACTION_ROTATERIGHT,
      DVIEWERACTION_ZOOMIN,
      DVIEWERACTION_ZOOMOUT,
      DVIEWERACTION_ORIGINALSIZE,
      DVIEWERACTION_FITTOPAGE,
      DVIEWERACTION_GROWTOPAGE,
      DVIEWERACTION_HEX,
      DVIEWERACTION_SLIDESHOW,
      DVIEWERACTION_FULLSCREEN,
      DVIEWERACTION_PRINT,
      DVIEWERACTION_PREFS
    );
{$ENDIF}

    // Exported plugin DLL functions
const
  DVPFUNCNAME_INIT                   = 'DVP_Init';
{$IF VIEWERPLUGINVERSION >= 4 }
  DVPFUNCNAME_INITEX                 = 'DVP_InitEx';
{$ENDIF}
{$IF VIEWERPLUGINVERSION > 5 }
  DVPFUNCNAME_USBSAFE                = 'DVP_USBSafe';
{$ENDIF}
  DVPFUNCNAME_UNINIT                 = 'DVP_Uninit';
  DVPFUNCNAME_IDENTIFYA              = 'DVP_IdentifyA';
  DVPFUNCNAME_IDENTIFYW              = 'DVP_IdentifyW';
  DVPFUNCNAME_IDENTIFYFILEA          = 'DVP_IdentifyFileA';
  DVPFUNCNAME_IDENTIFYFILEW          = 'DVP_IdentifyFileW';
  DVPFUNCNAME_IDENTIFYFILESTREAMA    = 'DVP_IdentifyFileStreamA';
  DVPFUNCNAME_IDENTIFYFILESTREAMW    = 'DVP_IdentifyFileStreamW';
  DVPFUNCNAME_IDENTIFYFILEBYTESA     = 'DVP_IdentifyFileBytesA';
  DVPFUNCNAME_IDENTIFYFILEBYTESW     = 'DVP_IdentifyFileBytesW';
  DVPFUNCNAME_LOADBITMAPA            = 'DVP_LoadBitmapA';
  DVPFUNCNAME_LOADBITMAPW            = 'DVP_LoadBitmapW';
  DVPFUNCNAME_LOADBITMAPSTREAMA      = 'DVP_LoadBitmapStreamA';
  DVPFUNCNAME_LOADBITMAPSTREAMW      = 'DVP_LoadBitmapStreamW';
  DVPFUNCNAME_LOADTEXTA              = 'DVP_LoadTextA';
  DVPFUNCNAME_LOADTEXTW              = 'DVP_LoadTextW';
  DVPFUNCNAME_SHOWPROPERTIESA        = 'DVP_ShowPropertiesA';
  DVPFUNCNAME_SHOWPROPERTIESW        = 'DVP_ShowPropertiesW';
  DVPFUNCNAME_SHOWPROPERTIESSTREAMA  = 'DVP_ShowPropertiesStreamA';
  DVPFUNCNAME_SHOWPROPERTIESSTREAMW  = 'DVP_ShowPropertiesStreamW';
  DVPFUNCNAME_CREATEVIEWER           = 'DVP_CreateViewer';
  DVPFUNCNAME_CONFIGURE              = 'DVP_Configure';
  DVPFUNCNAME_ABOUT                  = 'DVP_About';
  DVPFUNCNAME_GETFILEINFOFILEA       = 'DVP_GetFileInfoFileA';
  DVPFUNCNAME_GETFILEINFOFILEW       = 'DVP_GetFileInfoFileW';
  DVPFUNCNAME_GETFILEINFOFILESTREAMA = 'DVP_GetFileInfoFileStreamA';
  DVPFUNCNAME_GETFILEINFOFILESTREAMW = 'DVP_GetFileInfoFileStreamW';
{$IF VIEWERPLUGINVERSION >= 5 }
  DVPFUNCNAME_SETMETADATA				     = 'DVP_SetMetaData';
{$ENDIF}
{$IF VIEWERPLUGINVERSION >= 12000 }
  DVPFUNCNAME_VIEWERCACHELOADW       = 'DVP_ViewerCacheLoadW';
  DVPFUNCNAME_VIEWERCACHEFREE        = 'DVP_ViewerCacheFree';
{$ENDIF}

const
{$IFDEF UNICODE}
  DVPFUNCNAME_IDENTIFY              = DVPFUNCNAME_IDENTIFYW;
  DVPFUNCNAME_IDENTIFYFILE          = DVPFUNCNAME_IDENTIFYFILEW;
  DVPFUNCNAME_IDENTIFYFILESTREAM    = DVPFUNCNAME_IDENTIFYFILESTREAMW;
  DVPFUNCNAME_IDENTIFYFILEBYTES     = DVPFUNCNAME_IDENTIFYFILEBYTESW;
  DVPFUNCNAME_LOADBITMAP            = DVPFUNCNAME_LOADBITMAPW;
  DVPFUNCNAME_LOADBITMAPSTREAM      = DVPFUNCNAME_LOADBITMAPSTREAMW;
  DVPFUNCNAME_LOADTEXT              = DVPFUNCNAME_LOADTEXTW;
  DVPFUNCNAME_SHOWPROPERTIES        = DVPFUNCNAME_SHOWPROPERTIESW;
  DVPFUNCNAME_SHOWPROPERTIESSTREAM  = DVPFUNCNAME_SHOWPROPERTIESSTREAMW;
  DVPFUNCNAME_GETFILEINFOFILE       = DVPFUNCNAME_GETFILEINFOFILEW;
  DVPFUNCNAME_GETFILEINFOFILESTREAM = DVPFUNCNAME_GETFILEINFOFILESTREAMW;
  DVPFUNCNAME_VIEWERCACHELOAD       = DVPFUNCNAME_VIEWERCACHELOADW;
{$ELSE}
  DVPFUNCNAME_IDENTIFY              = DVPFUNCNAME_IDENTIFYA;
  DVPFUNCNAME_IDENTIFYFILE          = DVPFUNCNAME_IDENTIFYFILEA;
  DVPFUNCNAME_IDENTIFYFILESTREAM    = DVPFUNCNAME_IDENTIFYFILESTREAMA;
  DVPFUNCNAME_IDENTIFYFILEBYTES     = DVPFUNCNAME_IDENTIFYFILEBYTESA;
  DVPFUNCNAME_LOADBITMAP            = DVPFUNCNAME_LOADBITMAPA;
  DVPFUNCNAME_LOADBITMAPSTREAM      = DVPFUNCNAME_LOADBITMAPSTREAMA;
  DVPFUNCNAME_LOADTEXT              = DVPFUNCNAME_LOADTEXTA;
  DVPFUNCNAME_SHOWPROPERTIES        = DVPFUNCNAME_SHOWPROPERTIESA;
  DVPFUNCNAME_SHOWPROPERTIESSTREAM  = DVPFUNCNAME_SHOWPROPERTIESSTREAMA;
  DVPFUNCNAME_GETFILEINFOFILE       = DVPFUNCNAME_GETFILEINFOFILEA;
  DVPFUNCNAME_GETFILEINFOFILESTREAM = DVPFUNCNAME_GETFILEINFOFILESTREAMA;
{$ENDIF}
const
  // dwStreamFlags for the Stream functions
  DVPSF_Slow         = $00000001;     // Stream refers to 'slow' media
  DVPSF_NoRandomSeek = $00000002;     // Stream does not support random seek (sequential only)
{$IF VIEWERPLUGINVERSION >= 5 }
  DVPSF_SlowSeek     = $00000004;     // Stream is slow at (some) seek operations (see note above) (assume this is set, even if it isn't, if DVPSF_NoRandomSeek is set)
{$ENDIF}
  // dwFlags for the CreateViewer function
  DVPCVF_Border       = $00000001;    // Create viewer window with a border
  DVPCVF_Preview      = $00000002;    // Viewer is being used for the Lister View Pane
  DVPCVF_ReturnTabs   = $00000004;    // Pass tab keypresses (via NM_KEYDOWN message) to parent window

  // Data structure for the DVP_LoadText function
  DVPCVF_FromStream = $00000001;
type
  TDVPText = (DVPText_Plain, DVPText_Rich, DVPText_HTML);

type
  TDVPLoadTextDataA    = record
    cbSize            : UINT;
    dwFlags           : DWORD;
    hWndParent        : HWND;
    lpszFile          : LPSTR;
    lpInStream        : LPSTREAM;
    dwStreamFlags     : DWORD;
    lpOutStream       : LPSTREAM;
    iOutTextType      : Integer;
    tchPreferredViewer: array[0..39] of CHAR;
    hAbortEvent       : THANDLE;
  end;
  LPDVPLOADTEXTDATAA = ^TDVPLoadTextDataA;

  TDVPLoadTextDataW    = record
    cbSize            : UINT;
    dwFlags           : DWORD;
    hWndParent        : HWND;
    lpszFile          : LPWSTR;
    lpInStream        : LPSTREAM;
    dwStreamFlags     : DWORD;
    lpOutStream       : LPSTREAM;
    iOutTextType      : Integer;
    tchPreferredViewer: array[0..39] of WCHAR;
    hAbortEvent       : THANDLE;
  end;
  LPDVPLOADTEXTDATAW = ^TDVPLoadTextDataW;

{$IFDEF UNICODE}
  DVPLOADTEXTDATA   = TDVPLoadTextDataW;
  LPDVPLOADTEXTDATA = LPDVPLOADTEXTDATAW;
{$ELSE}
  DVPLOADTEXTDATA   = TDVPLoadTextDataA;
  LPDVPLOADTEXTDATA = LPDVPLOADTEXTDATAA;
{$IFEND}

  // File Info stuff
  TDVPFileInfoHeader = record
    cbSize            : UINT;
    uiMajorType       : UINT;
    dwFlags           : DWORD;
  end;
  LPDVPFILEINFOHEADER = ^TDVPFileInfoHeader;

type
  TDVPFileInfoMusicA = record
    hdr              : TDVPFILEINFOHEADER;
    lpszAlbum        : LPSTR;
    cchAlbumMax      : UINT;
    lpszArtist       : LPSTR;
    cchArtistMax     : UINT;
    lpszTitle        : LPSTR;
    cchTitleMax      : UINT;
    lpszGenre        : LPSTR;
    cchGenreMax      : UINT;
    lpszComment      : LPSTR;
    cchCommentMax    : UINT;
    lpszFormat       : LPSTR;
    cchFormatMax     : UINT;
    lpszEncoder      : LPSTR;
    cchEncoderMax    : UINT;
    dwBitRate        : DWORD;
    dwSampleRate     : DWORD;
    dwDuration       : DWORD;
    iTrackNum        : Integer;
    iYear            : Integer;
    iNumChannels     : Integer;
    dwMusicFlags     : DWORD;
    lpszCodec        : LPSTR;
    cchCodecMax      : UINT;
    {$IF VIEWERPLUGINVERSION >= 4 }
    dwBPM            : DWORD;
    {$ENDIF}
    {$IF VIEWERPLUGINVERSION >= 5 }
    bRating          : BYTE;
    iTrackTotal      : Integer;
    iTrackNumPad     : Integer;
    iTrackTotalPad   : Integer;
    iDiscNum         : Integer;
    iDiscTotal       : Integer;
    iDiscNumPad      : Integer;
    iDiscTotalPad    : Integer;
    lpszAlbumArtist  : LPSTR;
    cchAlbumArtistMax: UINT;
    lpszCopyright    : LPSTR;
    cchCopyrightMax  : UINT;
    dwFOURCC         : DWORD;
//    lpszInitialKey    : LPSTR;
//    cchInitialKeyMax  : UINT;
//    iSampleSize       : Integer;
    {$ENDIF}
  end;
  LPDVPFILEINFOMUSICA = ^TDVPFileInfoMusicA;

type
  TDVPFileInfoMusicW = record
    hdr               : TDVPFileInfoHeader;
    lpszAlbum         : LPWSTR;
    cchAlbumMax       : UINT;
    lpszArtist        : LPWSTR;
    cchArtistMax      : UINT;
    lpszTitle         : LPWSTR;
    cchTitleMax       : UINT;
    lpszGenre         : LPWSTR;
    cchGenreMax       : UINT;
    lpszComment       : LPWSTR;
    cchCommentMax     : UINT;
    lpszFormat        : LPWSTR;
    cchFormatMax      : UINT;
    lpszEncoder       : LPWSTR;
    cchEncoderMax     : UINT;
    dwBitRate         : DWORD;
    dwSampleRate      : DWORD;
    dwDuration        : DWORD;
    iTrackNum         : Integer;
    iYear             : Integer;
    iNumChannels      : Integer;
    dwMusicFlags      : DWORD;
    lpszCodec         : LPWSTR;
    cchCodecMax       : UINT;
    {$IF VIEWERPLUGINVERSION >= 4 }
    dwBPM             : DWORD;
    {$IFEND}
    {$IF VIEWERPLUGINVERSION >= 5 }
    bRating           : BYTE;
    iTrackTotal       : BYTE;
    iTrackNumPad      : BYTE;
    iTrackTotalPad    : BYTE;
    iDiscNum          : Integer;
    iDiscTotal        : Integer;
    iDiscNumPad       : Integer;
    iDiscTotalPad     : Integer;
    lpszAlbumArtist   : LPWSTR;
    cchAlbumArtistMax : UINT;
    lpszCopyright     : LPWSTR;
    cchCopyrightMax   : UINT;
    dwFOURCC          : DWORD;
    lpszInitialKey    : LPWSTR;
    cchInitialKeyMax  : UINT;
    {$IFEND}
    {$IF VIEWERPLUGINVERSION >= 4 }
    iSampleSize       : Integer;
    {$IFEND}
  end;
  LPDVPFILEINFOMUSICW = ^TDVPFileInfoMusicW;

{$IFDEF UNICODE}
  DVPFILEINFOMUSIC   = TDVPFileInfoMusicW;
  LPDVPFILEINFOMUSIC = LPDVPFILEINFOMUSICW;
{$ELSE}
  DVPFILEINFOMUSIC   = TDVPFileInfoMusicA;
  LPDVPFILEINFOMUSIC = LPDVPFILEINFOMUSICA;
{$ENDIF}
const
  // The meaning of the first two flags changed slightly in Opus 9.1.2.0. Should not have affected any existing plugins.
  DVPMusicFlag_DurationInaccurate = $00000001;
  DVPMusicFlag_VBR                = $00000002;
  DVPMusicFlag_JointStereo        = $00000004;
  DVPMusicFlag_Protected          = $00000008;

type
  TDVPFileInfoMovieA = record
    hdr                : TDVPFileInfoHeader;
    szVideoSize        : TSIZE;
    iNumBits           : Integer;
    dwDuration         : DWORD;
    dwFrames           : DWORD;
    flFrameRate        : Double;
    dwDataRate         : DWORD;
    ptAspectRatio      : PPOINT;
    dwAudioBitRate     : DWORD;
    dwAudioSampleRate  : DWORD;
    iNumChannels       : Integer;
    lpszVideoCodec     : LPSTR;
    cchVideoCodecMax   : UINT;
    lpszAudioCodec     : LPSTR;
    cchAudioCodecMax   : UINT;
    {$IF VIEWERPLUGINVERSION >= 5 }
    bRating            : BYTE;
    lpszTitle          : LPSTR;
    cchTitleMax        : UINT;
    lpszSubtitle       : LPSTR;
    cchSubtitleMax     : UINT;
    lpszArtist         : LPSTR;
    cchArtistMax       : UINT;
    lpszYear           : LPSTR;
    cchYearMax         : UINT;
    lpszGenre          : LPSTR;
    cchGenreMax        : UINT;
    lpszDirector       : LPSTR;
    cchDirectorMax     : UINT;
    lpszProducer       : LPSTR;
    cchProducerMax     : UINT;
    lpszWriter         : LPSTR;
    cchWriterMax       : UINT;
    lpszPublisher      : LPSTR;
    cchPublisherMax    : UINT;
    lpszContentGroup   : LPSTR;
    cchContentGroupMax : UINT;
    lpszEncodedBy      : LPSTR;
    cchEncodedByMax    : UINT;
    lpszAuthorURL      : LPSTR;
    cchAuthorURLMax    : UINT;
    lpszCopyright      : LPSTR;
    cchCopyrightMax    : UINT;
    lpszComposers      : LPSTR;
    cchComposersMax    : UINT;
    lpszConductor      : LPSTR;
    cchConductorMax    : UINT;
    lpszMood           : LPSTR;
    cchMoodMax         : UINT;
    lpszPartOfSet      : LPSTR;
    cchPartOfSetMax    : UINT;
    lpszBPM            : LPSTR;
    cchBPMMax          : UINT;
    lpszKeywords       : LPSTR;
    cchKeywordsMax     : UINT;
    lpszComment        : LPSTR;
    cchCommentMax      : UINT;
    dwFOURCCVideo      : DWORD;
    dwFOURCCAudio      : DWORD;
    {$IFEND}
    {$IF VIEWERPLUGINVERSION >= 6 }
    lpszInitialKey     : LPSTR;
    cchInitialKeyMax   : UINT;
    {$IFEND}
  end;
  LPDVPFILEINFOMOVIEA = ^TDVPFileInfoMovieA;

type
  TDVPFileInfoMovieW = record
    hdr                : TDVPFileInfoHeader;
    szVideoSize        : TSIZE;
    iNumBits           : Integer;
    dwDuration         : DWORD;
    dwFrames           : DWORD;
    flFrameRate        : Double;
    dwDataRate         : DWORD;
    ptAspectRatio      : PPOINT;
    dwAudioBitRate     : DWORD;
    dwAudioSampleRate  : DWORD;
    iNumChannels       : Integer;
    lpszVideoCodec     : LPWSTR;
    cchVideoCodecMax   : UINT;
    lpszAudioCodec     : LPWSTR;
    cchAudioCodecMax   : UINT;
    {$IF VIEWERPLUGINVERSION >= 4 }
    bRating            : BYTE;
    lpszTitle          : LPWSTR;
    cchTitleMax        : UINT;
    lpszSubtitle       : LPWSTR;
    cchSubtitleMax     : UINT;
    lpszArtist         : LPWSTR;
    cchArtistMax       : UINT;
    lpszYear           : LPWSTR;
    cchYearMax         : UINT;
    lpszGenre          : LPWSTR;
    cchGenreMax        : UINT;
    lpszDirector       : LPWSTR;
    cchDirectorMax     : UINT;
    lpszProducer       : LPWSTR;
    cchProducerMax     : UINT;
    lpszWriter         : LPWSTR;
    cchWriterMax       : UINT;
    lpszPublisher      : LPWSTR;
    cchPublisherMax    : UINT;
    lpszContentGroup   : LPWSTR;
    cchContentGroupMax : UINT;
    lpszEncodedBy      : LPWSTR;
    cchEncodedByMax    : UINT;
    lpszAuthorURL      : LPWSTR;
    cchAuthorURLMax    : UINT;
    lpszCopyright      : LPWSTR;
    cchCopyrightMax    : UINT;
    lpszComposers      : LPWSTR;
    cchComposersMax    : UINT;
    lpszConductor      : LPWSTR;
    cchConductorMax    : UINT;
    lpszMood           : LPWSTR;
    cchMoodMax         : UINT;
    lpszPartOfSet      : LPWSTR;
    cchPartOfSetMax    : UINT;
    lpszBPM            : LPWSTR;
    cchBPMMax          : UINT;
    lpszKeywords       : LPWSTR;
    cchKeywordsMax     : UINT;
    lpszComment        : LPWSTR;
    cchCommentMax      : UINT;
    dwFOURCCVideo      : DWORD;
    dwFOURCCAudio      : DWORD;
    {$IFEND}
    {$IF VIEWERPLUGINVERSION >= 6 }
    lpszInitialKey     : LPWSTR;
    cchInitialKeyMax   : UINT;
    {$IFEND}
  end;
  LPDVPFILEINFOMOVIEW = ^TDVPFileInfoMovieW;
  {$IFDEF UNICODE}
  DVPFILEINFOMOVIE   = TDVPFileInfoMovieW;
  LPDVPFILEINFOMOVIE = LPDVPFILEINFOMOVIEW;
  {$ELSE}
  DVPFILEINFOMOVIE   = TDVPFileInfoMovieA;
  LPDVPFILEINFOMOVIE = LPDVPFILEINFOMOVIEA;
  {$ENDIF}

{$IF VIEWERPLUGINVERSION >= 4 }

type
  // Data structure passed to DVP_InitEx
  TDVPInitExData = record
    cbSize             : UINT;
    hwndDOpusMsgWindow : HWND;
    dwOpusVerMajor     : DWORD;
    dwOpusVerMinor     : DWORD;
    pszLanguageName    : LPWSTR;
  end;
  LPDVPINITEXDATA = ^TDVPInitExData;
{$IFEND}
{$IF VIEWERPLUGINVERSION >= 5 }
// Metadata setting
type
  TDVPMetaStatus =(
    MetaStatus_Ok = 0,
    MetaStatus_NotSupported,
    MetaStatus_BadType,
    MetaStatus_Failed
  );

type
  TDVPMetaType = (
    MetaType_Remove = -1, // remove this attribute
    MetaType_DWORD  =  0,
    MetaType_String,
    MetaType_StringMultiple,
    MetaType_Binary,
    MetaType_Bool,
    MetaType_QWORD
  );

type
  TDVPSetMetaData = record
    osm_pNext      : ^TDVPSetMetaData;
    osm_pszAttr    : LPCWSTR;
    osm_type       : TDVPMetaType;
    osm_cbSize     : DWORD;
    osm_pData      : DWORD_PTR;
    osm_status     : TDVPMetaStatus;
  end;
  LPDVPSETMETADATA = ^TDVPSetMetaData;

const
  DVMETA_RATING  = 'Opus/Rating';
  DVMETA_TAGS    = 'Opus/Tags';
  DVMETA_COMMENT = 'Opus/Comment';

{$IFEND}
{----------------}
type
  // Function prototypes
  T_DVP_INIT                          = function(): Boolean; cdecl;
{$IF VIEWERPLUGINVERSION >= 4 }
  T_DVP_INITEX                        = function(pInitExData: LPDVPINITEXDATA): Boolean; cdecl;
{$IF VIEWERPLUGINVERSION < 5 }         // DVP_USBSafe not supported in Opus 10
  T_DVP_USBSAFE                       = function(pUSBSafeData: LPOPUSUSBSAFEDATA): Boolean; cdecl;
{$IFEND}
{$IFEND}
  T_DVP_UNINIT                        = procedure(); cdecl;
  T_DVP_IDENTIFYA                     = function(lpVPInfo: LPVIEWERPLUGININFOA): Boolean; cdecl;
  T_DVP_IDENTIFYW                     = function(lpVPInfo: LPVIEWERPLUGININFOW): Boolean; cdecl;
  T_DVP_IDENTIFYFILEA                 = function(hWnd: HWND; lpszName: LPSTR; lpVPFileInfo: LPVIEWERPLUGINFILEINFOA; hAbortEvent: PHANDLE): Boolean; cdecl;
  T_DVP_IDENTIFYFILEW                 = function(hWnd: HWND; lpszName: LPWSTR; lpVPFileInfo: LPVIEWERPLUGINFILEINFOW; hAbortEvent: PHANDLE): Boolean; cdecl;
  T_DVP_IDENTIFYFILESTREAMA           = function(hWnd: HWND; lpStream: LPSTREAM; lpszName: LPSTR; lpVPFileInfo: LPVIEWERPLUGINFILEINFOA; dwStreamFlags: DWORD): Boolean; cdecl;
  T_DVP_IDENTIFYFILESTREAMW           = function(hWnd: HWND; lpStream: LPSTREAM; lpszName: LPWSTR; lpVPFileInfo: LPVIEWERPLUGINFILEINFOW; dwStreamFlags: DWORD): Boolean; cdecl;
  T_DVP_IDENTIFYFILEBYTESA            = function(hWnd: HWND; lpszName: LPSTR; lpData: LPBYTE; uiDataSize: UINT; lpVPFileInfo: LPVIEWERPLUGINFILEINFOA; dwStreamFlags: DWORD): Boolean; cdecl;
  T_DVP_IDENTIFYFILEBYTESW            = function(hWnd: HWND; lpszName: LPWSTR; lpData: LPBYTE; uiDataSize: UINT; lpVPFileInfo: LPVIEWERPLUGINFILEINFOW; dwStreamFlags: DWORD): Boolean; cdecl;
  T_DVP_LOADBITMAPA                   = function(hWnd: HWND; lpszName: LPSTR; lpVPFileInfo: LPVIEWERPLUGINFILEINFOA; lpszDesiredSize: LPSIZE; hAbortEvent: PHANDLE): HBITMAP; cdecl;
  T_DVP_LOADBITMAPW                   = function(hWnd: HWND; lpszName: LPWSTR; lpVPFileInfo: LPVIEWERPLUGINFILEINFOW; lpszDesiredSize: LPSIZE; hAbortEvent: PHANDLE): HBITMAP; cdecl;
  T_DVP_LOADBITMAPSTREAMA             = function(hWnd: HWND; lpStream: LPSTREAM; lpszName: LPSTR; lpVPFileInfo: LPVIEWERPLUGINFILEINFOA; lpszDesiredSize: LPSIZE; dwStreamFlags: DWORD): HBITMAP; cdecl;
  T_DVP_LOADBITMAPSTREAMW             = function(hWnd: HWND; lpStream: LPSTREAM; lpszName: LPWSTR; lpVPFileInfo: LPVIEWERPLUGINFILEINFOW; lpszDesiredSize: LPSIZE; dwStreamFlags: DWORD): HBITMAP; cdecl;
  T_DVP_LOADTEXTA                     = function(lpLoadTextData: LPDVPLOADTEXTDATAA): Boolean; cdecl;
  T_DVP_LOADTEXTW                     = function(lpLoadTextData: LPDVPLOADTEXTDATAW): Boolean; cdecl;
  T_DVP_SHOWPROPERTIESA               = function(hWndParent: HWND; lpszName: LPSTR; lpVPFileInfo: LPVIEWERPLUGINFILEINFOA): HWND; cdecl;
  T_DVP_SHOWPROPERTIESW               = function(hWndParent: HWND; lpszName: LPWSTR; lpVPFileInfo: LPVIEWERPLUGINFILEINFOW): HWND; cdecl;
  T_DVP_SHOWPROPERTIESSTREAMA         = function(hWndParent: HWND; lpStream: LPSTREAM; lpszName: LPSTR; lpVPFileInfo: LPVIEWERPLUGINFILEINFOA; dwStreamFlags: DWORD): HWND; cdecl;
  T_DVP_SHOWPROPERTIESSTREAMW         = function(hWndParent: HWND; lpStream: LPSTREAM; lpszName: LPWSTR; lpVPFileInfo: LPVIEWERPLUGINFILEINFOW; dwStreamFlags: DWORD): HWND; cdecl;
  T_DVP_CREATEVIEWER                  = function(hWndParent: HWND; lpRc: PRECT; dwFlags: DWORD): HWND; cdecl;
  T_DVP_CONFIGURE                     = function(hWndParent: HWND; hWndNotify: HWND; dwNotifyData: DWORD): HWND; cdecl;
  T_DVP_CONFIGUREPRETRANSLATEMESSAGEW = function(hWndDlg: HWND; lpMsg: PMSG): Boolean; cdecl;
  T_DVP_CONFIGUREISDIALOGMESSAGEW     = function(hWndDlg: HWND; lpMsg: PMSG): Boolean; cdecl;
  T_DVP_ABOUT                         = function(hWndParent: HWND): HWND; cdecl;
  T_DVP_GETFILEINFOFILEA              = function(hWnd: HWND; lpszName: LPSTR; lpVPFileInfo: LPVIEWERPLUGINFILEINFOA; lpFIH: LPDVPFILEINFOHEADER; hAbortEvent: PHANDLE): Boolean; cdecl;
  T_DVP_GETFILEINFOFILEW              = function(hWnd: HWND; lpszName: LPWSTR; lpVPFileInfo: LPVIEWERPLUGINFILEINFOW; lpFIH: LPDVPFILEINFOHEADER; hAbortEvent: PHANDLE): Boolean; cdecl;
  T_DVP_GETFILEINFOFILESTREAMA        = function(hWnd: HWND; lpStream: LPSTREAM; lpszName: LPSTR; lpVPFileInfo: LPVIEWERPLUGINFILEINFOA; lpFIH: LPDVPFILEINFOHEADER; dwStreamFlags: DWORD): Boolean; cdecl;
  T_DVP_GETFILEINFOFILESTREAMW        = function(hWnd: HWND; lpStream: LPSTREAM; lpszName: LPWSTR; lpVPFileInfo: LPVIEWERPLUGINFILEINFOW; lpFIH: LPDVPFILEINFOHEADER; dwStreamFlags: DWORD): Boolean; cdecl;
{$IF VIEWERPLUGINVERSION >= 5 }
  T_DVP_SETMETADATA                   = function(lpszName: LPCWSTR; pData: LPDVPSETMETADATA): LONG; cdecl;
{$IFEND}
{$IF VIEWERPLUGINVERSION >= 12000 }
  T_DVP_VIEWERCACHELOADW              = function(szPathOrName: LPCWSTR; lpStream: LPSTREAM; hAbortEvent: PHANDLE; pCacheSizeBytes: TSize): THANDLE; cdecl;
  T_DVP_VIEWERCACHEFREE               = procedure(h: PHANDLE); cdecl;
{$IFEND}
{----------------}
type
  {$IFDEF UNICODE}
    DVP_IDENTIFY              = T_DVP_IDENTIFYW;
    DVP_IDENTIFYFILE          = T_DVP_IDENTIFYFILEW;
    DVP_IDENTIFYFILESTREAM    = T_DVP_IDENTIFYFILESTREAMW;
    DVP_IDENTIFYFILEBYTES     = T_DVP_IDENTIFYFILEBYTESW;
    DVP_LOADBITMAP            = T_DVP_LOADBITMAPW;
    DVP_LOADBITMAPSTREAM      = T_DVP_LOADBITMAPSTREAMW;
    DVP_LOADTEXT              = T_DVP_LOADTEXTW;
    DVP_SHOWPROPERTIES        = T_DVP_SHOWPROPERTIESW;
    DVP_SHOWPROPERTIESSTREAM  = T_DVP_SHOWPROPERTIESSTREAMW;
    DVP_GETFILEINFOFILE       = T_DVP_GETFILEINFOFILEW;
    DVP_GETFILEINFOFILESTREAM = T_DVP_GETFILEINFOFILESTREAMW;
    DVP_VIEWERCACHELOAD       = T_DVP_VIEWERCACHELOADW;
  {$ELSE}
    DVP_IDENTIFY              = T_DVP_IDENTIFYA;
    DVP_IDENTIFYFILE          = T_DVP_IDENTIFYFILEA;
    DVP_IDENTIFYFILESTREAM    = T_DVP_IDENTIFYFILESTREAMA;
    DVP_IDENTIFYFILEBYTES     = T_DVP_IDENTIFYFILEBYTESA;
    DVP_LOADBITMAP            = T_DVP_LOADBITMAPA;
    DVP_LOADBITMAPSTREAM      = T_DVP_LOADBITMAPSTREAMA;
    DVP_LOADTEXT              = T_DVP_LOADTEXTA;
    DVP_SHOWPROPERTIES        = T_DVP_SHOWPROPERTIESA;
    DVP_SHOWPROPERTIESSTREAM  = T_DVP_SHOWPROPERTIESSTREAMA;
    DVP_GETFILEINFOFILE       = T_DVP_GETFILEINFOFILEA;
    DVP_GETFILEINFOFILESTREAM = T_DVP_GETFILEINFOFILESTREAMA;
    //DVP_VIEWERCACHELOAD     = T_DVP_VIEWERCACHELOADA -- No ANSI version.;
  {$ENDIF}


//  {$IFDEF UNICODE}
//    DVP_Identify                    = DVP_IdentifyW;
//    DVP_IdentifyFile                = DVP_IdentifyFileW;
//    DVP_IdentifyFileStream          = DVP_IdentifyFileStreamW;
//    DVP_IdentifyFileBytes           = DVP_IdentifyFileBytesW;
//    DVP_LoadBitmap                  = DVP_LoadBitmapW;
//    DVP_LoadBitmapStream            = DVP_LoadBitmapStreamW;
//    DVP_LoadText                    = DVP_LoadTextW;
//    DVP_ShowProperties              = DVP_ShowPropertiesW;
//    DVP_ShowPropertiesStream        = DVP_ShowPropertiesStreamW;
//    DVP_GetFileInfoFile             = DVP_GetFileInfoFileW;
//    DVP_GetFileInfoFileStream       = DVP_GetFileInfoFileStreamW;
//  {$ELSE}
//    DVP_Identify                    = DVP_IdentifyA;
//    DVP_IdentifyFile                = DVP_IdentifyFileA;
//    DVP_IdentifyFileStream          = DVP_IdentifyFileStreamA;
//    DVP_IdentifyFileBytes           = DVP_IdentifyFileBytesA;
//    DVP_LoadBitmap                  = DVP_LoadBitmapA;
//    DVP_LoadBitmapStream            = DVP_LoadBitmapStreamA;
//    DVP_LoadText                    = DVP_LoadTextA;
//    DVP_ShowProperties              = DVP_ShowPropertiesA;
//    DVP_ShowPropertiesStream        = DVP_ShowPropertiesStreamA;
//    DVP_GetFileInfoFile             = DVP_GetFileInfoFileA;
//    DVP_GetFileInfoFileStream       = DVP_GetFileInfoFileStreamA;
//  {$ENDIF}

const
  {$if VIEWERPLUGINVERSION >= 4 }
    OPUSVIEWER_IMAGE_FRAME_SIZE = 14;
  {$ELSE}
    OPUSVIEWER_IMAGE_FRAME_SIZE = 08;
  {$endif}

  function IIF(AValue: Boolean; const ATrue: Integer; const AFalse: Integer = 0): Integer; overload; inline;
  function MusicRatingWindowsToMP3(iRating : integer): integer;
  function MusicRatingMP3ToWindows(iRating : integer): integer;
  function MusicRatingToStars(iRating : integer): integer;
  function MusicStarsToRating(iStars : integer):integer;

implementation

function IIF(AValue: Boolean; const ATrue: Integer; const AFalse: Integer): Integer;
begin
  if AValue then
    Result := ATrue
  else
    Result := AFalse;
end;

function MusicRatingWindowsToMP3(iRating : integer): integer;
begin
  Result := IIF(iRating = 0, 0, IIF(iRating = 1, 1, IIF(iRating <= 25, 64, IIF(iRating <= 50, 128, IIF(iRating <= 75, 192, 255)))));
end;


function MusicRatingMP3ToWindows(iRating : integer): integer;
begin
  Result := IIF(iRating = 0, 0, IIF(iRating < 32, 1, IIF(iRating < 96, 25,IIF(iRating < 160, 50, IIF(iRating < 224, 75, 99)))));
end;


function MusicRatingToStars(iRating : integer): integer;
begin
  Result := IIF(iRating <= 0, 0, IIF(iRating <= 12, 1, IIF(iRating <= 37, 2, IIF(iRating <= 62, 3, IIF( iRating <= 87, 4, 5)))));
end;


function MusicStarsToRating(iStars : integer):integer;
const  iRating: array of Integer = (0, 1, 25, 50, 75, 99);
begin
  Result := IIF(iStars >= High(iRating), 99, iRating[iStars]);
end;

end.