Code Monkey home page Code Monkey logo

mack's Introduction

mack | Tests

mack is an opinionated, fast music organiser. It enforces:

  • Directory layout
  • File name format
  • Metadata consistency (e.g., consistent "feat" tagging)
  • Format consistency (e.g., ID3 version)
  • ...and more!

Examples of fixes

  • Moving featured artists from the artist tag to the title
  • Enforcing a consistent "feat" format in title tags
  • Whitespace normalisation
  • Renaming files to format "{artist}/{album}/{track} {title}", or another format specified with --fmt

Usage

See --help. An example invocation is:

% mack --dry-run -o Music .
01 Pyramid.mp3: renamed to Music/宇宙コンビニ/染まる音を確認したら/01 Pyramid.mp3
02 8films.mp3: renamed to Music/宇宙コンビニ/染まる音を確認したら/02 8films.mp3
03 tobira.mp3: renamed to Music/宇宙コンビニ/染まる音を確認したら/03 tobira.mp3
04 Compass.mp3: renamed to Music/宇宙コンビニ/染まる音を確認したら/04 Compass.mp3
05 strings.mp3: renamed to Music/宇宙コンビニ/染まる音を確認したら/05 strings.mp3

You can see what would be changed first using --dry-run.

Installation

cargo install mack

Performance

mack has a strong focus on performance. Files which were not updated since the last mack run will not be examined at all. On a sample modern laptop with a mid-spec SSD, this means that we only take 0.005 seconds to run over ~3500 files under most circumstances (0.015 seconds on the very first run).

Configuration

If you don't want a particular file to be touched by mack, add _NO_MACK as a substring anywhere in the comment tag.

mack's People

Contributors

cdown avatar dependabot[bot] avatar linsallyzhao avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

mack's Issues

Investigate using something else (nom?) instead of regexes

There are currently some limitations with regexes, especially that they don't support lookahead/behind assertions in rust-regex. fancy-regex supports these but has no .replace(), which is a pain in the arse since that's most of what we want to do.

Maybe we should just write a parser with nom.

"&" in artist name may need to be split into title tag

This is somewhat difficult and is outside the current provided infrastructure because it requires one to do some checks first to see if this looks like something that should be split out. For example "Simon & Garfunkel" should stay the same, but this should not as "Die Lit" is already attributed to the primary artist:

  • Artist: Playboi Carti & Nicki Minaj
  • Album: Die Lit
  • Track: Poke It Out

should become

  • Artist: Playboi Carti
  • Album: Die Lit
  • Track: Poke It Out (feat. Nicki Minaj)

...because "Die Lit" being in both shows this is really just a feat tag.

Possible other things to look for:

  • &
  • and
  • feat[uring]
  • vs
  • with

Add tests for each fixer

Using regexes (for example) is fairly logical for many fixers, but it's hard to validate visually that they work properly and don't regress. Adding tests would help avoid that.

It's probably worth also using quickcheck instead of static examples.

Add non-tag based fixers

The most major one is file renaming based on tags, which should be done after tag cleanup. There are others, though, like making sure case insensitive matches for the same artist or artist/album pair have the same capitalisation.

Tidy up main

Right now main is a cavalcade of nested conditions and matches. This should be cleaned up.

Work out how to deduplicate fix_tag_whitespace

I had intended to use a closure for this, but due to there not being any abstractions over taglib's Rust FFI bindings, we end up in a bit of a pickle as we end up having to borrow tags twice if we want to pass both (say) tags.album and tags.set_album to a function.

I'm not yet entirely certain how to overcome this in a DRY way, so it's implemented manually for now. This needs cleanup for sure.

Investigate taglib performance

Right now it seems the vast majority of our runtime is in taglib deref/malloc/free. This makes me think it might be better to just store the tags in Track.

clean_part should look at directories

After 429084d we now use clean_part for each format, but this isn't quite right -- it should be used for each directory we got.

This is a bit complicated since we don't want to sanitise the user string, but.

Move to pure Rust tagging lib

Pros:

  • The current way of passing around tags is pretty stilted due to the very C-like API provided by the taglib bindings. This would likely allow some better code structure and avoid the stilted .save() handling now.
  • taglib has some recent C-specific CVEs (although they don't look too worrying for our threat model).

Cons:

  • Right now it seems there's no generic tagging library for Rust, so we'd likely have to use separate libraries for separate tag types and abstract over them.
  • Pure Rust tagging libraries seem not super featureful compared to existing C solutions right now, resulting in issues even with fairly "normal" seeming mp3 files (eg. polyfloyd/rust-id3#27)

Add path renaming

We should rename things to artist/album/trackno title.ext. We need to work out how to specify the base dir, though.

Add dry run mode

Right now we offer no way of showing to the user what we would do before we do it. We also don't actually show what we did even if we did do it.

At its most basic level, this is basically just gating .save(), but that's not very useful by itself. We should also implement something which prints out the before and after for changed tags.

Keeping the "before" around probably requires some shenanigans, since we'll need to extract them from the taglib::Tag object before modification. It would be ideal not to just extract them all, but only clone when we know that we're actually going to make a change. Maybe Cow can help here.

If showing the before turns out to be too much of a burden, we should at least just show the after with the affected filename.

Handle char boundary truncation

Right now we use .truncate() for sanitisation, but this will panic if not at a char boundary. Perhaps collect into a Vec?

About assets

Hello, what are your thoughts on also ordering assets like lyrics (per file) covers (per album) maybe artist pics, etc. Are these in line with mack or don't matter? What about embedding that info?

I just found out about this tool, always seemed to want something like this and almost started writing something similar (dummy me).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.