audio: Remove min duration code from scanner.

The local scanner now handles this itself by looking at the duration.
This commit is contained in:
Thomas Adamcik 2014-12-16 22:50:01 +01:00
parent 4f8244c499
commit de6bd63481
4 changed files with 35 additions and 37 deletions

View File

@ -18,13 +18,10 @@ class Scanner(object):
:param timeout: timeout for scanning a URI in ms :param timeout: timeout for scanning a URI in ms
:type event: int :type event: int
:param min_duration: minimum duration of scanned URI in ms, -1 for all.
:type event: int
""" """
def __init__(self, timeout=1000, min_duration=100): def __init__(self, timeout=1000):
self._timeout_ms = timeout self._timeout_ms = timeout
self._min_duration_ms = min_duration
sink = gst.element_factory_make('fakesink') sink = gst.element_factory_make('fakesink')
@ -52,20 +49,15 @@ class Scanner(object):
the tags we found and duration is the length of the URI in the tags we found and duration is the length of the URI in
milliseconds, or :class:`None` if the URI has no duration. milliseconds, or :class:`None` if the URI has no duration.
""" """
tags, duration = None, None
try: try:
self._setup(uri) self._setup(uri)
tags = self._collect() # Ensure collect before queries. tags = self._collect()
duration = self._query_duration() duration = self._query_duration()
finally: finally:
self._reset() self._reset()
if self._min_duration_ms is None:
return tags, duration return tags, duration
elif duration >= self._min_duration_ms:
return tags, duration
raise exceptions.ScannerError('Rejecting file with less than %dms '
'audio data.' % self._min_duration_ms)
def _setup(self, uri): def _setup(self, uri):
"""Primes the pipeline for collection.""" """Primes the pipeline for collection."""
@ -80,7 +72,7 @@ class Scanner(object):
def _collect(self): def _collect(self):
"""Polls for messages to collect data.""" """Polls for messages to collect data."""
start = time.time() start = time.time()
timeout_s = self._timeout_ms / 1000. timeout_s = self._timeout_ms / 1000.0
tags = {} tags = {}
while time.time() - start < timeout_s: while time.time() - start < timeout_s:

View File

