Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# AGENTS.md

Guidance for AI coding agents (GitHub Copilot CLI and similar) working in this repository.

## Project classification

**Henkilökohtainen projekti.** Sijaitsee polussa `C:\Repos\Omat\RASP`, ei Zuren työprojekti. Zuren default-käytäntöjä (Zure-group org, AI-development-defaults wiki, asiakas-NDA) ei sovelleta.

- GitHub-org: `Zesseth` (käyttäjän henkilökohtainen)
- Lisenssi: ks. `LICENSE` (public repo)
- Kieli: kaikki koodi, kommentit, commitit, issuet, PR:t ja dokumentaatio **englanniksi** (public repo). Tämä AGENTS.md on poikkeus — agent-ohjeet suomeksi.

## Project Overview

RASP (Reaper Archiving System Project) is a Lua ReaScript plugin for the Reaper DAW. It provides automatic project versioning with full media backup and local archiving. No build step — Lua is interpreted directly by Reaper.

**Installation**: Copy the `RASP/` folder to Reaper's `Scripts/` directory, then load `RASP.lua` via Reaper's Actions menu.

## Architecture

```
RASP.lua # Entry point: loads modules, runs reaper.defer() main loop
modules/
config.lua # Settings persistence via Reaper's ExtState API
gui.lua # Dockable UI using Reaper's gfx rendering API
versioning.lua # Version number parsing, next-version calculation, file copying
file_operations.lua # File/directory ops for Linux (cp, rm via os.execute)
archiving.lua # Find/move old versioned folders to archive destination
```

**Data flow**: `RASP.lua` polls GUI state each defer cycle → dispatches to versioning or archiving modules → those call `file_operations` for disk work → `config` is read/written at any point.

**Settings persistence**: All user settings are stored in Reaper's ExtState under section `"RASP"`. There are no config files on disk.

## Key Design Patterns

- **Main loop**: Reaper plugins use `reaper.defer()` for a non-blocking event loop. The loop is in `RASP.lua` and re-registers itself each cycle.
- **File ops (Linux only)**: `file_operations.lua` provides a unified API using `cp -r` and `rm -rf` via `os.execute`. Windows is not supported — archiving requires shell commands unavailable on Windows. Always go through this module for file/directory operations.
- **Two versioning modes**:
- *Native*: Opens Reaper's built-in Save As dialog (user controls the path).
- *Auto*: Fully automated — calls `reaper.Main_SaveProjectEx(0, path, 3)` (flag 3 = flag 1 "create subdirectory" + flag 2 "copy all media") which saves the `.rpp`, copies all media into the new directory, and rewrites internal path references atomically. This is equivalent to Save As with "Copy all media into project directory" ticked. Do NOT replace this with manual file copying (`cp`) — that approach cannot rewrite `.rpp` internal references and will produce a broken project.
- **Safety**: Auto mode verifies the `.rpp` file exists after saving. Archiving never touches the currently open version. Destructive operations always show a confirmation dialog.
- **Version folder naming**: Projects are versioned by suffix on the folder name using a configurable prefix (default `_v`), digit count (default 3), and start number (default 1), e.g. `MyProject_v001/`.

## Reaper API Conventions

- `reaper.*` — core Reaper API functions
- `gfx.*` — immediate-mode graphics for the UI (gui.lua)
- `reaper.GetExtState` / `reaper.SetExtState` — persistent key-value storage
- `reaper.ShowMessageBox` — confirmation dialogs
- `reaper.GetProjectPath` / `reaper.GetProjectName` — current open project info

## Platform

- **Tuettu:** Linux (Debian), testattu Reaper v7.x:llä. Vaatii Reaper v6.0+.
- **Ei tuettu:** Windows — archiving käyttää `cp`/`rm` shell-komentoja joita ei ole Windowsissa.

## Current Development State

- **`master`** — stable release.
- **`V0.1_features`** — active branch, PR #21. Toteuttaa sekä v0.1- että v0.2-roadmap-featuret (UI, auto-versioning, increment, archiving, native/auto-tila, conflict handling). Issue #29 toteaa featurejen olevan tiedostetusti sekaisin samassa branchissa — molemmat mergetään masteriin yhdessä v0.2:na.
- **`V0.3_features`** — Backblaze B2 cloud archiving, ei aloitettu.

