~comcloudway/melon

4308a0a1657be020a6fe5e082e69a47e18c5fc46 — Jakob Meier 7 months ago a944ca3 0.1.0.beta3
Added meson build system

Thanks to https://codeberg.org/valos/Komikku for showing how to do it
10 files changed, 258 insertions(+), 26 deletions(-)

M .gitignore
M README.md
A bin/melon.in
A bin/meson.build
A data/icu.ccw.Melon.desktop.in
R melon.svg => data/icu.ccw.Melon.svg
A data/meson.build
M main.py
A melon/application.py
A meson.build
M .gitignore => .gitignore +1 -0
@@ 1,1 1,2 @@
**/__pycache__
build/

M README.md => README.md +1 -0
@@ 23,6 23,7 @@ Of course, you are welcome to send issues and pull requests via email as well:
## 🧩 Requirements
- `python3`
- `py3-beautifulsoup4`
- `py3-lxml`
- `py3-requests`
- `py3-sqlite3`
- `gtk4.0`

A bin/melon.in => bin/melon.in +96 -0
@@ 0,0 1,96 @@
#!@PYTHON@

# @prettyname@ -- @description@
#
# Copyright (C) 2019-2024 @authorfullname@ <@authoremail@>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import gettext
import locale
import os
import sys

sys.path.insert(1, '@pythondir@')

builddir = os.environ.get('MESON_BUILD_ROOT')
if builddir:
    sys.dont_write_bytecode = True
    sys.path.insert(1, os.environ['MESON_SOURCE_ROOT'])
    xdg_data_dir = os.path.join(builddir, '@prefix@', '@datadir@')
    os.putenv('XDG_DATA_DIRS', '%s:%s' % (xdg_data_dir, os.getenv('XDG_DATA_DIRS', '/usr/local/share/:/usr/share/')))


def install_excepthook():
    """ Make sure we exit when an unhandled exception occurs. """
    old_hook = sys.excepthook

    def new_hook(etype, evalue, etb):
        print('Error: An unhandled exception occurs')

        old_hook(etype, evalue, etb)

        context = GLib.main_context_default()
        done = False
        while context.iteration():
            if done:
                continue
            app = Gio.Application.get_default()
            if app.window:
                app.window.quit(force=True)
            else:
                app.quit()
            done = True

        sys.exit()

    sys.excepthook = new_hook


if __name__ == '__main__':
    import gi

    gi.require_version('Gtk', '4.0')
    gi.require_version('Adw', '1')

    from gi.repository import Gio
    from gi.repository import GLib
    from gi.repository import Gtk

    install_excepthook()

    # Why both locale and gettext are needed?
    # gettext works for the python part but not for XML UI files!
    try:
        locale.textdomain('@projectname@')
        locale.bindtextdomain('@projectname@', '@localedir@')
    except AttributeError as e:
        # Python built without gettext support doesn't have bindtextdomain() and textdomain()
        print('Could not bind the gettext translation domain. Some translations will not work.')
        print('Error: {}'.format(e))
    gettext.textdomain('@projectname@')
    gettext.bindtextdomain('@projectname@', '@localedir@')

    from @projectname@.application import Application

    Application.application_id = '@appid@'
    Application.version = '@VERSION@'
    app = Application()

    try:
        status = app.run(sys.argv)
    except SystemExit as e:
        status = e.code

    sys.exit(status)

A bin/meson.build => bin/meson.build +30 -0
@@ 0,0 1,30 @@
# Profiles
conf = configuration_data()

conf.set('VERSION', meson.project_version())
conf.set('PYTHON', py_installation.full_path())
conf.set('prefix', prefix)
conf.set('datadir', datadir)
conf.set('pkgdatadir', pkgdatadir)
conf.set('pythondir', join_paths(prefix, pythondir))
conf.set('localedir', join_paths(prefix, localedir))
conf.set('projectname', meson.project_name())
conf.set('prettyname', prettyname)
conf.set('description', description)
conf.set('authorfullname', authorfullname)
conf.set('authoremail', authoremail)
conf.set('appid', app_id)

# Install launch script and add `run` target
configure_file(
  input: meson.project_name() + '.in',
  output: meson.project_name(),
  configuration: conf,
  install: true,
  install_dir: get_option('bindir')
)

script_path = join_paths(meson.project_build_root(), 'bin', meson.project_name())
run_target('run',
  command: [script_path]
)

A data/icu.ccw.Melon.desktop.in => data/icu.ccw.Melon.desktop.in +15 -0
@@ 0,0 1,15 @@
[Desktop Entry]
Name=@prettyname@
Comment=@description@
Exec=@bindir@/@projectname@ %U
# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
Icon=@appid@
Terminal=false
Type=Application
StartupNotify=true
Categories=Graphics;Network;Viewer;GTK;GNOME;
# Translators: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
Keywords=viewer;videos;stream;browse;
X-GNOME-UsesNotifications=true
# Translators: Do NOT translate or transliterate this text (these are enum types)!
X-Purism-FormFactor=Workstation;Mobile;

R melon.svg => data/icu.ccw.Melon.svg +0 -0
A data/meson.build => data/meson.build +33 -0
@@ 0,0 1,33 @@
scalable_dir = join_paths(datadir, 'icons/hicolor/scalable/apps')
install_data (
  '@0@.svg'.format(app_id),
  install_dir: scalable_dir,
)

gnome = import('gnome')

#
# .desktop file
#
desktop_conf = configuration_data()
desktop_conf.set('bindir', join_paths(prefix, bindir))
desktop_conf.set('prettyname', prettyname)
# .desktop comment now hardcoded for better i18n support
desktop_conf.set('description', description)
desktop_conf.set('appid', app_id)
desktop_conf.set('projectname', meson.project_name())

desktop_file = configure_file(
    input: base_id + '.desktop.in',
    output: app_id + '.desktop',
    configuration: desktop_conf,
    install: true,
    install_dir: join_paths(datadir, 'applications')
)

#
# Dependencies
#
dependency('glib-2.0')
dependency('gtk4', version: '>=4.12.1')
dependency('libadwaita-1', version: '>=1.4.0')

M main.py => main.py +9 -26
@@ 1,29 1,12 @@
# manual quick-run script
import sys
import gi
gi.require_version('Gtk', '4.0')
gi.require_version('Adw', '1')
from gi.repository import Gtk, Adw, Gio, GLib
from melon.application import Application
Application.application_id = "icu.ccw.melon"
app = Application()

from melon.window import MainWindow
from melon.models import init_db
from melon.servers.utils import get_server_instance, load_server, get_servers_list
try:
    status = app.run(sys.argv)
except SystemExit as e:
    status = e.code

class MyApp(Adw.Application):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        # set name
        GLib.set_application_name("Melon")
        # initialize db
        init_db()
        # this has to wait till the db is initialized
        for _,server_data in get_servers_list().items():
            instance = get_server_instance(server_data)
            load_server(instance)
        self.connect('activate', self.on_activate)

    def on_activate(self, app):
        self.win = MainWindow(application=app)
        self.win.present()

app = MyApp(application_id="icu.ccw.melon")
app.run(sys.argv)
sys.exit(status)

A melon/application.py => melon/application.py +25 -0
@@ 0,0 1,25 @@
import gi
gi.require_version('Gtk', '4.0')
gi.require_version('Adw', '1')
from gi.repository import Gtk, Adw, Gio, GLib

from melon.window import MainWindow
from melon.models import init_db
from melon.servers.utils import get_server_instance, load_server, get_servers_list

class Application(Adw.Application):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        # set name
        GLib.set_application_name("Melon")
        # initialize db
        init_db()
        # this has to wait till the db is initialized
        for _,server_data in get_servers_list().items():
            instance = get_server_instance(server_data)
            load_server(instance)
        self.connect('activate', self.on_activate)

    def on_activate(self, app):
        self.win = MainWindow(application=app)
        self.win.present()

A meson.build => meson.build +48 -0
@@ 0,0 1,48 @@
project(
  'melon',
  version: '0.1.0',
  meson_version: '>= 0.59.0',
  license: 'GPL-3.0-or-later'
)

description = 'Video player that aims to be mobile friendly. Stream videos on the go from multiple sources.'
prettyname = 'Melon'

authornickname = 'comcloudway'
authorfullname = 'Jakob Meier'
authoremail = 'comcloudway@ccw.icu'

domainname = 'ccw'
domainext = 'icu'

gitrepo = 'https://codeberg.org/' + authornickname + '/' + prettyname

python = import('python')
py_installation = python.find_installation('python3')
if not py_installation.found()
    error('No valid python3 binary found')
else
    message('Found python3 binary')
endif

prefix = get_option('prefix') # should be /usr
bindir = get_option('bindir') # should be /bin
datadir = get_option('datadir') # should be /usr/share
pkgdatadir = join_paths(prefix, datadir, meson.project_name())
pythondir = py_installation.get_install_dir()
localedir = join_paths(prefix, get_option('localedir'))

base_id = '.'.join([domainext, domainname, prettyname])
app_id_aspath = '/'.join([domainext, domainname, prettyname])
app_id = base_id

install_subdir(meson.project_name(), install_dir: pythondir)
subdir('data')
subdir('bin')

# Run required post-install steps
gnome.post_install(
    gtk_update_icon_cache: true,
    glib_compile_schemas: true,
    update_desktop_database: true,
)