Skip to content

Commit

Permalink
Merge pull request #803 from musikid/meson
Browse files Browse the repository at this point in the history
build: add meson build system
  • Loading branch information
boltgolt committed Sep 14, 2023
2 parents f7649fc + 466c859 commit 95df4d2
Show file tree
Hide file tree
Showing 39 changed files with 530 additions and 135 deletions.
7 changes: 7 additions & 0 deletions .clang-tidy
@@ -0,0 +1,7 @@
Checks: 'clang-diagnostic-*,clang-analyser-*,-clang-diagnostic-unused-command-line-argument,google-*,bugprone-*,modernize-*,performance-*,portability-*,readability-*,-bugprone-easily-swappable-*,-readability-magic-numbers,-google-readability-todo'
WarningsAsErrors: 'clang-diagnostic-*,clang-analyser-*,-clang-diagnostic-unused-command-line-argument,google-*,bugprone-*,modernize-*,performance-*,portability-*,readability-*,-bugprone-easily-swappable-*,-readability-magic-numbers,-google-readability-todo'
CheckOptions:
- key: readability-function-cognitive-complexity.Threshold
value: '50'

# vim:syntax=yaml
7 changes: 5 additions & 2 deletions .github/workflows/check.yml
Expand Up @@ -8,16 +8,19 @@ jobs:
- name: Install required libraries
run: >
sudo apt-get update && sudo apt-get install -y
python3 python3-pip python3-setuptools python3-wheel ninja-build meson
python3 python3-pip python3-setuptools python3-wheel
cmake make build-essential clang-tidy
libpam0g-dev libinih-dev libevdev-dev
python3-dev libopencv-dev
- name: Install meson
run: sudo python3 -m pip install meson ninja

- uses: actions/checkout@v2

- name: Build
run: |
meson setup build howdy/src/pam
meson setup build
ninja -C build
- name: Check source code
Expand Down
3 changes: 3 additions & 0 deletions howdy-gtk/bin/howdy-gtk.in
@@ -0,0 +1,3 @@
#!/bin/sh

env python3 "@script_path@" "$@"
82 changes: 82 additions & 0 deletions howdy-gtk/meson.build
@@ -0,0 +1,82 @@
if meson.is_subproject()
project('howdy-gtk', license: 'MIT', version: 'beta', meson_version: '>= 0.64.0')
endif

datadir = get_option('prefix') / get_option('datadir') / 'howdy-gtk'
py_conf = configuration_data(paths_dict)
py_conf.set('data_dir', datadir)


py_paths = configure_file(
input: 'src/paths.py.in',
output: 'paths.py',
configuration: py_conf,
)

sources = files(
'src/authsticky.py',
'src/i18n.py',
'src/init.py',
'src/onboarding.py',
'src/paths_factory.py',
'src/tab_models.py',
'src/tab_video.py',
'src/window.py',
)

py = import('python').find_installation(
# modules: ['gi', 'elevate']
)
py.dependency()

if get_option('install_in_site_packages')
pysourcesinstalldir = join_paths(py.get_install_dir(), 'howdy-gtk')
else
pysourcesinstalldir = get_option('py_sources_dir') != '' ? get_option('py_sources_dir') : join_paths(get_option('prefix'), get_option('libdir'), 'howdy-gtk')
endif

if get_option('install_in_site_packages')
py.install_sources(
sources,
py_paths,
subdir: 'howdy-gtk',
install_mode: 'r--r--r--',
install_tag: 'py_sources',
)
else
install_data(
sources,
py_paths,
install_dir: pysourcesinstalldir,
install_mode: 'r--r--r--',
install_tag: 'py_sources',
)
endif

logos = files(
'src/logo.png',
'src/logo_about.png',
)
install_data(logos, install_dir: datadir)

interface_files = files(
'src/main.glade',
'src/onboarding.glade',
)
install_data(interface_files, install_dir: datadir)

cli_path = join_paths(pysourcesinstalldir, 'init.py')
conf_data = configuration_data({ 'script_path': cli_path })

bin_name = 'howdy-gtk'
bin = configure_file(
input: 'bin/howdy-gtk.in',
output: bin_name,
configuration: conf_data
)
install_data(
bin,
install_mode: 'rwxr-xr-x',
install_dir: get_option('prefix') / get_option('bindir'),
install_tag: 'bin',
)
5 changes: 2 additions & 3 deletions howdy-gtk/src/authsticky.py
Expand Up @@ -3,6 +3,7 @@
import gi
import signal
import sys
import paths_factory
import os

from i18n import _
Expand Down Expand Up @@ -32,9 +33,7 @@ def __init__(self):
gtk.Window.__init__(self)

