Add gphoto error handling, fix crash on fast triggering
This commit is contained in:
parent
0351c19eba
commit
9d5a49da21
|
@ -1,6 +1,7 @@
|
|||
[DEFAULT]
|
||||
# Camera type - can be : showmewebcam, picam, webcam, dslr
|
||||
cam_type = 'webcam'
|
||||
apply_settings_on_startup = true
|
||||
use_date_for_folder = false
|
||||
file_extension = 'jpg'
|
||||
jpg_quality = 88
|
||||
|
|
|
@ -37,6 +37,7 @@ _ = gettext.translation('template', localedir='locales', languages=[LOCALE]).get
|
|||
# defaults
|
||||
project_settings_defaults = {
|
||||
'cam_type': "webcam",
|
||||
'apply_settings_on_startup' : True,
|
||||
'use_date_for_folder': False,
|
||||
'file_extension':'png',
|
||||
'jpg_quality':90,
|
||||
|
@ -421,8 +422,8 @@ class dslr():
|
|||
'whitebalance' : dict(min=0, max=7, step=1, default=2, value=1), # 0 Automatic 1 Daylight 2 Fluorescent 3 Tungsten 4 Flash 5 Cloudy 6 Shade 7 Preset
|
||||
'capturetarget' : dict(min=0, max=1, step=1, default=0, value=0), # Internal memory
|
||||
'iso' : dict(min=0, max=5, default=0, step=1, value=0), # 0:100, 5:3200
|
||||
'shutterspeed' : dict(min=0, max=51, step=1, default=0, value=20), # 0 : 1/4000, 51: 30s
|
||||
'manualfocusdrive' : dict(min=0, max=1, step=1, default=0, value=0), # Trigger autofocus # manualfocusdrive
|
||||
'shutterspeed' : dict(min=0, max=51, step=1, default=0, value=30), # 0 : 1/4000, 51: 30s
|
||||
# ~ 'manualfocusdrive' : dict(min=0, max=1, step=1, default=0, value=0), # Trigger autofocus # manualfocusdrive
|
||||
}
|
||||
# Map generic config name to specific picamera setting name
|
||||
self.cam_settings_map = {
|
||||
|
@ -446,17 +447,22 @@ class dslr():
|
|||
self.onionskin_was_on = self.onionskin
|
||||
self.liveview_only = False
|
||||
self.lenspos = None
|
||||
self.flip_img = False
|
||||
self.cam_busy = False
|
||||
self.cam = self.gp.check_result(self.gp.gp_camera_new())
|
||||
self.camera_current_config = None
|
||||
self.cam = self.init_camera()
|
||||
|
||||
def init_camera(self):
|
||||
cam = self.gp.check_result(self.gp.gp_camera_new())
|
||||
try:
|
||||
self.gp.check_result(self.gp.gp_camera_init(self.cam))
|
||||
self.gp.check_result(self.gp.gp_camera_init(cam))
|
||||
# get configuration tree
|
||||
self.camera_current_config = self.gp.check_result(self.gp.gp_camera_get_config(self.cam))
|
||||
self.camera_current_config = self.gp.check_result(self.gp.gp_camera_get_config(cam))
|
||||
except:
|
||||
print(_("No camera found."))
|
||||
self.cam.exit()
|
||||
self.camera = None
|
||||
cam = None
|
||||
self.current_camera_config = None
|
||||
return cam
|
||||
|
||||
def test_device(self, source):
|
||||
pass
|
||||
|
@ -489,6 +495,8 @@ class dslr():
|
|||
return cur_check_value
|
||||
|
||||
def capture_frame(self, img_path):
|
||||
if self.cam is None:
|
||||
self.cam = self.init_camera()
|
||||
if not self.cam_busy:
|
||||
# CHECK: Should we init and close dslr for each frame ?
|
||||
# Check battery level
|
||||
|
@ -503,32 +511,33 @@ class dslr():
|
|||
# We don't want to download a jpg or raw from the dslr and save it as a false *.png.
|
||||
img_path = self.find_file_ext(file_path.name, img_path)
|
||||
print('Copying image to', img_path)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
try:
|
||||
camera_file = self.cam.file_get(
|
||||
file_path.folder,
|
||||
file_path.name,
|
||||
self.gp.GP_FILE_TYPE_NORMAL
|
||||
)
|
||||
except:
|
||||
print("Camera error. Check Battery and try restarting the camera.")
|
||||
return False
|
||||
try:
|
||||
capture_ok = camera_file.save(img_path)
|
||||
except:
|
||||
print('File access error.')
|
||||
return False
|
||||
# ~ camera.exit()
|
||||
except self.gp.GPhoto2Error as ex:
|
||||
print(ex.code)
|
||||
# This is the way to find which error code is returned by gphoto
|
||||
# See http://gphoto.org/doc/api/gphoto2-result_8h.html for error codes
|
||||
# Cam was turned off/on
|
||||
if ex.code == self.gp.GP_ERROR_IO_USB_FIND or ex.code == self.gp.GP_ERROR_IO_USB_CLAIM:
|
||||
self.cam.exit()
|
||||
self.cam = self.init_camera()
|
||||
# ~ if ex.code == self.gp.GP_ERROR_CAMERA_BUSY:
|
||||
# ~ print("Camera Busy.")
|
||||
self.cam_busy = False
|
||||
return False
|
||||
# Flip image if needed
|
||||
if self.flip_img:
|
||||
frm = cv2.imread(img_path)
|
||||
frm = cv2.flip(frm, -1)
|
||||
cv2.imwrite(img_path, frm)
|
||||
# Update frame
|
||||
cam.frame = cv2.imread(img_path)
|
||||
# ~ frame = cv2.resize(frame, (project_settings['screen_w'], project_settings['screen_h']))
|
||||
# ~ if capture_ok is None:
|
||||
# ~ return True
|
||||
self.frame = cv2.imread(img_path)
|
||||
self.cam_busy = False
|
||||
return True
|
||||
else:
|
||||
pass
|
||||
|
||||
def apply_gphoto_setting(self, setting:str):
|
||||
# Get corresponding setting name if possible
|
||||
|
@ -546,14 +555,6 @@ class dslr():
|
|||
choices = list(self.gp.check_result(self.gp.gp_widget_get_choices(cur_setting)))
|
||||
# Build dict with name/value equivalence
|
||||
choices_dict = {choices.index(i):i for i in list(choices)}
|
||||
# Increment mode : current value is increased or looped
|
||||
# ~ if inc:
|
||||
# Get current setting value
|
||||
# ~ new_value = gp.check_result(gp.gp_widget_get_value(cur_setting))
|
||||
# Check current value + 1 is in range
|
||||
# ~ if choices.index(new_value) in range(0, self.camera_current_settings[setting]['max']+1):
|
||||
# Apply or loop value accordingly
|
||||
# ~ pass
|
||||
# If new_value exists in list, apply
|
||||
if select_setting['value'] in choices_dict:
|
||||
cur_setting_choice = self.gp.check_result(self.gp.gp_widget_get_choice(cur_setting, select_setting['value']))
|
||||
|
@ -570,6 +571,8 @@ class dslr():
|
|||
self.camera_current_settings[setting]['value'] = self.camera_current_settings[setting]['min']
|
||||
|
||||
def apply_setting(self, to_set:list=None, inc:int=0):
|
||||
if self.cam is None:
|
||||
self.cam = self.init_camera()
|
||||
self.camera_current_config = self.gp.check_result(self.gp.gp_camera_get_config(self.cam))
|
||||
# iterate over the settings dictionary
|
||||
if to_set is None:
|
||||
|
@ -592,12 +595,14 @@ class dslr():
|
|||
return status
|
||||
|
||||
def flip_image(self):
|
||||
self.frame = cv2.flip(self.frame, -1)
|
||||
self.flip_img = True
|
||||
|
||||
def focus(self, direction:str='-'):
|
||||
self.apply_setting(['shutterspeed'], 1)
|
||||
|
||||
def reset_picture_settings(self):
|
||||
if self.cam is None:
|
||||
self.cam = self.init_camera()
|
||||
self.camera_current_config = self.gp.check_result(self.gp.gp_camera_get_config(self.cam))
|
||||
for setting in self.camera_current_settings:
|
||||
self.camera_current_settings[setting]['value'] = self.camera_current_settings[setting]['default']
|
||||
|
@ -992,6 +997,7 @@ def main(args):
|
|||
index = len(img_list)-1
|
||||
playhead = index
|
||||
|
||||
if project_settings['apply_settings_on_startup']:
|
||||
cam.apply_setting()
|
||||
|
||||
cam.frame = get_onionskin_frame(savepath)
|
||||
|
@ -1134,22 +1140,27 @@ def main(args):
|
|||
img_name = return_next_frame_number(get_last_frame(savepath))
|
||||
img_path = os.path.join(savepath, img_name)
|
||||
capture_ok = cam.capture_frame(img_path)
|
||||
if capture_ok:
|
||||
print(_("File {} written.").format(img_path))
|
||||
# Special case when we've no frame yet
|
||||
if len(img_list) and (img_list[index] == '{letter}.-001.{ext}'.format(letter=project_letter, ext=project_settings['file_extension'])):
|
||||
img_list[index] = img_name
|
||||
else:
|
||||
index += 1
|
||||
# Display a message if capture was not successfull
|
||||
if not capture_ok:
|
||||
cam.frame = generate_text_image(_("Error during capture."),
|
||||
project_settings['screen_w'], project_settings['screen_h']
|
||||
)
|
||||
cam.o_frame = cam.frame.copy()
|
||||
else:
|
||||
cam.frame = get_onionskin_frame(savepath)
|
||||
cam.o_frame = cam.frame.copy()
|
||||
# ~ frame = cam.frame
|
||||
# Display a message if capture was not successfull
|
||||
# This happens when you try to take too much pictures in a short span of time with the DSLR.
|
||||
# With a long exposure, gphoto will sometimes throw a GP_ERROR_CAMERA_BUSY (-110) error.
|
||||
# In this case, the user should try to take the picture again and it should work, so the need
|
||||
# for a message in UI is not obvious, and can be confusing.
|
||||
# Disabled for now
|
||||
# ~ else:
|
||||
# ~ cam.frame = generate_text_image(_("Error during capture."),
|
||||
# ~ project_settings['screen_w'], project_settings['screen_h']
|
||||
# ~ )
|
||||
# ~ cam.o_frame = cam.frame.copy()
|
||||
|
||||
# Quit app
|
||||
elif k%256 == 27:
|
||||
# ESC pressed
|
||||
|
|
Loading…
Reference in New Issue