tauri-plugin-mpv-api
Version:
A Tauri plugin for embedding the mpv player in your app via JSON IPC.
303 lines (299 loc) • 8.86 kB
JavaScript
var core = require('@tauri-apps/api/core');
var window = require('@tauri-apps/api/window');
var event = require('@tauri-apps/api/event');
const COMMON_PROPERTIES = [
'playlist', // Playlist
'filename', // Current filename
'pause', // Pause state
'eof-reached', // End of file reached state
'time-pos', // Playback position (seconds)
'duration', // Total duration (seconds)
'volume', // Volume (0-100)
'mute', // Mute state
'speed', // Playback speed
];
const DEFAULT_MPV_CONFIG = {
args: [
'--vo=gpu-next',
'--hwdec=auto-safe',
'--keep-open=yes',
'--force-window',
],
observedProperties: COMMON_PROPERTIES,
ipcTimeoutMs: 2000,
showMpvOutput: false,
};
/**
* Initialize mpv player.
*
* @param {MpvConfig} [mpvConfig] - Initialization options.
* @param {string} [windowLabel] - The label of the target window. Defaults to the current window's label.
* @returns {Promise<string>} A promise that resolves with the actual window label used for initialization.
* @throws {Error} Throws an error if mpv initialization fails (e.g., mpv executable not in PATH).
*
* @example
* ```typescript
* import { init, destroy, MpvConfig } from 'tauri-plugin-mpv-api';
*
* // Properties to observe
* const OBSERVED_PROPERTIES = ['pause', 'time-pos', 'duration', 'filename'] as const;
*
* // mpv configuration
* const mpvConfig: MpvConfig = {
* args: [
* '--vo=gpu-next',
* '--hwdec=auto-safe',
* '--keep-open=yes',
* '--force-window',
* ],
* observedProperties: OBSERVED_PROPERTIES,
* };
*
* // Initialize mpv
* try {
* await init(mpvConfig);
* } catch (error) {
* console.error('Failed to initialize mpv:', error);
* }
*
* // Destroy mpv when no longer needed
* await destroy();
* ```
*/
async function init(mpvConfig, windowLabel) {
mpvConfig = {
...DEFAULT_MPV_CONFIG,
...mpvConfig,
};
windowLabel = windowLabel ?? window.getCurrentWindow().label;
return await core.invoke('plugin:mpv|init', {
mpvConfig,
windowLabel,
});
}
/**
* @deprecated Use `init()` instead. This function will be removed in a future version.
*/
const initializeMpv = init;
/**
* Destroy mpv player.
*
* @param {string} [windowLabel] - Target window label, defaults to current window
* @returns {Promise<void>} A promise that resolves when the operation completes.
*
* @example
* ```typescript
* import { destroy } from 'tauri-plugin-mpv-api';
*
* await destroy();
* ```
*/
async function destroy(windowLabel) {
windowLabel = windowLabel ?? window.getCurrentWindow().label;
return await core.invoke('plugin:mpv|destroy', {
windowLabel,
});
}
/**
* @deprecated Use `destroy()` instead. This function will be removed in a future version.
*/
const destroyMpv = destroy;
async function observeMpvProperties(arg1, arg2, arg3) {
let properties;
let callback;
let windowLabel;
if (typeof arg1 === 'function') {
properties = COMMON_PROPERTIES;
callback = arg1;
windowLabel = arg2;
}
else {
properties = arg1;
callback = arg2;
windowLabel = arg3;
}
return await listenMpvEvents((mpvEvent) => {
if (mpvEvent.event === 'property-change') {
if (properties.includes(mpvEvent.name)) {
callback(mpvEvent);
}
}
}, windowLabel);
}
/**
* Listen to all mpv events.
*
* @param {(event: MpvEvent) => void} callback - Function to call when mpv events are received
* @param {string} [windowLabel] - Target window label, defaults to current window
* @returns {Promise<UnlistenFn>} Function to call to stop listening
*
* @example
* ```typescript
* import { listenMpvEvents } from 'tauri-plugin-mpv-api';
*
* // Listen events
* const unlisten = await listenMpvEvents((mpvEvent) => {
* if (mpvEvent.event === 'property-change') {
* const { name, data } = mpvEvent
* switch (name) {
* case 'pause':
* console.log('Playback paused state:', data);
* break;
* case 'time-pos':
* console.log('Current time position:', data);
* break;
* case 'duration':
* console.log('Duration:', data);
* break;
* case 'filename':
* console.log('Current playing file:', data);
* break;
* }
* }
* });
*
* // Unlisten when no longer needed
* unlisten();
* ```
*/
async function listenMpvEvents(callback, windowLabel) {
windowLabel = windowLabel ?? window.getCurrentWindow().label;
const eventName = `mpv-event-${windowLabel}`;
return await event.listen(eventName, (event) => callback(event.payload));
}
async function command(arg1, arg2, arg3) {
let finalMpvCommand;
let finalWindowLabel;
let isShortcut = false;
if (typeof arg1 === 'string') {
isShortcut = true;
const name = arg1;
const args = Array.isArray(arg2) ? arg2 : [];
finalWindowLabel = Array.isArray(arg2) ? arg3 : arg2;
finalMpvCommand = {
command: [name, ...args],
};
}
else {
isShortcut = false;
finalMpvCommand = arg1;
finalWindowLabel = arg2;
}
finalWindowLabel = finalWindowLabel ?? window.getCurrentWindow().label;
const response = await core.invoke('plugin:mpv|command', {
mpvCommand: finalMpvCommand,
windowLabel: finalWindowLabel,
});
if (isShortcut) {
if (response.error !== 'success') {
throw new Error(`mpv command failed: ${response.error}`);
}
return response.data;
}
else {
return response;
}
}
/**
* @deprecated Use `command()` instead. This function will be removed in a future version.
*/
const sendMpvCommand = command;
/**
* Gets the value of an mpv property.
*
* @param name The name of the property to get.
* @param windowLabel (Optional) The label of the Tauri window to target.
* @returns A promise that resolves with the typed property value.
* @throws {Error} Throws an error if the command fails.
*
* @example
* ```typescript
* import { getProperty } from 'tauri-plugin-mpv-api';
*
* // Get volume
* const volume = await getProperty('volume');
*
* // `custom` is now treated as `string`
* const custom = await getProperty<string>('my-custom-property');
* ```
*/
async function getProperty(name, windowLabel) {
const value = await command('get_property', [name], windowLabel);
return value;
}
/**
* Sets the value of an mpv property.
*
* @param name The name of the property to set.
* @param value The value to set. Must match the property's type if it is known.
* @param windowLabel (Optional) The label of the Tauri window to target.
* @returns A promise that resolves when the property has been set.
* @throws {Error} Throws an error if the command fails.
*
* @example
* ```typescript
* import { setProperty } from 'tauri-plugin-mpv-api';
*
* // Set volume
* await setProperty('volume', 80);
*
* // Explicitly provide a type for a custom or unknown property
* await setProperty<string>('my-custom-property', 'some-value');
* ```
*/
async function setProperty(name, value, windowLabel) {
await command('set_property', [name, value], windowLabel);
}
/**
* Set video margin ratio
*
* @param {VideoMarginRatio} ratio - Margin ratio configuration object
* @param {string} [windowLabel] - Target window label, defaults to current window
* @returns {Promise<void>} Promise with no return value
* @throws {Error} Throws error when setting fails
*
* @example
* ```typescript
* import { setVideoMarginRatio } from 'tauri-plugin-mpv-api';
*
* // Leave 10% space at bottom for control bar
* await setVideoMarginRatio({ bottom: 0.1 });
*
* // Leave margins on all sides
* await setVideoMarginRatio({
* left: 0.05,
* right: 0.05,
* top: 0.1,
* bottom: 0.15,
* });
*
* // Reset margins (remove all margins)
* await setVideoMarginRatio({
* left: 0,
* right: 0,
* top: 0,
* bottom: 0,
* });
* ```
*/
async function setVideoMarginRatio(ratio, windowLabel) {
windowLabel = windowLabel ?? window.getCurrentWindow().label;
return await core.invoke('plugin:mpv|set_video_margin_ratio', {
ratio,
windowLabel,
});
}
exports.COMMON_PROPERTIES = COMMON_PROPERTIES;
exports.DEFAULT_MPV_CONFIG = DEFAULT_MPV_CONFIG;
exports.command = command;
exports.destroy = destroy;
exports.destroyMpv = destroyMpv;
exports.getProperty = getProperty;
exports.init = init;
exports.initializeMpv = initializeMpv;
exports.listenMpvEvents = listenMpvEvents;
exports.observeMpvProperties = observeMpvProperties;
exports.sendMpvCommand = sendMpvCommand;
exports.setProperty = setProperty;
exports.setVideoMarginRatio = setVideoMarginRatio;
;