Skip to content

Commit

Permalink
example: media player
Browse files Browse the repository at this point in the history
  • Loading branch information
Aylur committed Nov 7, 2024
1 parent 5074a76 commit 5151434
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 0 deletions.
2 changes: 2 additions & 0 deletions docs/guide/getting-started/supported-languages.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ Examples:
- [Notification Popups](https://github.com/Aylur/astal/tree/main/examples/js/notifications)
![notification-popups](https://github.com/user-attachments/assets/0df0eddc-5c74-4af0-a694-48dc8ec6bb44)

- [Media Player](https://github.com/Aylur/astal/tree/main/examples/js/media-player)
![media-player](https://github.com/user-attachments/assets/891e9706-74db-4505-bd83-c3628d7b4fd0)

## Lua

Expand Down
2 changes: 2 additions & 0 deletions examples/js/media-player/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@girs/
node_modules/
5 changes: 5 additions & 0 deletions examples/js/media-player/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Media Player

![mpris](https://github.com/user-attachments/assets/891e9706-74db-4505-bd83-c3628d7b4fd0)

Using [Mpris](https://aylur.github.io/astal/guide/libraries/mpris).
11 changes: 11 additions & 0 deletions examples/js/media-player/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { App, Widget } from "astal/gtk3"
import style from "./style.scss"
import MprisPlayers from "./widget/MediaPlayer"

App.start({
instanceName: "players",
css: style,
main: () => {
new Widget.Window({}, MprisPlayers())
}
})
1 change: 1 addition & 0 deletions examples/js/media-player/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@use "./widget/MediaPlayer.scss";
56 changes: 56 additions & 0 deletions examples/js/media-player/widget/MediaPlayer.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gtk/theme/Adwaita/_colors-public.scss
$fg-color: #{"@theme_fg_color"};
$bg-color: #{"@theme_bg_color"};

window {
all: unset;
}

box.MediaPlayer {
padding: .6rem;
background-color: $bg-color;

box.cover-art {
min-width: 120px;
min-height: 120px;
border-radius: 9px;
margin-right: .6rem;
background-size: contain;
background-position: center;
}

box.title {
label {
font-weight: bold;
font-size: 1.1em;
}
}

scale {
padding: 0;
margin: .4rem 0;

trough {
min-height: 8px;
}

highlight {
background-color: $fg-color;
}

slider {
all: unset;
}
}

centerbox.actions {
min-width: 220px;

button {
min-width: 0;
min-height: 0;
padding: .4rem;
margin: 0 .2rem;
}
}
}
94 changes: 94 additions & 0 deletions examples/js/media-player/widget/MediaPlayer.tsx
Original file line number Diff line number Diff line change
@@ -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>
}

0 comments on commit 5151434

Please sign in to comment.