Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions .github/workflows/appimage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
name: Build AppImage

on:
release:
types: [published]
workflow_dispatch:

permissions:
contents: write

jobs:
appimage:
name: AppImage
runs-on: ubuntu-22.04

env:
DEBIAN_FRONTEND: noninteractive

steps:
- name: Check out sources
uses: actions/checkout@v7

- name: Install build and runtime packages
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
adwaita-icon-theme \
ca-certificates \
curl \
desktop-file-utils \
ffmpeg \
file \
frei0r-plugins \
gmic \
gir1.2-atk-1.0 \
gir1.2-gdkpixbuf-2.0 \
gir1.2-freedesktop \
gir1.2-glib-2.0 \
gir1.2-harfbuzz-0.0 \
gir1.2-gtk-3.0 \
gir1.2-pango-1.0 \
hicolor-icon-theme \
libcairo-gobject2 \
libcairo2 \
libdatrie1 \
libfontconfig1 \
libfreetype6 \
libfribidi0 \
libfuse2 \
libgdk-pixbuf2.0-bin \
libglib2.0-bin \
libgraphite2-3 \
libgtk-3-bin \
libharfbuzz0b \
libmlt-data \
libpango-1.0-0 \
libpangocairo-1.0-0 \
libpangoft2-1.0-0 \
libjpeg-turbo8 \
libjbig0 \
libpng16-16 \
librsvg2-common \
libthai0 \
libtiff5 \
libwayland-client0 \
libwayland-cursor0 \
libwayland-egl1 \
libwebp7 \
libwebpdemux2 \
libwebpmux3 \
libxkbcommon0 \
python3 \
python3-distutils \
python3-gi \
python3-gi-cairo \
python3-mlt \
python3-numpy \
python3-pil \
python3-setuptools \
python3-usb1 \
shared-mime-info \
squashfs-tools \
swh-plugins \
xauth \
xvfb \
zlib1g

- name: Build AppImage
run: packaging/appimage/build-appimage.sh

- name: Upload workflow artifact
uses: actions/upload-artifact@v7
with:
name: flowblade-appimage
path: dist/*.AppImage
if-no-files-found: error

- name: Smoke test AppImage startup
run: packaging/appimage/smoke-test-appimage.sh

- name: Smoke test AppImage in base containers
run: packaging/appimage/smoke-test-appimage-containers.sh

- name: Upload AppImage smoke test log
if: failure()
uses: actions/upload-artifact@v7
with:
name: flowblade-appimage-smoke-log
path: |
build/appimage-smoke/*.log
build/appimage-smoke-containers/**/*.log
if-no-files-found: ignore