## Agent workflow säännöt

- **Git:**
- `git add` (staging) ok automaattisesti.
- `git commit` vasta käyttäjän eksplisiittisen vahvistuksen jälkeen — odota että käyttäjä on katsonut `git diff --staged`.
- `git push` vain eksplisiittisestä pyynnöstä.
- **Ei AI-tekijyysmerkintöjä** commit-viesteihin, PR-kuvauksiin tai tuotettuun sisältöön. Kiellettyjä: `Co-authored-by: Copilot`, `Generated with ...`, `🤖 Generated with ...` ja vastaavat. Jos commit-pohja ehdottaa niitä, poista ennen commitia.
- **Destruktiiviset operaatiot** (poisto, force-push, hard reset remoteen menossa, salaisuuksien paljastaminen) vaativat aina eksplisiittisen luvan.
- **Konfliktit:** kun mergetään masteria, tarkista että roadmap ja dokumentaatio ovat linjassa toteutettujen featurejen kanssa.
68 changes: 64 additions & 4 deletions RASP.lua
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ local config = require("config")
local gui = require("gui")
local versioning = require("versioning")
local file_ops = require("file_operations")
local archiving = require("archiving")

-- Initialize configuration
config.init()
Expand All @@ -44,14 +45,73 @@ local function main()
-- Handle GUI events
if gui.should_create_version then
gui.should_create_version = false
gui.set_status("Creating new version...")

local success, result = versioning.create_new_version()
local mode = gui.get_versioning_mode()
if mode == "auto" then
gui.set_status("Creating new version (auto)...")
else
gui.set_status("Opening Save As dialog...")
end

local success, result = versioning.create_new_version(mode)
if success then
gui.set_status("Version created: " .. result)
if mode == "native" then
gui.set_status("Save As dialog opened")
else
gui.set_status("Version created successfully")
end
gui.update_project_info()
else
gui.set_status("Error: " .. result)
gui.set_status("Error: " .. (result or "Unknown error"), true)
end
end

-- Handle archive browsing
if gui.should_browse_archive_dest then
gui.should_browse_archive_dest = false

-- Try to use JS extension for folder browser if available
local has_js = reaper.JS_Dialog_BrowseForFolder and true or false
local selected_path

if has_js then
local retval
retval, selected_path = reaper.JS_Dialog_BrowseForFolder("Select Archive Destination", config.get("archive_destination"))
if retval == 1 and selected_path and selected_path ~= "" then
config.set("archive_destination", selected_path)
gui.update_project_info()
gui.set_status("Archive destination updated")
end
else
-- Fallback to text input dialog
local retval
retval, selected_path = reaper.GetUserInputs("Archive Destination", 1, "Folder path (full path required):", config.get("archive_destination"))
if retval and selected_path ~= "" then
-- Basic validation: check if path looks reasonable
if selected_path:match("[/\\]") or selected_path:len() > 2 then
config.set("archive_destination", selected_path)
gui.update_project_info()
gui.set_status("Archive destination updated")
else
gui.set_status("Invalid path format. Use full folder path.", true)
end
Comment thread
Zesseth marked this conversation as resolved.
end
end
end

-- Handle archiving
if gui.should_archive_now then
gui.should_archive_now = false
gui.set_status("Archiving old versions...")

local archive_dest = config.get("archive_destination")
local versions_to_keep = config.get("versions_to_keep")

local success, result = archiving.archive_versions(archive_dest, versions_to_keep)
if success then
gui.set_status(result)
else
gui.set_status("Error: " .. result, true)
end
end

Expand Down
109 changes: 100 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,24 @@ Reaper Archiving System Project

A Lua plugin for Reaper DAW that provides automatic project versioning with full media backup.

## Features (v0.1)
## Features (v0.2)

- **Dockable UI** - Native Reaper interface
- **Auto-versioning** - Open save as dialog
- **Cross-platform** - Works on Linux (Debian) and Windows
- **Safe Auto-versioning** - Copies entire project with all media files
- **Dual Saving Mode** - Choose between Native (Reaper dialog) or Auto (fully automated)
- **Conflict Handling** - Smart handling when version folder already exists
- **Linux support** - Tested on Debian Linux

## Requirements

