'libvlc+qwidget handle mouse event on Win64
I am working on Qt and using libVlc version 2.1.5 for live video streaming.I want to handle mouse press event on vlc frame.But when I click on vlc,it is not able to throw the mouse event. I have tried with
libvlc_video_set_mouse_input(libvlcMediaPlayer,false);
But it hides the mouse over vlc. Please help me if anyone knows.
Thanks.
Solution 1:[1]
You need to use libvlc_video_set_key_input function as well:
libvlc_video_set_mouse_input(media_player, 0);
libvlc_video_set_key_input(media_player, 0);
Solution 2:[2]
I have used libvlc 2.2.2 under Ubuntu 16 and managed to get mouse events on vlc video area in following way (providing only code relevant to the issue). In my VideoPlayer class I have members:
libvlc_media_player_t* vlcPlayer;
VideoWidget* widget;
, where VideoWidget is my custom widget class. In cpp I set libvlc_video_set_mouse_input(vlcPlayer, false);, create widget instance, pass it to my UI and when "play" video is called i also pass widget to vlc libvlc_media_player_set_xwindow(vlcPlayer, widget->winId());
My custom VideoWidget class is following:
// header
class VideoWidget : public QFrame
{
public:
VideoWidget(QWidget* parent = Q_NULLPTR);
protected:
void mousePressEvent(QMouseEvent* event) override;
};
// cpp
VideoWidget::VideoWidget(QWidget* parent)
: QFrame(parent)
{
}
void VideoWidget::mousePressEvent(QMouseEvent* event)
{
qDebug() << "mouse press";
QFrame::mousePressEvent(event);
}
So the idea is to catch mouse events with QWidget passed to vlc.
Solution 3:[3]
Three Solutions on Windows
Solution One: WS_EX_TRANSPARENT
Note: May not work on Windows 7 or below.
# Created by [email protected] at 2022/2/10 23:31
import vlc
import win32con
import win32gui
from PySide2 import QtWidgets, QtCore
def togglePlaying():
player.get_state() == vlc.State.Ended and player.set_media(player.get_media())
player.get_state() == vlc.State.Playing and player.pause()
player.get_state() != vlc.State.Playing and player.play()
def onVideoOut(event):
hwnd = win32gui.GetWindow(player.get_hwnd(), win32con.GW_CHILD)
exStyle = win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE)
exStyle |= win32con.WS_EX_LAYERED | win32con.WS_EX_TRANSPARENT
win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, exStyle)
app = QtWidgets.QApplication()
window = QtWidgets.QMainWindow()
window.setCentralWidget(QtWidgets.QWidget())
window.centralWidget().mousePressEvent = lambda *args: togglePlaying()
window.setWindowFlags(QtCore.Qt.WindowType.WindowCloseButtonHint)
window.resize(854, 480)
window.show()
filename = r"https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"
player = vlc.MediaPlayer(filename)
player.set_hwnd(window.centralWidget().winId())
player.event_manager().event_attach(vlc.EventType.MediaPlayerVout, onVideoOut)
player.play()
app.exec_()
Solution Two: Low-Level Mouse Hook
# Created by [email protected] at 2022/2/10 23:31
from ctypes import WINFUNCTYPE, c_int, Structure, cast, POINTER, windll
from ctypes.wintypes import LPARAM, WPARAM, DWORD, PULONG, LONG
import vlc
import win32con
import win32gui
from PySide2 import QtWidgets, QtCore
def genStruct(name="Structure", **kwargs):
return type(name, (Structure,), dict(
_fields_=list(kwargs.items()),
__str__=lambda self: "%s(%s)" % (name, ",".join("%s=%s" % (k, getattr(self, k)) for k in kwargs))
))
@WINFUNCTYPE(LPARAM, c_int, WPARAM, LPARAM)
def hookProc(nCode, wParam, lParam):
msg = cast(lParam, POINTER(HookStruct))[0]
hwnd = win32gui.WindowFromPoint((msg.pt.x, msg.pt.y))
if hwnd in vlcHwnds:
win32gui.PostMessage(widget.winId(), wParam, wParam, (msg.pt.y << 16) + msg.pt.x)
return windll.user32.CallNextHookEx(None, nCode, WPARAM(wParam), LPARAM(lParam))
def togglePlaying():
print("toggle")
player.get_state() == vlc.State.Ended and player.set_media(player.get_media())
player.get_state() == vlc.State.Playing and player.pause()
player.get_state() != vlc.State.Playing and player.play()
def onVideoOut(event):
hwnd1 = win32gui.GetWindow(player.get_hwnd(), win32con.GW_CHILD)
hwnd2 = win32gui.GetWindow(hwnd1, win32con.GW_CHILD)
vlcHwnds.append(hwnd1)
vlcHwnds.append(hwnd2)
print("vlcHwnds", vlcHwnds)
app = QtWidgets.QApplication()
widget = QtWidgets.QWidget()
widget.mouseReleaseEvent = lambda *args: togglePlaying()
window = QtWidgets.QMainWindow()
window.setCentralWidget(widget)
window.setWindowFlags(QtCore.Qt.WindowType.WindowCloseButtonHint)
window.resize(854, 480)
window.show()
vlcHwnds = []
HookStruct = genStruct(
"Hook", pt=genStruct("Point", x=LONG, y=LONG), mouseData=DWORD, flags=DWORD, time=DWORD, dwExtraInfo=PULONG)
msgDict = {v: k for k, v in win32con.__dict__.items() if k.startswith("WM_")}
windll.user32.SetWindowsHookExW(win32con.WH_MOUSE_LL, hookProc, None, 0)
filename = r"https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"
player = vlc.MediaPlayer(filename)
player.set_hwnd(widget.winId())
player.event_manager().event_attach(vlc.EventType.MediaPlayerVout, onVideoOut)
player.play()
app.exec_()
Solution Three: In-Process Mouse Hook
# Created by [email protected] at 2022/2/10 23:31
from ctypes import WINFUNCTYPE, c_int, Structure, cast, POINTER, windll
from ctypes.wintypes import LPARAM, WPARAM, DWORD, PULONG, LONG, HINSTANCE
import vlc
import win32api
import win32con
import win32gui
from PySide2 import QtWidgets, QtCore
def genStruct(name="Structure", **kwargs):
return type(name, (Structure,), dict(
_fields_=list(kwargs.items()),
__str__=lambda self: "%s(%s)" % (name, ",".join("%s=%s" % (k, getattr(self, k)) for k in kwargs))
))
@WINFUNCTYPE(LPARAM, c_int, WPARAM, LPARAM)
def hookProc(nCode, wParam, lParam):
msg = cast(lParam, POINTER(HookStruct))[0]
win32gui.PostMessage(widget.winId(), wParam, wParam, (msg.pt.y << 16) + msg.pt.x)
return windll.user32.CallNextHookEx(None, nCode, WPARAM(wParam), LPARAM(lParam))
def togglePlaying():
player.get_state() == vlc.State.Ended and player.set_media(player.get_media())
player.get_state() == vlc.State.Playing and player.pause()
player.get_state() != vlc.State.Playing and player.play()
def onVideoOut(event):
hwnd1 = win32gui.GetWindow(player.get_hwnd(), win32con.GW_CHILD)
processId = win32api.GetModuleHandle()
threadId = windll.user32.GetWindowThreadProcessId(hwnd1, None)
windll.user32.SetWindowsHookExW(win32con.WH_MOUSE, hookProc, HINSTANCE(processId), threadId)
app = QtWidgets.QApplication()
window = QtWidgets.QMainWindow()
widget = QtWidgets.QWidget()
widget.mouseReleaseEvent = lambda *args: togglePlaying()
window.setCentralWidget(widget)
window.setWindowFlags(QtCore.Qt.WindowType.WindowCloseButtonHint)
window.resize(854, 480)
window.show()
HookStruct = genStruct(
"Hook", pt=genStruct("Point", x=LONG, y=LONG), mouseData=DWORD, flags=DWORD, time=DWORD, dwExtraInfo=PULONG)
msgDict = {v: k for k, v in win32con.__dict__.items() if k.startswith("WM_")}
filename = r"https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"
player = vlc.MediaPlayer(filename)
player.set_hwnd(widget.winId())
player.event_manager().event_attach(vlc.EventType.MediaPlayerVout, onVideoOut)
player.play()
app.exec_()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | denn |
| Solution 2 | psalong |
| Solution 3 | BaiJiFeiLong |