- name: Attach AppImage to release
if: github.event_name == 'release'
env:
GH_TOKEN: ${{ github.token }}
run: gh release upload "${{ github.event.release.tag_name }}" dist/*.AppImage --clobber
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ mlt7.py
# Flatpak when building from local
/flowblade-trunk/.flatpak-builder/

# AppImage build outputs
/build/appimage/
/dist/

# Theme build data
/flowblade-trunk/Flowblade/res/css2/sass/gtk-flowblade-dark.css.map
/flowblade-trunk/Flowblade/res/css3/sass/gtk-flowblade-dark.css.map
Expand Down
3 changes: 2 additions & 1 deletion flowblade-trunk/Flowblade/src/dialogs/dialogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,8 @@ def environment_dialog(parent_window):
run_type = _("INSTALLATION")
elif editorstate.app_running_from == editorstate.RUNNING_FROM_FLATPAK:
run_type = "FLATPAK"
elif editorstate.app_running_from == editorstate.RUNNING_FROM_APPIMAGE:
run_type = "APPIMAGE"
else:
run_type = _("DEVELOPER VERSION")
r4 = guiutils.get_left_justified_box([Gtk.Label(label=_("Running from: ")), Gtk.Label(label=run_type)])
Expand Down Expand Up @@ -2070,4 +2072,3 @@ def replace_clip_not_enough_material_info():
primary_txt = _("Cannot replace the clip!")
secondary_txt = _("The clip being replaced is longer then the clip being added.")
dialogutils.warning_message(primary_txt, secondary_txt, gui.editor_window.window)

1 change: 1 addition & 0 deletions flowblade-trunk/Flowblade/src/editorstate.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
RUNNING_FROM_INSTALLATION = 0
RUNNING_FROM_DEV_VERSION = 1
RUNNING_FROM_FLATPAK = 2
RUNNING_FROM_APPIMAGE = 3
app_running_from = RUNNING_FROM_INSTALLATION
audio_monitoring_available = False

Expand Down
9 changes: 8 additions & 1 deletion flowblade-trunk/Flowblade/src/launch/launchutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ def get_modules_path():
def set_app_runtime_type(modules_path):

import editorstate
appdir = os.environ.get("APPDIR")
if appdir != None:
appdir = os.path.realpath(appdir)
if os.path.realpath(sys.argv[0]).startswith(appdir + os.sep):
editorstate.app_running_from = editorstate.RUNNING_FROM_APPIMAGE
return

root_dir = modules_path.split("/")[1]

# Used to decide which translations from file system are used.
Expand All @@ -27,4 +34,4 @@ def get_arg_value(key_str):
if parts[0] == key_str:
return parts[1]

return None
return None
9 changes: 8 additions & 1 deletion flowblade-trunk/Flowblade/src/process/gmicheadless.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,14 @@ def main(root_path, session_id, parent_folder, script, clip_path, range_in, rang
# Set paths.
respaths.set_paths(root_path)

if os.path.exists("/usr/bin/gmic") == True: # distro install an dev.
appdir = os.environ.get("APPDIR")
appimage_gmic = None
if appdir != None:
appimage_gmic = os.path.join(appdir, "usr", "bin", "gmic")

if appimage_gmic != None and os.path.exists(appimage_gmic) == True:
editorstate.gmic_path = appimage_gmic
elif os.path.exists("/usr/bin/gmic") == True: # distro install an dev.
editorstate.gmic_path = "/usr/bin/gmic"
elif os.path.exists("/app/bin/gmic") == True: # Flatpak
editorstate.gmic_path = "/app/bin/gmic"
Expand Down
9 changes: 8 additions & 1 deletion flowblade-trunk/Flowblade/src/tools/gmic.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,14 @@ def test_availablity():
print("G'MIC NOT found")

def set_gmic_path():
if os.path.exists("/usr/bin/gmic") == True:
appdir = os.environ.get("APPDIR")
appimage_gmic = None
if appdir != None:
appimage_gmic = os.path.join(appdir, "usr", "bin", "gmic")

if appimage_gmic != None and os.path.exists(appimage_gmic) == True:
editorstate.gmic_path = appimage_gmic
elif os.path.exists("/usr/bin/gmic") == True:
editorstate.gmic_path = "/usr/bin/gmic"
elif os.path.exists("/app/bin/gmic") == True: # File system and flatpak
editorstate.gmic_path = "/app/bin/gmic"
Expand Down
7 changes: 5 additions & 2 deletions flowblade-trunk/Flowblade/src/translations.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ def init_languages():
if (language):
langs += language.split(":")

if editorstate.app_running_from == editorstate.RUNNING_FROM_INSTALLATION or editorstate.app_running_from == editorstate.RUNNING_FROM_FLATPAK:
if editorstate.app_running_from == editorstate.RUNNING_FROM_APPIMAGE:
locale_path = respaths.LOCALE_PATH
print("Running from AppImage, using bundled translations at " + locale_path + ".")
elif editorstate.app_running_from == editorstate.RUNNING_FROM_INSTALLATION or editorstate.app_running_from == editorstate.RUNNING_FROM_FLATPAK:
# Use /usr/share/locale first if available and running from installation
# Look for installed translation in distro install
# Were using Russian as test language
Expand Down Expand Up @@ -935,4 +938,4 @@ def load_filters_translations():
plugin_editor_groups["Animation"] = _("Animation")
plugin_editor_groups["Background"] = _("Background")
plugin_editor_groups["Layout"] = _("Layout")
plugin_editor_groups["Fonts"] = _("Fonts")
plugin_editor_groups["Fonts"] = _("Fonts")
11 changes: 4 additions & 7 deletions flowblade-trunk/Flowblade/src/window/editorlayout.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,12 +195,6 @@ def top_level_project_panel():
def init_layout_data():
global _panel_positions, _positions_names, _panels_names, _position_notebooks, PANEL_MINIMUM_SIZES
_panel_positions = editorpersistance.prefs.panel_positions

# New panel needs to be made part of saced postions on firts load of 2.26.
try:
pos = _panel_positions[appconsts.PANEL_DISSOLVE_SELECT]
except:
_panel_positions[appconsts.PANEL_DISSOLVE_SELECT] = appconsts.PANEL_PLACEMENT_BOTTOM_ROW_RIGHT

# Use default panels positions if nothing available yet or too small screen,
# or default panel position is empty, layout code makes too many assumptions to make that work.
Expand All @@ -213,6 +207,10 @@ def init_layout_data():
editorpersistance.prefs.panel_positions = _panel_positions
editorpersistance.save()

# New panel needs to be made part of saved positions on first load of 2.26.
if appconsts.PANEL_DISSOLVE_SELECT not in _panel_positions:
_panel_positions[appconsts.PANEL_DISSOLVE_SELECT] = appconsts.PANEL_PLACEMENT_BOTTOM_ROW_RIGHT

if editorpersistance.prefs.positions_tabs == None:
editorpersistance.prefs.positions_tabs = DEFAULT_TABS_POSITIONS
editorpersistance.save()
Expand Down Expand Up @@ -826,4 +824,3 @@ def apply_layout(layout_dict):
gui.editor_window.window.show_all()
set_positions_frames_visibility()


17 changes: 15 additions & 2 deletions flowblade-trunk/flowblade
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,23 @@ print ("---------------------------")

# Get launch script dir
launch_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
real_launch_dir = os.path.realpath(launch_dir)
appdir = os.environ.get("APPDIR")
appdir_usr_bin = None
if appdir != None:
appdir = os.path.realpath(appdir)
appdir_usr_bin = os.path.join(appdir, "usr", "bin")

print ("Launch script dir:", launch_dir)

# Update sys.path to include modules.
# - When running in AppImage.
if appdir_usr_bin != None and real_launch_dir == appdir_usr_bin:
print ("Running from AppImage...")
modules_path = appdir + "/usr/share/flowblade/Flowblade/src"
print ("modules path:", modules_path)
# - When running on distro.
if os.path.realpath(launch_dir) == "/usr/bin":
elif real_launch_dir == "/usr/bin":
print ("Running from installation...")
modules_path = "/usr/share/flowblade/Flowblade/src"
if not os.path.isdir(modules_path):
Expand Down Expand Up @@ -77,7 +88,9 @@ try:
import app
import editorstate

if launch_dir == "/usr/bin":
if appdir_usr_bin != None and real_launch_dir == appdir_usr_bin:
editorstate.app_running_from = editorstate.RUNNING_FROM_APPIMAGE
elif launch_dir == "/usr/bin":
editorstate.app_running_from = editorstate.RUNNING_FROM_INSTALLATION
elif launch_dir == "/app/bin":
editorstate.app_running_from = editorstate.RUNNING_FROM_FLATPAK
Expand Down
Loading