### Required
- **Reaper DAW** v6.0 or newer (tested with v7.x)
- **Operating System**: Linux (Debian) or Windows 11 (tested)
- **Operating System**: Linux (Debian)

### Recommended
No extensions or additonal needed.
No extensions or additional software needed.

> **Note:** Windows is not supported. Archiving relies on `cp` and `rm` shell commands which are not available on Windows.

## Project Structure

Expand All @@ -37,28 +41,114 @@ RASP/
1. Copy `RASP/` folder to Reaper's `Scripts/` directory
2. In Reaper: Actions → Load ReaScript → Select `RASP.lua`
3. Run the script to open RASP window
4. Click "Create New Version" to version your project
4. Select saving method (Native/Auto)
5. Click "Create New Version" to version your project

See [installation guide](docs/installation.md) for detailed instructions.

## Version Format

```
MyProject/MyProject.rpp → Original
MyProject/MyProject.rpp → Original
MyProject_v001/MyProject_v001.rpp → Version 1
MyProject_v002/MyProject_v002.rpp → Version 2
```

---

## Versioning Guide

### Saving Method Selection

RASP provides two methods for creating new versions. You can switch between them using the **Native / Auto** toggle in the Versioning section.

<!-- TODO: Add screenshot of versioning section with switch -->

### Native Mode

Opens Reaper's built-in "Save As" dialog.

**When to use:**
- You want full control over save location
- You need to manually select which media to copy
- You're familiar with Reaper's "Copy all media" options

**How it works:**
1. Click "Create New Version"
2. Reaper's Save As dialog opens
3. Choose location and enable "Copy all media into project directory"
4. Save

**Console output:**
```
RASP: Opening Save As dialog...
💡 Tip: Enable 'Copy all media into project directory' for safe versioning
```

### Auto Mode (Recommended)

Fully automated versioning that guarantees all media files are copied.

**When to use:**
- You want fast, reliable versioning
- You want to ensure no media references break

**How it works:**
1. Click "Create New Version"
2. RASP automatically:
- Calculates next version number (v001 → v002)
- Creates new folder `ProjectName_v002/`
- Copies ALL project files (audio, MIDI, peaks, etc.)
- Saves project file with new name (Reaper rewrites internal path references)

**Console output (success):**
```
RASP: Creating version _v002...
📁 Target: /home/user/Projects/MySong_v002
✅ RASP: Version created successfully!
📄 Project: MySong_v002.rpp
📂 Location: /home/user/Projects/MySong_v002
```

**Console output (error):**
```
❌ RASP Error: Save failed: project file not found at /home/user/Projects/MySong_v002/MySong_v002.rpp
```
Comment thread
Zesseth marked this conversation as resolved.

### Conflict Handling

If the target version folder already exists, RASP shows a dialog with three options:

| Option | Result |
|--------|--------|
| **Yes** (Increment version) | Skips to the next available version number |
| **No** (Overwrite) | Saves into the existing folder |
| **Cancel** (Do nothing) | Aborts, no changes made |

### Why Auto Mode is Safer

Reaper projects can have media references that are:
- **Absolute paths** - Point to specific locations on disk
- **Relative paths** - Point relative to project file location

When you manually copy/move a project without its media, these references break. RASP's Auto mode:

1. ✅ Copies the **entire project folder** (all files)
2. ✅ Creates a new `.rpp` file with the version name
3. ✅ Reaper rewrites internal path references to match the new location

This ensures your versioned projects are **100% self-contained** and portable.

---

## Roadmap

### Version 0.1 (in progress)
### Version 0.1
- RASP UI / plugin to Reaper
- Auto version from RASP UI
- Increment version number when versioning

### Version 0.2 (planned)
### Version 0.2
- Safe versioning: increment version and save automatically using Reaper's native save
- Native/Auto mode selection (Auto = fully automated, Native = opens Reaper's Save As dialog)
- Conflict handling when version folder already exists (overwrite / increment / do nothing)
Expand All @@ -76,4 +166,5 @@ MyProject_v002/MyProject_v002.rpp → Version 2

### Future
- Additional cloud storage destinations (Amazon S3, Azure Blob Storage, Storj)
- Windows support (no plans currently — archiving requires shell commands unavailable on Windows)

Loading