python-camera-manager-directshow 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- GUI/__init__.py +3 -0
- GUI/main_GUI.py +1006 -0
- app/__init__.py +0 -0
- app/main.py +106 -0
- camera/__init__.py +5 -0
- camera/camera_device_bridge.py +1305 -0
- camera/camera_inspector_bridge.py +46 -0
- camera/camera_manager.py +1004 -0
- python_camera_manager_directshow-0.1.0.dist-info/METADATA +239 -0
- python_camera_manager_directshow-0.1.0.dist-info/RECORD +18 -0
- python_camera_manager_directshow-0.1.0.dist-info/WHEEL +5 -0
- python_camera_manager_directshow-0.1.0.dist-info/entry_points.txt +2 -0
- python_camera_manager_directshow-0.1.0.dist-info/licenses/LICENSE +21 -0
- python_camera_manager_directshow-0.1.0.dist-info/top_level.txt +4 -0
- runtime/__init__.py +0 -0
- runtime/dotnet/DirectShowLib.dll +0 -0
- runtime/dotnet/DirectShowLibWrapper.dll +0 -0
- runtime/dotnet/__init__.py +0 -0
app/__init__.py
ADDED
|
File without changes
|
app/main.py
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
# Allow running as `python app/main.py` while importing top-level packages.
|
|
5
|
+
PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
6
|
+
if PROJECT_ROOT not in sys.path:
|
|
7
|
+
sys.path.insert(0, PROJECT_ROOT)
|
|
8
|
+
|
|
9
|
+
from camera import _camera
|
|
10
|
+
from GUI.main_GUI import MainGUI, select_camera_gui, show_no_camera_dialog
|
|
11
|
+
import cv2
|
|
12
|
+
import threading
|
|
13
|
+
cv2.utils.logging.setLogLevel(cv2.utils.logging.LOG_LEVEL_ERROR)
|
|
14
|
+
|
|
15
|
+
debug = False
|
|
16
|
+
|
|
17
|
+
def debug_print(*args, **kwargs):
|
|
18
|
+
"""Print only if DEBUG mode is enabled."""
|
|
19
|
+
if debug:
|
|
20
|
+
print(*args, **kwargs)
|
|
21
|
+
|
|
22
|
+
def main():
|
|
23
|
+
gui = MainGUI()
|
|
24
|
+
# Scan for devices and prompt user to Retry/Cancel if none found
|
|
25
|
+
while True:
|
|
26
|
+
uvc_cameras = _camera.Camera.get_connected_cameras(get_formats=True, get_ranges=True)
|
|
27
|
+
|
|
28
|
+
if uvc_cameras:
|
|
29
|
+
break
|
|
30
|
+
|
|
31
|
+
retry = show_no_camera_dialog(gui.root)
|
|
32
|
+
if not retry:
|
|
33
|
+
print("No cameras found. Exiting.")
|
|
34
|
+
return
|
|
35
|
+
|
|
36
|
+
# Get device path and format from GUI
|
|
37
|
+
device_path, camera_format, request_rgb24 = select_camera_gui(uvc_cameras, gui.root)
|
|
38
|
+
if device_path is None or camera_format is None:
|
|
39
|
+
print("No camera selected. Exiting.")
|
|
40
|
+
return
|
|
41
|
+
|
|
42
|
+
debug_print(f"Selected camera: {device_path}")
|
|
43
|
+
debug_print(f"Format: {camera_format.width}x{camera_format.height} @ {camera_format.fps} FPS")
|
|
44
|
+
|
|
45
|
+
# Open the selected camera using the Camera class
|
|
46
|
+
camera = _camera.Camera(debug_logging=[False,False,False])
|
|
47
|
+
|
|
48
|
+
# Connect the GUI callback to the camera BEFORE opening
|
|
49
|
+
camera.set_frame_callback(gui.update_video_frame)
|
|
50
|
+
|
|
51
|
+
# Open with device path and format
|
|
52
|
+
camera_opened_successfully = camera.open(
|
|
53
|
+
device_path,
|
|
54
|
+
camera_format,
|
|
55
|
+
request_rgb24_conversion=bool(request_rgb24)
|
|
56
|
+
)
|
|
57
|
+
if not camera_opened_successfully:
|
|
58
|
+
debug_print("Failed to open camera.")
|
|
59
|
+
return
|
|
60
|
+
|
|
61
|
+
# Bind active camera to GUI controls (e.g., format switching)
|
|
62
|
+
gui.bind_camera(camera, device_path)
|
|
63
|
+
|
|
64
|
+
debug_print("Camera opened successfully!")
|
|
65
|
+
|
|
66
|
+
# Handle window close event to ensure clean shutdown
|
|
67
|
+
closing_state = {"started": False}
|
|
68
|
+
|
|
69
|
+
def on_close():
|
|
70
|
+
if closing_state["started"]:
|
|
71
|
+
return
|
|
72
|
+
|
|
73
|
+
closing_state["started"] = True
|
|
74
|
+
|
|
75
|
+
try:
|
|
76
|
+
# Stop forwarding new frames to Tk while shutdown is in progress.
|
|
77
|
+
camera.set_frame_callback(None)
|
|
78
|
+
except Exception:
|
|
79
|
+
pass
|
|
80
|
+
|
|
81
|
+
def close_camera_background():
|
|
82
|
+
try:
|
|
83
|
+
camera.close()
|
|
84
|
+
except Exception as e:
|
|
85
|
+
print(f"Error closing camera: {e}")
|
|
86
|
+
|
|
87
|
+
close_thread = threading.Thread(target=close_camera_background, daemon=True)
|
|
88
|
+
close_thread.start()
|
|
89
|
+
|
|
90
|
+
def finish_close():
|
|
91
|
+
try:
|
|
92
|
+
gui.root.destroy()
|
|
93
|
+
except Exception:
|
|
94
|
+
pass
|
|
95
|
+
|
|
96
|
+
# Try fast/clean close first; if driver blocks, force-close UI shortly after.
|
|
97
|
+
gui.root.after(50, finish_close)
|
|
98
|
+
gui.root.after(1500, finish_close)
|
|
99
|
+
|
|
100
|
+
gui.root.protocol("WM_DELETE_WINDOW", on_close)
|
|
101
|
+
|
|
102
|
+
# Start the GUI event loop
|
|
103
|
+
gui.run()
|
|
104
|
+
|
|
105
|
+
if __name__ == "__main__":
|
|
106
|
+
main()
|