Update Bs1770gainBackend to handle bs1770gain v0.6.0 XML output#3480
Update Bs1770gainBackend to handle bs1770gain v0.6.0 XML output#3480sampsyo merged 10 commits intobeetbox:masterfrom
Conversation
* Remove `0%\x08\x08` from output (backspace code doesn't resolve; progress percentages get spliced in)
* Handle changed attributes/fields:
* `sample-peak` attribute `factor` is called `amplitude` instead
* Album summary is not included in a `summary` tag now, but in two separate `integrated` and `sample-peak` tags
* Handle `lu` attribute
* Get bs1770gain version
* If v0.6.0 or later, add `--unit=ebu` flag to convert `db` attributes to LUFS
* May be useful later on
### Output examples
Track:
```
<!-- analyzing ... -->
<bs1770gain norm="-18.00">
<track total="1" number="1" file="02 tïtle 0.mp3">
<integrated lufs="-70.00" lu="52.00"/>
<sample-peak spfs="-72.28" amplitude="0.00"/>
</track>
<integrated lufs="-70.00" lu="52.00"/>
<sample-peak spfs="-72.28" amplitude="0.00"/>
</bs1770gain>
<!-- done. -->
```
Album:
```
<!-- analyzing ... -->
<bs1770gain norm="-18.00">
<track total="2" number="1" file="02 tïtle 0.mp3">
<integrated dbfs="-70.00" db="52.00"/>
<sample-peak dbfs="-72.28" amplitude="0.00"/>
</track>
<track total="2" number="2" file="02 tïtle 1.mp3">
<integrated dbfs="-70.00" db="52.00"/>
<sample-peak dbfs="-72.28" amplitude="0.00"/>
</track>
<integrated dbfs="-70.00" db="52.00"/>
<sample-peak dbfs="-72.28" amplitude="0.00"/>
</bs1770gain>
<!-- done. -->
```
* Fix unspecified `gain_adjustment` when method defined in config * Fix difference between dB and LUFS values in case of mismatched `target_level`/`method`: ``` db_to_lufs( target_level <dB> ) - lufs_to_dB( -23 <LUFS> ) ``` * Ignore single assertion in case of bs1770gain (cherry picked from commit 2395bf2)
* With `bs1770gain` installed the `Bs1770gainBackend` tests fail, but this should be fixed by beetbox#3480.
sampsyo
left a comment
There was a problem hiding this comment.
Cool; thanks for attacking this! Here are a few ideas.
beetsplug/replaygain.py
Outdated
| '([0-9]+.[0-9]+.[0-9]+), ', | ||
| call([cmd, '--version']).stdout.decode('utf-8') | ||
| ).group(1) | ||
| except AttributeError: |
There was a problem hiding this comment.
I’m a little confused—what is the potential AttributeError here? Is it the stdout attribute of the call result?
Maybe it would be nicer to just do a single call to check both whether the command exists and to get its version. Then we’d just need to handle OSError, I think?
There was a problem hiding this comment.
Yes, it's the stdout attribute.
Ok, I suppose there's no real chance that some weird version bs1770gain doesn't handle --version.
beetsplug/replaygain.py
Outdated
| if type(text) == bytes: | ||
| text = text.decode('utf-8') | ||
| while '\x08' in text: | ||
| text = re.sub('[^\x08]\x08', '', text) |
There was a problem hiding this comment.
This replacement is somewhat surprising! Maybe a comment would be useful here to describe what’s going wrong?
beetsplug/replaygain.py
Outdated
| parser.EndElementHandler = end_element_handler | ||
|
|
||
| try: | ||
| if type(text) == bytes: |
There was a problem hiding this comment.
| if type(text) == bytes: | |
| if isinstance(text, bytes): |
beetsplug/replaygain.py
Outdated
|
|
||
| try: | ||
| if type(text) == bytes: | ||
| text = text.decode('utf-8') |
There was a problem hiding this comment.
Is it necessary to do this conversion, or shall we perhaps just do the substitution directly on the bytes (with a bytes pattern)? That would avoid hard-coding an encoding, for example...
beetsplug/replaygain.py
Outdated
| try: | ||
| if type(text) == bytes: | ||
| text = text.decode('utf-8') | ||
| while '\x08' in text: |
There was a problem hiding this comment.
It might be safer to loop until the string stops changing. Otherwise, this runs the risk of this character being present but the pattern not matching (e.g., if it occurs at the beginning of the string).
There was a problem hiding this comment.
To me it seems more readable to cover that case in the pattern by also replacing \x08 at the start of the string
b'[^\x08]\x08|^\x08'then I can just explain it in a comment since I should write a bit about what's going on here anyway (:
* safer version comparison * regex bytes directly * handle b'\x08 ...' case * test_replaygain.py: injected command output should match the type of the actual output
sampsyo
left a comment
There was a problem hiding this comment.
Looking good! I have a couple of questions within, but I think this is basically ready to go. Would you mind adding a quick changelog entry?
beetsplug/replaygain.py
Outdated
| raise FatalReplayGainError( | ||
| u'Is bs1770gain installed?' | ||
| ) | ||
| except AttributeError: |
There was a problem hiding this comment.
Thanks for the reorganization, but I'm still not 100% sure when this exception can be raised. Isn't it the case that the command_output object will always have a stdout member if the call was successful?
There was a problem hiding this comment.
There is an edge case in test_replaygain where the backend is tested while bypassing calls to bs1770gain.
It was patching None to stdout there, I made it patch bs1770gain 0.0.0, instead.
…arsing # Conflicts: # docs/changelog.rst
sampsyo
left a comment
There was a problem hiding this comment.
Looks lovely; thank you for your persistence!
Fixes #3479.