Skip to content

Commit

Permalink
add mpris widget example
Browse files Browse the repository at this point in the history
  • Loading branch information
Aylur committed Jan 7, 2024
1 parent 268c081 commit 19f823b
Show file tree
Hide file tree
Showing 3 changed files with 219 additions and 0 deletions.
157 changes: 157 additions & 0 deletions example/media-widget/Media.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import Mpris from 'resource:///com/github/Aylur/ags/service/mpris.js'
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
import Utils from 'resource:///com/github/Aylur/ags/utils.js'

const FALLBACK_ICON = 'audio-x-generic-symbolic';
const PLAY_ICON = 'media-playback-start-symbolic';
const PAUSE_ICON = 'media-playback-pause-symbolic';
const PREV_ICON = 'media-skip-backward-symbolic';
const NEXT_ICON = 'media-skip-forward-symbolic';

/** @param {number} length */
function lengthStr(length) {
const min = Math.floor(length / 60);
const sec = Math.floor(length % 60);
const sec0 = sec < 10 ? '0' : '';
return `${min}:${sec0}${sec}`;
}

/** @param {import('types/service/mpris').MprisPlayer} player */
const Player = player => {
const img = Widget.Box({
class_name: 'img',
vpack: 'start',
css: player.bind('cover_path').transform(p => `
background-image: url('${p}');
`),
});

const title = Widget.Label({
class_name: 'title',
wrap: true,
hpack: 'start',
label: player.bind('track_title'),
});

const artist = Widget.Label({
class_name: 'artist',
wrap: true,
hpack: 'start',
label: player.bind('track_artists').transform(a => a.join(', ')),
});

const positionSlider = Widget.Slider({
class_name: 'position',
draw_value: false,
on_change: ({ value }) => player.position = value * player.length,
setup: self => {
const update = () => {
self.visible = player.length > 0;
self.value = player.position / player.length;
};
self.hook(player, update);
self.hook(player, update, 'position');
self.poll(1000, update);
},
});

const positionLabel = Widget.Label({
class_name: 'position',
hpack: 'start',
setup: self => {
const update = (_, time) => {
self.label = lengthStr(time || player.position)
self.visible = player.length > 0;
};

self.hook(player, update, 'position');
self.poll(1000, update);
},
});

const lengthLabel = Widget.Label({
class_name: 'length',
hpack: 'end',
visible: player.bind('length').transform(l => l > 0),
label: player.bind('length').transform(lengthStr),
});

const icon = Widget.Icon({
class_name: 'icon',
hexpand: true,
hpack: 'end',
vpack: 'start',
tooltip_text: player.identity || '',
icon: player.bind('entry').transform(entry => {
const name = `${entry}-symbolic`;
return Utils.lookUpIcon(name) ? name : FALLBACK_ICON;
}),
});

const playPause = Widget.Button({
class_name: 'play-pause',
on_clicked: () => player.playPause(),
visible: player.bind('can_play'),
child: Widget.Icon({
icon: player.bind('play_back_status').transform(s => {
switch (s) {
case 'Playing': return PAUSE_ICON;
case 'Paused':
case 'Stopped': return PLAY_ICON;
}
}),
}),
});

const prev = Widget.Button({
on_clicked: () => player.previous(),
visible: player.bind('can_go_prev'),
child: Widget.Icon(PREV_ICON),
});

const next = Widget.Button({
on_clicked: () => player.next(),
visible: player.bind('can_go_next'),
child: Widget.Icon(NEXT_ICON),
});

return Widget.Box({
class_name: 'player',
children: [
img,
Widget.Box({
vertical: true,
hexpand: true,
children: [
Widget.Box({
children: [
title,
icon,
],
}),
artist,
Widget.Box({ vexpand: true }),
positionSlider,
Widget.CenterBox({
start_widget: positionLabel,
center_widget: Widget.Box({
children: [
prev,
playPause,
next,
],
}),
end_widget: lengthLabel,
}),
],
}),
],
});
}

export default () => Widget.Box({
vertical: true,
css: 'padding: 1px', // small hack to make sure it is visible
visible: Mpris.bind('players').transform(p => p.length > 0),
children: Mpris.bind('players').transform(p => p.map(Player)),
});
13 changes: 13 additions & 0 deletions example/media-widget/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import App from 'resource:///com/github/Aylur/ags/app.js';
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
import Media from './Media.js';

const win = Widget.Window({
name: 'mpris',
child: Media(),
});

export default {
style: App.configDir + '/style.css',
windows: [win],
};
49 changes: 49 additions & 0 deletions example/media-widget/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
.player {
padding: 10px;
min-width: 350px;
}

.player .img {
min-width: 100px;
min-height: 100px;
background-size: cover;
background-position: center;
border-radius: 13px;
margin-right: 1em;
}

.player .title {
font-size: 1.2em;
}

.player .artist {
font-size: 1.1em;
color: @insensitive_fg_color;
}

.player scale.position {
padding: 0;
margin-bottom: .3em;
}

.player scale.position trough {
min-height: 8px;
}

.player scale.position highlight {
background-color: @theme_fg_color;
}

.player scale.position slider {
all: unset;
}

.player button {
min-height: 1em;
min-width: 1em;
padding: .3em;
}

.player button.play-pause {
margin: 0 .3em;
}

0 comments on commit 19f823b

Please sign in to comment.