1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/device_orientation/data_fetcher_impl_win.h"
8 #include <PortableDeviceTypes.h>
11 #include "base/logging.h"
12 #include "base/win/iunknown_impl.h"
13 #include "base/win/windows_version.h"
14 #include "content/browser/device_orientation/orientation.h"
18 // This should match ProviderImpl::kDesiredSamplingIntervalMs.
19 const int kPeriodInMilliseconds
= 100;
25 class DataFetcherImplWin::SensorEventSink
: public ISensorEvents
,
26 public base::win::IUnknownImpl
{
28 explicit SensorEventSink(DataFetcherImplWin
* const fetcher
)
29 : fetcher_(fetcher
) {}
31 virtual ~SensorEventSink() {}
34 virtual ULONG STDMETHODCALLTYPE
AddRef() OVERRIDE
{
35 return IUnknownImpl::AddRef();
38 virtual ULONG STDMETHODCALLTYPE
Release() OVERRIDE
{
39 return IUnknownImpl::Release();
42 virtual STDMETHODIMP
QueryInterface(REFIID riid
, void** ppv
) OVERRIDE
{
43 if (riid
== __uuidof(ISensorEvents
)) {
44 *ppv
= static_cast<ISensorEvents
*>(this);
48 return IUnknownImpl::QueryInterface(riid
, ppv
);
51 // ISensorEvents interface
52 STDMETHODIMP
OnEvent(ISensor
* sensor
,
54 IPortableDeviceValues
* event_data
) OVERRIDE
{
58 STDMETHODIMP
OnDataUpdated(ISensor
* sensor
,
59 ISensorDataReport
* new_data
) OVERRIDE
{
60 if (NULL
== new_data
|| NULL
== sensor
)
63 PROPVARIANT value
= {};
64 scoped_refptr
<Orientation
> orientation
= new Orientation();
66 if (SUCCEEDED(new_data
->GetSensorValue(
67 SENSOR_DATA_TYPE_TILT_X_DEGREES
, &value
))) {
68 orientation
->set_beta(value
.fltVal
);
70 PropVariantClear(&value
);
72 if (SUCCEEDED(new_data
->GetSensorValue(
73 SENSOR_DATA_TYPE_TILT_Y_DEGREES
, &value
))) {
74 orientation
->set_gamma(value
.fltVal
);
76 PropVariantClear(&value
);
78 if (SUCCEEDED(new_data
->GetSensorValue(
79 SENSOR_DATA_TYPE_TILT_Z_DEGREES
, &value
))) {
80 orientation
->set_alpha(value
.fltVal
);
82 PropVariantClear(&value
);
84 orientation
->set_absolute(true);
85 fetcher_
->OnOrientationData(orientation
.get());
90 STDMETHODIMP
OnLeave(REFSENSOR_ID sensor_id
) OVERRIDE
{
94 STDMETHODIMP
OnStateChanged(ISensor
* sensor
, SensorState state
) OVERRIDE
{
99 DataFetcherImplWin
* const fetcher_
;
101 DISALLOW_COPY_AND_ASSIGN(SensorEventSink
);
104 // Create a DataFetcherImplWin object and return NULL if no valid sensor found.
106 DataFetcher
* DataFetcherImplWin::Create() {
107 scoped_ptr
<DataFetcherImplWin
> fetcher(new DataFetcherImplWin
);
108 if (fetcher
->Initialize())
109 return fetcher
.release();
111 LOG(ERROR
) << "DataFetcherImplWin::Initialize failed!";
115 DataFetcherImplWin::~DataFetcherImplWin() {
117 sensor_
->SetEventSink(NULL
);
120 DataFetcherImplWin::DataFetcherImplWin() {
123 void DataFetcherImplWin::OnOrientationData(Orientation
* orientation
) {
124 // This method is called on Windows sensor thread.
125 base::AutoLock
autolock(next_orientation_lock_
);
126 next_orientation_
= orientation
;
129 const DeviceData
* DataFetcherImplWin::GetDeviceData(DeviceData::Type type
) {
130 if (type
!= DeviceData::kTypeOrientation
)
132 return GetOrientation();
135 const Orientation
* DataFetcherImplWin::GetOrientation() {
136 if (next_orientation_
.get()) {
137 base::AutoLock
autolock(next_orientation_lock_
);
138 next_orientation_
.swap(current_orientation_
);
140 if (!current_orientation_
.get())
141 return new Orientation();
142 return current_orientation_
.get();
145 bool DataFetcherImplWin::Initialize() {
146 if (base::win::GetVersion() < base::win::VERSION_WIN7
)
149 base::win::ScopedComPtr
<ISensorManager
> sensor_manager
;
150 HRESULT hr
= sensor_manager
.CreateInstance(CLSID_SensorManager
);
151 if (FAILED(hr
) || !sensor_manager
)
154 base::win::ScopedComPtr
<ISensorCollection
> sensor_collection
;
155 hr
= sensor_manager
->GetSensorsByType(
156 SENSOR_TYPE_INCLINOMETER_3D
, sensor_collection
.Receive());
158 if (FAILED(hr
) || !sensor_collection
)
162 hr
= sensor_collection
->GetCount(&count
);
163 if (FAILED(hr
) || !count
)
166 hr
= sensor_collection
->GetAt(0, sensor_
.Receive());
167 if (FAILED(hr
) || !sensor_
)
170 base::win::ScopedComPtr
<IPortableDeviceValues
> device_values
;
171 if (SUCCEEDED(device_values
.CreateInstance(CLSID_PortableDeviceValues
))) {
172 if (SUCCEEDED(device_values
->SetUnsignedIntegerValue(
173 SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL
, kPeriodInMilliseconds
))) {
174 base::win::ScopedComPtr
<IPortableDeviceValues
> return_values
;
175 sensor_
->SetProperties(device_values
.get(), return_values
.Receive());
179 scoped_refptr
<SensorEventSink
> sensor_event_impl(new SensorEventSink(this));
180 base::win::ScopedComPtr
<ISensorEvents
> sensor_events
;
181 hr
= sensor_event_impl
->QueryInterface(
182 __uuidof(ISensorEvents
), sensor_events
.ReceiveVoid());
183 if (FAILED(hr
) || !sensor_events
)
186 hr
= sensor_
->SetEventSink(sensor_events
);
193 } // namespace content