- removed -r command line option and renamed it to -s. then added -l as what -s used to be. - added detect_uri option to camera parameters so stream snapshots can now run a secondary stream that differs from the recording stream. also added sync logic so the recording loop and detection loop will run synchronously while still running in seperate threads. - live_secs renamed to live_mins. the amount of live footage to buffer in buffer_path is now based on minutes instead of seconds. - added live_clip_secs parameter so the amount of seconds each hls video clip should have is now adjustable. - remove max_event_secs. events are now transfered to rec_path based on minute increments. - added sec_per_image to make the amount of seconds between stream snapshots pulled from detect_uri adjustable. - added img_ext so the image snapshot format from detect_uri and then ultimately to img_comp_cmd can now be configured instead of being hardcoded to bmp. - added gray_image as a boolean parameter so the snapshots from detect_uri can be pulled in grayscale format or remain in color if desired. - removed img_scale since this parameter was not doing anything. overview: use of QFileSystemWatcher on the detection loop has been eliminated and thus eliminated use of functions such as listFacingFiles(), backwardFacingFiles() and forwardFacingFiles(). Instead, the detection and recording loops will now run synchronously and use predictable up-to-the-minute file naming scheme. client v1.1: - the build script will now include all imageformat plugins from the QT lib directory, adding support for jpg, svg, ico and gif image formats. - switched to 2 number versioning. - this client app will now support the server's new up-to-the-minute directory structure for live and recorded footage. - the version number is now be displayed on the main interface.
267 lines
8.9 KiB
Python
Executable File
267 lines
8.9 KiB
Python
Executable File
#!/usr/bin/python3
|
|
|
|
import os
|
|
import re
|
|
import subprocess
|
|
import shutil
|
|
import sys
|
|
import platform
|
|
|
|
def get_app_target(text):
|
|
return re.search(r'(APP_TARGET) +(\"(.*?)\")', text).group(3)
|
|
|
|
def get_app_ver(text):
|
|
return re.search(r'(APP_VERSION) +(\"(.*?)\")', text).group(3)
|
|
|
|
def get_app_name(text):
|
|
return re.search(r'(APP_NAME) +(\"(.*?)\")', text).group(3)
|
|
|
|
def get_qt_path():
|
|
try:
|
|
return str(subprocess.check_output(["qtpaths6", "--binaries-dir"]), 'utf-8').strip()
|
|
|
|
except:
|
|
print("A direct call to 'qtpaths6' has failed so automatic retrieval of the QT bin folder is not possible.")
|
|
|
|
return input("Please enter the QT bin path (leave blank to cancel the build): ")
|
|
|
|
def get_qt_from_cli():
|
|
for arg in sys.argv:
|
|
if arg == "-qt_dir":
|
|
index = sys.argv.index(arg)
|
|
|
|
try:
|
|
return sys.argv[index + 1]
|
|
|
|
except:
|
|
return ""
|
|
|
|
return ""
|
|
|
|
def get_ver_header():
|
|
current_dir = os.path.dirname(__file__)
|
|
|
|
if current_dir == "":
|
|
return "src" + os.sep + "common.h"
|
|
else:
|
|
return current_dir + os.sep + "src" + os.sep + "common.h"
|
|
|
|
def get_nearest_subdir(path, sub_name):
|
|
dir_list = os.listdir(path)
|
|
ret = ""
|
|
|
|
for entry in dir_list:
|
|
if sub_name in entry:
|
|
ret = entry
|
|
|
|
break
|
|
|
|
return ret
|
|
|
|
def cd():
|
|
current_dir = os.path.dirname(__file__)
|
|
|
|
if current_dir != "":
|
|
os.chdir(current_dir)
|
|
|
|
def verbose_copy(src, dst):
|
|
print("cpy: " + src + " --> " + dst)
|
|
|
|
if os.path.isdir(src):
|
|
if os.path.exists(dst) and os.path.isdir(dst):
|
|
shutil.rmtree(dst)
|
|
|
|
try:
|
|
# ignore errors thrown by shutil.copytree()
|
|
# it's likely not actually failing to copy
|
|
# the directory but still throws errors if
|
|
# it fails to apply the same file stats as
|
|
# the source. this type of error can be
|
|
# ignored.
|
|
shutil.copytree(src, dst)
|
|
|
|
except:
|
|
pass
|
|
|
|
elif os.path.exists(src):
|
|
shutil.copyfile(src, dst)
|
|
|
|
else:
|
|
print("wrn: " + src + " does not exists. skipping.")
|
|
|
|
def linux_build_app_dir(app_ver, app_name, app_target, qt_bin):
|
|
if not os.path.exists("app_dir/platforms"):
|
|
os.makedirs("app_dir/platforms")
|
|
|
|
if not os.path.exists("app_dir/xcbglintegrations"):
|
|
os.makedirs("app_dir/xcbglintegrations")
|
|
|
|
if not os.path.exists("app_dir/multimedia"):
|
|
os.makedirs("app_dir/multimedia")
|
|
|
|
if not os.path.exists("app_dir/platformthemes"):
|
|
os.makedirs("app_dir/platformthemes")
|
|
|
|
if not os.path.exists("app_dir/lib"):
|
|
os.makedirs("app_dir/lib")
|
|
|
|
if not os.path.exists("app_dir/icons"):
|
|
os.makedirs("app_dir/icons")
|
|
|
|
if not os.path.exists("app_dir/imageformats"):
|
|
os.makedirs("app_dir/imageformats")
|
|
|
|
verbose_copy(qt_bin + "/../plugins/platforms", "app_dir/platforms")
|
|
verbose_copy(qt_bin + "/../plugins/xcbglintegrations", "app_dir/xcbglintegrations")
|
|
verbose_copy(qt_bin + "/../plugins/multimedia", "app_dir/multimedia")
|
|
verbose_copy(qt_bin + "/../plugins/platformthemes", "app_dir/platformthemes")
|
|
verbose_copy(qt_bin + "/../plugins/imageformats", "app_dir/imageformats")
|
|
verbose_copy("build/" + app_target, "app_dir/" + app_target)
|
|
verbose_copy("icons/main.svg", "app_dir/icons/scalable.svg")
|
|
|
|
img_sizes = [8, 16, 22, 24, 28, 32, 36, 42, 48, 64, 72, 96, 128, 192, 256, 512, 1024]
|
|
|
|
for i in img_sizes:
|
|
subprocess.run(["inkscape", "-w", str(i), "-h", str(i), "icons/main.svg", "-o", "app_dir/icons/" + str(i) + ".png"])
|
|
|
|
shutil.copyfile("build/" + app_target, "/tmp/" + app_target)
|
|
# copying the executable file from the build folder to
|
|
# temp bypasses any -noexe retrictions a linux file
|
|
# system may have. there is a chance temp is also
|
|
# restricted in this way but that kind of config is
|
|
# rare. ldd will not run correctly with -noexe
|
|
# enabled.
|
|
|
|
lines = str(subprocess.check_output(["ldd", "/tmp/" + app_target]), 'utf-8').split("\n")
|
|
|
|
os.remove("/tmp/" + app_target)
|
|
|
|
for line in lines:
|
|
if " => " in line and "libc" not in line:
|
|
#if ("libQt" in line) or ("libicu" in line) or ("libGL.so" in line) or ("libpcre16.so" in line) or ("libpcre.so" in line):
|
|
if " (0x0" in line:
|
|
start_index = line.index("> ") + 2
|
|
end_index = line.index(" (0x0")
|
|
src_file = line[start_index:end_index]
|
|
file_name = os.path.basename(src_file)
|
|
|
|
verbose_copy(src_file, "app_dir/lib/" + file_name)
|
|
|
|
if "/usr/lib/x86_64-linux-gnu/qt6/bin" == qt_bin:
|
|
verbose_copy(qt_bin + "/../../libQt6DBus.so.6", "app_dir/lib/libQt6DBus.so.6")
|
|
verbose_copy(qt_bin + "/../../libQt6XcbQpa.so.6", "app_dir/lib/libQt6XcbQpa.so.6")
|
|
|
|
else:
|
|
verbose_copy(qt_bin + "/../lib/libQt6DBus.so.6", "app_dir/lib/libQt6DBus.so.6")
|
|
verbose_copy(qt_bin + "/../lib/libQt6XcbQpa.so.6", "app_dir/lib/libQt6XcbQpa.so.6")
|
|
verbose_copy(qt_bin + "/../lib/libQt6OpenGL.so.6", "app_dir/lib/libQt6OpenGL.so.6")
|
|
|
|
verbose_copy("templates/linux_run_script.sh", "app_dir/" + app_target + ".sh")
|
|
verbose_copy("templates/linux_uninstall.sh", "app_dir/uninstall.sh")
|
|
verbose_copy("templates/linux_icon.desktop", "app_dir/" + app_target + ".desktop")
|
|
|
|
complete(app_ver, app_target)
|
|
|
|
def complete(app_ver, app_target):
|
|
print("Build complete for version: " + app_ver)
|
|
print("You can now run the install.py script to install onto this machine or create an installer.")
|
|
|
|
def get_like_distro():
|
|
info = platform.freedesktop_os_release()
|
|
ids = [info["ID"]]
|
|
|
|
if "ID_LIKE" in info:
|
|
# ids are space separated and ordered by precedence
|
|
ids.extend(info["ID_LIKE"].split())
|
|
|
|
return ids
|
|
|
|
def list_installed_packages():
|
|
like_distro = get_like_distro()
|
|
|
|
if ("ubuntu" in like_distro) or ("debian" in like_distro) or ("linuxmint" in like_distro):
|
|
return str(subprocess.check_output(["apt", "list", "--installed"]), 'utf-8')
|
|
|
|
elif ("fedora" in like_distro) or ("rhel" in like_distro):
|
|
return str(subprocess.check_output(["dnf", "list", "installed"]), 'utf-8')
|
|
|
|
elif ("arch" in like_distro):
|
|
return str(subprocess.check_output(["pacman", "-Q"]), 'utf-8')
|
|
|
|
else:
|
|
print("Warning: unable to determine a package manager for this platform.")
|
|
|
|
return []
|
|
|
|
|
|
def list_of_words_in_text(list_of_words, text_body):
|
|
for word in list_of_words:
|
|
if not word in text_body:
|
|
return False
|
|
|
|
return True
|
|
|
|
def platform_setup():
|
|
ins_packages = list_installed_packages()
|
|
like_distro = get_like_distro()
|
|
dep_pkgs_a = ["pkg-config"]
|
|
dep_pkgs_b = ["ffmpeg", "libavcodec-dev", "libavformat-dev", "libavfilter-dev", "libavdevice-dev", "libilmbase-dev", "libvdpau-dev", "libxkbcommon-dev", "libgl-dev", "libxcb-cursor0", "inkscape"]
|
|
|
|
if not list_of_words_in_text(dep_pkgs_a, ins_packages) or not list_of_words_in_text(dep_pkgs_b, ins_packages):
|
|
if ("ubuntu" in like_distro) or ("debian" in like_distro) or ("linuxmint" in like_distro):
|
|
subprocess.run(["sudo", "apt", "update", "-y"])
|
|
subprocess.run(["sudo", "apt", "install", "-y"] + dep_pkgs_a)
|
|
subprocess.run(["sudo", "apt", "install", "-y"] + dep_pkgs_b)
|
|
|
|
elif ("fedora" in like_distro) or ("rhel" in like_distro):
|
|
subprocess.run(["sudo", "dnf", "install", "-y"] + dep_pkgs_a)
|
|
subprocess.run(["sudo", "dnf", "install", "-y"] + dep_pkgs_b)
|
|
|
|
elif ("arch" in like_distro):
|
|
subprocess.run(["sudo", "pacman", "-S", "--noconfirm"] + dep_pkgs_a)
|
|
subprocess.run(["sudo", "pacman", "-S", "--noconfirm"] + dep_pkgs_b)
|
|
|
|
def main():
|
|
platform_setup()
|
|
|
|
with open(get_ver_header()) as file:
|
|
text = file.read()
|
|
|
|
app_target = get_app_target(text)
|
|
app_ver = get_app_ver(text)
|
|
app_name = get_app_name(text)
|
|
qt_bin = get_qt_from_cli()
|
|
|
|
if qt_bin == "":
|
|
qt_bin = get_qt_path()
|
|
|
|
if qt_bin != "":
|
|
print("app_target = " + app_target)
|
|
print("app_version = " + app_ver)
|
|
print("app_name = " + app_name)
|
|
print("qt_bin = " + qt_bin)
|
|
|
|
cd()
|
|
|
|
result = subprocess.run([qt_bin + os.sep + "qmake", "-config", "release"])
|
|
|
|
if result.returncode == 0:
|
|
result = subprocess.run(["make"])
|
|
|
|
if result.returncode == 0:
|
|
if os.path.exists("app_dir"):
|
|
shutil.rmtree("app_dir")
|
|
|
|
os.makedirs("app_dir")
|
|
|
|
with open("app_dir" + os.sep + "info.txt", "w") as info_file:
|
|
info_file.write(app_target + "\n")
|
|
info_file.write(app_ver + "\n")
|
|
info_file.write(app_name + "\n")
|
|
|
|
linux_build_app_dir(app_ver, app_name, app_target, qt_bin)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|