├── .clang-format ├── .gitattributes ├── .github └── workflows │ ├── make-docs.yml │ └── nightly.yml ├── .gitignore ├── .gitmodules ├── README.md ├── Sdk.zig ├── build.zig ├── design ├── Logo.xcf ├── desktop-popup.xcf ├── dunst-wm.uxf ├── dunstblick-desktop.xcf ├── dunstblick-widgets.xcf ├── dunstblick.pdf ├── dunstwolke.pdf ├── dunstwolke.svg ├── dunstwolke_pfade.pdf ├── example.png ├── example.ui ├── logo.png ├── quark.png └── square-logo.png ├── development-stuff ├── .gitignore ├── API Design.md ├── TODO.md ├── broadcast-1337.bin ├── dunst-ui.md ├── dunstfs-dataset.sql ├── example-list.txt ├── old-code.zig ├── properties.txt ├── protocol.txt ├── todo.txt ├── ui-design-v2.uxf └── wasm-apps.md ├── docs ├── .gitignore ├── mkdocs.yml └── src │ ├── dunstblick.md │ ├── dunstblick │ ├── layout-engine.md │ ├── layout-language.md │ ├── protocol.md │ ├── types.md │ └── widgets.md │ ├── dunstfabric.md │ ├── dunstfs.md │ ├── dunstnetz.md │ ├── img │ └── dunstblick-handshake.svg │ └── index.md ├── extensions └── dfs-chrome │ ├── background.js │ ├── daemon.sh │ ├── images │ ├── dfs-128.png │ ├── dfs-16.png │ ├── dfs-32.png │ └── dfs-48.png │ ├── manifest.json │ ├── options.html │ ├── options.js │ ├── popup.css │ ├── popup.html │ └── popup.js ├── reference ├── bcb-ui.xcf ├── vision-irc.txt └── windows-xp-ui.xcf ├── src ├── apps │ └── wasm-demo.zig ├── dunst-environment │ └── main.zig ├── dunstblick-app │ └── dunstblick.zig ├── dunstblick-compiler │ ├── Compiler.zig │ ├── Database.zig │ ├── ErrorCollection.zig │ ├── Location.zig │ ├── Parser.zig │ ├── Tokenizer.zig │ ├── main.zig │ ├── package.zig │ └── tests.zig ├── dunstblick-desktop │ ├── dunst-ui │ │ ├── DunstblickUI.zig │ │ ├── Object.zig │ │ └── types.zig │ ├── dunstblick-types.zig │ ├── gui │ │ ├── ApplicationDescription.zig │ │ ├── ApplicationInstance.zig │ │ ├── HomeScreen.zig │ │ ├── fonts │ │ │ └── firasans-regular.ttf │ │ └── icons │ │ │ ├── application.svg │ │ │ ├── application.tvg │ │ │ ├── archiver.svg │ │ │ ├── archiver.tvg │ │ │ ├── calculator.svg │ │ │ ├── calculator.tvg │ │ │ ├── data.zig │ │ │ ├── mahjongg.svg │ │ │ ├── mahjongg.tvg │ │ │ ├── notes.svg │ │ │ ├── notes.tvg │ │ │ ├── settings.svg │ │ │ ├── settings.tvg │ │ │ ├── text-editor.svg │ │ │ ├── text-editor.tvg │ │ │ ├── view-compact.xcf │ │ │ ├── web-browser.svg │ │ │ ├── web-browser.tvg │ │ │ ├── zig-mark.svg │ │ │ └── zig-mark.tvg │ ├── main.zig │ └── network │ │ ├── AppDiscovery.zig │ │ └── NetworkApplication.zig ├── dunstblick-protocol │ ├── data-types.zig │ ├── decoder.zig │ ├── encoder.zig │ ├── enums.zig │ ├── layout.zig │ ├── protocol.zig │ ├── tcp │ │ ├── CryptoState.zig │ │ ├── client_state_machine.zig │ │ ├── server_state_machine.zig │ │ ├── shared_types.zig │ │ └── v1.zig │ ├── udp.zig │ ├── value.zig │ └── zigzagint.zig ├── dunstfs │ ├── RpcClient.zig │ ├── cli.zig │ ├── daemon.zig │ ├── html │ │ ├── file.ztt │ │ ├── frame.ztt │ │ ├── img │ │ │ ├── file-details.svg │ │ │ ├── file-edit.svg │ │ │ ├── file-view.svg │ │ │ └── mime │ │ │ │ ├── account.svg │ │ │ │ ├── archive.svg │ │ │ │ ├── cad.svg │ │ │ │ ├── chart.svg │ │ │ │ ├── code.svg │ │ │ │ ├── csv.svg │ │ │ │ ├── document.svg │ │ │ │ ├── generic.svg │ │ │ │ ├── image.svg │ │ │ │ ├── ms-excel.svg │ │ │ │ ├── ms-powerpoint.svg │ │ │ │ ├── ms-word.svg │ │ │ │ ├── music.svg │ │ │ │ ├── pdf.svg │ │ │ │ ├── table.svg │ │ │ │ └── video.svg │ │ ├── index.htm │ │ ├── index.ztt │ │ ├── settings.ztt │ │ └── style.css │ ├── interface.zig │ ├── magic.zig │ ├── old-main.zig │ └── rpc.zig ├── dunstinit │ ├── control-main.zig │ ├── rpc.zig │ └── service-main.zig ├── dunstnetz-daemon │ └── main.zig ├── dunstnetz │ └── main.zig ├── examples │ ├── calculator │ │ ├── README.md │ │ ├── calculator.svg │ │ ├── calculator.tvg │ │ ├── calculator.tvgt │ │ ├── layout.h │ │ ├── layout.json │ │ ├── layout.ui │ │ └── main.c │ ├── mediaserver │ │ ├── README.md │ │ ├── bass │ │ │ ├── bass.chm │ │ │ ├── bass.h │ │ │ ├── bass.txt │ │ │ └── x86_64 │ │ │ │ └── libbass.so │ │ ├── layouts │ │ │ ├── .gitignore │ │ │ ├── main.ui │ │ │ ├── menu.ui │ │ │ ├── searchitem.ui │ │ │ └── searchlist.ui │ │ ├── resources │ │ │ ├── add.png │ │ │ ├── album.png │ │ │ ├── close.png │ │ │ ├── disc-player.svg │ │ │ ├── disc-player.tvg │ │ │ ├── disc-player.tvgt │ │ │ ├── folder-open.png │ │ │ ├── menu.png │ │ │ ├── pause.png │ │ │ ├── placeholder.png │ │ │ ├── play.png │ │ │ ├── playlist-music.png │ │ │ ├── radio.png │ │ │ ├── repeat-once.png │ │ │ ├── repeat.png │ │ │ ├── settings.png │ │ │ ├── shuffle.png │ │ │ ├── skip-next.png │ │ │ ├── skip-previous.png │ │ │ ├── volume-high.png │ │ │ ├── volume-low.png │ │ │ ├── volume-medium.png │ │ │ ├── volume-off.png │ │ │ └── wallpaper.png │ │ ├── src │ │ │ ├── c.zig │ │ │ └── main.zig │ │ ├── testdata-2.mp3 │ │ ├── testdata.mp3 │ │ └── ui-design.xcf │ └── minimal │ │ ├── README.md │ │ ├── application.svg │ │ ├── application.tvg │ │ ├── main.c │ │ └── minimal.pro ├── images │ ├── kristall-32.png │ ├── person-female-01.png │ ├── person-male-01.png │ └── small-test.png ├── libdunstblick │ ├── include │ │ └── dunstblick.h │ └── src │ │ └── c-binding.zig ├── test │ └── widget-tester │ │ ├── 4by3.png │ │ ├── go.png │ │ ├── icon.tvg │ │ ├── index.ui │ │ ├── main.zig │ │ └── ziggy.tvg └── tools │ ├── render-widget-docs.zig │ └── wireshark-dissector.lua ├── system-root ├── bin │ ├── hello.c │ ├── hello.exe │ └── hello.pdb └── config │ └── services │ ├── date.json │ ├── hello-windows.json │ └── mqtt-eject.json └── vendor ├── file-5.40 ├── AUTHORS ├── COPYING ├── ChangeLog ├── INSTALL ├── MAINT ├── NEWS ├── README ├── TODO ├── config.h ├── magic │ └── magic.mgc └── src │ ├── apprentice.c │ ├── apptype.c │ ├── ascmagic.c │ ├── asctime_r.c │ ├── asprintf.c │ ├── buffer.c │ ├── cdf.c │ ├── cdf.h │ ├── cdf_time.c │ ├── compress.c │ ├── ctime_r.c │ ├── der.c │ ├── der.h │ ├── dprintf.c │ ├── elfclass.h │ ├── encoding.c │ ├── file.c │ ├── file.h │ ├── file_opts.h │ ├── fmtcheck.c │ ├── fsmagic.c │ ├── funcs.c │ ├── getline.c │ ├── getopt_long.c │ ├── gmtime_r.c │ ├── is_csv.c │ ├── is_json.c │ ├── is_tar.c │ ├── localtime_r.c │ ├── magic.c │ ├── magic.h │ ├── mygetopt.h │ ├── pread.c │ ├── print.c │ ├── readcdf.c │ ├── readelf.c │ ├── readelf.h │ ├── seccomp.c │ ├── softmagic.c │ ├── strcasestr.c │ ├── strlcat.c │ ├── strlcpy.c │ ├── tar.h │ └── vasprintf.c ├── pcre2-premade ├── pcre2.h ├── pcre2_chartables.c └── regex.h ├── xqlib-stripped ├── include │ ├── xcept │ ├── xlog │ └── xstd │ │ ├── optional │ │ ├── resource │ │ └── unique_id └── src │ └── xlog.cpp └── zig-meta ├── meta.zig └── src ├── closure.zig ├── fnwrap.zig └── interface.zig /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: LLVM 2 | 3 | SortIncludes: false 4 | MaxEmptyLinesToKeep: 1 5 | IndentWidth: 2 6 | ColumnLimit: 0 7 | NamespaceIndentation: All -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.zig text=auto eol=lf 2 | *.ui text=auto eol=lf -------------------------------------------------------------------------------- /.github/workflows/make-docs.yml: -------------------------------------------------------------------------------- 1 | name: Autogenerate Docs 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: actions/checkout@v2 13 | # submodules: "recursive" 14 | 15 | - name: Setup Python 16 | uses: actions/setup-python@v1 17 | with: 18 | python-version: '3.7' 19 | architecture: 'x64' 20 | 21 | - name: Install dependencies 22 | run: | 23 | python3 -m pip install --upgrade pip # install pip 24 | python3 -m pip install mkdocs # install mkdocs 25 | python3 -m pip install mkdocs-material # install material theme 26 | 27 | - name: Build site 28 | working-directory: docs 29 | run: mkdocs build 30 | 31 | - name: Deploy to Server 32 | uses: easingthemes/ssh-deploy@v2.1.1 33 | env: 34 | SSH_PRIVATE_KEY: ${{ secrets.KEY }} 35 | ARGS: "-rltgoDzvO --delete" 36 | SOURCE: "docs/site/" 37 | REMOTE_HOST: ${{ secrets.HOST }} 38 | REMOTE_USER: ${{ secrets.USERNAME }} 39 | TARGET: "/home/dunstblick-ci/website" 40 | 41 | 42 | ##- name: Deploy files to dunstwolke.org 43 | ## uses: appleboy/scp-action@master 44 | ## env: 45 | ## HOST: ${{ secrets.HOST }} 46 | ## USERNAME: ${{ secrets.USERNAME }} 47 | ## PORT: ${{ secrets.PORT }} 48 | ## KEY: ${{ secrets.KEY }} 49 | ## with: 50 | ## source: "./docs/site/*" 51 | ## target: "/home/dunstblick-ci/website" 52 | ## strip_components: 2 53 | -------------------------------------------------------------------------------- /.github/workflows/nightly.yml: -------------------------------------------------------------------------------- 1 | name: Continuous Build 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | pull_request: 7 | branches: [master] 8 | schedule: 9 | - cron: "0 5 * * *" # run at 5 AM UTC 10 | 11 | jobs: 12 | build-linux: 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | with: 18 | submodules: "recursive" 19 | 20 | - name: Install dependencies 21 | run: | 22 | sudo apt-get update 23 | sudo apt-get install libsdl2-dev libsdl2-image-dev 24 | 25 | - name: Setup Zig 26 | uses: goto-bus-stop/setup-zig@v1 27 | with: 28 | version: master 29 | 30 | - name: Build 31 | run: zig build 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | zig-cache/ 3 | zig-out/ 4 | .build_config/ 5 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "vendor/zig-args"] 2 | path = vendor/zig-args 3 | url = https://github.com/MasterQ32/zig-args 4 | [submodule "vendor/zig-network"] 5 | path = vendor/zig-network 6 | url = https://github.com/MasterQ32/zig-network 7 | [submodule "vendor/zig-uri"] 8 | path = vendor/zig-uri 9 | url = https://github.com/MasterQ32/zig-uri 10 | [submodule "vendor/stb"] 11 | path = vendor/stb 12 | url = https://github.com/nothings/stb 13 | [submodule "vendor/painterz"] 14 | path = vendor/painterz 15 | url = https://github.com/ziglibs/painterz 16 | [submodule "vendor/optional"] 17 | path = vendor/optional 18 | url = https://github.com/TartanLlama/optional 19 | [submodule "vendor/ini"] 20 | path = vendor/ini 21 | url = https://github.com/ziglibs/ini 22 | [submodule "vendor/foxwren"] 23 | path = vendor/foxwren 24 | url = https://github.com/malcolmstill/foxwren 25 | [submodule "vendor/zero-graphics"] 26 | path = vendor/zero-graphics 27 | url = https://github.com/MasterQ32/zero-graphics 28 | [submodule "vendor/zig-charm"] 29 | path = vendor/zig-charm 30 | url = https://github.com/jedisct1/zig-charm 31 | [submodule "vendor/known-folders"] 32 | path = vendor/known-folders 33 | url = https://github.com/ziglibs/known-folders 34 | [submodule "vendor/zig-sqlite"] 35 | path = vendor/zig-sqlite 36 | url = https://github.com/vrischmann/zig-sqlite 37 | [submodule "vendor/uuid6-zig"] 38 | path = vendor/uuid6-zig 39 | url = https://github.com/jdknezek/uuid6-zig 40 | [submodule "vendor/zig-qoi"] 41 | path = vendor/qoi 42 | url = https://github.com/MasterQ32/zig-qoi 43 | [submodule "vendor/sdk"] 44 | path = vendor/tvg 45 | url = https://github.com/TinyVG/sdk 46 | [submodule "vendor/antiphony"] 47 | path = vendor/antiphony 48 | url = https://github.com/ziglibs/antiphony 49 | [submodule "vendor/serve"] 50 | path = vendor/serve 51 | url = https://github.com/MasterQ32/zig-serve 52 | [submodule "vendor/ztt"] 53 | path = vendor/ztt 54 | url = https://github.com/MasterQ32/ZTT 55 | [submodule "vendor/pcre2"] 56 | path = vendor/pcre2 57 | url = https://github.com/PCRE2Project/pcre2 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dunstwolke 2 | 3 | Repository for developing software for a "personal cloud" project 4 | 5 | ## Dunstblick 6 | 7 | A UI system with a different approach: 8 | 9 | Serialize widgets and layout structure into a binary structure, deserialize this on the server side 10 | and only communicate with state changes in "object values" (bindings), not widget states. 11 | 12 | ### Video 13 | 14 | [![](https://mq32.de/public/screenshot/951e859e400b506b1e6f8cedf0838b4d.png)](https://mq32.de/public/dunstwolke-04.mp4) 15 | 16 | ### Examples 17 | 18 | - [Calculator](https://github.com/Dunstwolke/core/tree/master/src/examples/calculator) 19 | - Address Book 20 | - Text Editor 21 | - Media Player 22 | - Chat Application 23 | - Game Menu 24 | 25 | ### Documentation 26 | 27 | - Basic Concepts 28 | - Layout Definition and Semantics 29 | - Serialization / Binary Formats 30 | - 31 | - 32 | 33 | ### Configuration 34 | 35 | For the desktop variant, the following environment variables are available for configuration: 36 | - `DUNSTBLICK_DPI` might be used to set a fallback display density when the display one could not be determined 37 | - `DUNSTBLICK_FULLSCREEN` might be used to enforce fullscreen or window mode. Use `yes` or `no` 38 | -------------------------------------------------------------------------------- /design/Logo.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/design/Logo.xcf -------------------------------------------------------------------------------- /design/desktop-popup.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/design/desktop-popup.xcf -------------------------------------------------------------------------------- /design/dunst-wm.uxf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15 4 | 5 | UMLClass 6 | 7 | 165 8 | 135 9 | 60 10 | 60 11 | 12 | MENU 13 | valign=center 14 | 15 | 16 | 17 | UMLClass 18 | 19 | 165 20 | 195 21 | 60 22 | 570 23 | 24 | 25 | 26 | 27 | 28 | UMLClass 29 | 30 | 180 31 | 210 32 | 30 33 | 30 34 | 35 | 0 36 | valign=center 37 | transparency=0 38 | bg=#80FF80 39 | 40 | 41 | 42 | UMLClass 43 | 44 | 180 45 | 255 46 | 30 47 | 30 48 | 49 | 1 50 | valign=center 51 | transparency=0 52 | bg=#FF8080 53 | 54 | 55 | 56 | UMLClass 57 | 58 | 180 59 | 300 60 | 30 61 | 30 62 | 63 | 2 64 | valign=center 65 | transparency=0 66 | bg=#8080FF 67 | 68 | 69 | 70 | UMLClass 71 | 72 | 225 73 | 135 74 | 465 75 | 630 76 | 77 | APP 0 78 | valign=center 79 | transparency=0 80 | bg=#80FF80 81 | 82 | 83 | 84 | Relation 85 | 86 | 210 87 | 120 88 | 45 89 | 675 90 | 91 | lt=- 92 | lw=3 93 | 10.0;10.0;10.0;430.0 94 | 95 | 96 | UMLClass 97 | 98 | 690 99 | 135 100 | 465 101 | 315 102 | 103 | APP 1 104 | valign=center 105 | transparency=0 106 | bg=#FF8080 107 | 108 | 109 | 110 | UMLClass 111 | 112 | 690 113 | 450 114 | 465 115 | 315 116 | 117 | APP 2 118 | valign=center 119 | transparency=0 120 | bg=#8080FF 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /design/dunstblick-desktop.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/design/dunstblick-desktop.xcf -------------------------------------------------------------------------------- /design/dunstblick-widgets.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/design/dunstblick-widgets.xcf -------------------------------------------------------------------------------- /design/dunstblick.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/design/dunstblick.pdf -------------------------------------------------------------------------------- /design/dunstwolke.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/design/dunstwolke.pdf -------------------------------------------------------------------------------- /design/dunstwolke_pfade.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/design/dunstwolke_pfade.pdf -------------------------------------------------------------------------------- /design/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/design/example.png -------------------------------------------------------------------------------- /design/example.ui: -------------------------------------------------------------------------------- 1 | /** 2 | * models the following dialog: 3 | * https://www.researchgate.net/profile/Richard_Kennard/publication/224517249/figure/fig1/AS:302832667381772@1449212342988/Example-UI-with-5-fields.png 4 | **/ 5 | DockLayout { 6 | vertical-alignment: stretch; 7 | horizontal-alignment: stretch; 8 | 9 | GridLayout { 10 | /* this widget will layout at the bottom of the parent */ 11 | dock-site: bottom; 12 | 13 | /* two columns, both take the same size 14 | number of rows is inferred by 15 | "rowcount = ceil(childcount / colcount) 16 | when no row definition list is given. */ 17 | columns: expand, expand; 18 | 19 | Button { 20 | horizontal-alignment: right; 21 | vertical-alignment: bottom; 22 | Label { 23 | text: "Save"; 24 | } 25 | } 26 | Button { 27 | horizontal-alignment: left; 28 | vertical-alignment: bottom; 29 | Label { 30 | text: "Delete"; 31 | } 32 | } 33 | } 34 | /* Contains the main table */ 35 | GridLayout { 36 | /* two columns */ 37 | columns: auto, expand; /* auto=minimum size, expand=take rest */ 38 | rows: auto, auto, auto, auto, expand; 39 | Label { 40 | text: "Name:"; 41 | horizontal-alignment: right; 42 | } 43 | TextBox { 44 | text: "$name"; 45 | } 46 | Label { 47 | text: "Age:"; 48 | horizontal-alignment: right; 49 | } 50 | Slider { 51 | value: 60; 52 | minimum: 0; 53 | maximum: 100; 54 | } 55 | Label { 56 | text: "Gender:"; 57 | horizontal-alignment: right; 58 | } 59 | ComboBox { 60 | } 61 | Label { 62 | text: "Retired:"; 63 | horizontal-alignment: right; 64 | } 65 | Label { 66 | text: "Yes/No"; 67 | horizontal-alignment: left; 68 | } 69 | Label { 70 | text: "Notes:"; 71 | horizontal-alignment: right; 72 | vertical-alignment: top; 73 | } 74 | TextBox { 75 | /* multiline: true; */ 76 | text: "$notes"; 77 | horizontal-alignment: stretch; 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /design/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/design/logo.png -------------------------------------------------------------------------------- /design/quark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/design/quark.png -------------------------------------------------------------------------------- /design/square-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/design/square-logo.png -------------------------------------------------------------------------------- /development-stuff/.gitignore: -------------------------------------------------------------------------------- 1 | *.uit.dat 2 | -------------------------------------------------------------------------------- /development-stuff/API Design.md: -------------------------------------------------------------------------------- 1 | # Common 2 | 3 | # Types 4 | - string 5 | - integer 6 | - number 7 | - boolean 8 | - object-id (references globally known object) 9 | - list 10 | - resource-id 11 | 12 | object = [](key,type,value) 13 | key ist der "Name" der Property 14 | 15 | # Known Conversions 16 | string → number 17 | integer → number 18 | boolean → number 19 | 20 | boolean → string 21 | integer → string 22 | number → string 23 | 24 | number → integer 25 | string → integer 26 | boolean → integer 27 | 28 | # Lists 29 | listen können nur in objekten speichert sein, haben folgende API 30 | - clear() 31 | - insertRange(oid, prop, index, []value) 32 | - removeRange(oid, prop, index, count=1) 33 | - move(oid, prop, indexFrom, indexTo, count=1) 34 | 35 | AnyWidget { 36 | binding-context: resource(…); // use global object 37 | } 38 | 39 | AnyWidget { 40 | binding-context: bind(…); 41 | } 42 | 43 | AnyWidget { 44 | child-source: bind(…); 45 | child-template: resource(…); 46 | } 47 | Kinder werden alle ersetzt durch template-varianten die 48 | an eine liste gebunden sind. für jedes kind wird das 49 | template instanziert. 50 | problem für die zukunft: template selector für versch. untertypen?! 51 | 52 | # Messages 53 | 54 | rid = resource id 55 | oid = object id 56 | obj = object data 57 | data = raw data 58 | eid = event id 59 | value = One possible value of an UIValue. Must have a known type to deserialize 60 | type = UIType enumeration 61 | name = property name 62 | kind = resource kind 63 | 64 | ## Client Messages 65 | 66 | - UploadResource(rid, kind, data) 67 | - AddOrUpdateObject(obj) 68 | - RemoveObject(oid) 69 | - SetView(rid) 70 | - SetRoot(oid) 71 | - SetProperty(oid, name, value) // "unsafe command", uses the serverside object type or fails of property does not exist 72 | - Clear(oid, name) 73 | - InsertRange(oid, name, index, count, value …) // manipulate lists 74 | - RemoveRange(oid, name, index, count) // manipulate lists 75 | - MoveRange(oid, name, indexFrom, indexTo, count) // manipulate lists 76 | 77 | # Server Messages 78 | 79 | - EventCallback(eid) 80 | - PropertyChanged(oid, name, value) 81 | 82 | -------------------------------------------------------------------------------- /development-stuff/TODO.md: -------------------------------------------------------------------------------- 1 | # TODO 2 | 3 | ## dunstblick-desktop 4 | 5 | - User Interface 6 | - Collapsing of `exited` applications 7 | - Port the implementation to Wasm 8 | 9 | ## dunstblick-app 10 | 11 | - [ ] Also free the current_event thingy if any. This would dangle if the application would be closed. 12 | - [ ] Implement new SingleInterfaceApplication 13 | Single application interface that behaves like a connection to the outer world and replicates that behaviour. All connections will see the same data. 14 | - [ ] Rework the C api to use the event-driven API style as well 15 | 16 | ## dunstblick-display 17 | => see dunstblick-desktop 18 | 19 | ## dunstblick-compiler 20 | - [ ] Create a generator for resource info ("bindgen") 21 | 22 | ## Old 23 | 24 | - [x] Resource System 25 | - [ ] Vector Drawing 26 | - [ ] Deserialize Vectors 27 | - [ ] Define Vector format 28 | - [ ] Define Vector rendering 29 | - [ ] Implement missing widgets 30 | - [ ] ComboBox 31 | - [ ] TreeView 32 | - [ ] TreeViewItem 33 | - [ ] ListBox 34 | - [ ] ListBoxItem 35 | - [ ] TextBox 36 | - [ ] ScrollView 37 | - [x] ScrollBar 38 | - [ ] SpinEdit 39 | - [ ] RadioButton 40 | - [ ] Slider 41 | - Implement discrete and continuous mode 42 | - Snap to integers/values 43 | - [ ] GridLayout 44 | - Implement `row-span` and `col-span`. 45 | - [ ] Fix Bugs 46 | - [ ] Empty grid (no colums, no rows) should not crash 47 | - [ ] ~~Add "deferModalDrawing" to render/ui context~~ 48 | - [ ] Allow creation of modal popup windows 49 | - allow rendering stuff *after* everything else 50 | - required for combo boxes 51 | - required for message boxes 52 | - Improved text rendering API 53 | - [ ] Rich text 54 | - [ ] Full unicode 55 | - [ ] Multi-Line Rendering 56 | - [ ] Left-align 57 | - [ ] Right-align 58 | - [ ] Center 59 | - [ ] Justify 60 | - [ ] Object System 61 | - [ ] Make object properties mark if they have feedback to the client 62 | - [ ] Input Routing 63 | - [ ] Tab Switch 64 | - [ ] Filter keyboard for widgets with tab stop 65 | - [ ] Transitions between widgets 66 | - [ ] Ease-in 67 | - [ ] Ease-out 68 | - [ ] Transition between two layouts 69 | - [ ] Widget 70 | - [ ] Bindable child lists 71 | - [ ] Add "sort by property" + "sort asc, sort desc" 72 | - [ ] Give widgets a bindable "name" property that will be passed along with sent events to identify auto-generated widgets. 73 | - [ ] Add support for "push notifications" on the discovery network to allow certain applications announce messages without having an open connection to them 74 | -------------------------------------------------------------------------------- /development-stuff/broadcast-1337.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/development-stuff/broadcast-1337.bin -------------------------------------------------------------------------------- /development-stuff/dunst-ui.md: -------------------------------------------------------------------------------- 1 | # Dunstwolke™ User Interface 2 | 3 | - Unterstützt nur Standard-Widgets 4 | - [x] Button 5 | - [x] Label 6 | - [x] RadioButton 7 | - [x] CheckBox 8 | - [ ] TextBox 9 | - [ ] Picture (Bitmap-Grafik, Vektor-Grafik) 10 | - [ ] ListBox 11 | - [ ] ListBoxItem 12 | - [ ] TreeView 13 | - [ ] TreeItem 14 | - [ ] DataGrid 15 | - [ ] ComboBox 16 | - [ ] ScrollView 17 | - [x] Slider 18 | - [x] ProgressBar 19 | - [ ] NumberSpin 20 | - [x] Separator 21 | - [x] StackLayout 22 | - [x] DockLayout 23 | - [x] CanvasLayout 24 | - [x] GridLayout 25 | - [x] FlowLayout 26 | - [x] Spacer 27 | - [x] Panel 28 | - [x] TabPanel 29 | - Supported modale und nonmodale Dialoge/Kind-Fenster 30 | - Dialoge wie ein "Inventarfenster" können geöffnet werden 31 | - Dialoge sind immer floating 32 | - Layouts ermöglichen Bindings auf Listen 33 | - Angabe von Template-ID + List-Binding 34 | - Instanzen von Templates werden wiederverwendet (korrektes insert/remove-verhalten) 35 | - Widgets können Tastatur-Filter haben 36 | - Widget verschickt *alle* Tastatur-Events 37 | - Widget verschickt nur Accelerators (Hotkeys) 38 | - TODO: Globale Hotkey-Table? 39 | - TODO: Hotkey-Table per Widget? 40 | - Widgets haben Standard-Hotkeys 41 | - Clipboard: *Ctrl-C*, *Ctrl-V*, *Ctrl-X* 42 | - Selektion: *Ctrl-A*, Shift+Pfeiltaste, Ctrl+Pfeiltaste 43 | - Tab-Navigation: *Tab*, *Shift-Tab* 44 | - Ist 100% deklarativ 45 | - Templates erlauben 46 | - Widgets können nur über Templates+Listen dynamisch erstellt/gelöscht werden 47 | - Nutzt eine Art MVVM-Pattern 48 | - Widgets können auf manche Properties einen Wert binden 49 | - Bindung kann ToWidget, FromWidget, Bidirektional sein 50 | - Als Werte werden nur `object`, `number`, `string`, `bool` sowie `list` unterstützt 51 | - JSON-ähnliches Format 52 | - Anwendung kann beliebige Sub-Bäume der Datenstruktur aktualisieren 53 | - Aktualisierung einer Eigenschaft → Regeneration und Refresh der davon abhängigen UI 54 | - Objekte benötigen eine eindeutige ID für Callbacks 55 | - Bindbare Properties 56 | - Text (`string`) 57 | - Value (`number`) 58 | - Minimum (`number`) 59 | - Maximum (`number`) 60 | - Children (`list`) 61 | - Kann auch Remote benutzt werden 62 | - Voll asynchrones Interface 63 | - Benutzt nur "Message Passing" als Interface 64 | - Kann Resourcen cachen 65 | - UI besteht aus Beschreibungsdaten, alle Resouren also im Voraus bekannt 66 | - Resourcen haben eine ID 67 | - Anwendung überträgt Resourcen-Liste + Hashes 68 | - Falls Hash gleich, kann Resource wiederverwendet werden 69 | → reduziert bandbreite 70 | - Rendering sehr schlicht 71 | - Einfarbige Linien + Flächen 72 | - Vektorgrafiken für Icons 73 | - Drei Schriftarten 74 | - Monospace 75 | - Serif 76 | - Sans 77 | -------------------------------------------------------------------------------- /development-stuff/dunstfs-dataset.sql: -------------------------------------------------------------------------------- 1 | -- Demo data set for DunstFS (without actual file backings) 2 | ----- 3 | 4 | -- CREATE TABLE IF NOT EXISTS Files ( 5 | -- uuid TEXT PRIMARY KEY NOT NULL, -- a UUIDv4 that is used as a unique identifier 6 | -- user_name TEXT NULL -- A text that was given by the user as a human-readable name 7 | -- ); 8 | -- 9 | -- CREATE TABLE IF NOT EXISTS DataSets ( 10 | -- checksum TEXT PRIMARY KEY NOT NULL, -- Hash of the file contents (Blake3, 256 bit, no initial key) 11 | -- mime_type TEXT NOT NULL, -- The mime type 12 | -- creation_date TEXT NOT NULL -- ISO timestamp of when the data set was created 13 | -- ); 14 | -- 15 | -- CREATE TABLE IF NOT EXISTS Revisions( 16 | -- file TEXT PRIMARY KEY NOT NULL, -- the file for which this revision was created 17 | -- revision INT NOT NULL, -- Ever-increasing revision number of the file. The biggest number is the latest revision. 18 | -- dataset TEXT NOT NULL, -- Key into the dataset table for which file to reference 19 | -- UNIQUE (file, revision), 20 | -- FOREIGN KEY (file) REFERENCES Files (uuid), 21 | -- FOREIGN KEY (dataset) REFERENCES DataSets (checksum) 22 | -- ); 23 | -- 24 | -- CREATE TABLE IF NOT EXISTS FileTags ( 25 | -- file TEXT NOT NULL, -- The key of the file 26 | -- tag TEXT NOT NULL, -- The tag name 27 | -- UNIQUE(file,tag), 28 | -- FOREIGN KEY (file) REFERENCES Files(uuid) 29 | -- ); 30 | -- 31 | -- CREATE VIEW IF NOT EXISTS Tags AS SELECT tag, COUNT(file) AS count FROM FileTags GROUP BY tag 32 | 33 | INSERT INTO Files (uuid, user_name, last_change) VALUES 34 | ('0656707d-bf7a-45ef-ad08-aab956bcbb5e ', NULL, CURRENT_TIMESTAMP), 35 | ('17f2bde8-9d71-4ceb-93f9-1cb63cc4633e', 'Das kleine Handbuch für angehende Raumfahrer', CURRENT_TIMESTAMP), 36 | ('f055ec50-5570-4f9b-9b88-671b81cd62cf', 'Donnerwetter', CURRENT_TIMESTAMP); 37 | 38 | INSERT INTO DataSets(checksum, mime_type, creation_date) VALUES 39 | ('59ad4c00ede9148cfe756f2d3595b4e53169f9d8cc609f99b0e5ec117995f024', 'application/octet-stream', '2021-08-28 13:53:59'), 40 | ('465c05d4e301b9e05bf78b3637bd9515729f5c0fc390ca62c6f4761a7213c946', 'application/pdf', '2021-08-28 13:53:59'), 41 | ('eea0a4be265a73c8b68ab8ba610265ed7be0d18684d7ff99a2e0db36f278bbb7', 'audio/ogg', '2021-08-28 13:53:59'); 42 | 43 | INSERT INTO Revisions(file, revision, dataset) VALUES 44 | ('0656707d-bf7a-45ef-ad08-aab956bcbb5e', 1, '59ad4c00ede9148cfe756f2d3595b4e53169f9d8cc609f99b0e5ec117995f024'), 45 | ('17f2bde8-9d71-4ceb-93f9-1cb63cc4633e', 1, '465c05d4e301b9e05bf78b3637bd9515729f5c0fc390ca62c6f4761a7213c946'), 46 | ('f055ec50-5570-4f9b-9b88-671b81cd62cf', 1, 'eea0a4be265a73c8b68ab8ba610265ed7be0d18684d7ff99a2e0db36f278bbb7'); 47 | 48 | INSERT INTO FileTags (file, tag) VALUES 49 | ('0656707d-bf7a-45ef-ad08-aab956bcbb5e', 'keepass'), 50 | ('0656707d-bf7a-45ef-ad08-aab956bcbb5e', 'passwörter'), 51 | ('17f2bde8-9d71-4ceb-93f9-1cb63cc4633e', 'Urs Ganse'), 52 | ('17f2bde8-9d71-4ceb-93f9-1cb63cc4633e', 'raumfahrt'), 53 | ('17f2bde8-9d71-4ceb-93f9-1cb63cc4633e', 'Bergita Ganse'), 54 | ('f055ec50-5570-4f9b-9b88-671b81cd62cf', 'unknown artist'), 55 | ('f055ec50-5570-4f9b-9b88-671b81cd62cf', 'demoscene'); -------------------------------------------------------------------------------- /development-stuff/example-list.txt: -------------------------------------------------------------------------------- 1 | # Example Projects 2 | 3 | Each project includes a set of challenges this project 4 | solves. 5 | 6 | - Calculator 7 | - Basic UI Layout 8 | - Forward/Backward Communication 9 | - Adressbook 10 | - Complex / Grid Layout 11 | - Text Editor 12 | - Text Editing 13 | - Scrolling 14 | - Media Player 15 | - Icons Rendering 16 | - Dynamic image updates 17 | - Chat Application 18 | - Dynamic lists 19 | - Lots of status change 20 | - Rich text 21 | - Settings Menu / Game Menu 22 | - Special Styles 23 | - Transitions 24 | - Animations 25 | - Transparent UI 26 | - Foreign-Context rendering 27 | -------------------------------------------------------------------------------- /development-stuff/properties.txt: -------------------------------------------------------------------------------- 1 | 2 | generic style/properties: 3 | {,min-,max-}width : length 4 | {,min-,max-}height : length 5 | margin: : length 6 | padding: : length 7 | border-color : color 8 | background-color : color 9 | vertical-align : align, 10 | horizontal-align : align, 11 | 12 | button: 13 | on-click : callback 14 | 15 | label: 16 | text : binding(text) 17 | font-face : fontface 18 | font-size : length 19 | font-color : color 20 | 21 | radiobutton: 22 | on-click : callback(bool) 23 | on-select : callback 24 | is-selected : binding(bool) 25 | 26 | checkbox: 27 | on-click : callback(bool) 28 | is-selected : binding(bool) 29 | 30 | textbox: 31 | multi-line : bool 32 | text : binding(text) 33 | font-face : fontface 34 | font-size : length 35 | font-color : color 36 | on-input : callback(string) 37 | on-leave : callback(string) 38 | 39 | picture: 40 | image : resource(bitmap,vectors) 41 | on-click : callback(x,y,id) 42 | 43 | drawing: 44 | image : binding(vectors) 45 | on-click : callback(x,y,id) 46 | 47 | listbox: 48 | items : binding(list) 49 | item-template : resource(template) 50 | 51 | combobox: 52 | items : binding(list) 53 | item-text : binding(string) 54 | font-face : fontface 55 | font-size : length 56 | font-color : color 57 | 58 | datagrid: 59 | ??? 60 | - row-template? 61 | - cell-template? 62 | - selector of templates? 63 | 64 | scroll-view: 65 | items : binding(list) 66 | item-template : resource(template) 67 | 68 | slider: 69 | value : binding(number) 70 | minimum : binding(number) 71 | maximum : binding(number) 72 | 73 | progress-bar: 74 | value : binding(number) 75 | minimum : binding(number) 76 | maximum : binding(number) 77 | 78 | number-spin: 79 | value : binding(number) 80 | minimum : binding(number) 81 | maximum : binding(number) 82 | step-size : number 83 | digits : number 84 | font-face : fontface 85 | font-size : length 86 | font-color : color 87 | 88 | toolbar: 89 | – 90 | 91 | 92 | -------------------------------------------------------------------------------- /development-stuff/todo.txt: -------------------------------------------------------------------------------- 1 | - zg core rewrite 2 | - plseeaudio volume cntrol 3 | - media server 4 | - sqlite3 binding 5 | - mp3/ogg playback 6 | - dunstblick interface 7 | -------------------------------------------------------------------------------- /development-stuff/wasm-apps.md: -------------------------------------------------------------------------------- 1 | # WebAssembly Applications 2 | 3 | ## Goals 4 | 5 | - Run apps in a controlled environment 6 | - Allow migration of apps from one device to another 7 | - Platform-independent binary format (compile once, run everywhere) 8 | - Provide the same API on all platforms and devices. 9 | - Run on low-memory devices with only one Wasm page (64kib) 10 | 11 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | site/ 2 | data.js 3 | index.html 4 | main.js 5 | -------------------------------------------------------------------------------- /docs/mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: Dunstwolke 2 | site_url: https://dunstwolke.org/ 3 | repo_url: https://github.com/Dunstwolke/core 4 | edit_uri: null 5 | docs_dir: src 6 | 7 | nav: 8 | - Home: index.md 9 | - Fabric: dunstfabric.md 10 | - Dunstblick: 11 | - 'About': dunstblick.md 12 | - 'Layout Engine': dunstblick/layout-engine.md 13 | - 'Layout Language': dunstblick/layout-language.md 14 | - 'Protocol': dunstblick/protocol.md 15 | - 'Data Types': dunstblick/types.md 16 | - 'Widgets': dunstblick/widgets.md 17 | - Networking: dunstnetz.md 18 | - Filesystem: dunstfs.md 19 | theme: 20 | name: mkdocs 21 | nav_style: light 22 | -------------------------------------------------------------------------------- /docs/src/dunstblick.md: -------------------------------------------------------------------------------- 1 | # Dunstblick 2 | 3 | A graphical user interface with remote display capabilities. 4 | 5 | ## Concept 6 | 7 | ## Design Goals 8 | 9 | - Simple API 10 | - Declarative approach 11 | - Automatic layouting 12 | - Feasible to implement on a microcontroller 13 | - Low memory footprint 14 | - Reduced graphic fidelity should not hurt the user experience 15 | - Consistent look-and-feel 16 | 17 | ## Dunstblick URI Scheme 18 | 19 | The current URL scheme for dunstblick services is this: 20 | ``` 21 | dunstblick://host.name:port/ 22 | ``` 23 | The path must be either empty or `/`. 24 | 25 | ## Further Reading 26 | 27 | - [Protocol](dunstblick/protocol.md) 28 | - [Layout Engine](dunstblick/layout-engine.md) 29 | - [Layout Language](dunstblick/layout-language.md) 30 | - [Widgets](dunstblick/widgets.md) 31 | -------------------------------------------------------------------------------- /docs/src/dunstblick/layout-engine.md: -------------------------------------------------------------------------------- 1 | # Dunstblick Layouting Engine 2 | 3 | Description of the layouting engine of [Dunstblick](../dunstblick.md) 4 | 5 | > TODO: Write this page -------------------------------------------------------------------------------- /docs/src/dunstblick/layout-language.md: -------------------------------------------------------------------------------- 1 | # Dunstblick Layout Language 2 | 3 | Description of the [Dunstblick](../dunstblick.md) Layout Language 4 | 5 | > TODO: Write this page 6 | 7 | ## Example 8 | 9 | ```dll 10 | Picture 11 | { 12 | margins: 0; 13 | image: resource("wallpaper"); 14 | image-scaling: cover; 15 | DockLayout 16 | { 17 | Label 18 | { 19 | dock-site: bottom; 20 | text: bind("current-artist"); 21 | } 22 | Label 23 | { 24 | dock-site: bottom; 25 | text: bind("current-song"); 26 | } 27 | Picture 28 | { 29 | image: bind("current-albumart"); 30 | image-scaling: zoom; 31 | vertical-alignment: middle; 32 | horizontal-alignment: center; 33 | } 34 | } 35 | } 36 | ``` -------------------------------------------------------------------------------- /docs/src/dunstblick/protocol.md: -------------------------------------------------------------------------------- 1 | # Dunstblick Protocol Definition 2 | 3 | The document uses the following special terms: 4 | - *display client*: A program or device the user can use to interact with the system 5 | - *application* or *provider*: A program that provices a user interface, this can be operated with a *display client* 6 | - *user*: A person that wants to interact with an *application* 7 | 8 | ## Display Server Connection 9 | 10 | The following diagram shows the rough structure of the initial communication 11 | handshake: 12 | 13 | ![Sequence Diagram](../img/dunstblick-handshake.svg) 14 | 15 | ### Discovery Protocol 16 | 17 | > TODO: Continue dunstblick discovery protocol documentation 18 | 19 | ### Display Connection 20 | 21 | The display client connects to the previoulsy announced TCP port and sends the following packet: 22 | 23 | ``` 24 | magic : [4]u8 = { 0x21, 0x06, 0xc1, 0x62 } 25 | protocol_version : u16 = 1 26 | name : [32]u8 27 | password : [32]u8 28 | capabilities : u32 29 | screen_size_x : u16 30 | screen_size_y : u16 31 | ``` 32 | 33 | - *magic* and *protocol_version* are fixed values that must have the values above. 34 | - *name* is the zero-padded string of the display client. This can either be the device 35 | name, application name or another name that may help the user identify the display client. 36 | - *password* is a zero-padded connection password that may be used to authenticate the user 37 | to the application. 38 | - *capabilities* is a bit mask that specifies what features are available on the dispay client. 39 | - *screen_size_x* and *screen_size_y* define the initial size of the screen in pixels assuming that the screen has 96 DPI. 40 | 41 | > TODO: Continue dunstblick protocol documentation -------------------------------------------------------------------------------- /docs/src/dunstfabric.md: -------------------------------------------------------------------------------- 1 | # DunstFabric 2 | 3 | All connected Dunstwolke devices will form a common fabric which allows IPC calls between different applications, even if those run on different devices. 4 | 5 | Each device runs a central fabric daemon that will perform discovery of known devices and will do all dispatching of system calls. The fabric daemon is also able to spawn applications. 6 | 7 | Applications are written in [Wasm](https://webassembly.org/) or in a native language. Wasm applications can be transferred seamlessly between devices, while native applications are tied to the host machine. 8 | 9 | ## Application Design 10 | 11 | Applications have a entry point that will set up the application, but in contrast to other operating systems, the entry point will return to the OS. Now when events happen, the applications will be called with a set of events that lead to the wakeup of the application. The purpose of the entry point is only initialization and request of events. 12 | 13 | ## Syscall Design 14 | 15 | The following sections describe the rough ideas of a system call design for the Dunstwolke Fabric. 16 | 17 | ### Fabric Management 18 | 19 | - `listKnownDevices() []Device` lists all devices in the current fabric 20 | - `listAvailableDevices() []Device` lists all devices that are available at the moment 21 | - `removeDevice(Device) void` removes a device from the fabric 22 | - `addDevice() Device` pairs a new device to the fabric 23 | 24 | ### Process Management 25 | 26 | - `listProcesses() []{ Pid, Device }` lists all running processes 27 | - `listProcesses(Device) []Pid` lists all running processes for a device 28 | - `getProcessStats(Pid) ?struct { … }` returns the statistics for a process if any 29 | - `kill(Pid) void` kills a given process 30 | - `spawn(File, []String) Pid` spawns a new process with the given args and file 31 | - `moveProcess(Pid, Device) void` moves a process to a new device 32 | 33 | ### IPC 34 | 35 | The IPC of the fabric will work from applications to other applications targeting a certain subsystem identified by a Guid. 36 | 37 | - `createIpcService(Guid, display_name) ServiceHandle` will make this application provide a new IPC subsystem 38 | - `destroyIpcService(ServiceHandle) void` will shut down a previously established IPC subsystem 39 | - `getIpcMessage(ServiceHandle, blocking, *Pid, *[]u8) bool` will receive a IPC message 40 | - `sendIpcMessage(Guid, ?Pid, []u8)` will send a message to the service `Guid` with an optional target application 41 | 42 | > TODO: How to manage IPC responses? A non-Service might want to have answer to things 43 | 44 | ### Network 45 | 46 | Network system calls operate on the ip address of the fabric. Each fabric will have a one or more outbound ip address which are routed via a single device. An application creating the socket for an ip does not have to run on the same device that has this ip. 47 | 48 | - `createUdpSock(ip, port) UdpSocketHandle` creates a new udp socket bound to the given port 49 | - `closeUdpSock(UdpSocketHandle) void` destroys a previously created socket 50 | - `sendTo(UdpSocketHandle, ip, port, []u8) usize` sends data to a udp address 51 | - `receiveFrom(UdpSocketHandle, *ip, *port, *[]u8) usize` reads data from the udp port 52 | - `getSocketName(UdpSocketHandle, *ip, *port) void` 53 | -------------------------------------------------------------------------------- /docs/src/dunstfs.md: -------------------------------------------------------------------------------- 1 | # Dunstfile 2 | 3 | A decentralized file system that is more similar to a typical [Booru](https://tvtropes.org/pmwiki/pmwiki.php/Main/ImageBooru) than to a classic file system. 4 | 5 | ## Concept 6 | 7 | Each file is identified by a [unique id](https://en.wikipedia.org/wiki/Universally_unique_identifier) and has a set of tags. Files are opened via their ID and not via a file path. 8 | 9 | Tags are used to identify files quickly by the user and are free-form text input. Some example tags might be `Vacation`, `Summer '21`, `Bachelor Thesis`, ... 10 | 11 | There are some mandatory (and mostly auto-created) tags though: 12 | 13 | - The time tag `YYYY/MM/DD` to identify the file creation date 14 | - The [media type](https://en.wikipedia.org/wiki/Media_type) in the format defined in [RFC 2045](https://datatracker.ietf.org/doc/html/rfc2045), for example `text/plain` 15 | - A optional tag `executable` for Dunstwolke applications 16 | - A optional tag `transcendent` for files that will be replicated between all devices 17 | - A optional tag `local` for files that will never be replicated or transferred between devices 18 | 19 | Files are stored locally on devices, but are accessible from other devices via [Dunstnetz](dunstnetz.md). Files can exist on multiple devices at the same time and will be synchronized automatically between all available devices. 20 | 1 -------------------------------------------------------------------------------- /docs/src/dunstnetz.md: -------------------------------------------------------------------------------- 1 | # Dunstnetz 2 | 3 | A network protocol for decentralized communication 4 | 5 | > TODO: Document the dunstnetz concept -------------------------------------------------------------------------------- /docs/src/index.md: -------------------------------------------------------------------------------- 1 | # The Dunstwolke Project 2 | 3 | ## Introduction 4 | 5 | Dunstwolke is a project that tries another approach to a *personal cloud*. 6 | The core idea is to have a decentralized, ad-hoc computer network that 7 | connects several services to a nice personal experience. 8 | 9 | What started the project was the following thought: 10 | 11 | > Why should my wireless headset be connected uniquely to my laptop / mobile phone? 12 | > If i could connect the headset to all of my personal devices and just mix the audio 13 | > streams on the headset… 14 | > 15 | > I would somehome have to interface with the headset… 16 | > 17 | > And why shouldn't the headset itself play the music and only read the mp3 file 18 | > from a device with storage in local reach? 19 | 20 | These thoughts lead to a more complex idea of a system that can access and control 21 | several devices connected into a decentralized network with storage, remote user 22 | interfaces and *floating* applications. 23 | 24 | ## Prototypes and Concepts 25 | 26 | Right now most of the Dunstwolke Project is in early prototype stage or only exists 27 | as a concept: 28 | 29 | - [Dunstblick](dunstblick.md) 30 | - [Dunstnetz](dunstnetz.md) 31 | - [DunstFS](dunstfs.md) 32 | 33 | ## Source Code 34 | 35 | The project is written in Zig and is available on GitHub: 36 | 37 | https://github.com/Dunstwolke/core 38 | 39 | ## The Name 40 | 41 | The name *Dunstwolke* is a portmanteau of the german *Dunstkreis* (a sphere of influence) and *Wolke* (cloud). 42 | 43 | Also *Dunst* itself is translated as haze, so it also fits the cloud topic. -------------------------------------------------------------------------------- /extensions/dfs-chrome/background.js: -------------------------------------------------------------------------------- 1 | let color = '#3aa757'; 2 | 3 | chrome.runtime.onInstalled.addListener(() => { 4 | chrome.storage.sync.set({endpoint : "ws://fs.dunstwolke.org/ws"}); 5 | }); 6 | -------------------------------------------------------------------------------- /extensions/dfs-chrome/daemon.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | websocat --server-mode 127.0.42.1:8445 | while read -r line ; do 4 | echo "received msg:" 5 | echo ${line} 6 | case $(echo "${line}" | jq '.cmd' -r) in 7 | store) 8 | url="$(echo "${line}" | jq '.url' -r)" 9 | title="$(echo "${line}" | jq '.title' -r)" 10 | tags="$(echo "${line}" | jq '.tags[]' -r)" 11 | tempfile="/tmp/dfs-temp-download" 12 | # echo "url =${url}" 13 | # echo "title =${title}" 14 | # echo "tags =${tags}" 15 | 16 | if curl --silent -o "${tempfile}" "${url}" ; then 17 | mime="$(file --mime-type --brief "${tempfile}")" 18 | 19 | echo "${tags}" | xargs --delimiter="\n" dfs add --mime "${mime}" --name "${title}" "${tempfile}" 20 | else 21 | echo "failed to download ${url}" 22 | fi 23 | ;; 24 | *) 25 | echo "unknown cmd" 26 | ;; 27 | esac 28 | done -------------------------------------------------------------------------------- /extensions/dfs-chrome/images/dfs-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/extensions/dfs-chrome/images/dfs-128.png -------------------------------------------------------------------------------- /extensions/dfs-chrome/images/dfs-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/extensions/dfs-chrome/images/dfs-16.png -------------------------------------------------------------------------------- /extensions/dfs-chrome/images/dfs-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/extensions/dfs-chrome/images/dfs-32.png -------------------------------------------------------------------------------- /extensions/dfs-chrome/images/dfs-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/extensions/dfs-chrome/images/dfs-48.png -------------------------------------------------------------------------------- /extensions/dfs-chrome/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "DunstFS Utilities", 3 | "description": "Quickly safe links into your DunstFS file system.", 4 | "version": "1.0", 5 | "manifest_version": 3, 6 | "options_page": "options.html", 7 | "background": { 8 | "service_worker": "background.js" 9 | }, 10 | "permissions": ["storage", "activeTab", "scripting"], 11 | "action": { 12 | "default_popup": "popup.html", 13 | "default_icon": { 14 | "16": "/images/dfs-16.png", 15 | "32": "/images/dfs-32.png", 16 | "48": "/images/dfs-48.png", 17 | "128": "/images/dfs-128.png" 18 | } 19 | }, 20 | "icons": { 21 | "16": "/images/dfs-16.png", 22 | "32": "/images/dfs-32.png", 23 | "48": "/images/dfs-48.png", 24 | "128": "/images/dfs-128.png" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /extensions/dfs-chrome/options.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
DunstFS End Point:
16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /extensions/dfs-chrome/options.js: -------------------------------------------------------------------------------- 1 | let input_endPoint = document.getElementById("endpoint"); 2 | 3 | chrome.storage.sync.get("endpoint", ({endpoint}) => { 4 | input_endPoint.value = endpoint; 5 | }); 6 | 7 | input_endPoint.addEventListener('input', () => { 8 | chrome.storage.sync.set({ 9 | endpoint : input_endPoint.value 10 | }); 11 | }); -------------------------------------------------------------------------------- /extensions/dfs-chrome/popup.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | input[type="text"] { 6 | width: 100%; 7 | } 8 | 9 | button { 10 | width: 4rem; 11 | height: 4rem; 12 | display: block; 13 | margin: 0.5rem; 14 | } 15 | 16 | h1 { 17 | margin: 0; 18 | text-align: center; 19 | } 20 | 21 | textarea { 22 | font-family: monospace; 23 | resize: none; 24 | } 25 | 26 | #overlay { 27 | position: fixed; 28 | top: 0; 29 | left: 0; 30 | width: 100%; 31 | height: 100%; 32 | background-color: #FFFFFFCC; 33 | display: flex; 34 | justify-content: center; 35 | align-items: center; 36 | } 37 | 38 | #overlay.hidden { 39 | display: none; 40 | } -------------------------------------------------------------------------------- /extensions/dfs-chrome/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |

