Initial commit containing the first set up of a new rust application, vision doc, first ADRs, and first tasks
This commit is contained in:
commit
9adf1410a3
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/target/
|
||||||
6
Cargo.toml
Normal file
6
Cargo.toml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[package]
|
||||||
|
name = "audio_always_works"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
21
docs/adr/001-rust_core_native_shell.md
Normal file
21
docs/adr/001-rust_core_native_shell.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Rust core, native shell
|
||||||
|
|
||||||
|
## Context and Problem Statement
|
||||||
|
The idea of this application is that it works on different platforms, via GUI and CLI, whilst still maintaining a native feel, and low resource usage.
|
||||||
|
|
||||||
|
## Considered Options
|
||||||
|
- React native
|
||||||
|
- Electron/nodejs
|
||||||
|
- Tauri
|
||||||
|
- Rust core, native shell
|
||||||
|
|
||||||
|
## Decision Outcome
|
||||||
|
Because this application needs access to low-level system APIs on different platforms, that might not be available via NodeJS/javascript, React native and Electron were not valid options.
|
||||||
|
|
||||||
|
Quickly, Tauri came into view, because its Rust core allows for access to these low-level system APIs. However, its browser-based GUI rendering does not feel completely native, at least not without considerable effort.
|
||||||
|
|
||||||
|
Finally, the author's aim is to also learn more about Rust and its ecosystem, so using Rust at the core, whilst integrating a native GUI shell seems like a good course at this time.
|
||||||
|
|
||||||
|
### Consequences
|
||||||
|
There might be less boilerplate available for creating a cross-platform, native look-and-feel application, which might slow down development.
|
||||||
|
However, it does allow the scope to be limited to macOS and GUI first, before focussing on cross-compliation and extending further.
|
||||||
19
docs/adr/002-crux.md
Normal file
19
docs/adr/002-crux.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Crux as a framework for rust core, native shell
|
||||||
|
|
||||||
|
## Context and Problem Statement
|
||||||
|
Upon diving deeper into the options to implement the core in rust, but the outer shell in native code, it became apparent that this is still a relatively new field. Often times, these implementations rely on non-native solutions in the outer shell, like tauri, and flutter. These are best developed, but were discarded in 001.
|
||||||
|
|
||||||
|
## Considered Options
|
||||||
|
- Writing from scratch
|
||||||
|
- Crux
|
||||||
|
|
||||||
|
## Decision Outcome
|
||||||
|
Although Mitchell Hashimoto has recently shown with his implementation of Ghostty, that it is perfectly possible to hand-roll a native shell for a different core (zig in his case), using a framework that is used by multiple other projects and people gives me more confidence in the approach. Although Crux is not perfect, and doesn't fully support Windows and Linux (yet), as they focus more heavily on mobile, it is a good enough starting point to build upon and learn more about both rust, and the development of this application.
|
||||||
|
Crux heavily relies on ports-and-adapters architecture, as well as event sourcing, which is a good fit for the rust core, native shell approach.
|
||||||
|
|
||||||
|
### Consequences
|
||||||
|
It will not be immediately possible to build a Windows and/or Linux outer shell. This is acceptable for now.
|
||||||
|
|
||||||
|
Crux's reliance on event sourcing means it's possible to define which events and subsequent commands need to be supported, as shown here:
|
||||||
|
|
||||||
|

