2024-01-30 11:29:07 -05:00
|
|
|
const Mpris = await Service.import('mpris');
|
2024-01-13 11:15:08 -05:00
|
|
|
|
2024-01-30 11:29:07 -05:00
|
|
|
const { Box, CenterBox } = Widget;
|
2024-01-13 11:15:08 -05:00
|
|
|
|
2024-01-13 23:38:31 -05:00
|
|
|
import * as mpris from './mpris.ts';
|
|
|
|
import PlayerGesture from './gesture.ts';
|
|
|
|
import Separator from '../misc/separator.ts';
|
2024-01-13 11:15:08 -05:00
|
|
|
|
|
|
|
const FAVE_PLAYER = 'org.mpris.MediaPlayer2.spotify';
|
|
|
|
const SPACING = 8;
|
|
|
|
|
|
|
|
// Types
|
2024-01-13 23:38:31 -05:00
|
|
|
import { MprisPlayer } from 'types/service/mpris.ts';
|
2024-01-13 11:15:08 -05:00
|
|
|
import { Variable as Var } from 'types/variable';
|
2024-01-29 18:54:07 -05:00
|
|
|
import { Colors, PlayerBox, PlayerOverlay } from 'global-types';
|
2024-01-13 11:15:08 -05:00
|
|
|
|
|
|
|
|
|
|
|
const Top = (
|
|
|
|
player: MprisPlayer,
|
2024-01-29 18:54:07 -05:00
|
|
|
overlay: PlayerOverlay,
|
2024-01-13 11:15:08 -05:00
|
|
|
) => Box({
|
|
|
|
class_name: 'top',
|
|
|
|
hpack: 'start',
|
|
|
|
vpack: 'start',
|
|
|
|
|
|
|
|
children: [
|
|
|
|
mpris.PlayerIcon(player, overlay),
|
|
|
|
],
|
|
|
|
});
|
|
|
|
|
|
|
|
const Center = (
|
|
|
|
player: MprisPlayer,
|
2024-01-29 18:54:07 -05:00
|
|
|
colors: Var<Colors>,
|
2024-01-13 11:15:08 -05:00
|
|
|
) => Box({
|
|
|
|
class_name: 'center',
|
|
|
|
|
|
|
|
children: [
|
|
|
|
CenterBox({
|
|
|
|
vertical: true,
|
|
|
|
|
2024-01-14 20:52:30 -05:00
|
|
|
start_widget: Box({
|
|
|
|
class_name: 'metadata',
|
|
|
|
vertical: true,
|
|
|
|
hpack: 'start',
|
|
|
|
vpack: 'center',
|
|
|
|
hexpand: true,
|
|
|
|
|
|
|
|
children: [
|
|
|
|
mpris.TitleLabel(player),
|
|
|
|
mpris.ArtistLabel(player),
|
|
|
|
],
|
|
|
|
}),
|
2024-01-13 11:15:08 -05:00
|
|
|
}),
|
|
|
|
|
|
|
|
CenterBox({
|
|
|
|
vertical: true,
|
|
|
|
|
2024-01-14 20:52:30 -05:00
|
|
|
center_widget: mpris.PlayPauseButton(player, colors),
|
2024-01-13 11:15:08 -05:00
|
|
|
}),
|
|
|
|
|
|
|
|
],
|
|
|
|
});
|
|
|
|
|
|
|
|
const Bottom = (
|
|
|
|
player: MprisPlayer,
|
2024-01-29 18:54:07 -05:00
|
|
|
colors: Var<Colors>,
|
2024-01-13 11:15:08 -05:00
|
|
|
) => Box({
|
|
|
|
class_name: 'bottom',
|
|
|
|
|
|
|
|
children: [
|
|
|
|
mpris.PreviousButton(player, colors),
|
|
|
|
Separator(SPACING),
|
|
|
|
|
|
|
|
mpris.PositionSlider(player, colors),
|
|
|
|
Separator(SPACING),
|
|
|
|
|
|
|
|
mpris.NextButton(player, colors),
|
|
|
|
Separator(SPACING),
|
|
|
|
|
|
|
|
mpris.ShuffleButton(player, colors),
|
|
|
|
Separator(SPACING),
|
|
|
|
|
|
|
|
mpris.LoopButton(player, colors),
|
|
|
|
],
|
|
|
|
});
|
|
|
|
|
|
|
|
const PlayerBox = (
|
|
|
|
player: MprisPlayer,
|
2024-01-29 18:54:07 -05:00
|
|
|
colors: Var<Colors>,
|
|
|
|
overlay: PlayerOverlay,
|
2024-01-13 11:15:08 -05:00
|
|
|
) => {
|
|
|
|
const widget = mpris.CoverArt(player, colors, {
|
|
|
|
class_name: `player ${player.name}`,
|
|
|
|
hexpand: true,
|
|
|
|
|
|
|
|
start_widget: Top(player, overlay),
|
|
|
|
center_widget: Center(player, colors),
|
|
|
|
end_widget: Bottom(player, colors),
|
|
|
|
});
|
|
|
|
|
|
|
|
widget.visible = false;
|
|
|
|
|
|
|
|
return widget;
|
|
|
|
};
|
|
|
|
|
|
|
|
export default () => {
|
|
|
|
const content = PlayerGesture({
|
2024-01-29 18:54:07 -05:00
|
|
|
setup: (self: PlayerOverlay) => {
|
2024-01-13 11:15:08 -05:00
|
|
|
self
|
2024-01-29 18:54:07 -05:00
|
|
|
.hook(Mpris, (_, bus_name) => {
|
2024-01-13 11:15:08 -05:00
|
|
|
const players = self.attribute.players;
|
|
|
|
|
|
|
|
if (players.has(bus_name)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sometimes the signal doesn't give the bus_name
|
|
|
|
if (!bus_name) {
|
|
|
|
const player = Mpris.players.find((p) => {
|
|
|
|
return !players.has(p.bus_name);
|
|
|
|
});
|
|
|
|
|
|
|
|
if (player) {
|
|
|
|
bus_name = player.bus_name;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the one on top so we can move it up later
|
2024-01-29 18:54:07 -05:00
|
|
|
const previousFirst = self.overlays.at(-1) as PlayerBox;
|
2024-01-13 11:15:08 -05:00
|
|
|
|
|
|
|
// Make the new player
|
|
|
|
const player = Mpris.getPlayer(bus_name);
|
2024-01-29 18:54:07 -05:00
|
|
|
const colorsVar = Variable({
|
|
|
|
imageAccent: '#6b4fa2',
|
|
|
|
buttonAccent: '#ecdcff',
|
|
|
|
buttonText: '#25005a',
|
|
|
|
hoverAccent: '#d4baff',
|
|
|
|
});
|
2024-01-13 11:15:08 -05:00
|
|
|
|
|
|
|
if (!player) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
players.set(
|
|
|
|
bus_name,
|
2024-01-29 18:54:07 -05:00
|
|
|
PlayerBox(player, colorsVar, self),
|
2024-01-13 11:15:08 -05:00
|
|
|
);
|
|
|
|
self.overlays = Array.from(players.values())
|
2024-01-29 18:54:07 -05:00
|
|
|
.map((widget) => widget) as PlayerBox[];
|
2024-01-13 11:15:08 -05:00
|
|
|
|
|
|
|
const includes = self.attribute
|
|
|
|
.includesWidget(previousFirst);
|
|
|
|
|
2024-01-29 18:54:07 -05:00
|
|
|
// Select favorite player at startup
|
2024-01-13 11:15:08 -05:00
|
|
|
const attrs = self.attribute;
|
|
|
|
|
|
|
|
if (!attrs.setup && players.has(FAVE_PLAYER)) {
|
|
|
|
attrs.moveToTop(players.get(FAVE_PLAYER));
|
|
|
|
attrs.setup = true;
|
|
|
|
}
|
|
|
|
|
2024-01-29 18:54:07 -05:00
|
|
|
// Move previousFirst on top again
|
2024-01-13 11:15:08 -05:00
|
|
|
else if (includes) {
|
|
|
|
attrs.moveToTop(previousFirst);
|
|
|
|
}
|
|
|
|
}, 'player-added')
|
|
|
|
|
2024-01-29 18:54:07 -05:00
|
|
|
.hook(Mpris, (_, bus_name) => {
|
2024-01-13 11:15:08 -05:00
|
|
|
const players = self.attribute.players;
|
|
|
|
|
|
|
|
if (!bus_name || !players.has(bus_name)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-01-29 18:54:07 -05:00
|
|
|
// Get the one on top so we can move it up later
|
|
|
|
const previousFirst = self.overlays.at(-1) as PlayerBox;
|
2024-01-13 11:15:08 -05:00
|
|
|
|
2024-01-29 18:54:07 -05:00
|
|
|
// Remake overlays without deleted one
|
2024-01-13 11:15:08 -05:00
|
|
|
players.delete(bus_name);
|
|
|
|
self.overlays = Array.from(players.values())
|
2024-01-29 18:54:07 -05:00
|
|
|
.map((widget) => widget) as PlayerBox[];
|
2024-01-13 11:15:08 -05:00
|
|
|
|
2024-01-29 18:54:07 -05:00
|
|
|
// Move previousFirst on top again
|
2024-01-13 11:15:08 -05:00
|
|
|
const includes = self.attribute
|
|
|
|
.includesWidget(previousFirst);
|
|
|
|
|
|
|
|
if (includes) {
|
|
|
|
self.attribute.moveToTop(previousFirst);
|
|
|
|
}
|
|
|
|
}, 'player-closed');
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
return Box({
|
|
|
|
class_name: 'media',
|
|
|
|
child: content,
|
|
|
|
});
|
|
|
|
};
|