From 51514347ef3bc1d7a6f37e798a43111b2f2fc9e0 Mon Sep 17 00:00:00 2001
From: Aylur <k.demeter@protonmail.com>
Date: Thu, 7 Nov 2024 01:45:07 +0000
Subject: example: media player

---
 examples/js/media-player/widget/MediaPlayer.tsx | 94 +++++++++++++++++++++++++
 1 file changed, 94 insertions(+)
 create mode 100644 examples/js/media-player/widget/MediaPlayer.tsx

(limited to 'examples/js/media-player/widget/MediaPlayer.tsx')

diff --git a/examples/js/media-player/widget/MediaPlayer.tsx b/examples/js/media-player/widget/MediaPlayer.tsx
new file mode 100644
index 0000000..06c7e77
--- /dev/null
+++ b/examples/js/media-player/widget/MediaPlayer.tsx
@@ -0,0 +1,94 @@
+import { Astal, Gtk } from "astal/gtk3"
+import Mpris from "gi://AstalMpris"
+import { bind } from "astal"
+
+function lengthStr(length: number) {
+    const min = Math.floor(length / 60)
+    const sec = Math.floor(length % 60)
+    const sec0 = sec < 10 ? "0" : ""
+    return `${min}:${sec0}${sec}`
+}
+
+
+function MediaPlayer({ player }: { player: Mpris.Player }) {
+    const { START, END } = Gtk.Align
+
+    const title = bind(player, "title").as(t =>
+        t || "Unknown Track")
+
+    const artist = bind(player, "artist").as(a =>
+        a || "Unknown Artist")
+
+    const coverArt = bind(player, "coverArt").as(c =>
+        `background-image: url('${c}')`)
+
+    const playerIcon = bind(player, "entry").as(e =>
+        Astal.Icon.lookup_icon(e) ? e : "audio-x-generic-symbolic")
+
+    const position = bind(player, "position").as(p => player.length > 0
+        ? p / player.length : 0)
+
+    const playIcon = bind(player, "playbackStatus").as(s =>
+        s === Mpris.PlaybackStatus.PLAYING
+            ? "media-playback-pause-symbolic"
+            : "media-playback-start-symbolic"
+    )
+
+    return <box className="MediaPlayer">
+        <box className="cover-art" css={coverArt} />
+        <box vertical>
+            <box className="title">
+                <label truncate hexpand halign={START} label={title} />
+                <icon icon={playerIcon} />
+            </box>
+            <label halign={START} valign={START} vexpand wrap label={artist} />
+            <slider
+                visible={bind(player, "length").as(l => l > 0)}
+                onDragged={({ value }) => player.position = value * player.length}
+                value={position}
+            />
+            <centerbox className="actions">
+                <label
+                    hexpand
+                    className="position"
+                    halign={START}
+                    visible={bind(player, "length").as(l => l > 0)}
+                    label={bind(player, "position").as(lengthStr)}
+                />
+                <box>
+                    <button
+                        onClicked={() => player.previous()}
+                        visible={bind(player, "canGoPrevious")}>
+                        <icon icon="media-skip-backward-symbolic" />
+                    </button>
+                    <button
+                        onClicked={() => player.play_pause()}
+                        visible={bind(player, "canControl")}>
+                        <icon icon={playIcon} />
+                    </button>
+                    <button
+                        onClicked={() => player.next()}
+                        visible={bind(player, "canGoNext")}>
+                        <icon icon="media-skip-forward-symbolic" />
+                    </button>
+                </box>
+                <label
+                    className="length"
+                    hexpand
+                    halign={END}
+                    visible={bind(player, "length").as(l => l > 0)}
+                    label={bind(player, "length").as(l => l > 0 ? lengthStr(l) : "0:00")}
+                />
+            </centerbox>
+        </box>
+    </box>
+}
+
+export default function MprisPlayers() {
+    const mpris = Mpris.get_default()
+    return <box vertical>
+        {bind(mpris, "players").as(arr => arr.map(player => (
+            <MediaPlayer player={player} />
+        )))}
+    </box>
+}
-- 
cgit v1.2.3