# Get the absolute or relative path to the logo file
logo_path = "/usr/lib/howdy-gtk/logo.png"
if not os.access(logo_path, os.R_OK):
logo_path = "./logo.png"
logo_path = paths_factory.logo_path()

# Create image and calculate scale size based on image size
self.logo_surface = cairo.ImageSurface.create_from_png(logo_path)
Expand Down
21 changes: 5 additions & 16 deletions howdy-gtk/src/onboarding.py
Expand Up @@ -3,6 +3,7 @@
import re
import time
import subprocess
import paths_factory

from i18n import _

Expand All @@ -22,7 +23,7 @@ def __init__(self):
self.connect("delete_event", self.exit)

self.builder = gtk.Builder()
self.builder.add_from_file("./onboarding.glade")
self.builder.add_from_file(paths_factory.onboarding_wireframe_path())
self.builder.connect_signals(self)

self.window = self.builder.get_object("onboardingwindow")
Expand Down Expand Up @@ -67,29 +68,17 @@ def go_next_slide(self, button=None):
self.execute_slide6()

def execute_slide1(self):
conf_path = "/etc/howdy"

self.downloadoutputlabel = self.builder.get_object("downloadoutputlabel")
eventbox = self.builder.get_object("downloadeventbox")
eventbox.modify_bg(gtk.StateType.NORMAL, gdk.Color(red=0, green=0, blue=0))

for lib_site in ("/lib", "/usr/lib", "/lib64", "/usr/lib64"):
if os.path.exists(lib_site + "/security/howdy/"):
break
else:
lib_site = None

if lib_site is None:
self.downloadoutputlabel.set_text(_("Unable to find Howdy's installation location"))
return


if os.path.exists(conf_path + "/dlib-data/shape_predictor_5_face_landmarks.dat"):
# TODO: Better way to do this?
if os.path.exists(paths_factory.dlib_data_dir_path() / "shape_predictor_5_face_landmarks.dat"):
self.downloadoutputlabel.set_text(_("Datafiles have already been downloaded!\nClick Next to continue"))
self.enable_next()
return

self.proc = subprocess.Popen("./install.sh", stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True, cwd=conf_path + "/howdy/dlib-data")
self.proc = subprocess.Popen("./install.sh", stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True, cwd=paths_factory.dlib_data_dir_path())

self.download_lines = []
self.read_download_line()
Expand Down
13 changes: 13 additions & 0 deletions howdy-gtk/src/paths.py.in
@@ -0,0 +1,13 @@
from pathlib import PurePath

# Define the absolute path to the config directory
config_dir = PurePath("@config_dir@")

# Define the absolute path to the DLib models data directory
dlib_data_dir = PurePath("@dlib_data_dir@")

# Define the absolute path to the Howdy user models directory
user_models_dir = PurePath("@user_models_dir@")

# Define the absolute path to the Howdy data directory
data_dir = PurePath("@data_dir@")
32 changes: 32 additions & 0 deletions howdy-gtk/src/paths_factory.py
@@ -0,0 +1,32 @@
from pathlib import PurePath
import paths


def config_file_path() -> str:
"""Return the path to the config file"""
return str(paths.config_dir / "config.ini")


def user_models_dir_path() -> PurePath:
"""Return the path to the user models directory"""
return paths.user_models_dir


def logo_path() -> str:
"""Return the path to the logo file"""
return str(paths.data_dir / "logo.png")


def onboarding_wireframe_path() -> str:
"""Return the path to the onboarding wireframe file"""
return str(paths.data_dir / "onboarding.glade")


def main_window_wireframe_path() -> str:
"""Return the path to the main window wireframe file"""
return str(paths.data_dir / "main.glade")


def dlib_data_dir_path() -> PurePath:
"""Return the path to the dlib data directory"""
return paths.dlib_data_dir
3 changes: 2 additions & 1 deletion howdy-gtk/src/tab_video.py
@@ -1,6 +1,7 @@
import configparser

from i18n import _
import paths_factory

from gi.repository import Gtk as gtk
from gi.repository import Gdk as gdk
Expand All @@ -17,7 +18,7 @@ def on_page_switch(self, notebook, page, page_num):

try:
self.config = configparser.ConfigParser()
self.config.read("/etc/howdy/config.ini")
self.config.read(paths_factory.config_file_path())
except Exception:
print(_("Can't open camera"))

Expand Down
7 changes: 4 additions & 3 deletions howdy-gtk/src/window.py
Expand Up @@ -7,6 +7,7 @@
import subprocess

from i18n import _
import paths_factory

# Make sure we have the libs we need
gi.require_version("Gtk", "3.0")
Expand All @@ -26,7 +27,7 @@ def __init__(self):
self.connect("delete_event", self.exit)

