├── .coverage ├── .gitattributes ├── .github └── workflows │ └── pytest.yaml ├── .gitignore ├── LICENSE.md ├── README.md ├── docs ├── .gitignore ├── README.md ├── Roadmap.canvas ├── Video 1.canvas ├── Video 10.md ├── Video 11.md ├── Video 2.canvas ├── Video 3.canvas ├── Video 4.canvas ├── Video 5.canvas ├── Video 8.md └── Video 9.md ├── plaintext_daw ├── __init__.py ├── cli.py ├── gui.py ├── lib.py ├── models │ ├── __init__.py │ ├── clip.py │ ├── instrument.py │ ├── note.py │ ├── pattern.py │ ├── song.py │ └── synthesizer │ │ ├── __init__.py │ │ ├── envelope.py │ │ ├── rawclip.py │ │ ├── synth.py │ │ └── wave.py └── resource_manager.py ├── setup.py ├── tauri ├── .gitignore ├── .vscode │ └── extensions.json ├── README.md ├── src-tauri │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── build.rs │ ├── icons │ │ ├── 128x128.png │ │ ├── 128x128@2x.png │ │ ├── 32x32.png │ │ ├── Square107x107Logo.png │ │ ├── Square142x142Logo.png │ │ ├── Square150x150Logo.png │ │ ├── Square284x284Logo.png │ │ ├── Square30x30Logo.png │ │ ├── Square310x310Logo.png │ │ ├── Square44x44Logo.png │ │ ├── Square71x71Logo.png │ │ ├── Square89x89Logo.png │ │ ├── StoreLogo.png │ │ ├── icon.icns │ │ ├── icon.ico │ │ └── icon.png │ ├── src │ │ ├── main.rs │ │ └── state.rs │ └── tauri.conf.json └── src │ ├── assets │ ├── javascript.svg │ └── tauri.svg │ ├── index.html │ ├── index2.html │ ├── main.js │ ├── main2.js │ └── style.css └── test ├── data ├── song1 │ ├── piano │ │ ├── Piano-A0.ogg.wav │ │ ├── Piano-A1.ogg.wav │ │ ├── Piano-A2.ogg.wav │ │ ├── Piano-A3.ogg.wav │ │ ├── Piano-A4.ogg.wav │ │ ├── Piano-A5.ogg.wav │ │ ├── Piano-A6.ogg.wav │ │ ├── Piano-A7.ogg.wav │ │ ├── Piano-C1.ogg.wav │ │ ├── Piano-C2.ogg.wav │ │ ├── Piano-C3.ogg.wav │ │ ├── Piano-C4.ogg.wav │ │ ├── Piano-C5.ogg.wav │ │ ├── Piano-C6.ogg.wav │ │ ├── Piano-C7.ogg.wav │ │ ├── Piano-C8.ogg.wav │ │ ├── Piano-D#1.ogg.wav │ │ ├── Piano-D#2.ogg.wav │ │ ├── Piano-D#3.ogg.wav │ │ ├── Piano-D#4.ogg.wav │ │ ├── Piano-D#5.ogg.wav │ │ ├── Piano-D#6.ogg.wav │ │ ├── Piano-D#7.ogg.wav │ │ ├── Piano-F#1.ogg.wav │ │ ├── Piano-F#2.ogg.wav │ │ ├── Piano-F#3.ogg.wav │ │ ├── Piano-F#4.ogg.wav │ │ ├── Piano-F#5.ogg.wav │ │ ├── Piano-F#6.ogg.wav │ │ └── Piano-F#7.ogg.wav │ ├── song.yml │ └── voice │ │ └── clip1.wav ├── song2 │ └── song.yml └── song3 │ └── song.yml ├── models ├── test_clip.py ├── test_instrument.py ├── test_note.py ├── test_pattern.py ├── test_song.py └── test_synth.py ├── test_integration.py ├── test_lib.py ├── test_renderer.py └── test_resource_manager.py /.coverage: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagekey/plaintext-daw/c74dc68330b1acec5892ecc20e34f208563e5a22/.coverage -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.wav filter=lfs diff=lfs merge=lfs -text 2 | -------------------------------------------------------------------------------- /.github/workflows/pytest.yaml: -------------------------------------------------------------------------------- 1 | name: pytest 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | strategy: 10 | matrix: 11 | python-version: ["3.10"] 12 | 13 | steps: 14 | - uses: actions/checkout@v3 15 | - name: Set up Python ${{ matrix.python-version }} 16 | uses: actions/setup-python@v4 17 | with: 18 | python-version: ${{ matrix.python-version }} 19 | - name: Install dependencies 20 | run: | 21 | apt install libsndfile-dev 22 | python -m pip install --upgrade pip 23 | pip install -e . 24 | pip install pytest pytest-cov 25 | - name: Test with pytest 26 | run: | 27 | sudo apt-get update 28 | sudo apt install ffmpeg 29 | pytest --cov=plaintext_daw 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.egg-info 2 | __pycache__ 3 | *.wav 4 | dist/ 5 | build/ 6 | .ptd_cache/ 7 | .ptd-cache/ 8 | .coverage -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 PageKey Solutions, LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # plaintext-daw 2 | 3 | A plaintext DAW (Digital Audio Workstation) 4 | 5 | ## Video Series 6 | 7 | This project has been developed on video on the PageKey Tech YouTube channel. You can check the series out [here](https://www.youtube.com/watch?v=MguWfieR2tI&list=PL3Kz_hCNpKST2x-SzgbpYBeWOa74F40s7). 8 | 9 | ## Discord 10 | 11 | [Join the Discord](https://discord.gg/5m5yFgDPF5) to discuss this project and connect with others! 12 | 13 | ## Pre-Requisites 14 | 15 | - You must have Git installed on your system and available in the PATH. 16 | 17 | - You must have Git LFS installed and configured for use. 18 | 19 | - You make sure `ffmpeg` is installed. 20 | 21 | ``` 22 | apt install ffmpeg 23 | brew install ffmpeg 24 | yum install ffmpeg 25 | ``` 26 | 27 | ## Installation 28 | 29 | General use: 30 | 31 | ``` 32 | pip install plaintext-daw 33 | ``` 34 | 35 | Development: 36 | 37 | ``` 38 | git clone git@github.com:pagekeytech/plaintext-daw 39 | cd plaintext-daw 40 | pip install -e . 41 | ``` 42 | 43 | ## Usage 44 | 45 | Type `plaintext-daw` on the command line to see usage instructions. 46 | 47 | ## Docs 48 | 49 | Open the `docs` folder as an Obsidian vault to view the documentation for this project. 50 | 51 | ## Attributions 52 | 53 | Piano samples are from [here](https://musical-artifacts.com/artifacts/403) licensed under [CC 4.0](https://creativecommons.org/licenses/by/4.0/deed.en). 54 | 55 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | .obsidian -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # plaintext-daw docs 2 | 3 | This folder contains all the notes used in the [plaintext-daw video series](https://www.youtube.com/watch?v=MguWfieR2tI&list=PL3Kz_hCNpKST2x-SzgbpYBeWOa74F40s7). 4 | 5 | You can open the folder in Obsidian as a vault to view the canvas files. 6 | -------------------------------------------------------------------------------- /docs/Roadmap.canvas: -------------------------------------------------------------------------------- 1 | { 2 | "nodes":[ 3 | {"id":"721f1c61f05dac26","x":134,"y":-135,"width":250,"height":60,"color":"4","type":"text","text":"[[Video 3.canvas|Video 3]]: Concatenate wavs"}, 4 | {"id":"a2ce55dde47cf092","x":-492,"y":-155,"width":896,"height":100,"type":"group","label":"Implementation"}, 5 | {"id":"f67f06a2dfe2607f","x":-168,"y":-135,"width":250,"height":60,"color":"4","type":"text","text":"[[Video 2.canvas|Video 2]]: Parsing Config"}, 6 | {"id":"11d37ce49304e0d8","x":-472,"y":-135,"width":250,"height":60,"color":"4","type":"text","text":"[[Video 1.canvas|Video 1]]: Project/CLI Setup"}, 7 | {"id":"fa91423271e2fd80","x":487,"y":-215,"width":345,"height":190,"type":"group","label":"Video 4"}, 8 | {"id":"e25d4c162c1cebb3","x":507,"y":-105,"width":305,"height":60,"color":"4","type":"text","text":"Add support for tempo, chords\nDone in [#4](https://github.com/pagekeytech/plaintext-daw/pull/4)"}, 9 | {"id":"5d809cd1f5f55bab","x":507,"y":-195,"width":250,"height":60,"color":"4","type":"text","text":"GUI: Open project dialog\nDone by LTstrange in [#2](https://github.com/pagekeytech/plaintext-daw/pull/2)"}, 10 | {"id":"96168461ba826c14","x":2698,"y":132,"width":250,"height":60,"type":"text","text":"Add support for one-off clips (at the song level)"}, 11 | {"id":"43f9207b4f2cdab3","x":2698,"y":222,"width":250,"height":60,"type":"text","text":"abc.js support - load files"}, 12 | {"id":"26f1a3be63ea5fbe","x":2698,"y":323,"width":250,"height":60,"color":"3","type":"text","text":"Synthesizer class\nLTstrange working"}, 13 | {"id":"f1ab7dc2f1481636","x":3011,"y":323,"width":250,"height":60,"type":"text","text":"Sync effects pipeline"}, 14 | {"id":"b446dfb20576fcd4","x":1715,"y":102,"width":250,"height":60,"color":"4","type":"text","text":"Support Synth instruments in CLI"}, 15 | {"id":"3635af63def0e86a","x":2055,"y":102,"width":250,"height":60,"color":"4","type":"text","text":"Respect note length/end, fix tempo"}, 16 | {"id":"c2878ed99519afa7","x":2370,"y":222,"width":250,"height":60,"color":"4","type":"text","text":"New architecture"}, 17 | {"id":"c32ac2ba5668c236","x":2370,"y":-117,"width":250,"height":60,"color":"4","type":"text","text":"Tauri GUI MVP\nSteve working"}, 18 | {"id":"7c325843770d5843","x":2406,"y":-11,"width":367,"height":64,"color":"4","type":"text","text":"Add mp3 loader (LTstrange)\n[https://stackoverflow.com/questions/53633177/how-to-read-a-mp3-audio-file-into-a-numpy-array-save-a-numpy-array-to-mp3](https://stackoverflow.com/questions/53633177/how-to-read-a-mp3-audio-file-into-a-numpy-array-save-a-numpy-array-to-mp3)"}, 19 | {"id":"f0279d95ca2d5c07","x":2677,"y":-117,"width":250,"height":60,"type":"text","text":"GUI: invoke render, save-as"}, 20 | {"id":"48748d1374493829","x":3027,"y":-117,"width":374,"height":60,"type":"text","text":"Add recording\nTry [pyaudio](https://people.csail.mit.edu/hubert/pyaudio/) or [python-sound-device](https://python-sounddevice.readthedocs.io/en/latest/)"}, 21 | {"id":"8159390b0971434e","x":2685,"y":-268,"width":250,"height":60,"color":"3","type":"text","text":"Rust Parser, WASM support\nYuuki working"}, 22 | {"id":"42f396f1a710a90f","x":1314,"y":102,"width":284,"height":60,"color":"4","type":"text","text":"Synthesize from expression\nLTstrange [#3](https://github.com/pagekeytech/plaintext-daw/pull/3) in progress"}, 23 | {"id":"7a6eb4edf2c1a5b0","x":890,"y":102,"width":385,"height":60,"color":"4","type":"text","text":"Load instrument from git repo"}, 24 | {"id":"d20cd9ac81fb9592","x":3454,"y":-590,"width":317,"height":60,"type":"text","text":"Use background music generated by plaintext-daw in videos"}, 25 | {"id":"f206f12c631f9d47","x":3454,"y":-503,"width":250,"height":60,"type":"text","text":"Move synth into instruments repo"}, 26 | {"id":"6f32b2299f743c4f","x":3457,"y":-754,"width":250,"height":60,"type":"text","text":"Rust re-implementation"}, 27 | {"id":"7ca18d17f9956be3","x":3457,"y":-672,"width":250,"height":60,"type":"text","text":"Switch `.yml` to `.yaml`?"}, 28 | {"id":"752261370b39ba7f","x":2859,"y":-564,"width":250,"height":60,"type":"text","text":"GUI: Display samples"}, 29 | {"id":"76869a7f31c3f6d7","x":2859,"y":-482,"width":250,"height":60,"type":"text","text":"GUI: Live render song"}, 30 | {"id":"5fee10b6904483a1","x":2859,"y":-402,"width":250,"height":60,"type":"text","text":"GUI: Live render pattern"}, 31 | {"id":"45a520f59598e512","x":3160,"y":-672,"width":250,"height":60,"type":"text","text":"Sheet music OCR?"}, 32 | {"id":"1f34fb08fc1f98ca","x":3160,"y":-590,"width":250,"height":59,"type":"text","text":"Buffered render / realtime playback"}, 33 | {"id":"7368cd1d3c5846c2","x":3160,"y":-503,"width":250,"height":60,"type":"text","text":"ChatGPT integration?\n-LTStrange"}, 34 | {"id":"fc5f2e15443bbd6c","x":2839,"y":-748,"width":290,"height":426,"type":"group","label":"Display"}, 35 | {"id":"e98cac6781019be1","x":2859,"y":-728,"width":250,"height":60,"type":"text","text":"GUI: Display Patterns"}, 36 | {"id":"acbb183ec74bfa8c","x":2859,"y":-646,"width":250,"height":60,"type":"text","text":"GUI: Display Song (timeline)"}, 37 | {"id":"b091de72cb9aa6d6","x":3202,"y":-384,"width":250,"height":60,"type":"text","text":"Multiply waves instead of adding? (Yuuki) see [here](http://msp.ucsd.edu/techniques/v0.11/book-html/node77.html)"} 38 | ], 39 | "edges":[ 40 | {"id":"d5f27daf4a1520cc","fromNode":"11d37ce49304e0d8","fromSide":"right","toNode":"f67f06a2dfe2607f","toSide":"left"}, 41 | {"id":"5476682596778cb0","fromNode":"f67f06a2dfe2607f","fromSide":"right","toNode":"721f1c61f05dac26","toSide":"left"}, 42 | {"id":"b4de894b83768188","fromNode":"721f1c61f05dac26","fromSide":"right","toNode":"5d809cd1f5f55bab","toSide":"left"}, 43 | {"id":"a54534f3cc95900c","fromNode":"721f1c61f05dac26","fromSide":"right","toNode":"e25d4c162c1cebb3","toSide":"left"}, 44 | {"id":"c08da602a354ecaf","fromNode":"e25d4c162c1cebb3","fromSide":"right","toNode":"7a6eb4edf2c1a5b0","toSide":"left"}, 45 | {"id":"73e02eb7d8404f8f","fromNode":"42f396f1a710a90f","fromSide":"right","toNode":"b446dfb20576fcd4","toSide":"left"}, 46 | {"id":"06276a2f58fa5429","fromNode":"7a6eb4edf2c1a5b0","fromSide":"right","toNode":"42f396f1a710a90f","toSide":"left"}, 47 | {"id":"e517ad213e9bef00","fromNode":"b446dfb20576fcd4","fromSide":"right","toNode":"3635af63def0e86a","toSide":"left"}, 48 | {"id":"8dcfe7cd466cad01","fromNode":"c2878ed99519afa7","fromSide":"right","toNode":"43f9207b4f2cdab3","toSide":"left"}, 49 | {"id":"5b4b0b75908126d5","fromNode":"c2878ed99519afa7","fromSide":"right","toNode":"96168461ba826c14","toSide":"left"}, 50 | {"id":"8df66b3296e94853","fromNode":"3635af63def0e86a","fromSide":"right","toNode":"7c325843770d5843","toSide":"left"}, 51 | {"id":"8963a3ae3515e5ce","fromNode":"3635af63def0e86a","fromSide":"right","toNode":"c2878ed99519afa7","toSide":"left"}, 52 | {"id":"5f40f37eb987233f","fromNode":"c2878ed99519afa7","fromSide":"right","toNode":"26f1a3be63ea5fbe","toSide":"left"}, 53 | {"id":"57cd730fa9a0c683","fromNode":"26f1a3be63ea5fbe","fromSide":"right","toNode":"f1ab7dc2f1481636","toSide":"left"}, 54 | {"id":"e420365143a241ad","fromNode":"3635af63def0e86a","fromSide":"right","toNode":"c32ac2ba5668c236","toSide":"left"}, 55 | {"id":"d3cefe2e8c14c796","fromNode":"c32ac2ba5668c236","fromSide":"right","toNode":"f0279d95ca2d5c07","toSide":"left"}, 56 | {"id":"eb7b373cbe92191b","fromNode":"f0279d95ca2d5c07","fromSide":"right","toNode":"48748d1374493829","toSide":"left"} 57 | ] 58 | } -------------------------------------------------------------------------------- /docs/Video 1.canvas: -------------------------------------------------------------------------------- 1 | { 2 | "nodes":[ 3 | {"id":"0e422a581a8c334e","x":219,"y":-661,"width":304,"height":86,"color":"4","type":"text","text":"First step:\nCreate git repo w/ README"}, 4 | {"id":"83d973163995c7ae","x":-555,"y":-769,"width":600,"height":68,"type":"text","text":"# Coding a Plaintext DAW"}, 5 | {"id":"f784c3788fb0e53b","x":-555,"y":-701,"width":250,"height":60,"type":"text","text":"Name: `plaintext-daw`\nCan always rename later"}, 6 | {"id":"52e1f78ede44f64c","x":-147,"y":-355,"width":275,"height":110,"type":"text","text":"Do all on video\n(or do all coding on vid?)\n(do planning offline?)"}, 7 | {"id":"3fb86b52e13e938c","x":-555,"y":-17,"width":711,"height":429,"type":"text","text":"MVP music file:\n```yaml\npiano:\n type: instrument\n path: piano.sft # sound font\npattern1:\n type: pattern\n notes: [a,b,c,d]\n instrument: piano\nsong:\n type: song\n output: 'song.wav'\n patterns:\n - name: pattern1\n start: 1 # start measure\n repeat: 0 # how many copies after the original one\n```"}, 8 | {"id":"e09aa969a206ae78","x":-555,"y":-624,"width":600,"height":248,"color":"3","type":"text","text":"**Main Idea**:\n- use plain text as your music creation format\n\nImplications:\n- Can use Git to collab / develop music just like code\n- Artists can \"open source\" their song\n- People can \"fork\" to cover / remix"}, 9 | {"id":"46a58ca5b57891f0","x":-555,"y":-238,"width":368,"height":97,"type":"text","text":"MVP2: Include another wav file to \"superimpose\""}, 10 | {"id":"b5941cfcfaff4856","x":-555,"y":-371,"width":357,"height":116,"type":"text","text":"MVP: render ANY wav from plaintext notes + MIDI instrument"}, 11 | {"id":"10b3120bf715c66c","x":-555,"y":-116,"width":250,"height":60,"type":"text","text":"Units:\nbpm, start_measure"}, 12 | {"id":"45b710e9d5d806be","x":219,"y":-125,"width":303,"height":94,"type":"text","text":"Research soundfonts, midi instruments - how to render a note to wav?"}, 13 | {"id":"a734baa5b20f489d","x":246,"y":-531,"width":250,"height":82,"color":"4","type":"text","text":"Add CLI command\nprint hello world\n`plaintext-daw`"}, 14 | {"id":"0b20e0de84c4b579","x":246,"y":-406,"width":250,"height":60,"color":"4","type":"text","text":"Parse sample yaml to dict"}, 15 | {"id":"e30bba146f5adb40","x":212,"y":-300,"width":317,"height":109,"type":"text","text":"Cross-reference pattern, instrument to create one huge song obj"}, 16 | {"id":"68ecce3fae3cef06","x":199,"y":-685,"width":357,"height":677,"type":"group","label":"First Steps"}, 17 | {"id":"521e1e553cc2aee2","x":-548,"y":482,"width":477,"height":287,"type":"group","label":"Title Ideas"}, 18 | {"id":"5a9c4c77cba06487","x":-528,"y":502,"width":395,"height":65,"type":"text","text":"Plaintext DAW: Why it could change EVERYTHING about music"}, 19 | {"id":"495e4dae685e2c8b","x":-528,"y":580,"width":425,"height":72,"type":"text","text":"Building a Plaintext DAW to Change Music FOREVER"}, 20 | {"id":"2d0733b671fafbb7","x":-528,"y":652,"width":437,"height":97,"type":"text","text":"Let's change music FOREVER - Coding a Plaintext DAW"} 21 | ], 22 | "edges":[ 23 | {"id":"b9a8f127af4b26b5","fromNode":"0e422a581a8c334e","fromSide":"bottom","toNode":"a734baa5b20f489d","toSide":"top"}, 24 | {"id":"74288a9f28afc6b6","fromNode":"e30bba146f5adb40","fromSide":"bottom","toNode":"45b710e9d5d806be","toSide":"top"}, 25 | {"id":"7380912a1acbcf42","fromNode":"a734baa5b20f489d","fromSide":"bottom","toNode":"0b20e0de84c4b579","toSide":"top"}, 26 | {"id":"3c5f46aa1b74c6a8","fromNode":"0b20e0de84c4b579","fromSide":"bottom","toNode":"e30bba146f5adb40","toSide":"top"} 27 | ] 28 | } -------------------------------------------------------------------------------- /docs/Video 10.md: -------------------------------------------------------------------------------- 1 | 0:00 Merging #11 by LTstrange 2 | 1:27 Debugging test failure 3 | 2:04 Writing test_get_instrument from Git 4 | 5:40 Mocking get_clip calls 5 | 7:16 Tip: How to check what is being called 6 | 7:59 How to patch external dependencies 7 | 9:10 clone_git_repo implementation 8 | 12:23 Catching a mistake with the tests! 9 | 13:33 FULL TEST of new architecture 10 | 15:14 Why the config loader method is good 11 | 15:40 Finally working 12 | 16:02 What's next / outro 13 | -------------------------------------------------------------------------------- /docs/Video 11.md: -------------------------------------------------------------------------------- 1 | 0:00 Organized Roadmap 2 | 1:20 Merging #9 3 | 1:29 Quick research: PyO3 and Tauri 4 | 2:02 Tauri Quickstart 5 | 3:39 It works! 6 | 4:13 First change 7 | 4:44 First thoughts, next steps 8 | 5:14 Adding a custom button with a println 9 | 5:51 Wrap-up 10 | -------------------------------------------------------------------------------- /docs/Video 2.canvas: -------------------------------------------------------------------------------- 1 | { 2 | "nodes":[ 3 | {"id":"b9fb3a07c3c52a4c","x":-299,"y":9,"width":250,"height":60,"type":"text","text":"Instrument\n(map note to sample)"}, 4 | {"id":"bfb2b1c250c27ddc","x":-886,"y":102,"width":250,"height":60,"type":"text","text":"Sample"}, 5 | {"id":"100d9f3283ed5296","x":-577,"y":102,"width":250,"height":60,"type":"text","text":"Note"}, 6 | {"id":"7f18cb2e5bdf23a4","x":-911,"y":349,"width":334,"height":117,"type":"text","text":"Future Idea 💡\nTrack for \"performance\"\nAuto-increment \"takes\""}, 7 | {"id":"9488de87fbb1d050","x":226,"y":-86,"width":650,"height":104,"type":"text","text":"```music-abc\na,2 b,4\n```"}, 8 | {"id":"bcb5ade020e641c9","x":-906,"y":526,"width":1323,"height":261,"type":"group","label":"Next Actions"}, 9 | {"id":"aaab936c8747d213","x":-885,"y":555,"width":367,"height":63,"color":"4","type":"text","text":"Add this canvas to `docs` folder in repo\nMake `docs` an Obsidian vault"}, 10 | {"id":"2680e7d5c8659b50","x":-174,"y":556,"width":250,"height":60,"color":"4","type":"text","text":"Find or create a free piano wav of a note"}, 11 | {"id":"84032d44b097fcfd","x":-477,"y":556,"width":250,"height":60,"color":"4","type":"text","text":"Paste/commit new config"}, 12 | {"id":"0af1acc8a1bbe2bd","x":-901,"y":850,"width":250,"height":60,"type":"text","text":"Finding Piano Samples"}, 13 | {"id":"d51435875e9aa7f0","x":-174,"y":707,"width":250,"height":60,"type":"text","text":"Render config w/o timing"}, 14 | {"id":"e4c1ff24bc69ac54","x":-885,"y":707,"width":250,"height":60,"type":"text","text":"Write a single note, config or not, to wav"}, 15 | {"id":"93561d61864c7a0f","x":-518,"y":707,"width":250,"height":60,"type":"text","text":"Write two notes"}, 16 | {"id":"a6ca1916ad7e5488","x":-901,"y":910,"width":400,"height":400,"type":"link","url":"https://musical-artifacts.com/artifacts/403"}, 17 | {"id":"8ed0d813ec5def53","x":-501,"y":910,"width":400,"height":400,"type":"link","url":"https://creativecommons.org/licenses/by/4.0/deed.en"}, 18 | {"id":"d67e58384324c923","x":-901,"y":1310,"width":625,"height":50,"type":"text","text":"Maybe eventually: can use [Soundfile](https://pypi.org/project/soundfile/) lib in Python for .ogg files"}, 19 | {"id":"67deb7c0d381abcd","x":114,"y":556,"width":250,"height":60,"type":"text","text":"Read a note in config from wav file"}, 20 | {"id":"766f6166f8c96806","x":147,"y":707,"width":250,"height":60,"type":"text","text":"Add timing"}, 21 | {"id":"32e037a08f155d7b","x":-931,"y":-1065,"width":1191,"height":621,"type":"group","label":"Research"}, 22 | {"id":"5251af96ca525964","x":-490,"y":-961,"width":716,"height":400,"type":"text","text":"Musescore has sf3 but it's early \n \nMaybe extract sf2 samples and use? \n \nSf2 spec - 87 pg PDF from 1998\nhttp://www.synthfont.com/SFSPEC21.PDF\n \nInstrument = collection of samples? \nMaybe add zip support eventually? Skip sf2 altogether \n \nTo superimpose two audio files, basically just add the raw data? \n[https://stackoverflow.com/questions/4039158/mixing-two-audio-files-together-with-python](https://stackoverflow.com/questions/4039158/mixing-two-audio-files-together-with-python\nDepend on wave, numpy to get/manipulate raw sound data"}, 23 | {"id":"5dd46df3a594609a","x":-911,"y":-561,"width":287,"height":85,"type":"text","text":"- Lets you load soundfonts\n- Coupled with `musicpy`"}, 24 | {"id":"14e5e1f933333913","x":-911,"y":-961,"width":400,"height":400,"type":"link","url":"https://pypi.org/project/sf2-loader/"}, 25 | {"id":"0f36709f7e47bf2d","x":-911,"y":-1045,"width":763,"height":59,"type":"text","text":"# Research: SoundFonts, MIDI Instruments"}, 26 | {"id":"16dba8c61efe32a8","x":-931,"y":-1359,"width":640,"height":246,"type":"group","label":"Recap"}, 27 | {"id":"5f3d49c5102cab32","x":-911,"y":-1193,"width":326,"height":60,"type":"text","text":"Working CLI + some fancy ideas"}, 28 | {"id":"0a05370012d814fa","x":-911,"y":-1253,"width":326,"height":60,"type":"text","text":"## Where we left off"}, 29 | {"id":"b88a5c1c53337427","x":-911,"y":-1339,"width":600,"height":68,"type":"text","text":"# Coding a Plaintext DAW 2"}, 30 | {"id":"2b21fd353b49d1b4","x":-906,"y":-373,"width":1837,"height":692,"type":"group","label":"New Config Format Design"}, 31 | {"id":"b6b6991695a3cc20","x":-269,"y":-1355,"width":504,"height":50,"type":"text","text":"Config Magic with Python Dataclasses | Plaintext DAW 2"}, 32 | {"id":"52390691284abdd3","x":-269,"y":-1305,"width":504,"height":225,"type":"text","text":"### Timestamps\n0:00 Intro\n0:26 Research: Soundfont, MIDI\n2:50 Design: Config\n5:29 Future Idea: Performances, Takes\n5:52 Next Actions\n7:25 Coding"}, 33 | {"id":"e9ff361eb42403d2","x":-763,"y":-272,"width":250,"height":60,"type":"text","text":"Song"}, 34 | {"id":"514ddc1985a179c6","x":-609,"y":-146,"width":250,"height":60,"type":"text","text":"Pattern"}, 35 | {"id":"959b8f250d0cbbde","x":-886,"y":-353,"width":481,"height":60,"type":"text","text":"## A More Complete Format?"}, 36 | {"id":"79dd5a6adfcb1df2","x":-17,"y":-346,"width":920,"height":652,"type":"text","text":"```yaml\npiano:\n type: instrument\n samples:\n a:\n path: piano/a.wav\n b:\n path: piano/b.wav\npattern1:\n type: pattern\n instrument: piano\n notes:\n\t- value: a\n\t length: 1\n\t- value: b\n\t length: 2\nsong:\n type: song\n output: 'song.wav'\n bpm: 100\n sample_rate: 44100\n samples:\n - path: voice/clip1.wav\n start: 2 # start on measure 2\n patterns:\n - name: pattern1\n start: 1 # start measure\n repeat: 0 # how many copies after the original one\n```"} 37 | ], 38 | "edges":[ 39 | {"id":"59afa83b3cba1bd4","fromNode":"b9fb3a07c3c52a4c","fromSide":"bottom","toNode":"bfb2b1c250c27ddc","toSide":"bottom","label":"has many"}, 40 | {"id":"55387f2e68ed7758","fromNode":"514ddc1985a179c6","fromSide":"bottom","toNode":"b9fb3a07c3c52a4c","toSide":"top","label":"has one"}, 41 | {"id":"2cfce77b1d2c7913","fromNode":"e9ff361eb42403d2","fromSide":"bottom","toNode":"bfb2b1c250c27ddc","toSide":"top","label":"has many"}, 42 | {"id":"d4b60e92fe54c85a","fromNode":"514ddc1985a179c6","fromSide":"bottom","toNode":"100d9f3283ed5296","toSide":"top","label":"has many"}, 43 | {"id":"271c73d695a0ae8b","fromNode":"e9ff361eb42403d2","fromSide":"bottom","toNode":"514ddc1985a179c6","toSide":"top","label":"has many"}, 44 | {"id":"52a741942e7a586b","fromNode":"aaab936c8747d213","fromSide":"right","toNode":"84032d44b097fcfd","toSide":"left"}, 45 | {"id":"2dc16f3c6b6a1917","fromNode":"2680e7d5c8659b50","fromSide":"right","toNode":"67deb7c0d381abcd","toSide":"left"}, 46 | {"id":"114bd9691108047b","fromNode":"84032d44b097fcfd","fromSide":"right","toNode":"2680e7d5c8659b50","toSide":"left"}, 47 | {"id":"bd06040fb732806d","fromNode":"67deb7c0d381abcd","fromSide":"bottom","toNode":"e4c1ff24bc69ac54","toSide":"top"}, 48 | {"id":"e47ab283883a624c","fromNode":"d51435875e9aa7f0","fromSide":"right","toNode":"766f6166f8c96806","toSide":"left"}, 49 | {"id":"f4c0d889b3fd3675","fromNode":"93561d61864c7a0f","fromSide":"right","toNode":"d51435875e9aa7f0","toSide":"left"}, 50 | {"id":"02c31d8b5988dbaf","fromNode":"e4c1ff24bc69ac54","fromSide":"right","toNode":"93561d61864c7a0f","toSide":"left"} 51 | ] 52 | } -------------------------------------------------------------------------------- /docs/Video 3.canvas: -------------------------------------------------------------------------------- 1 | { 2 | "nodes":[ 3 | {"id":"1a849a116796139d","x":-194,"y":-96,"width":302,"height":361,"type":"group","label":"Next Actions"}, 4 | {"id":"f7cd3053f80ce4f1","x":-443,"y":-407,"width":800,"height":270,"type":"group","label":"Recap"}, 5 | {"id":"8fe1159791982c44","x":-423,"y":-387,"width":756,"height":68,"type":"text","text":"# Coding a Plaintext DAW 3"}, 6 | {"id":"80abef71dec8eb97","x":-423,"y":-241,"width":359,"height":72,"type":"text","text":"We can load the config now.\nWe can iterate all notes in all patterns"}, 7 | {"id":"5aa851caed2070e1","x":-423,"y":-301,"width":359,"height":60,"type":"text","text":"## Where we left off"}, 8 | {"id":"51aad39e278d26cf","x":-45,"y":-301,"width":378,"height":60,"type":"text","text":"## What's Next"}, 9 | {"id":"8f9908694f502687","x":-45,"y":-241,"width":378,"height":72,"type":"text","text":"Assume all notes are sequential and write to wav file one after the other"}, 10 | {"id":"34465fcb1adabfa5","x":-174,"y":-75,"width":250,"height":60,"color":"4","type":"text","text":"Get wav file into numpy array (using `wave` lib?)"}, 11 | {"id":"1522690a2a5e6703","x":-174,"y":33,"width":250,"height":60,"color":"4","type":"text","text":"Write numpy array to wav file"}, 12 | {"id":"c27b81ef56cc73bf","x":-183,"y":163,"width":269,"height":62,"color":"4","type":"text","text":"Concat more than one wav file sequentially using numpy"}, 13 | {"id":"5982504ad2a08f46","x":-248,"y":288,"width":400,"height":400,"type":"link","url":"https://stackoverflow.com/a/62298670/"}, 14 | {"id":"fdffcbd902de9780","x":248,"y":-96,"width":430,"height":159,"type":"text","text":"Timestamps\n0:00 Roadmap\n2:20 Coding Plan for Video 3\n4:33 Coding"} 15 | ], 16 | "edges":[ 17 | {"id":"67465a6b68b6ca9e","fromNode":"34465fcb1adabfa5","fromSide":"bottom","toNode":"1522690a2a5e6703","toSide":"top"}, 18 | {"id":"341e38b5a3ff0e4e","fromNode":"1522690a2a5e6703","fromSide":"bottom","toNode":"c27b81ef56cc73bf","toSide":"top"} 19 | ] 20 | } -------------------------------------------------------------------------------- /docs/Video 4.canvas: -------------------------------------------------------------------------------- 1 | { 2 | "nodes":[ 3 | {"id":"28862f2b0ae8e5bd","x":-199,"y":54,"width":250,"height":60,"type":"text","text":"Synthesizer output\nLTstrange"}, 4 | {"id":"a0187f3ca786ef60","x":-232,"y":-290,"width":315,"height":60,"type":"text","text":"# plaintext-daw 4"}, 5 | {"id":"7085c490b5432cbb","x":-199,"y":-126,"width":250,"height":60,"color":"2","type":"text","text":"Demo"}, 6 | {"id":"786091db5a5ca45b","x":-199,"y":-203,"width":250,"height":60,"color":"1","type":"text","text":"CTA: Join us!\nDiscord link in description"}, 7 | {"id":"9cbcc92d4c0d2f5e","x":-199,"y":-66,"width":250,"height":60,"type":"text","text":"Basic GUI\nLTstrange"}, 8 | {"id":"a49e87c8ee73028a","x":-199,"y":-6,"width":250,"height":60,"type":"text","text":"Chords, Rhythm output\nSteve"}, 9 | {"id":"15d211a94aad7285","x":-324,"y":214,"width":250,"height":60,"type":"text","text":"Open Project Dialog\nLTstrange"}, 10 | {"id":"7c1df30a480c08e1","x":-74,"y":214,"width":250,"height":60,"type":"text","text":"Integrate Synthesizer\nLTstrange / Steve"}, 11 | {"id":"905b65a264a0d6db","x":-74,"y":154,"width":250,"height":60,"color":"3","type":"text","text":"What's next?"}, 12 | {"id":"54ab5d96d421c0be","x":-324,"y":154,"width":250,"height":60,"color":"4","type":"text","text":"What's new?"}, 13 | {"id":"9bd34679904a3725","x":-324,"y":274,"width":250,"height":60,"type":"text","text":"Chords, tempo support\nSteve"}, 14 | {"id":"4549d2fc42eb1094","x":-74,"y":274,"width":250,"height":60,"type":"text","text":"Instrument loader\nLTstrange / Steve"}, 15 | {"id":"1c7f67dbcb114039","x":-203,"y":373,"width":259,"height":60,"color":"5","type":"text","text":"Code Walkthrough"}, 16 | {"id":"e6156aced2ca7080","x":-203,"y":433,"width":259,"height":60,"type":"text","text":"[#2](https://github.com/pagekeytech/plaintext-daw/pull/2) Add a GUI\nLTstrange"}, 17 | {"id":"232d771c43e0748b","x":-203,"y":493,"width":259,"height":60,"type":"text","text":"[#4](https://github.com/pagekeytech/plaintext-daw/pull/4) Render tempo/chords\nSteve"}, 18 | {"id":"b1eec688d357f99b","x":-203,"y":553,"width":259,"height":60,"type":"text","text":"[#3](https://github.com/pagekeytech/plaintext-daw/pull/3) Synthesizer (draft)\nLTstrange"}, 19 | {"id":"5e922e3da3c4c083","x":-290,"y":650,"width":434,"height":93,"type":"text","text":"Title:\nChords? Tempo? SYNTH?? | plaintext-daw 4"}, 20 | {"id":"5935a9cb97674901","x":-290,"y":771,"width":433,"height":288,"type":"text","text":"Timestamps\n0:00 Demo 1: Chords + Tempo\n0:18 Demo 1 Timing Issues\n1:04 Demo 2: Synth by LTstrange\n1:39 Join the Discord!\n2:04 Overview\n2:31 Roadmap, New ideas\n2:48 Demo: GUI\n3:06 Code: GUI\n3:31 Code: Render Tempo/Chords\n"} 21 | ], 22 | "edges":[] 23 | } -------------------------------------------------------------------------------- /docs/Video 5.canvas: -------------------------------------------------------------------------------- 1 | { 2 | "nodes":[ 3 | {"id":"a312a6b2b07db940","x":-125,"y":-510,"width":250,"height":60,"color":"2","type":"text","text":"Demo"}, 4 | {"id":"ff211aaae5eb4502","x":-125,"y":-450,"width":250,"height":60,"type":"text","text":"song2: Saints Go Marching"}, 5 | {"id":"50ffca0b062e97f2","x":-125,"y":-587,"width":250,"height":60,"color":"1","type":"text","text":"CTA: Join us!\nDiscord link in description"}, 6 | {"id":"309998968a2cce52","x":-158,"y":-674,"width":315,"height":60,"type":"text","text":"# plaintext-daw 5"}, 7 | {"id":"20230a199fa801c7","x":-250,"y":-354,"width":250,"height":60,"color":"4","type":"text","text":"What's new?"}, 8 | {"id":"a56222f76d8ef806","x":0,"y":-354,"width":250,"height":60,"color":"3","type":"text","text":"What's next?"}, 9 | {"id":"6c95a22f015102c0","x":0,"y":-294,"width":250,"height":60,"type":"text","text":"Integrate Synthesizer\nLTstrange / Steve"}, 10 | {"id":"6b188da29cb85f72","x":-250,"y":-234,"width":250,"height":60,"type":"text","text":"Loaded instrument from Git repo"}, 11 | {"id":"fe4720887a817557","x":-250,"y":-174,"width":250,"height":60,"type":"text","text":"Fixed BPM calculation"}, 12 | {"id":"780fa673dd829979","x":-249,"y":-294,"width":250,"height":60,"type":"text","text":"Racked up some serious code debt (Steve)"}, 13 | {"id":"fceb488c1c0a6f22","x":-128,"y":-76,"width":259,"height":60,"color":"5","type":"text","text":"Code Walkthrough"} 14 | ], 15 | "edges":[] 16 | } -------------------------------------------------------------------------------- /docs/Video 8.md: -------------------------------------------------------------------------------- 1 | 0:00 Wild Intro 2 | 0:24 MP3 to NP Code Review/Merge (#7) 3 | 0:59 Merging Support Synth Instruments (#6) 4 | 2:04 New Branch for Re-Arch 5 | 2:17 Creating Test Files for TDD 6 | 2:50 Smoke Test, Other Failures 7 | 3:02 ResourceManager: The Big Idea 8 | 4:07 ResourceManager TDD 9 | 4:40 Breaking everything because I can 10 | 5:54 MERGE CONFLICT?!? 11 | 5:58 Synth clips 12 | 7:05 Validating fields 13 | 7:19 Coverage report with pytest-cov 14 | 7:39 Recap -------------------------------------------------------------------------------- /docs/Video 9.md: -------------------------------------------------------------------------------- 1 | 0:00 Lessons Learned 2 | 0:54 Merging PR #10 from LTstrange 3 | 1:44 Figuring out next steps 4 | 2:11 Starting get_song 5 | 2:21 Implementing check_types and refactor 6 | 3:38 Implementing get_song 7 | 3:52 Adding patch.object 8 | 4:16 WARNING! False test pass with called_with method 9 | 5:11 Changing the Song class 10 | 5:36 Getting fancy with assert_has_calls 11 | 6:08 Implementing get_pattern 12 | 6:10 TIP! Argument order for patch decorators 13 | 6:43 Finishing up get_song 14 | 7:09 Reordering methods in both files 15 | 8:06 Implementing get_instrument 16 | 8:17 Implementing get_pattern 17 | 8:36 Implementing get_note -------------------------------------------------------------------------------- /plaintext_daw/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagekey/plaintext-daw/c74dc68330b1acec5892ecc20e34f208563e5a22/plaintext_daw/__init__.py -------------------------------------------------------------------------------- /plaintext_daw/cli.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | import yaml 5 | 6 | from plaintext_daw.resource_manager import ResourceManager 7 | 8 | from .gui import gui 9 | from .models import Song 10 | 11 | 12 | def print_usage(): 13 | print("Usage:") 14 | print(" plaintext-daw render : render project file to wav") 15 | print(" plaintext-daw gui: open a GUI") 16 | 17 | 18 | def cli_entry_point(args=sys.argv): 19 | if len(args) >= 2: 20 | if args[1] == 'gui': 21 | exit(gui()) 22 | elif args[1] == 'render': 23 | if len(args) >= 3: 24 | config_path = args[2] 25 | if not os.path.exists(config_path): 26 | print("Error: %s not found" % config_path, file=sys.stderr) 27 | sys.exit(1) 28 | # Load config 29 | rm = ResourceManager(os.path.dirname(config_path)) 30 | config = rm.get_config_from_file(os.path.basename(config_path)) 31 | song = rm.get_song(config) 32 | # Render song to file 33 | song.render('song.wav') 34 | else: 35 | print_usage() 36 | else: 37 | print_usage() 38 | else: 39 | print_usage() 40 | -------------------------------------------------------------------------------- /plaintext_daw/gui.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @Time : 2023/1/28 23:07 3 | # @Author : LTstrange 4 | 5 | from PyQt5 import QtWidgets as qtw 6 | from PyQt5 import QtGui as qtg 7 | 8 | 9 | class MainWindow(qtw.QWidget): 10 | def __init__(self): 11 | super().__init__() 12 | 13 | self.setWindowTitle("plaintext-DAW") 14 | self.resize(640, 480) 15 | 16 | btn = qtw.QPushButton(self) 17 | fnt = qtg.QFont() 18 | fnt.setPointSize(20) 19 | btn.setFont(fnt) 20 | btn.setText("Open Project") 21 | btn.adjustSize() 22 | btn.clicked.connect(self.open_project) 23 | 24 | layout = qtw.QVBoxLayout() 25 | layout.addWidget(btn) 26 | 27 | self.setLayout(layout) 28 | 29 | def open_project(self): 30 | qtw.QMessageBox().information(self, "plaintext-DAW", "Hello World") 31 | 32 | 33 | def gui(): 34 | app = qtw.QApplication([]) 35 | mw = MainWindow() 36 | mw.show() 37 | return app.exec_() 38 | -------------------------------------------------------------------------------- /plaintext_daw/lib.py: -------------------------------------------------------------------------------- 1 | import wave 2 | import numpy as np 3 | from pydub import AudioSegment 4 | 5 | MAX_INT16 = 2 ** 15 6 | 7 | 8 | def minmax_mapping(wave_data: np.ndarray) -> np.ndarray: 9 | return 1.8 * wave_data / (np.max(wave_data) - np.min(wave_data)) 10 | 11 | 12 | def wav_to_np(wav_path) -> (np.ndarray, int, int, int): 13 | f = wave.open(wav_path) 14 | # Read metadata 15 | samples = f.getnframes() 16 | data = f.readframes(samples) 17 | channels = f.getnchannels() 18 | sample_rate = f.getframerate() 19 | f.close() 20 | # Convert to normalized np array 21 | audio_int16 = np.frombuffer(data, dtype=np.int16) 22 | audio_float32 = audio_int16.astype(np.float32) 23 | audio_normalized = audio_float32 / MAX_INT16 24 | return audio_normalized, channels, sample_rate 25 | 26 | 27 | def np_to_wav(song_np, channels, sample_width, sample_rate, wav_path): 28 | # clamp value 29 | song_np = minmax_mapping(song_np) 30 | 31 | # Convert song to raw audio 32 | audio_raw = song_np * MAX_INT16 33 | audio_raw_int16 = audio_raw.astype(np.int16) 34 | # Write to file 35 | f_out = wave.open(wav_path, 'wb') 36 | f_out.setnchannels(channels) 37 | f_out.setsampwidth(sample_width) 38 | f_out.setframerate(sample_rate) 39 | f_out.writeframes(audio_raw_int16) 40 | 41 | 42 | def mp3_to_np(mp3_path) -> (np.ndarray, int, int, int): 43 | audio = AudioSegment.from_mp3(mp3_path) 44 | channels = audio.channels 45 | sample_rate = audio.frame_rate 46 | 47 | audio_float32 = np.array(audio.get_array_of_samples()).reshape((-1, channels)).astype(np.float32) 48 | audio_normalized = audio_float32 / MAX_INT16 49 | 50 | return audio_normalized, channels, sample_rate 51 | 52 | 53 | def np_to_mp3(song_np: np.ndarray, sample_rate, mp3_path): 54 | if len(song_np.shape) == 1: 55 | song_np = song_np.reshape((-1, 1)) 56 | assert len(song_np.shape) == 2 # (sample_length, channels) 57 | 58 | # clamp value 59 | song_np = minmax_mapping(song_np) 60 | 61 | song_np *= MAX_INT16 62 | song_np = song_np.astype(np.int16) 63 | audio = AudioSegment(song_np.tobytes(), channels=song_np.shape[-1], frame_rate=sample_rate, 64 | sample_width=song_np.dtype.itemsize) 65 | audio.export(mp3_path, format='mp3') 66 | -------------------------------------------------------------------------------- /plaintext_daw/models/__init__.py: -------------------------------------------------------------------------------- 1 | from .instrument import Instrument 2 | from .note import Note 3 | from .pattern import Pattern 4 | from .clip import Clip 5 | from .song import Song -------------------------------------------------------------------------------- /plaintext_daw/models/clip.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | class Clip: 5 | 6 | def __init__( 7 | self, 8 | data: np.ndarray, 9 | channels: int, 10 | sample_rate: int, 11 | ): 12 | self.data = data 13 | self.channels = channels 14 | self.sample_rate = sample_rate 15 | -------------------------------------------------------------------------------- /plaintext_daw/models/instrument.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | from typing import Dict 3 | 4 | from .clip import Clip 5 | 6 | 7 | class InstrumentSource(Enum): 8 | IN_PLACE = 1 # in the config, no need to load an external file 9 | LOCAL_FILE = 2 # config file present somewhere on filesystem 10 | GIT = 3 # can be loaded with Git, either via ssh or https depending on the url 11 | 12 | 13 | class Instrument: 14 | def __init__( 15 | self, 16 | source=InstrumentSource.IN_PLACE, 17 | ins_type='wav', 18 | repo='', 19 | ref='', 20 | path='', 21 | ): 22 | self.clips: Dict[str, Clip] = {} 23 | self.source = source 24 | self.type = ins_type 25 | self.repo = repo 26 | self.ref = ref 27 | self.path = path 28 | 29 | def get_clip(self, note, bpm): 30 | return self.clips[note.value] 31 | -------------------------------------------------------------------------------- /plaintext_daw/models/note.py: -------------------------------------------------------------------------------- 1 | class Note: 2 | 3 | def __init__( 4 | self, 5 | value: str = '', 6 | start: float = 0, 7 | length: float = 1, 8 | ): 9 | self.value = value 10 | self.start = start 11 | self.length = length 12 | 13 | @staticmethod 14 | def beats_to_samples(beats, bpm, sample_rate): 15 | return int(beats*(60/bpm)*sample_rate) 16 | 17 | def get_start_sample(self, bpm, sample_rate): 18 | return Note.beats_to_samples(self.start, bpm, sample_rate) 19 | 20 | def get_end_sample(self, bpm, sample_rate): 21 | beat = self.start + self.length 22 | return Note.beats_to_samples(beat, bpm, sample_rate) 23 | -------------------------------------------------------------------------------- /plaintext_daw/models/pattern.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from .note import Note 4 | 5 | 6 | class Pattern: 7 | 8 | def __init__( 9 | self, 10 | instrument: str, 11 | start: int, 12 | repeat: int, 13 | ): 14 | self.instrument = instrument 15 | self.start = start 16 | self.repeat = repeat 17 | self.notes: List[Note] = [] 18 | -------------------------------------------------------------------------------- /plaintext_daw/models/song.py: -------------------------------------------------------------------------------- 1 | from typing import Dict 2 | 3 | import numpy as np 4 | 5 | from ..lib import np_to_wav 6 | from .instrument import Instrument 7 | from .pattern import Pattern 8 | from .clip import Clip 9 | 10 | 11 | class Song: 12 | 13 | def __init__( 14 | self, 15 | bpm: int, 16 | sample_rate: int, 17 | ): 18 | self.bpm = bpm 19 | self.sample_rate = sample_rate 20 | self.instruments: Dict[str, Instrument] = {} 21 | self.patterns: Dict[str, Pattern] = {} 22 | self.clips: Dict[str, Clip] = {} 23 | 24 | def render(self, out_filename: str): 25 | # Aggregate notes into a single list 26 | # Eventually, this approach will need to be upgraded when patterns have an offset too 27 | # For now, it works 28 | all_notes = [] 29 | for pattern_name, pattern in self.patterns.items(): 30 | for note in pattern.notes: 31 | all_notes.append(note) 32 | 33 | # Figure out how many samples the final render will be 34 | # end_sample = max([n.get_end_sample(self.sample_rate, self.bpm) for n in all_notes]) 35 | 36 | # Allocate an np array for the entire song 37 | song_data = np.zeros(1) 38 | 39 | # TODO support more options than just these defaults 40 | channels = 1 41 | sample_width = 2 42 | sample_rate = self.sample_rate 43 | 44 | for note in all_notes: 45 | # Get the raw audio data for this note 46 | instrument = self.instruments[pattern.instrument] 47 | clip = instrument.get_clip(note, self.bpm) 48 | if clip is not None: # only render note if found 49 | # Compute sample start/end 50 | start = note.get_start_sample(self.bpm, self.sample_rate) 51 | end = note.get_end_sample(self.bpm, self.sample_rate) 52 | # If end is past clip end, then make end at the clip end 53 | if end-start > len(clip.data): 54 | end = start + len(clip.data) 55 | # If end is past the song end, pad out the rest of the song with zeros 56 | num_new_samples = end - len(song_data) 57 | if num_new_samples > 0: 58 | song_data = np.pad(song_data, (0, num_new_samples)) 59 | # Put it in the song at the right place 60 | song_data[start:end] += clip.data[0:end-start] 61 | np_to_wav(song_data, channels, sample_width, sample_rate, out_filename) 62 | -------------------------------------------------------------------------------- /plaintext_daw/models/synthesizer/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @Time : 2023/2/9 15:16 3 | # @Author : LTstrange 4 | 5 | from .synth import Synthesizer 6 | 7 | __all__ = ["Synthesizer"] 8 | -------------------------------------------------------------------------------- /plaintext_daw/models/synthesizer/envelope.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @Time : 2023/2/9 18:50 3 | # @Author : LTstrange 4 | 5 | import numpy as np 6 | from .wave import Wave 7 | 8 | 9 | class Envelope: 10 | def __call__(self, wave: Wave, duration: float, sample_rate: float) -> np.ndarray: 11 | raise NotImplementedError 12 | 13 | 14 | class ADSR(Envelope): 15 | def __init__(self, attack: float, decay: float, sustain_level: float, release: float): 16 | """ 17 | fade in/out envelope 18 | :param attack: The time for the amplitude to increase from 0 to 1. 19 | :param decay: The time for the amplitude to decrease from 1 to sustain. 20 | :param sustain_level: A fraction of the maximum amplitude (0 to 1). 21 | :param release: The time for the amplitude to decrease from sustain to 0. 22 | """ 23 | self.attack = attack # second 24 | self.decay = decay # second 25 | self.sustain_level = sustain_level # fraction 26 | self.release = release # second 27 | 28 | def __call__(self, wave: Wave, duration: float, sample_rate: int) -> np.ndarray: 29 | # Calculate the length of each stage in samples 30 | attack_samples = int(self.attack * sample_rate) 31 | decay_samples = int(self.decay * sample_rate) 32 | sustain = duration - self.attack - self.decay - self.release 33 | sustain_samples = int(sustain * sample_rate) if sustain > 0 else 0 34 | release_samples = int(self.release * sample_rate) 35 | 36 | sample_length = attack_samples + decay_samples + sustain_samples + release_samples 37 | 38 | # Initialize the envelope 39 | envelope = np.zeros(sample_length) 40 | 41 | # Attack stage 42 | envelope[:attack_samples] = np.linspace(0, 1, attack_samples) 43 | # Decay stage 44 | envelope[attack_samples:attack_samples + decay_samples] = np.linspace(1, self.sustain_level, decay_samples) 45 | # Sustain stage 46 | envelope[attack_samples + decay_samples:attack_samples + decay_samples + sustain_samples] = self.sustain_level 47 | # Release stage 48 | envelope[attack_samples + decay_samples + sustain_samples:] = np.linspace(self.sustain_level, 0, 49 | release_samples) 50 | 51 | wave_samples = wave.render(duration, sample_length) 52 | return wave_samples * envelope 53 | -------------------------------------------------------------------------------- /plaintext_daw/models/synthesizer/rawclip.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @Time : 2023/2/9 15:14 3 | # @Author : LTstrange 4 | 5 | from .envelope import Envelope 6 | from .wave import Wave 7 | 8 | 9 | class RawClip: 10 | def __init__(self, source: Wave, envelope: Envelope, duration: float = None): 11 | self.source = source 12 | self.envelope = envelope 13 | self.duration = duration 14 | 15 | def set_duration(self, duration: float): 16 | self.duration = duration 17 | 18 | def render(self, sample_rate: float): 19 | if self.duration is None: 20 | raise "No duration defined. use `Clip.set_duration()`" 21 | return self.envelope(self.source, self.duration, sample_rate) 22 | -------------------------------------------------------------------------------- /plaintext_daw/models/synthesizer/synth.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, List, Tuple, Union 2 | import re 3 | import numpy as np 4 | import yaml 5 | 6 | from .wave import Sine, Wave 7 | from .rawclip import RawClip 8 | from .envelope import ADSR 9 | 10 | from plaintext_daw.models import Clip, Note 11 | 12 | 13 | class Synthesizer: 14 | def __init__(self, sample_rate): 15 | self.sample_rate = sample_rate 16 | self.__effects: list = [] 17 | self.__clips: Dict[str, Dict[str, float]] = dict() 18 | 19 | def set_pipeline(self, config): 20 | self.__effects = config 21 | 22 | def set_clips(self, config: dict): 23 | self.__clips = config 24 | 25 | def get_clip(self, note: Note, bpm: int) -> Union[Clip, None]: 26 | if note.value not in self.__clips: 27 | return None 28 | clip = self.__pipeline(self.__clips[note.value]) 29 | seconds = note.length * 60 / bpm 30 | clip.set_duration(seconds) 31 | rawdata = clip.render(self.sample_rate) 32 | return Clip(rawdata, 1, self.sample_rate) 33 | 34 | def __pipeline(self, actual_param: Dict[str, float]) -> RawClip: 35 | result = None 36 | for effect in self.__effects: 37 | effect, form_param = re.match(r"(\w+)(?:\((.+)\))?", effect).groups() 38 | form_param = form_param.split(',') 39 | if effect == 'sin' and form_param[0] == 'frequency': 40 | result = Wave([Sine(actual_param[form_param[0]], 1)]) 41 | elif effect == "ADSR" and len(form_param) == 4: 42 | form_param = [float(p) for p in form_param] 43 | result = RawClip(result, ADSR(*form_param)) 44 | return result 45 | -------------------------------------------------------------------------------- /plaintext_daw/models/synthesizer/wave.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @Time : 2023/2/9 16:09 3 | # @Author : LTstrange 4 | 5 | import numpy as np 6 | from enum import Enum 7 | from typing import List 8 | 9 | 10 | class WaveType(Enum): 11 | sine = 1 12 | 13 | 14 | class PrimitiveWave: 15 | def __init__(self, wave_type: WaveType, amplitude: float): 16 | self.wave_type = wave_type 17 | self.amplitude = amplitude 18 | 19 | def render(self, duration: float, sample_length: int) -> np.ndarray: 20 | raise NotImplementedError 21 | 22 | 23 | class Wave: 24 | def __init__(self, primitive_waves: List[PrimitiveWave]): 25 | self.primitive_waves = primitive_waves 26 | 27 | def render(self, duration: float, sample_length: int): 28 | wave = np.zeros(sample_length) 29 | for primitive in self.primitive_waves: 30 | wave += primitive.render(duration, sample_length) 31 | 32 | return wave 33 | 34 | 35 | class Sine(PrimitiveWave): 36 | def __init__(self, base_freq: float, amplitude: float): 37 | super().__init__(WaveType.sine, amplitude) 38 | self.base_freq = base_freq 39 | 40 | def render(self, duration: float, sample_length: int): 41 | t = np.linspace(0, duration, sample_length) 42 | return np.sin(2 * np.pi * self.base_freq * t) 43 | -------------------------------------------------------------------------------- /plaintext_daw/resource_manager.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | 4 | import yaml 5 | 6 | from plaintext_daw.lib import wav_to_np 7 | from plaintext_daw.models.clip import Clip 8 | from plaintext_daw.models.instrument import Instrument, InstrumentSource 9 | from plaintext_daw.models.note import Note 10 | from plaintext_daw.models.pattern import Pattern 11 | from plaintext_daw.models.song import Song 12 | from plaintext_daw.models.synthesizer import Synthesizer 13 | 14 | 15 | class ResourceManager: 16 | def __init__(self, working_dir, cache_dir='.ptd-cache'): 17 | self.working_dir = working_dir 18 | self.cache_dir = cache_dir 19 | 20 | @staticmethod 21 | def check_types(config, types): 22 | for type in types: 23 | if type not in config: 24 | raise ValueError(f'Required field {type} not found in config') 25 | 26 | def get_song(self, config): 27 | self.check_types(config, ['bpm', 'sample_rate', 'clips', 'instruments', 'patterns']) 28 | song = Song(config['bpm'], config['sample_rate']) 29 | for key, value in config['clips'].items(): 30 | song.clips[key] = self.get_clip(value) 31 | for key, value in config['instruments'].items(): 32 | song.instruments[key] = self.get_instrument(value) 33 | for key, value in config['patterns'].items(): 34 | song.patterns[key] = self.get_pattern(value) 35 | return song 36 | 37 | def get_clip(self, config): 38 | # config['type'] == 'wav': 39 | # load the binary data (WAV) 40 | self.check_types(config, ['path']) 41 | data, channels, sample_rate = wav_to_np(os.path.join(self.working_dir, config['path'])) 42 | 43 | clip = Clip( 44 | data=data, 45 | channels=channels, 46 | sample_rate=sample_rate, 47 | ) 48 | return clip 49 | 50 | def get_instrument(self, config): 51 | if 'source' in config and config['source'] == 'GIT': 52 | self.check_types(config, ['source', 'repo', 'ref', 'path']) 53 | self.clone_repo(config['repo'], config['ref']) 54 | repo_name = os.path.basename(config['repo']).replace('.git', '') 55 | path_to_config = os.path.join(self.cache_dir, repo_name, config['path']) 56 | config_home_area = os.path.dirname(path_to_config) 57 | config_from_file = self.get_config_from_file(path_to_config) 58 | instrument = Instrument( 59 | source=InstrumentSource.GIT, 60 | repo=config['repo'], 61 | ref=config['ref'], 62 | path=config['path'], 63 | ) 64 | for key, value in config_from_file['clips'].items(): 65 | instrument.clips[key] = self.get_clip({'path': os.path.join(config_home_area, value['path'])}) 66 | return instrument 67 | else: 68 | self.check_types(config, ['clips', 'type']) 69 | if config['type'] == 'synth': # synthesizer 70 | synth = Synthesizer(sample_rate=44100) 71 | synth.set_clips(config['clips']) 72 | self.check_types(config, ['pipeline']) 73 | synth.set_pipeline(config['pipeline']) 74 | return synth 75 | else: # wave clip 76 | instrument = Instrument() 77 | for key, value in config['clips'].items(): 78 | instrument.clips[key] = self.get_clip(value) 79 | return instrument 80 | 81 | def get_pattern(self, config): 82 | self.check_types(config, ['instrument', 'start', 'repeat']) 83 | pattern = Pattern(config['instrument'], config['start'], config['repeat']) 84 | for note_dict in config['notes']: 85 | pattern.notes.append(self.get_note(note_dict)) 86 | return pattern 87 | 88 | def get_note(self, config): 89 | self.check_types(config, ['value', 'start', 'length']) 90 | note = Note(config['value'], config['start'], config['length']) 91 | return note 92 | 93 | def clone_repo(self, repo, ref): 94 | cache_dir_path = os.path.join(self.working_dir, self.cache_dir) 95 | os.makedirs(cache_dir_path, exist_ok=True) 96 | repo_name = os.path.basename(repo) 97 | repo_path = os.path.join(cache_dir_path, repo_name) 98 | if not os.path.exists(repo_path): 99 | subprocess.check_call(f'git clone {repo}'.split(), cwd=cache_dir_path) 100 | subprocess.check_call(f'git checkout {ref}'.split(), cwd=os.path.join(cache_dir_path, repo_name)) 101 | 102 | def get_config_from_file(self, path): 103 | with open(os.path.join(self.working_dir, path)) as f: 104 | config = yaml.safe_load(f) 105 | return config 106 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | from distutils.core import setup 3 | 4 | 5 | setup( 6 | name='plaintext-daw', 7 | version='0.0.0', 8 | description='Plaintext DAW', 9 | author='Steve Grice', 10 | author_email='steve@pagekeytech.com', 11 | packages=['plaintext_daw'], 12 | entry_points={ 13 | 'console_scripts': ['plaintext-daw=plaintext_daw.cli:cli_entry_point'], 14 | }, 15 | install_requires=[ 16 | 'numpy', 17 | 'pyyaml', 18 | 'PyQt5', 19 | "pydub", 20 | ], 21 | ) 22 | -------------------------------------------------------------------------------- /tauri/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /tauri/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["tauri-apps.tauri-vscode", "rust-lang.rust-analyzer"] 3 | } 4 | -------------------------------------------------------------------------------- /tauri/README.md: -------------------------------------------------------------------------------- 1 | # Tauri + Vanilla 2 | 3 | This template should help get you started developing with Tauri in vanilla HTML, CSS and Javascript. 4 | 5 | ## Getting Started 6 | 7 | Run dev server 8 | 9 | ```bash 10 | cargo tauri dev 11 | ``` 12 | 13 | Run tests 14 | 15 | ```bash 16 | cd src-tauri 17 | cargo test 18 | ``` 19 | 20 | ## Recommended IDE Setup 21 | 22 | - [VS Code](https://code.visualstudio.com/) + [Tauri](https://marketplace.visualstudio.com/items?itemName=tauri-apps.tauri-vscode) + [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer) 23 | -------------------------------------------------------------------------------- /tauri/src-tauri/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | -------------------------------------------------------------------------------- /tauri/src-tauri/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "adler" 7 | version = "1.0.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 10 | 11 | [[package]] 12 | name = "aho-corasick" 13 | version = "0.7.20" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" 16 | dependencies = [ 17 | "memchr", 18 | ] 19 | 20 | [[package]] 21 | name = "alloc-no-stdlib" 22 | version = "2.0.4" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" 25 | 26 | [[package]] 27 | name = "alloc-stdlib" 28 | version = "0.2.2" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" 31 | dependencies = [ 32 | "alloc-no-stdlib", 33 | ] 34 | 35 | [[package]] 36 | name = "anyhow" 37 | version = "1.0.69" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" 40 | 41 | [[package]] 42 | name = "atk" 43 | version = "0.15.1" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "2c3d816ce6f0e2909a96830d6911c2aff044370b1ef92d7f267b43bae5addedd" 46 | dependencies = [ 47 | "atk-sys", 48 | "bitflags", 49 | "glib", 50 | "libc", 51 | ] 52 | 53 | [[package]] 54 | name = "atk-sys" 55 | version = "0.15.1" 56 | source = "registry+https://github.com/rust-lang/crates.io-index" 57 | checksum = "58aeb089fb698e06db8089971c7ee317ab9644bade33383f63631437b03aafb6" 58 | dependencies = [ 59 | "glib-sys", 60 | "gobject-sys", 61 | "libc", 62 | "system-deps 6.0.3", 63 | ] 64 | 65 | [[package]] 66 | name = "autocfg" 67 | version = "1.1.0" 68 | source = "registry+https://github.com/rust-lang/crates.io-index" 69 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 70 | 71 | [[package]] 72 | name = "base64" 73 | version = "0.13.1" 74 | source = "registry+https://github.com/rust-lang/crates.io-index" 75 | checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" 76 | 77 | [[package]] 78 | name = "bitflags" 79 | version = "1.3.2" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 82 | 83 | [[package]] 84 | name = "block" 85 | version = "0.1.6" 86 | source = "registry+https://github.com/rust-lang/crates.io-index" 87 | checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" 88 | 89 | [[package]] 90 | name = "block-buffer" 91 | version = "0.10.3" 92 | source = "registry+https://github.com/rust-lang/crates.io-index" 93 | checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" 94 | dependencies = [ 95 | "generic-array", 96 | ] 97 | 98 | [[package]] 99 | name = "brotli" 100 | version = "3.3.4" 101 | source = "registry+https://github.com/rust-lang/crates.io-index" 102 | checksum = "a1a0b1dbcc8ae29329621f8d4f0d835787c1c38bb1401979b49d13b0b305ff68" 103 | dependencies = [ 104 | "alloc-no-stdlib", 105 | "alloc-stdlib", 106 | "brotli-decompressor", 107 | ] 108 | 109 | [[package]] 110 | name = "brotli-decompressor" 111 | version = "2.3.4" 112 | source = "registry+https://github.com/rust-lang/crates.io-index" 113 | checksum = "4b6561fd3f895a11e8f72af2cb7d22e08366bebc2b6b57f7744c4bda27034744" 114 | dependencies = [ 115 | "alloc-no-stdlib", 116 | "alloc-stdlib", 117 | ] 118 | 119 | [[package]] 120 | name = "bstr" 121 | version = "1.2.0" 122 | source = "registry+https://github.com/rust-lang/crates.io-index" 123 | checksum = "b7f0778972c64420fdedc63f09919c8a88bda7b25135357fd25a5d9f3257e832" 124 | dependencies = [ 125 | "memchr", 126 | "serde", 127 | ] 128 | 129 | [[package]] 130 | name = "bumpalo" 131 | version = "3.12.0" 132 | source = "registry+https://github.com/rust-lang/crates.io-index" 133 | checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" 134 | 135 | [[package]] 136 | name = "bytemuck" 137 | version = "1.13.0" 138 | source = "registry+https://github.com/rust-lang/crates.io-index" 139 | checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393" 140 | 141 | [[package]] 142 | name = "byteorder" 143 | version = "1.4.3" 144 | source = "registry+https://github.com/rust-lang/crates.io-index" 145 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 146 | 147 | [[package]] 148 | name = "bytes" 149 | version = "1.4.0" 150 | source = "registry+https://github.com/rust-lang/crates.io-index" 151 | checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" 152 | 153 | [[package]] 154 | name = "cairo-rs" 155 | version = "0.15.12" 156 | source = "registry+https://github.com/rust-lang/crates.io-index" 157 | checksum = "c76ee391b03d35510d9fa917357c7f1855bd9a6659c95a1b392e33f49b3369bc" 158 | dependencies = [ 159 | "bitflags", 160 | "cairo-sys-rs", 161 | "glib", 162 | "libc", 163 | "thiserror", 164 | ] 165 | 166 | [[package]] 167 | name = "cairo-sys-rs" 168 | version = "0.15.1" 169 | source = "registry+https://github.com/rust-lang/crates.io-index" 170 | checksum = "3c55d429bef56ac9172d25fecb85dc8068307d17acd74b377866b7a1ef25d3c8" 171 | dependencies = [ 172 | "glib-sys", 173 | "libc", 174 | "system-deps 6.0.3", 175 | ] 176 | 177 | [[package]] 178 | name = "cargo_toml" 179 | version = "0.13.3" 180 | source = "registry+https://github.com/rust-lang/crates.io-index" 181 | checksum = "497049e9477329f8f6a559972ee42e117487d01d1e8c2cc9f836ea6fa23a9e1a" 182 | dependencies = [ 183 | "serde", 184 | "toml", 185 | ] 186 | 187 | [[package]] 188 | name = "cc" 189 | version = "1.0.79" 190 | source = "registry+https://github.com/rust-lang/crates.io-index" 191 | checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" 192 | 193 | [[package]] 194 | name = "cesu8" 195 | version = "1.1.0" 196 | source = "registry+https://github.com/rust-lang/crates.io-index" 197 | checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" 198 | 199 | [[package]] 200 | name = "cfb" 201 | version = "0.6.1" 202 | source = "registry+https://github.com/rust-lang/crates.io-index" 203 | checksum = "74f89d248799e3f15f91b70917f65381062a01bb8e222700ea0e5a7ff9785f9c" 204 | dependencies = [ 205 | "byteorder", 206 | "uuid 0.8.2", 207 | ] 208 | 209 | [[package]] 210 | name = "cfg-expr" 211 | version = "0.9.1" 212 | source = "registry+https://github.com/rust-lang/crates.io-index" 213 | checksum = "3431df59f28accaf4cb4eed4a9acc66bea3f3c3753aa6cdc2f024174ef232af7" 214 | dependencies = [ 215 | "smallvec", 216 | ] 217 | 218 | [[package]] 219 | name = "cfg-expr" 220 | version = "0.11.0" 221 | source = "registry+https://github.com/rust-lang/crates.io-index" 222 | checksum = "b0357a6402b295ca3a86bc148e84df46c02e41f41fef186bda662557ef6328aa" 223 | dependencies = [ 224 | "smallvec", 225 | ] 226 | 227 | [[package]] 228 | name = "cfg-if" 229 | version = "1.0.0" 230 | source = "registry+https://github.com/rust-lang/crates.io-index" 231 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 232 | 233 | [[package]] 234 | name = "cocoa" 235 | version = "0.24.1" 236 | source = "registry+https://github.com/rust-lang/crates.io-index" 237 | checksum = "f425db7937052c684daec3bd6375c8abe2d146dca4b8b143d6db777c39138f3a" 238 | dependencies = [ 239 | "bitflags", 240 | "block", 241 | "cocoa-foundation", 242 | "core-foundation", 243 | "core-graphics", 244 | "foreign-types", 245 | "libc", 246 | "objc", 247 | ] 248 | 249 | [[package]] 250 | name = "cocoa-foundation" 251 | version = "0.1.0" 252 | source = "registry+https://github.com/rust-lang/crates.io-index" 253 | checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318" 254 | dependencies = [ 255 | "bitflags", 256 | "block", 257 | "core-foundation", 258 | "core-graphics-types", 259 | "foreign-types", 260 | "libc", 261 | "objc", 262 | ] 263 | 264 | [[package]] 265 | name = "color_quant" 266 | version = "1.1.0" 267 | source = "registry+https://github.com/rust-lang/crates.io-index" 268 | checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" 269 | 270 | [[package]] 271 | name = "combine" 272 | version = "4.6.6" 273 | source = "registry+https://github.com/rust-lang/crates.io-index" 274 | checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" 275 | dependencies = [ 276 | "bytes", 277 | "memchr", 278 | ] 279 | 280 | [[package]] 281 | name = "convert_case" 282 | version = "0.4.0" 283 | source = "registry+https://github.com/rust-lang/crates.io-index" 284 | checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" 285 | 286 | [[package]] 287 | name = "core-foundation" 288 | version = "0.9.3" 289 | source = "registry+https://github.com/rust-lang/crates.io-index" 290 | checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" 291 | dependencies = [ 292 | "core-foundation-sys", 293 | "libc", 294 | ] 295 | 296 | [[package]] 297 | name = "core-foundation-sys" 298 | version = "0.8.3" 299 | source = "registry+https://github.com/rust-lang/crates.io-index" 300 | checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" 301 | 302 | [[package]] 303 | name = "core-graphics" 304 | version = "0.22.3" 305 | source = "registry+https://github.com/rust-lang/crates.io-index" 306 | checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" 307 | dependencies = [ 308 | "bitflags", 309 | "core-foundation", 310 | "core-graphics-types", 311 | "foreign-types", 312 | "libc", 313 | ] 314 | 315 | [[package]] 316 | name = "core-graphics-types" 317 | version = "0.1.1" 318 | source = "registry+https://github.com/rust-lang/crates.io-index" 319 | checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" 320 | dependencies = [ 321 | "bitflags", 322 | "core-foundation", 323 | "foreign-types", 324 | "libc", 325 | ] 326 | 327 | [[package]] 328 | name = "cpufeatures" 329 | version = "0.2.5" 330 | source = "registry+https://github.com/rust-lang/crates.io-index" 331 | checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" 332 | dependencies = [ 333 | "libc", 334 | ] 335 | 336 | [[package]] 337 | name = "crc32fast" 338 | version = "1.3.2" 339 | source = "registry+https://github.com/rust-lang/crates.io-index" 340 | checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" 341 | dependencies = [ 342 | "cfg-if", 343 | ] 344 | 345 | [[package]] 346 | name = "crossbeam-channel" 347 | version = "0.5.6" 348 | source = "registry+https://github.com/rust-lang/crates.io-index" 349 | checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" 350 | dependencies = [ 351 | "cfg-if", 352 | "crossbeam-utils", 353 | ] 354 | 355 | [[package]] 356 | name = "crossbeam-utils" 357 | version = "0.8.14" 358 | source = "registry+https://github.com/rust-lang/crates.io-index" 359 | checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" 360 | dependencies = [ 361 | "cfg-if", 362 | ] 363 | 364 | [[package]] 365 | name = "crypto-common" 366 | version = "0.1.6" 367 | source = "registry+https://github.com/rust-lang/crates.io-index" 368 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 369 | dependencies = [ 370 | "generic-array", 371 | "typenum", 372 | ] 373 | 374 | [[package]] 375 | name = "cssparser" 376 | version = "0.27.2" 377 | source = "registry+https://github.com/rust-lang/crates.io-index" 378 | checksum = "754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a" 379 | dependencies = [ 380 | "cssparser-macros", 381 | "dtoa-short", 382 | "itoa 0.4.8", 383 | "matches", 384 | "phf 0.8.0", 385 | "proc-macro2", 386 | "quote", 387 | "smallvec", 388 | "syn", 389 | ] 390 | 391 | [[package]] 392 | name = "cssparser-macros" 393 | version = "0.6.0" 394 | source = "registry+https://github.com/rust-lang/crates.io-index" 395 | checksum = "dfae75de57f2b2e85e8768c3ea840fd159c8f33e2b6522c7835b7abac81be16e" 396 | dependencies = [ 397 | "quote", 398 | "syn", 399 | ] 400 | 401 | [[package]] 402 | name = "ctor" 403 | version = "0.1.26" 404 | source = "registry+https://github.com/rust-lang/crates.io-index" 405 | checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" 406 | dependencies = [ 407 | "quote", 408 | "syn", 409 | ] 410 | 411 | [[package]] 412 | name = "cty" 413 | version = "0.2.2" 414 | source = "registry+https://github.com/rust-lang/crates.io-index" 415 | checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" 416 | 417 | [[package]] 418 | name = "darling" 419 | version = "0.13.4" 420 | source = "registry+https://github.com/rust-lang/crates.io-index" 421 | checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" 422 | dependencies = [ 423 | "darling_core", 424 | "darling_macro", 425 | ] 426 | 427 | [[package]] 428 | name = "darling_core" 429 | version = "0.13.4" 430 | source = "registry+https://github.com/rust-lang/crates.io-index" 431 | checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" 432 | dependencies = [ 433 | "fnv", 434 | "ident_case", 435 | "proc-macro2", 436 | "quote", 437 | "strsim", 438 | "syn", 439 | ] 440 | 441 | [[package]] 442 | name = "darling_macro" 443 | version = "0.13.4" 444 | source = "registry+https://github.com/rust-lang/crates.io-index" 445 | checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" 446 | dependencies = [ 447 | "darling_core", 448 | "quote", 449 | "syn", 450 | ] 451 | 452 | [[package]] 453 | name = "derive_more" 454 | version = "0.99.17" 455 | source = "registry+https://github.com/rust-lang/crates.io-index" 456 | checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" 457 | dependencies = [ 458 | "convert_case", 459 | "proc-macro2", 460 | "quote", 461 | "rustc_version 0.4.0", 462 | "syn", 463 | ] 464 | 465 | [[package]] 466 | name = "digest" 467 | version = "0.10.6" 468 | source = "registry+https://github.com/rust-lang/crates.io-index" 469 | checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" 470 | dependencies = [ 471 | "block-buffer", 472 | "crypto-common", 473 | ] 474 | 475 | [[package]] 476 | name = "dirs-next" 477 | version = "2.0.0" 478 | source = "registry+https://github.com/rust-lang/crates.io-index" 479 | checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" 480 | dependencies = [ 481 | "cfg-if", 482 | "dirs-sys-next", 483 | ] 484 | 485 | [[package]] 486 | name = "dirs-sys-next" 487 | version = "0.1.2" 488 | source = "registry+https://github.com/rust-lang/crates.io-index" 489 | checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" 490 | dependencies = [ 491 | "libc", 492 | "redox_users", 493 | "winapi", 494 | ] 495 | 496 | [[package]] 497 | name = "dispatch" 498 | version = "0.2.0" 499 | source = "registry+https://github.com/rust-lang/crates.io-index" 500 | checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" 501 | 502 | [[package]] 503 | name = "dtoa" 504 | version = "0.4.8" 505 | source = "registry+https://github.com/rust-lang/crates.io-index" 506 | checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" 507 | 508 | [[package]] 509 | name = "dtoa-short" 510 | version = "0.3.3" 511 | source = "registry+https://github.com/rust-lang/crates.io-index" 512 | checksum = "bde03329ae10e79ede66c9ce4dc930aa8599043b0743008548680f25b91502d6" 513 | dependencies = [ 514 | "dtoa", 515 | ] 516 | 517 | [[package]] 518 | name = "dunce" 519 | version = "1.0.3" 520 | source = "registry+https://github.com/rust-lang/crates.io-index" 521 | checksum = "0bd4b30a6560bbd9b4620f4de34c3f14f60848e58a9b7216801afcb4c7b31c3c" 522 | 523 | [[package]] 524 | name = "embed_plist" 525 | version = "1.2.2" 526 | source = "registry+https://github.com/rust-lang/crates.io-index" 527 | checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" 528 | 529 | [[package]] 530 | name = "encoding_rs" 531 | version = "0.8.32" 532 | source = "registry+https://github.com/rust-lang/crates.io-index" 533 | checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" 534 | dependencies = [ 535 | "cfg-if", 536 | ] 537 | 538 | [[package]] 539 | name = "fastrand" 540 | version = "1.8.0" 541 | source = "registry+https://github.com/rust-lang/crates.io-index" 542 | checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" 543 | dependencies = [ 544 | "instant", 545 | ] 546 | 547 | [[package]] 548 | name = "field-offset" 549 | version = "0.3.4" 550 | source = "registry+https://github.com/rust-lang/crates.io-index" 551 | checksum = "1e1c54951450cbd39f3dbcf1005ac413b49487dabf18a720ad2383eccfeffb92" 552 | dependencies = [ 553 | "memoffset", 554 | "rustc_version 0.3.3", 555 | ] 556 | 557 | [[package]] 558 | name = "filetime" 559 | version = "0.2.20" 560 | source = "registry+https://github.com/rust-lang/crates.io-index" 561 | checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" 562 | dependencies = [ 563 | "cfg-if", 564 | "libc", 565 | "redox_syscall", 566 | "windows-sys 0.45.0", 567 | ] 568 | 569 | [[package]] 570 | name = "flate2" 571 | version = "1.0.25" 572 | source = "registry+https://github.com/rust-lang/crates.io-index" 573 | checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" 574 | dependencies = [ 575 | "crc32fast", 576 | "miniz_oxide", 577 | ] 578 | 579 | [[package]] 580 | name = "fnv" 581 | version = "1.0.7" 582 | source = "registry+https://github.com/rust-lang/crates.io-index" 583 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 584 | 585 | [[package]] 586 | name = "foreign-types" 587 | version = "0.3.2" 588 | source = "registry+https://github.com/rust-lang/crates.io-index" 589 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 590 | dependencies = [ 591 | "foreign-types-shared", 592 | ] 593 | 594 | [[package]] 595 | name = "foreign-types-shared" 596 | version = "0.1.1" 597 | source = "registry+https://github.com/rust-lang/crates.io-index" 598 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 599 | 600 | [[package]] 601 | name = "form_urlencoded" 602 | version = "1.1.0" 603 | source = "registry+https://github.com/rust-lang/crates.io-index" 604 | checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" 605 | dependencies = [ 606 | "percent-encoding", 607 | ] 608 | 609 | [[package]] 610 | name = "futf" 611 | version = "0.1.5" 612 | source = "registry+https://github.com/rust-lang/crates.io-index" 613 | checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" 614 | dependencies = [ 615 | "mac", 616 | "new_debug_unreachable", 617 | ] 618 | 619 | [[package]] 620 | name = "futures-channel" 621 | version = "0.3.26" 622 | source = "registry+https://github.com/rust-lang/crates.io-index" 623 | checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" 624 | dependencies = [ 625 | "futures-core", 626 | ] 627 | 628 | [[package]] 629 | name = "futures-core" 630 | version = "0.3.26" 631 | source = "registry+https://github.com/rust-lang/crates.io-index" 632 | checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" 633 | 634 | [[package]] 635 | name = "futures-executor" 636 | version = "0.3.26" 637 | source = "registry+https://github.com/rust-lang/crates.io-index" 638 | checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" 639 | dependencies = [ 640 | "futures-core", 641 | "futures-task", 642 | "futures-util", 643 | ] 644 | 645 | [[package]] 646 | name = "futures-io" 647 | version = "0.3.26" 648 | source = "registry+https://github.com/rust-lang/crates.io-index" 649 | checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" 650 | 651 | [[package]] 652 | name = "futures-macro" 653 | version = "0.3.26" 654 | source = "registry+https://github.com/rust-lang/crates.io-index" 655 | checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" 656 | dependencies = [ 657 | "proc-macro2", 658 | "quote", 659 | "syn", 660 | ] 661 | 662 | [[package]] 663 | name = "futures-task" 664 | version = "0.3.26" 665 | source = "registry+https://github.com/rust-lang/crates.io-index" 666 | checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" 667 | 668 | [[package]] 669 | name = "futures-util" 670 | version = "0.3.26" 671 | source = "registry+https://github.com/rust-lang/crates.io-index" 672 | checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" 673 | dependencies = [ 674 | "futures-core", 675 | "futures-macro", 676 | "futures-task", 677 | "pin-project-lite", 678 | "pin-utils", 679 | "slab", 680 | ] 681 | 682 | [[package]] 683 | name = "fxhash" 684 | version = "0.2.1" 685 | source = "registry+https://github.com/rust-lang/crates.io-index" 686 | checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" 687 | dependencies = [ 688 | "byteorder", 689 | ] 690 | 691 | [[package]] 692 | name = "gdk" 693 | version = "0.15.4" 694 | source = "registry+https://github.com/rust-lang/crates.io-index" 695 | checksum = "a6e05c1f572ab0e1f15be94217f0dc29088c248b14f792a5ff0af0d84bcda9e8" 696 | dependencies = [ 697 | "bitflags", 698 | "cairo-rs", 699 | "gdk-pixbuf", 700 | "gdk-sys", 701 | "gio", 702 | "glib", 703 | "libc", 704 | "pango", 705 | ] 706 | 707 | [[package]] 708 | name = "gdk-pixbuf" 709 | version = "0.15.11" 710 | source = "registry+https://github.com/rust-lang/crates.io-index" 711 | checksum = "ad38dd9cc8b099cceecdf41375bb6d481b1b5a7cd5cd603e10a69a9383f8619a" 712 | dependencies = [ 713 | "bitflags", 714 | "gdk-pixbuf-sys", 715 | "gio", 716 | "glib", 717 | "libc", 718 | ] 719 | 720 | [[package]] 721 | name = "gdk-pixbuf-sys" 722 | version = "0.15.10" 723 | source = "registry+https://github.com/rust-lang/crates.io-index" 724 | checksum = "140b2f5378256527150350a8346dbdb08fadc13453a7a2d73aecd5fab3c402a7" 725 | dependencies = [ 726 | "gio-sys", 727 | "glib-sys", 728 | "gobject-sys", 729 | "libc", 730 | "system-deps 6.0.3", 731 | ] 732 | 733 | [[package]] 734 | name = "gdk-sys" 735 | version = "0.15.1" 736 | source = "registry+https://github.com/rust-lang/crates.io-index" 737 | checksum = "32e7a08c1e8f06f4177fb7e51a777b8c1689f743a7bc11ea91d44d2226073a88" 738 | dependencies = [ 739 | "cairo-sys-rs", 740 | "gdk-pixbuf-sys", 741 | "gio-sys", 742 | "glib-sys", 743 | "gobject-sys", 744 | "libc", 745 | "pango-sys", 746 | "pkg-config", 747 | "system-deps 6.0.3", 748 | ] 749 | 750 | [[package]] 751 | name = "gdkx11-sys" 752 | version = "0.15.1" 753 | source = "registry+https://github.com/rust-lang/crates.io-index" 754 | checksum = "b4b7f8c7a84b407aa9b143877e267e848ff34106578b64d1e0a24bf550716178" 755 | dependencies = [ 756 | "gdk-sys", 757 | "glib-sys", 758 | "libc", 759 | "system-deps 6.0.3", 760 | "x11", 761 | ] 762 | 763 | [[package]] 764 | name = "generator" 765 | version = "0.7.2" 766 | source = "registry+https://github.com/rust-lang/crates.io-index" 767 | checksum = "d266041a359dfa931b370ef684cceb84b166beb14f7f0421f4a6a3d0c446d12e" 768 | dependencies = [ 769 | "cc", 770 | "libc", 771 | "log", 772 | "rustversion", 773 | "windows 0.39.0", 774 | ] 775 | 776 | [[package]] 777 | name = "generic-array" 778 | version = "0.14.6" 779 | source = "registry+https://github.com/rust-lang/crates.io-index" 780 | checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" 781 | dependencies = [ 782 | "typenum", 783 | "version_check", 784 | ] 785 | 786 | [[package]] 787 | name = "getrandom" 788 | version = "0.1.16" 789 | source = "registry+https://github.com/rust-lang/crates.io-index" 790 | checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" 791 | dependencies = [ 792 | "cfg-if", 793 | "libc", 794 | "wasi 0.9.0+wasi-snapshot-preview1", 795 | ] 796 | 797 | [[package]] 798 | name = "getrandom" 799 | version = "0.2.8" 800 | source = "registry+https://github.com/rust-lang/crates.io-index" 801 | checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" 802 | dependencies = [ 803 | "cfg-if", 804 | "libc", 805 | "wasi 0.11.0+wasi-snapshot-preview1", 806 | ] 807 | 808 | [[package]] 809 | name = "gio" 810 | version = "0.15.12" 811 | source = "registry+https://github.com/rust-lang/crates.io-index" 812 | checksum = "68fdbc90312d462781a395f7a16d96a2b379bb6ef8cd6310a2df272771c4283b" 813 | dependencies = [ 814 | "bitflags", 815 | "futures-channel", 816 | "futures-core", 817 | "futures-io", 818 | "gio-sys", 819 | "glib", 820 | "libc", 821 | "once_cell", 822 | "thiserror", 823 | ] 824 | 825 | [[package]] 826 | name = "gio-sys" 827 | version = "0.15.10" 828 | source = "registry+https://github.com/rust-lang/crates.io-index" 829 | checksum = "32157a475271e2c4a023382e9cab31c4584ee30a97da41d3c4e9fdd605abcf8d" 830 | dependencies = [ 831 | "glib-sys", 832 | "gobject-sys", 833 | "libc", 834 | "system-deps 6.0.3", 835 | "winapi", 836 | ] 837 | 838 | [[package]] 839 | name = "glib" 840 | version = "0.15.12" 841 | source = "registry+https://github.com/rust-lang/crates.io-index" 842 | checksum = "edb0306fbad0ab5428b0ca674a23893db909a98582969c9b537be4ced78c505d" 843 | dependencies = [ 844 | "bitflags", 845 | "futures-channel", 846 | "futures-core", 847 | "futures-executor", 848 | "futures-task", 849 | "glib-macros", 850 | "glib-sys", 851 | "gobject-sys", 852 | "libc", 853 | "once_cell", 854 | "smallvec", 855 | "thiserror", 856 | ] 857 | 858 | [[package]] 859 | name = "glib-macros" 860 | version = "0.15.11" 861 | source = "registry+https://github.com/rust-lang/crates.io-index" 862 | checksum = "25a68131a662b04931e71891fb14aaf65ee4b44d08e8abc10f49e77418c86c64" 863 | dependencies = [ 864 | "anyhow", 865 | "heck 0.4.1", 866 | "proc-macro-crate", 867 | "proc-macro-error", 868 | "proc-macro2", 869 | "quote", 870 | "syn", 871 | ] 872 | 873 | [[package]] 874 | name = "glib-sys" 875 | version = "0.15.10" 876 | source = "registry+https://github.com/rust-lang/crates.io-index" 877 | checksum = "ef4b192f8e65e9cf76cbf4ea71fa8e3be4a0e18ffe3d68b8da6836974cc5bad4" 878 | dependencies = [ 879 | "libc", 880 | "system-deps 6.0.3", 881 | ] 882 | 883 | [[package]] 884 | name = "glob" 885 | version = "0.3.1" 886 | source = "registry+https://github.com/rust-lang/crates.io-index" 887 | checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" 888 | 889 | [[package]] 890 | name = "globset" 891 | version = "0.4.10" 892 | source = "registry+https://github.com/rust-lang/crates.io-index" 893 | checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" 894 | dependencies = [ 895 | "aho-corasick", 896 | "bstr", 897 | "fnv", 898 | "log", 899 | "regex", 900 | ] 901 | 902 | [[package]] 903 | name = "gobject-sys" 904 | version = "0.15.10" 905 | source = "registry+https://github.com/rust-lang/crates.io-index" 906 | checksum = "0d57ce44246becd17153bd035ab4d32cfee096a657fc01f2231c9278378d1e0a" 907 | dependencies = [ 908 | "glib-sys", 909 | "libc", 910 | "system-deps 6.0.3", 911 | ] 912 | 913 | [[package]] 914 | name = "gtk" 915 | version = "0.15.5" 916 | source = "registry+https://github.com/rust-lang/crates.io-index" 917 | checksum = "92e3004a2d5d6d8b5057d2b57b3712c9529b62e82c77f25c1fecde1fd5c23bd0" 918 | dependencies = [ 919 | "atk", 920 | "bitflags", 921 | "cairo-rs", 922 | "field-offset", 923 | "futures-channel", 924 | "gdk", 925 | "gdk-pixbuf", 926 | "gio", 927 | "glib", 928 | "gtk-sys", 929 | "gtk3-macros", 930 | "libc", 931 | "once_cell", 932 | "pango", 933 | "pkg-config", 934 | ] 935 | 936 | [[package]] 937 | name = "gtk-sys" 938 | version = "0.15.3" 939 | source = "registry+https://github.com/rust-lang/crates.io-index" 940 | checksum = "d5bc2f0587cba247f60246a0ca11fe25fb733eabc3de12d1965fc07efab87c84" 941 | dependencies = [ 942 | "atk-sys", 943 | "cairo-sys-rs", 944 | "gdk-pixbuf-sys", 945 | "gdk-sys", 946 | "gio-sys", 947 | "glib-sys", 948 | "gobject-sys", 949 | "libc", 950 | "pango-sys", 951 | "system-deps 6.0.3", 952 | ] 953 | 954 | [[package]] 955 | name = "gtk3-macros" 956 | version = "0.15.4" 957 | source = "registry+https://github.com/rust-lang/crates.io-index" 958 | checksum = "24f518afe90c23fba585b2d7697856f9e6a7bbc62f65588035e66f6afb01a2e9" 959 | dependencies = [ 960 | "anyhow", 961 | "proc-macro-crate", 962 | "proc-macro-error", 963 | "proc-macro2", 964 | "quote", 965 | "syn", 966 | ] 967 | 968 | [[package]] 969 | name = "hashbrown" 970 | version = "0.12.3" 971 | source = "registry+https://github.com/rust-lang/crates.io-index" 972 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 973 | 974 | [[package]] 975 | name = "heck" 976 | version = "0.3.3" 977 | source = "registry+https://github.com/rust-lang/crates.io-index" 978 | checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" 979 | dependencies = [ 980 | "unicode-segmentation", 981 | ] 982 | 983 | [[package]] 984 | name = "heck" 985 | version = "0.4.1" 986 | source = "registry+https://github.com/rust-lang/crates.io-index" 987 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 988 | 989 | [[package]] 990 | name = "hermit-abi" 991 | version = "0.2.6" 992 | source = "registry+https://github.com/rust-lang/crates.io-index" 993 | checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" 994 | dependencies = [ 995 | "libc", 996 | ] 997 | 998 | [[package]] 999 | name = "html5ever" 1000 | version = "0.25.2" 1001 | source = "registry+https://github.com/rust-lang/crates.io-index" 1002 | checksum = "e5c13fb08e5d4dfc151ee5e88bae63f7773d61852f3bdc73c9f4b9e1bde03148" 1003 | dependencies = [ 1004 | "log", 1005 | "mac", 1006 | "markup5ever", 1007 | "proc-macro2", 1008 | "quote", 1009 | "syn", 1010 | ] 1011 | 1012 | [[package]] 1013 | name = "http" 1014 | version = "0.2.8" 1015 | source = "registry+https://github.com/rust-lang/crates.io-index" 1016 | checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" 1017 | dependencies = [ 1018 | "bytes", 1019 | "fnv", 1020 | "itoa 1.0.5", 1021 | ] 1022 | 1023 | [[package]] 1024 | name = "http-range" 1025 | version = "0.1.5" 1026 | source = "registry+https://github.com/rust-lang/crates.io-index" 1027 | checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573" 1028 | 1029 | [[package]] 1030 | name = "ico" 1031 | version = "0.2.0" 1032 | source = "registry+https://github.com/rust-lang/crates.io-index" 1033 | checksum = "031530fe562d8c8d71c0635013d6d155bbfe8ba0aa4b4d2d24ce8af6b71047bd" 1034 | dependencies = [ 1035 | "byteorder", 1036 | "png", 1037 | ] 1038 | 1039 | [[package]] 1040 | name = "ident_case" 1041 | version = "1.0.1" 1042 | source = "registry+https://github.com/rust-lang/crates.io-index" 1043 | checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" 1044 | 1045 | [[package]] 1046 | name = "idna" 1047 | version = "0.3.0" 1048 | source = "registry+https://github.com/rust-lang/crates.io-index" 1049 | checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" 1050 | dependencies = [ 1051 | "unicode-bidi", 1052 | "unicode-normalization", 1053 | ] 1054 | 1055 | [[package]] 1056 | name = "ignore" 1057 | version = "0.4.18" 1058 | source = "registry+https://github.com/rust-lang/crates.io-index" 1059 | checksum = "713f1b139373f96a2e0ce3ac931cd01ee973c3c5dd7c40c0c2efe96ad2b6751d" 1060 | dependencies = [ 1061 | "crossbeam-utils", 1062 | "globset", 1063 | "lazy_static", 1064 | "log", 1065 | "memchr", 1066 | "regex", 1067 | "same-file", 1068 | "thread_local", 1069 | "walkdir", 1070 | "winapi-util", 1071 | ] 1072 | 1073 | [[package]] 1074 | name = "image" 1075 | version = "0.24.5" 1076 | source = "registry+https://github.com/rust-lang/crates.io-index" 1077 | checksum = "69b7ea949b537b0fd0af141fff8c77690f2ce96f4f41f042ccb6c69c6c965945" 1078 | dependencies = [ 1079 | "bytemuck", 1080 | "byteorder", 1081 | "color_quant", 1082 | "num-rational", 1083 | "num-traits", 1084 | ] 1085 | 1086 | [[package]] 1087 | name = "indexmap" 1088 | version = "1.9.2" 1089 | source = "registry+https://github.com/rust-lang/crates.io-index" 1090 | checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" 1091 | dependencies = [ 1092 | "autocfg", 1093 | "hashbrown", 1094 | ] 1095 | 1096 | [[package]] 1097 | name = "infer" 1098 | version = "0.7.0" 1099 | source = "registry+https://github.com/rust-lang/crates.io-index" 1100 | checksum = "20b2b533137b9cad970793453d4f921c2e91312a6d88b1085c07bc15fc51bb3b" 1101 | dependencies = [ 1102 | "cfb", 1103 | ] 1104 | 1105 | [[package]] 1106 | name = "instant" 1107 | version = "0.1.12" 1108 | source = "registry+https://github.com/rust-lang/crates.io-index" 1109 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" 1110 | dependencies = [ 1111 | "cfg-if", 1112 | ] 1113 | 1114 | [[package]] 1115 | name = "itoa" 1116 | version = "0.4.8" 1117 | source = "registry+https://github.com/rust-lang/crates.io-index" 1118 | checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" 1119 | 1120 | [[package]] 1121 | name = "itoa" 1122 | version = "1.0.5" 1123 | source = "registry+https://github.com/rust-lang/crates.io-index" 1124 | checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" 1125 | 1126 | [[package]] 1127 | name = "javascriptcore-rs" 1128 | version = "0.16.0" 1129 | source = "registry+https://github.com/rust-lang/crates.io-index" 1130 | checksum = "bf053e7843f2812ff03ef5afe34bb9c06ffee120385caad4f6b9967fcd37d41c" 1131 | dependencies = [ 1132 | "bitflags", 1133 | "glib", 1134 | "javascriptcore-rs-sys", 1135 | ] 1136 | 1137 | [[package]] 1138 | name = "javascriptcore-rs-sys" 1139 | version = "0.4.0" 1140 | source = "registry+https://github.com/rust-lang/crates.io-index" 1141 | checksum = "905fbb87419c5cde6e3269537e4ea7d46431f3008c5d057e915ef3f115e7793c" 1142 | dependencies = [ 1143 | "glib-sys", 1144 | "gobject-sys", 1145 | "libc", 1146 | "system-deps 5.0.0", 1147 | ] 1148 | 1149 | [[package]] 1150 | name = "jni" 1151 | version = "0.20.0" 1152 | source = "registry+https://github.com/rust-lang/crates.io-index" 1153 | checksum = "039022cdf4d7b1cf548d31f60ae783138e5fd42013f6271049d7df7afadef96c" 1154 | dependencies = [ 1155 | "cesu8", 1156 | "combine", 1157 | "jni-sys", 1158 | "log", 1159 | "thiserror", 1160 | "walkdir", 1161 | ] 1162 | 1163 | [[package]] 1164 | name = "jni-sys" 1165 | version = "0.3.0" 1166 | source = "registry+https://github.com/rust-lang/crates.io-index" 1167 | checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" 1168 | 1169 | [[package]] 1170 | name = "js-sys" 1171 | version = "0.3.61" 1172 | source = "registry+https://github.com/rust-lang/crates.io-index" 1173 | checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" 1174 | dependencies = [ 1175 | "wasm-bindgen", 1176 | ] 1177 | 1178 | [[package]] 1179 | name = "json-patch" 1180 | version = "0.2.7" 1181 | source = "registry+https://github.com/rust-lang/crates.io-index" 1182 | checksum = "eb3fa5a61630976fc4c353c70297f2e93f1930e3ccee574d59d618ccbd5154ce" 1183 | dependencies = [ 1184 | "serde", 1185 | "serde_json", 1186 | "treediff", 1187 | ] 1188 | 1189 | [[package]] 1190 | name = "kuchiki" 1191 | version = "0.8.1" 1192 | source = "registry+https://github.com/rust-lang/crates.io-index" 1193 | checksum = "1ea8e9c6e031377cff82ee3001dc8026cdf431ed4e2e6b51f98ab8c73484a358" 1194 | dependencies = [ 1195 | "cssparser", 1196 | "html5ever", 1197 | "matches", 1198 | "selectors", 1199 | ] 1200 | 1201 | [[package]] 1202 | name = "lazy_static" 1203 | version = "1.4.0" 1204 | source = "registry+https://github.com/rust-lang/crates.io-index" 1205 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 1206 | 1207 | [[package]] 1208 | name = "libc" 1209 | version = "0.2.139" 1210 | source = "registry+https://github.com/rust-lang/crates.io-index" 1211 | checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" 1212 | 1213 | [[package]] 1214 | name = "line-wrap" 1215 | version = "0.1.1" 1216 | source = "registry+https://github.com/rust-lang/crates.io-index" 1217 | checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9" 1218 | dependencies = [ 1219 | "safemem", 1220 | ] 1221 | 1222 | [[package]] 1223 | name = "lock_api" 1224 | version = "0.4.9" 1225 | source = "registry+https://github.com/rust-lang/crates.io-index" 1226 | checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" 1227 | dependencies = [ 1228 | "autocfg", 1229 | "scopeguard", 1230 | ] 1231 | 1232 | [[package]] 1233 | name = "log" 1234 | version = "0.4.17" 1235 | source = "registry+https://github.com/rust-lang/crates.io-index" 1236 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 1237 | dependencies = [ 1238 | "cfg-if", 1239 | ] 1240 | 1241 | [[package]] 1242 | name = "loom" 1243 | version = "0.5.6" 1244 | source = "registry+https://github.com/rust-lang/crates.io-index" 1245 | checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" 1246 | dependencies = [ 1247 | "cfg-if", 1248 | "generator", 1249 | "scoped-tls", 1250 | "serde", 1251 | "serde_json", 1252 | "tracing", 1253 | "tracing-subscriber", 1254 | ] 1255 | 1256 | [[package]] 1257 | name = "mac" 1258 | version = "0.1.1" 1259 | source = "registry+https://github.com/rust-lang/crates.io-index" 1260 | checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" 1261 | 1262 | [[package]] 1263 | name = "malloc_buf" 1264 | version = "0.0.6" 1265 | source = "registry+https://github.com/rust-lang/crates.io-index" 1266 | checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" 1267 | dependencies = [ 1268 | "libc", 1269 | ] 1270 | 1271 | [[package]] 1272 | name = "markup5ever" 1273 | version = "0.10.1" 1274 | source = "registry+https://github.com/rust-lang/crates.io-index" 1275 | checksum = "a24f40fb03852d1cdd84330cddcaf98e9ec08a7b7768e952fad3b4cf048ec8fd" 1276 | dependencies = [ 1277 | "log", 1278 | "phf 0.8.0", 1279 | "phf_codegen", 1280 | "string_cache", 1281 | "string_cache_codegen", 1282 | "tendril", 1283 | ] 1284 | 1285 | [[package]] 1286 | name = "matchers" 1287 | version = "0.1.0" 1288 | source = "registry+https://github.com/rust-lang/crates.io-index" 1289 | checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" 1290 | dependencies = [ 1291 | "regex-automata", 1292 | ] 1293 | 1294 | [[package]] 1295 | name = "matches" 1296 | version = "0.1.10" 1297 | source = "registry+https://github.com/rust-lang/crates.io-index" 1298 | checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" 1299 | 1300 | [[package]] 1301 | name = "memchr" 1302 | version = "2.5.0" 1303 | source = "registry+https://github.com/rust-lang/crates.io-index" 1304 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 1305 | 1306 | [[package]] 1307 | name = "memoffset" 1308 | version = "0.6.5" 1309 | source = "registry+https://github.com/rust-lang/crates.io-index" 1310 | checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" 1311 | dependencies = [ 1312 | "autocfg", 1313 | ] 1314 | 1315 | [[package]] 1316 | name = "miniz_oxide" 1317 | version = "0.6.2" 1318 | source = "registry+https://github.com/rust-lang/crates.io-index" 1319 | checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" 1320 | dependencies = [ 1321 | "adler", 1322 | ] 1323 | 1324 | [[package]] 1325 | name = "ndk" 1326 | version = "0.6.0" 1327 | source = "registry+https://github.com/rust-lang/crates.io-index" 1328 | checksum = "2032c77e030ddee34a6787a64166008da93f6a352b629261d0fee232b8742dd4" 1329 | dependencies = [ 1330 | "bitflags", 1331 | "jni-sys", 1332 | "ndk-sys", 1333 | "num_enum", 1334 | "thiserror", 1335 | ] 1336 | 1337 | [[package]] 1338 | name = "ndk-context" 1339 | version = "0.1.1" 1340 | source = "registry+https://github.com/rust-lang/crates.io-index" 1341 | checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" 1342 | 1343 | [[package]] 1344 | name = "ndk-sys" 1345 | version = "0.3.0" 1346 | source = "registry+https://github.com/rust-lang/crates.io-index" 1347 | checksum = "6e5a6ae77c8ee183dcbbba6150e2e6b9f3f4196a7666c02a715a95692ec1fa97" 1348 | dependencies = [ 1349 | "jni-sys", 1350 | ] 1351 | 1352 | [[package]] 1353 | name = "new_debug_unreachable" 1354 | version = "1.0.4" 1355 | source = "registry+https://github.com/rust-lang/crates.io-index" 1356 | checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" 1357 | 1358 | [[package]] 1359 | name = "nodrop" 1360 | version = "0.1.14" 1361 | source = "registry+https://github.com/rust-lang/crates.io-index" 1362 | checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" 1363 | 1364 | [[package]] 1365 | name = "nom8" 1366 | version = "0.2.0" 1367 | source = "registry+https://github.com/rust-lang/crates.io-index" 1368 | checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" 1369 | dependencies = [ 1370 | "memchr", 1371 | ] 1372 | 1373 | [[package]] 1374 | name = "nu-ansi-term" 1375 | version = "0.46.0" 1376 | source = "registry+https://github.com/rust-lang/crates.io-index" 1377 | checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" 1378 | dependencies = [ 1379 | "overload", 1380 | "winapi", 1381 | ] 1382 | 1383 | [[package]] 1384 | name = "num-integer" 1385 | version = "0.1.45" 1386 | source = "registry+https://github.com/rust-lang/crates.io-index" 1387 | checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" 1388 | dependencies = [ 1389 | "autocfg", 1390 | "num-traits", 1391 | ] 1392 | 1393 | [[package]] 1394 | name = "num-rational" 1395 | version = "0.4.1" 1396 | source = "registry+https://github.com/rust-lang/crates.io-index" 1397 | checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" 1398 | dependencies = [ 1399 | "autocfg", 1400 | "num-integer", 1401 | "num-traits", 1402 | ] 1403 | 1404 | [[package]] 1405 | name = "num-traits" 1406 | version = "0.2.15" 1407 | source = "registry+https://github.com/rust-lang/crates.io-index" 1408 | checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" 1409 | dependencies = [ 1410 | "autocfg", 1411 | ] 1412 | 1413 | [[package]] 1414 | name = "num_cpus" 1415 | version = "1.15.0" 1416 | source = "registry+https://github.com/rust-lang/crates.io-index" 1417 | checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" 1418 | dependencies = [ 1419 | "hermit-abi", 1420 | "libc", 1421 | ] 1422 | 1423 | [[package]] 1424 | name = "num_enum" 1425 | version = "0.5.9" 1426 | source = "registry+https://github.com/rust-lang/crates.io-index" 1427 | checksum = "8d829733185c1ca374f17e52b762f24f535ec625d2cc1f070e34c8a9068f341b" 1428 | dependencies = [ 1429 | "num_enum_derive", 1430 | ] 1431 | 1432 | [[package]] 1433 | name = "num_enum_derive" 1434 | version = "0.5.9" 1435 | source = "registry+https://github.com/rust-lang/crates.io-index" 1436 | checksum = "2be1598bf1c313dcdd12092e3f1920f463462525a21b7b4e11b4168353d0123e" 1437 | dependencies = [ 1438 | "proc-macro-crate", 1439 | "proc-macro2", 1440 | "quote", 1441 | "syn", 1442 | ] 1443 | 1444 | [[package]] 1445 | name = "objc" 1446 | version = "0.2.7" 1447 | source = "registry+https://github.com/rust-lang/crates.io-index" 1448 | checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" 1449 | dependencies = [ 1450 | "malloc_buf", 1451 | "objc_exception", 1452 | ] 1453 | 1454 | [[package]] 1455 | name = "objc-foundation" 1456 | version = "0.1.1" 1457 | source = "registry+https://github.com/rust-lang/crates.io-index" 1458 | checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" 1459 | dependencies = [ 1460 | "block", 1461 | "objc", 1462 | "objc_id", 1463 | ] 1464 | 1465 | [[package]] 1466 | name = "objc_exception" 1467 | version = "0.1.2" 1468 | source = "registry+https://github.com/rust-lang/crates.io-index" 1469 | checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" 1470 | dependencies = [ 1471 | "cc", 1472 | ] 1473 | 1474 | [[package]] 1475 | name = "objc_id" 1476 | version = "0.1.1" 1477 | source = "registry+https://github.com/rust-lang/crates.io-index" 1478 | checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" 1479 | dependencies = [ 1480 | "objc", 1481 | ] 1482 | 1483 | [[package]] 1484 | name = "once_cell" 1485 | version = "1.17.0" 1486 | source = "registry+https://github.com/rust-lang/crates.io-index" 1487 | checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" 1488 | 1489 | [[package]] 1490 | name = "overload" 1491 | version = "0.1.1" 1492 | source = "registry+https://github.com/rust-lang/crates.io-index" 1493 | checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" 1494 | 1495 | [[package]] 1496 | name = "pango" 1497 | version = "0.15.10" 1498 | source = "registry+https://github.com/rust-lang/crates.io-index" 1499 | checksum = "22e4045548659aee5313bde6c582b0d83a627b7904dd20dc2d9ef0895d414e4f" 1500 | dependencies = [ 1501 | "bitflags", 1502 | "glib", 1503 | "libc", 1504 | "once_cell", 1505 | "pango-sys", 1506 | ] 1507 | 1508 | [[package]] 1509 | name = "pango-sys" 1510 | version = "0.15.10" 1511 | source = "registry+https://github.com/rust-lang/crates.io-index" 1512 | checksum = "d2a00081cde4661982ed91d80ef437c20eacaf6aa1a5962c0279ae194662c3aa" 1513 | dependencies = [ 1514 | "glib-sys", 1515 | "gobject-sys", 1516 | "libc", 1517 | "system-deps 6.0.3", 1518 | ] 1519 | 1520 | [[package]] 1521 | name = "parking_lot" 1522 | version = "0.12.1" 1523 | source = "registry+https://github.com/rust-lang/crates.io-index" 1524 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 1525 | dependencies = [ 1526 | "lock_api", 1527 | "parking_lot_core", 1528 | ] 1529 | 1530 | [[package]] 1531 | name = "parking_lot_core" 1532 | version = "0.9.7" 1533 | source = "registry+https://github.com/rust-lang/crates.io-index" 1534 | checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" 1535 | dependencies = [ 1536 | "cfg-if", 1537 | "libc", 1538 | "redox_syscall", 1539 | "smallvec", 1540 | "windows-sys 0.45.0", 1541 | ] 1542 | 1543 | [[package]] 1544 | name = "paste" 1545 | version = "1.0.11" 1546 | source = "registry+https://github.com/rust-lang/crates.io-index" 1547 | checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" 1548 | 1549 | [[package]] 1550 | name = "percent-encoding" 1551 | version = "2.2.0" 1552 | source = "registry+https://github.com/rust-lang/crates.io-index" 1553 | checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" 1554 | 1555 | [[package]] 1556 | name = "pest" 1557 | version = "2.5.5" 1558 | source = "registry+https://github.com/rust-lang/crates.io-index" 1559 | checksum = "028accff104c4e513bad663bbcd2ad7cfd5304144404c31ed0a77ac103d00660" 1560 | dependencies = [ 1561 | "thiserror", 1562 | "ucd-trie", 1563 | ] 1564 | 1565 | [[package]] 1566 | name = "phf" 1567 | version = "0.8.0" 1568 | source = "registry+https://github.com/rust-lang/crates.io-index" 1569 | checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" 1570 | dependencies = [ 1571 | "phf_macros 0.8.0", 1572 | "phf_shared 0.8.0", 1573 | "proc-macro-hack", 1574 | ] 1575 | 1576 | [[package]] 1577 | name = "phf" 1578 | version = "0.10.1" 1579 | source = "registry+https://github.com/rust-lang/crates.io-index" 1580 | checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" 1581 | dependencies = [ 1582 | "phf_macros 0.10.0", 1583 | "phf_shared 0.10.0", 1584 | "proc-macro-hack", 1585 | ] 1586 | 1587 | [[package]] 1588 | name = "phf_codegen" 1589 | version = "0.8.0" 1590 | source = "registry+https://github.com/rust-lang/crates.io-index" 1591 | checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" 1592 | dependencies = [ 1593 | "phf_generator 0.8.0", 1594 | "phf_shared 0.8.0", 1595 | ] 1596 | 1597 | [[package]] 1598 | name = "phf_generator" 1599 | version = "0.8.0" 1600 | source = "registry+https://github.com/rust-lang/crates.io-index" 1601 | checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" 1602 | dependencies = [ 1603 | "phf_shared 0.8.0", 1604 | "rand 0.7.3", 1605 | ] 1606 | 1607 | [[package]] 1608 | name = "phf_generator" 1609 | version = "0.10.0" 1610 | source = "registry+https://github.com/rust-lang/crates.io-index" 1611 | checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" 1612 | dependencies = [ 1613 | "phf_shared 0.10.0", 1614 | "rand 0.8.5", 1615 | ] 1616 | 1617 | [[package]] 1618 | name = "phf_macros" 1619 | version = "0.8.0" 1620 | source = "registry+https://github.com/rust-lang/crates.io-index" 1621 | checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c" 1622 | dependencies = [ 1623 | "phf_generator 0.8.0", 1624 | "phf_shared 0.8.0", 1625 | "proc-macro-hack", 1626 | "proc-macro2", 1627 | "quote", 1628 | "syn", 1629 | ] 1630 | 1631 | [[package]] 1632 | name = "phf_macros" 1633 | version = "0.10.0" 1634 | source = "registry+https://github.com/rust-lang/crates.io-index" 1635 | checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" 1636 | dependencies = [ 1637 | "phf_generator 0.10.0", 1638 | "phf_shared 0.10.0", 1639 | "proc-macro-hack", 1640 | "proc-macro2", 1641 | "quote", 1642 | "syn", 1643 | ] 1644 | 1645 | [[package]] 1646 | name = "phf_shared" 1647 | version = "0.8.0" 1648 | source = "registry+https://github.com/rust-lang/crates.io-index" 1649 | checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" 1650 | dependencies = [ 1651 | "siphasher", 1652 | ] 1653 | 1654 | [[package]] 1655 | name = "phf_shared" 1656 | version = "0.10.0" 1657 | source = "registry+https://github.com/rust-lang/crates.io-index" 1658 | checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" 1659 | dependencies = [ 1660 | "siphasher", 1661 | ] 1662 | 1663 | [[package]] 1664 | name = "pin-project-lite" 1665 | version = "0.2.9" 1666 | source = "registry+https://github.com/rust-lang/crates.io-index" 1667 | checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" 1668 | 1669 | [[package]] 1670 | name = "pin-utils" 1671 | version = "0.1.0" 1672 | source = "registry+https://github.com/rust-lang/crates.io-index" 1673 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1674 | 1675 | [[package]] 1676 | name = "pkg-config" 1677 | version = "0.3.26" 1678 | source = "registry+https://github.com/rust-lang/crates.io-index" 1679 | checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" 1680 | 1681 | [[package]] 1682 | name = "plaintext-daw" 1683 | version = "0.0.0" 1684 | dependencies = [ 1685 | "serde", 1686 | "serde_json", 1687 | "serde_yaml", 1688 | "tauri", 1689 | "tauri-build", 1690 | ] 1691 | 1692 | [[package]] 1693 | name = "plist" 1694 | version = "1.4.0" 1695 | source = "registry+https://github.com/rust-lang/crates.io-index" 1696 | checksum = "5329b8f106a176ab0dce4aae5da86bfcb139bb74fb00882859e03745011f3635" 1697 | dependencies = [ 1698 | "base64", 1699 | "indexmap", 1700 | "line-wrap", 1701 | "quick-xml", 1702 | "serde", 1703 | "time", 1704 | ] 1705 | 1706 | [[package]] 1707 | name = "png" 1708 | version = "0.17.7" 1709 | source = "registry+https://github.com/rust-lang/crates.io-index" 1710 | checksum = "5d708eaf860a19b19ce538740d2b4bdeeb8337fa53f7738455e706623ad5c638" 1711 | dependencies = [ 1712 | "bitflags", 1713 | "crc32fast", 1714 | "flate2", 1715 | "miniz_oxide", 1716 | ] 1717 | 1718 | [[package]] 1719 | name = "ppv-lite86" 1720 | version = "0.2.17" 1721 | source = "registry+https://github.com/rust-lang/crates.io-index" 1722 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" 1723 | 1724 | [[package]] 1725 | name = "precomputed-hash" 1726 | version = "0.1.1" 1727 | source = "registry+https://github.com/rust-lang/crates.io-index" 1728 | checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" 1729 | 1730 | [[package]] 1731 | name = "proc-macro-crate" 1732 | version = "1.3.0" 1733 | source = "registry+https://github.com/rust-lang/crates.io-index" 1734 | checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34" 1735 | dependencies = [ 1736 | "once_cell", 1737 | "toml_edit", 1738 | ] 1739 | 1740 | [[package]] 1741 | name = "proc-macro-error" 1742 | version = "1.0.4" 1743 | source = "registry+https://github.com/rust-lang/crates.io-index" 1744 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 1745 | dependencies = [ 1746 | "proc-macro-error-attr", 1747 | "proc-macro2", 1748 | "quote", 1749 | "syn", 1750 | "version_check", 1751 | ] 1752 | 1753 | [[package]] 1754 | name = "proc-macro-error-attr" 1755 | version = "1.0.4" 1756 | source = "registry+https://github.com/rust-lang/crates.io-index" 1757 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 1758 | dependencies = [ 1759 | "proc-macro2", 1760 | "quote", 1761 | "version_check", 1762 | ] 1763 | 1764 | [[package]] 1765 | name = "proc-macro-hack" 1766 | version = "0.5.20+deprecated" 1767 | source = "registry+https://github.com/rust-lang/crates.io-index" 1768 | checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" 1769 | 1770 | [[package]] 1771 | name = "proc-macro2" 1772 | version = "1.0.51" 1773 | source = "registry+https://github.com/rust-lang/crates.io-index" 1774 | checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" 1775 | dependencies = [ 1776 | "unicode-ident", 1777 | ] 1778 | 1779 | [[package]] 1780 | name = "quick-xml" 1781 | version = "0.26.0" 1782 | source = "registry+https://github.com/rust-lang/crates.io-index" 1783 | checksum = "7f50b1c63b38611e7d4d7f68b82d3ad0cc71a2ad2e7f61fc10f1328d917c93cd" 1784 | dependencies = [ 1785 | "memchr", 1786 | ] 1787 | 1788 | [[package]] 1789 | name = "quote" 1790 | version = "1.0.23" 1791 | source = "registry+https://github.com/rust-lang/crates.io-index" 1792 | checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" 1793 | dependencies = [ 1794 | "proc-macro2", 1795 | ] 1796 | 1797 | [[package]] 1798 | name = "rand" 1799 | version = "0.7.3" 1800 | source = "registry+https://github.com/rust-lang/crates.io-index" 1801 | checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" 1802 | dependencies = [ 1803 | "getrandom 0.1.16", 1804 | "libc", 1805 | "rand_chacha 0.2.2", 1806 | "rand_core 0.5.1", 1807 | "rand_hc", 1808 | "rand_pcg", 1809 | ] 1810 | 1811 | [[package]] 1812 | name = "rand" 1813 | version = "0.8.5" 1814 | source = "registry+https://github.com/rust-lang/crates.io-index" 1815 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 1816 | dependencies = [ 1817 | "libc", 1818 | "rand_chacha 0.3.1", 1819 | "rand_core 0.6.4", 1820 | ] 1821 | 1822 | [[package]] 1823 | name = "rand_chacha" 1824 | version = "0.2.2" 1825 | source = "registry+https://github.com/rust-lang/crates.io-index" 1826 | checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" 1827 | dependencies = [ 1828 | "ppv-lite86", 1829 | "rand_core 0.5.1", 1830 | ] 1831 | 1832 | [[package]] 1833 | name = "rand_chacha" 1834 | version = "0.3.1" 1835 | source = "registry+https://github.com/rust-lang/crates.io-index" 1836 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 1837 | dependencies = [ 1838 | "ppv-lite86", 1839 | "rand_core 0.6.4", 1840 | ] 1841 | 1842 | [[package]] 1843 | name = "rand_core" 1844 | version = "0.5.1" 1845 | source = "registry+https://github.com/rust-lang/crates.io-index" 1846 | checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" 1847 | dependencies = [ 1848 | "getrandom 0.1.16", 1849 | ] 1850 | 1851 | [[package]] 1852 | name = "rand_core" 1853 | version = "0.6.4" 1854 | source = "registry+https://github.com/rust-lang/crates.io-index" 1855 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 1856 | dependencies = [ 1857 | "getrandom 0.2.8", 1858 | ] 1859 | 1860 | [[package]] 1861 | name = "rand_hc" 1862 | version = "0.2.0" 1863 | source = "registry+https://github.com/rust-lang/crates.io-index" 1864 | checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" 1865 | dependencies = [ 1866 | "rand_core 0.5.1", 1867 | ] 1868 | 1869 | [[package]] 1870 | name = "rand_pcg" 1871 | version = "0.2.1" 1872 | source = "registry+https://github.com/rust-lang/crates.io-index" 1873 | checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" 1874 | dependencies = [ 1875 | "rand_core 0.5.1", 1876 | ] 1877 | 1878 | [[package]] 1879 | name = "raw-window-handle" 1880 | version = "0.5.0" 1881 | source = "registry+https://github.com/rust-lang/crates.io-index" 1882 | checksum = "ed7e3d950b66e19e0c372f3fa3fbbcf85b1746b571f74e0c2af6042a5c93420a" 1883 | dependencies = [ 1884 | "cty", 1885 | ] 1886 | 1887 | [[package]] 1888 | name = "redox_syscall" 1889 | version = "0.2.16" 1890 | source = "registry+https://github.com/rust-lang/crates.io-index" 1891 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 1892 | dependencies = [ 1893 | "bitflags", 1894 | ] 1895 | 1896 | [[package]] 1897 | name = "redox_users" 1898 | version = "0.4.3" 1899 | source = "registry+https://github.com/rust-lang/crates.io-index" 1900 | checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" 1901 | dependencies = [ 1902 | "getrandom 0.2.8", 1903 | "redox_syscall", 1904 | "thiserror", 1905 | ] 1906 | 1907 | [[package]] 1908 | name = "regex" 1909 | version = "1.7.1" 1910 | source = "registry+https://github.com/rust-lang/crates.io-index" 1911 | checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" 1912 | dependencies = [ 1913 | "aho-corasick", 1914 | "memchr", 1915 | "regex-syntax", 1916 | ] 1917 | 1918 | [[package]] 1919 | name = "regex-automata" 1920 | version = "0.1.10" 1921 | source = "registry+https://github.com/rust-lang/crates.io-index" 1922 | checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" 1923 | dependencies = [ 1924 | "regex-syntax", 1925 | ] 1926 | 1927 | [[package]] 1928 | name = "regex-syntax" 1929 | version = "0.6.28" 1930 | source = "registry+https://github.com/rust-lang/crates.io-index" 1931 | checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" 1932 | 1933 | [[package]] 1934 | name = "remove_dir_all" 1935 | version = "0.5.3" 1936 | source = "registry+https://github.com/rust-lang/crates.io-index" 1937 | checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" 1938 | dependencies = [ 1939 | "winapi", 1940 | ] 1941 | 1942 | [[package]] 1943 | name = "rfd" 1944 | version = "0.10.0" 1945 | source = "registry+https://github.com/rust-lang/crates.io-index" 1946 | checksum = "0149778bd99b6959285b0933288206090c50e2327f47a9c463bfdbf45c8823ea" 1947 | dependencies = [ 1948 | "block", 1949 | "dispatch", 1950 | "glib-sys", 1951 | "gobject-sys", 1952 | "gtk-sys", 1953 | "js-sys", 1954 | "lazy_static", 1955 | "log", 1956 | "objc", 1957 | "objc-foundation", 1958 | "objc_id", 1959 | "raw-window-handle", 1960 | "wasm-bindgen", 1961 | "wasm-bindgen-futures", 1962 | "web-sys", 1963 | "windows 0.37.0", 1964 | ] 1965 | 1966 | [[package]] 1967 | name = "rustc_version" 1968 | version = "0.3.3" 1969 | source = "registry+https://github.com/rust-lang/crates.io-index" 1970 | checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" 1971 | dependencies = [ 1972 | "semver 0.11.0", 1973 | ] 1974 | 1975 | [[package]] 1976 | name = "rustc_version" 1977 | version = "0.4.0" 1978 | source = "registry+https://github.com/rust-lang/crates.io-index" 1979 | checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" 1980 | dependencies = [ 1981 | "semver 1.0.16", 1982 | ] 1983 | 1984 | [[package]] 1985 | name = "rustversion" 1986 | version = "1.0.11" 1987 | source = "registry+https://github.com/rust-lang/crates.io-index" 1988 | checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" 1989 | 1990 | [[package]] 1991 | name = "ryu" 1992 | version = "1.0.12" 1993 | source = "registry+https://github.com/rust-lang/crates.io-index" 1994 | checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" 1995 | 1996 | [[package]] 1997 | name = "safemem" 1998 | version = "0.3.3" 1999 | source = "registry+https://github.com/rust-lang/crates.io-index" 2000 | checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" 2001 | 2002 | [[package]] 2003 | name = "same-file" 2004 | version = "1.0.6" 2005 | source = "registry+https://github.com/rust-lang/crates.io-index" 2006 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 2007 | dependencies = [ 2008 | "winapi-util", 2009 | ] 2010 | 2011 | [[package]] 2012 | name = "scoped-tls" 2013 | version = "1.0.1" 2014 | source = "registry+https://github.com/rust-lang/crates.io-index" 2015 | checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" 2016 | 2017 | [[package]] 2018 | name = "scopeguard" 2019 | version = "1.1.0" 2020 | source = "registry+https://github.com/rust-lang/crates.io-index" 2021 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 2022 | 2023 | [[package]] 2024 | name = "selectors" 2025 | version = "0.22.0" 2026 | source = "registry+https://github.com/rust-lang/crates.io-index" 2027 | checksum = "df320f1889ac4ba6bc0cdc9c9af7af4bd64bb927bccdf32d81140dc1f9be12fe" 2028 | dependencies = [ 2029 | "bitflags", 2030 | "cssparser", 2031 | "derive_more", 2032 | "fxhash", 2033 | "log", 2034 | "matches", 2035 | "phf 0.8.0", 2036 | "phf_codegen", 2037 | "precomputed-hash", 2038 | "servo_arc", 2039 | "smallvec", 2040 | "thin-slice", 2041 | ] 2042 | 2043 | [[package]] 2044 | name = "semver" 2045 | version = "0.11.0" 2046 | source = "registry+https://github.com/rust-lang/crates.io-index" 2047 | checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" 2048 | dependencies = [ 2049 | "semver-parser", 2050 | ] 2051 | 2052 | [[package]] 2053 | name = "semver" 2054 | version = "1.0.16" 2055 | source = "registry+https://github.com/rust-lang/crates.io-index" 2056 | checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" 2057 | dependencies = [ 2058 | "serde", 2059 | ] 2060 | 2061 | [[package]] 2062 | name = "semver-parser" 2063 | version = "0.10.2" 2064 | source = "registry+https://github.com/rust-lang/crates.io-index" 2065 | checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" 2066 | dependencies = [ 2067 | "pest", 2068 | ] 2069 | 2070 | [[package]] 2071 | name = "serde" 2072 | version = "1.0.152" 2073 | source = "registry+https://github.com/rust-lang/crates.io-index" 2074 | checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" 2075 | dependencies = [ 2076 | "serde_derive", 2077 | ] 2078 | 2079 | [[package]] 2080 | name = "serde_derive" 2081 | version = "1.0.152" 2082 | source = "registry+https://github.com/rust-lang/crates.io-index" 2083 | checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" 2084 | dependencies = [ 2085 | "proc-macro2", 2086 | "quote", 2087 | "syn", 2088 | ] 2089 | 2090 | [[package]] 2091 | name = "serde_json" 2092 | version = "1.0.93" 2093 | source = "registry+https://github.com/rust-lang/crates.io-index" 2094 | checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" 2095 | dependencies = [ 2096 | "itoa 1.0.5", 2097 | "ryu", 2098 | "serde", 2099 | ] 2100 | 2101 | [[package]] 2102 | name = "serde_repr" 2103 | version = "0.1.10" 2104 | source = "registry+https://github.com/rust-lang/crates.io-index" 2105 | checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e" 2106 | dependencies = [ 2107 | "proc-macro2", 2108 | "quote", 2109 | "syn", 2110 | ] 2111 | 2112 | [[package]] 2113 | name = "serde_with" 2114 | version = "1.14.0" 2115 | source = "registry+https://github.com/rust-lang/crates.io-index" 2116 | checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" 2117 | dependencies = [ 2118 | "serde", 2119 | "serde_with_macros", 2120 | ] 2121 | 2122 | [[package]] 2123 | name = "serde_with_macros" 2124 | version = "1.5.2" 2125 | source = "registry+https://github.com/rust-lang/crates.io-index" 2126 | checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" 2127 | dependencies = [ 2128 | "darling", 2129 | "proc-macro2", 2130 | "quote", 2131 | "syn", 2132 | ] 2133 | 2134 | [[package]] 2135 | name = "serde_yaml" 2136 | version = "0.9.17" 2137 | source = "registry+https://github.com/rust-lang/crates.io-index" 2138 | checksum = "8fb06d4b6cdaef0e0c51fa881acb721bed3c924cfaa71d9c94a3b771dfdf6567" 2139 | dependencies = [ 2140 | "indexmap", 2141 | "itoa 1.0.5", 2142 | "ryu", 2143 | "serde", 2144 | "unsafe-libyaml", 2145 | ] 2146 | 2147 | [[package]] 2148 | name = "serialize-to-javascript" 2149 | version = "0.1.1" 2150 | source = "registry+https://github.com/rust-lang/crates.io-index" 2151 | checksum = "c9823f2d3b6a81d98228151fdeaf848206a7855a7a042bbf9bf870449a66cafb" 2152 | dependencies = [ 2153 | "serde", 2154 | "serde_json", 2155 | "serialize-to-javascript-impl", 2156 | ] 2157 | 2158 | [[package]] 2159 | name = "serialize-to-javascript-impl" 2160 | version = "0.1.1" 2161 | source = "registry+https://github.com/rust-lang/crates.io-index" 2162 | checksum = "74064874e9f6a15f04c1f3cb627902d0e6b410abbf36668afa873c61889f1763" 2163 | dependencies = [ 2164 | "proc-macro2", 2165 | "quote", 2166 | "syn", 2167 | ] 2168 | 2169 | [[package]] 2170 | name = "servo_arc" 2171 | version = "0.1.1" 2172 | source = "registry+https://github.com/rust-lang/crates.io-index" 2173 | checksum = "d98238b800e0d1576d8b6e3de32827c2d74bee68bb97748dcf5071fb53965432" 2174 | dependencies = [ 2175 | "nodrop", 2176 | "stable_deref_trait", 2177 | ] 2178 | 2179 | [[package]] 2180 | name = "sha2" 2181 | version = "0.10.6" 2182 | source = "registry+https://github.com/rust-lang/crates.io-index" 2183 | checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" 2184 | dependencies = [ 2185 | "cfg-if", 2186 | "cpufeatures", 2187 | "digest", 2188 | ] 2189 | 2190 | [[package]] 2191 | name = "sharded-slab" 2192 | version = "0.1.4" 2193 | source = "registry+https://github.com/rust-lang/crates.io-index" 2194 | checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" 2195 | dependencies = [ 2196 | "lazy_static", 2197 | ] 2198 | 2199 | [[package]] 2200 | name = "siphasher" 2201 | version = "0.3.10" 2202 | source = "registry+https://github.com/rust-lang/crates.io-index" 2203 | checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" 2204 | 2205 | [[package]] 2206 | name = "slab" 2207 | version = "0.4.7" 2208 | source = "registry+https://github.com/rust-lang/crates.io-index" 2209 | checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" 2210 | dependencies = [ 2211 | "autocfg", 2212 | ] 2213 | 2214 | [[package]] 2215 | name = "smallvec" 2216 | version = "1.10.0" 2217 | source = "registry+https://github.com/rust-lang/crates.io-index" 2218 | checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" 2219 | 2220 | [[package]] 2221 | name = "soup2" 2222 | version = "0.2.1" 2223 | source = "registry+https://github.com/rust-lang/crates.io-index" 2224 | checksum = "b2b4d76501d8ba387cf0fefbe055c3e0a59891d09f0f995ae4e4b16f6b60f3c0" 2225 | dependencies = [ 2226 | "bitflags", 2227 | "gio", 2228 | "glib", 2229 | "libc", 2230 | "once_cell", 2231 | "soup2-sys", 2232 | ] 2233 | 2234 | [[package]] 2235 | name = "soup2-sys" 2236 | version = "0.2.0" 2237 | source = "registry+https://github.com/rust-lang/crates.io-index" 2238 | checksum = "009ef427103fcb17f802871647a7fa6c60cbb654b4c4e4c0ac60a31c5f6dc9cf" 2239 | dependencies = [ 2240 | "bitflags", 2241 | "gio-sys", 2242 | "glib-sys", 2243 | "gobject-sys", 2244 | "libc", 2245 | "system-deps 5.0.0", 2246 | ] 2247 | 2248 | [[package]] 2249 | name = "stable_deref_trait" 2250 | version = "1.2.0" 2251 | source = "registry+https://github.com/rust-lang/crates.io-index" 2252 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 2253 | 2254 | [[package]] 2255 | name = "state" 2256 | version = "0.5.3" 2257 | source = "registry+https://github.com/rust-lang/crates.io-index" 2258 | checksum = "dbe866e1e51e8260c9eed836a042a5e7f6726bb2b411dffeaa712e19c388f23b" 2259 | dependencies = [ 2260 | "loom", 2261 | ] 2262 | 2263 | [[package]] 2264 | name = "string_cache" 2265 | version = "0.8.4" 2266 | source = "registry+https://github.com/rust-lang/crates.io-index" 2267 | checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08" 2268 | dependencies = [ 2269 | "new_debug_unreachable", 2270 | "once_cell", 2271 | "parking_lot", 2272 | "phf_shared 0.10.0", 2273 | "precomputed-hash", 2274 | "serde", 2275 | ] 2276 | 2277 | [[package]] 2278 | name = "string_cache_codegen" 2279 | version = "0.5.2" 2280 | source = "registry+https://github.com/rust-lang/crates.io-index" 2281 | checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" 2282 | dependencies = [ 2283 | "phf_generator 0.10.0", 2284 | "phf_shared 0.10.0", 2285 | "proc-macro2", 2286 | "quote", 2287 | ] 2288 | 2289 | [[package]] 2290 | name = "strsim" 2291 | version = "0.10.0" 2292 | source = "registry+https://github.com/rust-lang/crates.io-index" 2293 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 2294 | 2295 | [[package]] 2296 | name = "syn" 2297 | version = "1.0.107" 2298 | source = "registry+https://github.com/rust-lang/crates.io-index" 2299 | checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" 2300 | dependencies = [ 2301 | "proc-macro2", 2302 | "quote", 2303 | "unicode-ident", 2304 | ] 2305 | 2306 | [[package]] 2307 | name = "system-deps" 2308 | version = "5.0.0" 2309 | source = "registry+https://github.com/rust-lang/crates.io-index" 2310 | checksum = "18db855554db7bd0e73e06cf7ba3df39f97812cb11d3f75e71c39bf45171797e" 2311 | dependencies = [ 2312 | "cfg-expr 0.9.1", 2313 | "heck 0.3.3", 2314 | "pkg-config", 2315 | "toml", 2316 | "version-compare 0.0.11", 2317 | ] 2318 | 2319 | [[package]] 2320 | name = "system-deps" 2321 | version = "6.0.3" 2322 | source = "registry+https://github.com/rust-lang/crates.io-index" 2323 | checksum = "2955b1fe31e1fa2fbd1976b71cc69a606d7d4da16f6de3333d0c92d51419aeff" 2324 | dependencies = [ 2325 | "cfg-expr 0.11.0", 2326 | "heck 0.4.1", 2327 | "pkg-config", 2328 | "toml", 2329 | "version-compare 0.1.1", 2330 | ] 2331 | 2332 | [[package]] 2333 | name = "tao" 2334 | version = "0.15.8" 2335 | source = "registry+https://github.com/rust-lang/crates.io-index" 2336 | checksum = "ac8e6399427c8494f9849b58694754d7cc741293348a6836b6c8d2c5aa82d8e6" 2337 | dependencies = [ 2338 | "bitflags", 2339 | "cairo-rs", 2340 | "cc", 2341 | "cocoa", 2342 | "core-foundation", 2343 | "core-graphics", 2344 | "crossbeam-channel", 2345 | "dispatch", 2346 | "gdk", 2347 | "gdk-pixbuf", 2348 | "gdk-sys", 2349 | "gdkx11-sys", 2350 | "gio", 2351 | "glib", 2352 | "glib-sys", 2353 | "gtk", 2354 | "image", 2355 | "instant", 2356 | "jni", 2357 | "lazy_static", 2358 | "libc", 2359 | "log", 2360 | "ndk", 2361 | "ndk-context", 2362 | "ndk-sys", 2363 | "objc", 2364 | "once_cell", 2365 | "parking_lot", 2366 | "paste", 2367 | "png", 2368 | "raw-window-handle", 2369 | "scopeguard", 2370 | "serde", 2371 | "unicode-segmentation", 2372 | "uuid 1.3.0", 2373 | "windows 0.39.0", 2374 | "windows-implement", 2375 | "x11-dl", 2376 | ] 2377 | 2378 | [[package]] 2379 | name = "tar" 2380 | version = "0.4.38" 2381 | source = "registry+https://github.com/rust-lang/crates.io-index" 2382 | checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6" 2383 | dependencies = [ 2384 | "filetime", 2385 | "libc", 2386 | "xattr", 2387 | ] 2388 | 2389 | [[package]] 2390 | name = "tauri" 2391 | version = "1.2.4" 2392 | source = "registry+https://github.com/rust-lang/crates.io-index" 2393 | checksum = "fe7e0f1d535e7cbbbab43c82be4fc992b84f9156c16c160955617e0260ebc449" 2394 | dependencies = [ 2395 | "anyhow", 2396 | "cocoa", 2397 | "dirs-next", 2398 | "embed_plist", 2399 | "encoding_rs", 2400 | "flate2", 2401 | "futures-util", 2402 | "glib", 2403 | "glob", 2404 | "gtk", 2405 | "heck 0.4.1", 2406 | "http", 2407 | "ignore", 2408 | "objc", 2409 | "once_cell", 2410 | "percent-encoding", 2411 | "rand 0.8.5", 2412 | "raw-window-handle", 2413 | "rfd", 2414 | "semver 1.0.16", 2415 | "serde", 2416 | "serde_json", 2417 | "serde_repr", 2418 | "serialize-to-javascript", 2419 | "state", 2420 | "tar", 2421 | "tauri-macros", 2422 | "tauri-runtime", 2423 | "tauri-runtime-wry", 2424 | "tauri-utils", 2425 | "tempfile", 2426 | "thiserror", 2427 | "tokio", 2428 | "url", 2429 | "uuid 1.3.0", 2430 | "webkit2gtk", 2431 | "webview2-com", 2432 | "windows 0.39.0", 2433 | ] 2434 | 2435 | [[package]] 2436 | name = "tauri-build" 2437 | version = "1.2.1" 2438 | source = "registry+https://github.com/rust-lang/crates.io-index" 2439 | checksum = "8807c85d656b2b93927c19fe5a5f1f1f348f96c2de8b90763b3c2d561511f9b4" 2440 | dependencies = [ 2441 | "anyhow", 2442 | "cargo_toml", 2443 | "heck 0.4.1", 2444 | "json-patch", 2445 | "semver 1.0.16", 2446 | "serde_json", 2447 | "tauri-utils", 2448 | "winres", 2449 | ] 2450 | 2451 | [[package]] 2452 | name = "tauri-codegen" 2453 | version = "1.2.1" 2454 | source = "registry+https://github.com/rust-lang/crates.io-index" 2455 | checksum = "14388d484b6b1b5dc0f6a7d6cc6433b3b230bec85eaa576adcdf3f9fafa49251" 2456 | dependencies = [ 2457 | "base64", 2458 | "brotli", 2459 | "ico", 2460 | "json-patch", 2461 | "plist", 2462 | "png", 2463 | "proc-macro2", 2464 | "quote", 2465 | "semver 1.0.16", 2466 | "serde", 2467 | "serde_json", 2468 | "sha2", 2469 | "tauri-utils", 2470 | "thiserror", 2471 | "time", 2472 | "uuid 1.3.0", 2473 | "walkdir", 2474 | ] 2475 | 2476 | [[package]] 2477 | name = "tauri-macros" 2478 | version = "1.2.1" 2479 | source = "registry+https://github.com/rust-lang/crates.io-index" 2480 | checksum = "069319e5ecbe653a799b94b0690d9f9bf5d00f7b1d3989aa331c524d4e354075" 2481 | dependencies = [ 2482 | "heck 0.4.1", 2483 | "proc-macro2", 2484 | "quote", 2485 | "syn", 2486 | "tauri-codegen", 2487 | "tauri-utils", 2488 | ] 2489 | 2490 | [[package]] 2491 | name = "tauri-runtime" 2492 | version = "0.12.1" 2493 | source = "registry+https://github.com/rust-lang/crates.io-index" 2494 | checksum = "c507d954d08ac8705d235bc70ec6975b9054fb95ff7823af72dbb04186596f3b" 2495 | dependencies = [ 2496 | "gtk", 2497 | "http", 2498 | "http-range", 2499 | "rand 0.8.5", 2500 | "raw-window-handle", 2501 | "serde", 2502 | "serde_json", 2503 | "tauri-utils", 2504 | "thiserror", 2505 | "uuid 1.3.0", 2506 | "webview2-com", 2507 | "windows 0.39.0", 2508 | ] 2509 | 2510 | [[package]] 2511 | name = "tauri-runtime-wry" 2512 | version = "0.12.2" 2513 | source = "registry+https://github.com/rust-lang/crates.io-index" 2514 | checksum = "36b1c5764a41a13176a4599b5b7bd0881bea7d94dfe45e1e755f789b98317e30" 2515 | dependencies = [ 2516 | "cocoa", 2517 | "gtk", 2518 | "percent-encoding", 2519 | "rand 0.8.5", 2520 | "raw-window-handle", 2521 | "tauri-runtime", 2522 | "tauri-utils", 2523 | "uuid 1.3.0", 2524 | "webkit2gtk", 2525 | "webview2-com", 2526 | "windows 0.39.0", 2527 | "wry", 2528 | ] 2529 | 2530 | [[package]] 2531 | name = "tauri-utils" 2532 | version = "1.2.1" 2533 | source = "registry+https://github.com/rust-lang/crates.io-index" 2534 | checksum = "5abbc109a6eb45127956ffcc26ef0e875d160150ac16cfa45d26a6b2871686f1" 2535 | dependencies = [ 2536 | "brotli", 2537 | "ctor", 2538 | "glob", 2539 | "heck 0.4.1", 2540 | "html5ever", 2541 | "infer", 2542 | "json-patch", 2543 | "kuchiki", 2544 | "memchr", 2545 | "phf 0.10.1", 2546 | "proc-macro2", 2547 | "quote", 2548 | "semver 1.0.16", 2549 | "serde", 2550 | "serde_json", 2551 | "serde_with", 2552 | "thiserror", 2553 | "url", 2554 | "walkdir", 2555 | "windows 0.39.0", 2556 | ] 2557 | 2558 | [[package]] 2559 | name = "tempfile" 2560 | version = "3.3.0" 2561 | source = "registry+https://github.com/rust-lang/crates.io-index" 2562 | checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" 2563 | dependencies = [ 2564 | "cfg-if", 2565 | "fastrand", 2566 | "libc", 2567 | "redox_syscall", 2568 | "remove_dir_all", 2569 | "winapi", 2570 | ] 2571 | 2572 | [[package]] 2573 | name = "tendril" 2574 | version = "0.4.3" 2575 | source = "registry+https://github.com/rust-lang/crates.io-index" 2576 | checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" 2577 | dependencies = [ 2578 | "futf", 2579 | "mac", 2580 | "utf-8", 2581 | ] 2582 | 2583 | [[package]] 2584 | name = "thin-slice" 2585 | version = "0.1.1" 2586 | source = "registry+https://github.com/rust-lang/crates.io-index" 2587 | checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" 2588 | 2589 | [[package]] 2590 | name = "thiserror" 2591 | version = "1.0.38" 2592 | source = "registry+https://github.com/rust-lang/crates.io-index" 2593 | checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" 2594 | dependencies = [ 2595 | "thiserror-impl", 2596 | ] 2597 | 2598 | [[package]] 2599 | name = "thiserror-impl" 2600 | version = "1.0.38" 2601 | source = "registry+https://github.com/rust-lang/crates.io-index" 2602 | checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" 2603 | dependencies = [ 2604 | "proc-macro2", 2605 | "quote", 2606 | "syn", 2607 | ] 2608 | 2609 | [[package]] 2610 | name = "thread_local" 2611 | version = "1.1.7" 2612 | source = "registry+https://github.com/rust-lang/crates.io-index" 2613 | checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" 2614 | dependencies = [ 2615 | "cfg-if", 2616 | "once_cell", 2617 | ] 2618 | 2619 | [[package]] 2620 | name = "time" 2621 | version = "0.3.17" 2622 | source = "registry+https://github.com/rust-lang/crates.io-index" 2623 | checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" 2624 | dependencies = [ 2625 | "itoa 1.0.5", 2626 | "serde", 2627 | "time-core", 2628 | "time-macros", 2629 | ] 2630 | 2631 | [[package]] 2632 | name = "time-core" 2633 | version = "0.1.0" 2634 | source = "registry+https://github.com/rust-lang/crates.io-index" 2635 | checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" 2636 | 2637 | [[package]] 2638 | name = "time-macros" 2639 | version = "0.2.6" 2640 | source = "registry+https://github.com/rust-lang/crates.io-index" 2641 | checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" 2642 | dependencies = [ 2643 | "time-core", 2644 | ] 2645 | 2646 | [[package]] 2647 | name = "tinyvec" 2648 | version = "1.6.0" 2649 | source = "registry+https://github.com/rust-lang/crates.io-index" 2650 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" 2651 | dependencies = [ 2652 | "tinyvec_macros", 2653 | ] 2654 | 2655 | [[package]] 2656 | name = "tinyvec_macros" 2657 | version = "0.1.1" 2658 | source = "registry+https://github.com/rust-lang/crates.io-index" 2659 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 2660 | 2661 | [[package]] 2662 | name = "tokio" 2663 | version = "1.25.0" 2664 | source = "registry+https://github.com/rust-lang/crates.io-index" 2665 | checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af" 2666 | dependencies = [ 2667 | "autocfg", 2668 | "bytes", 2669 | "memchr", 2670 | "num_cpus", 2671 | "pin-project-lite", 2672 | "windows-sys 0.42.0", 2673 | ] 2674 | 2675 | [[package]] 2676 | name = "toml" 2677 | version = "0.5.11" 2678 | source = "registry+https://github.com/rust-lang/crates.io-index" 2679 | checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" 2680 | dependencies = [ 2681 | "serde", 2682 | ] 2683 | 2684 | [[package]] 2685 | name = "toml_datetime" 2686 | version = "0.5.1" 2687 | source = "registry+https://github.com/rust-lang/crates.io-index" 2688 | checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" 2689 | 2690 | [[package]] 2691 | name = "toml_edit" 2692 | version = "0.18.1" 2693 | source = "registry+https://github.com/rust-lang/crates.io-index" 2694 | checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" 2695 | dependencies = [ 2696 | "indexmap", 2697 | "nom8", 2698 | "toml_datetime", 2699 | ] 2700 | 2701 | [[package]] 2702 | name = "tracing" 2703 | version = "0.1.37" 2704 | source = "registry+https://github.com/rust-lang/crates.io-index" 2705 | checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" 2706 | dependencies = [ 2707 | "cfg-if", 2708 | "pin-project-lite", 2709 | "tracing-attributes", 2710 | "tracing-core", 2711 | ] 2712 | 2713 | [[package]] 2714 | name = "tracing-attributes" 2715 | version = "0.1.23" 2716 | source = "registry+https://github.com/rust-lang/crates.io-index" 2717 | checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" 2718 | dependencies = [ 2719 | "proc-macro2", 2720 | "quote", 2721 | "syn", 2722 | ] 2723 | 2724 | [[package]] 2725 | name = "tracing-core" 2726 | version = "0.1.30" 2727 | source = "registry+https://github.com/rust-lang/crates.io-index" 2728 | checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" 2729 | dependencies = [ 2730 | "once_cell", 2731 | "valuable", 2732 | ] 2733 | 2734 | [[package]] 2735 | name = "tracing-log" 2736 | version = "0.1.3" 2737 | source = "registry+https://github.com/rust-lang/crates.io-index" 2738 | checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" 2739 | dependencies = [ 2740 | "lazy_static", 2741 | "log", 2742 | "tracing-core", 2743 | ] 2744 | 2745 | [[package]] 2746 | name = "tracing-subscriber" 2747 | version = "0.3.16" 2748 | source = "registry+https://github.com/rust-lang/crates.io-index" 2749 | checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" 2750 | dependencies = [ 2751 | "matchers", 2752 | "nu-ansi-term", 2753 | "once_cell", 2754 | "regex", 2755 | "sharded-slab", 2756 | "smallvec", 2757 | "thread_local", 2758 | "tracing", 2759 | "tracing-core", 2760 | "tracing-log", 2761 | ] 2762 | 2763 | [[package]] 2764 | name = "treediff" 2765 | version = "3.0.2" 2766 | source = "registry+https://github.com/rust-lang/crates.io-index" 2767 | checksum = "761e8d5ad7ce14bb82b7e61ccc0ca961005a275a060b9644a2431aa11553c2ff" 2768 | dependencies = [ 2769 | "serde_json", 2770 | ] 2771 | 2772 | [[package]] 2773 | name = "typenum" 2774 | version = "1.16.0" 2775 | source = "registry+https://github.com/rust-lang/crates.io-index" 2776 | checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" 2777 | 2778 | [[package]] 2779 | name = "ucd-trie" 2780 | version = "0.1.5" 2781 | source = "registry+https://github.com/rust-lang/crates.io-index" 2782 | checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" 2783 | 2784 | [[package]] 2785 | name = "unicode-bidi" 2786 | version = "0.3.10" 2787 | source = "registry+https://github.com/rust-lang/crates.io-index" 2788 | checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" 2789 | 2790 | [[package]] 2791 | name = "unicode-ident" 2792 | version = "1.0.6" 2793 | source = "registry+https://github.com/rust-lang/crates.io-index" 2794 | checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" 2795 | 2796 | [[package]] 2797 | name = "unicode-normalization" 2798 | version = "0.1.22" 2799 | source = "registry+https://github.com/rust-lang/crates.io-index" 2800 | checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" 2801 | dependencies = [ 2802 | "tinyvec", 2803 | ] 2804 | 2805 | [[package]] 2806 | name = "unicode-segmentation" 2807 | version = "1.10.1" 2808 | source = "registry+https://github.com/rust-lang/crates.io-index" 2809 | checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" 2810 | 2811 | [[package]] 2812 | name = "unsafe-libyaml" 2813 | version = "0.2.6" 2814 | source = "registry+https://github.com/rust-lang/crates.io-index" 2815 | checksum = "137b80f8d41159fdb7c990322f0679b9ccbeb84d73f426844b7e838500b92b31" 2816 | 2817 | [[package]] 2818 | name = "url" 2819 | version = "2.3.1" 2820 | source = "registry+https://github.com/rust-lang/crates.io-index" 2821 | checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" 2822 | dependencies = [ 2823 | "form_urlencoded", 2824 | "idna", 2825 | "percent-encoding", 2826 | "serde", 2827 | ] 2828 | 2829 | [[package]] 2830 | name = "utf-8" 2831 | version = "0.7.6" 2832 | source = "registry+https://github.com/rust-lang/crates.io-index" 2833 | checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" 2834 | 2835 | [[package]] 2836 | name = "uuid" 2837 | version = "0.8.2" 2838 | source = "registry+https://github.com/rust-lang/crates.io-index" 2839 | checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" 2840 | 2841 | [[package]] 2842 | name = "uuid" 2843 | version = "1.3.0" 2844 | source = "registry+https://github.com/rust-lang/crates.io-index" 2845 | checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" 2846 | dependencies = [ 2847 | "getrandom 0.2.8", 2848 | ] 2849 | 2850 | [[package]] 2851 | name = "valuable" 2852 | version = "0.1.0" 2853 | source = "registry+https://github.com/rust-lang/crates.io-index" 2854 | checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" 2855 | 2856 | [[package]] 2857 | name = "version-compare" 2858 | version = "0.0.11" 2859 | source = "registry+https://github.com/rust-lang/crates.io-index" 2860 | checksum = "1c18c859eead79d8b95d09e4678566e8d70105c4e7b251f707a03df32442661b" 2861 | 2862 | [[package]] 2863 | name = "version-compare" 2864 | version = "0.1.1" 2865 | source = "registry+https://github.com/rust-lang/crates.io-index" 2866 | checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" 2867 | 2868 | [[package]] 2869 | name = "version_check" 2870 | version = "0.9.4" 2871 | source = "registry+https://github.com/rust-lang/crates.io-index" 2872 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 2873 | 2874 | [[package]] 2875 | name = "walkdir" 2876 | version = "2.3.2" 2877 | source = "registry+https://github.com/rust-lang/crates.io-index" 2878 | checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" 2879 | dependencies = [ 2880 | "same-file", 2881 | "winapi", 2882 | "winapi-util", 2883 | ] 2884 | 2885 | [[package]] 2886 | name = "wasi" 2887 | version = "0.9.0+wasi-snapshot-preview1" 2888 | source = "registry+https://github.com/rust-lang/crates.io-index" 2889 | checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" 2890 | 2891 | [[package]] 2892 | name = "wasi" 2893 | version = "0.11.0+wasi-snapshot-preview1" 2894 | source = "registry+https://github.com/rust-lang/crates.io-index" 2895 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 2896 | 2897 | [[package]] 2898 | name = "wasm-bindgen" 2899 | version = "0.2.84" 2900 | source = "registry+https://github.com/rust-lang/crates.io-index" 2901 | checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" 2902 | dependencies = [ 2903 | "cfg-if", 2904 | "wasm-bindgen-macro", 2905 | ] 2906 | 2907 | [[package]] 2908 | name = "wasm-bindgen-backend" 2909 | version = "0.2.84" 2910 | source = "registry+https://github.com/rust-lang/crates.io-index" 2911 | checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" 2912 | dependencies = [ 2913 | "bumpalo", 2914 | "log", 2915 | "once_cell", 2916 | "proc-macro2", 2917 | "quote", 2918 | "syn", 2919 | "wasm-bindgen-shared", 2920 | ] 2921 | 2922 | [[package]] 2923 | name = "wasm-bindgen-futures" 2924 | version = "0.4.34" 2925 | source = "registry+https://github.com/rust-lang/crates.io-index" 2926 | checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" 2927 | dependencies = [ 2928 | "cfg-if", 2929 | "js-sys", 2930 | "wasm-bindgen", 2931 | "web-sys", 2932 | ] 2933 | 2934 | [[package]] 2935 | name = "wasm-bindgen-macro" 2936 | version = "0.2.84" 2937 | source = "registry+https://github.com/rust-lang/crates.io-index" 2938 | checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" 2939 | dependencies = [ 2940 | "quote", 2941 | "wasm-bindgen-macro-support", 2942 | ] 2943 | 2944 | [[package]] 2945 | name = "wasm-bindgen-macro-support" 2946 | version = "0.2.84" 2947 | source = "registry+https://github.com/rust-lang/crates.io-index" 2948 | checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" 2949 | dependencies = [ 2950 | "proc-macro2", 2951 | "quote", 2952 | "syn", 2953 | "wasm-bindgen-backend", 2954 | "wasm-bindgen-shared", 2955 | ] 2956 | 2957 | [[package]] 2958 | name = "wasm-bindgen-shared" 2959 | version = "0.2.84" 2960 | source = "registry+https://github.com/rust-lang/crates.io-index" 2961 | checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" 2962 | 2963 | [[package]] 2964 | name = "web-sys" 2965 | version = "0.3.61" 2966 | source = "registry+https://github.com/rust-lang/crates.io-index" 2967 | checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" 2968 | dependencies = [ 2969 | "js-sys", 2970 | "wasm-bindgen", 2971 | ] 2972 | 2973 | [[package]] 2974 | name = "webkit2gtk" 2975 | version = "0.18.2" 2976 | source = "registry+https://github.com/rust-lang/crates.io-index" 2977 | checksum = "b8f859735e4a452aeb28c6c56a852967a8a76c8eb1cc32dbf931ad28a13d6370" 2978 | dependencies = [ 2979 | "bitflags", 2980 | "cairo-rs", 2981 | "gdk", 2982 | "gdk-sys", 2983 | "gio", 2984 | "gio-sys", 2985 | "glib", 2986 | "glib-sys", 2987 | "gobject-sys", 2988 | "gtk", 2989 | "gtk-sys", 2990 | "javascriptcore-rs", 2991 | "libc", 2992 | "once_cell", 2993 | "soup2", 2994 | "webkit2gtk-sys", 2995 | ] 2996 | 2997 | [[package]] 2998 | name = "webkit2gtk-sys" 2999 | version = "0.18.0" 3000 | source = "registry+https://github.com/rust-lang/crates.io-index" 3001 | checksum = "4d76ca6ecc47aeba01ec61e480139dda143796abcae6f83bcddf50d6b5b1dcf3" 3002 | dependencies = [ 3003 | "atk-sys", 3004 | "bitflags", 3005 | "cairo-sys-rs", 3006 | "gdk-pixbuf-sys", 3007 | "gdk-sys", 3008 | "gio-sys", 3009 | "glib-sys", 3010 | "gobject-sys", 3011 | "gtk-sys", 3012 | "javascriptcore-rs-sys", 3013 | "libc", 3014 | "pango-sys", 3015 | "pkg-config", 3016 | "soup2-sys", 3017 | "system-deps 6.0.3", 3018 | ] 3019 | 3020 | [[package]] 3021 | name = "webview2-com" 3022 | version = "0.19.1" 3023 | source = "registry+https://github.com/rust-lang/crates.io-index" 3024 | checksum = "b4a769c9f1a64a8734bde70caafac2b96cada12cd4aefa49196b3a386b8b4178" 3025 | dependencies = [ 3026 | "webview2-com-macros", 3027 | "webview2-com-sys", 3028 | "windows 0.39.0", 3029 | "windows-implement", 3030 | ] 3031 | 3032 | [[package]] 3033 | name = "webview2-com-macros" 3034 | version = "0.6.0" 3035 | source = "registry+https://github.com/rust-lang/crates.io-index" 3036 | checksum = "eaebe196c01691db62e9e4ca52c5ef1e4fd837dcae27dae3ada599b5a8fd05ac" 3037 | dependencies = [ 3038 | "proc-macro2", 3039 | "quote", 3040 | "syn", 3041 | ] 3042 | 3043 | [[package]] 3044 | name = "webview2-com-sys" 3045 | version = "0.19.0" 3046 | source = "registry+https://github.com/rust-lang/crates.io-index" 3047 | checksum = "aac48ef20ddf657755fdcda8dfed2a7b4fc7e4581acce6fe9b88c3d64f29dee7" 3048 | dependencies = [ 3049 | "regex", 3050 | "serde", 3051 | "serde_json", 3052 | "thiserror", 3053 | "windows 0.39.0", 3054 | "windows-bindgen", 3055 | "windows-metadata", 3056 | ] 3057 | 3058 | [[package]] 3059 | name = "winapi" 3060 | version = "0.3.9" 3061 | source = "registry+https://github.com/rust-lang/crates.io-index" 3062 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 3063 | dependencies = [ 3064 | "winapi-i686-pc-windows-gnu", 3065 | "winapi-x86_64-pc-windows-gnu", 3066 | ] 3067 | 3068 | [[package]] 3069 | name = "winapi-i686-pc-windows-gnu" 3070 | version = "0.4.0" 3071 | source = "registry+https://github.com/rust-lang/crates.io-index" 3072 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 3073 | 3074 | [[package]] 3075 | name = "winapi-util" 3076 | version = "0.1.5" 3077 | source = "registry+https://github.com/rust-lang/crates.io-index" 3078 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 3079 | dependencies = [ 3080 | "winapi", 3081 | ] 3082 | 3083 | [[package]] 3084 | name = "winapi-x86_64-pc-windows-gnu" 3085 | version = "0.4.0" 3086 | source = "registry+https://github.com/rust-lang/crates.io-index" 3087 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 3088 | 3089 | [[package]] 3090 | name = "windows" 3091 | version = "0.37.0" 3092 | source = "registry+https://github.com/rust-lang/crates.io-index" 3093 | checksum = "57b543186b344cc61c85b5aab0d2e3adf4e0f99bc076eff9aa5927bcc0b8a647" 3094 | dependencies = [ 3095 | "windows_aarch64_msvc 0.37.0", 3096 | "windows_i686_gnu 0.37.0", 3097 | "windows_i686_msvc 0.37.0", 3098 | "windows_x86_64_gnu 0.37.0", 3099 | "windows_x86_64_msvc 0.37.0", 3100 | ] 3101 | 3102 | [[package]] 3103 | name = "windows" 3104 | version = "0.39.0" 3105 | source = "registry+https://github.com/rust-lang/crates.io-index" 3106 | checksum = "f1c4bd0a50ac6020f65184721f758dba47bb9fbc2133df715ec74a237b26794a" 3107 | dependencies = [ 3108 | "windows-implement", 3109 | "windows_aarch64_msvc 0.39.0", 3110 | "windows_i686_gnu 0.39.0", 3111 | "windows_i686_msvc 0.39.0", 3112 | "windows_x86_64_gnu 0.39.0", 3113 | "windows_x86_64_msvc 0.39.0", 3114 | ] 3115 | 3116 | [[package]] 3117 | name = "windows-bindgen" 3118 | version = "0.39.0" 3119 | source = "registry+https://github.com/rust-lang/crates.io-index" 3120 | checksum = "68003dbd0e38abc0fb85b939240f4bce37c43a5981d3df37ccbaaa981b47cb41" 3121 | dependencies = [ 3122 | "windows-metadata", 3123 | "windows-tokens", 3124 | ] 3125 | 3126 | [[package]] 3127 | name = "windows-implement" 3128 | version = "0.39.0" 3129 | source = "registry+https://github.com/rust-lang/crates.io-index" 3130 | checksum = "ba01f98f509cb5dc05f4e5fc95e535f78260f15fea8fe1a8abdd08f774f1cee7" 3131 | dependencies = [ 3132 | "syn", 3133 | "windows-tokens", 3134 | ] 3135 | 3136 | [[package]] 3137 | name = "windows-metadata" 3138 | version = "0.39.0" 3139 | source = "registry+https://github.com/rust-lang/crates.io-index" 3140 | checksum = "9ee5e275231f07c6e240d14f34e1b635bf1faa1c76c57cfd59a5cdb9848e4278" 3141 | 3142 | [[package]] 3143 | name = "windows-sys" 3144 | version = "0.42.0" 3145 | source = "registry+https://github.com/rust-lang/crates.io-index" 3146 | checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" 3147 | dependencies = [ 3148 | "windows_aarch64_gnullvm", 3149 | "windows_aarch64_msvc 0.42.1", 3150 | "windows_i686_gnu 0.42.1", 3151 | "windows_i686_msvc 0.42.1", 3152 | "windows_x86_64_gnu 0.42.1", 3153 | "windows_x86_64_gnullvm", 3154 | "windows_x86_64_msvc 0.42.1", 3155 | ] 3156 | 3157 | [[package]] 3158 | name = "windows-sys" 3159 | version = "0.45.0" 3160 | source = "registry+https://github.com/rust-lang/crates.io-index" 3161 | checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" 3162 | dependencies = [ 3163 | "windows-targets", 3164 | ] 3165 | 3166 | [[package]] 3167 | name = "windows-targets" 3168 | version = "0.42.1" 3169 | source = "registry+https://github.com/rust-lang/crates.io-index" 3170 | checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" 3171 | dependencies = [ 3172 | "windows_aarch64_gnullvm", 3173 | "windows_aarch64_msvc 0.42.1", 3174 | "windows_i686_gnu 0.42.1", 3175 | "windows_i686_msvc 0.42.1", 3176 | "windows_x86_64_gnu 0.42.1", 3177 | "windows_x86_64_gnullvm", 3178 | "windows_x86_64_msvc 0.42.1", 3179 | ] 3180 | 3181 | [[package]] 3182 | name = "windows-tokens" 3183 | version = "0.39.0" 3184 | source = "registry+https://github.com/rust-lang/crates.io-index" 3185 | checksum = "f838de2fe15fe6bac988e74b798f26499a8b21a9d97edec321e79b28d1d7f597" 3186 | 3187 | [[package]] 3188 | name = "windows_aarch64_gnullvm" 3189 | version = "0.42.1" 3190 | source = "registry+https://github.com/rust-lang/crates.io-index" 3191 | checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" 3192 | 3193 | [[package]] 3194 | name = "windows_aarch64_msvc" 3195 | version = "0.37.0" 3196 | source = "registry+https://github.com/rust-lang/crates.io-index" 3197 | checksum = "2623277cb2d1c216ba3b578c0f3cf9cdebeddb6e66b1b218bb33596ea7769c3a" 3198 | 3199 | [[package]] 3200 | name = "windows_aarch64_msvc" 3201 | version = "0.39.0" 3202 | source = "registry+https://github.com/rust-lang/crates.io-index" 3203 | checksum = "ec7711666096bd4096ffa835238905bb33fb87267910e154b18b44eaabb340f2" 3204 | 3205 | [[package]] 3206 | name = "windows_aarch64_msvc" 3207 | version = "0.42.1" 3208 | source = "registry+https://github.com/rust-lang/crates.io-index" 3209 | checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" 3210 | 3211 | [[package]] 3212 | name = "windows_i686_gnu" 3213 | version = "0.37.0" 3214 | source = "registry+https://github.com/rust-lang/crates.io-index" 3215 | checksum = "d3925fd0b0b804730d44d4b6278c50f9699703ec49bcd628020f46f4ba07d9e1" 3216 | 3217 | [[package]] 3218 | name = "windows_i686_gnu" 3219 | version = "0.39.0" 3220 | source = "registry+https://github.com/rust-lang/crates.io-index" 3221 | checksum = "763fc57100a5f7042e3057e7e8d9bdd7860d330070251a73d003563a3bb49e1b" 3222 | 3223 | [[package]] 3224 | name = "windows_i686_gnu" 3225 | version = "0.42.1" 3226 | source = "registry+https://github.com/rust-lang/crates.io-index" 3227 | checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" 3228 | 3229 | [[package]] 3230 | name = "windows_i686_msvc" 3231 | version = "0.37.0" 3232 | source = "registry+https://github.com/rust-lang/crates.io-index" 3233 | checksum = "ce907ac74fe331b524c1298683efbf598bb031bc84d5e274db2083696d07c57c" 3234 | 3235 | [[package]] 3236 | name = "windows_i686_msvc" 3237 | version = "0.39.0" 3238 | source = "registry+https://github.com/rust-lang/crates.io-index" 3239 | checksum = "7bc7cbfe58828921e10a9f446fcaaf649204dcfe6c1ddd712c5eebae6bda1106" 3240 | 3241 | [[package]] 3242 | name = "windows_i686_msvc" 3243 | version = "0.42.1" 3244 | source = "registry+https://github.com/rust-lang/crates.io-index" 3245 | checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" 3246 | 3247 | [[package]] 3248 | name = "windows_x86_64_gnu" 3249 | version = "0.37.0" 3250 | source = "registry+https://github.com/rust-lang/crates.io-index" 3251 | checksum = "2babfba0828f2e6b32457d5341427dcbb577ceef556273229959ac23a10af33d" 3252 | 3253 | [[package]] 3254 | name = "windows_x86_64_gnu" 3255 | version = "0.39.0" 3256 | source = "registry+https://github.com/rust-lang/crates.io-index" 3257 | checksum = "6868c165637d653ae1e8dc4d82c25d4f97dd6605eaa8d784b5c6e0ab2a252b65" 3258 | 3259 | [[package]] 3260 | name = "windows_x86_64_gnu" 3261 | version = "0.42.1" 3262 | source = "registry+https://github.com/rust-lang/crates.io-index" 3263 | checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" 3264 | 3265 | [[package]] 3266 | name = "windows_x86_64_gnullvm" 3267 | version = "0.42.1" 3268 | source = "registry+https://github.com/rust-lang/crates.io-index" 3269 | checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" 3270 | 3271 | [[package]] 3272 | name = "windows_x86_64_msvc" 3273 | version = "0.37.0" 3274 | source = "registry+https://github.com/rust-lang/crates.io-index" 3275 | checksum = "f4dd6dc7df2d84cf7b33822ed5b86318fb1781948e9663bacd047fc9dd52259d" 3276 | 3277 | [[package]] 3278 | name = "windows_x86_64_msvc" 3279 | version = "0.39.0" 3280 | source = "registry+https://github.com/rust-lang/crates.io-index" 3281 | checksum = "5e4d40883ae9cae962787ca76ba76390ffa29214667a111db9e0a1ad8377e809" 3282 | 3283 | [[package]] 3284 | name = "windows_x86_64_msvc" 3285 | version = "0.42.1" 3286 | source = "registry+https://github.com/rust-lang/crates.io-index" 3287 | checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" 3288 | 3289 | [[package]] 3290 | name = "winres" 3291 | version = "0.1.12" 3292 | source = "registry+https://github.com/rust-lang/crates.io-index" 3293 | checksum = "b68db261ef59e9e52806f688020631e987592bd83619edccda9c47d42cde4f6c" 3294 | dependencies = [ 3295 | "toml", 3296 | ] 3297 | 3298 | [[package]] 3299 | name = "wry" 3300 | version = "0.23.4" 3301 | source = "registry+https://github.com/rust-lang/crates.io-index" 3302 | checksum = "4c1ad8e2424f554cc5bdebe8aa374ef5b433feff817aebabca0389961fc7ef98" 3303 | dependencies = [ 3304 | "base64", 3305 | "block", 3306 | "cocoa", 3307 | "core-graphics", 3308 | "crossbeam-channel", 3309 | "dunce", 3310 | "gdk", 3311 | "gio", 3312 | "glib", 3313 | "gtk", 3314 | "html5ever", 3315 | "http", 3316 | "kuchiki", 3317 | "libc", 3318 | "log", 3319 | "objc", 3320 | "objc_id", 3321 | "once_cell", 3322 | "serde", 3323 | "serde_json", 3324 | "sha2", 3325 | "soup2", 3326 | "tao", 3327 | "thiserror", 3328 | "url", 3329 | "webkit2gtk", 3330 | "webkit2gtk-sys", 3331 | "webview2-com", 3332 | "windows 0.39.0", 3333 | "windows-implement", 3334 | ] 3335 | 3336 | [[package]] 3337 | name = "x11" 3338 | version = "2.21.0" 3339 | source = "registry+https://github.com/rust-lang/crates.io-index" 3340 | checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e" 3341 | dependencies = [ 3342 | "libc", 3343 | "pkg-config", 3344 | ] 3345 | 3346 | [[package]] 3347 | name = "x11-dl" 3348 | version = "2.21.0" 3349 | source = "registry+https://github.com/rust-lang/crates.io-index" 3350 | checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" 3351 | dependencies = [ 3352 | "libc", 3353 | "once_cell", 3354 | "pkg-config", 3355 | ] 3356 | 3357 | [[package]] 3358 | name = "xattr" 3359 | version = "0.2.3" 3360 | source = "registry+https://github.com/rust-lang/crates.io-index" 3361 | checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" 3362 | dependencies = [ 3363 | "libc", 3364 | ] 3365 | -------------------------------------------------------------------------------- /tauri/src-tauri/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "plaintext-daw" 3 | version = "0.0.0" 4 | description = "A Tauri App" 5 | authors = ["you"] 6 | license = "" 7 | repository = "" 8 | edition = "2021" 9 | 10 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 11 | 12 | [build-dependencies] 13 | tauri-build = { version = "1.2", features = [] } 14 | 15 | [dependencies] 16 | serde_json = "1.0" 17 | serde_yaml = "0.9.17" 18 | serde = { version = "1.0", features = ["derive"] } 19 | tauri = { version = "1.2", features = ["dialog-open"] } 20 | 21 | 22 | [features] 23 | # by default Tauri runs in production mode 24 | # when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL 25 | default = ["custom-protocol"] 26 | # this feature is used used for production builds where `devPath` points to the filesystem 27 | # DO NOT remove this 28 | custom-protocol = ["tauri/custom-protocol"] 29 | -------------------------------------------------------------------------------- /tauri/src-tauri/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | tauri_build::build() 3 | } 4 | -------------------------------------------------------------------------------- /tauri/src-tauri/icons/128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagekey/plaintext-daw/c74dc68330b1acec5892ecc20e34f208563e5a22/tauri/src-tauri/icons/128x128.png -------------------------------------------------------------------------------- /tauri/src-tauri/icons/128x128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagekey/plaintext-daw/c74dc68330b1acec5892ecc20e34f208563e5a22/tauri/src-tauri/icons/128x128@2x.png -------------------------------------------------------------------------------- /tauri/src-tauri/icons/32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagekey/plaintext-daw/c74dc68330b1acec5892ecc20e34f208563e5a22/tauri/src-tauri/icons/32x32.png -------------------------------------------------------------------------------- /tauri/src-tauri/icons/Square107x107Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagekey/plaintext-daw/c74dc68330b1acec5892ecc20e34f208563e5a22/tauri/src-tauri/icons/Square107x107Logo.png -------------------------------------------------------------------------------- /tauri/src-tauri/icons/Square142x142Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagekey/plaintext-daw/c74dc68330b1acec5892ecc20e34f208563e5a22/tauri/src-tauri/icons/Square142x142Logo.png -------------------------------------------------------------------------------- /tauri/src-tauri/icons/Square150x150Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagekey/plaintext-daw/c74dc68330b1acec5892ecc20e34f208563e5a22/tauri/src-tauri/icons/Square150x150Logo.png -------------------------------------------------------------------------------- /tauri/src-tauri/icons/Square284x284Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagekey/plaintext-daw/c74dc68330b1acec5892ecc20e34f208563e5a22/tauri/src-tauri/icons/Square284x284Logo.png -------------------------------------------------------------------------------- /tauri/src-tauri/icons/Square30x30Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagekey/plaintext-daw/c74dc68330b1acec5892ecc20e34f208563e5a22/tauri/src-tauri/icons/Square30x30Logo.png -------------------------------------------------------------------------------- /tauri/src-tauri/icons/Square310x310Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagekey/plaintext-daw/c74dc68330b1acec5892ecc20e34f208563e5a22/tauri/src-tauri/icons/Square310x310Logo.png -------------------------------------------------------------------------------- /tauri/src-tauri/icons/Square44x44Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagekey/plaintext-daw/c74dc68330b1acec5892ecc20e34f208563e5a22/tauri/src-tauri/icons/Square44x44Logo.png -------------------------------------------------------------------------------- /tauri/src-tauri/icons/Square71x71Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagekey/plaintext-daw/c74dc68330b1acec5892ecc20e34f208563e5a22/tauri/src-tauri/icons/Square71x71Logo.png -------------------------------------------------------------------------------- /tauri/src-tauri/icons/Square89x89Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagekey/plaintext-daw/c74dc68330b1acec5892ecc20e34f208563e5a22/tauri/src-tauri/icons/Square89x89Logo.png -------------------------------------------------------------------------------- /tauri/src-tauri/icons/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagekey/plaintext-daw/c74dc68330b1acec5892ecc20e34f208563e5a22/tauri/src-tauri/icons/StoreLogo.png -------------------------------------------------------------------------------- /tauri/src-tauri/icons/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagekey/plaintext-daw/c74dc68330b1acec5892ecc20e34f208563e5a22/tauri/src-tauri/icons/icon.icns -------------------------------------------------------------------------------- /tauri/src-tauri/icons/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagekey/plaintext-daw/c74dc68330b1acec5892ecc20e34f208563e5a22/tauri/src-tauri/icons/icon.ico -------------------------------------------------------------------------------- /tauri/src-tauri/icons/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagekey/plaintext-daw/c74dc68330b1acec5892ecc20e34f208563e5a22/tauri/src-tauri/icons/icon.png -------------------------------------------------------------------------------- /tauri/src-tauri/src/main.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr( 2 | all(not(debug_assertions), target_os = "windows"), 3 | windows_subsystem = "windows" 4 | )] 5 | 6 | use std::process::Command; 7 | use std::sync::{Arc, Mutex}; 8 | use tauri::api::dialog; 9 | use tauri::{Manager, State}; 10 | 11 | mod state; 12 | 13 | struct AppState(Arc>); 14 | 15 | fn render_song(path: String) { 16 | Command::new("plaintext-daw") 17 | .arg("render") 18 | .arg(path) 19 | .spawn() 20 | .expect("failed to render song"); 21 | } 22 | 23 | #[tauri::command] 24 | fn open_project(handle: tauri::AppHandle, app_state: State) { 25 | let app_state = app_state.0.clone(); 26 | dialog::FileDialogBuilder::new() 27 | .add_filter("Yaml", &["yml", "yaml"]) 28 | .pick_file(move |file_path| { 29 | if let Some(path) = file_path { 30 | app_state.lock().unwrap().filepath = path.to_str().unwrap().to_string(); 31 | tauri::WindowBuilder::new( 32 | &handle, 33 | "editor", 34 | tauri::WindowUrl::App("index2.html".into()), 35 | ) 36 | .title("Plaintext DAW Editor") 37 | .build() 38 | .unwrap(); 39 | handle 40 | .get_window("open-project") 41 | .unwrap() 42 | .close() 43 | .expect("Unable to close window"); 44 | } 45 | }); 46 | } 47 | 48 | #[tauri::command] 49 | fn get_app(handle: tauri::AppHandle, filepath: State) -> state::App { 50 | let fpath = filepath.0.lock().unwrap(); 51 | let result = (*fpath).clone(); 52 | result 53 | } 54 | 55 | fn main() { 56 | tauri::Builder::default() 57 | .manage(AppState(Default::default())) 58 | .invoke_handler(tauri::generate_handler![get_app, open_project,]) 59 | .run(tauri::generate_context!()) 60 | .expect("error while running tauri application"); 61 | } 62 | -------------------------------------------------------------------------------- /tauri/src-tauri/src/state.rs: -------------------------------------------------------------------------------- 1 | use serde::Deserialize; 2 | use serde::Serialize; 3 | 4 | #[derive(Clone, Default, Serialize)] 5 | pub struct App { 6 | pub filepath: String, 7 | pub song: Song, 8 | pub contents: String, 9 | } 10 | 11 | #[derive(Clone, Default, Deserialize, Serialize)] 12 | pub struct Song { 13 | pub bpm: i32, 14 | pub sample_rate: i32, 15 | } 16 | -------------------------------------------------------------------------------- /tauri/src-tauri/tauri.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "beforeDevCommand": "", 4 | "beforeBuildCommand": "", 5 | "devPath": "../src", 6 | "distDir": "../src", 7 | "withGlobalTauri": true 8 | }, 9 | "package": { 10 | "productName": "plaintext-daw", 11 | "version": "0.0.0" 12 | }, 13 | "tauri": { 14 | "allowlist": { 15 | "all": false, 16 | "dialog": { 17 | "all": false, 18 | "open": true 19 | } 20 | }, 21 | "bundle": { 22 | "active": true, 23 | "category": "DeveloperTool", 24 | "copyright": "", 25 | "deb": { 26 | "depends": [] 27 | }, 28 | "externalBin": [], 29 | "icon": [ 30 | "icons/32x32.png", 31 | "icons/128x128.png", 32 | "icons/128x128@2x.png", 33 | "icons/icon.icns", 34 | "icons/icon.ico" 35 | ], 36 | "identifier": "com.tauri.dev", 37 | "longDescription": "", 38 | "macOS": { 39 | "entitlements": null, 40 | "exceptionDomain": "", 41 | "frameworks": [], 42 | "providerShortName": null, 43 | "signingIdentity": null 44 | }, 45 | "resources": [], 46 | "shortDescription": "", 47 | "targets": "all", 48 | "windows": { 49 | "certificateThumbprint": null, 50 | "digestAlgorithm": "sha256", 51 | "timestampUrl": "" 52 | } 53 | }, 54 | "security": { 55 | "csp": null 56 | }, 57 | "updater": { 58 | "active": false 59 | }, 60 | "windows": [ 61 | { 62 | "label": "open-project", 63 | "fullscreen": false, 64 | "height": 200, 65 | "resizable": true, 66 | "title": "plaintext-daw", 67 | "width": 600 68 | } 69 | ] 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /tauri/src/assets/javascript.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tauri/src/assets/tauri.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /tauri/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Tauri App 8 | 9 | 10 | 11 | 12 |
13 |

