mirror of
https://github.com/beetbox/beets.git
synced 2026-01-14 04:01:43 +01:00
added bitrate and length to mediafile
--HG-- extra : convert_revision : svn%3A41726ec3-264d-0410-9c23-a9f1637257cc/trunk%40119
This commit is contained in:
parent
7ff7eabf7f
commit
b1a45fda0b
5 changed files with 64 additions and 8 deletions
|
|
@ -4,8 +4,10 @@ from string import Template
|
|||
|
||||
# Fields in the "items" table; all the metadata available for items in the
|
||||
# library. These are used directly in SQL; they are vulnerable to injection if
|
||||
# accessible to the user.
|
||||
metadata_fields = [
|
||||
# accessible to the user. The fields are divided into read-write
|
||||
# metadata, all metadata (inlcuding read-only attributes), and all
|
||||
# fields (i.e., including non-metadata attributes).
|
||||
metadata_rw_fields = [
|
||||
('title', 'text'),
|
||||
('artist', 'text'),
|
||||
('album', 'text'),
|
||||
|
|
@ -24,10 +26,15 @@ metadata_fields = [
|
|||
('bpm', 'int'),
|
||||
('comp', 'bool'),
|
||||
]
|
||||
metadata_fields = [
|
||||
('length', 'real'),
|
||||
('bitrate', 'int'),
|
||||
] + metadata_rw_fields
|
||||
item_fields = [
|
||||
('id', 'integer primary key'),
|
||||
('path', 'text'),
|
||||
] + metadata_fields
|
||||
metadata_rw_keys = map(operator.itemgetter(0), metadata_rw_fields)
|
||||
metadata_keys = map(operator.itemgetter(0), metadata_fields)
|
||||
item_keys = map(operator.itemgetter(0), item_fields)
|
||||
|
||||
|
|
@ -241,7 +248,7 @@ class Item(object):
|
|||
def write(self):
|
||||
"""Writes the item's metadata to the associated file."""
|
||||
f = MediaFile(self.path)
|
||||
for key in metadata_keys:
|
||||
for key in metadata_rw_keys:
|
||||
setattr(f, key, getattr(self, key))
|
||||
f.save()
|
||||
|
||||
|
|
@ -262,7 +269,7 @@ class Item(object):
|
|||
value = getattr(self, key)
|
||||
# sanitize the value for inclusion in a path:
|
||||
# replace / and leading . with _
|
||||
if isinstance(value, str) or isinstance(value, unicode):
|
||||
if isinstance(value, basestring):
|
||||
value.replace(os.sep, '_')
|
||||
re.sub(r'[' + os.sep + r']|^\.', '_', value)
|
||||
elif key in ('track', 'tracktotal', 'disc', 'disctotal'):
|
||||
|
|
@ -466,11 +473,11 @@ class CollectionQuery(Query):
|
|||
return cls(subqueries)
|
||||
|
||||
class AnySubstringQuery(CollectionQuery):
|
||||
"""A query that matches a substring in any item field. """
|
||||
"""A query that matches a substring in any metadata field. """
|
||||
|
||||
def __init__(self, pattern):
|
||||
subqueries = []
|
||||
for field in item_keys:
|
||||
for field in metadata_rw_keys:
|
||||
subqueries.append(SubstringQuery(field, pattern))
|
||||
super(AnySubstringQuery, self).__init__(subqueries)
|
||||
|
||||
|
|
|
|||
|
|
@ -505,4 +505,12 @@ class MediaFile(object):
|
|||
as_type = bool),
|
||||
flac = StorageStyle('compilation')
|
||||
)
|
||||
|
||||
|
||||
@property
|
||||
def length(self):
|
||||
return self.mgfile.info.length
|
||||
|
||||
@property
|
||||
def bitrate(self):
|
||||
return self.mgfile.info.bitrate
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -30,6 +30,8 @@ def item(lib=None): return beets.library.Item({
|
|||
'bpm': 8,
|
||||
'comp': True,
|
||||
'path': 'somepath',
|
||||
'length': 60.0,
|
||||
'bitrate': 128000,
|
||||
}, lib)
|
||||
np = beets.library._normpath
|
||||
|
||||
|
|
@ -173,4 +175,4 @@ def suite():
|
|||
return unittest.TestLoader().loadTestsFromName(__name__)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(defaultTest='suite')
|
||||
unittest.main(defaultTest='suite')
|
||||
|
|
|
|||
|
|
@ -21,6 +21,21 @@ def MakeReadingTest(path, correct_dict, field):
|
|||
repr(got) + ') when testing ' + os.path.basename(path))
|
||||
return ReadingTest
|
||||
|
||||
def MakeReadOnlyTest(path, field, value):
|
||||
class ReadOnlyTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.f = beets.mediafile.MediaFile(path)
|
||||
def runTest(self):
|
||||
got = getattr(self.f, field)
|
||||
fail_msg = field + ' incorrect (expected ' + \
|
||||
repr(value) + ', got ' + repr(got) + \
|
||||
') on ' + os.path.basename(path)
|
||||
if field == 'length':
|
||||
self.assertTrue(value-0.1 < got < value+0.1, fail_msg)
|
||||
else:
|
||||
self.assertEqual(got, value, fail_msg)
|
||||
return ReadOnlyTest
|
||||
|
||||
def MakeWritingTest(path, correct_dict, field, testsuffix='_test'):
|
||||
|
||||
class WritingTest(unittest.TestCase):
|
||||
|
|
@ -162,6 +177,24 @@ correct_dicts = {
|
|||
|
||||
}
|
||||
|
||||
read_only_correct_dicts = {
|
||||
|
||||
'full.mp3': {
|
||||
'length': 1.0,
|
||||
'bitrate': 80000,
|
||||
},
|
||||
|
||||
'full.flac': {
|
||||
'length': 1.0,
|
||||
},
|
||||
|
||||
'full.m4a': {
|
||||
'length': 1.0,
|
||||
'bitrate': 64000,
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
def suite_for_file(path, correct_dict, writing=True):
|
||||
s = unittest.TestSuite()
|
||||
for field in correct_dict:
|
||||
|
|
@ -191,6 +224,12 @@ def suite():
|
|||
# Special test for advanced release date.
|
||||
s.addTest(suite_for_file(os.path.join('rsrc', 'date.mp3'),
|
||||
correct_dicts['date']))
|
||||
|
||||
# Read-only attribute tests.
|
||||
for fname, correct_dict in read_only_correct_dicts.iteritems():
|
||||
path = os.path.join('rsrc', fname)
|
||||
for field, value in correct_dict.iteritems():
|
||||
s.addTest(MakeReadOnlyTest(path, field, value)())
|
||||
|
||||
return s
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue