diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index d21e4e64..cf60bf44 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -66,6 +66,17 @@ jobs: dist/FastFlix dist/LICENSE + - name: Build Mac App + if : ${{ startsWith(matrix.os, 'macos') }} + run: python scripts/build_mac_app.py "${{ matrix.os }}" + + - name: Upload Mac App artifact + if : ${{ startsWith(matrix.os, 'macos') }} + uses: actions/upload-artifact@v4 + with: + name: FastFlix_${{ env.VERSION }}_appbundle_${{ matrix.os }}_${{ env.ARCH }} + path: FastFlix.app + build-windows-2022: diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index a64bb8ac..40c125b3 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -18,7 +18,7 @@ jobs: with: python-version: "3.12" - - run: pip install black==23.7.0 + - run: pip install black==24.8.0 - run: python -m black --check . test: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8adf78e1..00f777a1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.6.0 hooks: - id: mixed-line-ending - id: trailing-whitespace @@ -12,14 +12,18 @@ repos: - id: check-byte-order-marker - id: debug-statements - id: check-added-large-files - exclude: tests/media/.+ + exclude: | + (?x)^( + tests/media/.+| + ^fastflix/data/icon.icns + )$ - id: check-case-conflict - id: check-executables-have-shebangs - id: check-toml - id: detect-private-key - id: end-of-file-fixer - repo: https://github.com/psf/black - rev: 23.7.0 + rev: 24.8.0 hooks: - id: black # - repo: https://github.com/pre-commit/mirrors-mypy diff --git a/CHANGES b/CHANGES index 5e8d78d3..fddb3de9 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,7 @@ * Adding #354 M1 support (thanks to Nhunz and Anton) * Adding #536 Improve Profiles - save advanced options (thanks to CelticTaonga and DCNerds) * Adding #568 center app on startup (thanks to Viet-Duc Le) +* Adding #587 Distribute a mac app bundle (thanks to Ivan Novokhatski) * Adding #589 support for pydantic 2.x (thanks to dmo marillat) * Adding #592 Add alpha channel for VP9 (thjanks to subof) * Fixing #185 audio channels not being set properly and resetting on encoder change (thanks to Tupsi) diff --git a/fastflix/command_runner.py b/fastflix/command_runner.py index 42668149..9a2f457f 100644 --- a/fastflix/command_runner.py +++ b/fastflix/command_runner.py @@ -110,9 +110,10 @@ def change_priority( logger.exception(f"Could not set process priority to {new_priority}") def read_output(self): - with open(self.output_file, "r", encoding="utf-8", errors="ignore") as out_file, open( - self.error_output_file, "r", encoding="utf-8", errors="ignore" - ) as err_file: + with ( + open(self.output_file, "r", encoding="utf-8", errors="ignore") as out_file, + open(self.error_output_file, "r", encoding="utf-8", errors="ignore") as err_file, + ): while True: time.sleep(0.01) if not self.is_alive(): diff --git a/fastflix/data/Info.plist.template b/fastflix/data/Info.plist.template new file mode 100644 index 00000000..ee7ddce9 --- /dev/null +++ b/fastflix/data/Info.plist.template @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + FastFlix + CFBundleInfoDictionaryVersion + 6.0 + CFBundleIconFile + icon.icns + CFBundleIdentifier + com.github.cdgriffith.FastFlix + CFBundlePackageType + APPL + CFBundleSignature + PURE + CFBundleVersion + {version} + CFBundleName + FastFlix + CSResourcesFileMapped + + NSHighResolutionCapable + + NSDisablePersistence + + LSMinimumSystemVersion + {mac_version} + + diff --git a/fastflix/data/icon.icns b/fastflix/data/icon.icns new file mode 100644 index 00000000..b2c14858 Binary files /dev/null and b/fastflix/data/icon.icns differ diff --git a/fastflix/encoders/vceencc_av1/settings_panel.py b/fastflix/encoders/vceencc_av1/settings_panel.py index bdacaed1..a607c292 100644 --- a/fastflix/encoders/vceencc_av1/settings_panel.py +++ b/fastflix/encoders/vceencc_av1/settings_panel.py @@ -301,9 +301,9 @@ def update_video_encoder_settings(self): pa_paq=self.widgets.pa_paq.currentText(), pa_taq=None if self.widgets.pa_taq.currentIndex() == 0 else self.widgets.pa_taq.currentText(), pa_motion_quality=self.widgets.pa_motion_quality.currentText(), - output_depth=None - if self.widgets.output_depth.currentIndex() == 0 - else self.widgets.output_depth.currentText(), + output_depth=( + None if self.widgets.output_depth.currentIndex() == 0 else self.widgets.output_depth.currentText() + ), ) encode_type, q_value = self.get_mode_settings() diff --git a/fastflix/encoders/vceencc_avc/settings_panel.py b/fastflix/encoders/vceencc_avc/settings_panel.py index f2341f7e..dcd8e1d2 100644 --- a/fastflix/encoders/vceencc_avc/settings_panel.py +++ b/fastflix/encoders/vceencc_avc/settings_panel.py @@ -301,9 +301,9 @@ def update_video_encoder_settings(self): pa_paq=self.widgets.pa_paq.currentText(), pa_taq=None if self.widgets.pa_taq.currentIndex() == 0 else self.widgets.pa_taq.currentText(), pa_motion_quality=self.widgets.pa_motion_quality.currentText(), - output_depth=None - if self.widgets.output_depth.currentIndex() == 0 - else self.widgets.output_depth.currentText(), + output_depth=( + None if self.widgets.output_depth.currentIndex() == 0 else self.widgets.output_depth.currentText() + ), ) encode_type, q_value = self.get_mode_settings() diff --git a/fastflix/encoders/vceencc_hevc/settings_panel.py b/fastflix/encoders/vceencc_hevc/settings_panel.py index cef9dc58..2c2089b8 100644 --- a/fastflix/encoders/vceencc_hevc/settings_panel.py +++ b/fastflix/encoders/vceencc_hevc/settings_panel.py @@ -295,9 +295,9 @@ def update_video_encoder_settings(self): pa_paq=self.widgets.pa_paq.currentText(), pa_taq=None if self.widgets.pa_taq.currentIndex() == 0 else self.widgets.pa_taq.currentText(), pa_motion_quality=self.widgets.pa_motion_quality.currentText(), - output_depth=None - if self.widgets.output_depth.currentIndex() == 0 - else self.widgets.output_depth.currentText(), + output_depth=( + None if self.widgets.output_depth.currentIndex() == 0 else self.widgets.output_depth.currentText() + ), ) encode_type, q_value = self.get_mode_settings() diff --git a/fastflix/encoders/vp9/settings_panel.py b/fastflix/encoders/vp9/settings_panel.py index 86765ec8..0b6210e1 100644 --- a/fastflix/encoders/vp9/settings_panel.py +++ b/fastflix/encoders/vp9/settings_panel.py @@ -214,9 +214,9 @@ def update_video_encoder_settings(self): extra=self.ffmpeg_extras, extra_both_passes=self.widgets.extra_both_passes.isChecked(), fast_first_pass=self.widgets.fast_first_pass.isChecked(), - tile_columns=self.widgets.tile_columns.currentText() - if self.widgets.tile_columns.currentIndex() > 0 - else "-1", + tile_columns=( + self.widgets.tile_columns.currentText() if self.widgets.tile_columns.currentIndex() > 0 else "-1" + ), tile_rows=self.widgets.tile_rows.currentText() if self.widgets.tile_rows.currentIndex() > 0 else "-1", ) encode_type, q_value = self.get_mode_settings() diff --git a/scripts/build_mac_app.py b/scripts/build_mac_app.py new file mode 100644 index 00000000..6d96d2d4 --- /dev/null +++ b/scripts/build_mac_app.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +from pathlib import Path +import sys +import shutil +from subprocess import check_output + +from fastflix.version import __version__ + +here = Path(__file__).parent +plist_template = here.parent / "fastflix" / "data" / "Info.plist.template" + +build_folder = Path(here.parent / "FastFlix.app") +build_folder.mkdir(exist_ok=True) + +content_folder = build_folder / "Contents" +content_folder.mkdir(exist_ok=True) + +macos_folder = content_folder / "MacOS" +macos_folder.mkdir(exist_ok=True) + +resources_folder = content_folder / "Resources" +resources_folder.mkdir(exist_ok=True) + +mac_version = f"{sys.argv[1].split(" - ")[1]}.0" +assert mac_version in ("12.0", "13.0", "14.0", "15.0") + +with open(plist_template) as in_file, open(content_folder / "Info.plist", "w") as out_file: + template = in_file.read().format(version=__version__, mac_version=mac_version) + out_file.write(template) + +shutil.copy(here.parent / "fastflix" / "data" / "icon.icns", resources_folder / "icon.icns") + +shutil.copy(here.parent / "dist" / "FastFlix", macos_folder / "FastFlix") +shutil.copy(here.parent / "LICENSE", macos_folder / "LICENSE") + +check_output(["chmod", "+x", macos_folder / "FastFlix"])