Compare commits
3 commits
0e4c0f4ba5
...
393b7970c3
Author | SHA1 | Date | |
---|---|---|---|
393b7970c3 | |||
f93a3cef4d | |||
cca7f91303 |
4 changed files with 182 additions and 108 deletions
8
.gitignore
vendored
8
.gitignore
vendored
|
@ -2,4 +2,10 @@ bin/
|
||||||
obj/
|
obj/
|
||||||
/packages/
|
/packages/
|
||||||
riderModule.iml
|
riderModule.iml
|
||||||
/_ReSharper.Caches/
|
/_ReSharper.Caches/
|
||||||
|
|
||||||
|
# AUR
|
||||||
|
deltatune-wls/
|
||||||
|
pkg/
|
||||||
|
src/
|
||||||
|
*.pkg.tar.zst
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="GirCore.Gtk-4.0" Version="0.6.3" />
|
<PackageReference Include="GirCore.Gtk-4.0" Version="0.6.3" />
|
||||||
|
<PackageReference Include="System.CommandLine" Version="2.0.0-beta7.25380.108" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -1,130 +1,152 @@
|
||||||
using Gdk;
|
using System.CommandLine;
|
||||||
|
using Gdk;
|
||||||
using Gio;
|
using Gio;
|
||||||
using GLib;
|
using GLib;
|
||||||
using Gtk;
|
using Gtk;
|
||||||
using Pango;
|
using Pango;
|
||||||
using ZwlrLayerShell;
|
using ZwlrLayerShell;
|
||||||
using Application = Gtk.Application;
|
using Application = Gtk.Application;
|
||||||
using TimeSpan = System.TimeSpan;
|
|
||||||
using Variant = GLib.Variant;
|
using Variant = GLib.Variant;
|
||||||
|
|
||||||
if (!LayerShell.IsSupported())
|
var overlayLayer = new Option<bool>("--overlay", "-o")
|
||||||
|
{ Description = "Use the overlay layer instead of the top layer." };
|
||||||
|
var horizontalMargin = new Option<uint>("--hmargin", "-H")
|
||||||
|
{ Description = "Horizontal margin from screen edge in pixels.", DefaultValueFactory = parseResult => 55 };
|
||||||
|
var verticalMargin = new Option<uint>("--vmargin", "-V")
|
||||||
|
{ Description = "Vertical margin from screen edge in pixels.", DefaultValueFactory = parseResult => 15 };
|
||||||
|
|
||||||
|
var root = new RootCommand("Displays your current song like in Deltarune Chapter 1.")
|
||||||
|
{ Options = { overlayLayer, horizontalMargin, verticalMargin } };
|
||||||
|
|
||||||
|
root.SetAction(RunApplication);
|
||||||
|
|
||||||
|
var rootParsed = root.Parse(args);
|
||||||
|
|
||||||
|
return rootParsed.Invoke();
|
||||||
|
|
||||||
|
void RunApplication(ParseResult parseResult)
|
||||||
{
|
{
|
||||||
Console.WriteLine("You must be running on a Wayland compositor that supports zwlr_layer_shell_v1");
|
if (!LayerShell.IsSupported())
|
||||||
return 255;
|
|
||||||
}
|
|
||||||
|
|
||||||
ApplicationWindow? window = null;
|
|
||||||
|
|
||||||
var application = Application.New("gay.pancakes.deltatune_wls", Gio.ApplicationFlags.FlagsNone);
|
|
||||||
|
|
||||||
GLib.Functions.TimeoutAdd(GLib.Constants.PRIORITY_DEFAULT, 500, () =>
|
|
||||||
{
|
|
||||||
if (window == null) return true;
|
|
||||||
|
|
||||||
var playerctl = Subprocess.New(["playerctl", "metadata", "--format", "{{ title }}"],
|
|
||||||
SubprocessFlags.StdoutPipe | SubprocessFlags.StderrSilence);
|
|
||||||
|
|
||||||
var pipe = playerctl.GetStdoutPipe();
|
|
||||||
if (pipe == null) return true;
|
|
||||||
|
|
||||||
var stdout = DataInputStream.New(pipe);
|
|
||||||
var line = stdout.ReadLineUtf8(out UIntPtr length, null);
|
|
||||||
|
|
||||||
window.ActivateAction("new_song", Variant.NewString(line?.Trim() ?? ""));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
application.OnActivate += (sender, eventArgs) =>
|
|
||||||
{
|
|
||||||
window = ApplicationWindow.New((Application)sender);
|
|
||||||
|
|
||||||
LayerShell.InitForWindow(window);
|
|
||||||
LayerShell.SetNamespace(window, "deltatune-wls");
|
|
||||||
LayerShell.SetLayer(window, Layer.Top);
|
|
||||||
LayerShell.SetAnchor(window, Edge.Left, true);
|
|
||||||
LayerShell.SetAnchor(window, Edge.Right, true);
|
|
||||||
LayerShell.SetAnchor(window, Edge.Top, true);
|
|
||||||
LayerShell.SetMargin(window, 15);
|
|
||||||
LayerShell.SetMargin(window, Edge.Left, 55);
|
|
||||||
|
|
||||||
var label = Label.New(null);
|
|
||||||
label.Halign = Align.Start;
|
|
||||||
label.Ellipsize = EllipsizeMode.End;
|
|
||||||
|
|
||||||
window.SetChild(label);
|
|
||||||
|
|
||||||
window.OnDestroy += (widget, args1) => application.Quit();
|
|
||||||
|
|
||||||
var action = SimpleAction.NewStateful("new_song", VariantType.String, Variant.NewString(""));
|
|
||||||
action.OnActivate += (simpleAction, signalArgs) =>
|
|
||||||
{
|
{
|
||||||
var title = simpleAction.GetState()!.GetString(out _);
|
Console.WriteLine("You must be running on a Wayland compositor that supports zwlr_layer_shell_v1");
|
||||||
var newTitle = signalArgs.Parameter!.GetString(out _);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (newTitle != title)
|
ApplicationWindow? window = null;
|
||||||
|
|
||||||
|
var application = Application.New("gay.pancakes.deltatune_wls", Gio.ApplicationFlags.FlagsNone);
|
||||||
|
|
||||||
|
GLib.Functions.TimeoutAdd(GLib.Constants.PRIORITY_DEFAULT, 500, () =>
|
||||||
|
{
|
||||||
|
if (window == null) return true;
|
||||||
|
|
||||||
|
var playerctl = Subprocess.New(["playerctl", "metadata", "--format", "{{ title }}"],
|
||||||
|
SubprocessFlags.StdoutPipe | SubprocessFlags.StderrSilence);
|
||||||
|
|
||||||
|
var pipe = playerctl.GetStdoutPipe();
|
||||||
|
if (pipe == null) return true;
|
||||||
|
|
||||||
|
var stdout = DataInputStream.New(pipe);
|
||||||
|
var line = stdout.ReadLineUtf8(out UIntPtr length, null);
|
||||||
|
|
||||||
|
window.ActivateAction("new_song", Variant.NewString(line?.Trim() ?? ""));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
application.OnActivate += (sender, eventArgs) =>
|
||||||
|
{
|
||||||
|
window = ApplicationWindow.New((Application)sender);
|
||||||
|
|
||||||
|
LayerShell.InitForWindow(window);
|
||||||
|
LayerShell.SetNamespace(window, "deltatune-wls");
|
||||||
|
LayerShell.SetLayer(window, parseResult.GetValue(overlayLayer) ? Layer.Overlay : Layer.Top);
|
||||||
|
LayerShell.SetAnchor(window, Edge.Left, true);
|
||||||
|
LayerShell.SetAnchor(window, Edge.Right, true);
|
||||||
|
LayerShell.SetAnchor(window, Edge.Top, true);
|
||||||
|
LayerShell.SetMargin(window, Edge.Left, (int)parseResult.GetValue(horizontalMargin));
|
||||||
|
LayerShell.SetMargin(window, Edge.Right, (int)parseResult.GetValue(horizontalMargin));
|
||||||
|
LayerShell.SetMargin(window, Edge.Top, (int)parseResult.GetValue(verticalMargin));
|
||||||
|
LayerShell.SetMargin(window, Edge.Bottom, (int)parseResult.GetValue(verticalMargin));
|
||||||
|
|
||||||
|
var label = Label.New(null);
|
||||||
|
label.Halign = Align.Start;
|
||||||
|
label.Ellipsize = EllipsizeMode.End;
|
||||||
|
|
||||||
|
window.SetChild(label);
|
||||||
|
|
||||||
|
window.OnDestroy += (widget, args1) => application.Quit();
|
||||||
|
|
||||||
|
var action = SimpleAction.NewStateful("new_song", VariantType.String, Variant.NewString(""));
|
||||||
|
action.OnActivate += (simpleAction, signalArgs) =>
|
||||||
{
|
{
|
||||||
simpleAction.SetState(signalArgs.Parameter);
|
var title = simpleAction.GetState()!.GetString(out _);
|
||||||
label.SetLabel($"♪ ~ {newTitle}");
|
var newTitle = signalArgs.Parameter!.GetString(out _);
|
||||||
if (!label.HasCssClass("fade-in"))
|
|
||||||
|
if (newTitle != title)
|
||||||
{
|
{
|
||||||
label.AddCssClass("fade-in");
|
simpleAction.SetState(signalArgs.Parameter);
|
||||||
GLib.Functions.TimeoutAddSeconds(GLib.Constants.PRIORITY_DEFAULT, 9, () => {
|
label.SetLabel($"♪ ~ {newTitle}");
|
||||||
label.RemoveCssClass("fade-in");
|
if (!label.HasCssClass("fade-in"))
|
||||||
return false;
|
{
|
||||||
});
|
label.AddCssClass("fade-in");
|
||||||
|
GLib.Functions.TimeoutAddSeconds(GLib.Constants.PRIORITY_DEFAULT, 9, () =>
|
||||||
|
{
|
||||||
|
label.RemoveCssClass("fade-in");
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
window.AddAction(action);
|
||||||
|
|
||||||
|
window.Present();
|
||||||
};
|
};
|
||||||
window.AddAction(action);
|
|
||||||
|
|
||||||
window.Present();
|
var css = CssProvider.New();
|
||||||
};
|
css.LoadFromString("""
|
||||||
|
window {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
var css = CssProvider.New();
|
window label {
|
||||||
css.LoadFromString("""
|
font-size: x-large;
|
||||||
window {
|
color: white;
|
||||||
background-color: transparent;
|
text-shadow: -1px -1px 0 #15249a, 1px -1px 0 #15249a, -1px 1px 0 #15249a, 1px 1px 0 #15249a;;
|
||||||
}
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
window label {
|
.fade-in {
|
||||||
font-size: x-large;
|
animation: 8s fade-in ease-in-out both;
|
||||||
color: white;
|
}
|
||||||
text-shadow: -1px -1px 0 #15249a, 1px -1px 0 #15249a, -1px 1px 0 #15249a, 1px 1px 0 #15249a;;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fade-in {
|
@keyframes fade-in {
|
||||||
animation: 8s fade-in ease-in-out both;
|
0% {
|
||||||
}
|
transform: translateX(80px);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes fade-in {
|
5% {
|
||||||
0% {
|
transform: translateX(50px);
|
||||||
transform: translateX(80px);
|
opacity: 1;
|
||||||
opacity: 0;
|
}
|
||||||
}
|
|
||||||
|
80% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
5% {
|
85% {
|
||||||
transform: translateX(50px);
|
transform: translateX(50px);
|
||||||
opacity: 1;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
80% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
85% {
|
100% {
|
||||||
transform: translateX(50px);
|
transform: translateX(0);
|
||||||
}
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
StyleContext.AddProviderForDisplay(Display.GetDefault()!, css,
|
||||||
|
Gtk.Constants.STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||||
|
|
||||||
100% {
|
application.RunWithSynchronizationContext(null);
|
||||||
transform: translateX(0);
|
}
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
""");
|
|
||||||
StyleContext.AddProviderForDisplay(Display.GetDefault()!, css,
|
|
||||||
Gtk.Constants.STYLE_PROVIDER_PRIORITY_APPLICATION);
|
|
||||||
|
|
||||||
return application.RunWithSynchronizationContext(null);
|
|
45
PKGBUILD
Normal file
45
PKGBUILD
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
# Maintainer: Your Name <youremail@domain.com>
|
||||||
|
pkgname=deltatune-wls-git
|
||||||
|
pkgver=r7.0e4c0f4
|
||||||
|
pkgrel=1
|
||||||
|
pkgdesc="A Linux and Wayland port of DeltaTune based on layer shell"
|
||||||
|
arch=("x86_64")
|
||||||
|
url="https://git.meow.company/pancakes/DeltatuneWls"
|
||||||
|
license=("unknown")
|
||||||
|
groups=()
|
||||||
|
depends=("dotnet-runtime" "gtk4-layer-shell")
|
||||||
|
makedepends=("dotnet-sdk" "git")
|
||||||
|
provides=("${pkgname%-VCS}")
|
||||||
|
conflicts=("${pkgname%-VCS}")
|
||||||
|
replaces=()
|
||||||
|
backup=()
|
||||||
|
options=("!strip")
|
||||||
|
install=
|
||||||
|
source=("${pkgname%-git}::git+https://git.meow.company/pancakes/DeltatuneWls#commit=f93a3cef4d2fdbde8fa0505f2647fbd825e7f7cc"
|
||||||
|
"git+https://git.meow.company/pancakes/ZwlrLayerShell#commit=8fbb1f42a070b83796b589d83bea6eeaa263ed60")
|
||||||
|
noextract=()
|
||||||
|
sha256sums=('SKIP' 'SKIP')
|
||||||
|
|
||||||
|
pkgver() {
|
||||||
|
cd "$srcdir/${pkgname%-git}"
|
||||||
|
|
||||||
|
# Git, no tags available
|
||||||
|
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare() {
|
||||||
|
cd "$srcdir/${pkgname%-git}"
|
||||||
|
git submodule init
|
||||||
|
git config submodule.ZwlrLayerShell.url "$srcdir/ZwlrLayerShell"
|
||||||
|
git -c protocol.file.allow=always submodule update
|
||||||
|
}
|
||||||
|
|
||||||
|
build() {
|
||||||
|
cd "$srcdir/${pkgname%-git}"
|
||||||
|
dotnet publish -r linux-x64
|
||||||
|
}
|
||||||
|
|
||||||
|
package() {
|
||||||
|
cd "$srcdir/${pkgname%-git}"
|
||||||
|
install -Dm755 DeltatuneWls/bin/Release/net9.0/linux-x64/publish/DeltatuneWls ${pkgdir}/usr/bin/deltatune-wls
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue