feat: camera support, using mpv as backend
it should be able to play any video or stream that mpv itself can handle close #67 close #129
This commit is contained in:
parent
1375c823c9
commit
d2d2c82041
@ -90,6 +90,9 @@ screw_rotation: 0
|
|||||||
# Define distances and speeds for the extrude panel. CSV list 2 to 4 integers
|
# Define distances and speeds for the extrude panel. CSV list 2 to 4 integers
|
||||||
extrude_distances: 5, 10, 15, 25
|
extrude_distances: 5, 10, 15, 25
|
||||||
extrude_speeds: 1, 2, 5, 25
|
extrude_speeds: 1, 2, 5, 25
|
||||||
|
|
||||||
|
# Camera configuration
|
||||||
|
camera_url: http://127.0.0.1/webcam/?action=stream
|
||||||
```
|
```
|
||||||
|
|
||||||
## Preheat Options
|
## Preheat Options
|
||||||
|
@ -165,7 +165,7 @@ class KlipperScreenConfig:
|
|||||||
strs = (
|
strs = (
|
||||||
'moonraker_api_key', 'moonraker_host', 'titlebar_name_type',
|
'moonraker_api_key', 'moonraker_host', 'titlebar_name_type',
|
||||||
'screw_positions', 'power_devices', 'titlebar_items', 'z_babystep_values',
|
'screw_positions', 'power_devices', 'titlebar_items', 'z_babystep_values',
|
||||||
'extrude_distances', "extrude_speeds",
|
'extrude_distances', "extrude_speeds", "camera_url",
|
||||||
)
|
)
|
||||||
numbers = (
|
numbers = (
|
||||||
'moonraker_port', 'move_speed_xy', 'move_speed_z',
|
'moonraker_port', 'move_speed_xy', 'move_speed_z',
|
||||||
|
@ -128,6 +128,12 @@ icon: motor-off
|
|||||||
method: printer.gcode.script
|
method: printer.gcode.script
|
||||||
params: {"script":"M18"}
|
params: {"script":"M18"}
|
||||||
|
|
||||||
|
[menu __main actions camera]
|
||||||
|
name: {{ gettext('Camera') }}
|
||||||
|
icon: camera
|
||||||
|
panel: camera
|
||||||
|
enable: {{ camera_configured }}
|
||||||
|
|
||||||
[menu __main actions console]
|
[menu __main actions console]
|
||||||
name: {{ gettext('Console') }}
|
name: {{ gettext('Console') }}
|
||||||
icon: console
|
icon: console
|
||||||
@ -231,6 +237,13 @@ icon: custom-script
|
|||||||
panel: gcode_macros
|
panel: gcode_macros
|
||||||
enable: {{ printer.gcode_macros.count > 0 }}
|
enable: {{ printer.gcode_macros.count > 0 }}
|
||||||
|
|
||||||
|
|
||||||
|
[menu __print camera]
|
||||||
|
name: {{ gettext('Camera') }}
|
||||||
|
icon: camera
|
||||||
|
panel: camera
|
||||||
|
enable: {{ camera_configured }}
|
||||||
|
|
||||||
[menu __print console]
|
[menu __print console]
|
||||||
name: {{ gettext('Console') }}
|
name: {{ gettext('Console') }}
|
||||||
icon: console
|
icon: console
|
||||||
|
85
panels/camera.py
Normal file
85
panels/camera.py
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
import mpv
|
||||||
|
import logging
|
||||||
|
import gi
|
||||||
|
|
||||||
|
gi.require_version("Gtk", "3.0")
|
||||||
|
from gi.repository import Gtk, Gdk
|
||||||
|
|
||||||
|
from ks_includes.screen_panel import ScreenPanel
|
||||||
|
|
||||||
|
|
||||||
|
def create_panel(*args):
|
||||||
|
return CameraPanel(*args)
|
||||||
|
|
||||||
|
|
||||||
|
class CameraPanel(ScreenPanel):
|
||||||
|
def __init__(self, screen, title):
|
||||||
|
super().__init__(screen, title)
|
||||||
|
self.mpv = None
|
||||||
|
self.da = Gtk.DrawingArea()
|
||||||
|
self.da.set_hexpand(True)
|
||||||
|
self.da.set_vexpand(True)
|
||||||
|
fs = self._gtk.Button("move", _("Fullscreen"), None, self.bts, Gtk.PositionType.LEFT, 1)
|
||||||
|
fs.connect("clicked", self.play)
|
||||||
|
fs.set_hexpand(True)
|
||||||
|
fs.set_vexpand(False)
|
||||||
|
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
|
||||||
|
box.add(self.da)
|
||||||
|
box.add(fs)
|
||||||
|
self.content.add(box)
|
||||||
|
self.content.show_all()
|
||||||
|
self.url = self.ks_printer_cfg.get("camera_url", "http://127.0.0.1/webcam/?action=stream").replace('"', '')
|
||||||
|
logging.debug(f"Camera URL: {self.url}")
|
||||||
|
# wayland has no primary monitor with that we can detect it
|
||||||
|
self.wayland = Gdk.Display.get_default().get_primary_monitor() is None
|
||||||
|
# gpu output driver doesn't work on a pi3 and the autoselected sdl doesn't size correctly
|
||||||
|
# consider adding a software switch to enable the gpu backend if set by the user
|
||||||
|
self.vo = 'x11' if self.wayland else 'wlshm'
|
||||||
|
|
||||||
|
def activate(self):
|
||||||
|
self.play()
|
||||||
|
|
||||||
|
def deactivate(self):
|
||||||
|
if self.mpv:
|
||||||
|
self.mpv.terminate()
|
||||||
|
self.mpv = None
|
||||||
|
|
||||||
|
def play(self, fs=None):
|
||||||
|
# Create mpv after show or the 'window' property will be None
|
||||||
|
self.mpv = mpv.MPV(
|
||||||
|
log_handler=self.log,
|
||||||
|
vo=self.vo,
|
||||||
|
profile='sw-fast',
|
||||||
|
)
|
||||||
|
# On wayland mpv cannot be embedded at least for now
|
||||||
|
# https://github.com/mpv-player/mpv/issues/9654
|
||||||
|
if fs or self.wayland:
|
||||||
|
self.mpv.fullscreen = True
|
||||||
|
|
||||||
|
@self.mpv.on_key_press('MBTN_LEFT' or 'MBTN_LEFT_DBL')
|
||||||
|
def clicked():
|
||||||
|
self.mpv.quit(0)
|
||||||
|
else:
|
||||||
|
self.mpv.wid = f'{self.da.get_property("window").get_xid()}'
|
||||||
|
|
||||||
|
@self.mpv.on_key_press('MBTN_LEFT' or 'MBTN_LEFT_DBL')
|
||||||
|
def clicked():
|
||||||
|
self._screen.show_popup_message(self.url, level=1)
|
||||||
|
self.mpv.play(self.url)
|
||||||
|
if fs or self.wayland:
|
||||||
|
try:
|
||||||
|
self.mpv.wait_for_playback()
|
||||||
|
except mpv.ShutdownError:
|
||||||
|
logging.info('Exiting Fullscreen')
|
||||||
|
except Exception as e:
|
||||||
|
logging.exception(e)
|
||||||
|
self.mpv.terminate()
|
||||||
|
self.mpv = None
|
||||||
|
if self.wayland:
|
||||||
|
self._screen._menu_go_back()
|
||||||
|
else:
|
||||||
|
self.play()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def log(loglevel, component, message):
|
||||||
|
logging.debug(f'[{loglevel}] {component}: {message}')
|
@ -31,10 +31,6 @@ class MenuPanel(ScreenPanel):
|
|||||||
self.content.add(scroll)
|
self.content.add(scroll)
|
||||||
|
|
||||||
def activate(self):
|
def activate(self):
|
||||||
self.j2_data = self._printer.get_printer_status_data()
|
|
||||||
self.j2_data.update({
|
|
||||||
'moonraker_connected': self._screen._ws.connected
|
|
||||||
})
|
|
||||||
if self._screen.vertical_mode:
|
if self._screen.vertical_mode:
|
||||||
self.arrangeMenuItems(self.items, 3)
|
self.arrangeMenuItems(self.items, 3)
|
||||||
else:
|
else:
|
||||||
@ -99,7 +95,8 @@ class MenuPanel(ScreenPanel):
|
|||||||
if enable == "{{ moonraker_connected }}":
|
if enable == "{{ moonraker_connected }}":
|
||||||
logging.info(f"moonraker connected {self._screen._ws.connected}")
|
logging.info(f"moonraker connected {self._screen._ws.connected}")
|
||||||
return self._screen._ws.connected
|
return self._screen._ws.connected
|
||||||
|
elif enable == "{{ camera_configured }}":
|
||||||
|
return self.ks_printer_cfg.get("camera_url", None) is not None
|
||||||
self.j2_data = self._printer.get_printer_status_data()
|
self.j2_data = self._printer.get_printer_status_data()
|
||||||
try:
|
try:
|
||||||
j2_temp = Template(enable, autoescape=True)
|
j2_temp = Template(enable, autoescape=True)
|
||||||
|
@ -9,11 +9,11 @@ FBDEV="xserver-xorg-video-fbdev"
|
|||||||
PYTHON="python3-virtualenv virtualenv python3-distutils"
|
PYTHON="python3-virtualenv virtualenv python3-distutils"
|
||||||
PYGOBJECT="libgirepository1.0-dev gcc libcairo2-dev pkg-config python3-dev gir1.2-gtk-3.0"
|
PYGOBJECT="libgirepository1.0-dev gcc libcairo2-dev pkg-config python3-dev gir1.2-gtk-3.0"
|
||||||
MISC="librsvg2-common libopenjp2-7 libatlas-base-dev wireless-tools libdbus-glib-1-dev autoconf"
|
MISC="librsvg2-common libopenjp2-7 libatlas-base-dev wireless-tools libdbus-glib-1-dev autoconf"
|
||||||
OPTIONAL="xserver-xorg-legacy fonts-nanum fonts-ipafont"
|
OPTIONAL="xserver-xorg-legacy fonts-nanum fonts-ipafont, libmpv-dev"
|
||||||
|
|
||||||
# moonraker will check this list when updating
|
# moonraker will check this list when updating
|
||||||
# if new packages are required for existing installs add them below too.
|
# if new packages are required for existing installs add them below too.
|
||||||
PKGLIST="libdbus-glib-1-dev autoconf fonts-ipafont"
|
PKGLIST="libdbus-glib-1-dev autoconf fonts-ipafont, libmpv-dev"
|
||||||
|
|
||||||
Red='\033[0;31m'
|
Red='\033[0;31m'
|
||||||
Green='\033[0;32m'
|
Green='\033[0;32m'
|
||||||
|
@ -5,3 +5,4 @@ websocket-client==1.4.2
|
|||||||
pycairo==1.22.0
|
pycairo==1.22.0
|
||||||
PyGObject==3.42.2
|
PyGObject==3.42.2
|
||||||
python-networkmanager==2.2
|
python-networkmanager==2.2
|
||||||
|
python-mpv==0.5.2
|
||||||
|
Loading…
x
Reference in New Issue
Block a user