self.builder = gtk.Builder()
self.builder.add_from_file("./main.glade")
self.builder.add_from_file(paths_factory.main_window_wireframe_path())
self.builder.connect_signals(self)

self.window = self.builder.get_object("mainwindow")
Expand All @@ -49,7 +50,7 @@ def __init__(self):
# Add the treeview
self.modellistbox.add(self.treeview)

filelist = os.listdir("/etc/howdy/models")
filelist = os.listdir(paths_factory.user_models_dir_path())
self.active_user = ""

self.userlist.items = 0
Expand Down Expand Up @@ -120,7 +121,7 @@ def exit(self, widget, context):
elevate.elevate()

# If no models have been created yet or when it is forced, start the onboarding
if "--force-onboarding" in sys.argv or not os.path.exists("/etc/howdy/models"):
if "--force-onboarding" in sys.argv or not os.path.exists(paths_factory.user_models_dir_path()):
import onboarding
onboarding.OnboardingWindow()

Expand Down
2 changes: 1 addition & 1 deletion howdy/debian/howdy.manpages
@@ -1 +1 @@
debian/howdy.1
howdy.1
File renamed without changes.
1 change: 1 addition & 0 deletions howdy/meson.build
@@ -0,0 +1 @@
subdir('src')
Expand Up @@ -4,6 +4,8 @@

_howdy() {
local cur prev opts
local config_path="@config_path@"
source _variables
COMPREPLY=()
# The argument typed so far
cur="${COMP_WORDS[COMP_CWORD]}"
Expand All @@ -20,7 +22,7 @@ _howdy() {
;;
# For disable, grab the current "disabled" config option and give the reverse
"disable")
local status=$(cut -d'=' -f2 <<< $(cat /etc/howdy/config.ini | grep 'disabled =') | xargs echo -n)
local status=$(cut -d'=' -f2 <<< $(cat $config_path | grep 'disabled =') | xargs echo -n)

[ "$status" == "false" ] && COMPREPLY="true" || COMPREPLY="false"
return 0
Expand Down
3 changes: 3 additions & 0 deletions howdy/src/bin/howdy.in
@@ -0,0 +1,3 @@
#!/bin/sh

env python3 "@script_path@" "$@"
22 changes: 10 additions & 12 deletions howdy/src/cli/add.py
Expand Up @@ -8,6 +8,7 @@
import configparser
import builtins
import numpy as np
import paths_factory

from recorders.video_capture import VideoCapture
from i18n import _
Expand All @@ -26,39 +27,36 @@
# OpenCV needs to be imported after dlib
import cv2

# Define the absolute path to the config directory
config_path = "/etc/howdy"

# Test if at lest 1 of the data files is there and abort if it's not
if not os.path.isfile(config_path + "/dlib-data/shape_predictor_5_face_landmarks.dat"):
if not os.path.isfile(paths_factory.shape_predictor_5_face_landmarks_path()):
print(_("Data files have not been downloaded, please run the following commands:"))
print("\n\tcd " + config_path + "/dlib-data")
print("\n\tcd " + paths_factory.dlib_data_dir_path())
print("\tsudo ./install.sh\n")
sys.exit(1)

# Read config from disk
config = configparser.ConfigParser()
config.read(config_path + "/config.ini")
config.read(paths_factory.config_file_path())

use_cnn = config.getboolean("core", "use_cnn", fallback=False)
if use_cnn:
face_detector = dlib.cnn_face_detection_model_v1(config_path + "/dlib-data/mmod_human_face_detector.dat")
face_detector = dlib.cnn_face_detection_model_v1(paths_factory.mmod_human_face_detector_path())
else:
face_detector = dlib.get_frontal_face_detector()

pose_predictor = dlib.shape_predictor(config_path + "/dlib-data/shape_predictor_5_face_landmarks.dat")
face_encoder = dlib.face_recognition_model_v1(config_path + "/dlib-data/dlib_face_recognition_resnet_model_v1.dat")
pose_predictor = dlib.shape_predictor(paths_factory.shape_predictor_5_face_landmarks_path())
face_encoder = dlib.face_recognition_model_v1(paths_factory.dlib_face_recognition_resnet_model_v1_path())

user = builtins.howdy_user
# The permanent file to store the encoded model in
enc_file = config_path + "/models/" + user + ".dat"
enc_file = paths_factory.user_model_path(user)
# Known encodings
encodings = []

# Make the ./models folder if it doesn't already exist
if not os.path.exists(config_path + "/models"):
if not os.path.exists(paths_factory.user_models_dir_path()):
print(_("No face model folder found, creating one"))
os.makedirs(config_path + "/models")
os.makedirs(paths_factory.user_models_dir_path())

# To try read a premade encodings file if it exists
try:
Expand Down

0 comments on commit 95df4d2

Please sign in to comment.