From 8a64686ff3d504bab3edcc1d558447ac0913b7db Mon Sep 17 00:00:00 2001 From: Lucas Duailibe Date: Mon, 11 Mar 2013 17:56:13 -0300 Subject: [PATCH 1/4] store fingerprints --- beetsplug/chroma.py | 19 +++++++++++++++++-- docs/plugins/chroma.rst | 5 +++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/beetsplug/chroma.py b/beetsplug/chroma.py index 2e2ce52b5..7722f2f9d 100644 --- a/beetsplug/chroma.py +++ b/beetsplug/chroma.py @@ -112,6 +112,11 @@ def _all_releases(items): yield release_id class AcoustidPlugin(plugins.BeetsPlugin): + def __init__(self): + super(AcoustidPlugin, self).__init__() + self.config.add({ + u'write': False + }) def track_distance(self, item, info): if item.path not in _matches: # Match failed. @@ -150,12 +155,15 @@ class AcoustidPlugin(plugins.BeetsPlugin): def commands(self): submit_cmd = ui.Subcommand('submit', help='submit Acoustid fingerprints') + submit_cmd.parser.add_option('-w', '--write', action='store_true', + help='store the calculated fingerprints') def submit_cmd_func(lib, opts, args): try: apikey = config['acoustid']['apikey'].get(unicode) except confit.NotFoundError: raise ui.UserError('no Acoustid user API key provided') - submit_items(apikey, lib.items(ui.decargs(args))) + submit_items(lib, apikey, lib.items(ui.decargs(args)), + write=opts.write) submit_cmd.func = submit_cmd_func return [submit_cmd] @@ -184,7 +192,7 @@ def apply_acoustid_metadata(task, session): # UI commands. -def submit_items(userkey, items, chunksize=64): +def submit_items(lib, userkey, items, chunksize=64, write=False): """Submit fingerprints for the items to the Acoustid server. """ data = [] # The running list of dictionaries to submit. @@ -212,6 +220,13 @@ def submit_items(userkey, items, chunksize=64): )) try: _, fp = acoustid.fingerprint_file(item.path) + item.acoustid_fingerprint = fp + if write: + log.info(u'{0}: storing fingerprint'.format( + util.displayable_path(item.path) + )) + item.write() + lib.store(item) except acoustid.FingerprintGenerationError as exc: log.info( 'fingerprint generation failed: {0}'.format(exc) diff --git a/docs/plugins/chroma.rst b/docs/plugins/chroma.rst index b24a4816a..1166ada5d 100644 --- a/docs/plugins/chroma.rst +++ b/docs/plugins/chroma.rst @@ -45,7 +45,7 @@ Next, you will need a mechanism for decoding audio files supported by the * On Linux, you can install `GStreamer for Python`_, `FFmpeg`_, or `MAD`_ and `pymad`_. How you install these will depend on your distribution. For example, on Ubuntu, run ``apt-get install python-gst0.10-dev``. On Arch Linux, you want - ``pacman -S gstreamer0.10-python``. + ``pacman -S gstreamer0.10-python``. * On Windows, try the Gstreamer "WinBuilds" from the `OSSBuild`_ project. @@ -94,6 +94,7 @@ value ``apikey`` in a section called ``acoustid`` like so:: Then, run ``beet submit``. (You can also provide a query to submit a subset of your library.) The command will use stored fingerprints if they're available; -otherwise it will fingerprint each file before submitting it. +otherwise it will fingerprint each file before submitting it. The ``-w``option +will store the fingerprints in the library. .. _get an API key: http://acoustid.org/api-key From 3390fd339a1eea51de5821d3e60ba5b9c567ae64 Mon Sep 17 00:00:00 2001 From: Lucas Duailibe Date: Mon, 11 Mar 2013 18:31:53 -0300 Subject: [PATCH 2/4] store fingerprints with the "fingerprint" command --- beetsplug/chroma.py | 86 ++++++++++++++++++++++++----------------- docs/plugins/chroma.rst | 7 +++- 2 files changed, 56 insertions(+), 37 deletions(-) diff --git a/beetsplug/chroma.py b/beetsplug/chroma.py index 7722f2f9d..f2871254a 100644 --- a/beetsplug/chroma.py +++ b/beetsplug/chroma.py @@ -155,17 +155,21 @@ class AcoustidPlugin(plugins.BeetsPlugin): def commands(self): submit_cmd = ui.Subcommand('submit', help='submit Acoustid fingerprints') - submit_cmd.parser.add_option('-w', '--write', action='store_true', - help='store the calculated fingerprints') def submit_cmd_func(lib, opts, args): try: apikey = config['acoustid']['apikey'].get(unicode) except confit.NotFoundError: raise ui.UserError('no Acoustid user API key provided') - submit_items(lib, apikey, lib.items(ui.decargs(args)), - write=opts.write) + submit_items(apikey, lib.items(ui.decargs(args))) submit_cmd.func = submit_cmd_func - return [submit_cmd] + + fingerprint_cmd = ui.Subcommand('fingerprint', + help='fingerprints files with no fingerprint stored') + def fingerprint_cmd_func(lib, opts, args): + for item in lib.items(ui.decargs(args)): + fingerprint_item(item, lib=lib, write=True) + fingerprint_cmd.func = fingerprint_cmd_func + return [submit_cmd, fingerprint_cmd] # Hooks into import process. @@ -192,7 +196,7 @@ def apply_acoustid_metadata(task, session): # UI commands. -def submit_items(lib, userkey, items, chunksize=64, write=False): +def submit_items(userkey, items, chunksize=64): """Submit fingerprints for the items to the Acoustid server. """ data = [] # The running list of dictionaries to submit. @@ -203,35 +207,7 @@ def submit_items(lib, userkey, items, chunksize=64, write=False): del data[:] for item in items: - # Get a fingerprint and length for this track. - if not item.length: - log.info(u'{0}: no duration available'.format( - util.displayable_path(item.path) - )) - continue - elif item.acoustid_fingerprint: - log.info(u'{0}: using existing fingerprint'.format( - util.displayable_path(item.path) - )) - fp = item.acoustid_fingerprint - else: - log.info(u'{0}: fingerprinting'.format( - util.displayable_path(item.path) - )) - try: - _, fp = acoustid.fingerprint_file(item.path) - item.acoustid_fingerprint = fp - if write: - log.info(u'{0}: storing fingerprint'.format( - util.displayable_path(item.path) - )) - item.write() - lib.store(item) - except acoustid.FingerprintGenerationError as exc: - log.info( - 'fingerprint generation failed: {0}'.format(exc) - ) - continue + fp = fingerprint_item(item) # Construct a submission dictionary for this item. item_data = { @@ -261,3 +237,43 @@ def submit_items(lib, userkey, items, chunksize=64, write=False): # Submit remaining data in a final chunk. if data: submit_chunk() + + +def fingerprint_item(item, lib=None, write=False): + """Fingerprints files that don't already have prints stored + """ + # Get a fingerprint and length for this track. + if not item.length: + log.info(u'{0}: no duration available'.format( + util.displayable_path(item.path) + )) + return + elif item.acoustid_fingerprint: + if not write: + log.info(u'{0}: using existing fingerprint'.format( + util.displayable_path(item.path) + )) + return item.acoustid_fingerprint + log.info(u'{0}: skipping. fingerprint exsists'.format( + util.displayable_path(item.path) + )) + else: + log.info(u'{0}: fingerprinting'.format( + util.displayable_path(item.path) + )) + try: + _, fp = acoustid.fingerprint_file(item.path) + item.acoustid_fingerprint = fp + if write and lib is not None: + log.info(u'{0}: writing fingerprint'.format( + util.displayable_path(item.path) + )) + item.write() + lib.store(item) + return item.acoustid_fingerprint + except acoustid.FingerprintGenerationError as exc: + log.info( + 'fingerprint generation failed: {0}'.format(exc) + ) + return + diff --git a/docs/plugins/chroma.rst b/docs/plugins/chroma.rst index 1166ada5d..0677ca957 100644 --- a/docs/plugins/chroma.rst +++ b/docs/plugins/chroma.rst @@ -78,6 +78,10 @@ editing your :doc:`configuration file `. Put ``chroma`` on your ``plugins:`` line. With that, beets will use fingerprinting the next time you run ``beet import``. +You can also use ``beet fingerprint`` to fingerprint the tracks already imported +without fingerprints. (You can provide a query to fingerprint a subset of your +library). + .. _submitfp: Submitting Fingerprints @@ -94,7 +98,6 @@ value ``apikey`` in a section called ``acoustid`` like so:: Then, run ``beet submit``. (You can also provide a query to submit a subset of your library.) The command will use stored fingerprints if they're available; -otherwise it will fingerprint each file before submitting it. The ``-w``option -will store the fingerprints in the library. +otherwise it will fingerprint each file before submitting it. .. _get an API key: http://acoustid.org/api-key From a6ae5c4a4fb680fffbfa96ff7374f6bbbc579030 Mon Sep 17 00:00:00 2001 From: Lucas Duailibe Date: Mon, 11 Mar 2013 19:22:03 -0300 Subject: [PATCH 3/4] cleaning up --- beetsplug/chroma.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/beetsplug/chroma.py b/beetsplug/chroma.py index f2871254a..edb6a7282 100644 --- a/beetsplug/chroma.py +++ b/beetsplug/chroma.py @@ -112,11 +112,6 @@ def _all_releases(items): yield release_id class AcoustidPlugin(plugins.BeetsPlugin): - def __init__(self): - super(AcoustidPlugin, self).__init__() - self.config.add({ - u'write': False - }) def track_distance(self, item, info): if item.path not in _matches: # Match failed. From 704259b4595150fad26a34f62384b8b98b290e79 Mon Sep 17 00:00:00 2001 From: Lucas Duailibe Date: Mon, 11 Mar 2013 19:26:33 -0300 Subject: [PATCH 4/4] fix typo --- beetsplug/chroma.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beetsplug/chroma.py b/beetsplug/chroma.py index edb6a7282..e8df67497 100644 --- a/beetsplug/chroma.py +++ b/beetsplug/chroma.py @@ -249,7 +249,7 @@ def fingerprint_item(item, lib=None, write=False): util.displayable_path(item.path) )) return item.acoustid_fingerprint - log.info(u'{0}: skipping. fingerprint exsists'.format( + log.info(u'{0}: skipping. fingerprint exists'.format( util.displayable_path(item.path) )) else: