diff --git a/README.md b/README.md index 0627b81..129f0d6 100644 --- a/README.md +++ b/README.md @@ -53,14 +53,14 @@ virtual/ │ │   ├── 02. BLACKPINK - BOOMBAYAH.opus │ │   └── cover.jpg │   ├── BLACKPINK - 2016. SQUARE TWO - Single [Dance-Pop;K-Pop]/... -│   ├── LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]/... +│   ├── LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]/... │   ├── NewJeans - 2022. Ditto - Single [Contemporary R&B;K-Pop]/... │   └── {NEW} LOOΠΔ - 2017. Kim Lip - Single [Contemporary R&B;Dance-Pop;K-Pop]/... ├── 2. Releases - New/ │   └── {NEW} LOOΠΔ - 2017. Kim Lip - Single [Contemporary R&B;Dance-Pop;K-Pop]/... ├── 3. Releases - Recently Added/ │   ├── [2023-10-25] LOOΠΔ - 2017. Kim Lip - Single [Contemporary R&B;Dance-Pop;K-Pop]/... -│   ├── [2023-10-01] LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]/... +│   ├── [2023-10-01] LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]/... │   └── [2023-02-28] NewJeans - 2022. Ditto - Single [Contemporary R&B;K-Pop]/... │   ├── [2022-08-22] BLACKPINK - 2016. SQUARE TWO - Single [Dance-Pop;K-Pop]/... │   ├── [2022-08-10] BLACKPINK - 2016. SQUARE ONE - Single [Big Room House;Dance-Pop;K-Pop]/... @@ -70,9 +70,9 @@ virtual/ │   │   └── BLACKPINK - 2016. SQUARE TWO - Single [Dance-Pop;K-Pop]/... │   ├── LOOΠΔ/ │   │   ├── {NEW} LOOΠΔ - 2017. Kim Lip - Single [Contemporary R&B;Dance-Pop;K-Pop]/... -│   │   └── LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]/... +│   │   └── LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]/... │   ├── LOOΠΔ ODD EYE CIRCLE/ -│   │   └── LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]/... +│   │   └── LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]/... │   └── NewJeans/ │   └── NewJeans - 2022. Ditto - Single [Contemporary R&B;K-Pop]/... ├── 5. Genres/ @@ -81,20 +81,23 @@ virtual/ │   ├── Contemporary R&B/ │   │   ├── NewJeans - 2022. Ditto - Single [Contemporary R&B;K-Pop]/... │   │   └── {NEW} LOOΠΔ - 2017. Kim Lip - Single [Contemporary R&B;Dance-Pop;K-Pop]/... +│   ├── Future Bass/ +│   │ └── LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]/... │   ├── Dance-Pop/ │   │   ├── BLACKPINK - 2016. SQUARE ONE - Single [Big Room House;Dance-Pop;K-Pop]/... │   │   ├── BLACKPINK - 2016. SQUARE TWO - Single [Dance-Pop;K-Pop]/... +│   │ ├── LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]/... │   │   └── {NEW} LOOΠΔ - 2017. Kim Lip - Single [Contemporary R&B;Dance-Pop;K-Pop]/... │   └── K-Pop/ │   ├── BLACKPINK - 2016. SQUARE ONE - Single [Big Room House;Dance-Pop;K-Pop]/... │   ├── BLACKPINK - 2016. SQUARE TWO - Single [Dance-Pop;K-Pop]/... -│   ├── LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]/... +│   ├── LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]/... │   └── {NEW} LOOΠΔ - 2017. Kim Lip - Single [Contemporary R&B;Dance-Pop;K-Pop]/... ├── 6. Labels/ │   ├── ADOR/ │   │ └── NewJeans - 2022. Ditto - Single [Contemporary R&B;K-Pop]/... │   ├── BlockBerry Creative/ -│   │   ├── LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]/... +│   │   ├── LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]/... │   │ └── {NEW} LOOΠΔ - 2017. Kim Lip - Single [Contemporary R&B;Dance-Pop;K-Pop]/... │   └── YG Entertainment/ │   ├── BLACKPINK - 2016. SQUARE ONE - Single [Big Room House;Dance-Pop;K-Pop]/... @@ -102,7 +105,7 @@ virtual/ ├── 7. Collages/ │   └── Road Trip/ │   ├── 1. BLACKPINK - 2016. SQUARE TWO - Single [Dance-Pop;K-Pop]/... -│   └── 2. LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]/... +│   └── 2. LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]/... └── 8. Playlists/ └── Shower/ ├── 1. LOOΠΔ ODD EYE CIRCLE - Chaotic.opus @@ -111,17 +114,19 @@ virtual/ └── 4. LOOΠΔ - Eclipse.opus ``` -In addition to a flat directory of all releases, Rosé creates -additional directories based on Date Added, Artist, Genre, and Label. Rosé also -provides a few other features designed to keep your music library organized: +In addition to a flat directory of all releases, Rosé creates directories based +on Date Added, Artist, Genre, and Label. Rosé also provides a few other +concepts for organizing your music library: - **Collages:** Collections of releases. - **Playlists:** Collections of tracks. - **New release tracking:** Track new unlistened additions to the library. Rosé's virtual filesystem organizes your music library by the metadata in the -music tags. Thus, the quality of the virtual filesystem depends on the quality -of the tags, Rosé also provides functions for improving the tags of your music +music tags. The quality of the virtual filesystem depends on the quality of the +tags. + +Thus, Rosé also provides functions for improving the tags of your music library. Rosé provides an easy text-based interface for manually modifying metadata, automatic metadata importing from third-party sources, and a rules engine to automatically apply metadata changes based on patterns. @@ -164,18 +169,32 @@ _Demo Video TBD_ # Is Rosé Right for Me? -Rosé also makes some opinionated decisions. Please make sure that Rosé's -opinions are acceptable for you: - -- Rosé modifies files in the source directory, even as early as the first - library scan. All mutations in Rosé are persisted by writing to the source - directory; Rosé maintains no state of its own outside of the source - directory. This makes Rosé work very poorly with torrents. -- Rosé expects all releases to be immediate child directories of the - source directory. And Rosé expects that all tracks belong to a "release" - (meaning an album, single, EP, etc.). This means that loose audio files at - the root of the source directory will be ignored. Thus, Rosé works very - poorly with collections of individual track files. +Rosé expects users to be comfortable with the shell and general software +concepts. Rosé assumes general technical competency in its documentation and +user interface. + +Rosé provides several parts of a complete music system, but not a complete +music system. The user can then construct their own complete music system by +composing multiple programs. For example, Rosé+nnn+mpv. + +Rosé creates the most value when used with a large music library. For small +libraries of several hundred releases or less, Rosé's organization is +unnecessary, as the entire library is easily browsed via a flat view over all +releases. + +Rosé is also a pretty opinionated tool. Rosé makes some assumptions about the +user's music library, which vastly simplify its architecture, but may make Rosé +unsuitable for your music library. These assumptions are: + +1. Rosé modifies files in the source directory, even as early as the first + library scan. All mutations in Rosé are persisted by writing to the source + directory; Rosé maintains no state of its own outside of the source + directory. This makes Rosé work very poorly with torrents. +2. Rosé expects all releases to be immediate child directories of the + source directory. And Rosé expects that all tracks belong to a "release" + (meaning an album, single, EP, etc.). This means that loose audio files at + the root of the source directory will be ignored. Thus, Rosé works very + poorly with collections of individual track files. # Installation @@ -284,7 +303,7 @@ finally (3) play music! $ ls -1 "1. Releases/" 'BLACKPINK - 2016. SQUARE ONE - Single [Big Room House;Dance-Pop;K-Pop]' 'BLACKPINK - 2016. SQUARE TWO - Single [Dance-Pop;K-Pop]' - 'LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]' + 'LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]' 'NewJeans - 2022. Ditto - Single [Contemporary R&B;K-Pop]' '{NEW} LOOΠΔ - 2017. Kim Lip - Single [Contemporary R&B;Dance-Pop;K-Pop]' ``` @@ -295,7 +314,7 @@ finally (3) play music! Mine is `mpv`: ```bash - $ mpv "1. Releases/LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]/04. LOOΠΔ ODD EYE CIRCLE - Chaotic.opus" + $ mpv "1. Releases/LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]/04. LOOΠΔ ODD EYE CIRCLE - Chaotic.opus" (+) Audio --aid=1 'Chaotic' (opus 2ch 48000Hz) File tags: Artist: LOOΠΔ ODD EYE CIRCLE diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index e8d36c7..16ec6a0 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -45,11 +45,12 @@ This has some nice consequences: drifts from source files, that drift can always be automatically resolved simply by rebuilding the cache. -# Stable Release & Track Identifiers +# Release & Track Identifiers -Rosé assigns UUIDs to each release and track in order to identify them across -arbitrarily large metadata changes. These UUIDs are persisted to the source -files. +Rosé assigns a stable UUID to each release and track in order to identify them. +The UUIDs are also used to track membership in collages and playlists. + +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 @@ -58,6 +59,13 @@ files. - Each track has a custom `roseid` tag. 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 +file renames and tag changes. Rosé does not depend on the source directory's +filenames or tags remaining static; the source directory can be freely +modified. The only constraint is that each release must be a directory in the +root of the `music_source_dir`. + # Read Cache Update The read cache update is optimized to minimize the number of disk accesses, as diff --git a/docs/CACHE_MAINTENANCE.md b/docs/CACHE_MAINTENANCE.md index 6f78e9f..0f42776 100644 --- a/docs/CACHE_MAINTENANCE.md +++ b/docs/CACHE_MAINTENANCE.md @@ -1,67 +1,60 @@ # Maintaining the Cache The read cache is a SQLite database that replicates the metadata in -`music_source_dir`. The read cache exists to improve performance: it can be -read from far more performantly than the `music_source_dir` can. +`music_source_dir`. The read cache exists solely to improve performance: it can +be read from far more performantly than the `music_source_dir` can. -The read cache is never written to directly, outside of the `update_cache_*` -functions, which re-read the source files and write their metadata into the -cache. All mutations in the system occur directly to the source files, not to -the read cache. +The read cache does not have any state of its own. _All_ of the data in the read +cache is replicated from the `music_source_dir`. Hence, we never write to the +read cache. Instead, all updates write to the source files, which then triggers +the cache update function. The cache update function updates the cache to match +the source directory's state. -# Cache Drift +> [!NOTE] +> To better understand how the read cache fits into Rosé, we recommend reading +> [Architecture](./ARCHITECTURE.md). -So what's the problem? +# Cache Drift -The read cache has the possibility of _drifting_ from the source directory. For -example, let's say that I move files around in the source directory, modify -tags directly, or even delete a release. After those actions, the read cache -will still reflect the previous state, and thus we say that the cache has -_drifted_. +Assuming you only modify your music library through Rosé, the cache will always +remain up to date, since Rosé triggers a cache update whenever it is aware of +an update to the source directory. -This is problematic because some operations in the virtual filesystem will -begin to fail. For example, if a file is moved in the source directory, and the -virtual filesystem then attempts to read from its previous path, it will hit a -FileNotFound (ENOENT) error. +However, that assumption does not hold. If changes are made directly to the +source directory, and Rosé is not "informed," Rosé's cache will contain the +previous state of the source directory. We call this a _cache drift_. -Thus, after changes to the source directory, we need to update the cache so -that it _synchronizes_ with the source directory. Note that this -synchronization is entirely _one-way_: the source files update the read cache. -The opposite direction never occurs: the read cache never updates the source -files. +This is problematic because Rosé may attempt to read files that no longer exist +or display old metadata. Thus, we should inform Rosé whenever a change is made +to the source directory. # Updating the Cache -The cache can be updated with the command `rose cache update`. By default, this -command only checks files which have changed since the last cache update. It -uses the mtime (last modified) field for this purpose. However, sometimes we -want to refresh the cache regardless of mtimes. In that case, we can run `rose -cache update --force`. - -It would be pretty annoying if you had to run this command by hand after each -metadata update. So Rosé will automatically run this command whenever an update -happens _through_ Rosé. That means: +A cache update can be performed manually with the `rose cache update` command. +In this command, Rosé will identify any files that changed and update the read +cache accordingly. In other words, this command informs Rosé that something +changed in the source directory. -- If a file is modified in the virtual filesystem, a cache update is - triggered when the file handle closes. -- If a release is modified by the command line, a cache update is triggered at - the end of the command. +For performance reasons, the `rose cache update` command only checks files with +a different Last Modified (mtime) from the last cache update. To disable this +behavior and recheck every file, pass the `--force/-f` flag. -Rosé will also update the cache on virtual filesystem mount. +It would be annoying if you had to run `rose cache upate` by hand after each +metadata change. Rosé thus automatically updates the cache in response to +changes made _through_ Rosé. Any updates made through the virtual filesystem or +command line automatically trigger a cache update for the changed files. Rosé +will also update the cache when the virtual filesystem is mounted. -# Updating on External Changes +However, even with that improvement, you would still need to run `rose cache +update` automatically whenever changes are made directly to the source +directory. Thus, Rosé provides the `rose cache watch` command, which runs a +watcher that listens for file update events in the source directory. This +watcher will trigger a cache update whenever a file in the source directory +changes. -However, there is one class of updates that this does not update in response -to, and that is updates made by external tools directly to the source -directory. If another system updates your source directory directly, the read -cache will drift. - -To update in response to those external changes, you can run `rose cache -watch`. This command starts a watcher that triggers a cache update whenever a -file changes in the source directory. `rose cache watch` runs in the -foreground, so it is recommended that you manage it with a service manager like -systemd. See [Configuration](./CONFIGURATION.md) for example systemd unit -files. +By default, the watcher runs in the foreground. We recommend backgrounding it +with a service manager, such as systemd. See +[Configuration](./CONFIGURATION.md) for sample systemd unit files. # Cache Resets @@ -71,14 +64,9 @@ When Rosé detects that: 2. The configuration file has changed, 3. Or the cache database schema has changed, -Rosé will delete the read cache and rebuild it from scratch. - -A full cache rebuild is fairly performant, though an order of magnitude slower -than a cache scan that results in no changes. - -Deleting the read cache is a supported operation, and it is a viable solution -in case your cache ends up in a bad state (e.g. due to a bug or other issue). +Rosé will delete the read cache and rebuild it from scratch. A full cache +rebuild is fairly performant, though an order of magnitude slower than a cache +scan that results in no changes. -Since Rosé stores all of its state in the source directory, and merely -replicates that state into the cache, deleting the cache will never result in a -loss of data. +Deleting the read cache does not result in any loss of data, and is a viable +solution if your cache ends up in a bad state (e.g. due to a bug). diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index 9294025..a0d8eb6 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -16,10 +16,10 @@ The configuration parameters, with examples, are: # The directory containing the music to manage. Rosé has strong expectations # towards the organization of this directory. # -# All releases are expected to be immediate child directories of the -# music_source_dir. And Rosé expects that all tracks belong to a "release" -# (meaning an album, single, EP, etc.). Therefore, loose audio files at the -# top-level of the source directory will be ignored. +# All releases must be immediate child directories of the music_source_dir. And +# Rosé expects that all tracks belong to a "release" (meaning an album, single, +# EP, etc.). Therefore, loose audio files at the top-level of the source +# directory will be ignored. # # Rosé also writes collages and playlists to this directory, as `!collages` and # `!playlists` subdirectories. diff --git a/docs/METADATA_MANAGEMENT.md b/docs/METADATA_MANAGEMENT.md index 23814f8..3a80743 100644 --- a/docs/METADATA_MANAGEMENT.md +++ b/docs/METADATA_MANAGEMENT.md @@ -70,7 +70,7 @@ The artist tag is described by the following grammar: ::= string ';' | string ``` -Rosé only supports the artist roles: +Rosé supports the following artist roles: - `main` - `guest` @@ -111,16 +111,17 @@ Virtual Filesystem Directory Name. So for example: ```bash -$ rose releases edit "LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]" +$ rose releases edit "LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]" $ rose releases edit "018b4ff1-acdf-7ff1-bcd6-67757aea0fed" ``` This command opens up a TOML representation of the release's metadata in your `$EDITOR`. Upon save and exit, the TOML's metadata is written to the file tags. -Rosé validates the Artist Role and Release Type fields. The values provided -must be one of the supported values. The supported values are documented in -[Artist Tags](#artist-tags) and [Release Type Tags](#release-type-tags). +> [!NOTE] +> Rosé validates the Artist Role and Release Type fields upon metadata edit. +> The values provided must be one of the supported values. The supported values +> are documented in [Artist Tags](#artist-tags) and [Release Type Tags](#release-type-tags). An example of the TOML representation is: @@ -197,7 +198,7 @@ Rosé supports three tag container formats: - MP4: `.m4a` files - Vorbis: `.ogg`, `.opus`, and `.flac` files -In this section, we will list out the per-container fields that we read/write. +In this section, we list out the per-container field names that we read/write. Rosé will only write to a single field for each tag; however, for tags with multiple conventions out in the rest of the world, Rosé will support reading from additional fields. diff --git a/docs/PLAYLISTS_COLLAGES.md b/docs/PLAYLISTS_COLLAGES.md index d10e70e..6fe07f5 100644 --- a/docs/PLAYLISTS_COLLAGES.md +++ b/docs/PLAYLISTS_COLLAGES.md @@ -11,7 +11,7 @@ playlists together. Collages and playlists are stored on-disk in the source directory, in the `!collages` and `!playlists` directories, respectively. Each collage and -playlist is a single `.toml` file inside their respective directory. +playlist is a single `.toml` file. For example: @@ -33,7 +33,7 @@ description_meta = "BLACKPINK - 2016. SQUARE TWO - Single [Dance-Pop;K-Pop]" [[releases]] uuid = "018b4ff1-acdf-7ff1-bcd6-67757aea0fed" -description_meta = "LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]" +description_meta = "LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]" ``` and for a playlist: @@ -57,6 +57,11 @@ update, so that they remain meaningful. The ordering of the releases/tracks is meaningful: they represent the ordering of releases/tracks in the collage/playlist. +Playlists can also have custom cover art. These are stored as +`{playlist_name}.{image_ext}`. So for example, `Shower.toml`'s cover art would +be located at `Shower.jpg` (or `.png`). The extensions to treat as images are +configurable. See [Configuration](./CONFIGURATION.md). + # Operations However, working with this file directly is quite annoying, so Rosé allows you @@ -109,8 +114,8 @@ added by UUID. This is because the release virtual directory name is globally unique, while track virtual filenames are not globally unique._ ```bash -$ rose collages add-release "Morning" "LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]" -[17:59:38] INFO: Added release LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop] to collage Morning +$ rose collages add-release "Morning" "LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]" +[17:59:38] INFO: Added release LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop] to collage Morning [17:59:38] INFO: Refreshing the read cache for 1 collages [17:59:38] INFO: Applying cache updates for collage Morning @@ -136,15 +141,15 @@ too. We will try to fix this later._ ```bash $ cd $fuse_mount_dir -$ cp -r "1. Releases/LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]" "7. Collages/Morning/" -cp: cannot create directory '7. Collages/Morning/LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]': No such file or directory +$ cp -r "1. Releases/LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]" "7. Collages/Morning/" +cp: cannot create directory '7. Collages/Morning/LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]': No such file or directory $ tree "7. Collages/Morning/" 7. Collages/Morning/ ├── 1. BLACKPINK - 2016. SQUARE TWO - Single [Dance-Pop;K-Pop]/... -└── 2. LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]/... +└── 2. LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]/... -$ cp "1. Releases/LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]/04. LOOΠΔ ODD EYE CIRCLE - Chaotic.opus" "8. Playlists/Evening/" +$ cp "1. Releases/LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]/04. LOOΠΔ ODD EYE CIRCLE - Chaotic.opus" "8. Playlists/Evening/" $ tree "8. Playlists/Evening/" 8. Playlists/Evening/ @@ -160,8 +165,8 @@ removed by UUID. This is because the release virtual directory name is globally unique, while track virtual filenames are not globally unique._ ```bash -$ rose collages remove-release "Morning" "LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]" -[18:11:43] INFO: Removed release LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop] from collage Morning +$ rose collages remove-release "Morning" "LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]" +[18:11:43] INFO: Removed release LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop] from collage Morning [18:11:43] INFO: Refreshing the read cache for 1 collages [18:11:43] INFO: Applying cache updates for collage Morning @@ -181,13 +186,13 @@ Virtual filesystem: ```bash $ cd $fuse_mount_dir -$ rmdir "7. Collages/Morning/LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]" +$ rmdir "7. Collages/Morning/LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]" $ tree "7. Collages/Morning/" 7. Collages/Morning/ 0 directories, 0 files -$ rm "8. Playlists/Evening/LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]/04. LOOΠΔ ODD EYE CIRCLE - Chaotic.opus" +$ rm "8. Playlists/Evening/LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]/04. LOOΠΔ ODD EYE CIRCLE - Chaotic.opus" $ tree "8. Playlists/Evening/" 8. Playlists/Evening/ @@ -205,9 +210,9 @@ deleting their line entry from the text file._ $ rose collages edit "Road Trip" # Opens the following text in $EDITOR: BLACKPINK - 2016. SQUARE TWO - Single [Dance-Pop;K-Pop] -LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop] +LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop] # We will save the following text: -LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop] +LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop] BLACKPINK - 2016. SQUARE TWO - Single [Dance-Pop;K-Pop] # And the logs printed to stderr are: [18:20:53] INFO: Edited collage Road Trip from EDITOR @@ -216,7 +221,7 @@ BLACKPINK - 2016. SQUARE TWO - Single [Dance-Pop;K-Pop] $ tree "7. Collages/Road Trip" 7. Collages/Road Trip/ -├── 1. LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]/... +├── 1. LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]/... └── 2. BLACKPINK - 2016. SQUARE TWO - Single [Dance-Pop;K-Pop]/... $ rose playlists edit "Shower" diff --git a/docs/VIRTUAL_FILESYSTEM.md b/docs/VIRTUAL_FILESYSTEM.md index 5e050ee..496ac85 100644 --- a/docs/VIRTUAL_FILESYSTEM.md +++ b/docs/VIRTUAL_FILESYSTEM.md @@ -1,26 +1,21 @@ # Browsing the Virtual Filesystem -The virtual filesystem is the "User Interface" of Rosé. - -The virtual filesystem exposes a rich and meaningful music library organization -as a standard API, which other systems can easily compose with. Contrast this -with "normal" music players: other programs cannot easily interact with their -music organization patterns. - -Therefore, the Virtual Filesystem is designed to be used by other programs. A -powerful combination is to combine the Virtual Filesystem with a file manager -like [nnn](https://github.com/jarun/nnn). +The virtual filesystem is the primary "User Interface" of Rosé. It exposes a +meaningful music library organization as the filesystem. Since the filesystem +is a foundational API, other programs can trivially integrate with Rosé. For +example, Rosé can used with a file manager like [nnn](https://github.com/jarun/nnn) +and a media player like [mpv](https://mpv.io/). # Mounting & Unmounting -The Virtual Filesystem is mounted with the `rose fs mount` command. By default, -this command starts a backgrounded daemon. You can run the filesystem in the -foreground with the `--foreground/-f` flag. +You can mount the virtual filesystem `rose fs mount` command. By default, this +starts a backgrounded daemon. You can run the filesystem in the foreground with +the `--foreground/-f` flag. -The Virtual Filesystem is unmounted with the `rose fs unmount` command. This -command is a thin wrapper around `umount`. Note that this is subject to all the -restrictions of `umount`: If the Virtual Filesystem is currently in use, the -command will fail. +You can unmount the virtual filesystem with the `rose fs unmount` command. This +command simply calls `umount` under the hood. Thus, this command is subject to +the restrictions of `umount`. Including: if the virtual filesystem is currently +in use, unmounting command will fail. # Directory Structure @@ -36,26 +31,26 @@ library. They are: 7. `Collages` 8. `Playlists` -They should be fairly intuitive. They are numbered in the filesystem for the -sake of ordering. +Each directory should be fairly intuitive. They are numbered in the filesystem +to create an intentional ordering. # Directory and File Names Rosé constructs a "virtual" directory name for each release and "virtual" file -name for each track. These virtual names are constructed from the music -metadata. When the metadata is updated, the virtual names auto-update in -response. +name for each track. Rosé uses the source directory's metadata tags to do so. +When the source directory changes, the virtual names auto-update in response. -The release template is: +The release directory name template is: ``` %ALBUM_ARTISTS% - %YEAR%. %ALBUM_TITLE% - %RELEASE_TYPE% [%GENRE%] ``` -But the `- %RELEASE_TYPE%` field is omitted when the release is of type `album`, -`other`, or `unknown`. +> [!NOTE] +> The `- %RELEASE_TYPE%` field is omitted when the release is of type `album`, +> `other`, or `unknown`. -The file template is: +The track file name template is: ``` %TRACK_ARTISTS% - %TRACK_TITLE%.%EXTENSION% @@ -66,19 +61,22 @@ position prefix is of the format `%POSITION%. `. For example, tracks in a release have a prefix of `%DISC_NUMBER%-%TRACK_NUMBER%. `. Collages and playlists also apply a position prefix to each release/track in them. +Rosé exposes all cover art under the filename `cover.{ext}`, regardless of the +filename in the source directory. + # New Releases Rose supports flagging releases as "NEW" and making that evident in the virtual directory name. NEW releases have their virtual directory name prefixed with `{NEW}`. -By default, releases are flagged as NEW when first imported into Rosé. +By default, Rosé flags releases as new when they are first imported. NEW-ness has no effects besides prefixing the directory name with `{NEW}` and adding the release to the `2. Releases - New` top-level directory. NEW-ness is designed for you, the human operator, to edit manually. -NEW-ness is tracked within a release's `.rose.{uuid}.toml` file. See +Rosé tracks NEW-ness within a release's `.rose.{uuid}.toml` file. See [Architecture](./ARCHITECTURE.md) for more information about this file. # Operations @@ -100,7 +98,7 @@ Command line: ```bash $ cd $fuse_mount_dir -$ rose releases toggle-new "LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]" +$ rose releases toggle-new "LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]" [21:47:52] INFO: Refreshing the read cache for 1 releases [21:47:52] INFO: Applying cache updates for release LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match [21:47:52] INFO: Refreshing the read cache for 1 collages @@ -110,9 +108,9 @@ $ rose releases toggle-new "LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-P $ tree "2. Releases - New/" 2. Releases - New/ ├── {NEW} LOOΠΔ - 2017. Kim Lip - Single [Contemporary R&B;Dance-Pop;K-Pop]/... -└── {NEW} LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]/... +└── {NEW} LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]/... -$ rose releases toggle-new "{NEW} LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]" +$ rose releases toggle-new "{NEW} LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]" [21:49:36] INFO: Refreshing the read cache for 1 releases [21:49:36] INFO: Applying cache updates for release LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match [21:49:36] INFO: Refreshing the read cache for 1 collages @@ -129,14 +127,14 @@ Virtual filesystem: ```bash $ cd $fuse_mount_dir -$ mv "1. Releases/LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]" "1. Releases/{NEW} LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]" +$ mv "1. Releases/LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]" "1. Releases/{NEW} LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]" $ tree "2. Releases - New/" 2. Releases - New/ ├── {NEW} LOOΠΔ - 2017. Kim Lip - Single [Contemporary R&B;Dance-Pop;K-Pop]/... -└── {NEW} LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]/... +└── {NEW} LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]/... -$ mv "1. Releases/{NEW} LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]" "1. Releases/LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]" +$ mv "1. Releases/{NEW} LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]" "1. Releases/LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]" $ tree "2. Releases - New/" 2. Releases - New/ @@ -155,12 +153,12 @@ Command line: ```bash $ cd $fuse_mount_dir -$ rose releases delete "LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]" -[21:56:25] INFO: Trashed release LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop] +$ rose releases delete "LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]" +[21:56:25] INFO: Trashed release LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop] [21:56:25] INFO: Evicting cached releases that are not on disk [21:56:25] INFO: Evicted release /home/blissful/demo/source/LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match from cache [21:56:25] INFO: Refreshing the read cache for 1 collages -[21:56:25] INFO: Removing nonexistent release LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop] from collage Long Flight +[21:56:25] INFO: Removing nonexistent release LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop] from collage Long Flight [21:56:25] INFO: Updating release descriptions for Long Flight [21:56:25] INFO: Applying cache updates for collage Long Flight @@ -177,7 +175,7 @@ Virtual filesystem: ```bash $ cd $fuse_mount_dir -$ rmdir "1. Releases/LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [K-Pop]" +$ rmdir "1. Releases/LOOΠΔ ODD EYE CIRCLE - 2017. Mix & Match - EP [Dance-Pop;Future Bass;K-Pop]" $ tree "1. Releases/" 1. Releases/