|
||||||
85
docs/adr/002-events.drawio
Normal file
85
docs/adr/002-events.drawio
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
<mxfile host="draw.home.privatevoid.nl" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15" version="27.1.6">
|
||||||
|
<diagram name="Page-1" id="G3W9eUluDOTOJ3pVBLrm">
|
||||||
|
<mxGraphModel dx="1745" dy="1191" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
|
||||||
|
<root>
|
||||||
|
<mxCell id="0" />
|
||||||
|
<mxCell id="1" parent="0" />
|
||||||
|
<mxCell id="qVedj06A-rBEsVxlXKs5-4" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="460" y="20" width="690" height="1110" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="qVedj06A-rBEsVxlXKs5-2" value="Audio devices listed" style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;fillColor=#f0a30a;strokeColor=#BD7000;fillStyle=solid;direction=west;gradientDirection=north;shadow=1;size=20;pointerEvents=1;fontColor=#000000;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="1220" y="50" width="140" height="160" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="qVedj06A-rBEsVxlXKs5-3" value="List audio devices" style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;fillColor=#1ba1e2;strokeColor=#006EAF;fillStyle=solid;direction=west;gradientDirection=north;shadow=1;size=20;pointerEvents=1;fontColor=#ffffff;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="735" y="40" width="140" height="160" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="qVedj06A-rBEsVxlXKs5-5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0;entryDx=140;entryDy=90;entryPerimeter=0;" parent="1" source="qVedj06A-rBEsVxlXKs5-3" target="qVedj06A-rBEsVxlXKs5-2" edge="1">
|
||||||
|
<mxGeometry relative="1" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="qVedj06A-rBEsVxlXKs5-6" value="Change input device" style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;fillColor=#1ba1e2;strokeColor=#006EAF;fillStyle=solid;direction=west;gradientDirection=north;shadow=1;size=20;pointerEvents=1;fontColor=#ffffff;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="735" y="230" width="140" height="160" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="qVedj06A-rBEsVxlXKs5-7" value="Change output device" style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;fillColor=#1ba1e2;strokeColor=#006EAF;fillStyle=solid;direction=west;gradientDirection=north;shadow=1;size=20;pointerEvents=1;fontColor=#ffffff;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="735" y="420" width="140" height="160" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="qVedj06A-rBEsVxlXKs5-9" value="Update rules" style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;fillColor=#1ba1e2;strokeColor=#006EAF;fillStyle=solid;direction=west;gradientDirection=north;shadow=1;size=20;pointerEvents=1;fontColor=#ffffff;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="735" y="640" width="140" height="160" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="qVedj06A-rBEsVxlXKs5-10" value="Default input device changed" style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;fillColor=#f0a30a;strokeColor=#BD7000;fillStyle=solid;direction=west;gradientDirection=north;shadow=1;size=20;pointerEvents=1;fontColor=#000000;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="210" y="220" width="140" height="160" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="qVedj06A-rBEsVxlXKs5-11" value="Input device changed" style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;fillColor=#f0a30a;strokeColor=#BD7000;fillStyle=solid;direction=west;gradientDirection=north;shadow=1;size=20;pointerEvents=1;fontColor=#000000;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="1220" y="240" width="140" height="160" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="qVedj06A-rBEsVxlXKs5-12" value="Output device changed" style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;fillColor=#f0a30a;strokeColor=#BD7000;fillStyle=solid;direction=west;gradientDirection=north;shadow=1;size=20;pointerEvents=1;fontColor=#000000;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="1220" y="430" width="140" height="160" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="qVedj06A-rBEsVxlXKs5-14" value="Audio devices changed" style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;fillColor=#f0a30a;strokeColor=#BD7000;fillStyle=solid;direction=west;gradientDirection=north;shadow=1;size=20;pointerEvents=1;fontColor=#000000;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="210" y="30" width="140" height="160" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="qVedj06A-rBEsVxlXKs5-15" value="Default output device changed" style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;fillColor=#f0a30a;strokeColor=#BD7000;fillStyle=solid;direction=west;gradientDirection=north;shadow=1;size=20;pointerEvents=1;fontColor=#000000;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="210" y="410" width="140" height="160" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="qVedj06A-rBEsVxlXKs5-16" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0;entryDx=140;entryDy=90;entryPerimeter=0;" parent="1" source="qVedj06A-rBEsVxlXKs5-14" target="qVedj06A-rBEsVxlXKs5-3" edge="1">
|
||||||
|
<mxGeometry relative="1" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="qVedj06A-rBEsVxlXKs5-17" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0;entryDx=140;entryDy=90;entryPerimeter=0;" parent="1" source="qVedj06A-rBEsVxlXKs5-10" target="qVedj06A-rBEsVxlXKs5-6" edge="1">
|
||||||
|
<mxGeometry relative="1" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="qVedj06A-rBEsVxlXKs5-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0;entryDx=140;entryDy=90;entryPerimeter=0;" parent="1" source="qVedj06A-rBEsVxlXKs5-15" target="qVedj06A-rBEsVxlXKs5-7" edge="1">
|
||||||
|
<mxGeometry relative="1" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="qVedj06A-rBEsVxlXKs5-19" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0;entryDx=140;entryDy=90;entryPerimeter=0;" parent="1" source="qVedj06A-rBEsVxlXKs5-7" target="qVedj06A-rBEsVxlXKs5-12" edge="1">
|
||||||
|
<mxGeometry relative="1" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="qVedj06A-rBEsVxlXKs5-20" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0;entryDx=140;entryDy=90;entryPerimeter=0;" parent="1" source="qVedj06A-rBEsVxlXKs5-6" target="qVedj06A-rBEsVxlXKs5-11" edge="1">
|
||||||
|
<mxGeometry relative="1" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="qVedj06A-rBEsVxlXKs5-21" value="Rule created" style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;fillColor=#f0a30a;strokeColor=#BD7000;fillStyle=solid;direction=west;gradientDirection=north;shadow=1;size=20;pointerEvents=1;fontColor=#000000;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="210" y="630" width="140" height="160" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="qVedj06A-rBEsVxlXKs5-22" value="Rule updated" style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;fillColor=#f0a30a;strokeColor=#BD7000;fillStyle=solid;direction=west;gradientDirection=north;shadow=1;size=20;pointerEvents=1;fontColor=#000000;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="210" y="830" width="140" height="160" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="qVedj06A-rBEsVxlXKs5-23" value="Rule deleted" style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;fillColor=#f0a30a;strokeColor=#BD7000;fillStyle=solid;direction=west;gradientDirection=north;shadow=1;size=20;pointerEvents=1;fontColor=#000000;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="210" y="1009" width="140" height="160" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="qVedj06A-rBEsVxlXKs5-24" value="Rules updated" style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;fillColor=#f0a30a;strokeColor=#BD7000;fillStyle=solid;direction=west;gradientDirection=north;shadow=1;size=20;pointerEvents=1;fontColor=#000000;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="1220" y="650" width="140" height="160" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="qVedj06A-rBEsVxlXKs5-25" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0;entryDx=140;entryDy=90;entryPerimeter=0;" parent="1" source="qVedj06A-rBEsVxlXKs5-21" target="qVedj06A-rBEsVxlXKs5-9" edge="1">
|
||||||
|
<mxGeometry relative="1" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="qVedj06A-rBEsVxlXKs5-26" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0;entryDx=140;entryDy=90;entryPerimeter=0;" parent="1" source="qVedj06A-rBEsVxlXKs5-22" target="qVedj06A-rBEsVxlXKs5-9" edge="1">
|
||||||
|
<mxGeometry relative="1" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="qVedj06A-rBEsVxlXKs5-27" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0;entryDx=140;entryDy=90;entryPerimeter=0;" parent="1" source="qVedj06A-rBEsVxlXKs5-23" target="qVedj06A-rBEsVxlXKs5-9" edge="1">
|
||||||
|
<mxGeometry relative="1" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="qVedj06A-rBEsVxlXKs5-28" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0;entryDx=140;entryDy=90;entryPerimeter=0;" parent="1" source="qVedj06A-rBEsVxlXKs5-9" target="qVedj06A-rBEsVxlXKs5-24" edge="1">
|
||||||
|
<mxGeometry relative="1" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
</root>
|
||||||
|
</mxGraphModel>
|
||||||
|
</diagram>
|
||||||
|
</mxfile>
|
||||||
BIN
docs/adr/002-events.png
Normal file
BIN
docs/adr/002-events.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 81 KiB |
10
docs/adr/003-nom_parser_generator.md
Normal file
10
docs/adr/003-nom_parser_generator.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# Nom as Parser Generator
|
||||||
|
|
||||||
|
## Context and Problem Statement
|
||||||
|
|
||||||
|
|
||||||
|
## Considered Options
|
||||||
|
|
||||||
|
## Decision Outcome
|
||||||
|
|
||||||
|
### Consequences
|
||||||
0
docs/tasks/0001-create_native_shell_app.md
Normal file
0
docs/tasks/0001-create_native_shell_app.md
Normal file
0
docs/tasks/0003-create_rules_dsl_interpreter.md
Normal file
0
docs/tasks/0003-create_rules_dsl_interpreter.md
Normal file
0
docs/tasks/0004-display_rules_in_gui.md
Normal file
0
docs/tasks/0004-display_rules_in_gui.md
Normal file
0
docs/tasks/0005-create_rules_via_gui.md
Normal file
0
docs/tasks/0005-create_rules_via_gui.md
Normal file
0
docs/tasks/0006-store_rules_in_config_file.md
Normal file
0
docs/tasks/0006-store_rules_in_config_file.md
Normal file
0
docs/tasks/0007-read_config_file_on_start.md
Normal file
0
docs/tasks/0007-read_config_file_on_start.md
Normal file
0
docs/tasks/0008-hide_in_menu_bar.md
Normal file
0
docs/tasks/0008-hide_in_menu_bar.md
Normal file
0
docs/tasks/0009-execute_rules_on_device_change.md
Normal file
0
docs/tasks/0009-execute_rules_on_device_change.md
Normal file
8
docs/vision/vision.md
Normal file
8
docs/vision/vision.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# Vision for the application
|
||||||
|
|
||||||
|
With this application it's possible to define rules that allow the user to set the default input and output audio device based on the given predicates.
|
||||||
|
Predicates could be many different system states, but the first version will just focus on the available input and output audio devices.
|
||||||
|
The application should present itself as a GUI application, supported on macOS, Windows, and Linux flavours, as well as be available as a CLI application. This allows for the most flexible usage.
|
||||||
|
The first version of this application will focus on a macOS GUI though.
|
||||||
|
Rules configuration will be stored as a file in the user's home folder, which allows it to be edited by any text editor as well as the GUI.
|
||||||
|
The application should feel snappy and its GUI native. Because it is always running in the background, the resource usage should be very low.
|
||||||
3
src/main.rs
Normal file
3
src/main.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
fn main() {
|
||||||
|
println!("Hello, world!");
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user