Welcome to Plaintext DAW!

14 |
15 |
16 | 17 |
18 |
19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /tauri/src/index2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Tauri App 8 | 9 | 10 | 11 | 12 |
Editor
13 |
Filepath:
14 |
BPM:
15 |
Sample rate:
16 |
Clips
17 |
Instruments
18 |
Patterns
19 |
current project:
20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /tauri/src/main.js: -------------------------------------------------------------------------------- 1 | const { invoke } = window.__TAURI__.tauri; 2 | 3 | async function syscall() { 4 | await invoke('syscall_test', {}); 5 | } 6 | async function open_project() { 7 | await invoke('open_project', {}); 8 | } 9 | 10 | window.addEventListener("DOMContentLoaded", () => { 11 | document 12 | .querySelector("#open-project") 13 | .addEventListener("click", () => open_project()); 14 | }); 15 | -------------------------------------------------------------------------------- /tauri/src/main2.js: -------------------------------------------------------------------------------- 1 | const { invoke } = window.__TAURI__.tauri; 2 | 3 | 4 | window.addEventListener("DOMContentLoaded", async () => { 5 | invoke('get_app').then((app) => { 6 | document.querySelector("#filepath-value").innerHTML = app.filepath; 7 | document.querySelector("#bpm-value").innerHTML = app.song.bpm; 8 | document.querySelector("#sample-rate-value").innerHTML = app.song.sample_rate; 9 | document 10 | .querySelector("#current_project").innerHTML = `filepath: ${app.filepath}\n\n\ncontents:: ${app.contents}`; 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /tauri/src/style.css: -------------------------------------------------------------------------------- 1 | :root { 2 | font-family: Inter, Avenir, Helvetica, Arial, sans-serif; 3 | font-size: 16px; 4 | line-height: 24px; 5 | font-weight: 400; 6 | 7 | color: #0f0f0f; 8 | background-color: #f6f6f6; 9 | 10 | font-synthesis: none; 11 | text-rendering: optimizeLegibility; 12 | -webkit-font-smoothing: antialiased; 13 | -moz-osx-font-smoothing: grayscale; 14 | -webkit-text-size-adjust: 100%; 15 | } 16 | 17 | .container { 18 | margin: 0; 19 | padding-top: 10vh; 20 | display: flex; 21 | flex-direction: column; 22 | justify-content: center; 23 | text-align: center; 24 | } 25 | 26 | .row { 27 | display: flex; 28 | justify-content: center; 29 | } 30 | 31 | a { 32 | font-weight: 500; 33 | color: #646cff; 34 | text-decoration: inherit; 35 | } 36 | 37 | a:hover { 38 | color: #535bf2; 39 | } 40 | 41 | h1 { 42 | text-align: center; 43 | } 44 | 45 | input, 46 | button { 47 | border-radius: 8px; 48 | border: 1px solid transparent; 49 | padding: 0.6em 1.2em; 50 | font-size: 1em; 51 | font-weight: 500; 52 | font-family: inherit; 53 | color: #0f0f0f; 54 | background-color: #ffffff; 55 | transition: border-color 0.25s; 56 | box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2); 57 | } 58 | 59 | button { 60 | cursor: pointer; 61 | } 62 | 63 | button:hover { 64 | border-color: #396cd8; 65 | } 66 | 67 | input, 68 | button { 69 | outline: none; 70 | } 71 | 72 | #greet-input { 73 | margin-right: 5px; 74 | } 75 | 76 | @media (prefers-color-scheme: dark) { 77 | :root { 78 | color: #f6f6f6; 79 | background-color: #2f2f2f; 80 | } 81 | 82 | a:hover { 83 | color: #24c8db; 84 | } 85 | 86 | input, 87 | button { 88 | color: #ffffff; 89 | background-color: #0f0f0f98; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-A0.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a243ee2a3eba3a06e776a4c1fbfe13404658a447b8704def194455c9a7e48dfd 3 | size 485070 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-A1.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:17265a16da28de58c3466ec0df7074c979547869f77f008c3791e9b875c8f2fa 3 | size 755662 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-A2.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0286532a8db576facb99c264a679580ed56fc47441a64bc8b9a569e8c3b2adf3 3 | size 454606 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-A3.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a28dba32d7f68bb082ffab5b016fa6442ee47ca17664024ceab55d0c6e735f2d 3 | size 368590 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-A4.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2c4173391fdccc21edba8bfbe386006246cdf414777f6490b2dd7715edd83c6f 3 | size 246222 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-A5.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e0420aad71e8c834e1f4b9b7ec9c14352fa7266fca60bedfc63e2029074cf51c 3 | size 328398 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-A6.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:6c89f77823c506756158548dc4ff8947db2713a0eb820730f9e6a9194e94abe8 3 | size 230094 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-A7.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:726069f73acc887130a504d97c69cc010321b007a4dbe37584826e427d3b5899 3 | size 129742 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-C1.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4cc32be471d5119241538466b9223b0f6cd8c92e30f0c88c9792f65d189522ba 3 | size 433870 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-C2.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5dad229585c0e1e3c351252963b4a303b7d4cf247a92cf88ae8173d1b694ca54 3 | size 536270 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-C3.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b86f5d77747e1a7727865275a8e27174f8c7e14d44287097084202a34fecfca8 3 | size 374478 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-C4.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4d454962d5c468c7203847769a7524224b6424033e4aede97f05bae6b180f2fa 3 | size 284366 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-C5.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:aa7e3f3ed168d4f2350937f8d6469d1ba171b35723961a995c7df9453f12a4bf 3 | size 531406 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-C6.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:28c1dfeb606a1a2104a4648b58af6a6be5556ce082b865341406dd77e3f52ddf 3 | size 250574 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-C7.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0cf236d38b43b608af3e510f68b881d87323fdd7a94c64257487ef6b956acf72 3 | size 189134 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-C8.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a3d3830bd46114b4daa5eaf3d95650cb1274b913031912618f10b9b5af2922a6 3 | size 68302 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-D#1.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f5ea1ce876f0bbac46316a3fd7180dd602648e71775cee032b661af93b48b1fd 3 | size 708814 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-D#2.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d10a272079227b4e5d46a34140e218a58af0706ed1bfe65752c7190153ee8587 3 | size 529614 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-D#3.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d9fce344bcae23b46821f0d11312258bc2196139038dddfbe339c04d6425c122 3 | size 454862 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-D#4.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5f6f53d51f2c8b0ff3fde7402ab2ea6dd02001e7970896604c3bc8cc186a9293 3 | size 337870 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-D#5.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8a2ea86b27e030da2d064dfa397e8e0ea8123221515de05fb818f1ce84b07e7b 3 | size 555726 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-D#6.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:7f6d5e36c8ab8d6d4239aab7bdeee8d6887a3cd7a1844c8bb6d480ed7a6d71ed 3 | size 274382 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-D#7.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d87e463d0b7556d925cf5619604c1df012f4794c62b5dc8142e44fc6e1cb09fe 3 | size 142286 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-F#1.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:61a197e042e086bf2c3552d6cc9918272f9b56a4fdfaf5f54fd3d6a0d3f8da69 3 | size 575182 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-F#2.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3c3d532340d8fce2f4690c90b75590bf5047a42c528471da31a94b6b9cfa3ee3 3 | size 771790 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-F#3.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:29a7a75b16fef851b153685ec8342bd16e8e3bc6fb33053521a147deb206c67b 3 | size 339918 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-F#4.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:936d0bfad12f4962c6b2979043f2475a59ea0aed8bb7c8d1943db926e9e23553 3 | size 278222 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-F#5.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:664eb47665e465e01349028ebac6a34888ef7638d2275863e519475761d1e271 3 | size 405454 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-F#6.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:fcfada8fa397f404e6e6c39e14f539ab425c5a0c144a62dbb8e845e2de2a864f 3 | size 245454 4 | -------------------------------------------------------------------------------- /test/data/song1/piano/Piano-F#7.ogg.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:09b0de6e216018ea1ddddc570a74bd8aff948b35b0404e550095373f32b6e50a 3 | size 154318 4 | -------------------------------------------------------------------------------- /test/data/song1/song.yml: -------------------------------------------------------------------------------- 1 | bpm: 100 2 | sample_rate: 44100 3 | clips: 4 | clip1: 5 | path: voice/clip1.wav 6 | start: 2 7 | instruments: 8 | piano: 9 | type: wav 10 | clips: 11 | a: 12 | path: piano/Piano-A5.ogg.wav 13 | c: 14 | path: piano/Piano-C5.ogg.wav 15 | patterns: 16 | pattern1: 17 | instrument: piano 18 | start: 1 # start measure 19 | repeat: 0 # how many copies after the original one 20 | notes: 21 | - value: a 22 | start: 0 23 | length: 1 24 | - value: c 25 | start: 0 26 | length: 2 27 | - value: a 28 | start: 0.25 29 | length: 1 30 | - value: c 31 | start: 0.5 32 | length: 1 33 | - value: c 34 | start: 0.75 35 | length: 1 36 | - value: a 37 | start: 1 38 | length: 1 39 | - value: c 40 | start: 1 41 | length: 1 42 | - value: a 43 | start: 1.5 44 | length: 1 45 | -------------------------------------------------------------------------------- /test/data/song1/voice/clip1.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d6c5d0692e577a6386fc35e728515877e0a2fa57e5c1bb351a64faa58915af3e 3 | size 595236 4 | -------------------------------------------------------------------------------- /test/data/song2/song.yml: -------------------------------------------------------------------------------- 1 | bpm: 200 2 | sample_rate: 44100 3 | clips: {} 4 | instruments: 5 | piano: 6 | source: GIT 7 | repo: git@github.com:pagekeytech/plaintext-daw-instruments 8 | ref: master 9 | path: piano/instrument.yml 10 | patterns: 11 | pattern1: 12 | instrument: piano 13 | start: 1 # start measure 14 | repeat: 0 # how many copies after the original one 15 | notes: 16 | - value: C5 17 | start: 0 18 | length: 2 19 | - value: E5 20 | start: 1 21 | length: 1 22 | - value: F5 23 | start: 2 24 | length: 1 25 | - value: G5 26 | start: 3 27 | length: 1 28 | - value: C5 29 | start: 4 30 | length: 1 31 | - value: C5 32 | start: 4 33 | length: 1 34 | - value: E5 35 | start: 4 36 | length: 1 37 | - value: G5 38 | start: 5 39 | length: 1 40 | - value: C5 41 | start: 6 42 | length: 1 43 | - value: C5 44 | start: 7 45 | length: 1 46 | -------------------------------------------------------------------------------- /test/data/song3/song.yml: -------------------------------------------------------------------------------- 1 | bpm: 120 2 | sample_rate: 44100 3 | clips: {} 4 | instruments: 5 | synth: 6 | type: synth 7 | pipeline: 8 | - sin(frequency) 9 | - ADSR(0.1, 0.1, 0.7, 0.1) 10 | # Source for frequencies: https://pages.mtu.edu/~suits/notefreqs.html 11 | clips: 12 | C0: 13 | frequency: 16.35 14 | C#0: 15 | frequency: 17.32 16 | D0: 17 | frequency: 18.35 18 | D#0: 19 | frequency: 19.45 20 | E0: 21 | frequency: 20.6 22 | F0: 23 | frequency: 21.83 24 | F#0: 25 | frequency: 23.12 26 | G0: 27 | frequency: 24.5 28 | G#0: 29 | frequency: 25.96 30 | A0: 31 | frequency: 27.5 32 | A#0: 33 | frequency: 29.14 34 | B0: 35 | frequency: 30.87 36 | C1: 37 | frequency: 32.7 38 | C#1: 39 | frequency: 34.65 40 | D1: 41 | frequency: 36.71 42 | D#1: 43 | frequency: 38.89 44 | E1: 45 | frequency: 41.2 46 | F1: 47 | frequency: 43.65 48 | F#1: 49 | frequency: 46.25 50 | G1: 51 | frequency: 49 52 | G#1: 53 | frequency: 51.91 54 | A1: 55 | frequency: 55 56 | A#1: 57 | frequency: 58.27 58 | B1: 59 | frequency: 61.74 60 | C2: 61 | frequency: 65.41 62 | C#2: 63 | frequency: 69.3 64 | D2: 65 | frequency: 73.42 66 | D#2: 67 | frequency: 77.78 68 | E2: 69 | frequency: 82.41 70 | F2: 71 | frequency: 87.31 72 | F#2: 73 | frequency: 92.5 74 | G2: 75 | frequency: 98 76 | G#2: 77 | frequency: 103.83 78 | A2: 79 | frequency: 110 80 | A#2: 81 | frequency: 116.54 82 | B2: 83 | frequency: 123.47 84 | C3: 85 | frequency: 130.81 86 | C#3: 87 | frequency: 138.59 88 | D3: 89 | frequency: 146.83 90 | D#3: 91 | frequency: 155.56 92 | E3: 93 | frequency: 164.81 94 | F3: 95 | frequency: 174.61 96 | F#3: 97 | frequency: 185 98 | G3: 99 | frequency: 196 100 | G#3: 101 | frequency: 207.65 102 | A3: 103 | frequency: 220 104 | A#3: 105 | frequency: 233.08 106 | B3: 107 | frequency: 246.94 108 | C4: 109 | frequency: 261.63 110 | C#4: 111 | frequency: 277.18 112 | D4: 113 | frequency: 293.66 114 | D#4: 115 | frequency: 311.13 116 | E4: 117 | frequency: 329.63 118 | F4: 119 | frequency: 349.23 120 | F#4: 121 | frequency: 369.99 122 | G4: 123 | frequency: 392 124 | G#4: 125 | frequency: 415.3 126 | A4: 127 | frequency: 440 128 | A#4: 129 | frequency: 466.16 130 | B4: 131 | frequency: 493.88 132 | C5: 133 | frequency: 523.25 134 | C#5: 135 | frequency: 554.37 136 | D5: 137 | frequency: 587.33 138 | D#5: 139 | frequency: 622.25 140 | E5: 141 | frequency: 659.25 142 | F5: 143 | frequency: 698.46 144 | F#5: 145 | frequency: 739.99 146 | G5: 147 | frequency: 783.99 148 | G#5: 149 | frequency: 830.61 150 | A5: 151 | frequency: 880 152 | A#5: 153 | frequency: 932.33 154 | B5: 155 | frequency: 987.77 156 | C6: 157 | frequency: 1046.5 158 | C#6: 159 | frequency: 1108.73 160 | D6: 161 | frequency: 1174.66 162 | D#6: 163 | frequency: 1244.51 164 | E6: 165 | frequency: 1318.51 166 | F6: 167 | frequency: 1396.91 168 | F#6: 169 | frequency: 1479.98 170 | G6: 171 | frequency: 1567.98 172 | G#6: 173 | frequency: 1661.22 174 | A6: 175 | frequency: 1760 176 | A#6: 177 | frequency: 1864.66 178 | B6: 179 | frequency: 1975.53 180 | C7: 181 | frequency: 2093 182 | C#7: 183 | frequency: 2217.46 184 | D7: 185 | frequency: 2349.32 186 | D#7: 187 | frequency: 2489.02 188 | E7: 189 | frequency: 2637.02 190 | F7: 191 | frequency: 2793.83 192 | F#7: 193 | frequency: 2959.96 194 | G7: 195 | frequency: 3135.96 196 | G#7: 197 | frequency: 3322.44 198 | A7: 199 | frequency: 3520 200 | A#7: 201 | frequency: 3729.31 202 | B7: 203 | frequency: 3951.07 204 | C8: 205 | frequency: 4186.01 206 | C#8: 207 | frequency: 4434.92 208 | D8: 209 | frequency: 4698.63 210 | D#8: 211 | frequency: 4978.03 212 | E8: 213 | frequency: 5274.04 214 | F8: 215 | frequency: 5587.65 216 | F#8: 217 | frequency: 5919.91 218 | G8: 219 | frequency: 6271.93 220 | G#8: 221 | frequency: 6644.88 222 | A8: 223 | frequency: 7040 224 | A#8: 225 | frequency: 7458.62 226 | B8: 227 | frequency: 7902.13 228 | patterns: 229 | pattern1: 230 | instrument: synth 231 | start: 1 # start measure 232 | repeat: 0 # how many copies after the original one 233 | notes: 234 | - value: C5 235 | start: 0 236 | length: 1 237 | - value: E5 238 | start: 1 239 | length: 1 240 | - value: F5 241 | start: 2 242 | length: 1 243 | - value: G5 244 | start: 3 245 | length: 1 246 | - value: C5 247 | start: 4 248 | length: 1 249 | - value: E5 250 | start: 4 251 | length: 1 252 | - value: G5 253 | start: 4 254 | length: 1 255 | - value: G5 256 | start: 5 257 | length: 1 258 | - value: C5 259 | start: 6 260 | length: 1 261 | - value: C5 262 | start: 7 263 | length: 1 264 | -------------------------------------------------------------------------------- /test/models/test_clip.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from plaintext_daw.models import Clip 4 | 5 | 6 | class TestClip: 7 | def test_init(self): 8 | obj = Clip(np.array([1]), 1, 3) 9 | assert isinstance(obj, Clip) 10 | assert obj.data == np.array([1]) 11 | assert obj.channels == 1 12 | assert obj.sample_rate == 3 13 | -------------------------------------------------------------------------------- /test/models/test_instrument.py: -------------------------------------------------------------------------------- 1 | from plaintext_daw.models import Instrument 2 | from plaintext_daw.models.instrument import InstrumentSource 3 | 4 | 5 | class TestInstrument: 6 | def test_init(self): 7 | obj = Instrument() 8 | assert isinstance(obj, Instrument) 9 | assert obj.source == InstrumentSource.IN_PLACE 10 | -------------------------------------------------------------------------------- /test/models/test_note.py: -------------------------------------------------------------------------------- 1 | from plaintext_daw.models import Note 2 | 3 | 4 | class TestNote: 5 | def test_init(self): 6 | obj = Note() 7 | assert isinstance(obj, Note) 8 | assert obj.length == 1 9 | 10 | def test_beats_to_samples(self): 11 | beats = 1 12 | bpm = 60 13 | sample_rate = 44100 14 | assert Note.beats_to_samples(beats, bpm, sample_rate) == sample_rate 15 | assert Note.beats_to_samples(beats*2, bpm, sample_rate) == sample_rate*2 16 | assert Note.beats_to_samples(beats, bpm, sample_rate/2) == sample_rate/2 17 | 18 | def test_start_end_sample_simple(self): 19 | note = Note(value='a', start=0, length=1) 20 | # regardless of anything else, if it starts on beat 0, it starts on sample 0 21 | assert note.get_start_sample(60, 44100) == 0 22 | assert note.get_end_sample(60, 44100) == 44100 23 | note.start = 1 24 | note.length = 2 25 | assert note.get_start_sample(60, 44100) == 44100 26 | assert note.get_end_sample(60, 44100) == 44100*3 27 | -------------------------------------------------------------------------------- /test/models/test_pattern.py: -------------------------------------------------------------------------------- 1 | from plaintext_daw.models import Instrument, Note, Pattern 2 | from plaintext_daw.models.instrument import InstrumentSource 3 | 4 | 5 | class TestPattern: 6 | def test_init(self): 7 | obj = Pattern(instrument='hi', start=1, repeat=3) 8 | assert isinstance(obj, Pattern) 9 | assert obj.instrument == 'hi' 10 | assert obj.start == 1 11 | assert obj.repeat == 3 12 | -------------------------------------------------------------------------------- /test/models/test_song.py: -------------------------------------------------------------------------------- 1 | from plaintext_daw.models import Instrument, Pattern, Clip, Song 2 | 3 | 4 | class TestSong: 5 | def test_init(self): 6 | song = Song(100, 44100) 7 | assert isinstance(song, Song) 8 | assert song.bpm == 100 9 | assert song.sample_rate == 44100 10 | -------------------------------------------------------------------------------- /test/models/test_synth.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @Time : 2023/2/15 14:19 3 | # @Author : LTstrange 4 | from plaintext_daw.models import Note 5 | from plaintext_daw.models.synthesizer import Synthesizer 6 | 7 | 8 | def test_synth_init(): 9 | synth = Synthesizer(44100) 10 | assert synth.sample_rate == 44100 11 | 12 | 13 | def test_synth_set_clips(): 14 | synth = Synthesizer(44100) 15 | clips = {"a": "b"} 16 | synth.set_clips(clips) 17 | 18 | assert synth._Synthesizer__clips == {"a": "b"} 19 | 20 | 21 | def test_synth_set_pipeline(): 22 | synth = Synthesizer(44100) 23 | pipeline = ["sin(frequency)", "ADSR(0.1, 0.1, 0.7, 0.1)"] 24 | synth.set_pipeline(pipeline) 25 | 26 | assert synth._Synthesizer__effects == ["sin(frequency)", "ADSR(0.1, 0.1, 0.7, 0.1)"] 27 | 28 | 29 | def test_synth_get_clip(): 30 | synth = Synthesizer(44100) 31 | synth.set_clips({"a": {"frequency": 0}}) 32 | synth.set_pipeline(["sin(frequency)", "ADSR(0.1, 0.1, 0.7, 0.1)"]) 33 | clip = synth.get_clip(Note("a"), 100) 34 | 35 | assert clip.sample_rate == 44100 36 | assert clip.channels == 1 37 | assert all(clip.data) == 0 38 | -------------------------------------------------------------------------------- /test/test_integration.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import numpy as np 4 | 5 | from plaintext_daw.cli import cli_entry_point 6 | from plaintext_daw.lib import np_to_wav 7 | from plaintext_daw.models.synthesizer import Synthesizer 8 | 9 | 10 | def test_song1_render_local(): 11 | if os.path.exists('song.wav'): os.remove('song.wav') 12 | cli_entry_point(['plaintext-daw', 'render', 'test/data/song1/song.yml']) 13 | assert os.path.exists('song.wav') 14 | if os.path.exists('song.wav'): os.remove('song.wav') 15 | 16 | def test_song2_render_git(): 17 | if os.path.exists('song.wav'): os.remove('song.wav') 18 | cli_entry_point(['plaintext-daw', 'render', 'test/data/song2/song.yml']) 19 | assert os.path.exists('song.wav') 20 | if os.path.exists('song.wav'): os.remove('song.wav') 21 | 22 | def test_song3_synth(): 23 | if os.path.exists('song.wav'): os.remove('song.wav') 24 | cli_entry_point(['plaintext-daw', 'render', 'test/data/song3/song.yml']) 25 | assert os.path.exists('song.wav') 26 | if os.path.exists('song.wav'): os.remove('song.wav') 27 | -------------------------------------------------------------------------------- /test/test_lib.py: -------------------------------------------------------------------------------- 1 | from plaintext_daw.lib import np_to_mp3, minmax_mapping 2 | from plaintext_daw.models.synthesizer.envelope import ADSR 3 | from plaintext_daw.models.synthesizer.rawclip import RawClip 4 | 5 | import os 6 | 7 | from plaintext_daw.models.synthesizer.wave import Wave, Sine 8 | 9 | 10 | def test_min_max_mapping(): 11 | sample_rate = 44100 12 | signal = RawClip(Wave([Sine(65.406, 2)]), ADSR(0.1, 0, 1, 0.1), duration=2).render(sample_rate) 13 | # assert signal.max() > 1 and signal.min() < -1 14 | signal = minmax_mapping(signal) 15 | assert signal.max() < 1 and signal.min() > -1 16 | 17 | 18 | def test_convert_mp3(): 19 | if os.path.exists("song.mp3"): os.remove("song.mp3") 20 | sample_rate = 44100 21 | signal = RawClip(Wave([Sine(65.406, 1)]), ADSR(0.1, 0, 1, 0.1), duration=2).render(sample_rate) 22 | np_to_mp3(signal, sample_rate, "song.mp3") 23 | 24 | assert os.path.exists("song.mp3") 25 | if os.path.exists("song.mp3"): os.remove("song.mp3") 26 | -------------------------------------------------------------------------------- /test/test_renderer.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pagekey/plaintext-daw/c74dc68330b1acec5892ecc20e34f208563e5a22/test/test_renderer.py -------------------------------------------------------------------------------- /test/test_resource_manager.py: -------------------------------------------------------------------------------- 1 | from unittest import mock 2 | from unittest.mock import call, patch 3 | 4 | import numpy as np 5 | import pytest 6 | from plaintext_daw.models.clip import Clip 7 | 8 | from plaintext_daw.models.instrument import Instrument, InstrumentSource 9 | from plaintext_daw.models.note import Note 10 | from plaintext_daw.models.pattern import Pattern 11 | from plaintext_daw.models.song import Song 12 | 13 | from plaintext_daw.resource_manager import ResourceManager 14 | 15 | 16 | class TestResourceManager: 17 | 18 | def setup_method(self, test_method): 19 | self.rm = ResourceManager('.') 20 | 21 | def test_working_dir(self): 22 | assert self.rm.working_dir == '.' 23 | 24 | def test_check_types(self): 25 | config = { 26 | 'foo': 'val1', 27 | 'bar': 'val2', 28 | } 29 | ResourceManager.check_types(config, ['foo', 'bar']) 30 | with pytest.raises(ValueError, match='baz'): 31 | ResourceManager.check_types(config, ['foo', 'bar', 'baz']) 32 | 33 | @patch.object(ResourceManager, 'get_clip') 34 | @patch.object(ResourceManager, 'get_instrument') 35 | @patch.object(ResourceManager, 'get_pattern') 36 | def test_get_song(self, mock_get_pattern, mock_get_instrument, mock_get_clip): 37 | with pytest.raises(ValueError): 38 | self.rm.get_song({'bpm': 100}) 39 | 40 | clip_dict = { 41 | 'costco': {'pancake': 'wait'}, 42 | 'walmart': {'no': 'free samples'}, 43 | } 44 | ins_dict = { 45 | 'myins': {'field': 'hello'}, 46 | 'yourins': {'name': 'insurance??'}, 47 | } 48 | pattern_dict = { 49 | 'pattern': {'hey': 'there'}, 50 | 'other': {'angle': 'momentum'}, 51 | } 52 | song = self.rm.get_song({ 53 | 'bpm': 100, 54 | 'sample_rate': 44100, 55 | 'clips': clip_dict, 56 | 'instruments': ins_dict, 57 | 'patterns': pattern_dict, 58 | }) 59 | assert isinstance(song, Song) 60 | assert song.bpm == 100 61 | assert song.sample_rate == 44100 62 | mock_get_clip.assert_has_calls([ 63 | call(clip_dict['costco']), 64 | call(clip_dict['walmart']), 65 | ]) 66 | mock_get_instrument.assert_has_calls([ 67 | call(ins_dict['myins']), 68 | call(ins_dict['yourins']), 69 | ]) 70 | mock_get_pattern.assert_has_calls([ 71 | call(pattern_dict['pattern']), 72 | call(pattern_dict['other']), 73 | ]) 74 | 75 | def test_get_clip_no_type(self): 76 | with pytest.raises(ValueError): 77 | self.rm.get_clip({}) 78 | with pytest.raises(ValueError): 79 | self.rm.get_clip({'type': 'something crazy'}) 80 | 81 | def test_get_clip_wav(self): 82 | # Good config 83 | wav_path = 'test/data/song1/piano/Piano-A0.ogg.wav' 84 | config = { 85 | 'type': 'wav', 86 | 'path': wav_path, 87 | } 88 | clip = self.rm.get_clip(config) 89 | assert isinstance(clip, Clip) 90 | assert isinstance(clip.data, np.ndarray) 91 | assert clip.channels == 1 92 | assert clip.sample_rate == 44100 93 | 94 | # Missing fields 95 | 96 | @patch.object(ResourceManager, 'get_clip') 97 | def test_get_instrument(self, mock_get_clip): 98 | clips_dict = { 99 | 'A0': {'path': 'path/to/A0.wav'}, 100 | 'C5': {'path': 'path/to/C5.wav'}, 101 | } 102 | instrument = self.rm.get_instrument({ 103 | 'clips': clips_dict, 104 | 'type': 'wav' 105 | }) 106 | assert isinstance(instrument, Instrument) 107 | assert instrument.source == InstrumentSource.IN_PLACE 108 | assert instrument.type == 'wav' 109 | mock_get_clip.assert_has_calls([ 110 | call(clips_dict['A0']), 111 | call(clips_dict['C5']), 112 | ]) 113 | 114 | @patch.object(ResourceManager, 'clone_repo') 115 | @patch.object(ResourceManager, 'get_config_from_file', return_value={ 116 | 'clips': { 117 | 'A4': { 118 | 'path': 'samples/A4.wav', 119 | }, 120 | 'A#4': { 121 | 'path': 'samples/A#4.wav', 122 | }, 123 | }, 124 | }) 125 | @patch.object(ResourceManager, 'get_clip') 126 | def test_get_instrument_git(self, mock_get_clip, mock_get_config_from_file, mock_clone_repo): 127 | the_repo = 'git@gitub.com:pagekeytech/plaintext-daw-instruments' 128 | instrument = self.rm.get_instrument({ 129 | 'source': 'GIT', 130 | 'repo': the_repo, 131 | 'ref': 'master', 132 | 'path': 'piano/instrument.yml', 133 | }) 134 | assert instrument.source == InstrumentSource.GIT 135 | assert instrument.repo == the_repo 136 | assert instrument.ref == 'master' 137 | assert instrument.path == 'piano/instrument.yml' 138 | mock_clone_repo.assert_called_with(the_repo, 'master') 139 | mock_get_config_from_file.assert_called_with('.ptd-cache/plaintext-daw-instruments/piano/instrument.yml') 140 | mock_get_clip.assert_has_calls([ 141 | call({'path': '.ptd-cache/plaintext-daw-instruments/piano/samples/A4.wav'}), 142 | call({'path': '.ptd-cache/plaintext-daw-instruments/piano/samples/A#4.wav'}), 143 | ]) 144 | 145 | @patch.object(ResourceManager, 'get_note') 146 | def test_get_pattern(self, mock_get_note): 147 | notes = [ 148 | {'value': 'A0', 'start': 0, 'length': 1}, 149 | {'value': 'A1', 'start': 1, 'length': 2}, 150 | ] 151 | pattern = self.rm.get_pattern({ 152 | 'instrument': 'piano', 153 | 'start': 12, 154 | 'repeat': 0, 155 | 'notes': notes, 156 | }) 157 | assert isinstance(pattern, Pattern) 158 | assert pattern.start == 12 159 | assert pattern.repeat == 0 160 | mock_get_note.assert_has_calls([call(n) for n in notes]) 161 | 162 | def test_get_pattern(self): 163 | note = self.rm.get_note({ 164 | 'value': 'C5', 165 | 'start': 7, 166 | 'length': 3, 167 | }) 168 | assert isinstance(note, Note) 169 | assert note.value == 'C5' 170 | assert note.start == 7 171 | assert note.length == 3 172 | 173 | @patch('plaintext_daw.resource_manager.os.makedirs') 174 | @patch('plaintext_daw.resource_manager.os.path.exists', return_value=False) 175 | @patch('plaintext_daw.resource_manager.subprocess.check_call') 176 | def test_clone_repo(self, mock_check_call, mock_exists, mock_makedirs): 177 | the_repo = 'git@gitub.com:pagekeytech/plaintext-daw-instruments' 178 | self.rm.working_dir = 'wdir' 179 | self.rm.clone_repo(the_repo, 'master') 180 | mock_makedirs.assert_called_with('wdir/.ptd-cache', exist_ok=True) 181 | mock_exists.assert_called_with('wdir/.ptd-cache/plaintext-daw-instruments') 182 | mock_check_call.assert_has_calls([ 183 | call(['git', 'clone', the_repo], cwd='wdir/.ptd-cache'), 184 | call(['git', 'checkout', 'master'], cwd='wdir/.ptd-cache/plaintext-daw-instruments'), 185 | ]) 186 | self.rm.working_dir = '.' 187 | 188 | @patch('plaintext_daw.resource_manager.yaml.safe_load') 189 | def test_get_config_from_file(self, mock_safe_load): 190 | mock_open = mock.mock_open(read_data='file data') 191 | with mock.patch('builtins.open', mock_open): 192 | self.rm.get_config_from_file('file.yml') 193 | mock_open.assert_called_with('./file.yml') 194 | self.rm.working_dir = 'hello' 195 | self.rm.get_config_from_file('file.yml') 196 | mock_open.assert_called_with('hello/file.yml') 197 | self.rm.working_dir = '.' 198 | --------------------------------------------------------------------------------