feat: read gphoto config
This commit is contained in:
@@ -31,6 +31,9 @@ class MainController:
|
|||||||
self.photo_button: QPushButton = view.photo_button
|
self.photo_button: QPushButton = view.photo_button
|
||||||
self.photo_button.clicked.connect(self.take_photo)
|
self.photo_button.clicked.connect(self.take_photo)
|
||||||
|
|
||||||
|
self.record_button: QPushButton = view.record_button
|
||||||
|
# self.record_button.clicked.connect(self.fun_test)
|
||||||
|
|
||||||
self.color_list.colorSelected.connect(self.on_color_selected)
|
self.color_list.colorSelected.connect(self.on_color_selected)
|
||||||
self.color_list.editColor.connect(self.on_edit_color)
|
self.color_list.editColor.connect(self.on_edit_color)
|
||||||
self.thumbnail_list.selectedThumbnail.connect(self.on_thumbnail_selected)
|
self.thumbnail_list.selectedThumbnail.connect(self.on_thumbnail_selected)
|
||||||
@@ -84,7 +87,7 @@ class MainController:
|
|||||||
|
|
||||||
def start_liveview(self):
|
def start_liveview(self):
|
||||||
self.manager.start_camera()
|
self.manager.start_camera()
|
||||||
self.manager.start_stream()
|
# self.manager.start_stream()
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
self.manager.stop()
|
self.manager.stop()
|
||||||
@@ -19,13 +19,15 @@ class CameraManager(QThread):
|
|||||||
|
|
||||||
self.is_connected = False
|
self.is_connected = False
|
||||||
|
|
||||||
|
|
||||||
self.start()
|
|
||||||
|
|
||||||
def run(self) -> None:
|
|
||||||
self.timer = QTimer()
|
self.timer = QTimer()
|
||||||
self.timer.setInterval(int(1000 / self.fps))
|
self.timer.setInterval(int(1000 / self.fps))
|
||||||
self.timer.timeout.connect(self._update_frame)
|
self.timer.timeout.connect(self._update_frame)
|
||||||
|
self.start()
|
||||||
|
|
||||||
|
def run(self) -> None:
|
||||||
|
# self.timer = QTimer()
|
||||||
|
# self.timer.setInterval(int(1000 / self.fps))
|
||||||
|
# self.timer.timeout.connect(self._update_frame)
|
||||||
self.exec()
|
self.exec()
|
||||||
|
|
||||||
def start_camera(self) -> None:
|
def start_camera(self) -> None:
|
||||||
|
|||||||
@@ -1,30 +1,63 @@
|
|||||||
|
from typing import Optional, List
|
||||||
|
from dataclasses import dataclass, field
|
||||||
import gphoto2 as gp
|
import gphoto2 as gp
|
||||||
import cv2
|
import cv2
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from .base_camera import BaseCamera
|
from .base_camera import BaseCamera
|
||||||
|
|
||||||
|
camera_widget_types = {
|
||||||
|
gp.GP_WIDGET_WINDOW: "GP_WIDGET_WINDOW", # type: ignore
|
||||||
|
gp.GP_WIDGET_SECTION: "GP_WIDGET_SECTION", # type: ignore
|
||||||
|
gp.GP_WIDGET_TEXT: "GP_WIDGET_TEXT", # type: ignore
|
||||||
|
gp.GP_WIDGET_RANGE: "GP_WIDGET_RANGE", # type: ignore
|
||||||
|
gp.GP_WIDGET_TOGGLE: "GP_WIDGET_TOGGLE", # type: ignore
|
||||||
|
gp.GP_WIDGET_RADIO: "GP_WIDGET_RADIO", # type: ignore
|
||||||
|
gp.GP_WIDGET_MENU: "GP_WIDGET_MENU", # type: ignore
|
||||||
|
gp.GP_WIDGET_BUTTON: "GP_WIDGET_BUTTON", # type: ignore
|
||||||
|
gp.GP_WIDGET_DATE: "GP_WIDGET_DATE", # type: ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class CameraWidget:
|
||||||
|
id: int
|
||||||
|
name: str
|
||||||
|
label: str
|
||||||
|
type: str
|
||||||
|
widget: object
|
||||||
|
value: Optional[str] = None
|
||||||
|
choices: List[str] = field(default_factory=list)
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return f"[{self.id} - {self.type}] '{self.name}' {self.label}\n\tvalue = {self.value} | choices = {self.choices}"
|
||||||
|
|
||||||
|
|
||||||
class GPhotoCamera(BaseCamera):
|
class GPhotoCamera(BaseCamera):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.camera = None
|
self.camera = None
|
||||||
|
self.widgets: List[CameraWidget] = []
|
||||||
|
|
||||||
def connect(self) -> bool:
|
def connect(self) -> bool:
|
||||||
self.error_msg = None
|
self.error_msg = None
|
||||||
try:
|
try:
|
||||||
self.camera = gp.Camera() # type: ignore
|
self.camera = gp.Camera() # type: ignore
|
||||||
self.camera.init()
|
self.camera.init()
|
||||||
|
self.read_config()
|
||||||
|
widget = self.get_setting_by_name("iso")
|
||||||
|
self.set_setting_by_id(widget.id, "100")
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.error_msg = f"[GPHOTO2] {e}"
|
self.error_msg = f"[GPHOTO2] {e}"
|
||||||
self.camera = None
|
self.camera = None
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def disconnect(self) -> None:
|
def disconnect(self) -> None:
|
||||||
if self.camera:
|
if self.camera:
|
||||||
self.camera.exit()
|
self.camera.exit()
|
||||||
self.camera = None
|
self.camera = None
|
||||||
|
self.widgets.clear()
|
||||||
|
|
||||||
def get_frame(self):
|
def get_frame(self):
|
||||||
self.error_msg = None
|
self.error_msg = None
|
||||||
@@ -32,15 +65,62 @@ class GPhotoCamera(BaseCamera):
|
|||||||
if self.camera is None:
|
if self.camera is None:
|
||||||
self.error_msg = "[GPHOTO2] Camera is not initialized."
|
self.error_msg = "[GPHOTO2] Camera is not initialized."
|
||||||
return (False, None)
|
return (False, None)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
file = self.camera.capture_preview() # type: ignore
|
file = self.camera.capture_preview() # type: ignore
|
||||||
data = file.get_data_and_size()
|
data = file.get_data_and_size()
|
||||||
frame = np.frombuffer(data, dtype=np.uint8)
|
frame = np.frombuffer(data, dtype=np.uint8)
|
||||||
frame = cv2.imdecode(frame, cv2.IMREAD_COLOR)
|
frame = cv2.imdecode(frame, cv2.IMREAD_COLOR)
|
||||||
|
|
||||||
return (True, frame)
|
return (True, frame)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.error_msg = f"[GPHOTO2] {e}"
|
self.error_msg = f"[GPHOTO2] {e}"
|
||||||
return (False, None)
|
return (False, None)
|
||||||
|
|
||||||
|
def get_setting_by_id(self, id: int) -> CameraWidget:
|
||||||
|
return next(w for w in self.widgets if w.id == id)
|
||||||
|
|
||||||
|
def get_setting_by_name(self, name: str) -> CameraWidget:
|
||||||
|
return next(w for w in self.widgets if w.name == name)
|
||||||
|
|
||||||
|
def set_setting_by_id(self, id: int, value: str):
|
||||||
|
widget = self.get_setting_by_id(id)
|
||||||
|
if value in widget.choices:
|
||||||
|
widget.widget.set_value(value) # type: ignore
|
||||||
|
self.camera.set_single_config(widget.name, widget.widget) # type: ignore
|
||||||
|
|
||||||
|
def read_config(self):
|
||||||
|
if not self.camera:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.widgets.clear()
|
||||||
|
|
||||||
|
def parse_widget(widget):
|
||||||
|
temp_widget = CameraWidget(
|
||||||
|
id=widget.get_id(),
|
||||||
|
name=widget.get_name(),
|
||||||
|
label=widget.get_label(),
|
||||||
|
type=camera_widget_types[widget.get_type()],
|
||||||
|
widget=widget
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
temp_widget.value = widget.get_value()
|
||||||
|
except gp.GPhoto2Error:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
temp_widget.choices = list(widget.get_choices())
|
||||||
|
except gp.GPhoto2Error:
|
||||||
|
pass
|
||||||
|
|
||||||
|
self.widgets.append(temp_widget)
|
||||||
|
|
||||||
|
for i in range(widget.count_children()):
|
||||||
|
parse_widget(widget.get_child(i))
|
||||||
|
|
||||||
|
config = self.camera.get_config()
|
||||||
|
parse_widget(config)
|
||||||
|
|
||||||
|
for wid in self.widgets:
|
||||||
|
print(wid)
|
||||||
|
|||||||
Reference in New Issue
Block a user