142 lines
4.8 KiB
JavaScript
Executable File
142 lines
4.8 KiB
JavaScript
Executable File
const mpris = await Service.import("mpris")
|
|
|
|
|
|
export default function Media() {
|
|
const track = Utils.watch("", mpris, "player-changed", () => {
|
|
if (mpris.players[0]) {
|
|
const { track_artists, track_title } = mpris.players[0]
|
|
return `${track_artists.join(", ")} -${track_title}`
|
|
} else {
|
|
return "Nothing is playing"
|
|
}
|
|
})
|
|
|
|
return Widget.EventBox({
|
|
class_name: "media",
|
|
on_primary_click: () => mpris.getPlayer("")?.playPause(),
|
|
on_scroll_up: () => mpris.getPlayer("")?.next(),
|
|
on_scroll_down: () => mpris.getPlayer("")?.previous(),
|
|
child: Widget.Icon({icon: 'emblem-music-symbolic'}),
|
|
})
|
|
}
|
|
|
|
function PlayerImg(player) {
|
|
return Widget.Box({
|
|
hpack: "start",
|
|
width_request: 80,
|
|
height_request: 80,
|
|
css: player.bind("track_cover_url").transform(p => `
|
|
background-image: url('${p || player.cover_path || '/home/nathan/Pictures/symbols/audio.png'}');
|
|
background-size: contain;
|
|
background-repeat: no-repeat;
|
|
background-position: center;
|
|
`),
|
|
})
|
|
|
|
}
|
|
|
|
|
|
function PlayerGUI(player) {
|
|
|
|
|
|
return Widget.Box({
|
|
class_name: "playerbox",
|
|
height_request: 200,
|
|
vexpand: false,
|
|
vertical: true,
|
|
children: [
|
|
Widget.Box({
|
|
vertical: false,
|
|
margin: 15,
|
|
hpack: "start",
|
|
spacing: 20,
|
|
children: [
|
|
PlayerImg(player),
|
|
Widget.Box({
|
|
vertical: true,
|
|
children: [
|
|
Widget.Label({
|
|
hpack: "start",
|
|
max_width_chars: 30,
|
|
truncate: "end",
|
|
label: player.bind('track-title').as(t => t)
|
|
}),
|
|
Widget.Label({
|
|
hpack: "start",
|
|
max_width_chars: 30,
|
|
truncate: "end",
|
|
label: player.bind("track_artists").transform(a => a.join(", ")),
|
|
wrap: true,
|
|
}),
|
|
Widget.Label({
|
|
hpack: "start",
|
|
max_width_chars: 30,
|
|
truncate: "end",
|
|
label: player.bind('track-album').as(t => t)
|
|
}),
|
|
]
|
|
})
|
|
],
|
|
|
|
}),
|
|
|
|
Widget.Slider({
|
|
class_name: "position",
|
|
draw_value: false,
|
|
on_change: ({ value }) => player.position = value * player.length,
|
|
visible: player.bind("length").as(l => l > 0),
|
|
setup: self => {
|
|
function update() {
|
|
const value = player.position / player.length
|
|
self.value = value > 0 ? value : 0
|
|
}
|
|
self.hook(player, update)
|
|
self.hook(player, update, "position")
|
|
self.poll(1000, update)
|
|
},
|
|
}),
|
|
|
|
Widget.Box({
|
|
vertical: false,
|
|
hpack: "center",
|
|
spacing: 20,
|
|
children: [
|
|
Widget.Button({
|
|
child: Widget.Icon({ icon: 'media-skip-backward-symbolic'}),
|
|
on_primary_click: () => player.previous()
|
|
}),
|
|
Widget.Button({
|
|
child: Widget.Icon({ icon: player.bind("play_back_status").transform(s => {
|
|
switch (s) {
|
|
case "Playing": return 'media-playback-pause-symbolic'
|
|
case "Paused":
|
|
case "Stopped": return 'media-playback-start-symbolic'
|
|
}
|
|
}),
|
|
}),
|
|
on_primary_click: () => player.playPause(),
|
|
}),
|
|
Widget.Button({
|
|
child: Widget.Icon({ icon: 'media-skip-forward-symbolic'}),
|
|
on_primary_click: () => player.next()
|
|
})
|
|
]
|
|
})
|
|
],
|
|
setup: self => {
|
|
|
|
},
|
|
})
|
|
}
|
|
|
|
export function Players() {
|
|
|
|
const plrs = mpris.bind('players')
|
|
.as(p => p.map((v) => PlayerGUI(v)))
|
|
|
|
return Widget.Box({
|
|
vertical: true,
|
|
children: plrs,
|
|
})
|
|
}
|