DunstFS QuickSave

10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
Title:
Tags:
21 |
22 |

Connecting to DunstFS...

23 |
24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /extensions/dfs-chrome/popup.js: -------------------------------------------------------------------------------- 1 | let overlay = document.getElementById("overlay"); 2 | let overlay_text = document.getElementById("overlay-text"); 3 | let input_title = document.getElementById("title"); 4 | let input_taglist = document.getElementById("taglist"); 5 | let input_saveButton = document.getElementById("saveButton"); 6 | 7 | function setPageBackgroundColor() { 8 | chrome.storage.sync.get("color", ({color}) => { 9 | document.body.style.backgroundColor = color; 10 | }); 11 | } 12 | 13 | let global_ws = null; 14 | 15 | async function init() { 16 | 17 | let [tab] = await chrome.tabs.query({active : true, currentWindow : true}); 18 | 19 | chrome.storage.sync.get("endpoint", ({endpoint}) => { 20 | var ws = new WebSocket(endpoint, "dfs"); 21 | 22 | let is_connected = false 23 | 24 | ws.addEventListener('close', (close) => { 25 | console.log("websocket-close", close); 26 | if (is_connected) { 27 | overlay_text.innerText = "Connection lost!"; 28 | } else { 29 | overlay_text.innerText = "Service not available!"; 30 | } 31 | is_connected = false; 32 | overlay.classList.remove("hidden"); 33 | global_ws = null; 34 | }); 35 | ws.addEventListener('error', (error) => { 36 | console.log("websocket-error", error); 37 | }); 38 | ws.addEventListener('message', (msg) => { 39 | console.log("websocket-message", msg); 40 | }); 41 | ws.addEventListener('open', (open) => { 42 | console.log("websocket-open", open); 43 | overlay.classList.add("hidden"); 44 | overlay_text.innerText = "Connected!"; 45 | is_connected = true; 46 | global_ws = ws; 47 | }); 48 | }); 49 | 50 | console.log(tab); 51 | 52 | input_title.value = tab.title; 53 | 54 | input_saveButton.addEventListener("click", async () => { 55 | if (global_ws != null) { 56 | let tag_src = input_taglist.value; 57 | 58 | let tags = tag_src.split(' ').map(s => s.trim(",")).filter(x => x != ""); 59 | 60 | global_ws.send(JSON.stringify({ 61 | cmd : "store", 62 | url : tab.url, 63 | title : input_title.value, 64 | tags : tags, 65 | })); 66 | } 67 | 68 | // chrome.scripting.executeScript({ 69 | // target : {tabId : tab.id}, 70 | // function : setPageBackgroundColor, 71 | // }); 72 | }); 73 | } 74 | 75 | init(); 76 | -------------------------------------------------------------------------------- /reference/bcb-ui.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/reference/bcb-ui.xcf -------------------------------------------------------------------------------- /reference/vision-irc.txt: -------------------------------------------------------------------------------- 1 | ikskuh: I'm not sure I'm grasping the vision of dunstblick, how do you plan to use this? 2 | aaah 3 | are you okay with spoilers for my next showtime talk? :D 4 | sure :D 5 | i figured that dunstblick may be the right project for a talk 6 | i create a lot of self-made IoT devices 7 | small scale (lpc1786 or smaller) or large scale (RPI, ...) 8 | also i have a lot of services deployed on several machines 9 | my vision for dunstblick is to access all those systems with a very resource-gentle UI system 10 | web stack is too bloatet imho for that, it also requires you to write a lot of web servers and html/js frontends 11 | neat, this is making a lot more sense with that use-case in mind 12 | so the idea of dunstblick is that you can easily discover applications in your local network and attach a interface to them 13 | for example: i have a rack with RGB LEDs built-in 14 | and i want to set the color/animation for those 15 | open up dunstblick, attach to "LED Control", change some colors, done 16 | same workflow for everything else 17 | sounds quite handy 18 | the network-controllable power board? sure thing :D 19 | attach, flip some checkboxes, done :D 20 | what all do your IoT devices do? 21 | right now, not that much :D 22 | i have these two i told you about, but i also have my stereo as IoT 23 | it's just an RPI+Amp 24 | nice 25 | and i would like to control the media playing there not via SSH anymore :D 26 | another example: you could make a generic pulseaudio volume control 27 | throw that on all your machines and you can now control volume of your computer with your smartphone 28 | have a weather service sampling data from your local weather station? covered :D -------------------------------------------------------------------------------- /reference/windows-xp-ui.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/reference/windows-xp-ui.xcf -------------------------------------------------------------------------------- /src/apps/wasm-demo.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | export fn app_init(value: i32) i32 { 4 | return value; 5 | } 6 | 7 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { 8 | _ = message; 9 | _ = stack_trace; 10 | while (true) {} 11 | } 12 | 13 | pub fn main() void { 14 | std.mem.doNotOptimizeAway(app_init); 15 | } 16 | 17 | // zig build-exe -target wasm32-freestanding-none -O ReleaseSmall -fno-compiler-rt src/apps/wasm-demo.zig && wasm2wat wasm-demo.wasm > wasm-demo.wat 18 | -------------------------------------------------------------------------------- /src/dunst-environment/main.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const known_folders = @import("known-folders"); 3 | const logger = std.log.scoped(.dunst_environment); 4 | 5 | pub const RootFolder = enum { 6 | /// Used by DunstFS filesystem to store datasets and metadata 7 | filesystem, 8 | 9 | /// Operating system applications are stored here 10 | bin, 11 | 12 | /// This folder stores configuration files or folders for Dunstwolke services 13 | config, 14 | }; 15 | 16 | pub fn openRoot(folder: RootFolder, options: std.fs.Dir.OpenDirOptions) !std.fs.Dir { 17 | var data_dir = try openDunstRoot(); 18 | defer data_dir.close(); 19 | 20 | return data_dir.makeOpenPath(@tagName(folder), options) catch |err| { 21 | logger.err("Could not open the Dunstwolke directory '/{s}': {s}", .{ @tagName(folder), @errorName(err) }); 22 | return err; 23 | }; 24 | } 25 | 26 | fn openDunstRoot() !std.fs.Dir { 27 | var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); 28 | defer arena.deinit(); 29 | 30 | if (std.process.getEnvVarOwned(arena.allocator(), "DUNSTWOLKE_ROOT_FS")) |dunstwolke_root_fs| { 31 | if (std.mem.trim(u8, dunstwolke_root_fs, " \r\n\t").len > 0) { 32 | if (!std.fs.path.isAbsolute(dunstwolke_root_fs)) { 33 | logger.err("Environment variable DUNSTWOLKE_ROOT_FS must be an absolute path!", .{}); 34 | return error.InvalidEnvVariable; 35 | } 36 | return try std.fs.openDirAbsolute(dunstwolke_root_fs, .{}); 37 | } 38 | } else |_| { 39 | // ignore the error 40 | } 41 | 42 | const maybe_data_dir = known_folders.open(arena.allocator(), .data, .{}) catch |err| { 43 | logger.err(" nCouldot open the data directory: {s}", .{@errorName(err)}); 44 | return err; 45 | }; 46 | var data_dir = maybe_data_dir orelse { 47 | logger.err("Could not find the data directory!", .{}); 48 | return error.FileNotFound; 49 | }; 50 | defer data_dir.close(); 51 | 52 | return data_dir.makeOpenPath("dunstwolke", .{}) catch |err| { 53 | logger.err("Could not open the Dunstwolke root directory: {s}", .{@errorName(err)}); 54 | return err; 55 | }; 56 | } 57 | -------------------------------------------------------------------------------- /src/dunstblick-compiler/Compiler.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | const Self = @This(); 4 | 5 | pub const Location = @import("Location.zig"); 6 | pub const Tokenizer = @import("Tokenizer.zig"); 7 | pub const Database = @import("Database.zig"); 8 | pub const Parser = @import("Parser.zig"); 9 | pub const ErrorCollection = @import("ErrorCollection.zig"); 10 | 11 | allocator: std.mem.Allocator, 12 | database: *Database, 13 | 14 | errors: ErrorCollection, 15 | 16 | pub fn init(allocator: std.mem.Allocator, database: *Database) Self { 17 | return Self{ 18 | .allocator = allocator, 19 | .database = database, 20 | .errors = ErrorCollection.init(allocator), 21 | }; 22 | } 23 | pub fn deinit(self: *Self) void { 24 | self.errors.deinit(); 25 | self.* = undefined; 26 | } 27 | 28 | pub fn compile(self: *Self, reader: anytype, writer: anytype) !void { 29 | var input_src = std.ArrayList(u8).init(self.allocator); 30 | defer input_src.deinit(); 31 | 32 | try reader.readAllArrayList(&input_src, 4 << 20); 33 | 34 | var tokenIterator = Tokenizer.init(input_src.items); 35 | 36 | var parser = Parser{ 37 | .allocator = self.allocator, 38 | .database = self.database, 39 | 40 | .errors = &self.errors, 41 | .tokens = &tokenIterator, 42 | }; 43 | 44 | parser.parseFile(writer) catch |err| { 45 | try self.errors.add(tokenIterator.location, "syntax error: {s}", .{ 46 | err, 47 | }); 48 | return err; 49 | }; 50 | } 51 | 52 | pub fn getErrors(self: Self) []const ErrorCollection.CompileError { 53 | return self.errors.list.items; 54 | } 55 | -------------------------------------------------------------------------------- /src/dunstblick-compiler/ErrorCollection.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | const Location = @import("Location.zig"); 4 | 5 | pub const CompileError = struct { 6 | where: Location, 7 | message: []const u8, 8 | 9 | pub fn format(value: @This(), fmt: []const u8, options: std.fmt.FormatOptions, stream: anytype) !void { 10 | _ = fmt; 11 | _ = options; 12 | try stream.print("{}: {s}", .{ 13 | value.where, 14 | value.message, 15 | }); 16 | } 17 | }; 18 | 19 | const Self = @This(); 20 | 21 | arena: std.heap.ArenaAllocator, 22 | list: std.ArrayList(CompileError), 23 | 24 | pub fn init(allocator: std.mem.Allocator) Self { 25 | return Self{ 26 | .arena = std.heap.ArenaAllocator.init(allocator), 27 | .list = std.ArrayList(CompileError).init(allocator), 28 | }; 29 | } 30 | 31 | pub fn deinit(self: *Self) void { 32 | self.arena.deinit(); 33 | self.list.deinit(); 34 | self.* = undefined; 35 | } 36 | 37 | pub fn add(self: *Self, where: Location, comptime fmt: []const u8, args: anytype) !void { 38 | const msg = try std.fmt.allocPrint(self.arena.allocator(), fmt, args); 39 | errdefer self.arena.allocator().free(msg); 40 | 41 | try self.list.append(CompileError{ 42 | .where = where, 43 | .message = msg, 44 | }); 45 | } 46 | -------------------------------------------------------------------------------- /src/dunstblick-compiler/Location.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | line: u32, 4 | column: u32, 5 | 6 | pub fn format(value: @This(), fmt: []const u8, options: std.fmt.FormatOptions, stream: anytype) !void { 7 | _ = fmt; 8 | _ = options; 9 | try stream.print("{d}:{d}", .{ 10 | value.line, 11 | value.column, 12 | }); 13 | } 14 | -------------------------------------------------------------------------------- /src/dunstblick-compiler/package.zig: -------------------------------------------------------------------------------- 1 | pub const Compiler = @import("Compiler.zig"); 2 | pub const Database = @import("Database.zig"); 3 | pub const Location = @import("Location.zig"); 4 | pub const ErrorCollection = @import("ErrorCollection.zig"); 5 | -------------------------------------------------------------------------------- /src/dunstblick-compiler/tests.zig: -------------------------------------------------------------------------------- 1 | test { 2 | _ = @import("Compiler.zig"); 3 | _ = @import("Database.zig"); 4 | _ = @import("Location.zig"); 5 | _ = @import("ErrorCollection.zig"); 6 | _ = @import("Parser.zig"); 7 | _ = @import("Tokenizer.zig"); 8 | } 9 | -------------------------------------------------------------------------------- /src/dunstblick-desktop/dunst-ui/Object.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const protocol = @import("dunstblick-protocol"); 3 | 4 | const logger = std.log.scoped(.dunstblick_object); 5 | 6 | const types = @import("types.zig"); 7 | 8 | const Value = types.Value; 9 | const ObjectList = types.ObjectList; 10 | 11 | const Object = @This(); 12 | 13 | allocator: std.mem.Allocator, 14 | id: protocol.ObjectID, 15 | properties: std.AutoArrayHashMapUnmanaged(protocol.PropertyName, Value), 16 | 17 | pub fn init(allocator: std.mem.Allocator, id: protocol.ObjectID) Object { 18 | return Object{ 19 | .id = id, 20 | .allocator = allocator, 21 | .properties = .{}, 22 | }; 23 | } 24 | 25 | pub fn deinit(self: *Object) void { 26 | { 27 | var it = self.properties.iterator(); 28 | while (it.next()) |entry| { 29 | entry.value_ptr.deinit(); 30 | } 31 | } 32 | self.properties.deinit(self.allocator); 33 | self.* = undefined; 34 | } 35 | 36 | /// Adds a property. If the property already exists, returns `error.AlreadyExists`. 37 | pub fn addProperty(self: *Object, name: protocol.PropertyName, value: Value) !void { 38 | const gop = try self.properties.getOrPut(self.allocator, name); 39 | if (gop.found_existing) 40 | return error.AlreadyExists; 41 | 42 | gop.value_ptr.* = value; 43 | } 44 | 45 | /// Adds a property. If the property already exists, overrides the previous value. 46 | pub fn setProperty(self: *Object, name: protocol.PropertyName, value: Value) !void { 47 | const gop = try self.properties.getOrPut(self.allocator, name); 48 | if (gop.found_existing) { 49 | gop.value_ptr.deinit(); 50 | } 51 | gop.value_ptr.* = value; 52 | } 53 | 54 | pub fn getProperty(self: *Object, name: protocol.PropertyName) ?*Value { 55 | if (self.properties.getEntry(name)) |entry| { 56 | return entry.value_ptr; 57 | } else { 58 | return null; 59 | } 60 | } 61 | 62 | fn getList(self: *Object, prop_name: protocol.PropertyName) !*ObjectList { 63 | if (self.properties.getEntry(prop_name)) |entry| { 64 | if (entry.value_ptr.* == .objectlist) { 65 | return &entry.value_ptr.objectlist; 66 | } else { 67 | return error.TypeMismatch; 68 | } 69 | } else { 70 | return error.PropertyNotFound; 71 | } 72 | } 73 | 74 | pub fn clear(self: *Object, prop_name: protocol.PropertyName) !void { 75 | const list = try self.getList(prop_name); 76 | list.shrinkRetainingCapacity(0); 77 | } 78 | 79 | pub fn insertRange(self: *Object, prop_name: protocol.PropertyName, index: usize, items: []const protocol.ObjectID) !void { 80 | const list = try self.getList(prop_name); 81 | _ = list; 82 | _ = prop_name; 83 | _ = index; 84 | _ = items; 85 | @panic("not implemented yet!"); 86 | } 87 | 88 | pub fn removeRange(self: *Object, prop_name: protocol.PropertyName, index: usize, count: usize) !void { 89 | const list = try self.getList(prop_name); 90 | _ = list; 91 | _ = prop_name; 92 | _ = index; 93 | _ = count; 94 | @panic("not implemented yet!"); 95 | } 96 | 97 | pub fn moveRange(self: *Object, prop_name: protocol.PropertyName, index_from: usize, index_to: usize, count: usize) !void { 98 | const list = try self.getList(prop_name); 99 | _ = list; 100 | _ = prop_name; 101 | _ = index_from; 102 | _ = index_to; 103 | _ = count; 104 | @panic("not implemented yet!"); 105 | } 106 | -------------------------------------------------------------------------------- /src/dunstblick-desktop/dunst-ui/types.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const protocol = @import("dunstblick-protocol"); 3 | 4 | pub const Object = @import("Object.zig"); 5 | pub const Value = protocol.Value; 6 | 7 | pub const ObjectList = protocol.ObjectList; 8 | pub const SizeList = protocol.SizeList; 9 | pub const String = protocol.String; 10 | -------------------------------------------------------------------------------- /src/dunstblick-desktop/gui/ApplicationDescription.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | const Self = @This(); 4 | const ApplicationInstance = @import("ApplicationInstance.zig"); 5 | 6 | pub const Interface = struct { 7 | pub const SpawnError = error{ IoError, OutOfMemory }; 8 | pub const DestroyError = error{Indestructible}; 9 | spawn: fn (*Self, std.mem.Allocator) SpawnError!*ApplicationInstance, 10 | destroy: fn (*Self) DestroyError!void, 11 | 12 | pub fn get(comptime T: type) *const @This() { 13 | return &struct { 14 | fn destroyFallback(self: *Self) DestroyError!void { 15 | _ = self; 16 | return DestroyError.Indestructible; 17 | } 18 | 19 | const vtable = Interface{ 20 | .spawn = T.spawn, 21 | .destroy = if (@hasDecl(T, "destroy")) T.destroy else destroyFallback, 22 | }; 23 | }.vtable; 24 | } 25 | }; 26 | 27 | pub const State = union(enum) { 28 | /// The app isn't available 29 | not_available, 30 | /// The app was there once, but is gone now. They user should delete it now 31 | gone, 32 | /// The app is ready to be started 33 | ready, 34 | }; 35 | 36 | /// The name of the application that is displayed 37 | display_name: [:0]const u8, 38 | 39 | /// If the application has a TVG icon, this field is not null and contains the 40 | /// application icon 41 | icon: ?[]const u8, 42 | 43 | /// The VTable for the application, provides methods for this 44 | vtable: *const Interface, 45 | 46 | state: State, 47 | 48 | /// Spawns a new instance of this application 49 | pub fn spawn(self: *Self, allocator: std.mem.Allocator) Interface.SpawnError!*ApplicationInstance { 50 | return try self.vtable.spawn(self, allocator); 51 | } 52 | 53 | /// Destroys this application description if possible. 54 | pub fn destroy(self: *Self) Interface.DestroyError!void { 55 | return try self.vtable.destroy(self); 56 | } 57 | -------------------------------------------------------------------------------- /src/dunstblick-desktop/gui/ApplicationInstance.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | const zerog = @import("zero-graphics"); 4 | 5 | const Self = @This(); 6 | const ApplicationDescription = @import("ApplicationDescription.zig"); 7 | 8 | const Size = zerog.Size; 9 | 10 | pub const Interface = struct { 11 | const GenericError = error{OutOfMemory}; 12 | 13 | pub const UpdateError = GenericError || error{IoError}; 14 | pub const ResizeError = GenericError; 15 | pub const RenderError = GenericError || zerog.Renderer2D.DrawError; 16 | pub const UiError = GenericError || error{IoError} || zerog.UserInterface.Builder.Error; 17 | 18 | update: ?fn (*Self, f32) UpdateError!void, 19 | processUserInterface: ?fn (*Self, zerog.Rectangle, zerog.UserInterface.Builder) UiError!void, 20 | resize: ?fn (*Self, size: Size) ResizeError!void, 21 | render: ?fn (*Self, zerog.Rectangle, *zerog.Renderer2D) RenderError!void, 22 | close: ?fn (*Self) void, 23 | deinit: fn (*Self) void, 24 | 25 | pub fn get(comptime T: type) *const @This() { 26 | return &struct { 27 | const vtable = Interface{ 28 | .update = if (@hasDecl(T, "update")) T.update else null, 29 | .resize = if (@hasDecl(T, "resize")) T.resize else null, 30 | .render = if (@hasDecl(T, "render")) T.render else null, 31 | .close = if (@hasDecl(T, "render")) T.close else null, 32 | .deinit = T.deinit, 33 | .processUserInterface = if (@hasDecl(T, "processUserInterface")) T.processUserInterface else null, 34 | }; 35 | }.vtable; 36 | } 37 | }; 38 | 39 | pub const Status = union(enum) { 40 | /// contains the current loading status as a string 41 | starting: []const u8, 42 | 43 | /// the application is ready to be interacted with 44 | running, 45 | 46 | /// the application was quit and should be freed by the 47 | /// desktop environment. Contains the exit reason. 48 | exited: []const u8, 49 | }; 50 | 51 | description: ApplicationDescription, 52 | vtable: *const Interface, 53 | status: Status = Status{ .starting = "Starting..." }, 54 | 55 | pub fn update(self: *Self, dt: f32) !void { 56 | std.debug.assert(self.status == .starting or self.status == .running); 57 | if (self.vtable.update) |fun| { 58 | try fun(self, dt); 59 | } 60 | } 61 | 62 | pub fn resize(self: *Self, size: Size) !void { 63 | std.debug.assert(self.status == .starting or self.status == .running); 64 | if (self.vtable.resize) |fun| { 65 | try fun(self, size); 66 | } 67 | } 68 | 69 | pub fn render(self: *Self, rectangle: zerog.Rectangle, target: *zerog.Renderer2D) !void { 70 | std.debug.assert(self.status == .running); 71 | if (self.vtable.render) |fun| { 72 | try fun(self, rectangle, target); 73 | } 74 | } 75 | 76 | pub fn processUserInterface(self: *Self, rectangle: zerog.Rectangle, builder: zerog.UserInterface.Builder) !void { 77 | std.debug.assert(self.status == .running); 78 | if (self.vtable.processUserInterface) |fun| { 79 | try fun(self, rectangle, builder); 80 | } 81 | } 82 | 83 | /// Requests the proper shutdown of the application and a transition to state `.exited`. 84 | /// Use this when the application should be closed. 85 | pub fn close(self: *Self) void { 86 | std.debug.assert(self.status == .starting or self.status == .running); 87 | if (self.vtable.close) |fun| { 88 | fun(self); 89 | } 90 | } 91 | 92 | /// Frees all resources of this instance. 93 | pub fn deinit(self: *Self) void { 94 | self.vtable.deinit(self); 95 | } 96 | -------------------------------------------------------------------------------- /src/dunstblick-desktop/gui/fonts/firasans-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/dunstblick-desktop/gui/fonts/firasans-regular.ttf -------------------------------------------------------------------------------- /src/dunstblick-desktop/gui/icons/application.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/dunstblick-desktop/gui/icons/application.tvg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/dunstblick-desktop/gui/icons/application.tvg -------------------------------------------------------------------------------- /src/dunstblick-desktop/gui/icons/archiver.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/dunstblick-desktop/gui/icons/archiver.tvg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/dunstblick-desktop/gui/icons/archiver.tvg -------------------------------------------------------------------------------- /src/dunstblick-desktop/gui/icons/calculator.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/dunstblick-desktop/gui/icons/calculator.tvg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/dunstblick-desktop/gui/icons/calculator.tvg -------------------------------------------------------------------------------- /src/dunstblick-desktop/gui/icons/mahjongg.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/dunstblick-desktop/gui/icons/mahjongg.tvg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/dunstblick-desktop/gui/icons/mahjongg.tvg -------------------------------------------------------------------------------- /src/dunstblick-desktop/gui/icons/notes.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/dunstblick-desktop/gui/icons/notes.tvg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/dunstblick-desktop/gui/icons/notes.tvg -------------------------------------------------------------------------------- /src/dunstblick-desktop/gui/icons/settings.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/dunstblick-desktop/gui/icons/settings.tvg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/dunstblick-desktop/gui/icons/settings.tvg -------------------------------------------------------------------------------- /src/dunstblick-desktop/gui/icons/text-editor.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/dunstblick-desktop/gui/icons/text-editor.tvg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/dunstblick-desktop/gui/icons/text-editor.tvg -------------------------------------------------------------------------------- /src/dunstblick-desktop/gui/icons/view-compact.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/dunstblick-desktop/gui/icons/view-compact.xcf -------------------------------------------------------------------------------- /src/dunstblick-desktop/gui/icons/web-browser.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/dunstblick-desktop/gui/icons/web-browser.tvg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/dunstblick-desktop/gui/icons/web-browser.tvg -------------------------------------------------------------------------------- /src/dunstblick-desktop/gui/icons/zig-mark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/dunstblick-desktop/gui/icons/zig-mark.tvg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/dunstblick-desktop/gui/icons/zig-mark.tvg -------------------------------------------------------------------------------- /src/dunstblick-protocol/decoder.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | usingnamespace @import("data-types.zig"); 4 | 5 | const ZigZagInt = @import("zigzagint.zig"); 6 | 7 | pub const Decoder = struct { 8 | const Self = @This(); 9 | 10 | source: []const u8, 11 | offset: usize, 12 | 13 | pub fn init(data: []const u8) Self { 14 | return Self{ 15 | .source = data, 16 | .offset = 0, 17 | }; 18 | } 19 | 20 | pub fn readByte(self: *Self) !u8 { 21 | if (self.offset >= self.source.len) 22 | return error.EndOfStream; 23 | const value = self.source[self.offset]; 24 | self.offset += 1; 25 | return value; 26 | } 27 | 28 | pub fn readEnum(self: *Self, comptime T: type) !T { 29 | if (@typeInfo(T) != .Enum) @compileError("T must be a enum type!"); 30 | 31 | const I = std.meta.Tag(T); 32 | switch (I) { 33 | u8 => { 34 | const byte = try self.readByte(); 35 | return std.meta.intToEnum(T, byte); 36 | }, 37 | u32 => { 38 | const int = try self.readVarUInt(); 39 | return std.meta.intToEnum(T, int); 40 | }, 41 | else => @compileError(@typeName(I) ++ " is not a supported enumeration tag type!"), 42 | } 43 | } 44 | 45 | pub fn readVarUInt(self: *Self) !u32 { 46 | var number: u32 = 0; 47 | 48 | while (true) { 49 | const value = try self.readByte(); 50 | number <<= 7; 51 | number |= value & 0x7F; 52 | if ((value & 0x80) == 0) 53 | break; 54 | } 55 | 56 | return number; 57 | } 58 | 59 | pub fn readVarSInt(self: *Self) !i32 { 60 | return ZigZagInt.decode(try self.readVarUInt()); 61 | } 62 | 63 | pub fn readRaw(self: *Self, n: usize) ![]const u8 { 64 | if (self.offset + n > self.source.len) 65 | return error.EndOfStream; 66 | const value = self.source[self.offset .. self.offset + n]; 67 | self.offset += n; 68 | return value; 69 | } 70 | 71 | pub fn readToEnd(self: *Self) ![]const u8 { 72 | if (self.offset >= self.source.len) 73 | return &[0]u8{}; 74 | const value = self.source[self.offset..]; 75 | self.offset = self.source.len; 76 | return value; 77 | } 78 | 79 | pub fn readNumber(self: *Self) !f32 { 80 | const bits = try self.readRaw(4); 81 | return @bitCast(f32, bits[0..4].*); 82 | } 83 | pub fn readString(self: *Self, allocator: std.mem.Allocator) ![]const u8 { 84 | const len = try self.readVarUInt(); 85 | 86 | const str = try allocator.alloc(u8, len); 87 | errdefer allocator.free(str); 88 | 89 | std.mem.copy(u8, str, try self.readRaw(len)); 90 | 91 | return str; 92 | } 93 | }; 94 | -------------------------------------------------------------------------------- /src/dunstblick-protocol/encoder.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const builtin = @import("builtin"); 3 | 4 | usingnamespace @import("data-types.zig"); 5 | 6 | const ZigZagInt = @import("zigzagint.zig"); 7 | 8 | pub fn Encoder(comptime Stream: type) type { 9 | return struct { 10 | const Self = @This(); 11 | 12 | stream: Stream, 13 | 14 | pub fn init(stream: Stream) Self { 15 | return Self{ 16 | .stream = stream, 17 | }; 18 | } 19 | 20 | pub fn writeByte(self: *Self, byte: u8) !void { 21 | try self.stream.writeByte(byte); 22 | } 23 | 24 | pub fn writeRaw(self: *Self, data: []const u8) !void { 25 | try self.stream.writeAll(data); 26 | } 27 | 28 | pub fn writeEnum(self: *Self, e: u8) !void { 29 | try self.writeByte(e); 30 | } 31 | 32 | pub fn writeID(self: *Self, id: u32) !void { 33 | try self.writeVarUInt(id); 34 | } 35 | 36 | pub fn writeString(self: *Self, string: []const u8) !void { 37 | try self.writeVarUInt(@intCast(u32, string.len)); 38 | try self.writeRaw(string); 39 | } 40 | 41 | pub fn writeNumber(self: *Self, number: f32) !void { 42 | std.debug.assert(builtin.target.cpu.arch.endian() == .Little); 43 | try self.writeRaw(std.mem.asBytes(&number)); 44 | } 45 | 46 | pub fn writeVarUInt(self: *Self, value: u32) !void { 47 | var buf: [5]u8 = undefined; 48 | 49 | var maxidx: usize = 4; 50 | 51 | comptime var n: usize = 0; 52 | inline while (n < 5) : (n += 1) { 53 | const chr = &buf[4 - n]; 54 | chr.* = @truncate(u8, (value >> (7 * n)) & 0x7F); 55 | if (chr.* != 0) 56 | maxidx = 4 - n; 57 | if (n > 0) 58 | chr.* |= 0x80; 59 | } 60 | 61 | std.debug.assert(maxidx < 5); 62 | try self.writeRaw(buf[maxidx..]); 63 | } 64 | 65 | pub fn writeVarSInt(self: *Self, value: i32) !void { 66 | try self.writeVarUInt(ZigZagInt.encode(value)); 67 | } 68 | }; 69 | } 70 | -------------------------------------------------------------------------------- /src/dunstblick-protocol/enums.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const types = @import("data-types.zig"); 3 | 4 | fn val(e: types.Enum) u8 { 5 | return @enumToInt(e); 6 | } 7 | 8 | pub fn enumCast(src: types.Enum, comptime E: type) !E { 9 | return try std.math.intToEnum(val(src)); 10 | } 11 | 12 | pub fn isEnumeration(comptime T: type) bool { 13 | return @typeInfo(T) == .Enum and std.meta.Tag(T) == u8; 14 | } 15 | 16 | pub const HorizontalAlignment = enum(u8) { 17 | left = val(.left), 18 | center = val(.center), 19 | right = val(.right), 20 | stretch = val(.stretch), 21 | }; 22 | 23 | pub const VerticalAlignment = enum(u8) { 24 | top = val(.top), 25 | middle = val(.middle), 26 | bottom = val(.bottom), 27 | stretch = val(.stretch), 28 | }; 29 | 30 | pub const DockSite = enum(u8) { 31 | left = val(.left), 32 | right = val(.right), 33 | top = val(.top), 34 | bottom = val(.bottom), 35 | }; 36 | 37 | pub const Visibility = enum(u8) { 38 | visible = val(.visible), 39 | hidden = val(.hidden), 40 | collapsed = val(.collapsed), 41 | }; 42 | 43 | pub const Font = enum(u8) { 44 | sans = val(.sans), 45 | serif = val(.serif), 46 | monospace = val(.monospace), 47 | }; 48 | 49 | pub const ImageScaling = enum(u8) { 50 | none = val(.none), 51 | center = val(.center), 52 | stretch = val(.stretch), 53 | zoom = val(.zoom), 54 | contain = val(.contain), 55 | cover = val(.cover), 56 | }; 57 | 58 | pub const StackDirection = enum(u8) { 59 | vertical = val(.vertical), 60 | horizontal = val(.horizontal), 61 | }; 62 | 63 | pub const Orientation = enum(u8) { 64 | horizontal = val(.horizontal), 65 | vertical = val(.vertical), 66 | }; 67 | 68 | pub const DisplayProgressStyle = enum(u8) { 69 | none = val(.none), 70 | percent = val(.percent), 71 | absolute = val(.absolute), 72 | }; 73 | -------------------------------------------------------------------------------- /src/dunstblick-protocol/tcp/CryptoState.zig: -------------------------------------------------------------------------------- 1 | //! The common state for `ClientStateMachine` and `ServerStateMachine`. 2 | 3 | const std = @import("std"); 4 | const Charm = @import("charm").Charm; 5 | 6 | const Self = @This(); 7 | 8 | pub const Tag = [Charm.tag_length]u8; 9 | pub const Hash = [Charm.hash_length]u8; 10 | pub const Key = [Charm.key_length]u8; 11 | pub const Nonce = [Charm.nonce_length]u8; 12 | 13 | const Mode = enum { 14 | not_started, 15 | client, 16 | server, 17 | }; 18 | 19 | /// When this is not `.not_started`, both `client_nonce` and `server_nonce` are properly 20 | /// set and the crypto provider is ready. 21 | mode: Mode = .not_started, 22 | 23 | /// When this is `true`, the packages will be encrypted/decrypted with `charm`. 24 | encryption_enabled: bool = false, 25 | 26 | /// The cryptographic provider for the connection. 27 | charm: Charm, 28 | 29 | /// The client nonce is a random string generated on the startup of the system. 30 | client_nonce: Nonce, 31 | 32 | /// The client nonce is a random string generated on the startup of the system. 33 | server_nonce: Nonce, 34 | 35 | pub fn init() Self { 36 | var self = Self{ 37 | .client_nonce = undefined, 38 | .server_nonce = undefined, 39 | .charm = undefined, 40 | }; 41 | std.crypto.random.bytes(&self.client_nonce); 42 | std.crypto.random.bytes(&self.server_nonce); 43 | return self; 44 | } 45 | 46 | pub fn start(self: *Self, key: Key, mode: Mode) Hash { 47 | std.debug.assert(mode != .not_started); 48 | 49 | self.charm = Charm.new(key, null); 50 | // feed the state some random data, so we 51 | // kill replayability with this and 52 | // make the same data look different each connection 53 | _ = self.charm.hash(&self.client_nonce); 54 | _ = self.charm.hash(&self.server_nonce); 55 | 56 | var auth_token_src: [32]u8 = undefined; 57 | std.mem.copy(u8, auth_token_src[0..16], &self.client_nonce); 58 | std.mem.copy(u8, auth_token_src[16..32], &self.server_nonce); 59 | const auth_token = self.charm.hash(&auth_token_src); 60 | self.mode = mode; 61 | return auth_token; 62 | } 63 | 64 | pub fn encrypt(self: *Self, data: []u8) Tag { 65 | std.debug.assert(self.mode != .not_started); 66 | return self.charm.encrypt(data); 67 | } 68 | 69 | pub fn decrypt(self: *Self, tag: Tag, data: []u8) error{InvalidData}!void { 70 | std.debug.assert(self.mode != .not_started); 71 | self.charm.decrypt(data, tag) catch return error.InvalidData; 72 | } 73 | 74 | pub fn hash(self: *Self, data: []const u8) Hash { 75 | std.debug.assert(self.mode != .not_started); 76 | return self.charm.hash(data); 77 | } 78 | 79 | pub fn hashPassword(password: []const u8, salt: []const u8) Key { 80 | var key: Key = undefined; 81 | std.crypto.pwhash.pbkdf2( 82 | &key, 83 | password, 84 | salt, 85 | 1_000, 86 | std.crypto.auth.hmac.HmacSha1, 87 | ) catch unreachable; 88 | return key; 89 | } 90 | -------------------------------------------------------------------------------- /src/dunstblick-protocol/zigzagint.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | pub fn encode(n: i32) u32 { 4 | const v = (n << 1) ^ (n >> 31); 5 | return @bitCast(u32, v); 6 | } 7 | 8 | pub fn decode(u: u32) i32 { 9 | const n = @bitCast(i32, u); 10 | return (n >> 1) ^ (n << 31); 11 | } 12 | 13 | test "ZigZag" { 14 | const input = 42; 15 | std.debug.assert(encode(input) == 84); 16 | std.debug.assert(decode(84) == input); 17 | } 18 | -------------------------------------------------------------------------------- /src/dunstfs/html/file.ztt: -------------------------------------------------------------------------------- 1 |
2 |

3 | 4 |
-------------------------------------------------------------------------------- /src/dunstfs/html/frame.ztt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | DunstFS 8 | 9 | 10 | 11 | 12 |
13 | 20 |
21 | 22 |
23 | 24 | 52 | 53 | 54 | 55 |
56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /src/dunstfs/html/img/file-details.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/dunstfs/html/img/file-edit.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/dunstfs/html/img/file-view.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/dunstfs/html/img/mime/account.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/dunstfs/html/img/mime/archive.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/dunstfs/html/img/mime/cad.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/dunstfs/html/img/mime/chart.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/dunstfs/html/img/mime/code.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/dunstfs/html/img/mime/csv.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/dunstfs/html/img/mime/document.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/dunstfs/html/img/mime/generic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/dunstfs/html/img/mime/image.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/dunstfs/html/img/mime/ms-excel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/dunstfs/html/img/mime/ms-powerpoint.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/dunstfs/html/img/mime/ms-word.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/dunstfs/html/img/mime/music.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/dunstfs/html/img/mime/pdf.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/dunstfs/html/img/mime/table.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/dunstfs/html/img/mime/video.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/dunstfs/html/index.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | DunstFS 7 | 8 | 9 | 10 | 11 |
12 | 19 |
20 | 21 |
22 | 33 | 34 | 58 |
59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/dunstfs/html/index.ztt: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | 20 | 21 |
22 |
-------------------------------------------------------------------------------- /src/dunstfs/html/settings.ztt: -------------------------------------------------------------------------------- 1 |
2 |

Settings

3 |
4 | 5 | 6 |
7 |
8 |
-------------------------------------------------------------------------------- /src/dunstfs/rpc.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const rpc = @import("antiphony"); 3 | const Uuid = @import("uuid6"); 4 | const network = @import("network"); 5 | 6 | pub const dunstfs_port = 5229; 7 | pub const protocol_magic = [4]u8{ 0x42, 0x6c, 0x74, 0xb6 }; 8 | pub const protocol_version: u8 = 1; 9 | 10 | pub const end_point = network.EndPoint{ 11 | .address = .{ .ipv4 = network.Address.IPv4.loopback }, 12 | .port = dunstfs_port, 13 | }; 14 | 15 | pub const public_end_point = network.EndPoint{ 16 | .address = .{ .ipv4 = network.Address.IPv4.any }, 17 | .port = dunstfs_port, 18 | }; 19 | 20 | pub const AllocatingCall = rpc.AllocatingCall; 21 | 22 | pub const AddFileError = error{ OutOfMemory, AccessDenied, IoError, InvalidSourceFile, SourceFileNotFound }; 23 | pub const UpdateFileError = error{ NotImplementedYet, OutOfMemory, AccessDenied, IoError, InvalidSourceFile, FileNotFound, SourceFileNotFound }; 24 | pub const RemoveFileError = error{ OutOfMemory, IoError, FileNotFound }; 25 | pub const GetFileError = error{ OutOfMemory, IoError, FileNotFound, AccessDenied, InvalidDestinationFile }; 26 | pub const RenameFileError = error{ OutOfMemory, IoError, FileNotFound }; 27 | pub const AddTagError = error{ OutOfMemory, IoError, FileNotFound }; 28 | pub const RemoveTagError = error{ OutOfMemory, IoError, FileNotFound }; 29 | pub const ListFileTagsError = error{ OutOfMemory, IoError, FileNotFound }; 30 | pub const ListTagsError = error{ OutOfMemory, IoError }; 31 | pub const ListFilesError = error{ OutOfMemory, IoError }; 32 | pub const OpenFileError = error{ NotImplementedYet, OutOfMemory, IoError, FileNotFound }; 33 | pub const FileInfoError = error{ OutOfMemory, IoError, FileNotFound }; 34 | 35 | pub const FileListItem = struct { 36 | uuid: Uuid, 37 | user_name: ?[]const u8, 38 | last_change: []const u8, 39 | mime_type: []const u8, 40 | }; 41 | 42 | pub const TagInfo = struct { 43 | tag: []const u8, 44 | count: u32, 45 | }; 46 | 47 | pub const Date = [19]u8; // YYYY-MM-DD hh:mm:ss 48 | 49 | pub const FileInfo = struct { 50 | name: ?[]const u8, 51 | tags: []const []const u8, 52 | revisions: []const Revision, // sorted new-to-old 53 | last_change: Date, 54 | 55 | pub fn currentRevision(self: @This()) ?Revision { 56 | if (self.revisions.len > 0) { 57 | return self.revisions[0]; 58 | } else { 59 | return null; 60 | } 61 | } 62 | }; 63 | 64 | pub const Revision = struct { 65 | number: u32, 66 | dataset: [32]u8, // blake3 hash of the file contents 67 | date: Date, 68 | mime: []const u8, 69 | size: u64, 70 | }; 71 | 72 | pub const Definition = rpc.CreateDefinition(.{ 73 | .host = .{ 74 | // File management 75 | .add = fn (source_file: []const u8, mime_type: []const u8, name: ?[]const u8, tags: []const []const u8) AddFileError!Uuid, 76 | .update = fn (file: Uuid, source_file: []const u8, mime: []const u8) UpdateFileError!void, 77 | .rename = fn (file: Uuid, name: ?[]const u8) RenameFileError!void, 78 | .delete = fn (file: Uuid) RemoveFileError!void, 79 | .get = fn (file: Uuid, target: []const u8) GetFileError!Revision, 80 | .open = fn (file: Uuid, read_only: bool) OpenFileError!void, 81 | .info = fn (file: Uuid) FileInfoError!FileInfo, 82 | 83 | .list = fn (skip: u32, limit: ?u32, include_filters: []const []const u8, exclude_filters: []const []const u8) ListFilesError![]FileListItem, 84 | .find = fn (skip: u32, limit: ?u32, filter: []const u8, exact: bool) ListFilesError![]FileListItem, 85 | 86 | // Tag management 87 | .addTags = fn (file: Uuid, tags: []const []const u8) AddTagError!void, 88 | .removeTags = fn (file: Uuid, tags: []const []const u8) RemoveTagError!void, 89 | .listFileTags = fn (file: Uuid) ListFileTagsError![]const []const u8, 90 | .listTags = fn (filter: ?[]const u8, limit: ?u32) ListTagsError![]TagInfo, 91 | 92 | // Utility 93 | .collectGarbage = fn () void, 94 | }, 95 | .client = .{}, 96 | }); 97 | -------------------------------------------------------------------------------- /src/dunstinit/rpc.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const rpc = @import("antiphony"); 3 | const network = @import("network"); 4 | 5 | pub const dunstfabric_port = 8938; 6 | pub const protocol_magic = [4]u8{ 0xf7, 0xcb, 0xbb, 0x05 }; 7 | pub const protocol_version: u8 = 1; 8 | 9 | pub const end_point = network.EndPoint{ 10 | .address = .{ .ipv4 = network.Address.IPv4.loopback }, 11 | .port = dunstfabric_port, 12 | }; 13 | 14 | pub const public_end_point = network.EndPoint{ 15 | .address = .{ .ipv4 = network.Address.IPv4.any }, 16 | .port = dunstfabric_port, 17 | }; 18 | 19 | pub const ProcessID = union(enum) { 20 | windows: std.os.windows.DWORD, 21 | unix: i32, 22 | }; 23 | 24 | pub const ServiceControlError = error{ Timeout, UnkownService, IoError, FileNotFound, OutOfMemory }; 25 | pub const CreateServiceError = error{ Timeout, AlreadyExists, FileNotFound, OutOfMemory }; 26 | 27 | pub const ServiceStatus = struct { 28 | online: bool, 29 | pid: ?ProcessID, 30 | }; 31 | 32 | pub const ServiceDescriptor = struct { 33 | autostart: bool = false, 34 | restart: Restart = .no, 35 | command: []const []const u8, 36 | dependencies: []const u8 = &.{}, 37 | }; 38 | 39 | pub const Restart = enum { 40 | /// The service will never be restarted. 41 | no, 42 | 43 | /// The service will only be restarted if the exit code is not 0. 44 | @"on-failure", 45 | 46 | /// The service will always be restarted unless it is explicitly stopped. 47 | always, 48 | }; 49 | 50 | pub const Definition = rpc.CreateDefinition(.{ 51 | .host = .{ 52 | // Service control 53 | .startService = fn (service: []const u8) ServiceControlError!void, 54 | .restartService = fn (service: []const u8) ServiceControlError!void, 55 | .stopService = fn (service: []const u8) ServiceControlError!void, 56 | .getServiceStatus = fn (service: []const u8) ServiceControlError!ServiceStatus, 57 | 58 | // Service management 59 | .createService = fn (name: []const u8, desc: ServiceDescriptor) CreateServiceError!void, 60 | .deleteService = fn (name: []const u8) ServiceControlError!void, 61 | .getServiceDescriptor = fn (name: []const u8) CreateServiceError!ServiceDescriptor, 62 | }, 63 | .client = .{}, 64 | }); 65 | -------------------------------------------------------------------------------- /src/dunstnetz-daemon/main.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const dunstnetz = @import("dunstnetz"); 3 | const wasm = @import("wasm"); 4 | 5 | const device_config = dunstnetz.DeviceConfig{ 6 | .name = "Demo Device", 7 | .address = dunstnetz.DeviceAddress.fromBytes([6]u8{ 0xae, 0x22, 0x3a, 0xa1, 0x0c, 0x68 }), 8 | .capabilities = dunstnetz.DeviceCaps{ 9 | .audio_sink = false, 10 | .audio_source = false, 11 | .mass_storage = false, 12 | .display = false, 13 | .app_host = false, 14 | .internet_access = false, 15 | }, 16 | }; 17 | 18 | var gpa = std.heap.GeneralPurposeAllocator(.{}){}; 19 | 20 | pub fn main() !void { 21 | defer _ = gpa.deinit(); 22 | 23 | try dunstnetz.init(); 24 | defer dunstnetz.deinit(); 25 | 26 | var file = try std.fs.cwd().openFile("wasm-demo.wasm", .{}); 27 | defer file.close(); 28 | 29 | var module = try wasm.Module.parse(&gpa.allocator, file.reader()); 30 | defer module.deinit(); 31 | 32 | var instance = try module.instantiate(&gpa.allocator, null, struct {}); 33 | defer instance.deinit(); 34 | 35 | { 36 | const result = try instance.call("app_init", .{@as(i32, 1)}); 37 | std.debug.print("{}\n", .{result}); 38 | } 39 | { 40 | const result = try instance.call("app_init", .{@as(i32, 0)}); 41 | std.debug.print("{}\n", .{result}); 42 | } 43 | 44 | // var device = try dunstnetz.Device.create(device_config); 45 | // defer device.destroy(); 46 | 47 | // try device.send(dunstnetz.Message{ 48 | // .receiver = dunstnetz.DeviceAddress.fromBytes([6]u8{ 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }), 49 | // .data = "Hello, World!", 50 | // .reliable = true, 51 | // .sequenced = undefined, // ignored for 52 | // .channel = 0, // 0 … 63 53 | // }); 54 | 55 | // var session = try device.openSession( 56 | // dunstnetz.AppAddress.init(0x00, 0x00, 0x01), // target application 57 | // &[_]dunstnetz.ChannelConfig{ // init 4 channels, each one has 58 | // .{ .reliable = false, .sequenced = false }, 59 | // .{ .reliable = false, .sequenced = true }, 60 | // .{ .reliable = true, .sequenced = false }, 61 | // .{ .reliable = true, .sequenced = true }, 62 | // }, 63 | // ); 64 | // defer session.close(); 65 | 66 | while (true) { 67 | // try device.update(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/dunstnetz/main.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const network = @import("network"); 3 | 4 | pub const DeviceAddress = enum(u48) { 5 | const Self = @This(); 6 | 7 | _, 8 | 9 | pub fn fromBytes(value: [6]u8) Self { 10 | return @bitCast(Self, value); 11 | } 12 | 13 | pub fn toBytes(self: Self) [6]u8 { 14 | return @bitCast([6]u8, self); 15 | } 16 | }; 17 | 18 | pub const AppAddress = enum(u24) { 19 | const Self = @This(); 20 | 21 | _, 22 | 23 | pub fn fromBytes(value: [3]u8) Self { 24 | return @bitCast(Self, value); 25 | } 26 | 27 | pub fn toBytes(self: Self) [3]u8 { 28 | return @bitCast([3]u8, self); 29 | } 30 | }; 31 | 32 | /// The broadcast address. Can be used to 33 | pub const broadcast = DeviceAddress.fromBytes([6]u8{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }); 34 | 35 | pub const DeviceConfig = struct { 36 | name: []const u8, 37 | address: DeviceAddress, 38 | capabilities: DeviceCaps, 39 | }; 40 | 41 | pub const DeviceCaps = struct { 42 | audio_sink: bool, 43 | audio_source: bool, 44 | mass_storage: bool, 45 | display: bool, 46 | app_host: bool, 47 | internet_access: bool, 48 | }; 49 | 50 | pub fn init() !void { 51 | try network.init(); 52 | } 53 | 54 | pub fn deinit() void { 55 | network.deinit(); 56 | } 57 | 58 | pub const Device = struct { 59 | const Self = @This(); 60 | 61 | pub fn create(device_config: DeviceConfig) !Self { 62 | _ = device_config; 63 | return Self{}; 64 | } 65 | 66 | pub fn destroy(self: *Self) void { 67 | self.* = undefined; 68 | } 69 | 70 | pub fn update(self: *Self) void { 71 | _ = self; 72 | @panic("not implemented yet"); 73 | } 74 | }; 75 | -------------------------------------------------------------------------------- /src/examples/calculator/README.md: -------------------------------------------------------------------------------- 1 | # Calculator Example 2 | 3 | This example demonstrates how to implement a simple calculator application: 4 | 5 | [![](https://mq32.de/public/screenshot/951e859e400b506b1e6f8cedf0838b4d.png)](https://mq32.de/public/dunstwolke-04.mp4) 6 | 7 | Techniques and features used in this example: 8 | 9 | - Bindings 10 | - Property Updates 11 | - Callbacks 12 | 13 | Widgets used: 14 | 15 | - Grid Layout 16 | - Dock Layout 17 | - Button 18 | - Label 19 | -------------------------------------------------------------------------------- /src/examples/calculator/calculator.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/examples/calculator/calculator.tvg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/calculator/calculator.tvg -------------------------------------------------------------------------------- /src/examples/calculator/calculator.tvgt: -------------------------------------------------------------------------------- 1 | (tvg 1 2 | (24 24 1/1 u8888 default) 3 | ( 4 | (0.000 0.000 0.000 1.000) 5 | ) 6 | ( 7 | ( 8 | fill_path 9 | (flat 0) 10 | ( 11 | (7 2) 12 | ( 13 | (line - 17 2) 14 | (bezier - (18.104569499661586 2) (19 2.8954305003384135) (19 4)) 15 | (line - 19 20) 16 | (bezier - (19 21.104569499661586) (18.104569499661586 22) (17 22)) 17 | (line - 7 22) 18 | (bezier - (5.8954305003384135 22) (5 21.104569499661586) (5 20)) 19 | (line - 5 4) 20 | (bezier - (5 2.8954305003384135) (5.895430500338413 2) (7 2)) 21 | ) 22 | (7 4) 23 | ( 24 | (line - 7 8) 25 | (line - 17 8) 26 | (line - 17 4) 27 | (line - 7 4) 28 | ) 29 | (7 10) 30 | ( 31 | (line - 7 12) 32 | (line - 9 12) 33 | (line - 9 10) 34 | (line - 7 10) 35 | ) 36 | (11 10) 37 | ( 38 | (line - 11 12) 39 | (line - 13 12) 40 | (line - 13 10) 41 | (line - 11 10) 42 | ) 43 | (15 10) 44 | ( 45 | (line - 15 12) 46 | (line - 17 12) 47 | (line - 17 10) 48 | (line - 15 10) 49 | ) 50 | (7 14) 51 | ( 52 | (line - 7 16) 53 | (line - 9 16) 54 | (line - 9 14) 55 | (line - 7 14) 56 | ) 57 | (11 14) 58 | ( 59 | (line - 11 16) 60 | (line - 13 16) 61 | (line - 13 14) 62 | (line - 11 14) 63 | ) 64 | (15 14) 65 | ( 66 | (line - 15 16) 67 | (line - 17 16) 68 | (line - 17 14) 69 | (line - 15 14) 70 | ) 71 | (7 18) 72 | ( 73 | (line - 7 20) 74 | (line - 9 20) 75 | (line - 9 18) 76 | (line - 7 18) 77 | ) 78 | (11 18) 79 | ( 80 | (line - 11 20) 81 | (line - 13 20) 82 | (line - 13 18) 83 | (line - 11 18) 84 | ) 85 | (15 18) 86 | ( 87 | (line - 15 20) 88 | (line - 17 20) 89 | (line - 17 18) 90 | (line - 15 18) 91 | (close -) 92 | ) 93 | ) 94 | ) 95 | ) 96 | ) 97 | -------------------------------------------------------------------------------- /src/examples/calculator/layout.h: -------------------------------------------------------------------------------- 1 | 0xFE, 0x0, 0x14, 0x6, 0x4, 0x0, 0x2, 0x8A, 0x1, 0x1, 0x3, 0x0, 0x0, 0x0, 0xFD, 0x3, 0x0, 0x0, 0x0, 0x0, 0x12, 0x4, 0x55, 0x13, 0x5, 0x55, 0x1, 0x0, 0x1, 0x1E, 0xF, 0x0, 0x2, 0xA, 0x1, 0x43, 0x0, 0x0, 0x0, 0x1, 0x1E, 0x10, 0x0, 0x2, 0xA, 0x2, 0x43, 0x45, 0x0, 0x0, 0x0, 0x13, 0x0, 0x0, 0x1, 0x1E, 0xE, 0x0, 0x2, 0xA, 0x2, 0xC3, 0xB7, 0x0, 0x0, 0x0, 0x1, 0x1E, 0x7, 0x0, 0x2, 0xA, 0x1, 0x37, 0x0, 0x0, 0x0, 0x1, 0x1E, 0x8, 0x0, 0x2, 0xA, 0x1, 0x38, 0x0, 0x0, 0x0, 0x1, 0x1E, 0x9, 0x0, 0x2, 0xA, 0x1, 0x39, 0x0, 0x0, 0x0, 0x1, 0x1E, 0xD, 0x0, 0x2, 0xA, 0x2, 0xC3, 0x97, 0x0, 0x0, 0x0, 0x1, 0x1E, 0x4, 0x0, 0x2, 0xA, 0x1, 0x34, 0x0, 0x0, 0x0, 0x1, 0x1E, 0x5, 0x0, 0x2, 0xA, 0x1, 0x35, 0x0, 0x0, 0x0, 0x1, 0x1E, 0x6, 0x0, 0x2, 0xA, 0x1, 0x36, 0x0, 0x0, 0x0, 0x1, 0x1E, 0xC, 0x0, 0x2, 0xA, 0x1, 0x2D, 0x0, 0x0, 0x0, 0x1, 0x1E, 0x1, 0x0, 0x2, 0xA, 0x1, 0x31, 0x0, 0x0, 0x0, 0x1, 0x1E, 0x2, 0x0, 0x2, 0xA, 0x1, 0x32, 0x0, 0x0, 0x0, 0x1, 0x1E, 0x3, 0x0, 0x2, 0xA, 0x1, 0x33, 0x0, 0x0, 0x0, 0x1, 0x1E, 0xB, 0x0, 0x2, 0xA, 0x1, 0x2B, 0x0, 0x0, 0x0, 0x1, 0x1E, 0xA, 0x0, 0x2, 0xA, 0x1, 0x30, 0x0, 0x0, 0x0, 0x1, 0x1E, 0x11, 0x0, 0x2, 0xA, 0x1, 0x2C, 0x0, 0x0, 0x0, 0x13, 0x0, 0x0, 0x1, 0x1E, 0x12, 0x0, 0x2, 0xA, 0x1, 0x3D, 0x0, 0x0, 0x0, 0x0, 0x0, -------------------------------------------------------------------------------- /src/examples/calculator/layout.json: -------------------------------------------------------------------------------- 1 | { 2 | "properties": { 3 | "result": 1 4 | }, 5 | "callbacks": { 6 | "1": 1, 7 | "2": 2, 8 | "3": 3, 9 | "4": 4, 10 | "5": 5, 11 | "6": 6, 12 | "7": 7, 13 | "8": 8, 14 | "9": 9, 15 | "0": 10, 16 | "+": 11, 17 | "-": 12, 18 | "*": 13, 19 | "/": 14, 20 | "C": 15, 21 | "CE": 16, 22 | ",": 17, 23 | "=": 18 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/examples/calculator/layout.ui: -------------------------------------------------------------------------------- 1 | DockLayout 2 | { 3 | Panel 4 | { 5 | dock-site: top; 6 | Label 7 | { 8 | text: bind("result"); 9 | horizontal-alignment: right; 10 | } 11 | } 12 | GridLayout 13 | { 14 | margins: 0; 15 | columns: expand, expand, expand, expand; 16 | rows: expand, expand, expand, expand, expand; 17 | 18 | /* row 1 */ 19 | Button 20 | { 21 | on-click: callback("C"); 22 | Label { text: "C"; } 23 | } 24 | Button 25 | { 26 | on-click: callback("CE"); 27 | Label { text: "CE"; } 28 | } 29 | Spacer { } 30 | 31 | Button 32 | { 33 | on-click: callback("/"); 34 | Label { text: "÷"; } 35 | } 36 | 37 | /* row 2 */ 38 | Button 39 | { 40 | on-click: callback("7"); 41 | Label { text: "7"; } 42 | } 43 | Button 44 | { 45 | on-click: callback("8"); 46 | Label { text: "8"; } 47 | } 48 | Button 49 | { 50 | on-click: callback("9"); 51 | Label { text: "9"; } 52 | } 53 | Button 54 | { 55 | on-click: callback("*"); 56 | Label { text: "×"; } 57 | } 58 | 59 | /* row 3 */ 60 | Button 61 | { 62 | on-click: callback("4"); 63 | Label { text: "4"; } 64 | } 65 | Button 66 | { 67 | on-click: callback("5"); 68 | Label { text: "5"; } 69 | } 70 | Button 71 | { 72 | on-click: callback("6"); 73 | Label { text: "6"; } 74 | } 75 | Button 76 | { 77 | on-click: callback("-"); 78 | Label { text: "-"; } 79 | } 80 | 81 | /* row 4 */ 82 | Button 83 | { 84 | on-click: callback("1"); 85 | Label { text: "1"; } 86 | } 87 | Button 88 | { 89 | on-click: callback("2"); 90 | Label { text: "2"; } 91 | } 92 | Button 93 | { 94 | on-click: callback("3"); 95 | Label { text: "3"; } 96 | } 97 | Button 98 | { 99 | on-click: callback("+"); 100 | Label { text: "+"; } 101 | } 102 | 103 | 104 | /* row 5 */ 105 | Button 106 | { 107 | on-click: callback("0"); 108 | Label { text: "0"; } 109 | } 110 | Button 111 | { 112 | on-click: callback(","); 113 | Label { text: ","; } 114 | } 115 | Spacer { } 116 | Button 117 | { 118 | on-click: callback("="); 119 | Label { text: "="; } 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/examples/mediaserver/README.md: -------------------------------------------------------------------------------- 1 | # Dunstwolke MediaServer 2 | -------------------------------------------------------------------------------- /src/examples/mediaserver/bass/bass.chm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/bass/bass.chm -------------------------------------------------------------------------------- /src/examples/mediaserver/bass/bass.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/bass/bass.txt -------------------------------------------------------------------------------- /src/examples/mediaserver/bass/x86_64/libbass.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/bass/x86_64/libbass.so -------------------------------------------------------------------------------- /src/examples/mediaserver/layouts/.gitignore: -------------------------------------------------------------------------------- 1 | *.cui 2 | -------------------------------------------------------------------------------- /src/examples/mediaserver/layouts/main.ui: -------------------------------------------------------------------------------- 1 | Picture 2 | { 3 | margins: 0; 4 | image: resource("wallpaper"); 5 | image-scaling: cover; 6 | hit-test-visible: true; 7 | DockLayout 8 | { 9 | GridLayout 10 | { 11 | dock-site: bottom; 12 | columns: auto, expand, auto, auto, auto, expand, auto; 13 | 14 | Button 15 | { 16 | on-click: callback("open-volume-control"); 17 | horizontal-alignment: center; 18 | Picture { image: resource("icon-volume-medium"); } 19 | } 20 | Spacer { } 21 | Button 22 | { 23 | on-click: callback("previous-song"); 24 | horizontal-alignment: center; 25 | Picture { image: resource("icon-skip-previous"); } 26 | } 27 | Button 28 | { 29 | on-click: callback("play-pause"); 30 | horizontal-alignment: center; 31 | Picture { image: resource("icon-play"); } 32 | } 33 | Button 34 | { 35 | on-click: callback("next-song"); 36 | horizontal-alignment: center; 37 | Picture { image: resource("icon-skip-next"); } 38 | } 39 | Spacer { } 40 | Button 41 | { 42 | on-click: callback("open-main-menu"); 43 | horizontal-alignment: center; 44 | Picture { image: resource("icon-menu"); } 45 | } 46 | } 47 | Label 48 | { 49 | dock-site: bottom; 50 | text: bind("current-artist"); 51 | } 52 | Label 53 | { 54 | dock-site: bottom; 55 | text: bind("current-song"); 56 | } 57 | Picture 58 | { 59 | image: bind("current-albumart"); 60 | image-scaling: zoom; 61 | vertical-alignment: middle; 62 | horizontal-alignment: center; 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /src/examples/mediaserver/layouts/menu.ui: -------------------------------------------------------------------------------- 1 | Container 2 | { 3 | GridLayout 4 | { 5 | vertical-alignment: bottom; 6 | dock-site: bottom; 7 | columns: auto, expand, auto, auto, auto, expand, auto; 8 | 9 | Button 10 | { 11 | on-click: callback("open-settings"); 12 | horizontal-alignment: center; 13 | Picture { image: resource("icon-settings"); } 14 | } 15 | 16 | Spacer { } 17 | CheckBox 18 | { 19 | on-click: callback("toggle-repeat-one"); 20 | horizontal-alignment: center; 21 | Picture { image: resource("icon-repeat-one"); } 22 | } 23 | CheckBox 24 | { 25 | on-click: callback("toggle-repeat-all"); 26 | horizontal-alignment: center; 27 | Picture { image: resource("icon-repeat-all"); } 28 | } 29 | CheckBox 30 | { 31 | on-click: callback("toggle-shuffle"); 32 | horizontal-alignment: center; 33 | Picture { image: resource("icon-shuffle"); } 34 | } 35 | Spacer { } 36 | Button 37 | { 38 | on-click: callback("close-main-menu"); 39 | horizontal-alignment: center; 40 | Picture { image: resource("icon-close"); } 41 | } 42 | } 43 | GridLayout { 44 | horizontal-alignment: center; 45 | vertical-alignment: middle; 46 | columns: expand, expand, expand; 47 | DockLayout { 48 | Label { dock-site: bottom; text: "Albums"; } 49 | Button { 50 | on-click: callback("open-albums"); 51 | horizontal-alignment: center; 52 | Picture { 53 | image: resource("icon-album"); 54 | } 55 | } 56 | } 57 | DockLayout { 58 | Label { dock-site: bottom; text: "Radio"; } 59 | Button { 60 | on-click: callback("open-radio"); 61 | horizontal-alignment: center; 62 | Picture { 63 | image: resource("icon-radio"); 64 | } 65 | } 66 | } 67 | DockLayout { 68 | Label { dock-site: bottom; text: "Playlists"; } 69 | Button { 70 | on-click: callback("open-playlists"); 71 | horizontal-alignment: center; 72 | Picture { 73 | image: resource("icon-playlist"); 74 | } 75 | } 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /src/examples/mediaserver/layouts/searchitem.ui: -------------------------------------------------------------------------------- 1 | Panel { 2 | margins: 0; 3 | horizontal-alignment: stretch; 4 | DockLayout { 5 | Button { 6 | dock-site: right; 7 | Picture { image: resource("icon-open-folder"); } 8 | } 9 | Button { 10 | dock-site: right; 11 | Picture { image: resource("icon-add"); } 12 | } 13 | Button { 14 | dock-site: right; 15 | Picture { image: resource("icon-play"); } 16 | } 17 | Label { 18 | horizontal-alignment: left; 19 | text: "Gloryhammer"; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/examples/mediaserver/resources/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/resources/add.png -------------------------------------------------------------------------------- /src/examples/mediaserver/resources/album.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/resources/album.png -------------------------------------------------------------------------------- /src/examples/mediaserver/resources/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/resources/close.png -------------------------------------------------------------------------------- /src/examples/mediaserver/resources/disc-player.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/examples/mediaserver/resources/disc-player.tvg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/resources/disc-player.tvg -------------------------------------------------------------------------------- /src/examples/mediaserver/resources/disc-player.tvgt: -------------------------------------------------------------------------------- 1 | (tvg 1 2 | (24 24 1/1 u8888 default) 3 | ( 4 | (0.000 0.000 0.000 1.000) 5 | ) 6 | ( 7 | ( 8 | fill_path 9 | (flat 0) 10 | ( 11 | (14.5 10.37) 12 | ( 13 | (bezier - (15.54 10.37) (16.38 9.53) (16.38 8.5)) 14 | (bezier - (16.38 7.46) (15.54 6.63) (14.5 6.63)) 15 | (bezier - (13.46 6.63) (12.63 7.46) (12.63 8.5)) 16 | (bezier - (12.630000000000003 9.532772482183582) (13.467227517816418 10.369999999999997) (14.500000000000002 10.369999999999997)) 17 | ) 18 | (14.5 1) 19 | ( 20 | (bezier - (18.64213562373095 1) (22 4.35786437626905) (22 8.5)) 21 | (bezier - (22 10.67) (21.08 12.63) (19.6 14)) 22 | (line - 9.4 14) 23 | (bezier - (7.93 12.63) (7 10.67) (7 8.5)) 24 | (bezier - (7 4.35) (10.36 1) (14.5 1)) 25 | ) 26 | (6 21) 27 | ( 28 | (line - 6 22) 29 | (line - 4 22) 30 | (line - 4 21) 31 | (line - 2 21) 32 | (line - 2 15) 33 | (line - 22 15) 34 | (line - 22 21) 35 | (line - 20 21) 36 | (line - 20 22) 37 | (line - 18 22) 38 | (line - 18 21) 39 | (line - 6 21) 40 | ) 41 | (4 18) 42 | ( 43 | (line - 4 19) 44 | (line - 13 19) 45 | (line - 13 18) 46 | (line - 4 18) 47 | ) 48 | (15 17) 49 | ( 50 | (line - 15 19) 51 | (line - 17 19) 52 | (line - 17 17) 53 | (line - 15 17) 54 | ) 55 | (19 17) 56 | ( 57 | (bezier - (18.447715250169207 17) (18 17.447715250169207) (18 18)) 58 | (bezier - (18 18.552284749830793) (18.447715250169207 19) (19 19)) 59 | (bezier - (19.552284749830793 19) (20 18.552284749830793) (20 18)) 60 | (bezier - (20 17.447715250169207) (19.552284749830793 17) (19 17)) 61 | (close -) 62 | ) 63 | ) 64 | ) 65 | ) 66 | ) 67 | -------------------------------------------------------------------------------- /src/examples/mediaserver/resources/folder-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/resources/folder-open.png -------------------------------------------------------------------------------- /src/examples/mediaserver/resources/menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/resources/menu.png -------------------------------------------------------------------------------- /src/examples/mediaserver/resources/pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/resources/pause.png -------------------------------------------------------------------------------- /src/examples/mediaserver/resources/placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/resources/placeholder.png -------------------------------------------------------------------------------- /src/examples/mediaserver/resources/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/resources/play.png -------------------------------------------------------------------------------- /src/examples/mediaserver/resources/playlist-music.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/resources/playlist-music.png -------------------------------------------------------------------------------- /src/examples/mediaserver/resources/radio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/resources/radio.png -------------------------------------------------------------------------------- /src/examples/mediaserver/resources/repeat-once.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/resources/repeat-once.png -------------------------------------------------------------------------------- /src/examples/mediaserver/resources/repeat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/resources/repeat.png -------------------------------------------------------------------------------- /src/examples/mediaserver/resources/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/resources/settings.png -------------------------------------------------------------------------------- /src/examples/mediaserver/resources/shuffle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/resources/shuffle.png -------------------------------------------------------------------------------- /src/examples/mediaserver/resources/skip-next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/resources/skip-next.png -------------------------------------------------------------------------------- /src/examples/mediaserver/resources/skip-previous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/resources/skip-previous.png -------------------------------------------------------------------------------- /src/examples/mediaserver/resources/volume-high.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/resources/volume-high.png -------------------------------------------------------------------------------- /src/examples/mediaserver/resources/volume-low.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/resources/volume-low.png -------------------------------------------------------------------------------- /src/examples/mediaserver/resources/volume-medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/resources/volume-medium.png -------------------------------------------------------------------------------- /src/examples/mediaserver/resources/volume-off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/resources/volume-off.png -------------------------------------------------------------------------------- /src/examples/mediaserver/resources/wallpaper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/resources/wallpaper.png -------------------------------------------------------------------------------- /src/examples/mediaserver/src/c.zig: -------------------------------------------------------------------------------- 1 | usingnamespace @cImport({ 2 | @cInclude("bass.h"); 3 | }); 4 | -------------------------------------------------------------------------------- /src/examples/mediaserver/testdata-2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/testdata-2.mp3 -------------------------------------------------------------------------------- /src/examples/mediaserver/testdata.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/testdata.mp3 -------------------------------------------------------------------------------- /src/examples/mediaserver/ui-design.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/mediaserver/ui-design.xcf -------------------------------------------------------------------------------- /src/examples/minimal/README.md: -------------------------------------------------------------------------------- 1 | # Dunstblick Minimal Example 2 | 3 | This example provides a very simple user interface with a button and a label 4 | that say "Click me!". 5 | If the button gets clicked, the application will shut down. 6 | 7 | The code is held to an absolute minimum to demonstrate the basic code layout 8 | of an application. 9 | -------------------------------------------------------------------------------- /src/examples/minimal/application.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/examples/minimal/application.tvg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/examples/minimal/application.tvg -------------------------------------------------------------------------------- /src/examples/minimal/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | static bool app_running = true; 10 | 11 | /* 12 | * Button { 13 | * on-click: callback("click=42"); 14 | * Label { 15 | * text: "Click me!"; 16 | * } 17 | * } 18 | */ 19 | static uint8_t const compiled_layout[] = { 0x01, 0x1e, 0x2a, 0x00, 0x02, 0x0a, 0x09, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x20, 0x6d, 0x65, 0x21, 0x00, 0x00, 0x00}; 20 | 21 | int main() 22 | { 23 | dunstblick_Provider * provider = dunstblick_OpenProvider( 24 | "Minimal Example", 25 | "This example is a minimal example of a Dunstblick application", 26 | NULL, 0); 27 | if (!provider) 28 | return 1; 29 | 30 | dunstblick_AddResource(provider, 1, DUNSTBLICK_RESOURCE_LAYOUT, compiled_layout, sizeof compiled_layout); 31 | 32 | bool app_running = true; 33 | while (app_running) { 34 | dunstblick_Event event; 35 | if(dunstblick_WaitEvent(provider, &event) != DUNSTBLICK_ERROR_GOT_EVENT) 36 | abort(); 37 | switch(event.type) 38 | { 39 | case DUNSTBLICK_EVENT_CONNECTED: 40 | dunstblick_SetView(event.connected.connection, 1); 41 | printf("Device connected!\n"); 42 | break; 43 | 44 | case DUNSTBLICK_EVENT_WIDGET: 45 | assert(event.widget_event.event == 42); 46 | app_running = false; 47 | break; 48 | } 49 | } 50 | 51 | dunstblick_CloseProvider(provider); 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /src/examples/minimal/minimal.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | CONFIG += console 3 | CONFIG -= app_bundle 4 | CONFIG -= qt 5 | 6 | SOURCES += \ 7 | main.c 8 | 9 | win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../libdunstblick/release/ -llibdunstblick 10 | else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../libdunstblick/debug/ -llibdunstblick 11 | else:unix: LIBS += -L$$OUT_PWD/../../libdunstblick/ -llibdunstblick 12 | 13 | INCLUDEPATH += $$PWD/../../libdunstblick 14 | DEPENDPATH += $$PWD/../../libdunstblick 15 | 16 | # static linking 17 | win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../libdunstblick/release/liblibdunstblick.a 18 | else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../libdunstblick/debug/liblibdunstblick.a 19 | else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../libdunstblick/release/libdunstblick.lib 20 | else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../../libdunstblick/debug/libdunstblick.lib 21 | else:unix: PRE_TARGETDEPS += $$OUT_PWD/../../libdunstblick/liblibdunstblick.a 22 | 23 | 24 | DISTFILES += README.md 25 | -------------------------------------------------------------------------------- /src/images/kristall-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/images/kristall-32.png -------------------------------------------------------------------------------- /src/images/person-female-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/images/person-female-01.png -------------------------------------------------------------------------------- /src/images/person-male-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/images/person-male-01.png -------------------------------------------------------------------------------- /src/images/small-test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/images/small-test.png -------------------------------------------------------------------------------- /src/test/widget-tester/4by3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/test/widget-tester/4by3.png -------------------------------------------------------------------------------- /src/test/widget-tester/go.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/test/widget-tester/go.png -------------------------------------------------------------------------------- /src/test/widget-tester/icon.tvg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/test/widget-tester/icon.tvg -------------------------------------------------------------------------------- /src/test/widget-tester/main.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const dunstblick = @import("dunstblick"); 3 | const app_data = @import("app-data"); 4 | 5 | pub fn main() !void { 6 | var gpa = std.heap.GeneralPurposeAllocator(.{}){}; 7 | defer _ = gpa.deinit(); 8 | 9 | var app = try dunstblick.Application.open( 10 | gpa.allocator(), 11 | "Widget Tester", 12 | "A overview over all Dunstblick widgets", 13 | app_data.resources.app_icon.data, 14 | ); 15 | defer app.close(); 16 | 17 | inline for (comptime std.meta.declarations(app_data.resources)) |decl| { 18 | const res = @field(app_data.resources, decl.name); 19 | try app.addResource(res.id, res.kind, res.data); 20 | } 21 | 22 | while (true) { 23 | const event = (try app.pollEvent(null)) orelse break; 24 | switch (event.*) { 25 | .connected => |event_args| { 26 | const con = event_args.connection; 27 | try con.setView(app_data.resources.index.id); 28 | 29 | var root_obj = try con.beginChangeObject(app_data.objects.root); 30 | errdefer root_obj.cancel(); 31 | 32 | try root_obj.setProperty(app_data.properties.@"main-group", .{ 33 | .integer = 0, 34 | }); 35 | try root_obj.setProperty(app_data.properties.@"input-group", .{ 36 | .integer = 0, 37 | }); 38 | 39 | try root_obj.commit(); 40 | 41 | try con.setRoot(app_data.objects.root); 42 | }, 43 | .disconnected => { 44 | // 45 | }, 46 | .widget_event => |event_args| { 47 | std.log.info("User triggerd {}", .{event_args.event}); 48 | }, 49 | .property_changed => { 50 | // 51 | }, 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/test/widget-tester/ziggy.tvg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/src/test/widget-tester/ziggy.tvg -------------------------------------------------------------------------------- /src/tools/render-widget-docs.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const protocol = @import("dunstblick-protocol"); 3 | 4 | pub fn main() !u8 { 5 | var stdout = std.io.getStdOut(); 6 | var writer = stdout.writer(); 7 | 8 | try writer.writeAll("# Dunstblick Widgets\n"); 9 | try writer.writeAll("\n"); 10 | try writer.writeAll("Description of the Widgets available in [Dunstblick](../dunstblick.md)\n"); 11 | try writer.writeAll("\n"); 12 | try writer.writeAll("## Overview\n"); 13 | try writer.writeAll("\n"); 14 | try writer.writeAll("The following widgets are available in [Dunstblick](../dunstblick.md):\n"); 15 | try writer.writeAll("\n"); 16 | 17 | for (protocol.layout_format.widget_types) |widget| { 18 | try writer.print("- [{s}](#widget:{s})\n", .{ 19 | widget.widget, 20 | @tagName(widget.type), 21 | }); 22 | } 23 | try writer.writeAll("\n"); 24 | try writer.writeAll("## Widgets\n"); 25 | try writer.writeAll("\n"); 26 | 27 | for (protocol.layout_format.widget_types) |widget| { 28 | try writer.print("

{s}

\n", .{ 29 | @tagName(widget.type), 30 | widget.widget, 31 | }); 32 | 33 | if (widget.description.len > 0) { 34 | try writer.writeAll(widget.description); 35 | try writer.writeAll("\n"); 36 | } else { 37 | std.log.warn("Widget {s} is missing a description!", .{widget.widget}); 38 | try writer.writeAll("This widget doesn't have any documentation at this moment.\n"); 39 | } 40 | try writer.writeAll("\n"); 41 | try writer.writeAll("**Properties:**\n"); 42 | try writer.writeAll("\n"); 43 | 44 | for (widget.properties) |property_id, i| { 45 | const property = getPropertyInfo(property_id); 46 | if (i > 0) { 47 | try writer.writeAll(", "); 48 | } 49 | try writer.print("[`{s}`](#property:{s})", .{ 50 | property.property, 51 | @tagName(property.value), 52 | }); 53 | } 54 | try writer.writeAll("\n"); 55 | 56 | try writer.writeAll("\n"); 57 | } 58 | 59 | try writer.writeAll("## Properties\n"); 60 | try writer.writeAll("\n"); 61 | 62 | for (protocol.layout_format.properties) |prop| { 63 | try writer.print("

{s}

\n", .{ 64 | @tagName(prop.value), 65 | prop.property, 66 | }); 67 | 68 | if (prop.description.len > 0) { 69 | try writer.writeAll(prop.description); 70 | try writer.writeAll("\n"); 71 | } else { 72 | std.log.warn("Property {s} is missing a description!", .{prop.property}); 73 | try writer.writeAll("This property doesn't have any documentation at this moment.\n"); 74 | } 75 | 76 | try writer.writeAll("\n"); 77 | 78 | try writer.print("**Data Type:** `{s}`\n", .{@tagName(prop.type)}); 79 | try writer.writeAll("\n"); 80 | 81 | if (prop.type == .enumeration) { 82 | try writer.writeAll("**Possible Values:** "); 83 | for (prop.allowed_enums) |enum_id, i| { 84 | const enumeration = getEnumInfo(enum_id); 85 | if (i > 0) { 86 | try writer.writeAll(", "); 87 | } 88 | try writer.print("`{s}`", .{enumeration.enumeration}); 89 | } 90 | } 91 | 92 | try writer.writeAll("\n"); 93 | } 94 | 95 | return 0; 96 | } 97 | 98 | fn getPropertyInfo(id: protocol.Property) protocol.layout_format.PropertyDescriptor { 99 | for (protocol.layout_format.properties) |prop| { 100 | if (prop.value == id) 101 | return prop; 102 | } 103 | @panic("Someone forget to add a property to the descriptor list!"); 104 | } 105 | 106 | fn getEnumInfo(id: protocol.Enum) protocol.layout_format.EnumDescriptor { 107 | for (protocol.layout_format.enumerations) |enumerator| { 108 | if (enumerator.value == id) 109 | return enumerator; 110 | } 111 | @panic("Someone forget to add a enumeration to the descriptor list!"); 112 | } 113 | -------------------------------------------------------------------------------- /src/tools/wireshark-dissector.lua: -------------------------------------------------------------------------------- 1 | dunstblick_discovery = Proto("dunst", "Dunstblick Discovery") 2 | 3 | local message_length = ProtoField.bytes("dunst.magic", "magic", base.SPACE) 4 | local message_type = ProtoField.uint16("dunst.type", "type", base.DEC, { 5 | [0] = "discover", 6 | [1] = "discover_response", 7 | }) 8 | 9 | local features = ProtoField.uint16("dunst.feature", "Features", base.HEX) 10 | local has_description = ProtoField.bool("dunst.feature.has_description", "has_description", 16, {}, 1) 11 | local has_icon = ProtoField.bool("dunst.feature.has_icon", "has_icon", 16, {}, 2) 12 | local requires_auth = ProtoField.bool("dunst.feature.requires_auth", "requires_auth", 16, {}, 4) 13 | local wants_username = ProtoField.bool("dunst.feature.wants_username", "wants_username", 16, {}, 8) 14 | local wants_password = ProtoField.bool("dunst.feature.wants_password", "wants_password", 16, {}, 16) 15 | local is_encrypted = ProtoField.bool("dunst.feature.is_encrypted", "is_encrypted", 16, {}, 32) 16 | 17 | local tcp_port = ProtoField.uint16("dunst.tcp_port", "TCP Port", base.DEC) 18 | local display_name = ProtoField.stringz("dunst.display_name", "Display Name", base.UNICODE) 19 | 20 | local short_desc = ProtoField.stringz("dunst.short_desc", "App Description", base.UNICODE) 21 | 22 | local tvg_icon = ProtoField.bytes("dunst.iconfoo", "App Icon", base.NONE) 23 | local tvg_icon_len = ProtoField.uint16("dunst.iconfoo.len", "Size", base.DEC) 24 | local tvg_icon_bits = ProtoField.bytes("dunst.iconfoo.bits", "Size", base.NONE) 25 | 26 | dunstblick_discovery.fields = { 27 | message_length, 28 | message_type, 29 | features, 30 | has_description, 31 | has_icon, 32 | requires_auth, 33 | wants_username, 34 | wants_password, 35 | is_encrypted, 36 | tcp_port, 37 | display_name, 38 | short_desc, 39 | tvg_icon, 40 | tvg_icon_len, 41 | tvg_icon_bits, 42 | } 43 | 44 | function dunstblick_discovery.dissector(buffer, pinfo, tree) 45 | length = buffer:len() 46 | if length == 0 then return end 47 | 48 | pinfo.cols.protocol = "Dunstblick" 49 | 50 | local subtree = tree:add(dunstblick_discovery, buffer(), "Dunstblick Discovery") 51 | 52 | subtree:add_le(message_length, buffer(0,4)) 53 | 54 | local discover_respond = subtree:add_le(message_type, buffer(4,2)) 55 | 56 | local msg_type = buffer(4,2):le_uint() 57 | if msg_type == 1 then 58 | local features_tree = discover_respond:add_le(features, buffer(6,2)) 59 | local feature_fld = buffer(6,2) 60 | do 61 | features_tree:add_le(has_description, feature_fld) 62 | features_tree:add_le(has_icon, feature_fld) 63 | features_tree:add_le(requires_auth, feature_fld) 64 | features_tree:add_le(wants_username, feature_fld) 65 | features_tree:add_le(wants_password, feature_fld) 66 | features_tree:add_le(is_encrypted, feature_fld) 67 | end 68 | 69 | discover_respond:add_le(tcp_port, buffer(8,2)) 70 | discover_respond:add_le(display_name, buffer(10,64)) 71 | 72 | local feature_int = feature_fld:le_uint() 73 | local offset = 74 74 | 75 | if bit.band(feature_int, 1) ~= 0 then 76 | discover_respond:add_le(short_desc, buffer(offset,256)) 77 | offset = offset + 256 78 | end 79 | 80 | if bit.band(feature_int, 2) ~= 0 then 81 | local bits = buffer(offset, 514) 82 | local icon_tree = discover_respond:add_le(tvg_icon, bits) 83 | 84 | icon_tree:add_le(tvg_icon_len, bits(0,2)) 85 | 86 | local len = math.min(512, bits(0,2):le_uint()) 87 | icon_tree:add_le(tvg_icon_bits, bits(2,len)) 88 | offset = offset + 514 89 | end 90 | 91 | end 92 | end 93 | 94 | local tcp_port = DissectorTable.get("udp.port") 95 | tcp_port:add(1309, dunstblick_discovery) -------------------------------------------------------------------------------- /system-root/bin/hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | printf("Hello, World\r\n"); 5 | } -------------------------------------------------------------------------------- /system-root/bin/hello.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/system-root/bin/hello.exe -------------------------------------------------------------------------------- /system-root/bin/hello.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/system-root/bin/hello.pdb -------------------------------------------------------------------------------- /system-root/config/services/date.json: -------------------------------------------------------------------------------- 1 | { 2 | "command": [ 3 | "date" 4 | ] 5 | } -------------------------------------------------------------------------------- /system-root/config/services/hello-windows.json: -------------------------------------------------------------------------------- 1 | { 2 | "command": [ 3 | "system-root/bin/hello.exe" 4 | ] 5 | } -------------------------------------------------------------------------------- /system-root/config/services/mqtt-eject.json: -------------------------------------------------------------------------------- 1 | { 2 | "autostart": true, 3 | "restart": "always", 4 | "command": [ 5 | "nc", 6 | "-l", 7 | "8080" 8 | ] 9 | } -------------------------------------------------------------------------------- /vendor/file-5.40/AUTHORS: -------------------------------------------------------------------------------- 1 | See COPYING. 2 | -------------------------------------------------------------------------------- /vendor/file-5.40/COPYING: -------------------------------------------------------------------------------- 1 | $File: COPYING,v 1.2 2018/09/09 20:33:28 christos Exp $ 2 | Copyright (c) Ian F. Darwin 1986, 1987, 1989, 1990, 1991, 1992, 1994, 1995. 3 | Software written by Ian F. Darwin and others; 4 | maintained 1994- Christos Zoulas. 5 | 6 | This software is not subject to any export provision of the United States 7 | Department of Commerce, and may be exported to any country or planet. 8 | 9 | Redistribution and use in source and binary forms, with or without 10 | modification, are permitted provided that the following conditions 11 | are met: 12 | 1. Redistributions of source code must retain the above copyright 13 | notice immediately at the beginning of the file, without modification, 14 | this list of conditions, and the following disclaimer. 15 | 2. Redistributions in binary form must reproduce the above copyright 16 | notice, this list of conditions and the following disclaimer in the 17 | documentation and/or other materials provided with the distribution. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 23 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 | SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /vendor/file-5.40/MAINT: -------------------------------------------------------------------------------- 1 | $File: MAINT,v 1.10 2008/02/05 19:08:11 christos Exp $ 2 | 3 | Maintenance notes: 4 | 5 | I am continuing to maintain the file command. I welcome your help, 6 | but to make my life easier I'd like to request the following: 7 | 8 | - Do not distribute changed versions. 9 | 10 | People trying to be helpful occasionally put up their hacked versions 11 | of the file command for anonymous FTP, and people all over the 12 | world get copies of the hacked versions. Within a day or two I am 13 | getting email from around the world asking me why "my" file command 14 | won't compile!!! Needless to say this detracts from the limited 15 | time I have available to work on the actual software. Therefore I 16 | ask you again to please NOT distribute your changed version. If 17 | you need to make changes, please add a patch file next to the 18 | distribution tar, and a README file that clearly explains what you 19 | are trying to fix. 20 | 21 | Thank you for your assistance and cooperation. 22 | 23 | Code Overview 24 | 25 | This is a rough idea of the control flow from the main program: 26 | 27 | file.c main() 28 | file.c process (called for each file) 29 | printf file name 30 | magic.c magic_file() 31 | fsmagic.c file_fsmagic() 32 | (handles statbuf modes for DEV) 33 | (handles statbuf modes for executable &c. 34 | reads data from file. 35 | funcs.c: file_buffer() 36 | compress.c file_zmagic() 37 | is_tar.c file_is_tar() 38 | softmagic.c file_softmagic() 39 | match() - looks for match against main magic database 40 | ascmagic.c file_ascmagic() 41 | readelf.c file_tryelf() 42 | "unknown" 43 | 44 | Christos Zoulas (see README for email address) 45 | -------------------------------------------------------------------------------- /vendor/file-5.40/NEWS: -------------------------------------------------------------------------------- 1 | See ChangeLog. 2 | -------------------------------------------------------------------------------- /vendor/file-5.40/TODO: -------------------------------------------------------------------------------- 1 | Most TODOs live in the TODO section of doc/file.man (i.e. file(1)). 2 | They are more visible there, so please add any further TODOs to that 3 | file, not here. More speculative material can live here. 4 | 5 | (This change was made when Reuben Thomas noticed that all the bugs 6 | listed in the BUGS section of the man page had been fixed!) 7 | 8 | --- 9 | It would be nice to simplify file considerably. For example, 10 | reimplement the apprentice and non-pattern magic methods in Python, 11 | and compile the magic patterns to a giant regex (or something similar; 12 | maybe using Ragel (http://www.complang.org/ragel/)) so that only a 13 | small amount of C is needed (because fast execution is typically only 14 | required for soft magic, not the more detailed information given by 15 | hard-wired routines). In this regard, note that hplip, which is 16 | BSD-licensed, has a magic reimplementation in Python. 17 | --- 18 | Read the kerberos magic entry for more ideas. 19 | --- 20 | Write a string merger to make magic entry sizes dynamic. 21 | Strings will be converted to offsets from the string table. 22 | --- 23 | Programming language support, we can introduce the concept of a group 24 | of rules where n rules need to match before the rule is positive. This 25 | could require structural changes to the matching code :-( 26 | 27 | 0 group 2 # require 2 matches 28 | # rule 1 29 | >0 .... 30 | ... 31 | # rule 2 32 | >0 .... 33 | ... 34 | --- 35 | - Merge the stat code dance in one place and keep it in one place 36 | (perhaps struct buffer). 37 | - Enable seeking around if offset > nbytes if possible (the fd 38 | is seekable). 39 | - We could use file_pipe2file more (for EOF offsets, CDF documents), 40 | but that is expensive; perhaps we should provide a way to disable it 41 | - The implementation of struct buffer needs re-thinking and more work. 42 | For example we don't always pass the fd in the child. This is not 43 | important yet as we don't have yet cases where use/indirect magic 44 | needs negative offsets. 45 | - Really the whole thing just needs here's an (offset, buffer, size) 46 | you have (filebuffer, filebuffersize &&|| fd), fill the buffer with 47 | data from offset. The buffer API should be changed to just do that. 48 | 49 | christos 50 | -------------------------------------------------------------------------------- /vendor/file-5.40/magic/magic.mgc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/vendor/file-5.40/magic/magic.mgc -------------------------------------------------------------------------------- /vendor/file-5.40/src/asctime_r.c: -------------------------------------------------------------------------------- 1 | /* $File: asctime_r.c,v 1.1 2012/05/15 17:14:36 christos Exp $ */ 2 | 3 | #include "file.h" 4 | #ifndef lint 5 | FILE_RCSID("@(#)$File: asctime_r.c,v 1.1 2012/05/15 17:14:36 christos Exp $") 6 | #endif /* lint */ 7 | #include 8 | #include 9 | 10 | /* asctime_r is not thread-safe anyway */ 11 | char * 12 | asctime_r(const struct tm *t, char *dst) 13 | { 14 | char *p = asctime(t); 15 | if (p == NULL) 16 | return NULL; 17 | memcpy(dst, p, 26); 18 | return dst; 19 | } 20 | -------------------------------------------------------------------------------- /vendor/file-5.40/src/asprintf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Ian F. Darwin 1986-1995. 3 | * Software written by Ian F. Darwin and others; 4 | * maintained 1995-present by Christos Zoulas and others. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice immediately at the beginning of the file, without modification, 11 | * this list of conditions, and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 20 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | #include "file.h" 30 | 31 | #ifndef lint 32 | FILE_RCSID("@(#)$File: asprintf.c,v 1.5 2018/09/09 20:33:28 christos Exp $") 33 | #endif 34 | 35 | int asprintf(char **ptr, const char *fmt, ...) 36 | { 37 | va_list vargs; 38 | int retval; 39 | 40 | va_start(vargs, fmt); 41 | retval = vasprintf(ptr, fmt, vargs); 42 | va_end(vargs); 43 | 44 | return retval; 45 | } 46 | -------------------------------------------------------------------------------- /vendor/file-5.40/src/buffer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Christos Zoulas 2017. 3 | * All Rights Reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice immediately at the beginning of the file, without modification, 10 | * this list of conditions, and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 | * SUCH DAMAGE. 26 | */ 27 | #include "file.h" 28 | 29 | #ifndef lint 30 | FILE_RCSID("@(#)$File: buffer.c,v 1.8 2020/02/16 15:52:49 christos Exp $") 31 | #endif /* lint */ 32 | 33 | #include "magic.h" 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | void 40 | buffer_init(struct buffer *b, int fd, const struct stat *st, const void *data, 41 | size_t len) 42 | { 43 | b->fd = fd; 44 | if (st) 45 | memcpy(&b->st, st, sizeof(b->st)); 46 | else if (b->fd == -1 || fstat(b->fd, &b->st) == -1) 47 | memset(&b->st, 0, sizeof(b->st)); 48 | b->fbuf = data; 49 | b->flen = len; 50 | b->eoff = 0; 51 | b->ebuf = NULL; 52 | b->elen = 0; 53 | } 54 | 55 | void 56 | buffer_fini(struct buffer *b) 57 | { 58 | free(b->ebuf); 59 | } 60 | 61 | int 62 | buffer_fill(const struct buffer *bb) 63 | { 64 | struct buffer *b = CCAST(struct buffer *, bb); 65 | 66 | if (b->elen != 0) 67 | return b->elen == FILE_BADSIZE ? -1 : 0; 68 | 69 | if (!S_ISREG(b->st.st_mode)) 70 | goto out; 71 | 72 | b->elen = CAST(size_t, b->st.st_size) < b->flen ? 73 | CAST(size_t, b->st.st_size) : b->flen; 74 | if ((b->ebuf = malloc(b->elen)) == NULL) 75 | goto out; 76 | 77 | b->eoff = b->st.st_size - b->elen; 78 | if (pread(b->fd, b->ebuf, b->elen, b->eoff) == -1) { 79 | free(b->ebuf); 80 | b->ebuf = NULL; 81 | goto out; 82 | } 83 | 84 | return 0; 85 | out: 86 | b->elen = FILE_BADSIZE; 87 | return -1; 88 | } 89 | -------------------------------------------------------------------------------- /vendor/file-5.40/src/ctime_r.c: -------------------------------------------------------------------------------- 1 | /* $File: ctime_r.c,v 1.1 2012/05/15 17:14:36 christos Exp $ */ 2 | 3 | #include "file.h" 4 | #ifndef lint 5 | FILE_RCSID("@(#)$File: ctime_r.c,v 1.1 2012/05/15 17:14:36 christos Exp $") 6 | #endif /* lint */ 7 | #include 8 | #include 9 | 10 | /* ctime_r is not thread-safe anyway */ 11 | char * 12 | ctime_r(const time_t *t, char *dst) 13 | { 14 | char *p = ctime(t); 15 | if (p == NULL) 16 | return NULL; 17 | memcpy(dst, p, 26); 18 | return dst; 19 | } 20 | -------------------------------------------------------------------------------- /vendor/file-5.40/src/der.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2016 Christos Zoulas 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 15 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 16 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 18 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | * POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | extern int der_offs(struct magic_set *, struct magic *, size_t); 28 | extern int der_cmp(struct magic_set *, struct magic *); 29 | -------------------------------------------------------------------------------- /vendor/file-5.40/src/dprintf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Ian F. Darwin 1986-1995. 3 | * Software written by Ian F. Darwin and others; 4 | * maintained 1995-present by Christos Zoulas and others. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice immediately at the beginning of the file, without modification, 11 | * this list of conditions, and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 20 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | #include "file.h" 29 | 30 | #ifndef lint 31 | FILE_RCSID("@(#)$File: dprintf.c,v 1.2 2018/09/09 20:33:28 christos Exp $") 32 | #endif /* lint */ 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | int 40 | dprintf(int fd, const char *fmt, ...) 41 | { 42 | va_list ap; 43 | /* Simpler than using vasprintf() here, since we never need more */ 44 | char buf[1024]; 45 | int len; 46 | 47 | va_start(ap, fmt); 48 | len = vsnprintf(buf, sizeof(buf), fmt, ap); 49 | va_end(ap); 50 | 51 | if ((size_t)len >= sizeof(buf)) 52 | return -1; 53 | 54 | if (write(fd, buf, (size_t)len) != len) 55 | return -1; 56 | 57 | return len; 58 | } 59 | -------------------------------------------------------------------------------- /vendor/file-5.40/src/elfclass.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Christos Zoulas 2008. 3 | * All Rights Reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice immediately at the beginning of the file, without modification, 10 | * this list of conditions, and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 | * SUCH DAMAGE. 26 | */ 27 | if (nbytes <= sizeof(elfhdr)) 28 | return 0; 29 | 30 | u.l = 1; 31 | (void)memcpy(&elfhdr, buf, sizeof elfhdr); 32 | swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[EI_DATA]; 33 | 34 | type = elf_getu16(swap, elfhdr.e_type); 35 | notecount = ms->elf_notes_max; 36 | switch (type) { 37 | #ifdef ELFCORE 38 | case ET_CORE: 39 | phnum = elf_getu16(swap, elfhdr.e_phnum); 40 | if (phnum > ms->elf_phnum_max) 41 | return toomany(ms, "program headers", phnum); 42 | flags |= FLAGS_IS_CORE; 43 | if (dophn_core(ms, clazz, swap, fd, 44 | CAST(off_t, elf_getu(swap, elfhdr.e_phoff)), phnum, 45 | CAST(size_t, elf_getu16(swap, elfhdr.e_phentsize)), 46 | fsize, &flags, ¬ecount) == -1) 47 | return -1; 48 | break; 49 | #endif 50 | case ET_EXEC: 51 | case ET_DYN: 52 | phnum = elf_getu16(swap, elfhdr.e_phnum); 53 | if (phnum > ms->elf_phnum_max) 54 | return toomany(ms, "program", phnum); 55 | shnum = elf_getu16(swap, elfhdr.e_shnum); 56 | if (shnum > ms->elf_shnum_max) 57 | return toomany(ms, "section", shnum); 58 | if (dophn_exec(ms, clazz, swap, fd, 59 | CAST(off_t, elf_getu(swap, elfhdr.e_phoff)), phnum, 60 | CAST(size_t, elf_getu16(swap, elfhdr.e_phentsize)), 61 | fsize, shnum, &flags, ¬ecount) == -1) 62 | return -1; 63 | /*FALLTHROUGH*/ 64 | case ET_REL: 65 | shnum = elf_getu16(swap, elfhdr.e_shnum); 66 | if (shnum > ms->elf_shnum_max) 67 | return toomany(ms, "section headers", shnum); 68 | if (doshn(ms, clazz, swap, fd, 69 | CAST(off_t, elf_getu(swap, elfhdr.e_shoff)), shnum, 70 | CAST(size_t, elf_getu16(swap, elfhdr.e_shentsize)), 71 | fsize, elf_getu16(swap, elfhdr.e_machine), 72 | CAST(int, elf_getu16(swap, elfhdr.e_shstrndx)), 73 | &flags, ¬ecount) == -1) 74 | return -1; 75 | break; 76 | 77 | default: 78 | break; 79 | } 80 | if (notecount == 0) 81 | return toomany(ms, "notes", ms->elf_notes_max); 82 | return 1; 83 | -------------------------------------------------------------------------------- /vendor/file-5.40/src/file_opts.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Table of command-line options 3 | * 4 | * The first column specifies the short name, if any, or 0 if none. 5 | * The second column specifies the long name. 6 | * The third column specifies whether it takes a parameter. 7 | * The fourth columns specifies whether is is marked as "default" 8 | * if POSIXLY_CORRECT is defined: 1, 9 | * if POSIXLY_CORRECT is not defined: 2. 10 | * The fifth column is the documentation. 11 | * 12 | * N.B. The long options' order must correspond to the code in file.c, 13 | * and OPTSTRING must be kept up-to-date with the short options. 14 | * Pay particular attention to the numbers of long-only options in the 15 | * switch statement! 16 | */ 17 | 18 | OPT_LONGONLY("help", 0, 0, 19 | " display this help and exit\n", OPT_HELP) 20 | OPT('v', "version", 0, 0, 21 | " output version information and exit\n") 22 | OPT('m', "magic-file", 1, 0, 23 | " LIST use LIST as a colon-separated list of magic\n" 24 | " number files\n") 25 | OPT('z', "uncompress", 0, 0, 26 | " try to look inside compressed files\n") 27 | OPT('Z', "uncompress-noreport", 0, 0, 28 | " only print the contents of compressed files\n") 29 | OPT('b', "brief", 0, 0, 30 | " do not prepend filenames to output lines\n") 31 | OPT('c', "checking-printout", 0, 0, 32 | " print the parsed form of the magic file, use in\n" 33 | " conjunction with -m to debug a new magic file\n" 34 | " before installing it\n") 35 | OPT('e', "exclude", 1, 0, 36 | " TEST exclude TEST from the list of test to be\n" 37 | " performed for file. Valid tests are:\n" 38 | " %e\n") 39 | OPT_LONGONLY("exclude-quiet", 1, 0, 40 | " TEST like exclude, but ignore unknown tests\n", OPT_EXCLUDE_QUIET) 41 | OPT('f', "files-from", 1, 0, 42 | " FILE read the filenames to be examined from FILE\n") 43 | OPT('F', "separator", 1, 0, 44 | " STRING use string as separator instead of `:'\n") 45 | OPT('i', "mime", 0, 0, 46 | " output MIME type strings (--mime-type and\n" 47 | " --mime-encoding)\n") 48 | OPT_LONGONLY("apple", 0, 0, 49 | " output the Apple CREATOR/TYPE\n", OPT_APPLE) 50 | OPT_LONGONLY("extension", 0, 0, 51 | " output a slash-separated list of extensions\n", OPT_EXTENSIONS) 52 | OPT_LONGONLY("mime-type", 0, 0, 53 | " output the MIME type\n", OPT_MIME_TYPE) 54 | OPT_LONGONLY("mime-encoding", 0, 0, 55 | " output the MIME encoding\n", OPT_MIME_ENCODING) 56 | OPT('k', "keep-going", 0, 0, 57 | " don't stop at the first match\n") 58 | OPT('l', "list", 0, 0, 59 | " list magic strength\n") 60 | #ifdef S_IFLNK 61 | OPT('L', "dereference", 0, 1, 62 | " follow symlinks") 63 | OPT('h', "no-dereference", 0, 2, 64 | " don't follow symlinks") 65 | #endif 66 | OPT('n', "no-buffer", 0, 0, 67 | " do not buffer output\n") 68 | OPT('N', "no-pad", 0, 0, 69 | " do not pad output\n") 70 | OPT('0', "print0", 0, 0, 71 | " terminate filenames with ASCII NUL\n") 72 | #if defined(HAVE_UTIME) || defined(HAVE_UTIMES) 73 | OPT('p', "preserve-date", 0, 0, 74 | " preserve access times on files\n") 75 | #endif 76 | OPT('P', "parameter", 1, 0, 77 | " set file engine parameter limits\n" 78 | " %P\n") 79 | OPT('r', "raw", 0, 0, 80 | " don't translate unprintable chars to \\ooo\n") 81 | OPT('s', "special-files", 0, 0, 82 | " treat special (block/char devices) files as\n" 83 | " ordinary ones\n") 84 | OPT('S', "no-sandbox", 0, 0, 85 | " disable system call sandboxing\n") 86 | OPT('C', "compile", 0, 0, 87 | " compile file specified by -m\n") 88 | OPT('d', "debug", 0, 0, 89 | " print debugging messages\n") 90 | -------------------------------------------------------------------------------- /vendor/file-5.40/src/getline.c: -------------------------------------------------------------------------------- 1 | /* $NetBSD: getline.c,v 1.2 2014/09/16 17:23:50 christos Exp $ */ 2 | 3 | /*- 4 | * Copyright (c) 2011 The NetBSD Foundation, Inc. 5 | * All rights reserved. 6 | * 7 | * This code is derived from software contributed to The NetBSD Foundation 8 | * by Christos Zoulas. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #include "file.h" 33 | #if !HAVE_GETLINE 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | public ssize_t 41 | getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp) 42 | { 43 | char *ptr, *eptr; 44 | 45 | 46 | if (*buf == NULL || *bufsiz == 0) { 47 | *bufsiz = BUFSIZ; 48 | if ((*buf = malloc(*bufsiz)) == NULL) 49 | return -1; 50 | } 51 | 52 | for (ptr = *buf, eptr = *buf + *bufsiz;;) { 53 | int c = fgetc(fp); 54 | if (c == -1) { 55 | if (feof(fp)) { 56 | ssize_t diff = (ssize_t)(ptr - *buf); 57 | if (diff != 0) { 58 | *ptr = '\0'; 59 | return diff; 60 | } 61 | } 62 | return -1; 63 | } 64 | *ptr++ = c; 65 | if (c == delimiter) { 66 | *ptr = '\0'; 67 | return ptr - *buf; 68 | } 69 | if (ptr + 2 >= eptr) { 70 | char *nbuf; 71 | size_t nbufsiz = *bufsiz * 2; 72 | ssize_t d = ptr - *buf; 73 | if ((nbuf = realloc(*buf, nbufsiz)) == NULL) 74 | return -1; 75 | *buf = nbuf; 76 | *bufsiz = nbufsiz; 77 | eptr = nbuf + nbufsiz; 78 | ptr = nbuf + d; 79 | } 80 | } 81 | } 82 | 83 | public ssize_t 84 | getline(char **buf, size_t *bufsiz, FILE *fp) 85 | { 86 | return getdelim(buf, bufsiz, '\n', fp); 87 | } 88 | 89 | #endif 90 | 91 | #ifdef TEST 92 | int 93 | main(int argc, char *argv[]) 94 | { 95 | char *p = NULL; 96 | ssize_t len; 97 | size_t n = 0; 98 | 99 | while ((len = getline(&p, &n, stdin)) != -1) 100 | (void)printf("%" SIZE_T_FORMAT "d %s", len, p); 101 | free(p); 102 | return 0; 103 | } 104 | #endif 105 | -------------------------------------------------------------------------------- /vendor/file-5.40/src/gmtime_r.c: -------------------------------------------------------------------------------- 1 | /* $File: gmtime_r.c,v 1.2 2015/07/11 14:41:37 christos Exp $ */ 2 | 3 | #include "file.h" 4 | #ifndef lint 5 | FILE_RCSID("@(#)$File: gmtime_r.c,v 1.2 2015/07/11 14:41:37 christos Exp $") 6 | #endif /* lint */ 7 | #include 8 | #include 9 | 10 | /* asctime_r is not thread-safe anyway */ 11 | struct tm * 12 | gmtime_r(const time_t *t, struct tm *tm) 13 | { 14 | struct tm *tmp = gmtime(t); 15 | if (tmp == NULL) 16 | return NULL; 17 | memcpy(tm, tmp, sizeof(*tm)); 18 | return tmp; 19 | } 20 | -------------------------------------------------------------------------------- /vendor/file-5.40/src/localtime_r.c: -------------------------------------------------------------------------------- 1 | /* $File: localtime_r.c,v 1.2 2015/07/11 14:41:37 christos Exp $ */ 2 | 3 | #include "file.h" 4 | #ifndef lint 5 | FILE_RCSID("@(#)$File: localtime_r.c,v 1.2 2015/07/11 14:41:37 christos Exp $") 6 | #endif /* lint */ 7 | #include 8 | #include 9 | 10 | /* asctime_r is not thread-safe anyway */ 11 | struct tm * 12 | localtime_r(const time_t *t, struct tm *tm) 13 | { 14 | struct tm *tmp = localtime(t); 15 | if (tmp == NULL) 16 | return NULL; 17 | memcpy(tm, tmp, sizeof(*tm)); 18 | return tmp; 19 | } 20 | -------------------------------------------------------------------------------- /vendor/file-5.40/src/mygetopt.h: -------------------------------------------------------------------------------- 1 | /* $NetBSD: getopt.h,v 1.8 2007/11/06 19:21:18 christos Exp $ */ 2 | 3 | /*- 4 | * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 | * All rights reserved. 6 | * 7 | * This code is derived from software contributed to The NetBSD Foundation 8 | * by Dieter Baron and Thomas Klausner. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. All advertising materials mentioning features or use of this software 19 | * must display the following acknowledgement: 20 | * This product includes software developed by the NetBSD 21 | * Foundation, Inc. and its contributors. 22 | * 4. Neither the name of The NetBSD Foundation nor the names of its 23 | * contributors may be used to endorse or promote products derived 24 | * from this software without specific prior written permission. 25 | * 26 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 | * POSSIBILITY OF SUCH DAMAGE. 37 | */ 38 | 39 | #ifndef _GETOPT_H_ 40 | #define _GETOPT_H_ 41 | 42 | #include 43 | 44 | /* 45 | * Gnu like getopt_long() and BSD4.4 getsubopt()/optreset extensions 46 | */ 47 | #define no_argument 0 48 | #define required_argument 1 49 | #define optional_argument 2 50 | 51 | struct option { 52 | /* name of long option */ 53 | const char *name; 54 | /* 55 | * one of no_argument, required_argument, and optional_argument: 56 | * whether option takes an argument 57 | */ 58 | int has_arg; 59 | /* if not NULL, set *flag to val when option found */ 60 | int *flag; 61 | /* if flag not NULL, value to set *flag to; else return value */ 62 | int val; 63 | }; 64 | 65 | int getopt_long(int, char * const *, const char *, 66 | const struct option *, int *); 67 | 68 | #endif /* !_GETOPT_H_ */ 69 | -------------------------------------------------------------------------------- /vendor/file-5.40/src/pread.c: -------------------------------------------------------------------------------- 1 | #include "file.h" 2 | #ifndef lint 3 | FILE_RCSID("@(#)$File: pread.c,v 1.3 2014/09/15 19:11:25 christos Exp $") 4 | #endif /* lint */ 5 | #include 6 | #include 7 | 8 | ssize_t 9 | pread(int fd, void *buf, size_t len, off_t off) { 10 | off_t old; 11 | ssize_t rv; 12 | 13 | if ((old = lseek(fd, off, SEEK_SET)) == -1) 14 | return -1; 15 | 16 | if ((rv = read(fd, buf, len)) == -1) 17 | return -1; 18 | 19 | if (lseek(fd, old, SEEK_SET) == -1) 20 | return -1; 21 | 22 | return rv; 23 | } 24 | -------------------------------------------------------------------------------- /vendor/file-5.40/src/strcasestr.c: -------------------------------------------------------------------------------- 1 | /* $NetBSD: strcasestr.c,v 1.3 2005/11/29 03:12:00 christos Exp $ */ 2 | 3 | /*- 4 | * Copyright (c) 1990, 1993 5 | * The Regents of the University of California. All rights reserved. 6 | * 7 | * This code is derived from software contributed to Berkeley by 8 | * Chris Torek. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the University nor the names of its contributors 19 | * may be used to endorse or promote products derived from this software 20 | * without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 | * SUCH DAMAGE. 33 | */ 34 | 35 | #if defined(LIBC_SCCS) && !defined(lint) 36 | __RCSID("$NetBSD: strcasestr.c,v 1.3 2005/11/29 03:12:00 christos Exp $"); 37 | __RCSID("$NetBSD: strncasecmp.c,v 1.2 2007/06/04 18:19:27 christos Exp $"); 38 | #endif /* LIBC_SCCS and not lint */ 39 | 40 | #include "file.h" 41 | 42 | #include 43 | #include 44 | #include 45 | 46 | static int 47 | _strncasecmp(const char *s1, const char *s2, size_t n) 48 | { 49 | if (n != 0) { 50 | const unsigned char *us1 = (const unsigned char *)s1, 51 | *us2 = (const unsigned char *)s2; 52 | 53 | do { 54 | if (tolower(*us1) != tolower(*us2++)) 55 | return tolower(*us1) - tolower(*--us2); 56 | if (*us1++ == '\0') 57 | break; 58 | } while (--n != 0); 59 | } 60 | return 0; 61 | } 62 | 63 | /* 64 | * Find the first occurrence of find in s, ignore case. 65 | */ 66 | char * 67 | strcasestr(const char *s, const char *find) 68 | { 69 | char c, sc; 70 | size_t len; 71 | 72 | if ((c = *find++) != 0) { 73 | c = tolower((unsigned char)c); 74 | len = strlen(find); 75 | do { 76 | do { 77 | if ((sc = *s++) == 0) 78 | return (NULL); 79 | } while ((char)tolower((unsigned char)sc) != c); 80 | } while (_strncasecmp(s, find, len) != 0); 81 | s--; 82 | } 83 | return (char *)(intptr_t)(s); 84 | } 85 | -------------------------------------------------------------------------------- /vendor/file-5.40/src/strlcat.c: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */ 2 | 3 | /* 4 | * Copyright (c) 1998 Todd C. Miller 5 | * 6 | * Permission to use, copy, modify, and distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | /* OPENBSD ORIGINAL: lib/libc/string/strlcat.c */ 20 | #include "file.h" 21 | 22 | #include 23 | #include 24 | 25 | /* 26 | * Appends src to string dst of size siz (unlike strncat, siz is the 27 | * full size of dst, not space left). At most siz-1 characters 28 | * will be copied. Always NUL terminates (unless siz <= strlen(dst)). 29 | * Returns strlen(src) + MIN(siz, strlen(initial dst)). 30 | * If retval >= siz, truncation occurred. 31 | */ 32 | size_t 33 | strlcat(char *dst, const char *src, size_t siz) 34 | { 35 | char *d = dst; 36 | const char *s = src; 37 | size_t n = siz; 38 | size_t dlen; 39 | 40 | /* Find the end of dst and adjust bytes left but don't go past end */ 41 | while (n-- != 0 && *d != '\0') 42 | d++; 43 | dlen = d - dst; 44 | n = siz - dlen; 45 | 46 | if (n == 0) 47 | return(dlen + strlen(s)); 48 | while (*s != '\0') { 49 | if (n != 1) { 50 | *d++ = *s; 51 | n--; 52 | } 53 | s++; 54 | } 55 | *d = '\0'; 56 | 57 | return(dlen + (s - src)); /* count does not include NUL */ 58 | } 59 | -------------------------------------------------------------------------------- /vendor/file-5.40/src/strlcpy.c: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: strlcpy.c,v 1.10 2005/08/08 08:05:37 espie Exp $ */ 2 | 3 | /* 4 | * Copyright (c) 1998 Todd C. Miller 5 | * 6 | * Permission to use, copy, modify, and distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | /* OPENBSD ORIGINAL: lib/libc/string/strlcpy.c */ 20 | #include "file.h" 21 | 22 | #include 23 | #include 24 | 25 | /* 26 | * Copy src to string dst of size siz. At most siz-1 characters 27 | * will be copied. Always NUL terminates (unless siz == 0). 28 | * Returns strlen(src); if retval >= siz, truncation occurred. 29 | */ 30 | size_t 31 | strlcpy(char *dst, const char *src, size_t siz) 32 | { 33 | char *d = dst; 34 | const char *s = src; 35 | size_t n = siz; 36 | 37 | /* Copy as many bytes as will fit */ 38 | if (n != 0 && --n != 0) { 39 | do { 40 | if ((*d++ = *s++) == 0) 41 | break; 42 | } while (--n != 0); 43 | } 44 | 45 | /* Not enough room in dst, add NUL and traverse rest of src */ 46 | if (n == 0) { 47 | if (siz != 0) 48 | *d = '\0'; /* NUL-terminate dst */ 49 | while (*s++) 50 | ; 51 | } 52 | 53 | return(s - src - 1); /* count does not include NUL */ 54 | } 55 | -------------------------------------------------------------------------------- /vendor/file-5.40/src/tar.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Ian F. Darwin 1986-1995. 3 | * Software written by Ian F. Darwin and others; 4 | * maintained 1995-present by Christos Zoulas and others. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice immediately at the beginning of the file, without modification, 11 | * this list of conditions, and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 20 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | /* 29 | * Header file for public domain tar (tape archive) program. 30 | * 31 | * @(#)tar.h 1.20 86/10/29 Public Domain. 32 | * 33 | * Created 25 August 1985 by John Gilmore, ihnp4!hoptoad!gnu. 34 | * 35 | * $File: tar.h,v 1.13 2010/11/30 14:58:53 rrt Exp $ # checkin only 36 | */ 37 | 38 | /* 39 | * Header block on tape. 40 | * 41 | * I'm going to use traditional DP naming conventions here. 42 | * A "block" is a big chunk of stuff that we do I/O on. 43 | * A "record" is a piece of info that we care about. 44 | * Typically many "record"s fit into a "block". 45 | */ 46 | #define RECORDSIZE 512 47 | #define NAMSIZ 100 48 | #define TUNMLEN 32 49 | #define TGNMLEN 32 50 | 51 | union record { 52 | unsigned char charptr[RECORDSIZE]; 53 | struct header { 54 | char name[NAMSIZ]; 55 | char mode[8]; 56 | char uid[8]; 57 | char gid[8]; 58 | char size[12]; 59 | char mtime[12]; 60 | char chksum[8]; 61 | char linkflag; 62 | char linkname[NAMSIZ]; 63 | char magic[8]; 64 | char uname[TUNMLEN]; 65 | char gname[TGNMLEN]; 66 | char devmajor[8]; 67 | char devminor[8]; 68 | } header; 69 | }; 70 | 71 | /* The magic field is filled with this if uname and gname are valid. */ 72 | #define TMAGIC "ustar" /* 5 chars and a null */ 73 | #define GNUTMAGIC "ustar " /* 7 chars and a null */ 74 | -------------------------------------------------------------------------------- /vendor/pcre2-premade/regex.h: -------------------------------------------------------------------------------- 1 | #include -------------------------------------------------------------------------------- /vendor/xqlib-stripped/include/xcept: -------------------------------------------------------------------------------- 1 | #ifndef XQLIB_XCEPT_HPP 2 | #define XQLIB_XCEPT_HPP 3 | 4 | #include 5 | #include 6 | 7 | namespace xcept 8 | { 9 | #define XCEPTION(_Name) \ 10 | struct _Name : std::exception \ 11 | { \ 12 | std::string const msg; \ 13 | explicit _Name(std::string const & _msg) noexcept; \ 14 | virtual ~_Name() noexcept override; \ 15 | virtual const char* what() const noexcept override; \ 16 | } 17 | 18 | XCEPTION(invalid_argument); 19 | XCEPTION(invalid_operation); 20 | 21 | XCEPTION(io_error); 22 | XCEPTION(db_error); 23 | XCEPTION(end_of_stream); 24 | 25 | XCEPTION(critical_log); 26 | XCEPTION(compile_error); 27 | XCEPTION(opengl_error); 28 | 29 | #undef XCEPTION 30 | } 31 | 32 | #endif // XCEPT_HPP 33 | -------------------------------------------------------------------------------- /vendor/xqlib-stripped/include/xlog: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace xlog 7 | { 8 | enum log_level : int 9 | { 10 | all = std::numeric_limits::min(), 11 | verbose = -100, 12 | message = 0, 13 | warning = 100, 14 | error = 200, 15 | critical = 300, 16 | }; 17 | 18 | void set_verbosity(log_level min_level); 19 | 20 | void enable_colors(bool enabled); 21 | 22 | void abort_on_critical(bool enabled); 23 | 24 | struct log 25 | { 26 | private: 27 | log_level level; 28 | std::stringstream text; 29 | public: 30 | explicit log(log_level level = message); 31 | explicit log(char const * prefix, log_level level = message); 32 | log(log const &) = delete; 33 | log(log &&) = default; 34 | ~log(); 35 | public: 36 | template 37 | log & operator<< (T const & val) 38 | { 39 | text << val; 40 | return *this; 41 | } 42 | }; 43 | } 44 | 45 | #define XLOG_STR(x) #x 46 | #define XLOG_SSTR(x) XLOG_STR(x) 47 | 48 | #define XLOG_MSG() xlog::log(__FILE__ ":" XLOG_SSTR(__LINE__), xlog::message) 49 | #define XLOG_WARN() xlog::log(__FILE__ ":" XLOG_SSTR(__LINE__), xlog::warning) 50 | #define XLOG_ERROR() xlog::log(__FILE__ ":" XLOG_SSTR(__LINE__), xlog::error) 51 | #define XLOG_CRITICAL() xlog::log(__FILE__ ":" XLOG_SSTR(__LINE__), xlog::critical) 52 | #define XLOG_VERBOSE() xlog::log(__FILE__ ":" XLOG_SSTR(__LINE__), xlog::verbose) 53 | -------------------------------------------------------------------------------- /vendor/xqlib-stripped/include/xstd/optional: -------------------------------------------------------------------------------- 1 | #ifndef XQLIB_OPTIONAL_HPP 2 | #define XQLIB_OPTIONAL_HPP 3 | 4 | #include 5 | 6 | namespace xstd 7 | { 8 | using tl::optional; 9 | using tl::nullopt; 10 | 11 | template 12 | auto get_member(R T::*member) 13 | { 14 | return [=](T const & val) { return val.*member; }; 15 | } 16 | } 17 | 18 | #endif // OPTIONAL_HPP 19 | -------------------------------------------------------------------------------- /vendor/xqlib-stripped/include/xstd/resource: -------------------------------------------------------------------------------- 1 | #ifndef XQLIB_RESOURCE_HPP 2 | #define XQLIB_RESOURCE_HPP 3 | 4 | #include 5 | 6 | namespace xstd 7 | { 8 | namespace _detail 9 | { 10 | template 11 | T constexpr make_null() 12 | { 13 | if constexpr(std::is_pointer_v) 14 | return nullptr; 15 | else if constexpr(std::is_integral_v) 16 | return 0; 17 | else 18 | static_assert(std::is_integral_v, "Custom resource type must be pointer or integer!"); 19 | } 20 | } 21 | 22 | //! A simple wrapper for C resources. 23 | //! Requires a static deleter function. 24 | //! @tparam T The type of the resource. 25 | //! @tparam Deleter The deleter function that will release this resource. 26 | template()> 27 | struct resource 28 | { 29 | static_assert(std::is_pod_v, "resource must be a POD type."); 30 | private: 31 | T _value; 32 | public: 33 | resource() : _value(Null) { } 34 | explicit resource(T value) : _value(value) { } 35 | resource(resource const &) = delete; 36 | resource(resource && other) : _value(other._value) 37 | { 38 | other._value = Null; 39 | } 40 | ~resource() 41 | { 42 | if(_value != Null) 43 | Deleter(_value); 44 | } 45 | 46 | public: 47 | void reset(T new_content = Null) 48 | { 49 | *this = resource(new_content); 50 | } 51 | 52 | T release() 53 | { 54 | auto * result = _value; 55 | _value = Null; 56 | return result; 57 | } 58 | 59 | T get() { return _value; } 60 | T const get() const { return _value; } 61 | 62 | public: 63 | T & operator*() { return _value; } 64 | T const & operator*() const { return _value; } 65 | 66 | T * operator->() { return _value; } 67 | T const * operator->() const { return _value; } 68 | 69 | T & operator[](std::size_t index) { return _value[index]; } 70 | T const & operator[](std::size_t index) const { return _value[index]; } 71 | 72 | operator bool() const { return (_value != Null); } 73 | 74 | resource & operator = (resource && other) 75 | { 76 | this->~resource(); 77 | new (this) resource(std::move(other)); 78 | return *this; 79 | } 80 | 81 | bool operator== (resource const & other) const { 82 | return _value == other._value; 83 | } 84 | 85 | bool operator== (T const * other) const { 86 | return _value == other; 87 | } 88 | 89 | bool operator== (std::nullptr_t) const { 90 | return (_value == Null); 91 | } 92 | 93 | bool operator!= (resource const & other) const { 94 | return _value != other._value; 95 | } 96 | 97 | bool operator!= (T const * other) const { 98 | return _value != other; 99 | } 100 | 101 | bool operator!= (std::nullptr_t) const { 102 | return (_value != Null); 103 | } 104 | }; 105 | } 106 | 107 | #endif // CRESOURCE_HPP 108 | -------------------------------------------------------------------------------- /vendor/xqlib-stripped/include/xstd/unique_id: -------------------------------------------------------------------------------- 1 | #ifndef XQLIB_UNIQUE_ID_HPP 2 | #define XQLIB_UNIQUE_ID_HPP 3 | 4 | #include 5 | 6 | namespace xstd 7 | { 8 | //! Type-safe generic unique identifier. 9 | //! 10 | //! @tparam tag The tag type provides a simple distinction between different 11 | //! identifiers. It is not used in the unique_id itself. 12 | template 13 | struct unique_id 14 | { 15 | unsigned long const value; 16 | 17 | constexpr unique_id() noexcept : value(0) { } 18 | explicit constexpr unique_id(unsigned long _value) noexcept : value(_value) { } 19 | constexpr unique_id(unique_id const & other) noexcept = default; 20 | constexpr unique_id(unique_id && other) noexcept : 21 | value(other.value) 22 | { 23 | const_cast(other.value) = 0; 24 | } 25 | ~unique_id() noexcept = default; 26 | 27 | //! returns true if the unique_id is a null-id. 28 | constexpr bool is_null() const { 29 | return (this->value == 0); 30 | } 31 | 32 | //! returns an invalid id. 33 | static constexpr unique_id null() { return unique_id{0}; } 34 | 35 | public: // operator implementations 36 | constexpr unique_id & operator= (unique_id const & other) noexcept 37 | { 38 | const_cast(value) = other.value; 39 | return *this; 40 | } 41 | 42 | constexpr bool operator==(unique_id const & other) const noexcept { 43 | return (this->value == other.value); 44 | } 45 | 46 | constexpr bool operator!=(unique_id const & other) const noexcept { 47 | return !(*this == other); 48 | } 49 | 50 | constexpr bool operator<(unique_id const & other) const noexcept { 51 | return this->value < other.value; 52 | } 53 | public: 54 | //! hash type for the unique_id. is required to use in some containers. 55 | struct hash 56 | { 57 | constexpr std::size_t operator()(unique_id const & id) const noexcept 58 | { 59 | return id.value; 60 | } 61 | }; 62 | }; 63 | } 64 | 65 | #endif // XCOMMON_HPP 66 | -------------------------------------------------------------------------------- /vendor/xqlib-stripped/src/xlog.cpp: -------------------------------------------------------------------------------- 1 | #include "../include/xlog" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace 8 | { 9 | bool colored_output = false; 10 | #ifdef DEBUG 11 | xlog::log_level min_level = xlog::verbose; 12 | #else 13 | xlog::log_level min_level = xlog::message; 14 | #endif 15 | std::mutex output_lock; 16 | #ifdef DEBUG 17 | bool die_on_critical = true; 18 | #else 19 | bool die_on_critical = false; 20 | #endif 21 | } 22 | 23 | void xlog::enable_colors(bool enabled) 24 | { 25 | colored_output = enabled; 26 | } 27 | 28 | void xlog::abort_on_critical(bool enabled) 29 | { 30 | die_on_critical = enabled; 31 | } 32 | 33 | void xlog::set_verbosity(log_level min) 34 | { 35 | min_level = min; 36 | } 37 | 38 | xlog::log::log(xlog::log_level lvl) : 39 | level(lvl), 40 | text() 41 | { 42 | 43 | } 44 | 45 | xlog::log::log(char const * prefix, xlog::log_level lvl) : 46 | level(lvl), 47 | text() 48 | { 49 | text << prefix << ": "; 50 | } 51 | 52 | xlog::log::~log() 53 | { 54 | if(level >= min_level) 55 | { 56 | std::lock_guard _ { output_lock }; 57 | 58 | auto & stream = (level >= warning) ? std::cerr : std::cout; 59 | 60 | if(colored_output) 61 | { 62 | stream << "\x1b["; 63 | if(level >= critical) 64 | stream << "35"; // magenta 65 | else if(level >= error) 66 | stream << "31"; // red 67 | else if(level >= warning) 68 | stream << "33"; // yellow 69 | else if(level < message) 70 | stream << "32"; // green 71 | else if(level < message) 72 | stream << "39"; // "reset/default" 73 | stream << "m"; 74 | } 75 | 76 | stream << text.str() << std::endl; 77 | stream.flush(); 78 | 79 | if(colored_output) 80 | { 81 | stream << "\x1b[39m"; 82 | } 83 | } 84 | if((level >= critical) and die_on_critical) 85 | abort(); 86 | } 87 | -------------------------------------------------------------------------------- /vendor/zig-meta/meta.zig: -------------------------------------------------------------------------------- 1 | const intf = @import("src/interface.zig"); 2 | 3 | pub const interfaceCast = intf.interfaceCast; 4 | pub const Interface = intf.Interface; 5 | 6 | pub const Closure = @import("src/closure.zig").Closure; 7 | -------------------------------------------------------------------------------- /vendor/zig-meta/src/closure.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | // pub fn main() void { 4 | // std.log.info("mutable closure:", .{}); 5 | // runMutDemo(); 6 | 7 | // std.log.info("const closure:", .{}); 8 | // runConstDemo(); 9 | // } 10 | 11 | // fn runMutDemo() void { 12 | // var call_count: usize = 0; 13 | 14 | // var closed = Closure(struct { 15 | // fn C(state: *struct { i: u32 = 0, c: *usize }, increment: u32) u32 { 16 | // defer state.i += increment; 17 | // state.c.* += 1; 18 | // return state.i; 19 | // } 20 | // }.C).init( 21 | // .{ .c = &call_count }, 22 | // ); 23 | 24 | // std.log.info(" invocation 1 => {}", .{closed.invoke(.{1})}); 25 | // std.log.info(" invocation 2 => {}", .{closed.invoke(.{0})}); 26 | // std.log.info(" invocation 3 => {}", .{closed.invoke(.{2})}); 27 | // std.log.info(" invocation 4 => {}", .{closed.invoke(.{3})}); 28 | // std.log.info(" invocation 5 => {}", .{closed.invoke(.{0})}); 29 | 30 | // std.log.info(" invocation count: {}", .{call_count}); 31 | // } 32 | 33 | // fn runConstDemo() void { 34 | // const closed = Closure(struct { 35 | // fn C(state: struct { i: u32 }, increment: u32) u32 { 36 | // return state.i + increment; 37 | // } 38 | // }.C).init( 39 | // .{ .i = 10 }, 40 | // ); 41 | 42 | // std.log.info(" static invocation 1 => {}", .{closed.invoke(.{1})}); 43 | // std.log.info(" static invocation 2 => {}", .{closed.invoke(.{0})}); 44 | // std.log.info(" static invocation 3 => {}", .{closed.invoke(.{2})}); 45 | // std.log.info(" static invocation 4 => {}", .{closed.invoke(.{3})}); 46 | // std.log.info(" static invocation 5 => {}", .{closed.invoke(.{0})}); 47 | // } 48 | 49 | /// Creates a closure type that will store and pass the first argument of the passed 50 | /// function 51 | pub fn Closure(comptime function: anytype) type { 52 | const F = @TypeOf(function); 53 | const A0 = @typeInfo(F).Fn.args[0].arg_type.?; 54 | 55 | return struct { 56 | const Self = @This(); 57 | 58 | pub const is_mutable = (@typeInfo(A0) == .Pointer); 59 | pub const State = if (is_mutable) 60 | std.meta.Child(A0) 61 | else 62 | A0; 63 | pub const Result = (@typeInfo(F).Fn.return_type.?); 64 | 65 | state: State, 66 | 67 | pub fn init(state: State) Self { 68 | return Self{ .state = state }; 69 | } 70 | 71 | pub fn invoke(self: if (is_mutable) *Self else Self, args: anytype) Result { 72 | return @call(.{}, function, .{if (is_mutable) &self.state else self.state} ++ args); 73 | } 74 | }; 75 | } 76 | -------------------------------------------------------------------------------- /vendor/zig-meta/src/fnwrap.zig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dunstwolke/core/047d36ce01be3fd7ac160c2360f0139b9c0a5856/vendor/zig-meta/src/fnwrap.zig --------------------------------------------------------------------------------