GarageJam 8.0.1
Multitrack music studio for GNOME, written in Python 3 with GTK 4, libadwaita and GStreamer (including GStreamer Editing Services for the timeline). Projects are saved in the open GJXML format.
pydoc garagejam. Version 8.0.1 specifics beyond the 8.0 README were not found.| License | GPL-3.0 |
| Language | Python 3 |
| Toolkit | GTK ≥ 4.12, libadwaita ≥ 1.5, GStreamer, GStreamer Editing Services |
| Homepage | www.garagejam.org |
| Repository | github.com/oleaamot-dev/music |
| Project file | .gjxml (GJXML 1.0) |
Package overview
The garagejam package separates the data model from the audio engine and the UI. The model has no GTK dependency, so it can be tested on its own.
| Module | Brief description |
|---|---|
| garagejam.project | Model (Project, Track, Clip) and GJXML read/write. |
| garagejam.engine | GES timeline mirror, transport, metering, recording, export, waveform peaks. |
| garagejam.timeline | Arrange view: Cairo drawing, drag, trim and drop. |
| garagejam.trackheader | Per-track controls. |
| garagejam.window | Main window, actions and dialogs. |
| garagejam.app | Adw.Application subclass and CSS. |
garagejam.app ──► garagejam.window ──► garagejam.timeline
│ garagejam.trackheader
▼
garagejam.engine ──► garagejam.project (model)
Dependency direction is illustrative, based on the documented responsibilities of each module.
Module garagejam.project
Holds the in-memory model of a session and its serialisation to GJXML 1.0. Times are in seconds. Loading ignores unknown elements and attributes and clamps out-of-range values. Saving is atomic.
class Project
A session: global timing, metadata and an ordered list of tracks. Maps to the <project> element.
| Attributes (from GJXML) | ||
|---|---|---|
| str | name from name= | Project name. Also names the recordings folder. |
| float | tempo | Beats per minute. Example file uses 96. |
| int | beats_per_bar | Numerator of the time signature (beats-per-bar). |
| int | beat_unit | Denominator of the time signature (beat-unit). |
| int | sample_rate | Sample rate in Hz (sample-rate), e.g. 48000. |
| dict | metadata | Free-form tags such as artist. Written as tags on Ogg export. |
| list[Track] | tracks | Ordered tracks. |
Python attribute names are inferred by snake-casing the XML attribute names.
class Track
One lane of the arrange view. Maps to <track>.
| Attributes (from GJXML) | ||
|---|---|---|
| str | id | Stable identifier, e.g. t1. |
| str | name | Display name. |
| str | color | Hex colour, e.g. #e66100. |
| float | volume | Linear gain. The UI shows it in dB. |
| float | pan | Stereo position. 0 is centre. |
| bool | mute | Mute flag. |
| bool | solo | Solo flag. |
| bool | armed | Record-arm flag. |
| list[Clip] | clips | Clips on this track. Overlaps on one track are refused. |
class Clip
A region of an audio file placed on a track. Maps to <clip>.
| Attributes (from GJXML) | ||
|---|---|---|
| str | id | Identifier, e.g. c1. |
| str | name | Display name. |
| str | src | Audio file path. Relative to the project file when the audio lives beside it. |
| float | start | Position on the timeline, in seconds. Drags snap to half-beats unless Shift is held. |
| float | inpoint | Offset into the source file, in seconds. Changed by trimming the left edge. |
| float | duration | Length in seconds. Changed by trimming the right edge. |
| float | gain | Linear multiplier applied on top of the track volume. |
GJXML read / write inferred
Names and signatures are placeholders. The module is documented to read and write GJXML, but the exact entry points were not available.
- Load behaviour
- Unknown elements and attributes are ignored. Out-of-range values are clamped.
- Save behaviour
- Atomic. Audio paths are stored relative to the project when the files sit beside it.
Module garagejam.engine
Audio engine. Mirrors the model into a GStreamer Editing Services (GES) timeline and owns playback, recording, metering and export.
Responsibilities
| Area | Behaviour |
|---|---|
| Transport | Play, pause, stop, seek, return to start. |
| Metering | Live input meter while recording, master L/R meters during playback. |
| Recording | Overdub: the timeline plays while the armed track records. The take is aligned to the first captured buffer and starts where recording began. If the armed track already has audio there, the take goes on a new track directly below. Files go to <project>-audio/, or ~/Music/GarageJam/<name>/ for an unsaved project. |
| Export | Mix down to WAV or Ogg Vorbis. Project metadata is written as tags (Ogg). |
| Waveforms | Computes peak data used by the timeline to draw clips. |
| Devices | Output sink and input source are overridable, see environment variables. |
fakesink and audiotestsrc, so no sound card is required.Module garagejam.timeline
The arrange view, drawn with Cairo.
- Ruler in bars, beat grid, waveforms, playhead and autoscroll.
- Zoom with Ctrl+scroll, Ctrl+plus and Ctrl+minus, plus zoom-to-fit.
- Drag clips in time and between tracks. Snaps to half-beats, hold Shift to move freely.
- Trim either clip edge. Split at the playhead, duplicate, delete.
- Import audio by dropping files onto a lane.
Module garagejam.trackheader
Per-track controls shown left of each lane: name, colour, mute, solo, record-arm, pan, volume with a dB readout, reorder and delete.
Module garagejam.window
The main window. Registers the application actions, shows file dialogs (open, save, import, export), the project settings dialog (tempo, beats per bar, sample rate, metadata), the unsaved-changes prompt and the keyboard shortcuts window.
Module garagejam.app
Defines the Adw.Application subclass that starts the program, loads the application CSS and follows the system dark-mode setting. A .gjxml path given on the command line is opened at startup.
GJXML 1.0 file format
Root element <gjxml version="1.0" generator="GarageJam 8.0.0"> containing one <project>.
<?xml version="1.0" encoding="UTF-8"?>
<gjxml version="1.0" generator="GarageJam 8.0.0">
<project name="Demo Jam" tempo="96" beats-per-bar="4" beat-unit="4" sample-rate="48000">
<metadata>
<artist>Ole Kristian Aamot</artist>
</metadata>
<tracks>
<track id="t1" name="Drums" color="#e66100" volume="0.9" pan="0"
mute="false" solo="false" armed="false">
<clip id="c1" name="Groove" src="Demo Jam-audio/take-1.wav"
start="0" inpoint="0" duration="5" gain="1"/>
</track>
</tracks>
</project>
</gjxml>
| Element | Attributes |
|---|---|
| gjxml | version, generator |
| project | name, tempo, beats-per-bar, beat-unit, sample-rate |
| metadata | child elements such as artist |
| track | id, name, color, volume, pan, mute, solo, armed |
| clip | id, name, src, start, inpoint, duration, gain |
Times are seconds. inpoint is the offset into the source file. gain is a linear multiplier on top of the track volume. Unknown elements and attributes are ignored on load, and out-of-range values are clamped.
Actions & shortcuts
| Key | Action |
|---|---|
Space | Play / pause |
R | Record / stop recording |
Esc | Stop (press twice to return to start) |
Home | Go to start |
S | Split selected clip at playhead |
Delete | Delete selected clip |
Ctrl+D | Duplicate clip |
Ctrl+T | Add track |
Ctrl+I | Import audio |
Ctrl+E | Export mix |
Ctrl+S / Ctrl+O / Ctrl+N | Save / open / new |
Environment variables
| Variable | Default | Description |
|---|---|---|
GARAGEJAM_AUDIO_SINK | autoaudiosink | GStreamer element used for playback, e.g. pulsesink. |
GARAGEJAM_AUDIO_SRC | autoaudiosrc | GStreamer element used for recording, e.g. pipewiresrc. |
Command line
./bin/garagejam # run from the source tree ./bin/garagejam song.gjxml # open a project pip install --user . && garagejam
To open .gjxml files from Files, install data/org.garagejam.GarageJam.desktop into ~/.local/share/applications/ and register the MIME type:
xdg-mime install data/org.garagejam.GarageJam.mime.xml
Dependencies
GTK ≥ 4.12 and libadwaita ≥ 1.5.
Fedora
sudo dnf install python3-gobject python3-cairo gtk4 libadwaita \
gstreamer1 gstreamer1-plugins-base gstreamer1-plugins-good \
gstreamer1-plugins-bad-free gst-editing-services
Debian / Ubuntu
sudo apt install python3-gi python3-gi-cairo gir1.2-gtk-4.0 gir1.2-adw-1 \
gir1.2-gstreamer-1.0 gir1.2-gst-plugins-base-1.0 gir1.2-ges-1.0 \
gstreamer1.0-plugins-base gstreamer1.0-plugins-good
Tests
python3 -m pytest
Covers the model and the headless engine. No sound card is needed.
File list
| File | Description |
|---|---|
| garagejam/project.py | Model and GJXML read/write |
| garagejam/engine.py | GES timeline mirror, transport, metering, recording, export, peaks |
| garagejam/timeline.py | Arrange view |
| garagejam/trackheader.py | Per-track controls |
| garagejam/window.py | Main window, actions, dialogs |
| garagejam/app.py | Adw.Application, CSS |
| bin/garagejam | Launcher script |
| data/ | Desktop entry, MIME definition |
| tests/ | pytest model and engine tests |
| pyproject.toml | Packaging |