mirror of
https://github.com/beetbox/beets.git
synced 2025-12-06 08:39:17 +01:00
Merge branch 'master' into discogs_original_year
This commit is contained in:
commit
a840bc700b
28 changed files with 236 additions and 144 deletions
|
|
@ -40,6 +40,7 @@ def apply_item_metadata(item, track_info):
|
|||
item.artist_credit = track_info.artist_credit
|
||||
item.title = track_info.title
|
||||
item.mb_trackid = track_info.track_id
|
||||
item.mb_releasetrackid = track_info.release_track_id
|
||||
if track_info.artist_id:
|
||||
item.mb_artistid = track_info.artist_id
|
||||
if track_info.data_source:
|
||||
|
|
@ -129,6 +130,7 @@ def apply_metadata(album_info, mapping):
|
|||
|
||||
# MusicBrainz IDs.
|
||||
item.mb_trackid = track_info.track_id
|
||||
item.mb_releasetrackid = track_info.release_track_id
|
||||
item.mb_albumid = album_info.album_id
|
||||
if track_info.artist_id:
|
||||
item.mb_artistid = track_info.artist_id
|
||||
|
|
|
|||
|
|
@ -129,6 +129,8 @@ class TrackInfo(object):
|
|||
|
||||
- ``title``: name of the track
|
||||
- ``track_id``: MusicBrainz ID; UUID fragment only
|
||||
- ``release_track_id``: MusicBrainz ID respective to a track on a
|
||||
particular release; UUID fragment only
|
||||
- ``artist``: individual track artist name
|
||||
- ``artist_id``
|
||||
- ``length``: float: duration of the track in seconds
|
||||
|
|
@ -152,14 +154,15 @@ class TrackInfo(object):
|
|||
may be None. The indices ``index``, ``medium``, and ``medium_index``
|
||||
are all 1-based.
|
||||
"""
|
||||
def __init__(self, title, track_id, artist=None, artist_id=None,
|
||||
length=None, index=None, medium=None, medium_index=None,
|
||||
medium_total=None, artist_sort=None, disctitle=None,
|
||||
artist_credit=None, data_source=None, data_url=None,
|
||||
media=None, lyricist=None, composer=None, composer_sort=None,
|
||||
arranger=None, track_alt=None):
|
||||
def __init__(self, title, track_id, release_track_id=None, artist=None,
|
||||
artist_id=None, length=None, index=None, medium=None,
|
||||
medium_index=None, medium_total=None, artist_sort=None,
|
||||
disctitle=None, artist_credit=None, data_source=None,
|
||||
data_url=None, media=None, lyricist=None, composer=None,
|
||||
composer_sort=None, arranger=None, track_alt=None):
|
||||
self.title = title
|
||||
self.track_id = track_id
|
||||
self.release_track_id = release_track_id
|
||||
self.artist = artist
|
||||
self.artist_id = artist_id
|
||||
self.length = length
|
||||
|
|
|
|||
|
|
@ -281,6 +281,10 @@ def album_info(release):
|
|||
continue
|
||||
|
||||
all_tracks = medium['track-list']
|
||||
if 'data-track-list' in medium:
|
||||
all_tracks += medium['data-track-list']
|
||||
track_count = len(all_tracks)
|
||||
|
||||
if 'pregap' in medium:
|
||||
all_tracks.insert(0, medium['pregap'])
|
||||
|
||||
|
|
@ -302,8 +306,9 @@ def album_info(release):
|
|||
index,
|
||||
int(medium['position']),
|
||||
int(track['position']),
|
||||
len(medium['track-list']),
|
||||
track_count,
|
||||
)
|
||||
ti.release_track_id = track['id']
|
||||
ti.disctitle = disctitle
|
||||
ti.media = format
|
||||
ti.track_alt = track['number']
|
||||
|
|
|
|||
|
|
@ -455,6 +455,7 @@ class Item(LibModel):
|
|||
'mb_albumid': types.STRING,
|
||||
'mb_artistid': types.STRING,
|
||||
'mb_albumartistid': types.STRING,
|
||||
'mb_releasetrackid': types.STRING,
|
||||
'albumtype': types.STRING,
|
||||
'label': types.STRING,
|
||||
'acoustid_fingerprint': types.STRING,
|
||||
|
|
|
|||
|
|
@ -1865,6 +1865,12 @@ class MediaFile(object):
|
|||
StorageStyle('MUSICBRAINZ_TRACKID'),
|
||||
ASFStorageStyle('MusicBrainz/Track Id'),
|
||||
)
|
||||
mb_releasetrackid = MediaField(
|
||||
MP3DescStorageStyle(u'MusicBrainz Release Track Id'),
|
||||
MP4StorageStyle('----:com.apple.iTunes:MusicBrainz Release Track Id'),
|
||||
StorageStyle('MUSICBRAINZ_RELEASETRACKID'),
|
||||
ASFStorageStyle('MusicBrainz/Release Track Id'),
|
||||
)
|
||||
mb_albumid = MediaField(
|
||||
MP3DescStorageStyle(u'MusicBrainz Album Id'),
|
||||
MP4StorageStyle('----:com.apple.iTunes:MusicBrainz Album Id'),
|
||||
|
|
|
|||
|
|
@ -237,7 +237,7 @@ def show_change(cur_artist, cur_album, match):
|
|||
medium = track_info.disc
|
||||
mediums = track_info.disctotal
|
||||
if config['per_disc_numbering']:
|
||||
if mediums > 1:
|
||||
if mediums and mediums > 1:
|
||||
return u'{0}-{1}'.format(medium, medium_index)
|
||||
else:
|
||||
return six.text_type(medium_index or index)
|
||||
|
|
|
|||
|
|
@ -498,9 +498,10 @@ class DiscogsPlugin(BeetsPlugin):
|
|||
medium, medium_index, _ = self.get_track_index(track['position'])
|
||||
artist, artist_id = self.get_artist(track.get('artists', []))
|
||||
length = self.get_track_length(track['duration'])
|
||||
return TrackInfo(title, track_id, artist, artist_id, length, index,
|
||||
medium, medium_index, artist_sort=None,
|
||||
disctitle=None, artist_credit=None)
|
||||
return TrackInfo(title, track_id, artist=artist, artist_id=artist_id,
|
||||
length=length, index=index,
|
||||
medium=medium, medium_index=medium_index,
|
||||
artist_sort=None, disctitle=None, artist_credit=None)
|
||||
|
||||
def get_track_index(self, position):
|
||||
"""Returns the medium, medium index and subtrack index for a discogs
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ class KeyFinderPlugin(BeetsPlugin):
|
|||
self.find_key(lib.items(ui.decargs(args)), write=ui.should_write())
|
||||
|
||||
def imported(self, session, task):
|
||||
self.find_key(task.items)
|
||||
self.find_key(task.imported_items())
|
||||
|
||||
def find_key(self, items, write=False):
|
||||
overwrite = self.config['overwrite'].get(bool)
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ New features:
|
|||
and tracklist positions. Track ids are stored in ``mb_trackid``. :bug:`#2336`
|
||||
Thanks to :user:`dbogdanov`.
|
||||
* :doc:`/plugins/discogs`: Fetch original year from master releases. :bug:`#1122`
|
||||
* As a first step to get :bug:`#406` implemented, beets now imports the
|
||||
``musicbrainz_releasetrackid`` field into the library and tags media files
|
||||
accordingly. Thanks to :user:`Rawrmonkeys`.
|
||||
|
||||
|
||||
Fixes:
|
||||
|
|
@ -104,6 +107,11 @@ Fixes:
|
|||
to which a track belongs, not the total number of different mediums present
|
||||
on the release. :bug:`2887`
|
||||
Thanks to :user:`dbogdanov`.
|
||||
* The importer now supports audio files contained in data tracks when they are
|
||||
listed in MusicBrainz: the corresponding audio tracks are now merged into the
|
||||
main track list. Thanks to :user:`jdetrey`. :bug:`1638`
|
||||
* :doc:`/plugins/keyfinder`: Avoid a crash when trying to process unmatched
|
||||
tracks. :bug:`2537`
|
||||
|
||||
|
||||
For developers:
|
||||
|
|
|
|||
|
|
@ -239,6 +239,7 @@ Audio information:
|
|||
MusicBrainz and fingerprint information:
|
||||
|
||||
* mb_trackid
|
||||
* mb_releasetrackid
|
||||
* mb_albumid
|
||||
* mb_artistid
|
||||
* mb_albumartistid
|
||||
|
|
|
|||
181
extra/_beet
181
extra/_beet
|
|
@ -2,28 +2,29 @@
|
|||
|
||||
# zsh completion for beets music library manager and MusicBrainz tagger: http://beets.radbox.org/
|
||||
|
||||
# NOTE: it will be very slow the first time you try to complete in a zsh shell (especially if you've enable many plugins)
|
||||
# You can make it faster in future by creating a cached version:
|
||||
# 1) perform a query completion with this file (_beet), e.g. do: beet list artist:"<TAB>
|
||||
# to create the completion function (takes a few seconds)
|
||||
# 2) save a copy of the completion function: which _beet > _beet_cached
|
||||
# 3) save a copy of the query completion function: which _beet_query > _beet_query_cached
|
||||
# 4) copy the contents of _beet_query_cached to the top of _beet_cached
|
||||
# 5) copy and paste the _beet_field_values function from _beet to the top of _beet_cached
|
||||
# 6) add the following line to the top of _beet_cached: #compdef beet
|
||||
# 7) add the following line to the bottom of _beet_cached: _beet "$@"
|
||||
# 8) save _beet_cached to your completions directory (e.g. /usr/share/zsh/functions/Completion)
|
||||
# 9) add the following line to your .zshrc file: compdef _beet_cached beet
|
||||
# You will need to repeat this proceedure each time you enable new plugins if you want them to complete properly.
|
||||
# Cache will be updated if it is older than the beets database or binary.
|
||||
# Need to set BEETS_LIBRARY to some preliminary value since it is used by the cache checking function.
|
||||
typeset -g BEETS_LIBRARY=~/.config/beets/library.db
|
||||
zstyle ":completion:${curcontext}:" cache-policy _beet_check_cache
|
||||
_beet_check_cache () {
|
||||
[[ ! -a "${1}" ]] || [[ ! -a ${~BEETS_LIBRARY} ]] || [[ "${1}" -ot ${~BEETS_LIBRARY} ]] || [[ "${1}" -ot =beet ]]
|
||||
}
|
||||
# Try to retrieve the cache, and find out if it needs to be updated
|
||||
if ! _retrieve_cache beets || _cache_invalid beets; then
|
||||
local updatecache=1
|
||||
# Location of database
|
||||
typeset -g BEETS_LIBRARY="$(beet config|grep library|cut -f 2 -d ' ')"
|
||||
# List of all fields
|
||||
local -a fields
|
||||
fields=(`beet fields | grep -G '^ ' | sort -u | colrm 1 2`)
|
||||
fi
|
||||
|
||||
# useful: argument to _regex_arguments for matching any word
|
||||
local matchany=/$'[^\0]##\0'/
|
||||
|
||||
# Deal with completions for querying and modifying fields..
|
||||
local fieldargs matchquery matchmodify
|
||||
local -a fields
|
||||
# get list of all fields
|
||||
fields=(`beet fields | grep -G '^ ' | sort -u | colrm 1 2`)
|
||||
|
||||
# regexps for matching query and modify terms on the command line
|
||||
matchquery=/"(${(j/|/)fields[@]})"$':[^\0]##\0'/
|
||||
matchmodify=/"(${(j/|/)fields[@]})"$'(=[^\0]##|!)\0'/
|
||||
|
|
@ -43,14 +44,17 @@ function _join_lines() {
|
|||
function _beet_field_values()
|
||||
{
|
||||
local -a output fieldvals
|
||||
local library="$(beet config|grep library|cut -f 2 -d ' ')"
|
||||
output=$(sqlite3 ${~library} "select distinct $1 from items;")
|
||||
local sqlcmd="select distinct $1 from items;"
|
||||
case $1
|
||||
in
|
||||
lyrics)
|
||||
fieldvals=
|
||||
;;
|
||||
*)
|
||||
if [[ "$(sqlite3 ${~BEETS_LIBRARY} ${sqlcmd} 2>&1)" =~ "no such column" ]]; then
|
||||
sqlcmd="select distinct value from item_attributes where key=='$1' and value!='';"
|
||||
fi
|
||||
output="$(sqlite3 ${~BEETS_LIBRARY} ${sqlcmd} 2>/dev/null | sed -rn '/^-+$/,${{/^[- ]+$/n};p}')"
|
||||
fieldvals=("${(f)output[@]}")
|
||||
;;
|
||||
esac
|
||||
|
|
@ -68,8 +72,7 @@ queryelem="_values -S : 'query field (add an extra : to match by regexp)' '::' $
|
|||
# store call to _values function for completing modify terms (no need to complete field values)
|
||||
modifyelem="_values -S = 'modify field (replace = with ! to remove field)' $(echo "'${^fields[@]}:: '")"
|
||||
# Create completion function for queries
|
||||
_regex_arguments _beet_query "$matchany" \# \( "$matchquery" ":query:query string:$queryelem" \) \
|
||||
\( "$matchquery" ":query:query string:$queryelem" \) \#
|
||||
_regex_arguments _beet_query "$matchany" \# \( "$matchquery" ":query:query string:$queryelem" \) \( "$matchquery" ":query:query string:$queryelem" \) \#
|
||||
# store regexps for completing lists of queries and modifications
|
||||
local -a query modify
|
||||
query=( \( "$matchquery" ":query:query string:{_beet_query}" \) \( "$matchquery" ":query:query string:{_beet_query}" \) \# )
|
||||
|
|
@ -174,73 +177,76 @@ function _beet_subcmd_options()
|
|||
}
|
||||
|
||||
# Now build the arguments to _regex_arguments for each subcommand.
|
||||
local -a options regex_words_subcmds regex_words_help
|
||||
local subcmd cmddesc
|
||||
for i in ${${(f)"$(beet help | _join_lines ' ' 3 'Commands:')"[@]}[@]}
|
||||
do
|
||||
subcmd="${i[(w)1]}"
|
||||
# remove first word and parenthesised alias, replace : with -, [ with (, ] with ), and remove single quotes
|
||||
cmddesc="${${${${${i[(w)2,-1]##\(*\) #}//:/-}//\[/(}//\]/)}//\'/}"
|
||||
case $subcmd
|
||||
if [[ -n $updatecache ]]; then
|
||||
local -a options regex_words_subcmds regex_words_help
|
||||
local subcmd cmddesc
|
||||
for i in ${${(f)"$(beet help | _join_lines ' ' 3 'Commands:')"[@]}[@]}
|
||||
do
|
||||
subcmd="${i[(w)1]}"
|
||||
# remove first word and parenthesised alias, replace : with -, [ with (, ] with ), and remove single quotes
|
||||
cmddesc="${${${${${i[(w)2,-1]##\(*\) #}//:/-}//\[/(}//\]/)}//\'/}"
|
||||
case $subcmd
|
||||
in
|
||||
(config)
|
||||
_regex_words options "config options" "$helpopt" "$pathopt" "$editopt" "$defaultopt"
|
||||
options=("${reply[@]}")
|
||||
;;
|
||||
(import)
|
||||
_regex_words options "import options" "$helpopt" "$writeopt" "$nowriteopt" "$copyopt" "$nocopyopt"\
|
||||
"$inferopt" "$noinferopt" "$resumeopt" "$noresumeopt" "$nopromptopt" "$logopt" "$individualopt" "$confirmopt"\
|
||||
"$retagopt" "$skipopt" "$noskipopt" "$flatopt" "$groupopt"
|
||||
options=( "${reply[@]}" \# "${files[@]}" \# )
|
||||
;;
|
||||
(list)
|
||||
_regex_words options "list options" "$helpopt" "$pathopt" "$albumopt" "$formatopt"
|
||||
options=( "$reply[@]" \# "${query[@]}" )
|
||||
;;
|
||||
(modify)
|
||||
_regex_words options "modify options" "$helpopt" "$dontmoveopt" "$writeopt" "$nowriteopt" "$albumopt" \
|
||||
"$noconfirmopt" "$formatopt"
|
||||
options=( "${reply[@]}" \# "${query[@]}" "${modify[@]}" )
|
||||
;;
|
||||
(move)
|
||||
_regex_words options "move options" "$helpopt" "$albumopt" "$destopt" "$copynomoveopt"
|
||||
options=( "${reply[@]}" \# "${query[@]}")
|
||||
;;
|
||||
(remove)
|
||||
_regex_words options "remove options" "$helpopt" "$albumopt" "$removeopt"
|
||||
options=( "${reply[@]}" \# "${query[@]}" )
|
||||
;;
|
||||
(stats)
|
||||
_regex_words options "stats options" "$helpopt" "$exactopt"
|
||||
options=( "${reply[@]}" \# "${query[@]}" )
|
||||
;;
|
||||
(update)
|
||||
_regex_words options "update options" "$helpopt" "$albumopt" "$dontmoveopt" "$pretendopt" "$formatopt"
|
||||
options=( "${reply[@]}" \# "${query[@]}" )
|
||||
;;
|
||||
(write)
|
||||
_regex_words options "write options" "$helpopt" "$pretendopt"
|
||||
options=( "${reply[@]}" \# "${query[@]}" )
|
||||
;;
|
||||
(fields|migrate|version)
|
||||
options=()
|
||||
;;
|
||||
(help)
|
||||
# The help subcommand is treated separately
|
||||
continue
|
||||
;;
|
||||
(*) # completions for plugin commands are generated using _beet_subcmd_options
|
||||
_beet_subcmd_options "$subcmd"
|
||||
options=( \( "${reply[@]}" \# "${query[@]}" \) )
|
||||
;;
|
||||
esac
|
||||
# Create variable for holding option for this subcommand, and assign to it (needs to have a unique name).
|
||||
typeset -a opts_for_$subcmd
|
||||
set -A opts_for_$subcmd ${options[@]} # Assignment MUST be done using set (other methods fail).
|
||||
regex_words_subcmds+=("$subcmd:$cmddesc:\${(@)opts_for_$subcmd}")
|
||||
# Add to regex_words args for help subcommand
|
||||
regex_words_help+=("$subcmd:$cmddesc")
|
||||
done
|
||||
(config)
|
||||
_regex_words options "config options" "$helpopt" "$pathopt" "$editopt" "$defaultopt"
|
||||
options=("${reply[@]}")
|
||||
;;
|
||||
(import)
|
||||
_regex_words options "import options" "$helpopt" "$writeopt" "$nowriteopt" "$copyopt" "$nocopyopt"\
|
||||
"$inferopt" "$noinferopt" "$resumeopt" "$noresumeopt" "$nopromptopt" "$logopt" "$individualopt" "$confirmopt"\
|
||||
"$retagopt" "$skipopt" "$noskipopt" "$flatopt" "$groupopt"
|
||||
options=( "${reply[@]}" \# "${files[@]}" \# )
|
||||
;;
|
||||
(list)
|
||||
_regex_words options "list options" "$helpopt" "$pathopt" "$albumopt" "$formatopt"
|
||||
options=( "$reply[@]" \# "${query[@]}" )
|
||||
;;
|
||||
(modify)
|
||||
_regex_words options "modify options" "$helpopt" "$dontmoveopt" "$writeopt" "$nowriteopt" "$albumopt" \
|
||||
"$noconfirmopt" "$formatopt"
|
||||
options=( "${reply[@]}" \# "${query[@]}" "${modify[@]}" )
|
||||
;;
|
||||
(move)
|
||||
_regex_words options "move options" "$helpopt" "$albumopt" "$destopt" "$copynomoveopt"
|
||||
options=( "${reply[@]}" \# "${query[@]}")
|
||||
;;
|
||||
(remove)
|
||||
_regex_words options "remove options" "$helpopt" "$albumopt" "$removeopt"
|
||||
options=( "${reply[@]}" \# "${query[@]}" )
|
||||
;;
|
||||
(stats)
|
||||
_regex_words options "stats options" "$helpopt" "$exactopt"
|
||||
options=( "${reply[@]}" \# "${query[@]}" )
|
||||
;;
|
||||
(update)
|
||||
_regex_words options "update options" "$helpopt" "$albumopt" "$dontmoveopt" "$pretendopt" "$formatopt"
|
||||
options=( "${reply[@]}" \# "${query[@]}" )
|
||||
;;
|
||||
(write)
|
||||
_regex_words options "write options" "$helpopt" "$pretendopt"
|
||||
options=( "${reply[@]}" \# "${query[@]}" )
|
||||
;;
|
||||
(fields|migrate|version)
|
||||
options=()
|
||||
;;
|
||||
(help)
|
||||
# The help subcommand is treated separately
|
||||
continue
|
||||
;;
|
||||
(*) # completions for plugin commands are generated using _beet_subcmd_options
|
||||
_beet_subcmd_options "$subcmd"
|
||||
options=( \( "${reply[@]}" \# "${query[@]}" \) )
|
||||
;;
|
||||
esac
|
||||
# Create variable for holding option for this subcommand, and assign to it (needs to have a unique name).
|
||||
typeset -a opts_for_$subcmd
|
||||
set -A opts_for_$subcmd ${options[@]} # Assignment MUST be done using set (other methods fail).
|
||||
regex_words_subcmds+=("$subcmd:$cmddesc:\${(@)opts_for_$subcmd}")
|
||||
# Add to regex_words args for help subcommand
|
||||
regex_words_help+=("$subcmd:$cmddesc")
|
||||
done
|
||||
_store_cache beets regex_words_subcmds regex_words_help BEETS_LIBRARY fields
|
||||
fi
|
||||
|
||||
local -a opts_for_help
|
||||
_regex_words subcmds "subcommands" "${regex_words_help[@]}"
|
||||
|
|
@ -253,7 +259,7 @@ _regex_words options "global options" "$configopt" "$debugopt" "$libopt" "$helpo
|
|||
globalopts=("${reply[@]}")
|
||||
|
||||
# Create main completion function
|
||||
#local -a subcmds
|
||||
local -a subcmds
|
||||
_regex_words subcmds "subcommands" "${regex_words_subcmds[@]}"
|
||||
subcmds=("${reply[@]}")
|
||||
_regex_arguments _beet "$matchany" \( "${globalopts[@]}" \# \) "${subcmds[@]}"
|
||||
|
|
@ -267,3 +273,4 @@ _beet "$@"
|
|||
# Local Variables:
|
||||
# mode:shell-script
|
||||
# End:
|
||||
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ def item(lib=None):
|
|||
mb_albumid='someID-2',
|
||||
mb_artistid='someID-3',
|
||||
mb_albumartistid='someID-4',
|
||||
mb_releasetrackid='someID-5',
|
||||
album_id=None,
|
||||
mtime=12345,
|
||||
)
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -103,9 +103,9 @@ def _make_item(title, track, artist=u'some artist'):
|
|||
|
||||
def _make_trackinfo():
|
||||
return [
|
||||
TrackInfo(u'one', None, u'some artist', length=1, index=1),
|
||||
TrackInfo(u'two', None, u'some artist', length=1, index=2),
|
||||
TrackInfo(u'three', None, u'some artist', length=1, index=3),
|
||||
TrackInfo(u'one', None, artist=u'some artist', length=1, index=1),
|
||||
TrackInfo(u'two', None, artist=u'some artist', length=1, index=2),
|
||||
TrackInfo(u'three', None, artist=u'some artist', length=1, index=3),
|
||||
]
|
||||
|
||||
|
||||
|
|
@ -827,15 +827,15 @@ class ApplyCompilationTest(_common.TestCase, ApplyTestUtil):
|
|||
trackinfo.append(TrackInfo(
|
||||
u'oneNew',
|
||||
u'dfa939ec-118c-4d0f-84a0-60f3d1e6522c',
|
||||
u'artistOneNew',
|
||||
u'a05686fc-9db2-4c23-b99e-77f5db3e5282',
|
||||
artist=u'artistOneNew',
|
||||
artist_id=u'a05686fc-9db2-4c23-b99e-77f5db3e5282',
|
||||
index=1,
|
||||
))
|
||||
trackinfo.append(TrackInfo(
|
||||
u'twoNew',
|
||||
u'40130ed1-a27c-42fd-a328-1ebefb6caef4',
|
||||
u'artistTwoNew',
|
||||
u'80b3cf5e-18fe-4c59-98c7-e5bb87210710',
|
||||
artist=u'artistTwoNew',
|
||||
artist_id=u'80b3cf5e-18fe-4c59-98c7-e5bb87210710',
|
||||
index=2,
|
||||
))
|
||||
self.info = AlbumInfo(
|
||||
|
|
|
|||
|
|
@ -1819,6 +1819,7 @@ def mocked_get_release_by_id(id_, includes=[], release_status=[],
|
|||
'id': id_,
|
||||
'medium-list': [{
|
||||
'track-list': [{
|
||||
'id': 'baz',
|
||||
'recording': {
|
||||
'title': 'foo',
|
||||
'id': 'bar',
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@ import mock
|
|||
|
||||
class MBAlbumInfoTest(_common.TestCase):
|
||||
def _make_release(self, date_str='2009', tracks=None, track_length=None,
|
||||
track_artist=False, medium_format='FORMAT'):
|
||||
track_artist=False, data_tracks=None,
|
||||
medium_format='FORMAT'):
|
||||
release = {
|
||||
'title': 'ALBUM TITLE',
|
||||
'id': 'ALBUM ID',
|
||||
|
|
@ -62,12 +63,15 @@ class MBAlbumInfoTest(_common.TestCase):
|
|||
'country': 'COUNTRY',
|
||||
'status': 'STATUS',
|
||||
}
|
||||
i = 0
|
||||
track_list = []
|
||||
if tracks:
|
||||
track_list = []
|
||||
for i, recording in enumerate(tracks):
|
||||
for recording in tracks:
|
||||
i += 1
|
||||
track = {
|
||||
'id': 'RELEASE TRACK ID %d' % i,
|
||||
'recording': recording,
|
||||
'position': i + 1,
|
||||
'position': i,
|
||||
'number': 'A1',
|
||||
}
|
||||
if track_length:
|
||||
|
|
@ -87,12 +91,24 @@ class MBAlbumInfoTest(_common.TestCase):
|
|||
}
|
||||
]
|
||||
track_list.append(track)
|
||||
release['medium-list'].append({
|
||||
'position': '1',
|
||||
'track-list': track_list,
|
||||
'format': medium_format,
|
||||
'title': 'MEDIUM TITLE',
|
||||
})
|
||||
data_track_list = []
|
||||
if data_tracks:
|
||||
for recording in data_tracks:
|
||||
i += 1
|
||||
data_track = {
|
||||
'id': 'RELEASE TRACK ID %d' % i,
|
||||
'recording': recording,
|
||||
'position': i,
|
||||
'number': 'A1',
|
||||
}
|
||||
data_track_list.append(data_track)
|
||||
release['medium-list'].append({
|
||||
'position': '1',
|
||||
'track-list': track_list,
|
||||
'data-track-list': data_track_list,
|
||||
'format': medium_format,
|
||||
'title': 'MEDIUM TITLE',
|
||||
})
|
||||
return release
|
||||
|
||||
def _make_track(self, title, tr_id, duration, artist=False, video=False):
|
||||
|
|
@ -183,6 +199,7 @@ class MBAlbumInfoTest(_common.TestCase):
|
|||
self._make_track('TITLE TWO', 'ID TWO', 200.0 * 1000.0)]
|
||||
release = self._make_release(tracks=[tracks[0]])
|
||||
second_track_list = [{
|
||||
'id': 'RELEASE TRACK ID 2',
|
||||
'recording': tracks[1],
|
||||
'position': '1',
|
||||
'number': 'A1',
|
||||
|
|
@ -354,6 +371,18 @@ class MBAlbumInfoTest(_common.TestCase):
|
|||
self.assertEqual(d.tracks[0].title, 'TITLE ONE')
|
||||
self.assertEqual(d.tracks[1].title, 'TITLE TWO')
|
||||
|
||||
def test_no_skip_audio_data_tracks(self):
|
||||
tracks = [self._make_track('TITLE ONE', 'ID ONE', 100.0 * 1000.0),
|
||||
self._make_track('TITLE TWO', 'ID TWO', 200.0 * 1000.0)]
|
||||
data_tracks = [self._make_track('TITLE AUDIO DATA', 'ID DATA TRACK',
|
||||
100.0 * 1000.0)]
|
||||
release = self._make_release(tracks=tracks, data_tracks=data_tracks)
|
||||
d = mb.album_info(release)
|
||||
self.assertEqual(len(d.tracks), 3)
|
||||
self.assertEqual(d.tracks[0].title, 'TITLE ONE')
|
||||
self.assertEqual(d.tracks[1].title, 'TITLE TWO')
|
||||
self.assertEqual(d.tracks[2].title, 'TITLE AUDIO DATA')
|
||||
|
||||
def test_skip_video_tracks_by_default(self):
|
||||
tracks = [self._make_track('TITLE ONE', 'ID ONE', 100.0 * 1000.0),
|
||||
self._make_track('TITLE VIDEO', 'ID VIDEO', 100.0 * 1000.0,
|
||||
|
|
@ -365,6 +394,17 @@ class MBAlbumInfoTest(_common.TestCase):
|
|||
self.assertEqual(d.tracks[0].title, 'TITLE ONE')
|
||||
self.assertEqual(d.tracks[1].title, 'TITLE TWO')
|
||||
|
||||
def test_skip_video_data_tracks_by_default(self):
|
||||
tracks = [self._make_track('TITLE ONE', 'ID ONE', 100.0 * 1000.0),
|
||||
self._make_track('TITLE TWO', 'ID TWO', 200.0 * 1000.0)]
|
||||
data_tracks = [self._make_track('TITLE VIDEO', 'ID VIDEO',
|
||||
100.0 * 1000.0, False, True)]
|
||||
release = self._make_release(tracks=tracks, data_tracks=data_tracks)
|
||||
d = mb.album_info(release)
|
||||
self.assertEqual(len(d.tracks), 2)
|
||||
self.assertEqual(d.tracks[0].title, 'TITLE ONE')
|
||||
self.assertEqual(d.tracks[1].title, 'TITLE TWO')
|
||||
|
||||
def test_no_skip_video_tracks_if_configured(self):
|
||||
config['match']['ignore_video_tracks'] = False
|
||||
tracks = [self._make_track('TITLE ONE', 'ID ONE', 100.0 * 1000.0),
|
||||
|
|
@ -378,6 +418,19 @@ class MBAlbumInfoTest(_common.TestCase):
|
|||
self.assertEqual(d.tracks[1].title, 'TITLE VIDEO')
|
||||
self.assertEqual(d.tracks[2].title, 'TITLE TWO')
|
||||
|
||||
def test_no_skip_video_data_tracks_if_configured(self):
|
||||
config['match']['ignore_video_tracks'] = False
|
||||
tracks = [self._make_track('TITLE ONE', 'ID ONE', 100.0 * 1000.0),
|
||||
self._make_track('TITLE TWO', 'ID TWO', 200.0 * 1000.0)]
|
||||
data_tracks = [self._make_track('TITLE VIDEO', 'ID VIDEO',
|
||||
100.0 * 1000.0, False, True)]
|
||||
release = self._make_release(tracks=tracks, data_tracks=data_tracks)
|
||||
d = mb.album_info(release)
|
||||
self.assertEqual(len(d.tracks), 3)
|
||||
self.assertEqual(d.tracks[0].title, 'TITLE ONE')
|
||||
self.assertEqual(d.tracks[1].title, 'TITLE TWO')
|
||||
self.assertEqual(d.tracks[2].title, 'TITLE VIDEO')
|
||||
|
||||
|
||||
class ParseIDTest(_common.TestCase):
|
||||
def test_parse_id_correct(self):
|
||||
|
|
@ -504,6 +557,7 @@ class MBLibraryTest(unittest.TestCase):
|
|||
'id': mbid,
|
||||
'medium-list': [{
|
||||
'track-list': [{
|
||||
'id': 'baz',
|
||||
'recording': {
|
||||
'title': 'foo',
|
||||
'id': 'bar',
|
||||
|
|
|
|||
|
|
@ -318,29 +318,30 @@ class ReadWriteTestBase(ArtTestMixin, GenreListTestMixin,
|
|||
"""
|
||||
|
||||
full_initial_tags = {
|
||||
'title': u'full',
|
||||
'artist': u'the artist',
|
||||
'album': u'the album',
|
||||
'genre': u'the genre',
|
||||
'composer': u'the composer',
|
||||
'grouping': u'the grouping',
|
||||
'year': 2001,
|
||||
'month': None,
|
||||
'day': None,
|
||||
'date': datetime.date(2001, 1, 1),
|
||||
'track': 2,
|
||||
'tracktotal': 3,
|
||||
'disc': 4,
|
||||
'disctotal': 5,
|
||||
'lyrics': u'the lyrics',
|
||||
'comments': u'the comments',
|
||||
'bpm': 6,
|
||||
'comp': True,
|
||||
'mb_trackid': '8b882575-08a5-4452-a7a7-cbb8a1531f9e',
|
||||
'mb_albumid': '9e873859-8aa4-4790-b985-5a953e8ef628',
|
||||
'mb_artistid': '7cf0ea9d-86b9-4dad-ba9e-2355a64899ea',
|
||||
'art': None,
|
||||
'label': u'the label',
|
||||
'title': u'full',
|
||||
'artist': u'the artist',
|
||||
'album': u'the album',
|
||||
'genre': u'the genre',
|
||||
'composer': u'the composer',
|
||||
'grouping': u'the grouping',
|
||||
'year': 2001,
|
||||
'month': None,
|
||||
'day': None,
|
||||
'date': datetime.date(2001, 1, 1),
|
||||
'track': 2,
|
||||
'tracktotal': 3,
|
||||
'disc': 4,
|
||||
'disctotal': 5,
|
||||
'lyrics': u'the lyrics',
|
||||
'comments': u'the comments',
|
||||
'bpm': 6,
|
||||
'comp': True,
|
||||
'mb_trackid': '8b882575-08a5-4452-a7a7-cbb8a1531f9e',
|
||||
'mb_releasetrackid': 'c29f3a57-b439-46fd-a2e2-93776b1371e0',
|
||||
'mb_albumid': '9e873859-8aa4-4790-b985-5a953e8ef628',
|
||||
'mb_artistid': '7cf0ea9d-86b9-4dad-ba9e-2355a64899ea',
|
||||
'art': None,
|
||||
'label': u'the label',
|
||||
}
|
||||
|
||||
tag_fields = [
|
||||
|
|
@ -366,6 +367,7 @@ class ReadWriteTestBase(ArtTestMixin, GenreListTestMixin,
|
|||
'bpm',
|
||||
'comp',
|
||||
'mb_trackid',
|
||||
'mb_releasetrackid',
|
||||
'mb_albumid',
|
||||
'mb_artistid',
|
||||
'art',
|
||||
|
|
@ -773,7 +775,7 @@ class MusepackTest(ReadWriteTestBase, unittest.TestCase):
|
|||
extension = 'mpc'
|
||||
audio_properties = {
|
||||
'length': 1.0,
|
||||
'bitrate': 23458,
|
||||
'bitrate': 24023,
|
||||
'format': u'Musepack',
|
||||
'samplerate': 44100,
|
||||
'bitdepth': 0,
|
||||
|
|
@ -871,7 +873,7 @@ class ApeTest(ReadWriteTestBase, ExtendedImageStructureTestMixin,
|
|||
extension = 'ape'
|
||||
audio_properties = {
|
||||
'length': 1.0,
|
||||
'bitrate': 112040,
|
||||
'bitrate': 112608,
|
||||
'format': u'APE',
|
||||
'samplerate': 44100,
|
||||
'bitdepth': 16,
|
||||
|
|
@ -883,7 +885,7 @@ class WavpackTest(ReadWriteTestBase, unittest.TestCase):
|
|||
extension = 'wv'
|
||||
audio_properties = {
|
||||
'length': 1.0,
|
||||
'bitrate': 108744,
|
||||
'bitrate': 109312,
|
||||
'format': u'WavPack',
|
||||
'samplerate': 44100,
|
||||
'bitdepth': 0,
|
||||
|
|
@ -895,7 +897,7 @@ class OpusTest(ReadWriteTestBase, unittest.TestCase):
|
|||
extension = 'opus'
|
||||
audio_properties = {
|
||||
'length': 1.0,
|
||||
'bitrate': 57984,
|
||||
'bitrate': 66792,
|
||||
'format': u'Opus',
|
||||
'samplerate': 48000,
|
||||
'bitdepth': 0,
|
||||
|
|
|
|||
Loading…
Reference in a new issue