diff --git a/appveyor.yml b/appveyor.yml index 28ffb1e0a..82613ab47 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -23,13 +23,13 @@ environment: PYTHON_ARCH: 64 build_script: - cmd: >- - appveyor DownloadFile https://github.com/acoustid/chromaprint/releases/download/v%CHROMAPRINT_FPCALC_VERSION%/chromaprint-fpcalc-%CHROMAPRINT_FPCALC_VERSION%-windows-i686.zip -FileName fpcalc.zip + appveyor DownloadFile https://github.com/acoustid/chromaprint/releases/download/v%CHROMAPRINT_FPCALC_VERSION%/chromaprint-fpcalc-%CHROMAPRINT_FPCALC_VERSION%-windows-x86_64.zip -FileName fpcalc.zip appveyor DownloadFile https://indy.fulgan.com/SSL/openssl-%OPENSSL_VERSION%-x64_86-win64.zip -FileName openssl.zip 7z x fpcalc.zip -y - copy /Y chromaprint-fpcalc-%CHROMAPRINT_FPCALC_VERSION%-windows-i686\fpcalc.exe %PYTHON% + copy /Y chromaprint-fpcalc-%CHROMAPRINT_FPCALC_VERSION%-windows-x86_64\fpcalc.exe fpcalc.exe 7z x openssl.zip -y diff --git a/picard.spec b/picard.spec index 9e057bbee..e739cb426 100644 --- a/picard.spec +++ b/picard.spec @@ -2,6 +2,7 @@ import os import glob +import platform def _picard_get_locale_files(): @@ -28,13 +29,23 @@ def get_locale_messages(): return data_files - block_cipher = None +os_name = platform.system() +binaries = [] + data_files = get_locale_messages() +fpcalc_name = 'fpcalc' +if os_name == 'Windows': + fpcalc_name = 'fpcalc.exe' + +if os.path.isfile(fpcalc_name): + binaries += [(fpcalc_name, '')] + + a = Analysis(['tagger.py'], pathex=['picard'], - binaries=[], + binaries=binaries, datas=data_files, hiddenimports=[], hookspath=[], diff --git a/picard/acoustid/__init__.py b/picard/acoustid/__init__.py index ccd867f38..25b60f9f1 100644 --- a/picard/acoustid/__init__.py +++ b/picard/acoustid/__init__.py @@ -22,7 +22,7 @@ from functools import partial from PyQt5 import QtCore from picard import config, log from picard.const import FPCALC_NAMES -from picard.util import find_executable +from picard.util import find_executable, is_frozen from picard.acoustid.json_helpers import parse_recording @@ -34,7 +34,10 @@ class AcoustIDClient(QtCore.QObject): self._running = 0 self._max_processes = 2 - if not config.setting["acoustid_fpcalc"]: + # The second condition is checked because in case of a packaged build of picard + # the temp directory that pyinstaller decompresses picard into changes on every + # launch, thus we need to ignore the existing config values. + if not config.setting["acoustid_fpcalc"] or is_frozen: fpcalc_path = find_executable(*FPCALC_NAMES) if fpcalc_path: config.setting["acoustid_fpcalc"] = fpcalc_path diff --git a/picard/util/__init__.py b/picard/util/__init__.py index 66b7da21a..0e27f1154 100644 --- a/picard/util/__init__.py +++ b/picard/util/__init__.py @@ -34,6 +34,11 @@ from string import Template # Required for compatibility with lastfmplus which imports this from here rather than loading it direct. from picard.const import MUSICBRAINZ_SERVERS +# These variables are set by pyinstaller if running from a packaged build +# See http://pyinstaller.readthedocs.io/en/stable/runtime-information.html +is_frozen = getattr(sys, 'frozen', False) +frozen_temp_path = getattr(sys, '_MEIPASS', '') + class LockableObject(QtCore.QObject): @@ -197,6 +202,9 @@ def find_executable(*executables): executables = [e + '.exe' for e in executables] paths = [os.path.dirname(sys.executable)] if sys.executable else [] paths += os.environ.get('PATH', '').split(os.pathsep) + # This is for searching for executables bundled in packaged builds + if is_frozen: + paths += [frozen_temp_path] for path in paths: for executable in executables: f = os.path.join(path, executable) diff --git a/tagger.py b/tagger.py index e6c5321d1..8885c3e3d 100755 --- a/tagger.py +++ b/tagger.py @@ -6,10 +6,12 @@ import sys sys.path.insert(0, '.') from picard.tagger import main +from picard.util import is_frozen, frozen_temp_path + # This is needed to find resources when using pyinstaller -if getattr(sys, 'frozen', False): - basedir = sys._MEIPASS +if is_frozen: + basedir = frozen_temp_path else: basedir = os.path.dirname(os.path.abspath(__file__))