[vlc-devel] [PATCH 3/3] vout: win32: handle tilt sensors for VR orientation
Steve Lhomme
robux4 at videolabs.io
Mon Feb 27 17:35:29 CET 2017
---
modules/video_output/Makefile.am | 5 +
modules/video_output/win32/events.c | 7 +
modules/video_output/win32/events.h | 9 ++
modules/video_output/win32/sensors.cpp | 235 +++++++++++++++++++++++++++++++++
4 files changed, 256 insertions(+)
create mode 100644 modules/video_output/win32/sensors.cpp
diff --git a/modules/video_output/Makefile.am b/modules/video_output/Makefile.am
index ab35948e33..d2144f8ac4 100644
--- a/modules/video_output/Makefile.am
+++ b/modules/video_output/Makefile.am
@@ -208,6 +208,7 @@ endif
libdirect3d9_plugin_la_SOURCES = video_output/win32/direct3d9.c \
video_output/win32/common.c video_output/win32/common.h \
video_output/win32/events.c video_output/win32/events.h \
+ video_output/win32/sensors.cpp \
video_output/win32/builtin_shaders.h \
video_output/win32/win32touch.c video_output/win32/win32touch.h
libdirect3d9_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) \
@@ -227,6 +228,7 @@ libdirect3d11_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) \
if !HAVE_WINSTORE
libdirect3d11_plugin_la_SOURCES += video_output/win32/events.c \
video_output/win32/events.h \
+ video_output/win32/sensors.cpp \
video_output/win32/win32touch.c video_output/win32/win32touch.h
libdirect3d11_plugin_la_LIBADD = -lgdi32 $(LIBCOM) -luuid
else
@@ -239,6 +241,7 @@ EXTRA_LTLIBRARIES += libdirect3d11_plugin.la
libdirectdraw_plugin_la_SOURCES = video_output/win32/directdraw.c \
video_output/win32/common.c video_output/win32/common.h \
video_output/win32/events.c video_output/win32/events.h \
+ video_output/win32/sensors.cpp \
video_output/win32/win32touch.c video_output/win32/win32touch.h
libdirectdraw_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) \
-DMODULE_NAME_IS_directdraw
@@ -253,6 +256,7 @@ libglwin32_plugin_la_SOURCES = $(OPENGL_COMMONSOURCES) \
video_output/win32/glwin32.c \
video_output/win32/common.c video_output/win32/common.h \
video_output/win32/events.c video_output/win32/events.h \
+ video_output/win32/sensors.cpp \
video_output/win32/win32touch.c video_output/win32/win32touch.h
libwgl_plugin_la_SOURCES = video_output/win32/wgl.c $(OPENGL_COMMONSOURCES)
@@ -277,6 +281,7 @@ endif
libwingdi_plugin_la_SOURCES = video_output/win32/wingdi.c \
video_output/win32/common.c video_output/win32/common.h \
video_output/win32/events.c video_output/win32/events.h \
+ video_output/win32/sensors.cpp \
video_output/win32/win32touch.c video_output/win32/win32touch.h
libwingdi_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) \
-DMODULE_NAME_IS_wingdi
diff --git a/modules/video_output/win32/events.c b/modules/video_output/win32/events.c
index 231086ce30..51ef3f34ec 100644
--- a/modules/video_output/win32/events.c
+++ b/modules/video_output/win32/events.c
@@ -76,6 +76,9 @@ struct event_thread_t
/* Gestures */
win32_gesture_sys_t *p_gesture;
+ /* Sensors */
+ void *p_sensors;
+
/* Title */
char *psz_title;
@@ -802,6 +805,8 @@ static int Win32VoutCreateWindow( event_thread_t *p_event )
InitGestures( p_event->hwnd, &p_event->p_gesture );
+ p_event->p_sensors = HookWindowsSensors(vd, p_event->hwnd);
+
if( p_event->hparent )
{
LONG i_style;
@@ -891,6 +896,8 @@ static void Win32VoutCloseWindow( event_thread_t *p_event )
DestroyCursor( p_event->cursor_empty );
+ UnhookWindowsSensors(p_event->p_sensors);
+
CloseGestures( p_event->p_gesture);
}
diff --git a/modules/video_output/win32/events.h b/modules/video_output/win32/events.h
index 883d769c28..af1414fcde 100644
--- a/modules/video_output/win32/events.h
+++ b/modules/video_output/win32/events.h
@@ -62,3 +62,12 @@ void EventThreadUpdateSourceAndPlace( event_thread_t *p_event,
void EventThreadUseOverlay( event_thread_t *, bool b_used );
bool EventThreadGetAndResetHasMoved( event_thread_t * );
+# ifdef __cplusplus
+extern "C" {
+# endif
+void* HookWindowsSensors(vout_display_t*, HWND);
+void UnhookWindowsSensors(void*);
+# ifdef __cplusplus
+}
+# endif
+
diff --git a/modules/video_output/win32/sensors.cpp b/modules/video_output/win32/sensors.cpp
new file mode 100644
index 0000000000..13d171c3fd
--- /dev/null
+++ b/modules/video_output/win32/sensors.cpp
@@ -0,0 +1,235 @@
+/*****************************************************************************
+ * sensors.cpp: Windows sensor handling
+ *****************************************************************************
+ * Copyright © 2017 Steve Lhomme
+ * Copyright © 2017 VideoLabs
+ *
+ * Authors: Steve Lhomme <robux4 at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_vout_wrapper.h>
+#include <vlc_charset.h> /* FromWide */
+#include "events.h"
+
+#include <initguid.h>
+#include <propsys.h> /* stupid mingw headers don't include this */
+#include <sensors.h>
+#include <sensorsapi.h>
+
+#include <new>
+
+#ifndef _MSC_VER
+DEFINE_PROPERTYKEY(SENSOR_DATA_TYPE_MAGNETOMETER_ACCURACY, 0x1637d8a2, 0x4248, 0x4275, 0x86, 0x5d, 0x55, 0x8d, 0xe8, 0x4a, 0xed, 0xfd, 22);
+#endif
+
+class SensorReceiver : public ISensorEvents
+{
+public:
+ SensorReceiver(vout_display_t *vd, const vlc_viewpoint_t & init_viewpoint)
+ :vd(vd)
+ ,current_pos(init_viewpoint)
+ {}
+
+ virtual ~SensorReceiver()
+ {}
+
+ STDMETHODIMP QueryInterface(REFIID iid, void** ppv)
+ {
+ if (ppv == NULL)
+ {
+ return E_POINTER;
+ }
+ if (iid == __uuidof(IUnknown))
+ {
+ *ppv = static_cast<IUnknown*>(this);
+ }
+ else if (iid == __uuidof(ISensorEvents))
+ {
+ *ppv = static_cast<ISensorEvents*>(this);
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+ AddRef();
+ return S_OK;
+ }
+
+ STDMETHODIMP_(ULONG) AddRef()
+ {
+ return InterlockedIncrement(&m_cRef);
+ }
+
+ STDMETHODIMP_(ULONG) Release()
+ {
+ ULONG count = InterlockedDecrement(&m_cRef);
+ if (count == 0)
+ {
+ delete this;
+ return 0;
+ }
+ return count;
+ }
+
+ HRESULT STDMETHODCALLTYPE OnStateChanged(ISensor *pSensor, SensorState state)
+ {
+ (void)pSensor;
+ (void)state;
+ return S_OK;
+ }
+
+ HRESULT STDMETHODCALLTYPE OnDataUpdated(ISensor *pSensor, ISensorDataReport *pNewData)
+ {
+ (void)pSensor;
+ vlc_viewpoint_t old_pos = current_pos;
+ HRESULT hr;
+ PROPVARIANT pvRot;
+
+ PropVariantInit(&pvRot);
+ hr = pNewData->GetSensorValue(SENSOR_DATA_TYPE_TILT_X_DEGREES, &pvRot);
+ if (SUCCEEDED(hr) && pvRot.vt == VT_R4)
+ {
+ current_pos.pitch = pvRot.fltVal;
+ PropVariantClear(&pvRot);
+ }
+ hr = pNewData->GetSensorValue(SENSOR_DATA_TYPE_TILT_Y_DEGREES, &pvRot);
+ if (SUCCEEDED(hr) && pvRot.vt == VT_R4)
+ {
+ current_pos.roll = pvRot.fltVal;
+ PropVariantClear(&pvRot);
+ }
+ hr = pNewData->GetSensorValue(SENSOR_DATA_TYPE_TILT_Z_DEGREES, &pvRot);
+ if (SUCCEEDED(hr) && pvRot.vt == VT_R4)
+ {
+ current_pos.yaw = pvRot.fltVal;
+ PropVariantClear(&pvRot);
+ }
+
+ vout_display_SendEventViewpointChanged(vd, current_pos.yaw - old_pos.yaw,
+ current_pos.pitch - old_pos.pitch,
+ current_pos.roll - old_pos.roll);
+ return S_OK;
+ }
+
+ HRESULT STDMETHODCALLTYPE OnEvent(ISensor *pSensor, REFGUID eventID, IPortableDeviceValues *pEventData)
+ {
+ (void)pSensor;
+ (void)eventID;
+ (void)pEventData;
+ return S_OK;
+ }
+
+ HRESULT STDMETHODCALLTYPE OnLeave(REFSENSOR_ID ID)
+ {
+ (void)ID;
+ return S_OK;
+ }
+
+private:
+ vout_display_t *const vd;
+ vlc_viewpoint_t current_pos;
+ long m_cRef;
+};
+
+void *HookWindowsSensors(vout_display_t *vd, HWND hwnd)
+{
+ ISensor *pSensor = NULL;
+ ISensorManager *pSensorManager;
+ HRESULT hr = CoCreateInstance( CLSID_SensorManager,
+ NULL, CLSCTX_INPROC_SERVER,
+ IID_ISensorManager, (void**)&pSensorManager );
+ if (SUCCEEDED(hr))
+ {
+ ISensorCollection *pInclinometers;
+ hr = pSensorManager->GetSensorsByType(SENSOR_TYPE_INCLINOMETER_3D, &pInclinometers);
+ if (SUCCEEDED(hr))
+ {
+ ULONG count;
+ pInclinometers->GetCount(&count);
+ msg_Dbg(vd, "Found %lu inclinometer", count);
+ for (ULONG i=0; i<count; ++i)
+ {
+ hr = pInclinometers->GetAt(i, &pSensor);
+ if (SUCCEEDED(hr))
+ {
+ SensorState state = SENSOR_STATE_NOT_AVAILABLE;
+ hr = pSensor->GetState(&state);
+ if (SUCCEEDED(hr))
+ {
+ if (state == SENSOR_STATE_ACCESS_DENIED)
+ hr = pSensorManager->RequestPermissions(hwnd, pInclinometers, TRUE);
+
+ if (SUCCEEDED(hr))
+ {
+ vlc_viewpoint_t start_viewpoint;
+ vlc_viewpoint_init(&start_viewpoint);
+ PROPVARIANT pvRot;
+ PropVariantInit(&pvRot);
+ hr = pSensor->GetProperty(SENSOR_DATA_TYPE_TILT_X_DEGREES, &pvRot);
+ if (SUCCEEDED(hr) && pvRot.vt == VT_R4)
+ {
+ start_viewpoint.pitch = pvRot.fltVal;
+ PropVariantClear(&pvRot);
+ }
+ hr = pSensor->GetProperty(SENSOR_DATA_TYPE_TILT_Y_DEGREES, &pvRot);
+ if (SUCCEEDED(hr) && pvRot.vt == VT_R4)
+ {
+ start_viewpoint.roll = pvRot.fltVal;
+ PropVariantClear(&pvRot);
+ }
+ hr = pSensor->GetProperty(SENSOR_DATA_TYPE_TILT_Z_DEGREES, &pvRot);
+ if (SUCCEEDED(hr) && pvRot.vt == VT_R4)
+ {
+ start_viewpoint.yaw = pvRot.fltVal;
+ PropVariantClear(&pvRot);
+ }
+
+ SensorReceiver *received = new(std::nothrow) SensorReceiver(vd, start_viewpoint);
+ if (received)
+ {
+ pSensor->SetEventSink(received);
+ break;
+ }
+ }
+ }
+
+ pSensor->Release();
+ }
+ }
+ pInclinometers->Release();
+ }
+ else
+ msg_Dbg(vd, "inclinometer not found. (hr=0x%lX)", hr);
+ pSensorManager->Release();
+ }
+ return pSensor;
+}
+
+void UnhookWindowsSensors(void *vSensor)
+{
+ if (!vSensor)
+ return;
+
+ ISensor *pSensor = static_cast<ISensor*>(vSensor);
+ pSensor->SetEventSink(NULL);
+ pSensor->Release();
+}
--
2.11.1
More information about the vlc-devel
mailing list