Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package r128gain for openSUSE:Factory checked in at 2023-03-26 20:19:49 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/r128gain (Old) and /work/SRC/openSUSE:Factory/.r128gain.new.31432 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "r128gain" Sun Mar 26 20:19:49 2023 rev:6 rq:1074378 version:1.0.7 Changes: -------- --- /work/SRC/openSUSE:Factory/r128gain/r128gain.changes 2021-10-25 15:18:44.189724517 +0200 +++ /work/SRC/openSUSE:Factory/.r128gain.new.31432/r128gain.changes 2023-03-26 20:19:50.419159675 +0200 @@ -1,0 +2,19 @@ +Sat Mar 25 20:23:48 UTC 2023 - Martin Hauke <mar...@gmx.de> + +- Update to version 1.0.7 + * feat: warn if input is not a directory in recursive mode. + * refactor: reduce get_r128_loudness complexity. + * fix: mypy pre-commit hook error. + * fix: workaround ffmpeg ebur128 filter early stop with concat. + * fix: improve ffmpeg ebur128 output parsing. + * fix: wrong replaygain sample peak calculation for non standard + sample rates. + * fix: don't map ffmpeg filter output. + * feat: make progress output persistant. + * feat: log filter script +- Update to version 1.0.6 + * no functional changes +- Update to version 1.0.5 + * no functional changes + +------------------------------------------------------------------- Old: ---- r128gain-1.0.4.tar.gz New: ---- r128gain-1.0.7.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ r128gain.spec ++++++ --- /var/tmp/diff_new_pack.Q4MMNC/_old 2023-03-26 20:19:50.867162016 +0200 +++ /var/tmp/diff_new_pack.Q4MMNC/_new 2023-03-26 20:19:50.875162058 +0200 @@ -1,8 +1,8 @@ # # spec file for package r128gain # -# Copyright (c) 2021 SUSE LLC -# Copyright (c) 2020-2021, Martin Hauke <mar...@gmx.de> +# Copyright (c) 2023 SUSE LLC +# Copyright (c) 2020-2023, Martin Hauke <mar...@gmx.de> # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,7 +18,7 @@ Name: r128gain -Version: 1.0.4 +Version: 1.0.7 Release: 0 Summary: Fast audio loudness (ReplayGain / R128) scanner & tagger License: LGPL-2.0-only ++++++ r128gain-1.0.4.tar.gz -> r128gain-1.0.7.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/r128gain-1.0.4/.github/workflows/ci.yml new/r128gain-1.0.7/.github/workflows/ci.yml --- old/r128gain-1.0.4/.github/workflows/ci.yml 2021-10-23 22:55:38.000000000 +0200 +++ new/r128gain-1.0.7/.github/workflows/ci.yml 2023-03-25 20:41:32.000000000 +0100 @@ -9,11 +9,12 @@ - uses: pre-commit/action@v2.0.0 test: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 strategy: + fail-fast: false matrix: - python-version: [3.6, 3.7, 3.8, 3.9] - ffmpeg-version: ["2.8", "3.0", "3.1", "3.2", "3.3", "3.4", "4.0", "4.1", "4.2", "4.3", "master"] + python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"] + ffmpeg-version: ["4.1", "4.2", "4.3", "4.4", "5.0", "master"] steps: - uses: actions/checkout@v2 @@ -29,7 +30,8 @@ path: ~/.cache/ci/r128gain key: ${{runner.os}}-ffmpeg-${{hashFiles('ci/build-minimal-ffmpeg')}}-${{matrix.ffmpeg-version}} - run: | - sudo apt-get install yasm + sudo apt-get update -q + sudo apt-get install -q yasm sox ./ci/build-minimal-ffmpeg ${{matrix.ffmpeg-version}} echo "$HOME/.local/bin" >> $GITHUB_PATH - run: | @@ -43,25 +45,21 @@ test-win: runs-on: ubuntu-latest + container: + image: fedora:latest strategy: + fail-fast: false matrix: - win-version: ["win32", "win64"] + bits: [32, 64] steps: - uses: actions/checkout@v2 - - run: sudo apt-get install p7zip-full mingw-w64 - - if: ${{matrix.win-version == 'win32'}} - run: | - sudo dpkg --add-architecture i386 - sudo apt-get update - sudo apt-get install wine32 - - if: ${{matrix.win-version == 'win64'}} - run: sudo apt-get install wine64 + # wine-core(x86-32) is needed in both cases because sox.exe is 32-bit + - run: sudo dnf --setopt=install_weak_deps=False install -y 'wine-core(x86-${{matrix.bits}})' 'wine-core(x86-32)' make git-core mingw${{matrix.bits}}-gcc yasm diffutils redhat-lsb-core p7zip-plugins - run: make -C win all test env: DOWNLOAD_DIR: /home/runner/.cache/ci/r128gain/build TEST_DL_CACHE_DIR: /home/runner/.cache/ci/r128gain/test - FFMPEG_CACHE_DIR: /home/runner/.cache/ci/r128gain/ffmpeg-${{matrix.win-version}} - FFMPEG_VERSION: 3.4 - WINEARCH: ${{matrix.win-version}} - continue-on-error: true + FFMPEG_CACHE_DIR: /home/runner/.cache/ci/r128gain/ffmpeg-win${{matrix.bits}} + FFMPEG_VERSION: "5.0" + WINEARCH: win${{matrix.bits}} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/r128gain-1.0.4/.pre-commit-config.yaml new/r128gain-1.0.7/.pre-commit-config.yaml --- old/r128gain-1.0.4/.pre-commit-config.yaml 2021-10-23 22:55:38.000000000 +0200 +++ new/r128gain-1.0.7/.pre-commit-config.yaml 2023-03-25 20:41:32.000000000 +0100 @@ -1,7 +1,7 @@ # https://pre-commit.com repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.0.1 + rev: v4.3.0 hooks: - id: check-added-large-files - id: check-case-conflict @@ -24,13 +24,15 @@ - --markdown-linebreak-ext=md - repo: https://github.com/pre-commit/mirrors-mypy - rev: v0.812 + rev: v0.971 hooks: - id: mypy + additional_dependencies: + - types-requests args: - --ignore-missing-imports - - repo: https://gitlab.com/pycqa/flake8 + - repo: https://github.com/pycqa/flake8 rev: 3.9.2 hooks: - id: flake8 @@ -51,12 +53,12 @@ - --ignore=D105,D107,D202,D210,D211,D212 - repo: https://github.com/shellcheck-py/shellcheck-py - rev: v0.7.2.1 + rev: v0.8.0.4 hooks: - id: shellcheck - repo: https://github.com/pre-commit/mirrors-isort - rev: v5.9.3 + rev: v5.10.1 hooks: - id: isort args: @@ -65,7 +67,7 @@ - --profile=black - repo: https://github.com/psf/black - rev: 21.9b0 + rev: 22.6.0 hooks: - id: black language_version: python3 @@ -73,7 +75,7 @@ - --line-length=120 - repo: https://github.com/pre-commit/mirrors-prettier - rev: v2.4.1 + rev: v2.7.1 hooks: - id: prettier args: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/r128gain-1.0.4/ci/build-minimal-ffmpeg new/r128gain-1.0.7/ci/build-minimal-ffmpeg --- old/r128gain-1.0.4/ci/build-minimal-ffmpeg 2021-10-23 22:55:38.000000000 +0200 +++ new/r128gain-1.0.7/ci/build-minimal-ffmpeg 2023-03-25 20:41:32.000000000 +0100 @@ -10,6 +10,16 @@ readonly PROC_COUNT=$(grep -c '^processor' /proc/cpuinfo) +parse_audio_decoders() { + # The lines between /* audio codecs */ and /* subtitles */ are audio + # codecs. Parse them out and filter out only decoders. + + # shellcheck disable=SC2016 + sed -n '/^\/\* audio codecs \*\/$/,${p;/^\/\* subtitles \*\/$/q}' \ + libavcodec/allcodecs.c | \ + sed -n 's/extern .*Codec ff_\(.*\)_decoder;/\1/p' +} + configure() { ./configure --prefix="${INSTALL_DIR}" \ --enable-gpl \ @@ -24,8 +34,7 @@ --disable-encoders \ --enable-encoder=pcm_s16le \ --disable-decoders \ - $(ffmpeg -hide_banner -codecs | grep '^ D.A' | cut -d ' ' -f 3 | xargs -I'{}' echo --enable-decoder={}) \ - --enable-decoder=dnxhd \ + $(parse_audio_decoders | xargs -I'{}' echo --enable-decoder={}) \ --disable-hwaccels \ --disable-muxers \ --enable-muxer=null \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/r128gain-1.0.4/freeze.py new/r128gain-1.0.7/freeze.py --- old/r128gain-1.0.4/freeze.py 2021-10-23 22:55:38.000000000 +0200 +++ new/r128gain-1.0.7/freeze.py 2023-03-25 20:41:32.000000000 +0100 @@ -1,5 +1,3 @@ -#!/usr/bin/env python3 - """ Package freezing for Windows. """ import os @@ -12,7 +10,7 @@ assert version_match is not None version = version_match.group(1) -build_exe_options = {"optimize": 0, "excludes": ["tkinter"]} +build_exe_options = {"includes": [], "packages": [], "optimize": 0, "excludes": []} setup( name="r128gain", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/r128gain-1.0.4/r128gain/__init__.py new/r128gain-1.0.7/r128gain/__init__.py --- old/r128gain-1.0.4/r128gain/__init__.py 2021-10-23 22:55:38.000000000 +0200 +++ new/r128gain-1.0.7/r128gain/__init__.py 2023-03-25 20:41:32.000000000 +0100 @@ -2,7 +2,7 @@ """ Scan audio files and tag them with ReplayGain/R128 loudness metadata. """ -__version__ = "1.0.4" +__version__ = "1.0.7" __author__ = "desbma" __license__ = "LGPLv2" @@ -21,6 +21,7 @@ import shutil import subprocess import sys +import tempfile import threading from typing import Callable, Dict, List, Optional, Sequence, Tuple, Union @@ -51,6 +52,7 @@ OPTIMAL_THREAD_COUNT = len(os.sched_getaffinity(0)) except AttributeError: OPTIMAL_THREAD_COUNT = os.cpu_count() # type: ignore +RE_ANULLSINK_REPLACE_OUTPUT = (re.compile(r"]anullsink(\[s\d+\])"), "]anullsink") def logger() -> logging.Logger: @@ -99,7 +101,41 @@ return r -def get_r128_loudness( +def run_ffmpeg(cmd: List[str]) -> bytes: + """Run FFmpeg command, and get stderr bytes.""" + # workaround https://github.com/kkroening/ffmpeg-python/issues/161 + python-ffmpeg incorrect handling of anullsink + filter_opt_index = cmd.index("-filter_complex") + filter_script = cmd[filter_opt_index + 1] + anullsink_pads = [] + for match in RE_ANULLSINK_REPLACE_OUTPUT[0].finditer(filter_script): + pad = match.group(1) + anullsink_pads.append(pad) + map_opt_idx = -1 + while True: + try: + map_opt_idx = cmd.index("-map", map_opt_idx + 1) + except ValueError: + break + if cmd[map_opt_idx + 1] in anullsink_pads: + cmd = cmd[:map_opt_idx] + cmd[map_opt_idx + 2 :] + map_opt_idx -= 1 + filter_opt_index = cmd.index("-filter_complex") + filter_script = RE_ANULLSINK_REPLACE_OUTPUT[0].sub(RE_ANULLSINK_REPLACE_OUTPUT[1], filter_script) + logger().debug(f"Filter script: {filter_script}") + with tempfile.TemporaryDirectory(prefix="r128gain_") as tmp_dir: + tmp_script_filepath = os.path.join(tmp_dir, "ffmpeg_filters") + with open(tmp_script_filepath, "wt") as f: + f.write(filter_script) + cmd[filter_opt_index] = "-filter_complex_script" + cmd[filter_opt_index + 1] = tmp_script_filepath + + # run + logger().debug(cmd_to_string(cmd)) + output = subprocess.run(cmd, check=True, stdin=subprocess.DEVNULL, stderr=subprocess.PIPE).stderr + return output + + +def get_r128_loudness( # noqa: C901 audio_filepaths: Sequence[str], *, calc_peak: bool = True, @@ -132,18 +168,15 @@ output_streams = [] ffmpeg_r128_streams = [] for ffmpeg_input in ffmpeg_inputs: + ffmpeg_input = ffmpeg_input.filter("aformat", sample_fmts="s16", sample_rates="48000", channel_layouts="stereo") if calc_peak: split_streams = ffmpeg_input.filter_multi_output("asplit", outputs=2) ffmpeg_rg_stream, ffmpeg_r128_stream = split_streams[0], split_streams[1] - ffmpeg_rg_stream = ffmpeg_rg_stream.filter("aformat", sample_fmts="s16", channel_layouts="stereo") ffmpeg_rg_stream = ffmpeg_rg_stream.filter("replaygain") + ffmpeg_rg_stream = ffmpeg_rg_stream.filter("anullsink") output_streams.append(ffmpeg_rg_stream) else: ffmpeg_r128_stream = ffmpeg_input - ffmpeg_r128_stream = ffmpeg_r128_stream.filter( - "aformat", sample_fmts="s16", sample_rates="48000", channel_layouts="stereo" - ) - ffmpeg_r128_stream = ffmpeg_r128_stream.filter("afifo") # needed for FFmpeg < 4.1 ffmpeg_r128_streams.append(ffmpeg_r128_stream) if len(audio_filepaths) > 1: @@ -165,8 +198,7 @@ ) # run - logger().debug(cmd_to_string(cmd)) - output = subprocess.run(cmd, check=True, stdin=subprocess.DEVNULL, stderr=subprocess.PIPE).stderr + output = run_ffmpeg(cmd) output_lines = output.decode("utf-8", errors="replace").splitlines() if calc_peak: @@ -182,13 +214,16 @@ sample_peak = None # parse r128 filter output - for i in reversed(range(len(output_lines))): - line = output_lines[i] + unrelated_line = True + for line in filter(str.strip, output_lines): if line.startswith("[Parsed_ebur128_") and line.endswith("Summary:"): - break - output_lines_r128 = filter( - lambda x: x and not x.startswith("[Parsed_replaygain_"), map(str.strip, output_lines[i:]) - ) + output_lines_r128 = [line.strip()] + unrelated_line = False + elif not unrelated_line: + if line.startswith(" "): + output_lines_r128.append(line.strip()) + else: + unrelated_line = True r128_stats_raw: Dict[str, str] = dict( tuple(map(str.strip, line.split(":", 1))) # type: ignore for line in output_lines_r128 @@ -315,7 +350,7 @@ def float_to_q7dot8(f: float) -> int: """Encode float f to a fixed point Q7.8 integer.""" # https://en.wikipedia.org/wiki/Q_(number_format)#Float_to_Q - return int(round(f * (2 ** 8), 0)) + return int(round(f * (2**8), 0)) def gain_to_scale(gain: float) -> float: @@ -639,8 +674,11 @@ # walk directories albums_filepaths = [] walk_stats = collections.OrderedDict((k, 0) for k in ("files", "dirs")) - with dynamic_tqdm(desc="Analyzing directories", unit=" dir", postfix=walk_stats, leave=False) as progress: + with dynamic_tqdm(desc="Analyzing directories", unit=" dir", postfix=walk_stats, leave=True) as progress: for input_directory in directories: + if not os.path.isdir(input_directory): + logging.getLogger().warning(f"{input_directory!r} is not a directory, ignoring") + continue for root_dir, subdirs, filepaths in os.walk(input_directory, followlinks=False): audio_filepaths = tuple( map(functools.partial(os.path.join, root_dir), filter(is_audio_filepath, filepaths)) @@ -686,7 +724,7 @@ total=sum(map(len, albums_filepaths)) + int(album_gain) * len(albums_filepaths), desc="Analyzing audio loudness", unit=" files", - leave=False, + leave=True, smoothing=0, ) as progress: # get results @@ -917,7 +955,8 @@ ) if err_count > 0: - exit(1) + # freeze target can not use exit directly + sys.exit(1) if getattr(sys, "frozen", False): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/r128gain-1.0.4/release new/r128gain-1.0.7/release --- old/r128gain-1.0.4/release 1970-01-01 01:00:00.000000000 +0100 +++ new/r128gain-1.0.7/release 2023-03-25 20:41:32.000000000 +0100 @@ -0,0 +1,16 @@ +#!/bin/bash -eu + +set -o pipefail + +readonly VERSION=${1:?} + + +cd "$(git rev-parse --show-toplevel)" + +sed -i "s/^\(__version__ = \"\).*\(\"\)/\1$VERSION\2/w /dev/stdout" r128gain/__init__.py + +git add r128gain/__init__.py + +git commit -m "Version ${VERSION}" + +git tag -m "Version ${VERSION}" "${VERSION}" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/r128gain-1.0.4/setup.py new/r128gain-1.0.7/setup.py --- old/r128gain-1.0.4/setup.py 2021-10-23 22:55:38.000000000 +0200 +++ new/r128gain-1.0.7/setup.py 2023-03-25 20:41:32.000000000 +0100 @@ -66,6 +66,8 @@ "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", "Topic :: Multimedia :: Sound/Audio :: Analysis", "Topic :: Utilities", ], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/r128gain-1.0.4/tests/__init__.py new/r128gain-1.0.7/tests/__init__.py --- old/r128gain-1.0.4/tests/__init__.py 2021-10-23 22:55:38.000000000 +0200 +++ new/r128gain-1.0.7/tests/__init__.py 2023-03-25 20:41:32.000000000 +0100 @@ -24,6 +24,9 @@ IS_TRAVIS = os.getenv("CI") and os.getenv("TRAVIS") +# WikiMedia rejects requests with the default User-Agent - fake a browser one +DUMMY_HEADERS = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"} + def download(url: str, filepath: str): """Download URL to local file.""" @@ -34,8 +37,8 @@ if os.path.isfile(cache_filepath): shutil.copyfile(cache_filepath, filepath) return - with requests.get(url, stream=True) as response, open(filepath, "wb") as file: - for chunk in response.iter_content(chunk_size=2 ** 14): + with requests.get(url, headers=DUMMY_HEADERS, stream=True) as response, open(filepath, "wb") as file: + for chunk in response.iter_content(chunk_size=2**14): file.write(chunk) if cache_dir is not None: shutil.copyfile(filepath, cache_filepath) @@ -96,6 +99,9 @@ shutil.copyfileobj(in_file, out_file) os.remove(flac_zic_filepath) + flac_filepath = os.path.join(cls.ref_temp_dir2.name, "f.flac") + download("https://www.dropbox.com/s/xejktantsrm4mbi/1-03_stolen_focus_cut.flac?dl=1", flac_filepath) + wv_filepath = os.path.join(cls.ref_temp_dir.name, "f.wv") cmd = ( "sox", @@ -169,6 +175,7 @@ self.aac_filepath = os.path.join(self.temp_dir.name, "f.aac") self.flac_filepath = os.path.join(self.temp_dir.name, "f.flac") self.flac_filepath_2 = os.path.join(self.temp_dir.name, "f2.flac") + self.flac_filepath_weird_sample_rate = os.path.join(self.temp_dir2.name, "f.flac") self.wv_filepath = os.path.join(self.temp_dir.name, "f.wv") self.silence_wv_filepath = os.path.join(self.temp_dir.name, "silence.wv") self.silence_mp3_filepath = os.path.join(self.temp_dir.name, "silence.mp3") @@ -177,21 +184,24 @@ self.vorbis_filepath: (-7.7, 1.0), self.opus_filepath: (-14.7, None), self.mp3_filepath: (-13.9, 0.94281), - self.m4a_filepath: (-20.6, 0.711426), + self.m4a_filepath: (-20.6, 0.710449), self.aac_filepath: (-9.0, 1.0), - self.flac_filepath: (-26.7, 0.232147), - self.wv_filepath: (-3.3, 0.705017), + self.flac_filepath: (-26.7, 0.232025), + self.wv_filepath: (-3.3, 0.709442), 0: (-10.6, 1.0), } self.ref_levels_2 = self.ref_levels.copy() self.ref_levels_2.update( { self.flac_filepath_2: (-6.2, 1.0), - self.silence_wv_filepath: (-70.0, 0.000031), + self.silence_wv_filepath: (-70.0, 0.000061), self.silence_mp3_filepath: (-70.0, 0.0), 0: (-10.3, 1.0), } ) + self.ref_levels_alt = { + self.flac_filepath_weird_sample_rate: (-14.1, 0.848785), + } self.max_peak_filepath = self.vorbis_filepath @@ -259,6 +269,15 @@ ref_levels_opus[r128gain.ALBUM_GAIN_KEY] = self.ref_levels[self.opus_filepath] self.assertEqual(r128gain.scan(filepaths, album_gain=album_gain), ref_levels_opus) + # weird sample rate + filepaths = (self.flac_filepath_weird_sample_rate,) + ref_levels_flac = { + self.flac_filepath_weird_sample_rate: self.ref_levels_alt[self.flac_filepath_weird_sample_rate], + } + if album_gain: + ref_levels_flac[r128gain.ALBUM_GAIN_KEY] = self.ref_levels_alt[self.flac_filepath_weird_sample_rate] + self.assertEqual(r128gain.scan(filepaths, album_gain=album_gain), ref_levels_flac) + if album_gain: # file order should not change results filepaths = ( @@ -327,7 +346,7 @@ mf = mutagen.File(self.opus_filepath) self.assertIsInstance(mf.tags, mutagen._vorbis.VComment) self.assertIn("R128_TRACK_GAIN", mf) - self.assertEqual(mf["R128_TRACK_GAIN"], [str(int(round(expected_track_gain_opus * (2 ** 8), 0)))]) + self.assertEqual(mf["R128_TRACK_GAIN"], [str(int(round(expected_track_gain_opus * (2**8), 0)))]) if delete_tags: mf = mutagen.File(self.mp3_filepath) @@ -983,7 +1002,7 @@ self.assertEqual(mf["R128_TRACK_GAIN"], ["0"]) self.assertNotIn("R128_ALBUM_GAIN", mf) - expected_output_gain = round((ref_loudness_opus - ref_track_loudness) * (2 ** 8)) + expected_output_gain = round((ref_loudness_opus - ref_track_loudness) * (2**8)) with open(opus_filepath, "rb") as f: self.assertEqual(r128gain.opusgain.parse_oggopus_output_gain(f), expected_output_gain) @@ -999,7 +1018,7 @@ self.assertIn("R128_ALBUM_GAIN", mf) self.assertEqual(mf["R128_ALBUM_GAIN"], ["0"]) - expected_output_gain = round((ref_loudness_opus - ref_album_loudness) * (2 ** 8)) + expected_output_gain = round((ref_loudness_opus - ref_album_loudness) * (2**8)) with open(opus_filepath, "rb") as f: self.assertEqual(r128gain.opusgain.parse_oggopus_output_gain(f), expected_output_gain) @@ -1019,7 +1038,7 @@ self.assertIn("R128_ALBUM_GAIN", mf) self.assertEqual(mf["R128_ALBUM_GAIN"], ["0"]) - expected_output_gain = round((ref_loudness_opus - ref_album_loudness) * (2 ** 8)) + expected_output_gain = round((ref_loudness_opus - ref_album_loudness) * (2**8)) with open(opus_filepath, "rb") as f: self.assertEqual(r128gain.opusgain.parse_oggopus_output_gain(f), expected_output_gain) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/r128gain-1.0.4/update-version new/r128gain-1.0.7/update-version --- old/r128gain-1.0.4/update-version 2021-10-23 22:55:38.000000000 +0200 +++ new/r128gain-1.0.7/update-version 1970-01-01 01:00:00.000000000 +0100 @@ -1,16 +0,0 @@ -#!/bin/bash -eu - -set -o pipefail - -readonly VERSION=${1:?} - - -cd "$(git rev-parse --show-toplevel)" - -sed -i "s/^\(__version__ = \"\).*\(\"\)/\1$VERSION\2/w /dev/stdout" r128gain/__init__.py - -git add r128gain/__init__.py - -git commit -m "Version ${VERSION}" - -git tag -m "Version ${VERSION}" "${VERSION}" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/r128gain-1.0.4/win/Makefile new/r128gain-1.0.7/win/Makefile --- old/r128gain-1.0.4/win/Makefile 2021-10-23 22:55:38.000000000 +0200 +++ new/r128gain-1.0.7/win/Makefile 2023-03-25 20:41:32.000000000 +0100 @@ -3,45 +3,59 @@ FFMPEG_CACHE_DIR ?= ${HOME}/.cache/ci/r128gain/ffmpeg-${WINEARCH} # versions -PYTHON_VERSION := 3.6.8 +PYTHON_VERSION := 3.8.10 PYTHON_VERSION_MAJOR := $(word 1,$(subst ., ,${PYTHON_VERSION})).$(word 2,$(subst ., ,${PYTHON_VERSION})) PYTHON_VERSION_SHORT := $(subst .,,${PYTHON_VERSION_MAJOR}) -CXFREEZE_VERSION := 6.1 +CXFREEZE_VERSION := 6.14.0 SOX_VERSION := 14.4.2 -# installers +# installers & packages DOWNLOAD_DIR ?= dl -PYTHON_INSTALLER-win32 := ${DOWNLOAD_DIR}/python-${PYTHON_VERSION}.exe -PYTHON_INSTALLER-win64 := ${DOWNLOAD_DIR}/python-${PYTHON_VERSION}-amd64.exe -PYTHON_INSTALLER := ${PYTHON_INSTALLER-${WINEARCH}} -CXFREEZE_WHEEL-win32 := ${DOWNLOAD_DIR}/cx_Freeze-${CXFREEZE_VERSION}-cp${PYTHON_VERSION_SHORT}-cp${PYTHON_VERSION_SHORT}m-${WINEARCH}.whl -CXFREEZE_WHEEL-win64 := ${DOWNLOAD_DIR}/cx_Freeze-${CXFREEZE_VERSION}-cp${PYTHON_VERSION_SHORT}-cp${PYTHON_VERSION_SHORT}m-win_amd64.whl -CXFREEZE_WHEEL := ${CXFREEZE_WHEEL-${WINEARCH}} -7ZIP_INSTALLER := ${DOWNLOAD_DIR}/7z938.msi -SOX_ZIP := ${DOWNLOAD_DIR}/sox-${SOX_VERSION}-win32.zip +PYTHON_EMBEDDABLE_ARCHIVE-win32 := ${DOWNLOAD_DIR}/python-${PYTHON_VERSION}-embed-win32.zip +PYTHON_EMBEDDABLE_ARCHIVE-win64 := ${DOWNLOAD_DIR}/python-${PYTHON_VERSION}-embed-amd64.zip +PYTHON_EMBEDDABLE_ARCHIVE := ${PYTHON_EMBEDDABLE_ARCHIVE-${WINEARCH}} +GET_PIP := ${DOWNLOAD_DIR}/get-pip.py +FUTURE_WHEEL := ${DOWNLOAD_DIR}/future-0.17.1-py3-none-any.whl +CXFREEZE_WHEEL-win32 := ${DOWNLOAD_DIR}/cx_Freeze-${CXFREEZE_VERSION}-cp${PYTHON_VERSION_SHORT}-cp${PYTHON_VERSION_SHORT}-${WINEARCH}.whl +CXFREEZE_WHEEL-win64 := ${DOWNLOAD_DIR}/cx_Freeze-${CXFREEZE_VERSION}-cp${PYTHON_VERSION_SHORT}-cp${PYTHON_VERSION_SHORT}-win_amd64.whl +CXFREEZE_WHEEL := ${CXFREEZE_WHEEL-${WINEARCH}} +7ZIP_INSTALLER := ${DOWNLOAD_DIR}/7z2107.msi +SOX_ZIP := ${DOWNLOAD_DIR}/sox-${SOX_VERSION}-win32.zip -# env +# native env & tools CURL := curl -s -f -L -m 600 --connect-timeout 30 --retry 10 --retry-max-time 5 WINE_DIR := /tmp/$(subst /,_,${CURDIR})/wine-${WINEARCH} -WINE := mkdir -p $(dir ${WINE_DIR}) && WINEPREFIX=${WINE_DIR} WINEARCH=${WINEARCH} WINEDLLOVERRIDES="mscoree,mshtml=" WINEDEBUG=-all wine -UNZIP := unzip -o -q -DD +UNZIP := unzip -q -o -DD # installed files -PYTHON_INSTALLED := ${WINE_DIR}/drive_c/Python${PYTHON_VERSION_SHORT}/python.exe -CXFREEZE_INSTALLED := ${WINE_DIR}/drive_c/Python${PYTHON_VERSION_SHORT}/Scripts/cxfreeze -PIP_INSTALLED := ${WINE_DIR}/drive_c/Python${PYTHON_VERSION_SHORT}/Scripts/pip.exe +PYTHON_INSTALLED := ${WINE_DIR}/drive_c/Python${PYTHON_VERSION_SHORT}/python.exe +PIP_INSTALLED := $(dir ${PYTHON_INSTALLED})Scripts/pip.exe +FUTURE_INSTALLED := $(dir ${PYTHON_INSTALLED})Lib/site-packages/future/__init__.py +CXFREEZE_INSTALLED := $(dir ${PYTHON_INSTALLED})Scripts/cxfreeze 7ZIP_INSTALLED := ${WINE_DIR}/drive_c/7-Zip/7z.sfx -SOX_INSTALLED := ${WINE_DIR}/drive_c/windows/system32/sox.exe -FFMPEG_INSTALLED := ${WINE_DIR}/drive_c/windows/system32/ffmpeg.exe +SOX_DIR := sox-${SOX_VERSION} +SOX_INSTALLED := ${WINE_DIR}/drive_c/${SOX_DIR}/sox.exe +FFMPEG_DIR := ffmpeg +FFMPEG_INSTALLED := ${WINE_DIR}/drive_c/${FFMPEG_DIR}/ffmpeg.exe ifeq ($(shell lsb_release -si),Ubuntu) WINPTHREAD_DLL_win32 := /usr/i686-w64-mingw32/lib/libwinpthread-1.dll WINPTHREAD_DLL_win64 := /usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll else +ifeq ($(shell test -e /etc/redhat-release && echo true),true) +WINPTHREAD_DLL_win32 := /usr/i686-w64-mingw32/sys-root/mingw/bin/libwinpthread-1.dll +WINPTHREAD_DLL_win64 := /usr/x86_64-w64-mingw32/sys-root/mingw/bin/libwinpthread-1.dll +else WINPTHREAD_DLL_win32 := /usr/i686-w64-mingw32/bin/libwinpthread-1.dll WINPTHREAD_DLL_win64 := /usr/x86_64-w64-mingw32/bin/libwinpthread-1.dll endif +endif WINPTHREAD_DLL := ${WINPTHREAD_DLL_${WINEARCH}} +# wine env +WINE := WINEPREFIX=${WINE_DIR} WINEARCH=${WINEARCH} WINEDLLOVERRIDES="mscoree,mshtml=" WINEDEBUG=-all WINEPATH="C:\\${SOX_DIR};C:\\${FFMPEG_DIR}" wine +WINE_PYTHON := ${WINE} ${PYTHON_INSTALLED} +WINE_PIP := ${WINE} ${PIP_INSTALLED} + # temp dirs OUTPUT_DIR := r128gain-${WINEARCH} @@ -61,10 +75,10 @@ # End targets # -r128gain_${WINEARCH}.7z: ${OUTPUT_DIR}/r128gain.exe ${OUTPUT_DIR}/LICENSE ${OUTPUT_DIR}/readme.txt ${OUTPUT_DIR}/python${PYTHON_VERSION_SHORT}.dll ${OUTPUT_DIR}/ffmpeg.exe ${OUTPUT_DIR}/libwinpthread-1.dll +r128gain_${WINEARCH}.7z: ${OUTPUT_DIR}/r128gain.exe ${OUTPUT_DIR}/LICENSE ${OUTPUT_DIR}/readme.txt ${OUTPUT_DIR}/ffmpeg.exe ${OUTPUT_DIR}/libwinpthread-1.dll 7z a -t7z -mx9 $@ ${OUTPUT_DIR} > /dev/null -r128gain_${WINEARCH}.zip: ${OUTPUT_DIR}/r128gain.exe ${OUTPUT_DIR}/LICENSE ${OUTPUT_DIR}/readme.txt ${OUTPUT_DIR}/python${PYTHON_VERSION_SHORT}.dll ${OUTPUT_DIR}/ffmpeg.exe +r128gain_${WINEARCH}.zip: ${OUTPUT_DIR}/r128gain.exe ${OUTPUT_DIR}/LICENSE ${OUTPUT_DIR}/readme.txt ${OUTPUT_DIR}/ffmpeg.exe 7z a -tzip -mx9 $@ ${OUTPUT_DIR} > /dev/null r128gain_${WINEARCH}.exe: ${7ZIP_INSTALLED} r128gain_${WINEARCH}.7z @@ -80,10 +94,6 @@ cd .. && ${WINE} ${PYTHON_INSTALLED} freeze.py build_exe -b win/${OUTPUT_DIR} 2> /dev/null > /dev/null touch $@ -${OUTPUT_DIR}/python${PYTHON_VERSION_SHORT}.dll: ${PYTHON_INSTALLED} - mkdir -p $(dir $@) - cp $(dir ${PYTHON_INSTALLED})$(notdir $@) $@ - ${OUTPUT_DIR}/LICENSE: mkdir -p $(dir $@) cp ../LICENSE $@ @@ -122,57 +132,72 @@ # Installations # -.requirements: ${PIP_INSTALLED} - cd .. && ${WINE} ${PYTHON_INSTALLED} -m pip -qqq install -r requirements.txt +.requirements: ${PIP_INSTALLED} ${FUTURE_INSTALLED} + cd .. && ${WINE_PIP} -qq install -r requirements.txt + cd .. && ${WINE_PIP} -qq install . touch $@ -${PYTHON_INSTALLED}: ${PYTHON_INSTALLER} - ${WINE} $< /quiet InstallAllUsers=1 TargetDir=$(dir ${PYTHON_INSTALLED}) +${PYTHON_INSTALLED}: ${PYTHON_EMBEDDABLE_ARCHIVE} + mkdir -p $(dir $@) + ${UNZIP} -d $(dir $@) $< + ${UNZIP} -d $(dir $@) $(dir $@)python${PYTHON_VERSION_SHORT}.zip + rm $(dir $@)python${PYTHON_VERSION_SHORT}.zip + echo 'import site' >>$(dir $@)python${PYTHON_VERSION_SHORT}._pth + +${PIP_INSTALLED}: ${PYTHON_INSTALLED} ${GET_PIP} + ${WINE_PYTHON} ${GET_PIP} -qq touch $@ -${CXFREEZE_INSTALLED}: ${CXFREEZE_WHEEL} ${PIP_INSTALLED} ${PYTHON_INSTALLED} - ${WINE} ${PYTHON_INSTALLED} -m pip -qqq install $< +${FUTURE_INSTALLED}: ${FUTURE_WHEEL} ${PIP_INSTALLED} + ${WINE_PIP} -qq install $< touch $@ -${PIP_INSTALLED}: ${PYTHON_INSTALLED} - ${WINE} ${PYTHON_INSTALLED} -m pip -qqq install -U pip +${CXFREEZE_INSTALLED}: ${CXFREEZE_WHEEL} ${PIP_INSTALLED} + ${WINE_PIP} -qq install $< touch $@ ${7ZIP_INSTALLED}: ${7ZIP_INSTALLER} ${WINE} msiexec /i $< /qb INSTALLDIR='c:\7-Zip' touch $@ -${FFMPEG_INSTALLED}: +${FFMPEG_INSTALLED}: ${WINPTHREAD_DLL} mkdir -p $(dir $@) ./cross-build-minimal-ffmpeg ${FFMPEG_VERSION} ${WINEARCH} ${FFMPEG_CACHE_DIR} $@ + cp ${WINPTHREAD_DLL} $(dir $@) ${SOX_INSTALLED}: ${SOX_ZIP} mkdir -p ${WINE_DIR}/drive_c ${UNZIP} $< -d ${WINE_DIR}/drive_c - cp ${WINE_DIR}/drive_c/sox-${SOX_VERSION}/*.dll $(dir $@) - cp ${WINE_DIR}/drive_c/sox-${SOX_VERSION}/sox.exe $@ # # Downloads # -${PYTHON_INSTALLER}: +${PYTHON_EMBEDDABLE_ARCHIVE}: mkdir -p $(dir $@) ${CURL} https://www.python.org/ftp/python/${PYTHON_VERSION}/$(notdir $@) > $@ +${GET_PIP}: + mkdir -p $(dir $@) + ${CURL} https://bootstrap.pypa.io/$(notdir $@) > $@ + +${FUTURE_WHEEL}: + mkdir -p $(dir $@) + ${CURL} https://www.piwheels.org/simple/future/$(notdir $@) > $@ + ${CXFREEZE_WHEEL-win32}: mkdir -p $(dir $@) - ${CURL} https://files.pythonhosted.org/packages/ea/2b/076f152fdaff10a08ca4012713532b6d2606c1995ee85812d271135f90e2/$(notdir $@) > $@ + ${CURL} https://files.pythonhosted.org/packages/00/6f/f05b5d50e1932c33d8aa8b0af255c5fc3f3830e6af1a82529509be0a1490/$(notdir $@) > $@ ${CXFREEZE_WHEEL-win64}: mkdir -p $(dir $@) - ${CURL} https://files.pythonhosted.org/packages/50/dc/ad7111fc626a24504e468382c431698e4dcd60c944b9e9adf2187d073865/$(notdir $@) > $@ + ${CURL} https://files.pythonhosted.org/packages/0d/bd/6ccd8b1f5ba4a12fbb5cc43dc53fa3741fb7b776b07c58d4bbb94fabc590/$(notdir $@) > $@ ${7ZIP_INSTALLER}: mkdir -p $(dir $@) ${CURL} http://www.7-zip.org/a/$(notdir $@) > $@.unckecked - echo "673377a03f91ff0f7f384794934b767c3389e50d7dc308f7c73f4633121518b3e4af8d33cf282398a710577e12fbb963152591c3e29b1092c79530bb2d8aa882 $@.unckecked" | sha512sum --status -c - && mv $@.unckecked $@ + echo "103210153e60b4234015796bb5f12483f99b5909df8c2fe5c9d3a823d4bdc721602a5261ad794e5280ff9f0d5f79add4e2a732dfb087fe8b4844d789acb8ea42 $@.unckecked" | sha512sum --status -c - && mv $@.unckecked $@ ${SOX_ZIP}: mkdir -p $(dir $@) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/r128gain-1.0.4/win/cross-build-minimal-ffmpeg new/r128gain-1.0.7/win/cross-build-minimal-ffmpeg --- old/r128gain-1.0.4/win/cross-build-minimal-ffmpeg 2021-10-23 22:55:38.000000000 +0200 +++ new/r128gain-1.0.7/win/cross-build-minimal-ffmpeg 2023-03-25 20:41:32.000000000 +0100 @@ -11,6 +11,16 @@ readonly PROC_COUNT=$(grep -c '^processor' /proc/cpuinfo) +parse_audio_decoders() { + # The lines between /* audio codecs */ and /* subtitles */ are + # audio codecs. Parse them out and filter out only decoders. + + # shellcheck disable=SC2016 + sed -n '/^\/\* audio codecs \*\/$/,${p;/^\/\* subtitles \*\/$/q}' \ + libavcodec/allcodecs.c | \ + sed -n 's/extern .*Codec ff_\(.*\)_decoder;/\1/p' +} + configure() { if [ "${ARCH}" = "win32" ] then @@ -35,7 +45,7 @@ --disable-encoders \ --enable-encoder=pcm_s16le \ --disable-decoders \ - $(ffmpeg -hide_banner -codecs | grep '^ D.A' | cut -d ' ' -f 3 | xargs -I'{}' echo --enable-decoder={}) \ + $(parse_audio_decoders | xargs -I'{}' echo --enable-decoder={}) \ --disable-hwaccels \ --disable-muxers \ --enable-muxer=null \