Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.idea/
*.iml
8 changes: 8 additions & 0 deletions player-ctl/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
commands: {
'player-ctl-play': require('./player-ctl-play'),
'player-ctl-pause': require('./player-ctl-pause'),
'player-ctl-next': require('./player-ctl-next'),
'player-ctl-previous': require('./player-ctl-previous'),
},
};
53 changes: 53 additions & 0 deletions player-ctl/manifest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: player-ctl
label: Player Controls
version: 1.0.0
author: Backslash

commands:
- name: player-ctl-play
label: Play media
isImmediate: true
bgColor: "#2563EB"
color: "#FFFFFF"
icon: play
keywords:
- player
- media
- play
- resume

- name: player-ctl-pause
label: Pause media
isImmediate: true
bgColor: "#2563EB"
color: "#FFFFFF"
icon: pause
keywords:
- player
- media
- pause
- stop

- name: player-ctl-next
label: Next media item
isImmediate: true
bgColor: "#2563EB"
color: "#FFFFFF"
icon: fast-forward
keywords:
- player
- media
- next
- skip

- name: player-ctl-previous
label: Previous media item
isImmediate: true
bgColor: "#2563EB"
color: "#FFFFFF"
icon: rewind
keywords:
- player
- media
- previous
- back
16 changes: 16 additions & 0 deletions player-ctl/player-ctl-next.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const { runPlayerctlCommand } = require("./utils");

const run = async (_, context) => {
const { search } = context;

const didRun = await runPlayerctlCommand(context, {
command: "playerctl next",
errorPrefix: "Failed to skip to the next item",
});

if (didRun) {
search?.clear?.();
}
};

module.exports = { run, actions: [] };
16 changes: 16 additions & 0 deletions player-ctl/player-ctl-pause.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const { runPlayerctlCommand } = require("./utils");

const run = async (_, context) => {
const { search } = context;

const didRun = await runPlayerctlCommand(context, {
command: "playerctl pause",
errorPrefix: "Failed to pause media playback",
});

if (didRun) {
search?.clear?.();
}
};

module.exports = { run, actions: [] };
16 changes: 16 additions & 0 deletions player-ctl/player-ctl-play.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const { runPlayerctlCommand } = require("./utils");

const run = async (_, context) => {
const { search } = context;

const didRun = await runPlayerctlCommand(context, {
command: "playerctl play",
errorPrefix: "Failed to start media playback",
});

if (didRun) {
search?.clear?.();
}
};

module.exports = { run, actions: [] };
16 changes: 16 additions & 0 deletions player-ctl/player-ctl-previous.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const { runPlayerctlCommand } = require("./utils");

const run = async (_, context) => {
const { search } = context;

const didRun = await runPlayerctlCommand(context, {
command: "playerctl previous",
errorPrefix: "Failed to go to the previous item",
});

if (didRun) {
search?.clear?.();
}
};

module.exports = { run, actions: [] };
62 changes: 62 additions & 0 deletions player-ctl/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
const execCommand = (exec, command) =>
new Promise((resolve, reject) => {
exec(command, (error, stdout, stderr) => {
if (error) {
const message = stderr?.trim() || error.message || "Unknown error";
return reject(new Error(message));
}
resolve(stdout);
});
});

const ensurePlayerctl = async ({ exec, toast }) => {
try {
await execCommand(exec, "command -v playerctl");
} catch {
const message =
"playerctl is required to control media. Install it with your package manager.";

if (toast?.error) {
toast.error("Missing dependency", { description: message });
}

throw new Error(message);
}
};

const handleNoPlayersFound = (toast) => {
if (toast?.error) {
toast.error("No media players running", {
description: "Start playback in your media player and try again.",
});
}
};

const runPlayerctlCommand = async (
context,
{ command, errorPrefix }
) => {
const { exec, toast } = context;

await ensurePlayerctl(context);

try {
await execCommand(exec, command);
return true;
} catch (error) {
const message = error?.message || "Unknown error";

if (message.toLowerCase().includes("no players found")) {
handleNoPlayersFound(toast);
return false;
}

throw new Error(`${errorPrefix}: ${message}`);
}
};

module.exports = {
execCommand,
ensurePlayerctl,
runPlayerctlCommand,
};