@ -13,6 +13,8 @@ from mopidy.utils import path
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
MIN_DURATION_MS = 100 # Shortest length of track to include.
def _get_library(args, config): def _get_library(args, config):
libraries = dict((l.name, l) for l in args.registry['local:library']) libraries = dict((l.name, l) for l in args.registry['local:library'])
@ -128,6 +130,9 @@ class ScanCommand(commands.Command):
relpath = translator.local_track_uri_to_path(uri, media_dir) relpath = translator.local_track_uri_to_path(uri, media_dir)
file_uri = path.path_to_uri(os.path.join(media_dir, relpath)) file_uri = path.path_to_uri(os.path.join(media_dir, relpath))
tags, duration = scanner.scan(file_uri) tags, duration = scanner.scan(file_uri)
if duration < MIN_DURATION_MS:
logger.warning('Failed %s: Track shorter than 100ms', uri)
else:
# TODO: reuse mtime from above... # TODO: reuse mtime from above...
mtime = os.path.getmtime(os.path.join(media_dir, relpath)) mtime = os.path.getmtime(os.path.join(media_dir, relpath))
track = scan.tags_to_track(tags).copy( track = scan.tags_to_track(tags).copy(

View File

@ -31,7 +31,7 @@ class StreamBackend(pykka.ThreadingActor, backend.Backend):
class StreamLibraryProvider(backend.LibraryProvider): class StreamLibraryProvider(backend.LibraryProvider):
def __init__(self, backend, timeout, blacklist): def __init__(self, backend, timeout, blacklist):
super(StreamLibraryProvider, self).__init__(backend) super(StreamLibraryProvider, self).__init__(backend)
self._scanner = scan.Scanner(min_duration=None, timeout=timeout) self._scanner = scan.Scanner(timeout=timeout)
self._blacklist_re = re.compile( self._blacklist_re = re.compile(
r'^(%s)$' % '|'.join(fnmatch.translate(u) for u in blacklist)) r'^(%s)$' % '|'.join(fnmatch.translate(u) for u in blacklist))

View File

@ -277,14 +277,10 @@ class ScannerTest(unittest.TestCase):
except exceptions.ScannerError as error: except exceptions.ScannerError as error:
self.errors[key] = error self.errors[key] = error
def check_tag(self, name, key, value): def check(self, name, key, value):
name = path_to_data_dir(name) name = path_to_data_dir(name)
self.assertEqual(self.tags[name][key], value) self.assertEqual(self.tags[name][key], value)
def check_duration(self, name, value):
name = path_to_data_dir(name)
self.assertEqual(self.durations[name], value)
def test_tags_is_set(self): def test_tags_is_set(self):
self.scan(self.find('scanner/simple')) self.scan(self.find('scanner/simple'))
self.assert_(self.tags) self.assert_(self.tags)
@ -295,23 +291,26 @@ class ScannerTest(unittest.TestCase):
def test_duration_is_set(self): def test_duration_is_set(self):
self.scan(self.find('scanner/simple')) self.scan(self.find('scanner/simple'))
self.check_duration('scanner/simple/song1.mp3', 4680)
self.check_duration('scanner/simple/song1.ogg', 4680) self.assertEqual(
self.durations[path_to_data_dir('scanner/simple/song1.mp3')], 4680)
self.assertEqual(
self.durations[path_to_data_dir('scanner/simple/song1.ogg')], 4680)
def test_artist_is_set(self): def test_artist_is_set(self):
self.scan(self.find('scanner/simple')) self.scan(self.find('scanner/simple'))
self.check_tag('scanner/simple/song1.mp3', 'artist', ['name']) self.check('scanner/simple/song1.mp3', 'artist', ['name'])
self.check_tag('scanner/simple/song1.ogg', 'artist', ['name']) self.check('scanner/simple/song1.ogg', 'artist', ['name'])
def test_album_is_set(self): def test_album_is_set(self):
self.scan(self.find('scanner/simple')) self.scan(self.find('scanner/simple'))
self.check_tag('scanner/simple/song1.mp3', 'album', ['albumname']) self.check('scanner/simple/song1.mp3', 'album', ['albumname'])
self.check_tag('scanner/simple/song1.ogg', 'album', ['albumname']) self.check('scanner/simple/song1.ogg', 'album', ['albumname'])
def test_track_is_set(self): def test_track_is_set(self):
self.scan(self.find('scanner/simple')) self.scan(self.find('scanner/simple'))
self.check_tag('scanner/simple/song1.mp3', 'title', ['trackname']) self.check('scanner/simple/song1.mp3', 'title', ['trackname'])
self.check_tag('scanner/simple/song1.ogg', 'title', ['trackname']) self.check('scanner/simple/song1.ogg', 'title', ['trackname'])
def test_nonexistant_dir_does_not_fail(self): def test_nonexistant_dir_does_not_fail(self):
self.scan(self.find('scanner/does-not-exist')) self.scan(self.find('scanner/does-not-exist'))
@ -323,11 +322,13 @@ class ScannerTest(unittest.TestCase):
def test_log_file_that_gst_thinks_is_mpeg_1_is_ignored(self): def test_log_file_that_gst_thinks_is_mpeg_1_is_ignored(self):
self.scan([path_to_data_dir('scanner/example.log')]) self.scan([path_to_data_dir('scanner/example.log')])
self.assert_(self.errors) self.assertLess(
self.durations[path_to_data_dir('scanner/example.log')], 100)
def test_empty_wav_file_is_ignored(self): def test_empty_wav_file(self):
self.scan([path_to_data_dir('scanner/empty.wav')]) self.scan([path_to_data_dir('scanner/empty.wav')])
self.assert_(self.errors) self.assertEqual(
self.durations[path_to_data_dir('scanner/empty.wav')], 0)
@unittest.SkipTest @unittest.SkipTest
def test_song_without_time_is_handeled(self): def test_song_without_time_is_handeled(self):