boris-behav-obs 9.6.6__tar.gz → 9.7.1__tar.gz
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.
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/PKG-INFO +4 -6
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/README.md +3 -5
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/cmd_arguments.py +2 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/config.py +1 -2
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/connections.py +3 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/core.py +203 -163
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/core_ui.py +6 -2
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/event_operations.py +55 -0
- boris_behav_obs-9.7.1/boris/ipc_mpv.py +304 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/observation_operations.py +173 -234
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/player_dock_widget.py +9 -4
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/utilities.py +77 -55
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/version.py +2 -2
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/video_operations.py +1 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris_behav_obs.egg-info/PKG-INFO +4 -6
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris_behav_obs.egg-info/SOURCES.txt +1 -2
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/pyproject.toml +1 -8
- boris_behav_obs-9.6.6/boris/1.py +0 -45
- boris_behav_obs-9.6.6/boris/mpv-1.0.3.py +0 -2102
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/LICENSE.TXT +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/MANIFEST.in +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/README.TXT +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/__init__.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/__main__.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/about.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/add_modifier.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/add_modifier_ui.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/advanced_event_filtering.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/analysis_plugins/__init__.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/analysis_plugins/_latency.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/analysis_plugins/irr_cohen_kappa.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/analysis_plugins/irr_cohen_kappa_with_modifiers.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/analysis_plugins/irr_weighted_cohen_kappa.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/analysis_plugins/irr_weighted_cohen_kappa_with_modifiers.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/analysis_plugins/list_of_dataframe_columns.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/analysis_plugins/number_of_occurences.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/analysis_plugins/number_of_occurences_by_independent_variable.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/analysis_plugins/time_budget.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/behav_coding_map_creator.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/behavior_binary_table.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/behaviors_coding_map.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/boris_cli.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/coding_pad.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/config_file.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/converters.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/converters_ui.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/cooccurence.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/core_qrc.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/db_functions.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/dev.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/dialog.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/duration_widget.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/edit_event.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/edit_event_ui.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/events_cursor.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/events_snapshots.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/exclusion_matrix.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/export_events.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/export_observation.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/external_processes.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/geometric_measurement.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/gui_utilities.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/image_overlay.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/import_observations.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/irr.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/latency.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/measurement_widget.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/media_file.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/menu_options.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/modifier_coding_map_creator.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/modifiers_coding_map.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/mpv.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/mpv2.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/observation.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/observation_ui.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/observations_list.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/otx_parser.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/param_panel.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/param_panel_ui.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/plot_data_module.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/plot_events.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/plot_events_rt.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/plot_spectrogram_rt.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/plot_waveform_rt.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/plugins.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/portion/__init__.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/portion/const.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/portion/dict.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/portion/func.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/portion/interval.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/portion/io.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/preferences.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/preferences_ui.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/project.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/project_functions.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/project_import_export.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/project_ui.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/qrc_boris.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/qrc_boris5.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/select_modifiers.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/select_observations.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/select_subj_behav.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/state_events.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/subjects_pad.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/synthetic_time_budget.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/time_budget_functions.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/time_budget_widget.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/transitions.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/video_equalizer.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/video_equalizer_ui.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/view_df.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/view_df_ui.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris/write_event.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris_behav_obs.egg-info/dependency_links.txt +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris_behav_obs.egg-info/entry_points.txt +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris_behav_obs.egg-info/requires.txt +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/boris_behav_obs.egg-info/top_level.txt +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/setup.cfg +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/tests/test_db_functions.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/tests/test_export_observation.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/tests/test_irr.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/tests/test_observation_gui.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/tests/test_otx_parser.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/tests/test_preferences_gui.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/tests/test_project_functions.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/tests/test_time_budget.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/tests/test_utilities.py +0 -0
- {boris_behav_obs-9.6.6 → boris_behav_obs-9.7.1}/tests/test_utilities2.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: boris-behav-obs
|
|
3
|
-
Version: 9.
|
|
3
|
+
Version: 9.7.1
|
|
4
4
|
Summary: BORIS - Behavioral Observation Research Interactive Software
|
|
5
5
|
Author-email: Olivier Friard <olivier.friard@unito.it>
|
|
6
6
|
License-Expression: GPL-3.0-only
|
|
@@ -52,13 +52,15 @@ It provides also some analysis tools like time budget and some plotting function
|
|
|
52
52
|
<!-- The BO-RIS paper has more than [ citations](https://www.boris.unito.it/citations) in peer-reviewed scientific publications. -->
|
|
53
53
|
|
|
54
54
|
|
|
55
|
-
The BORIS paper has more than
|
|
55
|
+
The BORIS paper has more than 2407 citations in peer-reviewed scientific publications.
|
|
56
56
|
|
|
57
57
|
|
|
58
58
|
|
|
59
59
|
|
|
60
60
|
See the official [BORIS web site](https://www.boris.unito.it).
|
|
61
61
|
|
|
62
|
+
<a href="https://www.boris.unito.it" target="_blank"><img alt="Website" src="https://img.shields.io/website?url=https%3A%2F%2Fwww.boris.unito.it"></a>
|
|
63
|
+
<a href="https://www.boris.unito.it/user_guide/" target="_blank"><img alt="User guide" src="https://img.shields.io/badge/Documentation-orange"></a>
|
|
62
64
|
[](https://www.python.org)
|
|
63
65
|

|
|
64
66
|

|
|
@@ -136,7 +138,3 @@ GNU General Public License for more details.
|
|
|
136
138
|
Distributed with a [GPL v.3 license](LICENSE.TXT).
|
|
137
139
|
|
|
138
140
|
Copyright (C) 2012-2025 Olivier Friard
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
@@ -14,13 +14,15 @@ It provides also some analysis tools like time budget and some plotting function
|
|
|
14
14
|
<!-- The BO-RIS paper has more than [ citations](https://www.boris.unito.it/citations) in peer-reviewed scientific publications. -->
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
The BORIS paper has more than
|
|
17
|
+
The BORIS paper has more than 2407 citations in peer-reviewed scientific publications.
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
See the official [BORIS web site](https://www.boris.unito.it).
|
|
23
23
|
|
|
24
|
+
<a href="https://www.boris.unito.it" target="_blank"><img alt="Website" src="https://img.shields.io/website?url=https%3A%2F%2Fwww.boris.unito.it"></a>
|
|
25
|
+
<a href="https://www.boris.unito.it/user_guide/" target="_blank"><img alt="User guide" src="https://img.shields.io/badge/Documentation-orange"></a>
|
|
24
26
|
[](https://www.python.org)
|
|
25
27
|

|
|
26
28
|

|
|
@@ -98,7 +100,3 @@ GNU General Public License for more details.
|
|
|
98
100
|
Distributed with a [GPL v.3 license](LICENSE.TXT).
|
|
99
101
|
|
|
100
102
|
Copyright (C) 2012-2025 Olivier Friard
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
@@ -35,6 +35,8 @@ def parse_arguments():
|
|
|
35
35
|
parser.add_option("-n", "--nosplashscreen", action="store_true", default=False, help="No splash screen")
|
|
36
36
|
parser.add_option("-p", "--project", action="store", default="", dest="project", help="Project file")
|
|
37
37
|
parser.add_option("-o", "--observation", action="store", default="", dest="observation", help="Observation id")
|
|
38
|
+
parser.add_option("-i", "--ipc", action="store_true", default="", dest="ipc", help="MPV IPC mode")
|
|
39
|
+
|
|
38
40
|
parser.add_option(
|
|
39
41
|
"-f",
|
|
40
42
|
"--no-first-launch-dialog",
|
|
@@ -120,6 +120,7 @@ def connections(self):
|
|
|
120
120
|
self.actionSelect_observations.triggered.connect(lambda: event_operations.select_events_between_activated(self))
|
|
121
121
|
|
|
122
122
|
self.actionEdit_selected_events.triggered.connect(lambda: event_operations.edit_selected_events(self))
|
|
123
|
+
self.action_add_comment.triggered.connect(lambda: event_operations.add_comment(self))
|
|
123
124
|
self.actionEdit_event_time.triggered.connect(lambda: event_operations.edit_time_selected_events(self))
|
|
124
125
|
|
|
125
126
|
self.actionCopy_events.triggered.connect(lambda: event_operations.copy_selected_events(self))
|
|
@@ -343,6 +344,8 @@ def connections(self):
|
|
|
343
344
|
|
|
344
345
|
self.tv_events.addAction(self.actionAdd_event)
|
|
345
346
|
self.tv_events.addAction(self.actionEdit_selected_events)
|
|
347
|
+
self.tv_events.addAction(self.action_add_comment)
|
|
348
|
+
|
|
346
349
|
self.tv_events.addAction(self.actionEdit_event_time)
|
|
347
350
|
|
|
348
351
|
self.tv_events.addAction(self.actionCopy_events)
|
|
@@ -150,7 +150,7 @@ if util.versiontuple(platform.python_version()) < util.versiontuple(MIN_PYTHON_V
|
|
|
150
150
|
logging.critical(msg)
|
|
151
151
|
sys.exit()
|
|
152
152
|
|
|
153
|
-
if sys.platform
|
|
153
|
+
if sys.platform.startswith("darwin"): # for MacOS
|
|
154
154
|
os.environ["LC_ALL"] = "en_US.UTF-8"
|
|
155
155
|
|
|
156
156
|
|
|
@@ -236,8 +236,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
236
236
|
processes: list = [] # list of QProcess processes
|
|
237
237
|
overlays: dict = {} # dict for storing video overlays
|
|
238
238
|
|
|
239
|
-
undo_queue = deque()
|
|
240
|
-
undo_description = deque()
|
|
239
|
+
undo_queue = deque() # queue for undoing event operations
|
|
240
|
+
undo_description = deque() # queue for description of event operations
|
|
241
241
|
|
|
242
242
|
current_player: int = 0 # id of the selected (left click) video player
|
|
243
243
|
|
|
@@ -400,7 +400,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
400
400
|
|
|
401
401
|
# if BORIS is running on Mac lock all dockwidget features
|
|
402
402
|
# because Qdockwidgets may have a strange behavior
|
|
403
|
-
if sys.platform
|
|
403
|
+
if sys.platform.startswith("darwin"):
|
|
404
404
|
self.action_block_dockwidgets.setChecked(True)
|
|
405
405
|
self.block_dockwidgets()
|
|
406
406
|
|
|
@@ -1428,55 +1428,60 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
1428
1428
|
if not self.dw_player[player].player.playlist_count:
|
|
1429
1429
|
return
|
|
1430
1430
|
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
if
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
self.dw_player[player].player.seek(new_time_float, "absolute+exact")
|
|
1431
|
+
try:
|
|
1432
|
+
# one media
|
|
1433
|
+
if self.dw_player[player].player.playlist_count == 1:
|
|
1434
|
+
if new_time < self.dw_player[player].player.duration:
|
|
1435
|
+
new_time_float = round(float(new_time), 3)
|
|
1437
1436
|
|
|
1438
|
-
|
|
1439
|
-
self.
|
|
1440
|
-
round(self.dw_player[0].player.time_pos / self.dw_player[0].player.duration * (cfg.SLIDER_MAXIMUM - 1))
|
|
1441
|
-
)
|
|
1442
|
-
return 0
|
|
1443
|
-
else:
|
|
1444
|
-
return 1
|
|
1437
|
+
self.dw_player[player].player.seek(new_time_float, "absolute+exact")
|
|
1438
|
+
self.mpv_timer_out()
|
|
1445
1439
|
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
for idx, d in enumerate(self.dw_player[player].cumul_media_durations_sec[:-1]):
|
|
1450
|
-
if d <= new_time < self.dw_player[player].cumul_media_durations_sec[idx + 1]:
|
|
1451
|
-
self.dw_player[player].player.playlist_pos = idx
|
|
1452
|
-
time.sleep(0.5)
|
|
1453
|
-
|
|
1454
|
-
self.dw_player[player].player.seek(
|
|
1455
|
-
round(
|
|
1456
|
-
float(new_time)
|
|
1457
|
-
- sum(self.dw_player[player].media_durations[0 : self.dw_player[player].player.playlist_pos]) / 1000,
|
|
1458
|
-
3,
|
|
1459
|
-
),
|
|
1460
|
-
"absolute+exact",
|
|
1440
|
+
if player == 0 and not self.user_move_slider:
|
|
1441
|
+
self.video_slider.setValue(
|
|
1442
|
+
round(self.dw_player[0].player.time_pos / self.dw_player[0].player.duration * (cfg.SLIDER_MAXIMUM - 1))
|
|
1461
1443
|
)
|
|
1444
|
+
return 0
|
|
1445
|
+
else:
|
|
1446
|
+
return 1
|
|
1447
|
+
|
|
1448
|
+
# many media
|
|
1449
|
+
else:
|
|
1450
|
+
if new_time < self.dw_player[player].cumul_media_durations_sec[-1]:
|
|
1451
|
+
for idx, d in enumerate(self.dw_player[player].cumul_media_durations_sec[:-1]):
|
|
1452
|
+
if d <= new_time < self.dw_player[player].cumul_media_durations_sec[idx + 1]:
|
|
1453
|
+
self.dw_player[player].player.playlist_pos = idx
|
|
1454
|
+
time.sleep(0.5)
|
|
1455
|
+
|
|
1456
|
+
self.dw_player[player].player.seek(
|
|
1457
|
+
round(
|
|
1458
|
+
float(new_time)
|
|
1459
|
+
- sum(self.dw_player[player].media_durations[0 : self.dw_player[player].player.playlist_pos]) / 1000,
|
|
1460
|
+
3,
|
|
1461
|
+
),
|
|
1462
|
+
"absolute+exact",
|
|
1463
|
+
)
|
|
1462
1464
|
|
|
1463
|
-
|
|
1465
|
+
break
|
|
1464
1466
|
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1467
|
+
if player == 0 and not self.user_move_slider:
|
|
1468
|
+
self.video_slider.setValue(
|
|
1469
|
+
round(self.dw_player[0].player.time_pos / self.dw_player[0].player.duration * (cfg.SLIDER_MAXIMUM - 1))
|
|
1470
|
+
)
|
|
1471
|
+
return 0
|
|
1472
|
+
else:
|
|
1473
|
+
QMessageBox.warning(
|
|
1474
|
+
self,
|
|
1475
|
+
cfg.programName,
|
|
1476
|
+
(
|
|
1477
|
+
"The indicated position is greater than the total media duration "
|
|
1478
|
+
f"({util.seconds2time(self.dw_player[player].cumul_media_durations_sec[-1])})"
|
|
1479
|
+
),
|
|
1468
1480
|
)
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
cfg.programName,
|
|
1474
|
-
(
|
|
1475
|
-
"The indicated position is greater than the total media duration "
|
|
1476
|
-
f"({util.seconds2time(self.dw_player[player].cumul_media_durations_sec[-1])})"
|
|
1477
|
-
),
|
|
1478
|
-
)
|
|
1479
|
-
return 1
|
|
1481
|
+
return 1
|
|
1482
|
+
except Exception as e:
|
|
1483
|
+
print(f"error in seek mediaplayer function: {e}")
|
|
1484
|
+
return 0
|
|
1480
1485
|
|
|
1481
1486
|
def jump_to(self) -> None:
|
|
1482
1487
|
"""
|
|
@@ -3685,6 +3690,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
3685
3690
|
if self.playerType == cfg.MEDIA:
|
|
3686
3691
|
for dw in self.dw_player:
|
|
3687
3692
|
dw.player.frame_step()
|
|
3693
|
+
|
|
3688
3694
|
if self.geometric_measurements_mode:
|
|
3689
3695
|
self.extract_frame(dw)
|
|
3690
3696
|
|
|
@@ -3692,6 +3698,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
3692
3698
|
for idx in self.plot_data:
|
|
3693
3699
|
self.timer_plot_data_out(self.plot_data[idx])
|
|
3694
3700
|
|
|
3701
|
+
self.mpv_timer_out()
|
|
3702
|
+
|
|
3695
3703
|
if self.geometric_measurements_mode:
|
|
3696
3704
|
geometric_measurement.redraw_measurements(self)
|
|
3697
3705
|
|
|
@@ -3709,6 +3717,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
3709
3717
|
if self.playerType == cfg.MEDIA:
|
|
3710
3718
|
for dw in self.dw_player:
|
|
3711
3719
|
dw.player.frame_back_step()
|
|
3720
|
+
|
|
3712
3721
|
if self.geometric_measurements_mode:
|
|
3713
3722
|
self.extract_frame(dw)
|
|
3714
3723
|
|
|
@@ -3716,6 +3725,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
3716
3725
|
for idx in self.plot_data:
|
|
3717
3726
|
self.timer_plot_data_out(self.plot_data[idx])
|
|
3718
3727
|
|
|
3728
|
+
self.mpv_timer_out()
|
|
3729
|
+
|
|
3719
3730
|
if self.geometric_measurements_mode:
|
|
3720
3731
|
geometric_measurement.redraw_measurements(self)
|
|
3721
3732
|
|
|
@@ -3728,77 +3739,78 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
3728
3739
|
QMessageBox.warning(self, cfg.programName, "Function not yet implemented")
|
|
3729
3740
|
return
|
|
3730
3741
|
|
|
3731
|
-
if not self.observationId:
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
if self.twEvents.selectedItems():
|
|
3736
|
-
row_s = self.twEvents.selectedItems()[0].row()
|
|
3737
|
-
row_e = self.twEvents.selectedItems()[-1].row()
|
|
3738
|
-
eventtime_s = self.pj[cfg.OBSERVATIONS][self.observationId][cfg.EVENTS][row_s][0]
|
|
3739
|
-
eventtime_e = self.pj[cfg.OBSERVATIONS][self.observationId][cfg.EVENTS][row_e][0]
|
|
3740
|
-
|
|
3741
|
-
durations = [] # in seconds
|
|
3742
|
-
|
|
3743
|
-
# TODO: check for 2nd player
|
|
3744
|
-
for mediaFile in self.pj[cfg.OBSERVATIONS][self.observationId][cfg.FILE][cfg.PLAYER1]:
|
|
3745
|
-
durations.append(self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO]["length"][mediaFile])
|
|
3746
|
-
|
|
3747
|
-
mediaFileIdx_s = [idx1 for idx1, x in enumerate(durations) if eventtime_s >= sum(durations[0:idx1])][-1]
|
|
3748
|
-
media_path_s = self.pj[cfg.OBSERVATIONS][self.observationId][cfg.FILE][cfg.PLAYER1][mediaFileIdx_s]
|
|
3749
|
-
|
|
3750
|
-
mediaFileIdx_e = [idx1 for idx1, x in enumerate(durations) if eventtime_e >= sum(durations[0:idx1])][-1]
|
|
3751
|
-
media_path_e = self.pj[cfg.OBSERVATIONS][self.observationId][cfg.FILE][cfg.PLAYER1][mediaFileIdx_e]
|
|
3752
|
-
|
|
3753
|
-
# calculate time for current media file in case of many queued media files
|
|
3754
|
-
|
|
3755
|
-
eventtime_onmedia_s = round(eventtime_s - util.float2decimal(sum(durations[0:mediaFileIdx_s])), 3)
|
|
3756
|
-
eventtime_onmedia_e = round(eventtime_e - util.float2decimal(sum(durations[0:mediaFileIdx_e])), 3)
|
|
3757
|
-
|
|
3758
|
-
if media_path_s != media_path_e:
|
|
3759
|
-
return
|
|
3760
|
-
|
|
3761
|
-
media_path = media_path_s
|
|
3762
|
-
|
|
3763
|
-
# example of external command defined in environment:
|
|
3764
|
-
# export BORISEXTERNAL="myprog -i {MEDIA_PATH} -s {START_S} -e {END_S} {DURATION_MS} --other"
|
|
3742
|
+
# if not self.observationId:
|
|
3743
|
+
# self.no_observation()
|
|
3744
|
+
# return
|
|
3765
3745
|
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3746
|
+
#
|
|
3747
|
+
# if self.twEvents.selectedItems():
|
|
3748
|
+
# row_s = self.twEvents.selectedItems()[0].row()
|
|
3749
|
+
# row_e = self.twEvents.selectedItems()[-1].row()
|
|
3750
|
+
# eventtime_s = self.pj[cfg.OBSERVATIONS][self.observationId][cfg.EVENTS][row_s][0]
|
|
3751
|
+
# eventtime_e = self.pj[cfg.OBSERVATIONS][self.observationId][cfg.EVENTS][row_e][0]
|
|
3752
|
+
#
|
|
3753
|
+
# durations = [] # in seconds
|
|
3754
|
+
#
|
|
3755
|
+
# # TODO: check for 2nd player
|
|
3756
|
+
# for mediaFile in self.pj[cfg.OBSERVATIONS][self.observationId][cfg.FILE][cfg.PLAYER1]:
|
|
3757
|
+
# durations.append(self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO]["length"][mediaFile])
|
|
3758
|
+
#
|
|
3759
|
+
# mediaFileIdx_s = [idx1 for idx1, x in enumerate(durations) if eventtime_s >= sum(durations[0:idx1])][-1]
|
|
3760
|
+
# media_path_s = self.pj[cfg.OBSERVATIONS][self.observationId][cfg.FILE][cfg.PLAYER1][mediaFileIdx_s]
|
|
3761
|
+
#
|
|
3762
|
+
# mediaFileIdx_e = [idx1 for idx1, x in enumerate(durations) if eventtime_e >= sum(durations[0:idx1])][-1]
|
|
3763
|
+
# media_path_e = self.pj[cfg.OBSERVATIONS][self.observationId][cfg.FILE][cfg.PLAYER1][mediaFileIdx_e]
|
|
3764
|
+
#
|
|
3765
|
+
# # calculate time for current media file in case of many queued media files
|
|
3766
|
+
#
|
|
3767
|
+
# eventtime_onmedia_s = round(eventtime_s - util.float2decimal(sum(durations[0:mediaFileIdx_s])), 3)
|
|
3768
|
+
# eventtime_onmedia_e = round(eventtime_e - util.float2decimal(sum(durations[0:mediaFileIdx_e])), 3)
|
|
3769
|
+
#
|
|
3770
|
+
# if media_path_s != media_path_e:
|
|
3771
|
+
# return
|
|
3772
|
+
#
|
|
3773
|
+
# media_path = media_path_s
|
|
3774
|
+
#
|
|
3775
|
+
# # example of external command defined in environment:
|
|
3776
|
+
# # export BORISEXTERNAL="myprog -i {MEDIA_PATH} -s {START_S} -e {END_S} {DURATION_MS} --other"
|
|
3777
|
+
#
|
|
3778
|
+
# if "BORISEXTERNAL" in os.environ:
|
|
3779
|
+
# external_command_template = os.environ["BORISEXTERNAL"]
|
|
3780
|
+
# else:
|
|
3781
|
+
# return
|
|
3782
|
+
#
|
|
3783
|
+
# external_command = external_command_template.format(
|
|
3784
|
+
# OBS_ID=self.observationId,
|
|
3785
|
+
# MEDIA_PATH=f'"{media_path}"',
|
|
3786
|
+
# MEDIA_BASENAME=f'"{os.path.basename(media_path)}"',
|
|
3787
|
+
# START_S=eventtime_onmedia_s,
|
|
3788
|
+
# END_S=eventtime_onmedia_e,
|
|
3789
|
+
# START_MS=eventtime_onmedia_s * 1000,
|
|
3790
|
+
# END_MS=eventtime_onmedia_e * 1000,
|
|
3791
|
+
# DURATION_S=eventtime_onmedia_e - eventtime_onmedia_s,
|
|
3792
|
+
# DURATION_MS=(eventtime_onmedia_e - eventtime_onmedia_s) * 1000,
|
|
3793
|
+
# )
|
|
3794
|
+
#
|
|
3795
|
+
# print(external_command)
|
|
3796
|
+
# """
|
|
3797
|
+
# p = subprocess.Popen(external_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
|
3798
|
+
# """
|
|
3799
|
+
# """
|
|
3800
|
+
# if eventtimeS == eventtimeE:
|
|
3801
|
+
# q = []
|
|
3802
|
+
# else:
|
|
3803
|
+
# durationsec = eventtimeE-eventtimeS
|
|
3804
|
+
# q = ["--durationmsec",str(int(durationsec*1000))]
|
|
3805
|
+
# args = [ex, "-f",os.path.abspath(fn),"--seekmsec",str(int(eventtimeS*1000)),*q,*("--size 1 --track 1 --redetect 100")
|
|
3806
|
+
# .split(" ")]
|
|
3807
|
+
# if os.path.split(fn)[1].split("_")[0] in set(["A1","A2","A3","A4","A5","A6","A7","A8","A9","A10"]):
|
|
3808
|
+
# args.append("--flip")
|
|
3809
|
+
# args.append("2")
|
|
3810
|
+
# print (os.path.split(fn)[1].split("_")[0])
|
|
3811
|
+
# print ("running",ex,"with",args,"in",os.path.split(ex)[0])
|
|
3812
|
+
# #pid = subprocess.Popen(args,executable=ex,cwd=os.path.split(ex)[0])
|
|
3813
|
+
# """
|
|
3802
3814
|
|
|
3803
3815
|
def no_media(self):
|
|
3804
3816
|
QMessageBox.warning(self, cfg.programName, "There is no media available")
|
|
@@ -3859,10 +3871,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
3859
3871
|
returns frame index for player player_idx
|
|
3860
3872
|
"""
|
|
3861
3873
|
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
else:
|
|
3865
|
-
estimated_frame_number = observation_operations.send_command({"command": ["get_property", "estimated_frame_number"]})
|
|
3874
|
+
estimated_frame_number = self.dw_player[player_idx].player.estimated_frame_number
|
|
3875
|
+
|
|
3866
3876
|
if estimated_frame_number is not None:
|
|
3867
3877
|
return estimated_frame_number
|
|
3868
3878
|
else:
|
|
@@ -3938,7 +3948,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
3938
3948
|
if self.dw_player[0].player.duration is None:
|
|
3939
3949
|
return
|
|
3940
3950
|
video_position = slider_position * self.dw_player[0].player.duration
|
|
3941
|
-
self.dw_player[0].player.command("seek", str(video_position), "absolute")
|
|
3951
|
+
# self.dw_player[0].player.command("seek", str(video_position), "absolute")
|
|
3952
|
+
self.dw_player[0].player.seek(video_position, "absolute")
|
|
3942
3953
|
|
|
3943
3954
|
self.plot_timer_out()
|
|
3944
3955
|
|
|
@@ -4131,7 +4142,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
4131
4142
|
self.dw_player[n_player].player.playlist_pos = self.dw_player[n_player].player.playlist_count - 1
|
|
4132
4143
|
self.seek_mediaplayer(self.dw_player[n_player].media_durations[-1], player=n_player)
|
|
4133
4144
|
|
|
4134
|
-
def mpv_timer_out(self, value: Union[float, None], scroll_slider=True):
|
|
4145
|
+
def mpv_timer_out(self, value: Union[float, None] = None, scroll_slider=True):
|
|
4135
4146
|
"""
|
|
4136
4147
|
print the media current position and total length for MPV player
|
|
4137
4148
|
scroll video slider to video position
|
|
@@ -4141,13 +4152,17 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
4141
4152
|
if not self.observationId:
|
|
4142
4153
|
return
|
|
4143
4154
|
|
|
4155
|
+
print("mpv timer out")
|
|
4156
|
+
|
|
4144
4157
|
cumulative_time_pos = self.getLaps()
|
|
4158
|
+
print(f"{cumulative_time_pos=}")
|
|
4145
4159
|
# get frame index
|
|
4146
4160
|
frame_idx = self.get_frame_index()
|
|
4161
|
+
print(f"{frame_idx=}")
|
|
4147
4162
|
# frame_idx = 0
|
|
4148
4163
|
|
|
4149
|
-
if value is None:
|
|
4150
|
-
current_media_time_pos = 0
|
|
4164
|
+
if value is None: # ipc mpv
|
|
4165
|
+
current_media_time_pos = self.dw_player[0].player.time_pos
|
|
4151
4166
|
else:
|
|
4152
4167
|
current_media_time_pos = value
|
|
4153
4168
|
|
|
@@ -4185,22 +4200,19 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
4185
4200
|
|
|
4186
4201
|
ct0 = cumulative_time_pos
|
|
4187
4202
|
|
|
4188
|
-
if
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
ct = self.getLaps(n_player=n_player)
|
|
4203
|
+
if self.dw_player[0].player.time_pos is not None:
|
|
4204
|
+
for n_player in range(1, len(self.dw_player)):
|
|
4205
|
+
ct = self.getLaps(n_player=n_player)
|
|
4192
4206
|
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
>= 1
|
|
4197
|
-
):
|
|
4198
|
-
self.sync_time(n_player, ct0) # self.seek_mediaplayer(ct0, n_player)
|
|
4207
|
+
# sync players 2..8 if time diff >= 1 s
|
|
4208
|
+
if abs(ct0 - (ct + dec(self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO][cfg.OFFSET][str(n_player + 1)]))) >= 1:
|
|
4209
|
+
self.sync_time(n_player, ct0) # self.seek_mediaplayer(ct0, n_player)
|
|
4199
4210
|
|
|
4200
4211
|
currentTimeOffset = dec(cumulative_time_pos + self.pj[cfg.OBSERVATIONS][self.observationId][cfg.TIME_OFFSET])
|
|
4201
4212
|
|
|
4202
4213
|
all_media_duration = sum(self.dw_player[0].media_durations) / 1000
|
|
4203
4214
|
current_media_duration = self.dw_player[0].player.duration # mediaplayer_length
|
|
4215
|
+
|
|
4204
4216
|
self.mediaTotalLength = current_media_duration
|
|
4205
4217
|
|
|
4206
4218
|
# current state(s)
|
|
@@ -4225,6 +4237,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
4225
4237
|
self.show_current_states_in_subjects_table()
|
|
4226
4238
|
|
|
4227
4239
|
# current media name
|
|
4240
|
+
print(f"{self.dw_player[0].player.playlist_pos=}")
|
|
4241
|
+
print(f"{self.dw_player[0].player.playlist=}")
|
|
4242
|
+
|
|
4228
4243
|
if self.dw_player[0].player.playlist_pos is not None:
|
|
4229
4244
|
current_media_name = Path(self.dw_player[0].player.playlist[self.dw_player[0].player.playlist_pos]["filename"]).name
|
|
4230
4245
|
current_playlist_index = self.dw_player[0].player.playlist_pos
|
|
@@ -4300,6 +4315,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
4300
4315
|
|
|
4301
4316
|
self.actionPlay.setIcon(QIcon(f":/play_{gui_utilities.theme_mode()}"))
|
|
4302
4317
|
|
|
4318
|
+
print(f"{msg=}")
|
|
4319
|
+
|
|
4303
4320
|
if msg:
|
|
4304
4321
|
self.lb_current_media_time.setText(msg)
|
|
4305
4322
|
|
|
@@ -4316,14 +4333,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
4316
4333
|
|
|
4317
4334
|
logging.info("Media end reached")
|
|
4318
4335
|
|
|
4319
|
-
"""
|
|
4320
|
-
print(f"{self.dw_player[0].player.time_pos=}")
|
|
4321
|
-
print(f"{self.dw_player[0].player.pause=}")
|
|
4322
|
-
print(f"{self.dw_player[0].player.core_idle=}")
|
|
4323
|
-
print(f"{self.dw_player[0].player.eof_reached=}")
|
|
4324
|
-
print(f"{self.dw_player[0].player.playlist_pos=}")
|
|
4325
|
-
"""
|
|
4326
|
-
|
|
4327
4336
|
if self.pj[cfg.OBSERVATIONS][self.observationId][cfg.CLOSE_BEHAVIORS_BETWEEN_VIDEOS]:
|
|
4328
4337
|
if self.dw_player[0].player.eof_reached and self.dw_player[0].player.core_idle:
|
|
4329
4338
|
if self.dw_player[0].player.playlist_pos == len(self.dw_player[0].player.playlist) - 1:
|
|
@@ -4593,14 +4602,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
4593
4602
|
|
|
4594
4603
|
if self.playerType == cfg.MEDIA:
|
|
4595
4604
|
# cumulative time
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
|
|
4599
|
-
)
|
|
4600
|
-
else:
|
|
4601
|
-
time_pos = observation_operations.send_command({"command": ["get_property", "time-pos"]})
|
|
4602
|
-
# TODO: fix!
|
|
4603
|
-
return dec(time_pos)
|
|
4605
|
+
mem_laps = sum(self.dw_player[n_player].media_durations[0 : self.dw_player[n_player].player.playlist_pos]) + (
|
|
4606
|
+
0 if self.dw_player[n_player].player.time_pos is None else self.dw_player[n_player].player.time_pos * 1000
|
|
4607
|
+
)
|
|
4604
4608
|
|
|
4605
4609
|
return dec(str(round(mem_laps / 1000, 3)))
|
|
4606
4610
|
|
|
@@ -5388,6 +5392,18 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
5388
5392
|
"""
|
|
5389
5393
|
logging.debug("function: closeEvent")
|
|
5390
5394
|
|
|
5395
|
+
# close MPV in IPC mode
|
|
5396
|
+
if self.MPV_IPC_MODE:
|
|
5397
|
+
try:
|
|
5398
|
+
for idx, p in enumerate(self.dw_player):
|
|
5399
|
+
p.player.process.terminate()
|
|
5400
|
+
try:
|
|
5401
|
+
p.player.process.wait(timeout=3) # wait up to 3s
|
|
5402
|
+
except subprocess.TimeoutExpired:
|
|
5403
|
+
p.player.process.kill() # force if still alive
|
|
5404
|
+
except Exception as e:
|
|
5405
|
+
logging.warning(f"Error stopping MPV process #{idx}: {e}")
|
|
5406
|
+
|
|
5391
5407
|
# check if re-encoding
|
|
5392
5408
|
if self.processes:
|
|
5393
5409
|
if (
|
|
@@ -5441,6 +5457,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
5441
5457
|
check if first player ended
|
|
5442
5458
|
"""
|
|
5443
5459
|
|
|
5460
|
+
print("play_video")
|
|
5461
|
+
|
|
5444
5462
|
if self.geometric_measurements_mode:
|
|
5445
5463
|
return
|
|
5446
5464
|
|
|
@@ -5462,6 +5480,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
5462
5480
|
|
|
5463
5481
|
self.statusbar.showMessage("", 0)
|
|
5464
5482
|
|
|
5483
|
+
if self.ipc_mpv_timer is not None:
|
|
5484
|
+
self.ipc_mpv_timer.start()
|
|
5485
|
+
|
|
5465
5486
|
self.plot_timer.start()
|
|
5466
5487
|
|
|
5467
5488
|
# start all timer for plotting data
|
|
@@ -5493,6 +5514,10 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
5493
5514
|
for data_timer in self.ext_data_timer_list:
|
|
5494
5515
|
data_timer.stop()
|
|
5495
5516
|
|
|
5517
|
+
if self.ipc_mpv_timer is not None:
|
|
5518
|
+
self.ipc_mpv_timer.stop()
|
|
5519
|
+
self.mpv_timer_out()
|
|
5520
|
+
|
|
5496
5521
|
player.player.pause = True
|
|
5497
5522
|
|
|
5498
5523
|
self.lb_player_status.setText(msg)
|
|
@@ -5542,13 +5567,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
5542
5567
|
|
|
5543
5568
|
self.update_visualizations()
|
|
5544
5569
|
|
|
5545
|
-
# subtitles
|
|
5546
|
-
"""
|
|
5547
|
-
st_track_number = 0 if self.config_param[DISPLAY_SUBTITLES] else -1
|
|
5548
|
-
for player in self.dw_player:
|
|
5549
|
-
player.mediaplayer.video_set_spu(st_track_number)
|
|
5550
|
-
"""
|
|
5551
|
-
|
|
5552
5570
|
def jumpForward_activated(self):
|
|
5553
5571
|
"""
|
|
5554
5572
|
forward from current position
|
|
@@ -5666,12 +5684,18 @@ def main():
|
|
|
5666
5684
|
ret, msg = util.check_ffmpeg_path()
|
|
5667
5685
|
if not ret:
|
|
5668
5686
|
if sys.platform.startswith("win"):
|
|
5669
|
-
|
|
5670
5687
|
import ctypes
|
|
5688
|
+
|
|
5671
5689
|
MessageBoxTimeoutW = ctypes.windll.user32.MessageBoxTimeoutW
|
|
5672
|
-
MessageBoxTimeoutW.argtypes = [ctypes.c_void_p, ctypes.c_wchar_p, ctypes.c_wchar_p,
|
|
5673
|
-
|
|
5674
|
-
|
|
5690
|
+
MessageBoxTimeoutW.argtypes = [ctypes.c_void_p, ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_uint, ctypes.c_uint, ctypes.c_uint]
|
|
5691
|
+
ctypes.windll.user32.MessageBoxTimeoutW(
|
|
5692
|
+
None,
|
|
5693
|
+
"The FFmpeg framework is not available.\nIt will be downloaded from the BORIS GitHub repository.",
|
|
5694
|
+
"FFmpeg",
|
|
5695
|
+
0,
|
|
5696
|
+
0,
|
|
5697
|
+
10000,
|
|
5698
|
+
) # time out
|
|
5675
5699
|
|
|
5676
5700
|
# if (not options.nosplashscreen):
|
|
5677
5701
|
# QMessageBox.warning(
|
|
@@ -5684,7 +5708,7 @@ def main():
|
|
|
5684
5708
|
logging.info("FFmpeg is not available. It will be downloaded from the BORIS GitHub repository")
|
|
5685
5709
|
|
|
5686
5710
|
# download ffmpeg and ffprobe from https://github.com/boris-behav-obs/boris-behav-obs.github.io/releases/download/files/
|
|
5687
|
-
url:str = "https://github.com/boris-behav-obs/boris-behav-obs.github.io/releases/download/files/"
|
|
5711
|
+
url: str = "https://github.com/boris-behav-obs/boris-behav-obs.github.io/releases/download/files/"
|
|
5688
5712
|
|
|
5689
5713
|
# search where to download ffmpeg
|
|
5690
5714
|
ffmpeg_dir = Path(__file__).parent / "misc"
|
|
@@ -5799,6 +5823,22 @@ def main():
|
|
|
5799
5823
|
results.ptText.appendHtml(f"Some issues were found in the project<br><br>{msg}")
|
|
5800
5824
|
results.show()
|
|
5801
5825
|
|
|
5826
|
+
# check mpv IPC mode
|
|
5827
|
+
window.MPV_IPC_MODE = False
|
|
5828
|
+
if options.ipc or sys.platform.startswith("darwin"):
|
|
5829
|
+
window.MPV_IPC_MODE = True
|
|
5830
|
+
# check if mpv is available
|
|
5831
|
+
if not shutil.which("mpv"):
|
|
5832
|
+
logging.critical("The mpv command is not available on the path")
|
|
5833
|
+
QMessageBox.critical(
|
|
5834
|
+
None,
|
|
5835
|
+
cfg.programName,
|
|
5836
|
+
("The mpv command is not available on the path"),
|
|
5837
|
+
QMessageBox.Ok | QMessageBox.Default,
|
|
5838
|
+
QMessageBox.NoButton,
|
|
5839
|
+
)
|
|
5840
|
+
sys.exit()
|
|
5841
|
+
|
|
5802
5842
|
window.show()
|
|
5803
5843
|
window.raise_() # for overlapping widget (?)
|
|
5804
5844
|
|