You are browsing as a guest. Sign up (or log in) to start making projects!

Axwabo

@Axwabo

Joined June 1st, 2026

  • 11Devlogs
  • 2Projects
  • 0Ships
  • 0Votes
Open comments for this post

4h 1m 27s logged

made settings sections with a whole lot of unnecessary abstractions for the funny :33:
[FromKeyedServices] when i could just access a static instance? absolutely yes!!


i couldn’t figure out how to style the children of an ItemsControl externally, so i had to give it an ItemTemplate with a class (which would be unnecessary if i could style the thing)
all that for a separator line… and padding… and margin… what if i just nuke this idea and simply have some spacing between the sections?


i tried organizing classes into vertical slices architecture, but i gave up and only did it for the Linux project instead
the using updates would’ve been funky + some global usings would become useless


PipeWire


the toggle list now no longer “flickers” on/off when refreshing devices, as i only set the link manager after PipeWire objects have been queried


device lists and link toggles are now disabled when switching devices so the user doesn’t accidentally break the linking process


added a button that refreshes links (in case things go wrong somehow)


you can now select the physical microphone from the PipeWire list, and it will update links
this preference isn’t saved to disk just yet


in my last devlog i mentioned some issues, which have now been fixed:

upon startup, the first two switches don’t work sometimes (race condition maybe?)

turns out that i had forgotten to add a potentially valid node to the list after looping through all lines, so it just discarded the last entry

certain links might not reconnect properly when switching the output device

what did i do to fix that? i’m not sure anymore
maybe it was a bit of delay?
this one might be linked related to the former issue

0
0
3
Open comments for this post

8h 59m 12s logged

PIPEWIRE WORKS!!1!1!

spent almost all day adding PipeWire node linking support
i was genuinely tweaking when i found out that the pw-cli create-link command doesn’t create a link… it does NOTHING
wishful thinking to assume that i can simply tell PipeWire to connect nodes automatically
now i have to query the ports, too, and connect those automatically; make sure to sort them, otherwise the channels might be mixed up ahaha (a0b498e7 khm khm)
i spent plenty of the time debugging, the parser i wrote had some funky stuff

how to use it

there are 4 toggles you can activate, as shown in the video:

  • sounds to primary output: this will play the soundboard’s audio in your headphones/primary speakers
  • sounds to virtual mic: forwards soundboard audio to the virtual microphone, letting others (e.g. in a call or in a game) hear the sounds
  • mic passthrough: connects your “real” microphone to the virtual microphone, allowing others to hear your voice when using the virtual mic
  • hear myself: connects your real microphone to your primary output device

more issues

  • upon startup, the first two switches don’t work sometimes (race condition maybe?)
  • certain links might not reconnect properly when switching the output device (it used to be worse when i queried links every time; it would connect only one port to the destination because the port ID was now assigned to something else)

some miscellaneous fixes:

  • fixed certain issues with xdg-desktop-portal shortcut assignments
  • removed the upload date from YouTube video views
  • fixed the NativeAOT build (an attribute was missing that let the ServiceProvider know not to strip view & viewmodel constructors)
  • added a DataToggle control that inherits from ToggleSwitch: clicking on it doesn’t toggle it automatically, the binding controls the state
0
0
6
Open comments for this post

6h 31m 18s logged

FINALLY figured out how to interface with xdg-desktop-portal, global shortcuts now work on Linux!!! (with a caveat ofc)
subsequent bind requests to the same action will just be ignored by the portal, even if you closed the dialog without binding any shortcuts
you should still be abe to bind them in System Settings
props to Pinta for the example on how to do this (the DBus flow kinda sucks ngl)
making this was partially possible because Avalonia updated to the latest Tmds.DBus version


adjusted the YouTube downloader layout: removed the description in favor of a stream selector
that also got rid of the upload date, oops


added a dummy ✏️ button to sounds (basic editor coming soon)
i don’t even want to think about how i’ll render waveforms without making the system go kaboom


also added a number input for volume, letting users type in the desired percentage
Avalonia magically handles the percentage conversion, i didn’t have to make a converter that multiplies the input by 0.01


made pages dynamic, fixing the inconsistent layout
this will make it easier to add platform-specific tabs instead of having to dump everything into settings
TabStrip just didn’t work properly, so i’ll stick with the TabControl (which doesn’t have… tab… focus…)


OtherSoundInteraction now lets you mute, pause or stop other sounds when a new playback is triggered


adopted Injectio so i can slap a [RegisterSingleton] attribute on each class i want in dependency injection without having to go to a different place to add a statement


the “Stop All Instances” button is now replaced by the “Relink” button for files that were not found


you can now drag-and-drop sounds into the board from the file manager

0
0
1
Open comments for this post

32m 8s logged

was debating whether to use js interop to do window dragging, but plain JS is enough
layouts turned out to be wrong for windows, so i created a simple Window base component instead
window dragging now works
also added a date display

