|
13 | 13 | Provides logging and platform/operating system compatibility. |
14 | 14 | """ |
15 | 15 |
|
| 16 | +import importlib |
16 | 17 | import logging |
17 | 18 | import os |
| 19 | +import platform |
18 | 20 | import subprocess |
19 | 21 | import sys |
20 | | -from contextlib import contextmanager |
21 | 22 | from typing import AnyStr, Optional |
22 | 23 |
|
23 | 24 | try: |
24 | 25 | import screeninfo |
25 | 26 | except ImportError: |
26 | 27 | screeninfo = None |
27 | 28 |
|
28 | | -from scenedetect.platform import get_and_create_path |
| 29 | +from scenedetect.platform import get_and_create_path, get_ffmpeg_version, get_mkvmerge_version |
29 | 30 |
|
30 | 31 | try: |
31 | 32 | import tkinter |
32 | 33 | except ImportError: |
33 | 34 | tkinter = None |
34 | 35 |
|
35 | 36 |
|
36 | | -# TODO(v1.7): Figure out how to make icon work on Linux. Might need a PNG version. |
37 | | -def get_icon_path() -> str: |
38 | | - if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"): |
39 | | - app_folder = os.path.abspath(os.path.dirname(sys.executable)) |
40 | | - icon_path = os.path.join(app_folder, "dvr-scan.ico") |
41 | | - if os.path.exists(icon_path): |
42 | | - return icon_path |
43 | | - # TODO(v1.7): Figure out how to properly get icon path in the package. The folder will be |
44 | | - # different in the final Windows build, may have to check if this is a frozen instance or not. |
45 | | - # Also need to ensure the icon is included in the package metadata. |
46 | | - # For Python distributions, may have to put dvr-scan.ico with the source files, and use |
47 | | - # os.path.dirname(sys.modules[package].__file__) (or just __file__ here). |
48 | | - for path in ("dvr-scan.ico", "dist/dvr-scan.ico"): |
49 | | - if os.path.exists(path): |
50 | | - return path |
51 | | - return "" |
52 | | - |
53 | | - |
54 | 37 | HAS_TKINTER = tkinter is not None |
55 | 38 |
|
56 | | -IS_WINDOWS = os.name == "nt" |
57 | | - |
58 | | -if IS_WINDOWS: |
59 | | - import ctypes |
60 | | - import ctypes.wintypes |
61 | | - |
62 | 39 |
|
63 | 40 | def get_min_screen_bounds(): |
64 | 41 | """Attempts to get the minimum screen resolution of all monitors using the `screeninfo` package. |
65 | 42 | Returns the minimum of all monitor's heights and widths with 10% padding, or None if the package |
66 | 43 | is unavailable.""" |
| 44 | + # TODO: See if we can replace this with Tkinter (`winfo_screenwidth` / `winfo_screenheight`). |
67 | 45 | if screeninfo is not None: |
68 | 46 | try: |
69 | 47 | monitors = screeninfo.get_monitors() |
@@ -157,42 +135,61 @@ def get_filename(path: AnyStr, include_extension: bool) -> AnyStr: |
157 | 135 | return filename |
158 | 136 |
|
159 | 137 |
|
160 | | -def set_icon(window_name: str): |
161 | | - icon_path = get_icon_path() |
162 | | - if not icon_path: |
163 | | - return |
164 | | - if not IS_WINDOWS: |
165 | | - # TODO: Set icon on Linux/OSX. |
166 | | - return |
167 | | - SendMessage = ctypes.windll.user32.SendMessageW |
168 | | - FindWindow = ctypes.windll.user32.FindWindowW |
169 | | - LoadImage = ctypes.windll.user32.LoadImageW |
170 | | - SetFocus = ctypes.windll.user32.SetFocus |
171 | | - IMAGE_ICON = 1 |
172 | | - ICON_SMALL = 1 |
173 | | - ICON_BIG = 1 |
174 | | - LR_LOADFROMFILE = 0x00000010 |
175 | | - LR_CREATEDIBSECTION = 0x00002000 |
176 | | - WM_SETICON = 0x0080 |
177 | | - hWnd = FindWindow(None, window_name) |
178 | | - hIcon = LoadImage(None, icon_path, IMAGE_ICON, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION) |
179 | | - SendMessage(hWnd, WM_SETICON, ICON_SMALL, hIcon) |
180 | | - SendMessage(hWnd, WM_SETICON, ICON_BIG, hIcon) |
181 | | - SetFocus(hWnd) |
182 | | - |
183 | | - |
184 | | -@contextmanager |
185 | | -def temp_tk_window(): |
186 | | - """Used to provide a hidden Tk window as a root for pop-up dialog boxes to return focus to |
187 | | - main region window when destroyed.""" |
188 | | - root = tkinter.Tk() |
189 | | - try: |
190 | | - root.withdraw() |
191 | | - # TODO: Set icon on Linux/OSX. |
192 | | - if IS_WINDOWS: |
193 | | - icon_path = get_icon_path() |
194 | | - if icon_path: |
195 | | - root.iconbitmap(os.path.abspath(icon_path)) |
196 | | - yield root |
197 | | - finally: |
198 | | - root.destroy() |
| 138 | +def get_system_version_info() -> str: |
| 139 | + """Get the system's operating system, Python, packages, and external tool versions. |
| 140 | + Useful for debugging or filing bug reports. |
| 141 | +
|
| 142 | + Used for the `scenedetect version -a` command. |
| 143 | + """ |
| 144 | + output_template = "{:<8} {}" |
| 145 | + line_separator = "-" * 40 |
| 146 | + not_found_str = "Not Installed" |
| 147 | + out_lines = [] |
| 148 | + |
| 149 | + # System (Python, OS) |
| 150 | + out_lines += ["System Info", line_separator] |
| 151 | + out_lines += [ |
| 152 | + output_template.format(name, version) |
| 153 | + for name, version in ( |
| 154 | + ("OS:", "%s" % platform.platform()), |
| 155 | + ("Python:", "%s %s" % (platform.python_implementation(), platform.python_version())), |
| 156 | + ("Arch:", " + ".join(platform.architecture())), |
| 157 | + ) |
| 158 | + ] |
| 159 | + output_template = "{:<16} {}" |
| 160 | + |
| 161 | + # Third-Party Packages |
| 162 | + out_lines += ["", "Packages", line_separator] |
| 163 | + third_party_packages = ( |
| 164 | + "cv2", |
| 165 | + "dvr_scan", |
| 166 | + "numpy", |
| 167 | + "platformdirs", |
| 168 | + "scenedetect", |
| 169 | + "screeninfo", |
| 170 | + "tqdm", |
| 171 | + ) |
| 172 | + for module_name in third_party_packages: |
| 173 | + try: |
| 174 | + module = importlib.import_module(module_name) |
| 175 | + if hasattr(module, "__version__"): |
| 176 | + out_lines.append(output_template.format(module_name, module.__version__)) |
| 177 | + else: |
| 178 | + out_lines.append(output_template.format(module_name, not_found_str)) |
| 179 | + except ModuleNotFoundError: |
| 180 | + out_lines.append(output_template.format(module_name, not_found_str)) |
| 181 | + |
| 182 | + # External Tools |
| 183 | + out_lines += ["", "Tools", line_separator] |
| 184 | + |
| 185 | + tool_version_info = ( |
| 186 | + ("ffmpeg", get_ffmpeg_version()), |
| 187 | + ("mkvmerge", get_mkvmerge_version()), |
| 188 | + ) |
| 189 | + |
| 190 | + for tool_name, tool_version in tool_version_info: |
| 191 | + out_lines.append( |
| 192 | + output_template.format(tool_name, tool_version if tool_version else not_found_str) |
| 193 | + ) |
| 194 | + |
| 195 | + return "\n".join(out_lines) |
0 commit comments