From 0e6878ef8a4fc46093bdb65db2f4f0049d3646cf Mon Sep 17 00:00:00 2001 From: Philipp Wolfer Date: Sat, 6 Jan 2024 15:11:03 +0100 Subject: [PATCH 1/3] PICARD-2813: Ignore fpcalc errors if there was still a result. If fpcalc encounters a recording error for which it still was able to generate a result it will return the special return code 3. Continue receiving results if this code was returned. --- picard/acoustid/__init__.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/picard/acoustid/__init__.py b/picard/acoustid/__init__.py index 5fca8321b..2ecbf0f7a 100644 --- a/picard/acoustid/__init__.py +++ b/picard/acoustid/__init__.py @@ -6,7 +6,7 @@ # Copyright (C) 2017-2018 Sambhav Kothari # Copyright (C) 2018 Vishal Choudhary # Copyright (C) 2018-2021 Laurent Monin -# Copyright (C) 2018-2023 Philipp Wolfer +# Copyright (C) 2018-2024 Philipp Wolfer # Copyright (C) 2023 Bob Swift # # This program is free software; you can redistribute it and/or @@ -203,7 +203,9 @@ class AcoustIDClient(QtCore.QObject): try: self._running -= 1 self._run_next_task() - if exit_code == 0 and exit_status == QtCore.QProcess.ExitStatus.NormalExit: + # fpcalc returns the exit code 3 in case of decoding errors that + # still allowed it to calculate a result. + if exit_code in {0, 3} and exit_status == QtCore.QProcess.ExitStatus.NormalExit: output = bytes(process.readAllStandardOutput()).decode() jsondata = json.loads(output) # Use only integer part of duration, floats are not allowed in lookup @@ -222,7 +224,11 @@ class AcoustIDClient(QtCore.QObject): finally: if result and result[0] == 'fingerprint': fp_type, fingerprint, length = result - task.file.set_acoustid_fingerprint(fingerprint, length) + # Only set the fingerprint if it was calculated without + # decoding errors. Otherwise fingerprints for broken files + # might get submitted. + if exit_code == 0: + task.file.set_acoustid_fingerprint(fingerprint, length) task.next_func(result) def _on_fpcalc_error(self, task, error): From 7f6d752274d294a609b719a7d57ecee7198b28fc Mon Sep 17 00:00:00 2001 From: Philipp Wolfer Date: Mon, 8 Jan 2024 07:43:14 +0100 Subject: [PATCH 2/3] PICARD-2813: Use constants for fpcalc exit codes --- picard/acoustid/__init__.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/picard/acoustid/__init__.py b/picard/acoustid/__init__.py index 2ecbf0f7a..327b3a3ee 100644 --- a/picard/acoustid/__init__.py +++ b/picard/acoustid/__init__.py @@ -28,6 +28,7 @@ from collections import ( deque, namedtuple, ) +from enum import IntEnum from functools import partial import json @@ -49,6 +50,13 @@ from picard.util import ( from picard.webservice.api_helpers import AcoustIdAPIHelper +class FpcalcExit(IntEnum): + # fpcalc returned successfully + NOERROR = 0 + # fpcalc encountered errors during decoding, but could still generate a fingerprint + DECODING_ERROR = 3 + + def get_score(node): try: return float(node.get('score', 1.0)) @@ -205,7 +213,7 @@ class AcoustIDClient(QtCore.QObject): self._run_next_task() # fpcalc returns the exit code 3 in case of decoding errors that # still allowed it to calculate a result. - if exit_code in {0, 3} and exit_status == QtCore.QProcess.ExitStatus.NormalExit: + if exit_code in {FpcalcExit.NOERROR, FpcalcExit.DECODING_ERROR} and exit_status == QtCore.QProcess.ExitStatus.NormalExit: output = bytes(process.readAllStandardOutput()).decode() jsondata = json.loads(output) # Use only integer part of duration, floats are not allowed in lookup @@ -227,7 +235,7 @@ class AcoustIDClient(QtCore.QObject): # Only set the fingerprint if it was calculated without # decoding errors. Otherwise fingerprints for broken files # might get submitted. - if exit_code == 0: + if exit_code == FpcalcExit.NOERROR: task.file.set_acoustid_fingerprint(fingerprint, length) task.next_func(result) From cf1e5aa48b10c42ad28d208b66bfcffecf274c81 Mon Sep 17 00:00:00 2001 From: Philipp Wolfer Date: Mon, 8 Jan 2024 12:16:47 +0100 Subject: [PATCH 3/3] PICARD-2813: Log a warning on fpcalc decoding issues --- picard/acoustid/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/picard/acoustid/__init__.py b/picard/acoustid/__init__.py index 327b3a3ee..94cd01c21 100644 --- a/picard/acoustid/__init__.py +++ b/picard/acoustid/__init__.py @@ -214,6 +214,9 @@ class AcoustIDClient(QtCore.QObject): # fpcalc returns the exit code 3 in case of decoding errors that # still allowed it to calculate a result. if exit_code in {FpcalcExit.NOERROR, FpcalcExit.DECODING_ERROR} and exit_status == QtCore.QProcess.ExitStatus.NormalExit: + if exit_code == FpcalcExit.DECODING_ERROR: + error = bytes(process.readAllStandardError()).decode() + log.warning("fpcalc non-critical decoding errors for %s: %s", task.file, error) output = bytes(process.readAllStandardOutput()).decode() jsondata = json.loads(output) # Use only integer part of duration, floats are not allowed in lookup