Skip to content

Commit

Permalink
write the rose release_id to the audio tags too
Browse files Browse the repository at this point in the history
  • Loading branch information
azuline committed Oct 29, 2023
1 parent d34dcde commit 3c0e9da
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 47 deletions.
8 changes: 5 additions & 3 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,11 @@ These UUIDs are persisted to the source files:
- Each release has a `.rose.{uuid}.toml` file, which preserves release-level
state, such as `New`. The UUID is in the filename instead of the file
contents for improved performance: we can collect the UUID via a `readdir`
call instead of an expensive file read.
- Each track has a custom `roseid` tag. This tag is written to the source audio
file.
call instead of an expensive file read. The release UUID is also written to
the nonstandard `rosereleaseid` audio tag for increased robustness to partial
data loss and race conditions.
- Each track has a nonstandard `roseid` audio tag that contains the track UUID.
This tag is written to the source audio file.

Therefore, provided that other programs do not erase the UUID, Rosé will be
able to identify releases and tracks across arbitrarily drastic directory and
Expand Down
82 changes: 43 additions & 39 deletions docs/METADATA_MANAGEMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Rosé manages the following tags:
- Track Number
- Disc Number
- Rosé ID
- Rosé Release ID

Rosé does not care about any other tags and does not do anything with them.

Expand Down Expand Up @@ -205,48 +206,51 @@ from additional fields.

## MP3

| Tag | Field Name | Will Ingest These Fields |
| ------------- | ------------------ | ---------------------------------------------------------------------------------------------------------------------- |
| Release Title | `TALB` | |
| Album Artists | `TPE2` | |
| Release Year | `TDRC` | `TYER` |
| Release Type | `TXXX:RELEASETYPE` | |
| Genre | `TCON` | |
| Label | `TPUB` | |
| Track Title | `TIT2` | |
| Track Artists | `TPE1` | `TPE4` (Remixer), `TCOM` (Composer), `TPE3` (Conductor), `TIPL,IPLS/producer` (producer), `TIPL,IPLS/DJ-mix` (djmixer) |
| Track Number | `TRCK` | |
| Disc Number | `TPOS` | |
| Rose ID | `TXXX:ROSEID` | |
| Tag | Field Name | Will Ingest These Fields |
| --------------- | -------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| Release Title | `TALB` | |
| Album Artists | `TPE2` | |
| Release Year | `TDRC` | `TYER` |
| Release Type | `TXXX:RELEASETYPE` | |
| Genre | `TCON` | |
| Label | `TPUB` | |
| Track Title | `TIT2` | |
| Track Artists | `TPE1` | `TPE4` (Remixer), `TCOM` (Composer), `TPE3` (Conductor), `TIPL,IPLS/producer` (producer), `TIPL,IPLS/DJ-mix` (djmixer) |
| Track Number | `TRCK` | |
| Disc Number | `TPOS` | |
| Rosé ID | `TXXX:ROSEID` | |
| Rosé Release ID | `TXXX:ROSERELEASEID` | |

## MP4

| Tag | Field Name | Will Ingest These Fields |
| ------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Release Title | `\xa9alb` | |
| Album Artists | `aART` | |
| Release Year | `\xa9day` | |
| Release Type | `----:com.apple.iTunes:RELEASETYPE` | |
| Genre | `\xa9gen` | |
| Label | `----:com.apple.iTunes:LABEL` | |
| Track Title | `\xa9nam` | |
| Track Artists | `\xa9ART` | `----:com.apple.iTunes:REMIXER` (Remixer), `\xa9wrt` (Composer), `----:com.apple.iTunes:CONDUCTOR` (Conductor), `----:com.apple.iTunes:PRODUCER` (producer), `----:com.apple.iTunes:DJMIXER` (djmixer) |
| Track Number | `trkn` | |
| Disc Number | `disk` | |
| Rose ID | `----:net.sunsetglow.rose:ID` | |
| Tag | Field Name | Will Ingest These Fields |
| --------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Release Title | `\xa9alb` | |
| Album Artists | `aART` | |
| Release Year | `\xa9day` | |
| Release Type | `----:com.apple.iTunes:RELEASETYPE` | |
| Genre | `\xa9gen` | |
| Label | `----:com.apple.iTunes:LABEL` | |
| Track Title | `\xa9nam` | |
| Track Artists | `\xa9ART` | `----:com.apple.iTunes:REMIXER` (Remixer), `\xa9wrt` (Composer), `----:com.apple.iTunes:CONDUCTOR` (Conductor), `----:com.apple.iTunes:PRODUCER` (producer), `----:com.apple.iTunes:DJMIXER` (djmixer) |
| Track Number | `trkn` | |
| Disc Number | `disk` | |
| Rosé ID | `----:net.sunsetglow.rose:ID` | |
| Rosé Release ID | `----:net.sunsetglow.rose:RELEASEID` | |

## Vorbis

| Tag | Field Name | Will Ingest These Fields |
| ------------- | -------------- | --------------------------------------------------------------------------------------------------------------- |
| Release Title | `album` | |
| Album Artists | `albumartist` | |
| Release Year | `date` | `year` |
| Release Type | `releasetype` | |
| Genre | `genre` | |
| Label | `organization` | `label`, `recordlabel` |
| Track Title | `title` | |
| Track Artists | `artist` | `remixer` (Remixer), `composer` (Composer), `conductor` (Conductor), `producer` (producer), `djmixer` (djmixer) |
| Track Number | `tracknumber` | |
| Disc Number | `discnumber` | |
| Rose ID | `roseid` | |
| Tag | Field Name | Will Ingest These Fields |
| --------------- | --------------- | --------------------------------------------------------------------------------------------------------------- |
| Release Title | `album` | |
| Album Artists | `albumartist` | |
| Release Year | `date` | `year` |
| Release Type | `releasetype` | |
| Genre | `genre` | |
| Label | `organization` | `label`, `recordlabel` |
| Track Title | `title` | |
| Track Artists | `artist` | `remixer` (Remixer), `composer` (Composer), `conductor` (Conductor), `producer` (producer), `djmixer` (djmixer) |
| Track Number | `tracknumber` | |
| Disc Number | `discnumber` | |
| Rosé ID | `roseid` | |
| Rosé Release ID | `rosereleaseid` | |
12 changes: 12 additions & 0 deletions docs/PLAYLISTS_COLLAGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,18 @@ Playlists can also have custom cover art. These are stored as
be located at `Shower.jpg` (or `.png`). The extensions to treat as images are
configurable. See [Configuration](./CONFIGURATION.md).

> [!NOTE]
> When a release or track is deleted from the source directory, Rosé does not
> autoremove that release/track from the collages and playlists that it belongs
> to. Rosé instead flags the release/track as "missing," which prevents it from
> appearing in the virtual filesystem. If the release/track is re-added to the
> source directory, Rosé will remove the missing flag, and the release/track
> will "regain" its lost position in the collage/playlist.
>
> We do this because we do not know if a missing release or a missing track is
> transient or not. For example, a file may be deleted by a tool like syncthing
> only to be readded later.
# Operations

However, working with this file directly is quite annoying, so Rosé allows you
Expand Down
11 changes: 8 additions & 3 deletions rose/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -812,13 +812,18 @@ def _update_cache_for_releases_executor(
# so, since this occurs once over the lifetime of the track's existence in Rose. We
# optimize this function because it is called repeatedly upon every metadata edit, but
# in this case, we skip this code path once an ID is generated.
#
# We also write the release ID to the tags. This is not needed in normal operations
# (since we have .rose.{uuid}.toml!), but provides a layer of defense in situations like
# a directory being written file-by-file and being processed in a half-written state.
track_id = tags.id
if not track_id:
if not track_id or not tags.release_id:
with lock(c, release_lock_name(release.id)):
track_id = str(uuid6.uuid7())
tags.id = track_id
tags.id = tags.id or str(uuid6.uuid7())
tags.release_id = release.id
tags.flush()
# And refresh the mtime because we've just written to the file.
track_id = tags.id
track_mtime = str(os.stat(f).st_mtime)

# And now create the cached track.
Expand Down
Loading

0 comments on commit 3c0e9da

Please sign in to comment.