Skip to content

Commit f4aff3e

Browse files
authored
Merge pull request #2012 from pupil-labs/develop
Pupil v2.4 Release Candidate 1
2 parents f7353e6 + 6705d98 commit f4aff3e

File tree

80 files changed

+1435
-336
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+1435
-336
lines changed

pupil_src/launchables/eye.py

+30-10
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ def eye(
141141
# helpers/utils
142142
from uvc import get_time_monotonic
143143
from file_methods import Persistent_Dict
144-
from version_utils import VersionFormat
144+
from version_utils import parse_version
145145
from methods import normalize, denormalize, timer
146146
from av_writer import JPEG_Writer, MPEG_Writer, NonMonotonicTimestampError
147147
from ndsi import H264Writer
@@ -236,9 +236,10 @@ def consume_events_and_render_buffer():
236236
glfw.glfwMakeContextCurrent(main_window)
237237
clear_gl_screen()
238238

239-
glViewport(0, 0, *g_pool.camera_render_size)
240-
for p in g_pool.plugins:
241-
p.gl_display()
239+
if all(c > 0 for c in g_pool.camera_render_size):
240+
glViewport(0, 0, *g_pool.camera_render_size)
241+
for p in g_pool.plugins:
242+
p.gl_display()
242243

243244
glViewport(0, 0, *window_size)
244245
# render graphs
@@ -289,6 +290,11 @@ def on_resize(window, w, h):
289290
nonlocal window_size
290291
nonlocal content_scale
291292

293+
is_minimized = bool(glfw.glfwGetWindowAttrib(window, glfw.GLFW_ICONIFIED))
294+
295+
if is_minimized:
296+
return
297+
292298
# Always clear buffers on resize to make sure that there are no overlapping
293299
# artifacts from previous frames.
294300
gl_utils.glClear(gl_utils.GL_COLOR_BUFFER_BIT)
@@ -362,7 +368,7 @@ def on_drop(window, count, paths):
362368
session_settings = Persistent_Dict(
363369
os.path.join(g_pool.user_dir, "user_settings_eye{}".format(eye_id))
364370
)
365-
if VersionFormat(session_settings.get("version", "0.0")) != g_pool.version:
371+
if parse_version(session_settings.get("version", "0.0")) != g_pool.version:
366372
logger.info(
367373
"Session setting are from a different version of this app. I will not use those."
368374
)
@@ -407,8 +413,15 @@ def toggle_general_settings(collapsed):
407413
width, height = session_settings.get("window_size", default_window_size)
408414

409415
main_window = glfw.glfwCreateWindow(width, height, title, None, None)
410-
window_pos = session_settings.get("window_position", window_position_default)
416+
417+
window_position_manager = gl_utils.WindowPositionManager()
418+
window_pos = window_position_manager.new_window_position(
419+
window=main_window,
420+
default_position=window_position_default,
421+
previous_position=session_settings.get("window_position", None),
422+
)
411423
glfw.glfwSetWindowPos(main_window, window_pos[0], window_pos[1])
424+
412425
glfw.glfwMakeContextCurrent(main_window)
413426
cygl.utils.init()
414427

@@ -503,6 +516,7 @@ def set_window_size():
503516
toggle_general_settings(True)
504517

505518
g_pool.writer = None
519+
g_pool.rec_path = None
506520

507521
# Register callbacks main_window
508522
glfw.glfwSetFramebufferSizeCallback(main_window, on_resize)
@@ -567,12 +581,12 @@ def window_should_update():
567581
break
568582
elif subject == "recording.started":
569583
if notification["record_eye"] and g_pool.capture.online:
570-
record_path = notification["rec_path"]
584+
g_pool.rec_path = notification["rec_path"]
571585
raw_mode = notification["compression"]
572586
start_time_synced = notification["start_time_synced"]
573-
logger.info("Will save eye video to: {}".format(record_path))
587+
logger.info(f"Will save eye video to: {g_pool.rec_path}")
574588
video_path = os.path.join(
575-
record_path, "eye{}.mp4".format(eye_id)
589+
g_pool.rec_path, "eye{}.mp4".format(eye_id)
576590
)
577591
if raw_mode and frame and g_pool.capture.jpeg_support:
578592
g_pool.writer = JPEG_Writer(video_path, start_time_synced)
@@ -592,7 +606,13 @@ def window_should_update():
592606
g_pool.writer.release()
593607
except RuntimeError:
594608
logger.error("No eye video recorded")
595-
g_pool.writer = None
609+
else:
610+
# TODO: wrap recording logic into plugin
611+
g_pool.capture.intrinsics.save(
612+
g_pool.rec_path, custom_name=f"eye{eye_id}"
613+
)
614+
finally:
615+
g_pool.writer = None
596616
elif subject.startswith("meta.should_doc"):
597617
ipc_socket.notify(
598618
{

pupil_src/launchables/player.py

+21-7
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ def player(
8383
from video_capture import File_Source
8484

8585
# helpers/utils
86-
from version_utils import VersionFormat
86+
from version_utils import parse_version
8787
from methods import normalize, denormalize, delta_t, get_system_info
8888
import player_methods as pm
8989
from pupil_recording import PupilRecording
@@ -131,7 +131,7 @@ def player(
131131
InvalidRecordingException,
132132
)
133133

134-
assert VersionFormat(pyglui_version) >= VersionFormat(
134+
assert parse_version(pyglui_version) >= parse_version(
135135
"1.28"
136136
), "pyglui out of date, please upgrade to newest version"
137137

@@ -346,7 +346,7 @@ def get_dt():
346346
session_settings = Persistent_Dict(
347347
os.path.join(user_dir, "user_settings_player")
348348
)
349-
if VersionFormat(session_settings.get("version", "0.0")) != app_version:
349+
if parse_version(session_settings.get("version", "0.0")) != app_version:
350350
logger.info(
351351
"Session setting are a different version of this app. I will not use those."
352352
)
@@ -356,13 +356,20 @@ def get_dt():
356356
width += icon_bar_width
357357
width, height = session_settings.get("window_size", (width, height))
358358

359-
window_pos = session_settings.get("window_position", window_position_default)
360359
window_name = f"Pupil Player: {meta_info.recording_name} - {rec_dir}"
361360

362361
glfw.glfwInit()
363362
glfw.glfwWindowHint(glfw.GLFW_SCALE_TO_MONITOR, glfw.GLFW_TRUE)
364363
main_window = glfw.glfwCreateWindow(width, height, window_name, None, None)
364+
365+
window_position_manager = gl_utils.WindowPositionManager()
366+
window_pos = window_position_manager.new_window_position(
367+
window=main_window,
368+
default_position=window_position_default,
369+
previous_position=session_settings.get("window_position", None),
370+
)
365371
glfw.glfwSetWindowPos(main_window, window_pos[0], window_pos[1])
372+
366373
glfw.glfwMakeContextCurrent(main_window)
367374
cygl.utils.init()
368375
g_pool.main_window = main_window
@@ -793,7 +800,7 @@ def player_drop(
793800
import glfw
794801
import gl_utils
795802
from OpenGL.GL import glClearColor
796-
from version_utils import VersionFormat
803+
from version_utils import parse_version
797804
from file_methods import Persistent_Dict
798805
from pyglui.pyfontstash import fontstash
799806
from pyglui.ui import get_roboto_font_path
@@ -830,13 +837,12 @@ def on_drop(window, count, paths):
830837
session_settings = Persistent_Dict(
831838
os.path.join(user_dir, "user_settings_player")
832839
)
833-
if VersionFormat(session_settings.get("version", "0.0")) != app_version:
840+
if parse_version(session_settings.get("version", "0.0")) != app_version:
834841
logger.info(
835842
"Session setting are from a different version of this app. I will not use those."
836843
)
837844
session_settings.clear()
838845
w, h = session_settings.get("window_size", (1280, 720))
839-
window_pos = session_settings.get("window_position", window_position_default)
840846

841847
glfw.glfwInit()
842848
glfw.glfwWindowHint(glfw.GLFW_SCALE_TO_MONITOR, glfw.GLFW_TRUE)
@@ -845,7 +851,15 @@ def on_drop(window, count, paths):
845851
glfw.glfwWindowHint(glfw.GLFW_RESIZABLE, 1)
846852

847853
glfw.glfwMakeContextCurrent(window)
854+
855+
window_position_manager = gl_utils.WindowPositionManager()
856+
window_pos = window_position_manager.new_window_position(
857+
window=window,
858+
default_position=window_position_default,
859+
previous_position=session_settings.get("window_position", None),
860+
)
848861
glfw.glfwSetWindowPos(window, window_pos[0], window_pos[1])
862+
849863
glfw.glfwSetDropCallback(window, on_drop)
850864

851865
glfont = fontstash.Context()

pupil_src/launchables/service.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def stop_eye_process(eye_id):
8888
# helpers/utils
8989
from file_methods import Persistent_Dict
9090
from methods import delta_t, get_system_info
91-
from version_utils import VersionFormat
91+
from version_utils import parse_version
9292
import audio
9393
from uvc import get_time_monotonic
9494

@@ -183,7 +183,7 @@ def get_dt():
183183
session_settings = Persistent_Dict(
184184
os.path.join(g_pool.user_dir, "user_settings_service")
185185
)
186-
if session_settings.get("version", VersionFormat("0.0")) < g_pool.version:
186+
if parse_version(session_settings.get("version", "0.0")) < g_pool.version:
187187
logger.info(
188188
"Session setting are from older version of this app. I will not use those."
189189
)

pupil_src/launchables/world.py

+11-4
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,10 @@ def detection_enabled_setter(is_on: bool):
118118

119119
# display
120120
import glfw
121-
from version_utils import VersionFormat
121+
from version_utils import parse_version
122122
from pyglui import ui, cygl, __version__ as pyglui_version
123123

124-
assert VersionFormat(pyglui_version) >= VersionFormat(
124+
assert parse_version(pyglui_version) >= parse_version(
125125
"1.27"
126126
), "pyglui out of date, please upgrade to newest version"
127127
from pyglui.cygl.utils import Named_Texture
@@ -441,7 +441,7 @@ def get_dt():
441441
session_settings = Persistent_Dict(
442442
os.path.join(g_pool.user_dir, "user_settings_world")
443443
)
444-
if VersionFormat(session_settings.get("version", "0.0")) != g_pool.version:
444+
if parse_version(session_settings.get("version", "0.0")) != g_pool.version:
445445
logger.info(
446446
"Session setting are from a different version of this app. I will not use those."
447447
)
@@ -514,8 +514,15 @@ def handle_notifications(noti):
514514
if hide_ui:
515515
glfw.glfwWindowHint(glfw.GLFW_VISIBLE, 0) # hide window
516516
main_window = glfw.glfwCreateWindow(width, height, "Pupil Capture - World")
517-
window_pos = session_settings.get("window_position", window_position_default)
517+
518+
window_position_manager = gl_utils.WindowPositionManager()
519+
window_pos = window_position_manager.new_window_position(
520+
window=main_window,
521+
default_position=window_position_default,
522+
previous_position=session_settings.get("window_position", None),
523+
)
518524
glfw.glfwSetWindowPos(main_window, window_pos[0], window_pos[1])
525+
519526
glfw.glfwMakeContextCurrent(main_window)
520527
cygl.utils.init()
521528
g_pool.main_window = main_window

pupil_src/shared_modules/accuracy_visualizer.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,8 @@ def __handle_calibration_result_notification(self, note_dict: dict) -> bool:
293293
return False
294294

295295
self.recent_input.update(
296-
gazer_class_name=note.gazer_class_name, gazer_params=note.params,
296+
gazer_class_name=note.gazer_class_name,
297+
gazer_params=note.params,
297298
)
298299

299300
self.recalculate()

pupil_src/shared_modules/annotations.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def create_annotation(label, timestamp, duration=0.0, **custom_fields):
2929
"""
3030
Returns a dictionary in the format needed to send annotations
3131
to an annotation plugin via the ICP.
32-
32+
3333
See python/remote_annotations.py in pupil-helpers for an example.
3434
3535
:param custom_fields:

pupil_src/shared_modules/audio/__init__.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ def get_audio_mode():
4141

4242

4343
def set_audio_mode(new_mode):
44-
"""a save way to set the audio mode
45-
"""
44+
"""a save way to set the audio mode"""
4645
if new_mode in get_audio_mode_list():
4746
global _audio_mode
4847
_audio_mode = new_mode

pupil_src/shared_modules/audio_playback.py

+10-4
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@
2626
import gl_utils
2727
from audio_utils import Audio_Viz_Transform, NoAudioLoadedError, load_audio
2828
from plugin import System_Plugin_Base
29-
from version_utils import VersionFormat
29+
from version_utils import parse_version
3030

3131

32-
assert VersionFormat(av.__version__) >= VersionFormat("0.4.4")
32+
assert parse_version(av.__version__) >= parse_version("0.4.4")
3333

3434

3535
logger = logging.getLogger(__name__)
@@ -191,7 +191,8 @@ def _setup_filter_graph(self):
191191
self.filter_graph_list[-2].link_to(self.filter_graph_list[-1])
192192
self.filter_graph_list.append(
193193
self.filter_graph.add(
194-
"aresample", "osf={}".format(self.audio.stream.format.packed.name),
194+
"aresample",
195+
"osf={}".format(self.audio.stream.format.packed.name),
195196
)
196197
)
197198
self.filter_graph_list[-2].link_to(self.filter_graph_list[-1])
@@ -421,7 +422,12 @@ def set_volume(val):
421422

422423
self.menu.append(
423424
ui.Slider(
424-
"req_audio_volume", self, step=0.05, min=0.0, max=1.0, label="Volume",
425+
"req_audio_volume",
426+
self,
427+
step=0.05,
428+
min=0.0,
429+
max=1.0,
430+
label="Volume",
425431
)
426432
)
427433
self.menu.append(

pupil_src/shared_modules/batch_exporter.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@
3636

3737
def get_recording_dirs(data_dir):
3838
"""
39-
You can supply a data folder or any folder
40-
- all folders within will be checked for necessary files
41-
- in order to make a visualization
39+
You can supply a data folder or any folder
40+
- all folders within will be checked for necessary files
41+
- in order to make a visualization
4242
"""
4343
if is_pupil_rec_dir(data_dir):
4444
yield data_dir

pupil_src/shared_modules/calibration_choreography/base_plugin.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,8 @@ def ref_list(self, value):
297297
def on_choreography_started(self, mode: ChoreographyMode):
298298
self.notify_all(
299299
ChoreographyNotification(
300-
mode=mode, action=ChoreographyAction.STARTED,
300+
mode=mode,
301+
action=ChoreographyAction.STARTED,
301302
).to_dict()
302303
)
303304

@@ -452,8 +453,7 @@ def update_ui(self):
452453
)
453454

454455
def deinit_ui(self):
455-
"""Gets called when the plugin get terminated, either voluntarily or forced.
456-
"""
456+
"""Gets called when the plugin get terminated, either voluntarily or forced."""
457457
if self.is_active:
458458
self._perform_stop()
459459
self.remove_menu()

pupil_src/shared_modules/calibration_choreography/natural_feature_plugin.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535
class NaturalFeatureChoreographyPlugin(CalibrationChoreographyPlugin):
3636
"""Calibrate using natural features in a scene.
37-
Features are selected by a user by clicking on
37+
Features are selected by a user by clicking on
3838
"""
3939

4040
label = "Natural Feature Calibration"

pupil_src/shared_modules/calibration_choreography/screen_marker_plugin.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,8 @@ def recent_events(self, events):
188188
if isinstance(state, MarkerWindowStateIdle):
189189
assert self.__currently_shown_marker_position is None # Sanity check
190190
if self.__current_list_of_markers_to_show:
191-
self.__currently_shown_marker_position = self.__current_list_of_markers_to_show.pop(
192-
0
191+
self.__currently_shown_marker_position = (
192+
self.__current_list_of_markers_to_show.pop(0)
193193
)
194194
logger.debug(
195195
f"Moving screen marker to site at {self.__currently_shown_marker_position}"

pupil_src/shared_modules/calibration_choreography/single_marker_plugin.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ class SingleMarkerChoreographyPlugin(
8282
MonitorSelectionMixin, CalibrationChoreographyPlugin
8383
):
8484
"""Calibrate using a single marker.
85-
Move your head for example in a spiral motion while gazing
86-
at the marker to quickly sample a wide range gaze angles.
85+
Move your head for example in a spiral motion while gazing
86+
at the marker to quickly sample a wide range gaze angles.
8787
"""
8888

8989
label = "Single Marker Calibration"

0 commit comments

Comments
 (0)