0
0
2
Open comments for this post

30m 9s logged

finally got something working, creating an OS using Blazor (yes, it will be painful)
i spent a lot of time trying to think about how to even start, then removing default assets, doing some basic styling
there is now a very basic taskbar with a working clock

0
0
2
Open comments for this post

6h 33m 41s logged

Did a bit of refactoring to accomodate for later NativeAOT support:

  • Each view & viewmodel has to be registered as a service
  • Moved to source-generated JSON handling
  • Hopefully, NativeAOT will make the app noticeably faster when I publish the project

Added global usings, and split up the project for better platform-specific service organization

Fixed the delete button not stopping the sound (how did I manage to fail that??)

Replaced the loop toggle with an Assign Shortcut button for quick access
I think the latter will be used more often, but having the loop toggle update two buttons at once was really cool

Sounds can now be added from YouTube; they are cached for fast access (how else would it work xd)
The window is not a dialog, so you can still interact with the soundboard while waiting for download(s)
(Idk if dialogs prevent interactions on some desktop environments tbh)
This is not the final layout, but it looks decent for now: clicking on a video (left side) takes you to the details page (right side) in the same window
Fun fact: pasting a youtube link automatically opens the video view, letting you download it even while the details are loading (will have to fix that up a little)

0
0
1
Open comments for this post

5h 40m 16s logged

More (almost zero) progress on global shortcuts: I’ve figured out the object path & destination from the Kotlin library zugaldia/stargate, but xdg-desktop-portal just crashes now upon calling CreateSession

  • Nothing usable yet

Added a devices page to select the output device

  • I tried to implement device switching by creating a separate Mixer, but SoundFlow already has functionality for that, so it became much simpler
  • Refactored code to use the new SoundFlowDeviceManager

A “Stop All Sounds” shortcut can now be assigned to each input when clicking the gear icon next to it
Fixed shortcut assignment not working after switching pages

  • Editing context is reopened on page change
  • The SelectionChanged event fired for every child control, not just the TabControl -> I now check for the source of the event

Attempted to add consistent text alignment in tab headers, that turned out to be stupid, so I just added a space after the Playbacks emoji
Removed the “Raise Maximum Volume” (a 0-150% range makes more sense imo)
Adjusted buttons in the sound editing view, this is not yet final

On the image you can see a pipewire graph I created, this is similar to how I want it to work

  • A sink for soundboard output which can be forwarded to the primary output device (e.g. headphones)
  • A mixer virtual device (discord doesn’t support sinks) that combines the microphone input and the soundboard sink, acting as a virtual mic which can be selected in apps
  • From a bit of testing, it turns out that connecting a sink to the primary output device produces some annoying popping, so I’ll probably just link/unlink the app’s playback to/from the primary output device, too
0
0
1
Open comments for this post

4h 9m 59s logged

Added pages & tabs to better separate UI
Activated inputs are now saved and loaded
Sound state is now displayed better, it includes missing file detection (exceptions are not yet handled)

  • Using a MultiBinding and an IMultiValueConverter with an enum didn’t work for some reason
    New page: playbacks
  • It shows all sounds, their current time
  • Will need a redesign
  • Pro tip: don’t call Dispatcher.Post in a method you called Dispatcher.Post in (it will keep updating the UI but prevents user input, you can’t even close the window normally)
    Did a bit of refactoring:
  • AudioManager is now a service
  • Removed the Host service, the desktop lifetime and the TopLevel will be injected
    Added an overlay when a file dialog is open (because unlike windows, not all OSes/desktop environments prevent interactions in this situation)
0
0
2
Open comments for this post

5h 0m 25s logged

Implemented input handling for the Launchpad Mini, now I’ll be able to press pads to play sounds
Creating the shortcuts system took a few iterations, I wasn’t happy with the code I wrote
Shortcuts can be removed even when the input method isn’t active, which wasn’t possible in an earlier iteration
Also implemented settings saving when the app exits

0
0
2
Open comments for this post

5h 31m 47s logged

Added a proper UI for triggering sounds with modes similar to that of voicemod (start -> stop, start -> restart, play -> pause, duplicate)
I played around with 2 rows below the big button but that seemed to take up too much space, so I moved them to the sound editor (which isn’t fully functional yet)
On the right side you can see input methods, which will include global shortcuts later (DBus is confusing af, the win32 api might actually be easier to work with 💀)
(Yes, I’ve half-made a global keyboard handler for windows previously)
Emojis are fairly expressive imo, but there are tooltips that describe what each button does
The layout definitely needs improvements, but it’s something ig
Also implemented loading sounds on startup, as well as saving when a new sound is added

0
0
3
Open comments for this post

1h 50m 44s logged

Created the very base of the project with Avalonia and SoundFlow, sound playback works
Spent a bunch of time trying to figure out the DBus interface for XDG global shortcuts (Linux part of keybinds):

0
0
4

Followers

Loading…