From 9c479eac8f46ef79d2907d91ce0b001f440a0ca1 Mon Sep 17 00:00:00 2001 From: raspicamplayer Date: Tue, 16 Mar 2021 22:37:54 +0100 Subject: [PATCH 01/13] Add force UDP option for RTSP --- camplayer/windowmanager.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/camplayer/windowmanager.py b/camplayer/windowmanager.py index a5ccbd7..a49dc37 100644 --- a/camplayer/windowmanager.py +++ b/camplayer/windowmanager.py @@ -806,7 +806,11 @@ def _stream_start(self, stream=None): '--win', omx_pos_arg # Window position ] +<<<<<<< HEAD if not self.force_udp and not stream.force_udp: +======= + if not self.force_udp: +>>>>>>> Add force UDP option for RTSP player_cmd.extend(['--avdict', 'rtsp_transport:tcp']) # Force RTSP over TCP if stream.url.startswith('file://'): @@ -857,7 +861,11 @@ def _stream_start(self, stream=None): '--no-video-title-show' # Disable filename popup on start ] +<<<<<<< HEAD if not self.force_udp and not stream.force_udp: +======= + if not self.force_udp: +>>>>>>> Add force UDP option for RTSP player_cmd.append('--rtsp-tcp') # Force RTSP over TCP # Keep in mind that VLC instances can be reused for From 8a8333d9e0c28b89fabc37b10321e046e93fd231 Mon Sep 17 00:00:00 2001 From: raspicamplayer Date: Sun, 28 Mar 2021 16:01:05 +0200 Subject: [PATCH 02/13] Autodetect udp/tcp with ffprobe --- camplayer/windowmanager.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/camplayer/windowmanager.py b/camplayer/windowmanager.py index a49dc37..a5ccbd7 100644 --- a/camplayer/windowmanager.py +++ b/camplayer/windowmanager.py @@ -806,11 +806,7 @@ def _stream_start(self, stream=None): '--win', omx_pos_arg # Window position ] -<<<<<<< HEAD if not self.force_udp and not stream.force_udp: -======= - if not self.force_udp: ->>>>>>> Add force UDP option for RTSP player_cmd.extend(['--avdict', 'rtsp_transport:tcp']) # Force RTSP over TCP if stream.url.startswith('file://'): @@ -861,11 +857,7 @@ def _stream_start(self, stream=None): '--no-video-title-show' # Disable filename popup on start ] -<<<<<<< HEAD if not self.force_udp and not stream.force_udp: -======= - if not self.force_udp: ->>>>>>> Add force UDP option for RTSP player_cmd.append('--rtsp-tcp') # Force RTSP over TCP # Keep in mind that VLC instances can be reused for From 66a5e312a513084d8872de17330396ef3bcfc5e4 Mon Sep 17 00:00:00 2001 From: raspicamplayer Date: Sun, 28 Mar 2021 17:05:26 +0200 Subject: [PATCH 03/13] Bump version --- camplayer/camplayer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/camplayer/camplayer.py b/camplayer/camplayer.py index 5e85b4a..8a37031 100644 --- a/camplayer/camplayer.py +++ b/camplayer/camplayer.py @@ -310,4 +310,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() From 11ddace70d4c730bccbfc81e324acbb2d1a6694b Mon Sep 17 00:00:00 2001 From: cybermaus Date: Thu, 15 Jul 2021 12:50:37 +0200 Subject: [PATCH 04/13] Support autodetect on old DVI monitors I have 10 old DVI monitors that result in tvservice yielding "state 0x6 [DVI CUSTOM RGB full unknown AR], 1440x900 @ 60.00Hz, progressive" which is not properly processed by utils.py. Since tvservice does this for every resolution the monitors support, rather then keep changing the config, I traced the source. Sidenote: tvservice does normally read and list the monitors mode. Only when asking the active status does it list custom. So the root problem is probably somewhere in tvservice: pi@raspberrypi:~ $ tvservice --device 2 -s state 0x6 [DVI CUSTOM RGB full unknown AR], 1440x900 @ 60.00Hz, progressive pi@raspberrypi:~ $ tvservice --device 2 -m DMT Group DMT has 16 modes: mode 4: 640x480 @ 60Hz 4:3, clock:25MHz progressive mode 5: 640x480 @ 72Hz 4:3, clock:31MHz progressive mode 6: 640x480 @ 75Hz 4:3, clock:31MHz progressive mode 8: 800x600 @ 56Hz 4:3, clock:36MHz progressive mode 9: 800x600 @ 60Hz 4:3, clock:40MHz progressive mode 10: 800x600 @ 72Hz 4:3, clock:50MHz progressive mode 11: 800x600 @ 75Hz 4:3, clock:49MHz progressive mode 16: 1024x768 @ 60Hz 4:3, clock:65MHz progressive mode 17: 1024x768 @ 70Hz 4:3, clock:75MHz progressive mode 18: 1024x768 @ 75Hz 4:3, clock:78MHz progressive mode 21: 1152x864 @ 75Hz 4:3, clock:108MHz progressive mode 32: 1280x960 @ 60Hz 4:3, clock:108MHz progressive mode 35: 1280x1024 @ 60Hz 5:4, clock:108MHz progressive mode 36: 1280x1024 @ 75Hz 5:4, clock:135MHz progressive (prefer) mode 47: 1440x900 @ 60Hz 16:10, clock:106MHz progressive mode 48: 1440x900 @ 75Hz 16:10, clock:136MHz progressive --- camplayer/utils/utils.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/camplayer/utils/utils.py b/camplayer/utils/utils.py index 7c651ea..087762f 100644 --- a/camplayer/utils/utils.py +++ b/camplayer/utils/utils.py @@ -157,6 +157,13 @@ def get_display_mode(display=2): res_width = int(tmp.group(3)) res_height = int(tmp.group(4)) framerate = int(tmp.group(5)) + else: + tmp = re.search('^state.+(CUSTOM).*[\s*\S*]* (\d+)x(\d+).+@ (\d+)', response) + if tmp: + hdmi_group = tmp.group(1) + res_width = int(tmp.group(2)) + res_height = int(tmp.group(3)) + framerate = int(tmp.group(4)) response = subprocess.check_output( ['tvservice', '--device', str(display), '--name'], From 0323aed99d498eb878ae83aef59222075db0c345 Mon Sep 17 00:00:00 2001 From: Maurits van Dueren den Hollander Date: Sat, 17 Jul 2021 21:09:08 +0200 Subject: [PATCH 05/13] Simple mouse gesture contoller normal left click --> does nothing normal mouse movement --> does nothing while left mouse button down: left, right, up, down --> inserts left, right, up, down keystroke right click --> inserts Q keystroke (quit program) normal right click --> inserts SPACE keystroke (pause/unpause) normal scroll up/down --> inserts 1 or 0 keystroke (zoom/unzoom) Example: to enlarge camera 3, zoom with scroll will, then holding the mouse button down move right 2 times --- camplayer/utils/inputhandler.py | 76 ++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/camplayer/utils/inputhandler.py b/camplayer/utils/inputhandler.py index 79de6da..0a98697 100644 --- a/camplayer/utils/inputhandler.py +++ b/camplayer/utils/inputhandler.py @@ -18,6 +18,11 @@ def __init__(self, event_type=['release', 'press', 'hold'], scan_interval=2500): self._event_hold = True if 'hold' in event_type else False self._running = True self._monitor_thread = threading.Thread(target=self._monitor, daemon=True).start() + self._mouse_inhibit = time.monotonic() + self._mouse_inhibit_duration = 0.5 + self._mouse_btn_state = 0 + self._mouse_abs_x = 500 + self._mouse_abs_y = 500 def destroy(self): """Stop monitoring thread""" @@ -62,13 +67,82 @@ def _monitor(self): while True: event = device.read_one() if event: + # keyboard and button events if event.type == evdev.ecodes.EV_KEY: - if self._event_up and event.value == 0: + + # mouse buttons + if ( event.code in {evdev.ecodes.BTN_MOUSE, + evdev.ecodes.BTN_RIGHT, + evdev.ecodes.BTN_MIDDLE} ): + # Left click: track (left) mouse button state + # note that left mouse click by itself does not do anything + if event.code == evdev.ecodes.BTN_MOUSE: + self._mouse_btn_state = event.value + # Right click, while left is already down, Quit program + elif ( event.code == evdev.ecodes.BTN_RIGHT + and self._mouse_btn_state == 1 + and event.value == 0 ): + event.code = evdev.ecodes.KEY_Q + self._event_queue.put_nowait(event) + # Right click, while left is not already down, Pause autorotate + elif ( event.code == evdev.ecodes.BTN_RIGHT + and event.value == 0 ): + event.code = evdev.ecodes.KEY_SPACE + self._event_queue.put_nowait(event) + + # other keys / keyboard keys + elif self._event_up and event.value == 0: self._event_queue.put_nowait(event) elif self._event_down and event.value == 1: self._event_queue.put_nowait(event) elif self._event_hold and event.value == 2: self._event_queue.put_nowait(event) + + # mouse movement events + elif event.type == evdev.ecodes.EV_REL: + + # unused for now, track absolute position + if event.code == evdev.ecodes.REL_X: + self._mouse_abs_x += event.value; + self._mouse_abs_x = min(1920, self._mouse_abs_x) + self._mouse_abs_x = max(1, self._mouse_abs_x) + elif event.code == evdev.ecodes.REL_Y: + self._mouse_abs_y += event.value; + self._mouse_abs_y = min(1080, self._mouse_abs_y) + self._mouse_abs_y = max(1, self._mouse_abs_y) + + # Gestures, only one per timeslot. + if (time.monotonic() > self._mouse_inhibit + self._mouse_inhibit_duration): + # wheel up/down is zoom in/out, iow, single/grid view + if ( event.code == evdev.ecodes.REL_WHEEL + and abs(event.value) > 0 ): + if event.value > 0: + event.code = evdev.ecodes.KEY_0 + else: + event.code = evdev.ecodes.KEY_1 + self._mouse_inhibit = time.monotonic() + self._event_queue.put_nowait(event) + # move left/right while button down is prev/next screen + elif ( event.code == evdev.ecodes.REL_X + and self._mouse_btn_state == 1 + and abs(event.value) > 10 ): + if event.value > 0: + event.code = evdev.ecodes.KEY_RIGHT + else: + event.code = evdev.ecodes.KEY_LEFT + self._mouse_inhibit = time.monotonic() + self._event_queue.put_nowait(event) + # move up/down while button down is higher/lower quality + elif ( event.code == evdev.ecodes.REL_Y + and self._mouse_btn_state == 1 + and abs(event.value) > 10 ): + if event.value > 0: + event.code = evdev.ecodes.KEY_DOWN + else: + event.code = evdev.ecodes.KEY_UP + self._mouse_inhibit = time.monotonic() + self._event_queue.put_nowait(event) + del event else: break From ffa9901293856695386ff7ef4f735f916efe3d9c Mon Sep 17 00:00:00 2001 From: cybermaus Date: Sat, 17 Jul 2021 23:06:17 +0200 Subject: [PATCH 06/13] Update README.MD with mouse gestures --- README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 11c11e8..cd5eec6 100644 --- a/README.md +++ b/README.md @@ -298,7 +298,19 @@ numeric key 0 Switch from single view to grid view mode and unpause rotati escape Switch from single view to grid view mode and unpause rotation. letter 'q' Quit camplayer. ``` - +## Mouse gestures +Please note there is no absolute positioning, nor any visible mouse. So you cannot jump directly to +the single view for a specific camera. you need to scroll to camera 1, and then gesture left/right a +few times +``` +while holding left button down +- move left/right Switch to previous/next screen (or window in single view mode). +- move up/down Increase/decrease stream quality (if multiple subchannels/substreams configured). +- click right Quit camplayer. +normal actions +- click right Pause/unpause automatic screen rotation. +- scroll up/down Switch between grid to single view mode. +``` ## Roadmap ### Camplayer 2 * Improve VLC and drop OMXplayer support, drop code hacks introduced to support them both. From 1dc83b59eeb07b74bd75e40cbfc1b6da77cd7853 Mon Sep 17 00:00:00 2001 From: cybermaus Date: Sat, 17 Jul 2021 23:18:34 +0200 Subject: [PATCH 07/13] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index cd5eec6..08f816e 100644 --- a/README.md +++ b/README.md @@ -311,6 +311,7 @@ normal actions - click right Pause/unpause automatic screen rotation. - scroll up/down Switch between grid to single view mode. ``` +- ## Roadmap ### Camplayer 2 * Improve VLC and drop OMXplayer support, drop code hacks introduced to support them both. From 5fa85198d9fa1a6a5b5198cfa27437f9bcb0ac0f Mon Sep 17 00:00:00 2001 From: Maurits van Dueren den Hollander Date: Sat, 24 Jul 2021 10:45:29 +0200 Subject: [PATCH 08/13] Revert "Update README.md" This reverts commit 1dc83b59eeb07b74bd75e40cbfc1b6da77cd7853. --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 08f816e..cd5eec6 100644 --- a/README.md +++ b/README.md @@ -311,7 +311,6 @@ normal actions - click right Pause/unpause automatic screen rotation. - scroll up/down Switch between grid to single view mode. ``` -- ## Roadmap ### Camplayer 2 * Improve VLC and drop OMXplayer support, drop code hacks introduced to support them both. From f7e2a652758ed922f6276136b87d1ebe6b2ca657 Mon Sep 17 00:00:00 2001 From: Maurits van Dueren den Hollander Date: Sat, 24 Jul 2021 10:47:47 +0200 Subject: [PATCH 09/13] Revert "Update README.MD with mouse gestures" This reverts commit ffa9901293856695386ff7ef4f735f916efe3d9c. --- README.md | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/README.md b/README.md index cd5eec6..11c11e8 100644 --- a/README.md +++ b/README.md @@ -298,19 +298,7 @@ numeric key 0 Switch from single view to grid view mode and unpause rotati escape Switch from single view to grid view mode and unpause rotation. letter 'q' Quit camplayer. ``` -## Mouse gestures -Please note there is no absolute positioning, nor any visible mouse. So you cannot jump directly to -the single view for a specific camera. you need to scroll to camera 1, and then gesture left/right a -few times -``` -while holding left button down -- move left/right Switch to previous/next screen (or window in single view mode). -- move up/down Increase/decrease stream quality (if multiple subchannels/substreams configured). -- click right Quit camplayer. -normal actions -- click right Pause/unpause automatic screen rotation. -- scroll up/down Switch between grid to single view mode. -``` + ## Roadmap ### Camplayer 2 * Improve VLC and drop OMXplayer support, drop code hacks introduced to support them both. From 246b1a1770cab931b390f4ed31f0b784ddb5de56 Mon Sep 17 00:00:00 2001 From: Maurits van Dueren den Hollander Date: Sat, 24 Jul 2021 10:48:28 +0200 Subject: [PATCH 10/13] Revert "Simple mouse gesture contoller" This reverts commit 0323aed99d498eb878ae83aef59222075db0c345. --- camplayer/utils/inputhandler.py | 76 +-------------------------------- 1 file changed, 1 insertion(+), 75 deletions(-) diff --git a/camplayer/utils/inputhandler.py b/camplayer/utils/inputhandler.py index 0a98697..79de6da 100644 --- a/camplayer/utils/inputhandler.py +++ b/camplayer/utils/inputhandler.py @@ -18,11 +18,6 @@ def __init__(self, event_type=['release', 'press', 'hold'], scan_interval=2500): self._event_hold = True if 'hold' in event_type else False self._running = True self._monitor_thread = threading.Thread(target=self._monitor, daemon=True).start() - self._mouse_inhibit = time.monotonic() - self._mouse_inhibit_duration = 0.5 - self._mouse_btn_state = 0 - self._mouse_abs_x = 500 - self._mouse_abs_y = 500 def destroy(self): """Stop monitoring thread""" @@ -67,82 +62,13 @@ def _monitor(self): while True: event = device.read_one() if event: - # keyboard and button events if event.type == evdev.ecodes.EV_KEY: - - # mouse buttons - if ( event.code in {evdev.ecodes.BTN_MOUSE, - evdev.ecodes.BTN_RIGHT, - evdev.ecodes.BTN_MIDDLE} ): - # Left click: track (left) mouse button state - # note that left mouse click by itself does not do anything - if event.code == evdev.ecodes.BTN_MOUSE: - self._mouse_btn_state = event.value - # Right click, while left is already down, Quit program - elif ( event.code == evdev.ecodes.BTN_RIGHT - and self._mouse_btn_state == 1 - and event.value == 0 ): - event.code = evdev.ecodes.KEY_Q - self._event_queue.put_nowait(event) - # Right click, while left is not already down, Pause autorotate - elif ( event.code == evdev.ecodes.BTN_RIGHT - and event.value == 0 ): - event.code = evdev.ecodes.KEY_SPACE - self._event_queue.put_nowait(event) - - # other keys / keyboard keys - elif self._event_up and event.value == 0: + if self._event_up and event.value == 0: self._event_queue.put_nowait(event) elif self._event_down and event.value == 1: self._event_queue.put_nowait(event) elif self._event_hold and event.value == 2: self._event_queue.put_nowait(event) - - # mouse movement events - elif event.type == evdev.ecodes.EV_REL: - - # unused for now, track absolute position - if event.code == evdev.ecodes.REL_X: - self._mouse_abs_x += event.value; - self._mouse_abs_x = min(1920, self._mouse_abs_x) - self._mouse_abs_x = max(1, self._mouse_abs_x) - elif event.code == evdev.ecodes.REL_Y: - self._mouse_abs_y += event.value; - self._mouse_abs_y = min(1080, self._mouse_abs_y) - self._mouse_abs_y = max(1, self._mouse_abs_y) - - # Gestures, only one per timeslot. - if (time.monotonic() > self._mouse_inhibit + self._mouse_inhibit_duration): - # wheel up/down is zoom in/out, iow, single/grid view - if ( event.code == evdev.ecodes.REL_WHEEL - and abs(event.value) > 0 ): - if event.value > 0: - event.code = evdev.ecodes.KEY_0 - else: - event.code = evdev.ecodes.KEY_1 - self._mouse_inhibit = time.monotonic() - self._event_queue.put_nowait(event) - # move left/right while button down is prev/next screen - elif ( event.code == evdev.ecodes.REL_X - and self._mouse_btn_state == 1 - and abs(event.value) > 10 ): - if event.value > 0: - event.code = evdev.ecodes.KEY_RIGHT - else: - event.code = evdev.ecodes.KEY_LEFT - self._mouse_inhibit = time.monotonic() - self._event_queue.put_nowait(event) - # move up/down while button down is higher/lower quality - elif ( event.code == evdev.ecodes.REL_Y - and self._mouse_btn_state == 1 - and abs(event.value) > 10 ): - if event.value > 0: - event.code = evdev.ecodes.KEY_DOWN - else: - event.code = evdev.ecodes.KEY_UP - self._mouse_inhibit = time.monotonic() - self._event_queue.put_nowait(event) - del event else: break From 819d4a25941cdd39535d7649d1639331235be95d Mon Sep 17 00:00:00 2001 From: Maurits van Dueren den Hollander Date: Sat, 24 Jul 2021 10:48:46 +0200 Subject: [PATCH 11/13] Revert "Support autodetect on old DVI monitors" This reverts commit 11ddace70d4c730bccbfc81e324acbb2d1a6694b. --- camplayer/utils/utils.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/camplayer/utils/utils.py b/camplayer/utils/utils.py index 087762f..7c651ea 100644 --- a/camplayer/utils/utils.py +++ b/camplayer/utils/utils.py @@ -157,13 +157,6 @@ def get_display_mode(display=2): res_width = int(tmp.group(3)) res_height = int(tmp.group(4)) framerate = int(tmp.group(5)) - else: - tmp = re.search('^state.+(CUSTOM).*[\s*\S*]* (\d+)x(\d+).+@ (\d+)', response) - if tmp: - hdmi_group = tmp.group(1) - res_width = int(tmp.group(2)) - res_height = int(tmp.group(3)) - framerate = int(tmp.group(4)) response = subprocess.check_output( ['tvservice', '--device', str(display), '--name'], From 6288489efb9388cf829965d6d39490985e9cf914 Mon Sep 17 00:00:00 2001 From: cybermaus Date: Sat, 24 Jul 2021 11:40:21 +0200 Subject: [PATCH 12/13] Fix newline to match upstream From 5819b91048acadde70395a5b817912b086174a49 Mon Sep 17 00:00:00 2001 From: Maurits van Dueren den Hollander Date: Sat, 24 Jul 2021 12:34:56 +0200 Subject: [PATCH 13/13] Mouse Gestures --- README.md | 13 +++++ camplayer/utils/inputhandler.py | 97 ++++++++++++++++++++++++++++++++- 2 files changed, 109 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 11c11e8..253de44 100644 --- a/README.md +++ b/README.md @@ -298,6 +298,19 @@ numeric key 0 Switch from single view to grid view mode and unpause rotati escape Switch from single view to grid view mode and unpause rotation. letter 'q' Quit camplayer. ``` +## Mouse gestures +Please note there is no visible mouse. Nor any absolute positioning. So you cannot click directly on +a specific camera. To view a specific camera in single view, scroll down for the first camera, then +continue to scroll or gesture left/right for the other cameras. +``` +direct control +- click right Pause/unpause automatic screen rotation. +- scroll down/up Switch from grid to single view mode and back. +while holding left button down +- left/right move Switch to previous/next screen (or window in single view mode). +- up/down move Increase/decrease stream quality (if multiple subchannels/substreams configured). +quit sequence Left down; Right down; Left release; Right release +``` ## Roadmap ### Camplayer 2 diff --git a/camplayer/utils/inputhandler.py b/camplayer/utils/inputhandler.py index 79de6da..a745148 100644 --- a/camplayer/utils/inputhandler.py +++ b/camplayer/utils/inputhandler.py @@ -18,6 +18,12 @@ def __init__(self, event_type=['release', 'press', 'hold'], scan_interval=2500): self._event_hold = True if 'hold' in event_type else False self._running = True self._monitor_thread = threading.Thread(target=self._monitor, daemon=True).start() + self._mouse_inhibit = time.monotonic() + self._mouse_inhibit_duration = 0.5 + self._mouse_btn_state = 0 + self._mouse_abs_x = 500 + self._mouse_abs_y = 500 + self._mouse_quit_sequence = 0 def destroy(self): """Stop monitoring thread""" @@ -62,13 +68,102 @@ def _monitor(self): while True: event = device.read_one() if event: + # keyboard and button events if event.type == evdev.ecodes.EV_KEY: - if self._event_up and event.value == 0: + + # mouse buttons + if ( event.code in {evdev.ecodes.BTN_MOUSE, + evdev.ecodes.BTN_RIGHT, + evdev.ecodes.BTN_MIDDLE} ): + # Left button + if event.code == evdev.ecodes.BTN_MOUSE: + # Left click: track mouse button state + self._mouse_btn_state = event.value + # Left down: set Quit sequence tracker + if event.value == 1: + self._mouse_quit_sequence = 1 + # Left release: advance Quit sequence tracker + elif event.value == 0 and self._mouse_quit_sequence == 2: + self._mouse_quit_sequence = 3 + # Right button + elif event.code == evdev.ecodes.BTN_RIGHT: + # Right down: advance Quit sequence tracker + if event.value == 1 and self._mouse_quit_sequence == 1: + self._mouse_quit_sequence = 2 + # Right release, as completion of Quit sequence: Quit program + elif event.value == 0 and self._mouse_quit_sequence == 3: + event.type = evdev.ecodes.EV_KEY + event.code = evdev.ecodes.KEY_Q + self._event_queue.put_nowait(event) + # Right release, while left is still down: Blank screen + elif event.value == 0 and self._mouse_btn_state == 1: + self._mouse_quit_sequence = 0 + event.type = evdev.ecodes.EV_KEY + event.code = evdev.ecodes.KEY_B + self._event_queue.put_nowait(event) + # Right release, while left is not down: Pause autorotate + elif event.value == 0 and self._mouse_btn_state == 1: + self._mouse_quit_sequence = 0 + event.type = evdev.ecodes.EV_KEY + event.code = evdev.ecodes.KEY_SPACE + self._event_queue.put_nowait(event) + + # other keys / keyboard keys + elif self._event_up and event.value == 0: self._event_queue.put_nowait(event) elif self._event_down and event.value == 1: self._event_queue.put_nowait(event) elif self._event_hold and event.value == 2: self._event_queue.put_nowait(event) + + # mouse movement events + elif event.type == evdev.ecodes.EV_REL: + + # unused for now, track absolute position + if event.code == evdev.ecodes.REL_X: + self._mouse_abs_x += event.value; + self._mouse_abs_x = min(1920, self._mouse_abs_x) + self._mouse_abs_x = max(1, self._mouse_abs_x) + elif event.code == evdev.ecodes.REL_Y: + self._mouse_abs_y += event.value; + self._mouse_abs_y = min(1080, self._mouse_abs_y) + self._mouse_abs_y = max(1, self._mouse_abs_y) + + # Gestures, only one per timeslot. + if (time.monotonic() > self._mouse_inhibit + self._mouse_inhibit_duration): + # wheel up/down is zoom in/out, iow, single/grid view + if ( event.code == evdev.ecodes.REL_WHEEL + and abs(event.value) > 0 ): + if event.value > 0: + event.code = evdev.ecodes.KEY_ESC + else: + event.code = evdev.ecodes.KEY_ENTER + event.type = evdev.ecodes.EV_KEY + self._mouse_inhibit = time.monotonic() + self._event_queue.put_nowait(event) + # move left/right while button down is prev/next screen + elif ( event.code == evdev.ecodes.REL_X + and self._mouse_btn_state == 1 + and abs(event.value) > 10 ): + if event.value > 0: + event.code = evdev.ecodes.KEY_RIGHT + else: + event.code = evdev.ecodes.KEY_LEFT + event.type = evdev.ecodes.EV_KEY + self._mouse_inhibit = time.monotonic() + self._event_queue.put_nowait(event) + # move up/down while button down is higher/lower quality + elif ( event.code == evdev.ecodes.REL_Y + and self._mouse_btn_state == 1 + and abs(event.value) > 10 ): + if event.value > 0: + event.code = evdev.ecodes.KEY_DOWN + else: + event.code = evdev.ecodes.KEY_UP + event.type = evdev.ecodes.EV_KEY + self._mouse_inhibit = time.monotonic() + self._event_queue.put_nowait(event) + del event else: break