============================================================================
  mh_PLAYer  -  BUNDLED PLUGINS, EXAMPLE PLUGIN  &  PLUGIN API OVERVIEW
  plugins folder   |   plugin API v1.1
============================================================================

ABOUT THIS FILE
----------------------------------------------------------------------------
  You are most likely reading this because you opened the mh_PLAYer plugins
  folder from  Plugins -> "Open Plugins Folder...".

  This folder is where mh_PLAYer loads plugins from. Nothing here needs
  installing - everything in it ships with mh_PLAYer and loads automatically
  at startup, appearing in the Plugins menu.

  Plugins require a licence with the Plugins feature (Studio Pro); the Plugins
  menu is locked on other tiers.


WHAT'S IN THIS FOLDER
----------------------------------------------------------------------------
  Six working plugins, plus a reference plugin to build your own from:

    Studio Watermark   Stamp a logo or title PNG onto a folder of rendered
                       frames - opacity, scale, 9-point position or tiled,
                       with a live preview. Originals are untouched.
    Field Recorder     Capture a live HDMI / USB device to disk - H.264
                       (MP4 / MOV) or ProRes 422, optional audio, preview
                       mirror. Uses the bundled FFmpeg.
    Contact Sheet      Labelled thumbnail grid from a folder of frames, or
                       scan a video for cuts to get one thumbnail per shot.
                       PNG, plus an optional multi-page PDF.
    Colour Palette     Dominant colours from an image, folder, or every shot
                       in a video, as labelled swatches with hex, RGB and
                       coverage. Exports TXT / JSON / CSS.
    Colour Theme       Movie-barcode image of a whole shot, sequence or
                       feature - one stripe per sampled frame, in AVERAGE
                       (flat colour) or SQUEEZE (keeps vertical structure)
                       style, with an optional title header. Outputs PNG.
    Test Patterns      SMPTE RP 219, SMPTE split-field, EBU 100% / 75% bars,
                       grey ramp and staircase. Any resolution, PNG / TIFF /
                       JPEG including 16-bit TIFF.

    example_plugin.py  Reference plugin - see the next section.

  Each plugin has its own README in this folder (README_Studio_Watermark.txt,
  README_Field_Recorder.txt, and so on) covering its settings, supported
  formats and troubleshooting in full.

  Studio Watermark needs a watermark PNG to stamp - it has no text generator.
  Two ready-to-use transparent samples ("WORK IN PROGRESS" and "(C)
  Copyright") come with the standalone Studio Watermark zip on the download
  page; see README_Studio_Watermark.txt.

  COPY, DON'T EDIT IN PLACE. This folder is refreshed when you re-extract the
  ZIP or run the installer, so changes made directly to a bundled plugin are
  lost on upgrade. Copy the file under a new name and edit that instead - your
  own plugins are never touched.

  DOWNLOADS / UPDATES. The bundled plugins are also published on their own
  page, so you can pick up a newer or corrected plugin without waiting for
  the next mh_PLAYer release - download the .py file and drop it in here:

      https://anti-matter-3d.com/mhplayer/


THE EXAMPLE PLUGIN  (example_plugin.py)
----------------------------------------------------------------------------
  A known-good plugin that exercises every part of the public  mh_player_api ,
  so you have a reliable starting point instead of guessing. Run it from
  Plugins -> "Example: Player Info...".

  It shows three things working together:
    - on_open_file     - react when a clip / image sequence is opened
    - on_frame_change  - react during playback (throttled; can fire ~60x/sec)
    - a menu item + dialog that reads LIVE player state, drives the playhead
      (Jump to In / Middle / Out), and writes a snapshot to the log

  Load a clip and play it: the dialog refreshes live, the Jump buttons move the
  playhead, and "Log snapshot" writes the current state to the log / console.
  To build your own, copy example_plugin.py and edit it.


WHAT THE PLUGIN API CAN DO
----------------------------------------------------------------------------
  Plugins are plain Python files (PySide6 available) that import one injected
  module:  import mh_player_api as api . Through it a plugin can:

    - add Plugins-menu items that open their own windows / dialogs
    - react to open-file, per-frame, and export-complete events
    - read live player state, and drive the playhead

  What this API version does NOT provide: hooks to modify displayed or exported
  pixels, draw onto the player canvas, or dock a panel into the player. These
  are observer / notification hooks, not display-pipeline hooks. (A plugin's own
  self-contained window can still do anything PySide6 / Python allows.)

  Attributes
    api.api_version             tuple, e.g. (1, 1)
    api.player_version          mh_PLAYer version string

  Hooks (register once at load)
    api.register_menu_item(label, callback)
    api.on_open_file(cb)          cb(path)
    api.on_frame_change(cb)       cb(idx, path)    throttle heavy work
    api.on_export_complete(cb)    cb(output_dir)   fires after a GUI export

  Queries (call FRESH each time - never cache results)
    api.get_current_frame()        -> int (index)
    api.get_current_frame_number() -> int (timeline number)
    api.get_sequence()             -> list[str]
    api.get_current_path()         -> str | None
    api.get_video_path()           -> str | None
    api.get_fps()                  -> float
    api.get_in_out()               -> (in, out)
    api.get_ev()                   -> float
    api.get_gamma()                -> float
    api.get_display_mode()         -> str
    api.get_proxy()                -> int
    api.get_playlist()             -> list[dict]
    api.get_edl()                  -> dict | None
    api.is_edl_active()            -> bool

  Actions
    api.goto_frame(index)
    api.play() / api.pause() / api.stop()
    api.open_file(path)
    api.log(message, level="info")      level: "info" | "warn" | "error"
    api.notify(message, timeout_ms=3000) status-bar / toast message


DEVELOPING YOUR OWN PLUGIN
----------------------------------------------------------------------------
  1. Put your  .py  file in THIS folder, alongside the bundled ones.
  2. Plugins -> "Reload Plugins"  (or restart mh_PLAYer).
  3. Files beginning with  _  or  .  are skipped - use them for shared helper
     modules you do NOT want loaded as plugins.
  4. Give your file its own name. A bundled plugin's name may be reused by a
     future release, which would overwrite your work.

  "Plugins -> About Plugin API..." shows this folder's path, the API version,
  and which plugins are currently loaded.

  Minimal skeleton:
    import mh_player_api as api

    def on_frame(idx, path):
        api.log(f"frame {idx}: {path}")

    api.on_frame_change(on_frame)
    api.register_menu_item("Hello", lambda: api.notify("Hi!"))

  Good-citizen rules (the example follows all of these):
    - mh_player_api is injected before plugins load, so the import always works.
    - Never cache query return values - call them fresh each time.
    - on_frame_change can fire ~60x/sec; throttle, and never block.
    - Use only the public api functions (no player internals), so your plugin
      keeps working across player updates within the same API major version.
    - Make registration reload-tolerant ("Reload Plugins" re-imports).
    - Guard the GUI import so the plugin still loads its hooks if the toolkit
      is unavailable.


----------------------------------------------------------------------------
  (C) 2026 Martin P. Heigan - anti-matter-3d.com
  Plugins:     https://anti-matter-3d.com/mhplayer/
  More tools:  https://anti-matter-3d.com/tools
============================================================================
