Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d1ed2f80e0 | |||
| 99159c1ab3 | |||
| d9ccf76097 | |||
| 53e031b183 | |||
| 69e83b5599 |
@@ -0,0 +1,12 @@
|
||||
# Strip upstream (ArtCraft / Discord) branding. Run: perl tools/craft-skills/skills/debrand/debrand.pl . (--check in CI)
|
||||
delete docs/brand
|
||||
# MIT/Apache texts stay verbatim. The copyright holder line stays everywhere (legal requirement).
|
||||
keep ^(LICENSE-(MIT|APACHE)|\.debrand)$
|
||||
dropline ^ATTRIBUTION\.md$ :: \|\s*`docs/brand/
|
||||
sub (?s)\nThe ArtCraft name, wordmark and logos in docs/brand/.*?LICENSE-brand\.txt\.\n =>
|
||||
sub \n- The ArtCraft trademarks in `docs/brand/` are the only exception, under `docs/brand/LICENSE-brand\.txt`\. =>
|
||||
sub until the owner draws SoundCraft's icon in ArtCraft like => until the owner draws SoundCraft's icon like
|
||||
sub https://getartcraft\.com/apps/soundcraft => https://github.com/storytold/soundcraft
|
||||
sub https://discord\.gg/artcraft => https://github.com/storytold/soundcraft/issues
|
||||
forbid (?i)artcraft(?! Team and the SoundCraft contributors)
|
||||
forbid (?i)discord
|
||||
@@ -0,0 +1,3 @@
|
||||
[submodule "tools/craft-skills"]
|
||||
path = tools/craft-skills
|
||||
url = https://git.marcospaulo.dev.br/storytold/craft-skills.git
|
||||
@@ -16,7 +16,6 @@ Standards and learnings shared across the crafting apps live in `../../craftrule
|
||||
- **Every bundled asset gets a row in [`ATTRIBUTION.md`](ATTRIBUTION.md)** (path, author, source, license) in the same commit that adds it. `cargo xtask assets` enforces this; CI fails otherwise.
|
||||
- Never copy files out of the Pro Tools bundle (`/Applications/Pro Tools.app`): no plugins, presets, icons, sounds, session templates or text. Observing the running app (screenshots kept under `plan/`, menu names) is fine; copying its resources is not.
|
||||
- Demo audio is synthesised in code (`crates/engine/src/demo.rs`). Demo and README media must be ours or public domain.
|
||||
- The ArtCraft trademarks in `docs/brand/` are the only exception, under `docs/brand/LICENSE-brand.txt`.
|
||||
|
||||
## Clean-room
|
||||
Pro Tools is installed on the dev machine and may be *observed* black-box: run it, use its UI with synthetic sessions, take screenshots by window id (`screencapture -l <id>`), stored only under `plan/protools/screenshots/`. Never read, disassemble or copy anything inside the Pro Tools bundle; never copy Avid icons, artwork, plugin names, presets, or wording beyond feature names. Never copy GPL/AGPL/LGPL code (Ardour, Audacity, LMMS, Freeverb sources…). Our plugins have our own names.
|
||||
|
||||
@@ -29,14 +29,6 @@ and, at runtime, the operating system's own UI fonts when available (never redis
|
||||
|
||||
| Path | Author | Source | License |
|
||||
|---|---|---|---|
|
||||
| `docs/brand/artcraft-logo.svg` | ArtCraft Team | craftrules `assets/brand/` | ArtCraft brand terms (`docs/brand/LICENSE-brand.txt`) |
|
||||
| `docs/brand/artcraft-logo.png` | ArtCraft Team | craftrules `assets/brand/` | ArtCraft brand terms |
|
||||
| `docs/brand/artcraft-logo-white.svg` | ArtCraft Team | craftrules `assets/brand/` | ArtCraft brand terms |
|
||||
| `docs/brand/artcraft-logo-white.png` | ArtCraft Team | craftrules `assets/brand/` | ArtCraft brand terms |
|
||||
| `docs/brand/artcraft-mark.svg` | ArtCraft Team | craftrules `assets/brand/` | ArtCraft brand terms |
|
||||
| `docs/brand/artcraft-mark.png` | ArtCraft Team | craftrules `assets/brand/` | ArtCraft brand terms |
|
||||
| `docs/brand/artcraft-mark-black.svg` | ArtCraft Team | craftrules `assets/brand/` | ArtCraft brand terms |
|
||||
| `docs/brand/artcraft-mark-black.png` | ArtCraft Team | craftrules `assets/brand/` | ArtCraft brand terms |
|
||||
| `assets/app-icon/icon.svg` | SoundCraft contributors | original (hand-placed SVG paths; placeholder app icon) | MIT OR Apache-2.0 |
|
||||
| `packaging/macos/dmg/` (all files) | @XusBadia | original (macOS DMG window background and layout, from the app icon; see `packaging/macos/dmg/README.md`) | MIT OR Apache-2.0 |
|
||||
| `assets/app-icon/soundcraft-1024.png` | SoundCraft contributors | original, rendered from `icon.svg` | MIT OR Apache-2.0 |
|
||||
|
||||
@@ -785,7 +785,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "craft-ui"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=5c874d51eeb3de70e735c8ce87a59a7dedd47675#5c874d51eeb3de70e735c8ce87a59a7dedd47675"
|
||||
source = "git+https://git.marcospaulo.dev.br/masi/craft-libs?rev=22544b6d619d4f16779b8bdfa3f0b642a86fc065#22544b6d619d4f16779b8bdfa3f0b642a86fc065"
|
||||
dependencies = [
|
||||
"egui",
|
||||
"serde",
|
||||
@@ -3424,7 +3424,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "soundcraft"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
dependencies = [
|
||||
"eframe",
|
||||
"egui",
|
||||
@@ -3442,7 +3442,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "soundcraft-au-host"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
dependencies = [
|
||||
"log",
|
||||
"serde",
|
||||
@@ -3452,7 +3452,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "soundcraft-audio-io"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
dependencies = [
|
||||
"log",
|
||||
"proptest",
|
||||
@@ -3464,7 +3464,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "soundcraft-automation"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
dependencies = [
|
||||
"log",
|
||||
"serde_json",
|
||||
@@ -3474,7 +3474,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "soundcraft-clap-host"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
dependencies = [
|
||||
"clap-sys",
|
||||
"libloading",
|
||||
@@ -3486,7 +3486,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "soundcraft-cli"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
dependencies = [
|
||||
"serde_json",
|
||||
"soundcraft-audio-io",
|
||||
@@ -3497,7 +3497,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "soundcraft-dsp"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
dependencies = [
|
||||
"log",
|
||||
"proptest",
|
||||
@@ -3508,7 +3508,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "soundcraft-engine"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
dependencies = [
|
||||
"log",
|
||||
"proptest",
|
||||
@@ -3530,7 +3530,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "soundcraft-midi"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
dependencies = [
|
||||
"proptest",
|
||||
"serde",
|
||||
@@ -3540,7 +3540,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "soundcraft-mix"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
dependencies = [
|
||||
"log",
|
||||
"rayon",
|
||||
@@ -3556,7 +3556,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "soundcraft-model"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
dependencies = [
|
||||
"proptest",
|
||||
"serde",
|
||||
@@ -3569,7 +3569,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "soundcraft-playback"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
dependencies = [
|
||||
"cpal",
|
||||
"log",
|
||||
@@ -3582,7 +3582,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "soundcraft-time"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
dependencies = [
|
||||
"proptest",
|
||||
"serde",
|
||||
@@ -3592,7 +3592,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "soundcraft-ui-egui"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
dependencies = [
|
||||
"craft-ui",
|
||||
"egui",
|
||||
@@ -3618,7 +3618,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "soundcraft-video"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
dependencies = [
|
||||
"image",
|
||||
"proptest",
|
||||
@@ -3629,7 +3629,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "soundcraft-vst3-host"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
dependencies = [
|
||||
"libloading",
|
||||
"log",
|
||||
@@ -3644,7 +3644,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "soundcraft-web"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
dependencies = [
|
||||
"eframe",
|
||||
"egui",
|
||||
@@ -5201,7 +5201,7 @@ checksum = "e450f9b2ed1dff33c94c12589a87338689467b9c4f5d8a5710bd09a847d2c8a7"
|
||||
|
||||
[[package]]
|
||||
name = "xtask"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
dependencies = [
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
@@ -4,7 +4,7 @@ members = ["crates/*", "apps/*", "xtask"]
|
||||
default-members = ["crates/*", "apps/*", "xtask"]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
edition = "2024"
|
||||
license = "MIT OR Apache-2.0"
|
||||
rust-version = "1.90"
|
||||
@@ -43,7 +43,7 @@ zip = { version = "9", default-features = false }
|
||||
cpal = "0.16"
|
||||
|
||||
# ui
|
||||
craft-ui = { version = "0.1.0", git = "https://github.com/storytold/craft-libs", rev = "5c874d51eeb3de70e735c8ce87a59a7dedd47675", features = ["serde"] }
|
||||
craft-ui = { version = "0.1.0", git = "https://git.marcospaulo.dev.br/masi/craft-libs", rev = "22544b6d619d4f16779b8bdfa3f0b642a86fc065", features = ["serde"] }
|
||||
egui = "0.36"
|
||||
eframe = { version = "0.36", default-features = false }
|
||||
egui_kittest = "0.36"
|
||||
|
||||
@@ -3,10 +3,6 @@ Copyright (c) 2026 ArtCraft Team and the SoundCraft contributors.
|
||||
Licensed under the MIT License or the Apache License, Version 2.0, at your option
|
||||
(LICENSE-MIT, LICENSE-APACHE).
|
||||
|
||||
The ArtCraft name, wordmark and logos in docs/brand/ are trademarks of the ArtCraft Team. They are
|
||||
not open source and are not covered by the license above; their terms are in
|
||||
docs/brand/LICENSE-brand.txt.
|
||||
|
||||
Third-party material
|
||||
|
||||
This product bundles third-party material under its own licenses, listed below. The per-file
|
||||
|
||||
@@ -1,12 +1,3 @@
|
||||
<p align="center">
|
||||
<a href="https://getartcraft.com/">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="docs/brand/artcraft-logo-white.svg">
|
||||
<img alt="ArtCraft" src="docs/brand/artcraft-logo.svg" width="200">
|
||||
</picture>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<h1 align="center">SoundCraft</h1>
|
||||
|
||||
<p align="center">
|
||||
@@ -27,27 +18,12 @@
|
||||
<img alt="Status: pre-alpha" src="https://img.shields.io/badge/status-pre--alpha-orange?style=flat-square">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://discord.gg/artcraft"><img alt="Join the ArtCraft community on Discord" src="https://img.shields.io/badge/Join%20us%20on%20Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white" height="40"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://getartcraft.com/apps/soundcraft"><b>SoundCraft on getartcraft.com</b></a> ·
|
||||
<a href="https://getartcraft.com/">ArtCraft</a> ·
|
||||
<a href="https://getartcraft.com/apps">All Crafting Apps</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img alt="SoundCraft's Edit window with a nine-track session: drums, bass, pad, keys and lead, a reverb aux and a master fader" src="docs/images/edit.png" width="100%">
|
||||
<br>
|
||||
<sub>The Edit window: tracks, waveforms, MIDI, rulers, markers and the transport, playing the built-in demo song (every sound in it is synthesised by SoundCraft itself).</sub>
|
||||
</p>
|
||||
|
||||
> [!NOTE]
|
||||
> **ArtCraft is a community of artists from all walks of life.** Painters, photographers,
|
||||
> filmmakers, illustrators, designers, animators, hobbyists, and people who picked up a pencil
|
||||
> last week. If you make things, you're one of us. **[Come say hi on Discord](https://discord.gg/artcraft).**
|
||||
|
||||
<p align="center">
|
||||
<a href="#what-it-does">What it does</a> ·
|
||||
<a href="#getting-started">Getting started</a> ·
|
||||
@@ -248,7 +224,7 @@ estimates are in [`ROADMAP.md`](ROADMAP.md); the full assessment is in
|
||||
[`docs/target-app-parity.md`](docs/target-app-parity.md), the ranked list of what's missing in
|
||||
[`docs/gaps.md`](docs/gaps.md), and the menu-by-menu comparison in
|
||||
[`docs/parity-checklist.md`](docs/parity-checklist.md). Bug reports and wish lists are
|
||||
very welcome, in the issues or on Discord.
|
||||
very welcome, in the issues.
|
||||
|
||||
## Downloads
|
||||
|
||||
@@ -317,44 +293,22 @@ RISC-V (riscv64): `soundcraft-<ver>-linux-riscv64.tar.gz`, a tarball only (glibc
|
||||
## The Crafting Apps
|
||||
|
||||
SoundCraft is one of the **Crafting Apps**: free, open-source creative tools from the
|
||||
[ArtCraft](https://getartcraft.com/) team, each written from scratch in Rust and each able to
|
||||
[storytold](https://github.com/storytold) team, each written from scratch in Rust and each able to
|
||||
stand on its own.
|
||||
|
||||
| | App | What it's for | Code | Learn more |
|
||||
|:-:|---|---|---|---|
|
||||
| <img src="https://raw.githubusercontent.com/storytold/photocraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.photocraft.png" alt="" width="32" height="32"> | **PhotoCraft** | Image editing: layers, masks, type and real PSD files | [GitHub](https://github.com/storytold/photocraft) | [Website](https://getartcraft.com/apps/photocraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/vectorcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.vectorcraft.png" alt="" width="32" height="32"> | **VectorCraft** | Vector illustration | [GitHub](https://github.com/storytold/vectorcraft) | [Website](https://getartcraft.com/apps/vectorcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/filmcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.filmcraft.png" alt="" width="32" height="32"> | **FilmCraft** | Video editing, color and sound | [GitHub](https://github.com/storytold/filmcraft) | [Website](https://getartcraft.com/apps/filmcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/lightcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.lightcraft.png" alt="" width="32" height="32"> | **LightCraft** | Photo library and raw development | [GitHub](https://github.com/storytold/lightcraft) | [Website](https://getartcraft.com/apps/lightcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/pdfcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.pdfcraft.png" alt="" width="32" height="32"> | **PdfCraft** | Reading, organizing and protecting PDFs | [GitHub](https://github.com/storytold/pdfcraft) | [Website](https://getartcraft.com/apps/pdfcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/effectcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.effectcraft.png" alt="" width="32" height="32"> | **EffectCraft** | Motion graphics and visual effects | [GitHub](https://github.com/storytold/effectcraft) | [Website](https://getartcraft.com/apps/effectcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/designcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.designcraft.png" alt="" width="32" height="32"> | **DesignCraft** | Page layout and publishing | [GitHub](https://github.com/storytold/designcraft) | [Website](https://getartcraft.com/apps/designcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/soundcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.soundcraft.png" alt="" width="32" height="32"> | **SoundCraft** | **Recording, editing and mixing audio · you are here** | [GitHub](https://github.com/storytold/soundcraft) | [Website](https://getartcraft.com/apps/soundcraft) |
|
||||
|
||||
And [**ArtCraft**](https://getartcraft.com/) itself, our AI image and video studio for artists who want real control.
|
||||
| | App | What it's for | Code |
|
||||
|:-:|---|---|---|
|
||||
| <img src="https://raw.githubusercontent.com/storytold/photocraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.photocraft.png" alt="" width="32" height="32"> | **PhotoCraft** | Image editing: layers, masks, type and real PSD files | [GitHub](https://github.com/storytold/photocraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/vectorcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.vectorcraft.png" alt="" width="32" height="32"> | **VectorCraft** | Vector illustration | [GitHub](https://github.com/storytold/vectorcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/filmcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.filmcraft.png" alt="" width="32" height="32"> | **FilmCraft** | Video editing, color and sound | [GitHub](https://github.com/storytold/filmcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/lightcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.lightcraft.png" alt="" width="32" height="32"> | **LightCraft** | Photo library and raw development | [GitHub](https://github.com/storytold/lightcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/pdfcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.pdfcraft.png" alt="" width="32" height="32"> | **PdfCraft** | Reading, organizing and protecting PDFs | [GitHub](https://github.com/storytold/pdfcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/effectcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.effectcraft.png" alt="" width="32" height="32"> | **EffectCraft** | Motion graphics and visual effects | [GitHub](https://github.com/storytold/effectcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/designcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.designcraft.png" alt="" width="32" height="32"> | **DesignCraft** | Page layout and publishing | [GitHub](https://github.com/storytold/designcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/soundcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.soundcraft.png" alt="" width="32" height="32"> | **SoundCraft** | **Recording, editing and mixing audio · you are here** | [GitHub](https://github.com/storytold/soundcraft) |
|
||||
|
||||
<br>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://discord.gg/artcraft"><img alt="Join the ArtCraft community on Discord" src="https://img.shields.io/badge/Join%20us%20on%20Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white" height="40"></a>
|
||||
</p>
|
||||
|
||||
<h3 align="center">Come make things with us</h3>
|
||||
|
||||
<p align="center">
|
||||
Our Discord is where artists of every kind hang out: people who paint, shoot, draw, cut film,
|
||||
set type, and people still figuring out what they like to make. Share what you're working on,
|
||||
ask for help, tell us what's broken, or tell us what you wish these tools could do.
|
||||
Whatever your medium and however long you've been at it, you're welcome here.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://discord.gg/artcraft"><b>discord.gg/artcraft</b></a> ·
|
||||
<a href="https://getartcraft.com/">getartcraft.com</a> ·
|
||||
<a href="https://getartcraft.com/apps">The Crafting Apps</a> ·
|
||||
<a href="https://getartcraft.com/apps/soundcraft">SoundCraft</a>
|
||||
</p>
|
||||
|
||||
## License and credits
|
||||
|
||||
SoundCraft is dual-licensed under [MIT](LICENSE-MIT) or [Apache-2.0](LICENSE-APACHE), at your option.
|
||||
@@ -367,18 +321,8 @@ Every icon in the interface is drawn in code, the app icon is original, and the
|
||||
screenshots' audio are synthesised by SoundCraft itself, so there are no samples or artwork from
|
||||
anyone else in this repository.
|
||||
|
||||
The ArtCraft name, wordmark and logos in [`docs/brand/`](docs/brand/) are trademarks of the
|
||||
ArtCraft Team and are not covered by this license. They may be used only unmodified, and only as
|
||||
part of this repository and SoundCraft, under [`docs/brand/LICENSE-brand.txt`](docs/brand/LICENSE-brand.txt).
|
||||
Forks and modified versions must remove them.
|
||||
|
||||
<sub>Avid and Pro Tools are trademarks or registered trademarks of Avid Technology, Inc. in the United States and/or other countries. SoundCraft is an independent, open-source project and is not affiliated with, sponsored by or endorsed by Avid Technology, Inc.; these names are used only to describe the workflows it is compatible with.</sub>
|
||||
|
||||
<sub>Adobe, Photoshop, Illustrator, Premiere Pro, Lightroom, Acrobat, After Effects and InDesign are trademarks or registered trademarks of Adobe Inc. in the United States and/or other countries. SoundCraft is an independent, open-source project and is not affiliated with, sponsored by or endorsed by Adobe Inc.; these names are used only to describe the workflows it is compatible with.</sub>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://getartcraft.com/"><img alt="ArtCraft" src="docs/brand/artcraft-mark.svg" width="28"></a><br>
|
||||
<sub>Made by the <a href="https://getartcraft.com/">ArtCraft</a> team and community.</sub>
|
||||
</p>
|
||||
|
||||
Tracks and Groups, Clips, MIDI Editor, Memory Locations, and Undo History use movable panels. Edit and Mix retain separate arrangements; Clips and MIDI Editor belong to Edit. Transport, plug-in, and specialist utility windows retain their existing hosts. Drag a panel header to a target edge or another header. Its context menu offers Float panel, Move to group, and Close panel. Existing panel toggles reopen panels at their saved location; Reset Panel Layout restores the app layout. Floating panels remain inside the current app window.
|
||||
|
||||
@@ -5,7 +5,7 @@ owl-template framing (craftrules `standards/icon-design.md`): a full-bleed colou
|
||||
in three-quarter view with its bill open and its eye on the viewer, its breast and wing running off
|
||||
the bottom and right edges, three song arcs leaving the bill.
|
||||
|
||||
This is a **placeholder** until the owner draws SoundCraft's icon in ArtCraft like the other apps'
|
||||
This is a **placeholder** until the owner draws SoundCraft's icon like the other apps'
|
||||
icons. Replace `icon.svg` and run `packaging/icons.sh`; nothing else needs to change.
|
||||
|
||||
## Palette
|
||||
|
||||
@@ -99,7 +99,7 @@ pub struct UiState {
|
||||
pub video_burn_in: bool,
|
||||
pub workspace_dir: String,
|
||||
pub configurations: Vec<(String, Value)>,
|
||||
/// Appearance (`ui.theme`): dark by default, light or follow the system on request.
|
||||
/// Appearance (`ui.theme`): dark by default; light, a Catppuccin flavour or the system on request.
|
||||
pub theme: theme::ThemeMode,
|
||||
/// The main window's size (logical points) and maximized state, and the interface scale, as
|
||||
/// the desktop app last saw them; it restores them at launch.
|
||||
@@ -254,7 +254,7 @@ pub struct SoundApp {
|
||||
fonts_ready: bool,
|
||||
fonts_installed: bool,
|
||||
/// The palette last applied to the context (light?), so visuals are set only on a change.
|
||||
theme_applied: Option<bool>,
|
||||
theme_applied: Option<theme::ThemeMode>,
|
||||
/// Last panel host context, used to cancel renderer-owned gestures on explicit replacement.
|
||||
pub(crate) docking_context: Option<egui::Context>,
|
||||
/// Transport simulation when there is no player (tests, offscreen renders).
|
||||
@@ -798,10 +798,10 @@ impl SoundApp {
|
||||
ctx.request_repaint();
|
||||
}
|
||||
}
|
||||
let light = theme::wants_light(ctx, self.ui.theme);
|
||||
if self.theme_applied != Some(light) || theme::is_light() != light {
|
||||
theme::apply(ctx, light);
|
||||
self.theme_applied = Some(light);
|
||||
let mode = theme::resolve(ctx, self.ui.theme);
|
||||
if self.theme_applied != Some(mode) || theme::active_mode() != mode {
|
||||
theme::apply(ctx, mode);
|
||||
self.theme_applied = Some(mode);
|
||||
}
|
||||
let now = ctx.input(|i| i.time);
|
||||
let dt = self.last_frame.replace(now).map_or(1.0 / 60.0, |t| (now - t) as f32).clamp(0.0, 0.25);
|
||||
|
||||
@@ -591,7 +591,7 @@ pub fn run_ui_command(app: &mut SoundApp, id: &str, p: &Value) -> Option<Result<
|
||||
return Some(Ok(json!({"mode": app.ui.theme.id()})));
|
||||
};
|
||||
let Some(mode) = crate::theme::ThemeMode::parse(mode) else {
|
||||
return Some(Err(format!("unknown theme `{mode}` (system, light or dark)")));
|
||||
return Some(Err(format!("unknown theme `{mode}` ({})", crate::theme::ThemeMode::id_list())));
|
||||
};
|
||||
app.ui.theme = mode;
|
||||
json!({"mode": mode.id()})
|
||||
|
||||
@@ -508,10 +508,9 @@ fn about(app: &mut SoundApp, ctx: &egui::Context) {
|
||||
_ => {
|
||||
ui.label(egui::RichText::new("SoundCraft").font(bold(22.0)));
|
||||
ui.label(format!("Version {}", env!("CARGO_PKG_VERSION")));
|
||||
ui.label("An open-source digital audio workstation from the ArtCraft team.");
|
||||
ui.label("An open-source digital audio workstation from the storytold team.");
|
||||
ui.label("Dual-licensed MIT OR Apache-2.0. Made with Rust and egui.");
|
||||
ui.hyperlink_to("getartcraft.com/apps/soundcraft", "https://getartcraft.com/apps/soundcraft");
|
||||
ui.hyperlink_to("Join us on Discord", "https://discord.gg/artcraft");
|
||||
ui.hyperlink_to("github.com/storytold/soundcraft", "https://github.com/storytold/soundcraft");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
//! Design tokens. Colours were chosen by eye to give a dark, studio-style look; they are ours.
|
||||
|
||||
use craft_ui::theme::catppuccin::Flavor;
|
||||
use egui::{Color32, FontFamily, FontId};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::atomic::{AtomicU8, Ordering};
|
||||
|
||||
/// Whether the Light palette is active. Dark is the default (the incumbent is dark-only).
|
||||
static LIGHT_THEME: AtomicBool = AtomicBool::new(false);
|
||||
/// Index into `ThemeMode::ALL` of the active palette. Dark (0) is the default (the incumbent is dark-only).
|
||||
static ACTIVE_THEME: AtomicU8 = AtomicU8::new(0);
|
||||
|
||||
/// Unit tests that change the process-wide palette must own it until their assertions finish.
|
||||
#[cfg(test)]
|
||||
@@ -13,7 +14,7 @@ pub(crate) fn lock_test_palette() -> std::sync::MutexGuard<'static, ()> {
|
||||
PALETTE.lock().unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
}
|
||||
|
||||
/// The Appearance setting (`ui.theme {mode}`). Dark by default; System and Light are opt-in.
|
||||
/// The Appearance setting (`ui.theme {mode}`). Dark by default; System, Light and the Catppuccin flavours are opt-in.
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum ThemeMode {
|
||||
@@ -21,16 +22,45 @@ pub enum ThemeMode {
|
||||
Light,
|
||||
#[default]
|
||||
Dark,
|
||||
#[serde(rename = "catppuccinLatte")]
|
||||
CatppuccinLatte,
|
||||
#[serde(rename = "catppuccinFrappe")]
|
||||
CatppuccinFrappe,
|
||||
#[serde(rename = "catppuccinMacchiato")]
|
||||
CatppuccinMacchiato,
|
||||
#[serde(rename = "catppuccinMocha")]
|
||||
CatppuccinMocha,
|
||||
}
|
||||
|
||||
impl ThemeMode {
|
||||
pub const ALL: [Self; 3] = [Self::Dark, Self::Light, Self::System];
|
||||
pub const ALL: [Self; 7] =
|
||||
[Self::Dark, Self::Light, Self::System, Self::CatppuccinLatte, Self::CatppuccinFrappe, Self::CatppuccinMacchiato, Self::CatppuccinMocha];
|
||||
|
||||
/// The Catppuccin flavour behind this mode, if it is one.
|
||||
pub const fn flavor(self) -> Option<Flavor> {
|
||||
match self {
|
||||
Self::CatppuccinLatte => Some(Flavor::Latte),
|
||||
Self::CatppuccinFrappe => Some(Flavor::Frappe),
|
||||
Self::CatppuccinMacchiato => Some(Flavor::Macchiato),
|
||||
Self::CatppuccinMocha => Some(Flavor::Mocha),
|
||||
Self::System | Self::Light | Self::Dark => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Every id, `|`-separated: for error messages.
|
||||
pub fn id_list() -> String {
|
||||
Self::ALL.map(Self::id).join("|")
|
||||
}
|
||||
|
||||
pub const fn label(self) -> &'static str {
|
||||
match self {
|
||||
Self::System => "System",
|
||||
Self::Light => "Light",
|
||||
Self::Dark => "Dark",
|
||||
Self::CatppuccinLatte => "Catppuccin Latte",
|
||||
Self::CatppuccinFrappe => "Catppuccin Frappé",
|
||||
Self::CatppuccinMacchiato => "Catppuccin Macchiato",
|
||||
Self::CatppuccinMocha => "Catppuccin Mocha",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +70,10 @@ impl ThemeMode {
|
||||
Self::System => "system",
|
||||
Self::Light => "light",
|
||||
Self::Dark => "dark",
|
||||
Self::CatppuccinLatte => "catppuccinLatte",
|
||||
Self::CatppuccinFrappe => "catppuccinFrappe",
|
||||
Self::CatppuccinMacchiato => "catppuccinMacchiato",
|
||||
Self::CatppuccinMocha => "catppuccinMocha",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,21 +360,126 @@ impl Tokens {
|
||||
};
|
||||
|
||||
pub fn current() -> Tokens {
|
||||
if is_light() { Self::LIGHT } else { Self::DARK }
|
||||
Self::for_mode(active_mode())
|
||||
}
|
||||
|
||||
/// The tokens of a resolved mode (`System` reads as Dark: resolve it with `resolve` first).
|
||||
pub fn for_mode(mode: ThemeMode) -> Tokens {
|
||||
match mode.flavor() {
|
||||
Some(f) => catppuccin(f),
|
||||
None if mode == ThemeMode::Light => Self::LIGHT,
|
||||
None => Self::DARK,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the Light palette is the active one.
|
||||
/// The palette in use: never `System`.
|
||||
pub fn active_mode() -> ThemeMode {
|
||||
ThemeMode::ALL.get(usize::from(ACTIVE_THEME.load(Ordering::Relaxed))).copied().unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Whether the active palette is a light one (Light or Catppuccin Latte).
|
||||
pub fn is_light() -> bool {
|
||||
LIGHT_THEME.load(Ordering::Relaxed)
|
||||
let mode = active_mode();
|
||||
mode.flavor().map_or(mode == ThemeMode::Light, |f| !f.is_dark())
|
||||
}
|
||||
|
||||
/// Resolve each frame from the integration's current OS appearance. Unknown uses Dark.
|
||||
pub fn wants_light(ctx: &egui::Context, mode: ThemeMode) -> bool {
|
||||
pub fn resolve(ctx: &egui::Context, mode: ThemeMode) -> ThemeMode {
|
||||
match mode {
|
||||
ThemeMode::Light => true,
|
||||
ThemeMode::Dark => false,
|
||||
ThemeMode::System => ctx.system_theme() == Some(egui::Theme::Light),
|
||||
ThemeMode::System if ctx.system_theme() == Some(egui::Theme::Light) => ThemeMode::Light,
|
||||
ThemeMode::System => ThemeMode::Dark,
|
||||
_ => mode,
|
||||
}
|
||||
}
|
||||
|
||||
/// A Catppuccin flavour on SoundCraft's token set (accent Mauve, selection Blue).
|
||||
fn catppuccin(f: Flavor) -> Tokens {
|
||||
let p = f.palette();
|
||||
let dark = f.is_dark();
|
||||
let a = |c: Color32, alpha: u8| Color32::from_rgba_unmultiplied(c.r(), c.g(), c.b(), alpha);
|
||||
let tint = |c: Color32, t: f32| p.base.lerp_to_gamma(c, t);
|
||||
Tokens {
|
||||
window_bg: p.base,
|
||||
panel_bg: p.base,
|
||||
panel_bg2: p.surface0,
|
||||
toolbar_bg: p.mantle,
|
||||
toolbar_group: p.crust,
|
||||
border: if dark { p.crust } else { p.surface1 },
|
||||
border_light: p.surface1,
|
||||
text: p.text,
|
||||
text_dim: p.subtext0,
|
||||
text_dark: if dark { p.crust } else { p.base },
|
||||
header_text: p.subtext1,
|
||||
counter_bg: p.crust,
|
||||
counter_text: p.green,
|
||||
counter_label: p.subtext1,
|
||||
accent: p.mauve,
|
||||
accent_dark: tint(p.mauve, 0.6),
|
||||
mode_on: p.green,
|
||||
mode_on_text: p.crust,
|
||||
mode_off_text: p.green,
|
||||
button: p.surface0,
|
||||
button_hi: p.surface1,
|
||||
button_border: p.surface2,
|
||||
name_field: if dark { p.text } else { p.base },
|
||||
name_field_sel: p.rosewater,
|
||||
ruler_bg: p.mantle,
|
||||
ruler_label_bg: p.mantle,
|
||||
ruler_text: p.subtext0,
|
||||
ruler_tick: p.overlay0,
|
||||
tempo_ruler: tint(p.green, 0.5),
|
||||
meter_ruler: tint(p.sapphire, 0.5),
|
||||
marker_ruler: p.surface0,
|
||||
playlist_bg: p.base,
|
||||
playlist_alt: p.mantle,
|
||||
grid_line: p.surface0,
|
||||
bar_line: p.surface1,
|
||||
selection: a(p.blue, 110),
|
||||
playhead: p.red,
|
||||
insertion: p.text,
|
||||
solo: p.yellow,
|
||||
mute: p.peach,
|
||||
rec: p.red,
|
||||
input: p.green,
|
||||
auto_read: p.green,
|
||||
auto_write: p.red,
|
||||
auto_touch: p.peach,
|
||||
auto_latch: p.mauve,
|
||||
meter_green: p.green,
|
||||
meter_yellow: p.yellow,
|
||||
meter_red: p.red,
|
||||
fader_track: p.crust,
|
||||
strip_bg: p.mantle,
|
||||
strip_section: p.base,
|
||||
slot_bg: p.crust,
|
||||
automation_line: p.text,
|
||||
menu_bar: p.mantle,
|
||||
group_border: if dark { p.crust } else { p.surface1 },
|
||||
mode_off: p.surface0,
|
||||
counter_off: p.surface1,
|
||||
counter_border: p.surface1,
|
||||
counter_rule: p.surface0,
|
||||
tool_bracket_off: p.surface1,
|
||||
row_selected: tint(p.blue, 0.35),
|
||||
visible_dot: p.overlay1,
|
||||
big_counter_bg: p.crust,
|
||||
header_selected: p.surface0,
|
||||
strip_selected: p.surface0,
|
||||
marker_text: p.text,
|
||||
playlist_lane: p.mantle,
|
||||
universe_bg: p.crust,
|
||||
universe_view: p.text,
|
||||
meter_bg: p.crust,
|
||||
meter_clip_off: tint(p.red, 0.3),
|
||||
knob_bg: p.surface0,
|
||||
knob_ring: p.overlay0,
|
||||
knob_pointer: p.text,
|
||||
insert_on: tint(p.blue, 0.3),
|
||||
insert_bypass: tint(p.yellow, 0.3),
|
||||
send_on: tint(p.green, 0.3),
|
||||
slot_border: p.surface1,
|
||||
section_label: p.subtext0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,11 +518,12 @@ pub fn mono(size: f32) -> FontId {
|
||||
FontId::new(size, FontFamily::Monospace)
|
||||
}
|
||||
|
||||
/// Make `light` (or dark) the active palette and apply its visuals. Call only when it changes.
|
||||
pub fn apply(ctx: &egui::Context, light: bool) {
|
||||
LIGHT_THEME.store(light, Ordering::Relaxed);
|
||||
/// Make `mode` (already resolved, not `System`) the active palette and apply its visuals. Call only when it changes.
|
||||
pub fn apply(ctx: &egui::Context, mode: ThemeMode) {
|
||||
let index = ThemeMode::ALL.iter().position(|m| *m == mode).unwrap_or_default();
|
||||
ACTIVE_THEME.store(u8::try_from(index).unwrap_or_default(), Ordering::Relaxed);
|
||||
let t = Tokens::current();
|
||||
let mut v = if light { egui::Visuals::light() } else { egui::Visuals::dark() };
|
||||
let mut v = if is_light() { egui::Visuals::light() } else { egui::Visuals::dark() };
|
||||
v.panel_fill = t.panel_bg;
|
||||
v.window_fill = t.panel_bg2;
|
||||
v.extreme_bg_color = t.slot_bg;
|
||||
@@ -436,6 +576,18 @@ mod tests {
|
||||
assert_eq!(ThemeMode::parse("sepia"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn catppuccin_themes_use_the_flavour_palette() {
|
||||
for mode in ThemeMode::ALL {
|
||||
let Some(f) = mode.flavor() else { continue };
|
||||
let (t, p) = (Tokens::for_mode(mode), f.palette());
|
||||
assert_eq!((t.window_bg, t.panel_bg, t.text, t.accent), (p.base, p.base, p.text, p.mauve), "{}", mode.id());
|
||||
}
|
||||
assert_eq!(ThemeMode::ALL.iter().filter(|m| m.flavor().is_some()).count(), Flavor::ALL.len());
|
||||
assert_eq!(ThemeMode::parse("catppuccinMocha"), Some(ThemeMode::CatppuccinMocha));
|
||||
assert_eq!(ThemeMode::id_list().split('|').count(), ThemeMode::ALL.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn theme_command_sets_and_reports_the_mode() {
|
||||
let mut app = SoundApp::new(soundcraft_engine::Engine::default(), None, Services::default());
|
||||
|
||||
@@ -405,7 +405,7 @@ mod selector_visual_regressions {
|
||||
move |ui, regions: &mut serde_json::Map<String, serde_json::Value>| {
|
||||
if !ready {
|
||||
crate::fonts::install(ui.ctx());
|
||||
crate::theme::apply(ui.ctx(), false);
|
||||
crate::theme::apply(ui.ctx(), crate::theme::ThemeMode::Dark);
|
||||
ready = true;
|
||||
return;
|
||||
}
|
||||
@@ -458,7 +458,7 @@ mod selector_visual_regressions {
|
||||
for scale in [1.0, 1.5, 2.0] {
|
||||
let ctx = egui::Context::default();
|
||||
crate::fonts::install(&ctx);
|
||||
crate::theme::apply(&ctx, false);
|
||||
crate::theme::apply(&ctx, crate::theme::ThemeMode::Dark);
|
||||
let mut app = mixer_app(narrow, mode);
|
||||
let mut output = ctx.run_ui(scaled_input(vec2(320.0, 640.0), scale), |ui| crate::mix_window::show(&mut app, ui));
|
||||
output.textures_delta.clear();
|
||||
@@ -505,7 +505,7 @@ mod selector_visual_regressions {
|
||||
move |ui, app: &mut crate::SoundApp| {
|
||||
if !ready {
|
||||
crate::fonts::install(ui.ctx());
|
||||
crate::theme::apply(ui.ctx(), false);
|
||||
crate::theme::apply(ui.ctx(), crate::theme::ThemeMode::Dark);
|
||||
ready = true;
|
||||
return;
|
||||
}
|
||||
@@ -553,7 +553,7 @@ mod selector_visual_regressions {
|
||||
for scale in [1.0, 1.5, 2.0] {
|
||||
let ctx = egui::Context::default();
|
||||
crate::fonts::install(&ctx);
|
||||
crate::theme::apply(&ctx, false);
|
||||
crate::theme::apply(&ctx, crate::theme::ThemeMode::Dark);
|
||||
let mut rect = Rect::NOTHING;
|
||||
let mut output = ctx.run_ui(scaled_input(vec2(320.0, 120.0), scale), |ui| {
|
||||
rect = selector_box(ui, width, 16.0, label, Tokens::current().text).rect;
|
||||
|
||||
@@ -180,7 +180,7 @@ fn shared_controls_visuals() {
|
||||
}
|
||||
let mut controls = Harness::builder().with_size(vec2(340.0, 150.0)).with_pixels_per_point(scale).wgpu().build_ui_state(
|
||||
|ui, rects: &mut Vec<egui::Rect>| {
|
||||
theme::apply(ui.ctx(), false);
|
||||
theme::apply(ui.ctx(), theme::ThemeMode::Dark);
|
||||
rects.clear();
|
||||
for enabled in [true, false] {
|
||||
ui.add_enabled_ui(enabled, |ui| {
|
||||
|
||||
@@ -43,7 +43,7 @@ fn shared_panels_and_controls_follow_manual_and_live_system_appearance() {
|
||||
}
|
||||
}
|
||||
let ctx = egui::Context::default();
|
||||
theme::apply(&ctx, light);
|
||||
theme::apply(&ctx, if light { theme::ThemeMode::Light } else { theme::ThemeMode::Dark });
|
||||
let tokens = theme::Tokens::current();
|
||||
let mut output = ctx.run_ui(egui::RawInput::default(), |ui| {
|
||||
widgets::icon_button(ui, vec2(38.0, 28.0), "loop", true, "Loop playback");
|
||||
@@ -58,7 +58,7 @@ fn shared_panels_and_controls_follow_manual_and_live_system_appearance() {
|
||||
if let Some(directory) = std::env::var_os("CRAFT_UI_THEME_SHOTS").map(std::path::PathBuf::from) {
|
||||
let mut controls = Harness::builder().with_size(vec2(340.0, 150.0)).with_pixels_per_point(scale).wgpu().build_ui_state(
|
||||
move |ui, _: &mut ()| {
|
||||
theme::apply(ui.ctx(), light);
|
||||
theme::apply(ui.ctx(), if light { theme::ThemeMode::Light } else { theme::ThemeMode::Dark });
|
||||
for enabled in [true, false] {
|
||||
ui.add_enabled_ui(enabled, |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
ArtCraft brand assets: license
|
||||
|
||||
The ArtCraft name, wordmark and mark (the "ArtCraft Marks"), including every file in this
|
||||
directory in every color, size and format, are owned by the ArtCraft Team. They are trademarks
|
||||
and are NOT open source. They are not covered by SoundCraft's MIT OR Apache-2.0 license, and nothing in
|
||||
that license, in NOTICE or in any other file of this repository grants any right to them.
|
||||
|
||||
Permission
|
||||
|
||||
The ArtCraft Team grants a limited, non-exclusive, non-transferable, revocable, royalty-free
|
||||
permission to use the ArtCraft Marks only:
|
||||
|
||||
1. as part of copies of this repository; and
|
||||
2. within SoundCraft itself, its documentation and its official builds, to identify SoundCraft as made
|
||||
by the ArtCraft team and community and to link to getartcraft.com and its community.
|
||||
|
||||
Conditions
|
||||
|
||||
The permission holds only while every one of these is true:
|
||||
|
||||
- The marks are used exactly as supplied in this directory. Do not redraw, recolor, crop,
|
||||
stretch, rotate, animate, outline or add effects to them, extract parts of them, or combine
|
||||
them with any other name, mark or artwork.
|
||||
- They are used only in the context of SoundCraft, and only to say that the ArtCraft team makes it.
|
||||
They must never suggest that the ArtCraft Team made, sponsors, endorses, certifies or supports
|
||||
any other product, service, fork, modified version, plug-in, organization or person.
|
||||
- Neither the marks nor the ArtCraft name appear in the name, logo, icon, domain, social media
|
||||
handle, app-store listing, advertising or marketing of anything other than SoundCraft.
|
||||
|
||||
Forks and modified versions
|
||||
|
||||
If you distribute or publish a modified version of SoundCraft, or any work derived from it, you must
|
||||
remove the ArtCraft Marks from it (or replace them with your own) and must not call it ArtCraft or
|
||||
present it as an ArtCraft product. You may say, in plain text, that your work is based on SoundCraft by
|
||||
the ArtCraft team. A fork kept only to propose changes back to this repository may keep the marks
|
||||
unchanged.
|
||||
|
||||
Everything else
|
||||
|
||||
Any use not expressly permitted here needs prior written permission from the ArtCraft Team
|
||||
(https://getartcraft.com/). The permission ends automatically for anyone who breaks these terms.
|
||||
All other rights are reserved.
|
||||
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 26 KiB |
@@ -1,4 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-10 -19.42 136.34 136.34" role="img" aria-label="ArtCraft">
|
||||
<title>ArtCraft</title>
|
||||
<path fill="#0b0b0c" d="M104.28,49.49L81.55,0h-31.23l-3.17,4.76L14.75,53.63,0,75.85l21.55,21.55,63.79-36.94,16.99,37.04,14.01-21.74-12.06-26.27ZM32.89,65.66l32.42-48.87,10.91,23.77-43.32,25.09Z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 341 B |
|
Before Width: | Height: | Size: 24 KiB |
@@ -1,4 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-10 -19.42 136.34 136.34" role="img" aria-label="ArtCraft">
|
||||
<title>ArtCraft</title>
|
||||
<path fill="#4e7bfb" d="M104.28,49.49L81.55,0h-31.23l-3.17,4.76L14.75,53.63,0,75.85l21.55,21.55,63.79-36.94,16.99,37.04,14.01-21.74-12.06-26.27ZM32.89,65.66l32.42-48.87,10.91,23.77-43.32,25.09Z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 341 B |
@@ -26,10 +26,10 @@
|
||||
<launchable type="desktop-id">ai.storyteller.soundcraft.desktop</launchable>
|
||||
<icon type="stock">ai.storyteller.soundcraft</icon>
|
||||
<!-- Only url types known to appstream 0.15 (Ubuntu 22.04, where CI validates): no vcs-browser. -->
|
||||
<url type="homepage">https://getartcraft.com/apps/soundcraft</url>
|
||||
<url type="homepage">https://github.com/storytold/soundcraft</url>
|
||||
<url type="bugtracker">https://github.com/storytold/soundcraft/issues</url>
|
||||
<url type="help">https://github.com/storytold/soundcraft</url>
|
||||
<url type="contact">https://discord.gg/artcraft</url>
|
||||
<url type="contact">https://github.com/storytold/soundcraft/issues</url>
|
||||
<categories>
|
||||
<category>AudioVideo</category>
|
||||
<category>Audio</category>
|
||||
|
||||
@@ -14,7 +14,7 @@ section: sound
|
||||
priority: optional
|
||||
maintainer: ${SOUNDCRAFT_MAINTAINER}
|
||||
vendor: Learning Machines LLC
|
||||
homepage: https://getartcraft.com/apps/soundcraft
|
||||
homepage: https://github.com/storytold/soundcraft
|
||||
license: MIT OR Apache-2.0
|
||||
description: |-
|
||||
Open-source, native digital audio workstation. Record, edit and mix
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
|
||||
<Icon Id="SoundcraftIcon.ico" SourceFile="$(var.IconPath)" />
|
||||
<Property Id="ARPPRODUCTICON" Value="SoundcraftIcon.ico" />
|
||||
<Property Id="ARPURLINFOABOUT" Value="https://getartcraft.com/apps/soundcraft" />
|
||||
<Property Id="ARPURLUPDATEINFO" Value="https://getartcraft.com/apps/soundcraft" />
|
||||
<Property Id="ARPHELPLINK" Value="https://discord.gg/artcraft" />
|
||||
<Property Id="ARPURLINFOABOUT" Value="https://github.com/storytold/soundcraft" />
|
||||
<Property Id="ARPURLUPDATEINFO" Value="https://github.com/storytold/soundcraft" />
|
||||
<Property Id="ARPHELPLINK" Value="https://github.com/storytold/soundcraft/issues" />
|
||||
|
||||
<StandardDirectory Id="ProgramFiles6432Folder">
|
||||
<Directory Id="INSTALLFOLDER" Name="SoundCraft" />
|
||||
|
||||