diff options
author | Eckhart Koppen <eckhart.koppen@nokia.com> | 2011-04-20 11:52:57 +0300 |
---|---|---|
committer | Eckhart Koppen <eckhart.koppen@nokia.com> | 2011-04-20 11:52:57 +0300 |
commit | fb3e9bc2d941462f1244aaf0ea79425a307f883d (patch) | |
tree | afce91959098ec887ce466abc6e40342261df3db /plugins | |
parent | c61d909c7b815319e40ba27d7f84e92aa5f1f946 (diff) | |
parent | 6f0dc7cc40dd63763a581a7fb6d4e76649b8026c (diff) |
Merge branch 'master' into 1.2.0v1.2.0
Diffstat (limited to 'plugins')
71 files changed, 4205 insertions, 414 deletions
diff --git a/plugins/contacts/symbian/contactsmodel/cntplsql/src/cpplcommaddrtable.cpp b/plugins/contacts/symbian/contactsmodel/cntplsql/src/cpplcommaddrtable.cpp index 8343622787..2de46ac1e1 100644 --- a/plugins/contacts/symbian/contactsmodel/cntplsql/src/cpplcommaddrtable.cpp +++ b/plugins/contacts/symbian/contactsmodel/cntplsql/src/cpplcommaddrtable.cpp @@ -1065,7 +1065,8 @@ CPplCommAddrTable::TMatch CPplCommAddrTable::CreatePaddedPhoneDigitsL(const TDes // digits total. TInt pad = KMaxPhoneMatchLength - KLowerSevenDigits - phoneNumber.iNumUpperDigits; phoneNumber.iUpperDigits = TMatch::PadOutPhoneMatchNumber(phoneNumber.iUpperDigits,pad); - } + phoneNumber.iNumUpperDigits = aNumUpperDigits; + } return phoneNumber; } diff --git a/plugins/contacts/symbian/contactsmodel/tsrc/t_cntmatch.cpp b/plugins/contacts/symbian/contactsmodel/tsrc/t_cntmatch.cpp index cbaf70e901..1c78748c34 100644 --- a/plugins/contacts/symbian/contactsmodel/tsrc/t_cntmatch.cpp +++ b/plugins/contacts/symbian/contactsmodel/tsrc/t_cntmatch.cpp @@ -254,14 +254,14 @@ LOCAL_C void Test3L() //it definetly should match on itself.... TESTVALUE(CheckPhoneMatchL(_L("123 4567"), 7),2); //Both numbers match by 7 digits.. - TESTVALUE(CheckPhoneMatchL(_L("123 4567"), 8),2); //But they must differ for more digits - TESTVALUE(CheckPhoneMatchL(_L("123 4567"), 9),2); // AB - all these should match both... - TESTVALUE(CheckPhoneMatchL(_L("123 4567"),10),2); - TESTVALUE(CheckPhoneMatchL(_L("123 4567"),11),2); - TESTVALUE(CheckPhoneMatchL(_L("123 4567"),12),2); - TESTVALUE(CheckPhoneMatchL(_L("123 4567"),13),2); - TESTVALUE(CheckPhoneMatchL(_L("123 4567"),14),2); - TESTVALUE(CheckPhoneMatchL(_L("123 4567"),15),2); + TESTVALUE(CheckPhoneMatchL(_L("123 4567"), 8),1); //But they must differ for more digits + TESTVALUE(CheckPhoneMatchL(_L("123 4567"), 9),1); // AB - all these should match both... + TESTVALUE(CheckPhoneMatchL(_L("123 4567"),10),1); + TESTVALUE(CheckPhoneMatchL(_L("123 4567"),11),1); + TESTVALUE(CheckPhoneMatchL(_L("123 4567"),12),1); + TESTVALUE(CheckPhoneMatchL(_L("123 4567"),13),1); + TESTVALUE(CheckPhoneMatchL(_L("123 4567"),14),1); + TESTVALUE(CheckPhoneMatchL(_L("123 4567"),15),1); TESTVALUE(CheckPhoneMatchL(_L("123 4567"), KBestMatchingPhoneNumbers),2); } diff --git a/plugins/contacts/symbian/contactsmodel/tsrc/t_nomach.cpp b/plugins/contacts/symbian/contactsmodel/tsrc/t_nomach.cpp index d8935c6ace..f2ec037950 100644 --- a/plugins/contacts/symbian/contactsmodel/tsrc/t_nomach.cpp +++ b/plugins/contacts/symbian/contactsmodel/tsrc/t_nomach.cpp @@ -611,7 +611,7 @@ LOCAL_C void Test11DigitMatchingL() CheckPhoneMatchL(K11DigitMatch5,KMatch13Digits,1); CheckPhoneMatchL(K11DigitMatch6,KMatch10Digits,3); - CheckPhoneMatchL(K11DigitMatch6,KMatch11Digits,3); + CheckPhoneMatchL(K11DigitMatch6,KMatch11Digits,1); } /** diff --git a/plugins/declarative/declarative.pro b/plugins/declarative/declarative.pro index f263687e6f..cf318adae9 100644 --- a/plugins/declarative/declarative.pro +++ b/plugins/declarative/declarative.pro @@ -6,11 +6,11 @@ contains(mobility_modules,sensors): SUBDIRS += sensors contains(mobility_modules,serviceframework): SUBDIRS += serviceframework contains(mobility_modules,publishsubscribe): SUBDIRS += publishsubscribe contains(mobility_modules,multimedia): SUBDIRS += multimedia -contains(mobility_modules,organizer):contains(mobility_modules,versit) SUBDIRS += organizer +contains(mobility_modules,organizer):contains(mobility_modules,versit): SUBDIRS += organizer contains(mobility_modules,systeminfo): SUBDIRS += systeminfo contains(mobility_modules,gallery): SUBDIRS += gallery contains(mobility_modules,feedback): SUBDIRS += feedback -contains(mobility_modules,contacts):contains(mobility_modules,versit) SUBDIRS += contacts +contains(mobility_modules,contacts):contains(mobility_modules,versit): SUBDIRS += contacts contains(mobility_modules,location): SUBDIRS += location !win32:!mac:!contains(S60_VERSION, 3.1):!contains(S60_VERSION, 3.2):contains(mobility_modules,connectivity): SUBDIRS += connectivity contains(qmf_enabled, yes)|wince*|win32|symbian|maemo5|maemo6 { diff --git a/plugins/declarative/multimedia/qdeclarativecamera.cpp b/plugins/declarative/multimedia/qdeclarativecamera.cpp index ce63be4432..d36a0c9f32 100644 --- a/plugins/declarative/multimedia/qdeclarativecamera.cpp +++ b/plugins/declarative/multimedia/qdeclarativecamera.cpp @@ -351,7 +351,6 @@ QString QDeclarativeCamera::errorString() const \o The initial camera state, with camera not loaded, the camera capabilities except of supported capture modes are unknown. - While the supported settings are unknown in this state, it's allowed to set the camera capture settings like codec, resolution, or frame rate. @@ -369,6 +368,28 @@ QString QDeclarativeCamera::errorString() const the viewfinder displays video frames and the camera is ready for capture. \endtable +*/ +/*! + \enum QDeclarativeCamera::State + \value UnloadedState + The initial camera state, with camera not loaded, + the camera capabilities except of supported capture modes + are unknown. + While the supported settings are unknown in this state, + it's allowed to set the camera capture settings like codec, + resolution, or frame rate. + + \value LoadedState + The camera is loaded and ready to be configured. + In the Idle state it's allowed to query camera capabilities, + set capture resolution, codecs, etc. + The viewfinder is not active in the loaded state. + + \value ActiveState + In the active state as soon as camera is started + the viewfinder displays video frames and the + camera is ready for capture. + The default camera state is ActiveState. */ @@ -452,7 +473,26 @@ void QDeclarativeCamera::stop() For example in continuous focusing mode, the focus is considered locked as long and the object is in focus, even while the actual focusing distance may be constantly changing. \endtable +*/ +/*! + \enum QDeclarativeCamera::LockStatus + \value Unlocked + The application is not interested in camera settings value. + The camera may keep this parameter without changes, this is common with camera focus, + or adjust exposure and white balance constantly to keep the viewfinder image nice. + + \value Searching + The application has requested the camera focus, exposure or white balance lock with + searchAndLock(). This state indicates the camera is focusing or calculating exposure and white balance. + \value Locked + The camera focus, exposure or white balance is locked. + The camera is ready to capture, application may check the exposure parameters. + + The locked state usually means the requested parameter stays the same, + except in the cases when the parameter is requested to be constantly updated. + For example in continuous focusing mode, the focus is considered locked as long + and the object is in focus, even while the actual focusing distance may be constantly changing. */ QDeclarativeCamera::LockStatus QDeclarativeCamera::lockStatus() const { @@ -588,6 +628,22 @@ void QDeclarativeCamera::keyReleaseEvent(QKeyEvent * event) \endtable */ +/*! + \enum QDeclarativeCamera::FlashMode + \value FlashOff Flash is Off. + \value FlashOn Flash is On. + \value FlashAuto Automatic flash. + \value FlashRedEyeReduction Red eye reduction flash. + \value FlashFill Use flash to fillin shadows. + \value FlashTorch Constant light source, useful for focusing and video capture. + \value FlashSlowSyncFrontCurtain + Use the flash in conjunction with a slow shutter speed. + This mode allows better exposure of distant objects and/or motion blur effect. + \value FlashSlowSyncRearCurtain + The similar mode to FlashSlowSyncFrontCurtain but flash is fired at the end of exposure. + \value FlashManual Flash power is manually set. + +*/ int QDeclarativeCamera::flashMode() const { if (!m_isValid) @@ -610,6 +666,12 @@ void QDeclarativeCamera::setFlashMode(int mode) Adjustment for the automatically calculated exposure. The value is in EV units. */ +/*! + \property QDeclarativeCamera::exposureCompensation + + Adjustment for the automatically calculated exposure. The value is + in EV units. + */ qreal QDeclarativeCamera::exposureCompensation() const { if (!m_isValid) @@ -629,6 +691,11 @@ void QDeclarativeCamera::setExposureCompensation(qreal ev) The sensor's ISO sensitivity. */ +/*! + \property QDeclarativeCamera::isoSensitivity + + The sensor's ISO sensitivity. + */ int QDeclarativeCamera::isoSensitivity() const { if (!m_isValid) @@ -650,6 +717,11 @@ void QDeclarativeCamera::setManualIsoSensitivity(int iso) The camera's shutter speed, in seconds. */ +/*! + \property QDeclarativeCamera::shutterSpeed + + The camera's shutter speed, in seconds. +*/ qreal QDeclarativeCamera::shutterSpeed() const { if (!m_isValid) @@ -663,6 +735,11 @@ qreal QDeclarativeCamera::shutterSpeed() const The lens aperture as an F number (the ratio of the focal length to effective aperture diameter). */ +/*! + \property QDeclarativeCamera::aperture + + The lens aperture as an F number (the ratio of the focal length to effective aperture diameter). +*/ qreal QDeclarativeCamera::aperture() const { if (!m_isValid) @@ -691,6 +768,27 @@ qreal QDeclarativeCamera::aperture() const \endtable */ +/*! + \enum QDeclarativeCamera::ExposureMode + \value ExposureManual Manual mode. + \value ExposureAuto Automatic mode. + \value ExposureNight Night mode. + \value ExposureBacklight Backlight exposure mode. + \value ExposureSpotlight Spotlight exposure mode. + \value ExposureSports Spots exposure mode. + \value ExposureSnow Snow exposure mode. + \value ExposureBeach Beach exposure mode. + \value ExposureLargeAperture Use larger aperture with small depth of field. + \value ExposureSmallAperture Use smaller aperture. + \value ExposurePortrait Portrait exposure mode. + \value ExposureModeVendor The base value for device specific exposure modes. + +*/ +/*! + \property QDeclarativeCamera::exposureMode + + Camera exposure modes. +*/ QDeclarativeCamera::ExposureMode QDeclarativeCamera::exposureMode() const { if (!m_isValid) @@ -716,6 +814,12 @@ void QDeclarativeCamera::setExposureMode(QDeclarativeCamera::ExposureMode mode) The resolution to capture the image at. If empty, the system will pick a good size. */ +/*! + \property QDeclarativeCamera::captureResolution + + The resolution to capture the image at. If empty, the system will pick + a good size. +*/ QSize QDeclarativeCamera::captureResolution() const { if (!m_isValid) @@ -743,6 +847,11 @@ void QDeclarativeCamera::setCaptureResolution(const QSize &resolution) The maximum optical zoom factor, or 1.0 if optical zoom is not supported. */ +/*! + \property QDeclarativeCamera::maximumOpticalZoom + + The maximum optical zoom factor, or 1.0 if optical zoom is not supported. +*/ qreal QDeclarativeCamera::maximumOpticalZoom() const { if (!m_isValid) @@ -756,6 +865,11 @@ qreal QDeclarativeCamera::maximumOpticalZoom() const The maximum digital zoom factor, or 1.0 if digital zoom is not supported. */ +/*! + \property QDeclarativeCamera::maximumDigitalZoom + + The maximum digital zoom factor, or 1.0 if digital zoom is not supported. +*/ qreal QDeclarativeCamera::maximumDigitalZoom() const { if (!m_isValid) @@ -769,6 +883,11 @@ qreal QDeclarativeCamera::maximumDigitalZoom() const The current optical zoom factor. */ +/*! + \property QDeclarativeCamera::opticalZoom + + The current optical zoom factor. +*/ qreal QDeclarativeCamera::opticalZoom() const { if (!m_isValid) @@ -788,6 +907,11 @@ void QDeclarativeCamera::setOpticalZoom(qreal value) The current digital zoom factor. */ +/*! + \property QDeclarativeCamera::digitalZoom + + The current digital zoom factor. +*/ qreal QDeclarativeCamera::digitalZoom() const { if (!m_isValid) @@ -803,6 +927,20 @@ void QDeclarativeCamera::setDigitalZoom(qreal value) } /*! + \enum QDeclarativeCamera::WhiteBalanceMode + \value WhiteBalanceManual Manual white balance. In this mode the manual white balance property value is used. + \value WhiteBalanceAuto Auto white balance mode. + \value WhiteBalanceSunlight Sunlight white balance mode. + \value WhiteBalanceCloudy Cloudy white balance mode. + \value WhiteBalanceShade Shade white balance mode. + \value WhiteBalanceTungsten Tungsten white balance mode. + \value WhiteBalanceFluorescent Fluorescent white balance mode. + \value WhiteBalanceIncandescent Incandescent white balance mode. + \value WhiteBalanceFlash Flash white balance mode. + \value WhiteBalanceSunset Sunset white balance mode. + \value WhiteBalanceVendor Vendor defined white balance mode. +*/ +/*! \qmlproperty enumeration Camera::whiteBalanceMode \table @@ -822,6 +960,11 @@ void QDeclarativeCamera::setDigitalZoom(qreal value) \sa manualWhiteBalance */ +/*! + \property QDeclarativeCamera::whiteBalanceMode + + \sa WhiteBalanceMode +*/ QDeclarativeCamera::WhiteBalanceMode QDeclarativeCamera::whiteBalanceMode() const { if (!m_isValid) @@ -845,6 +988,13 @@ void QDeclarativeCamera::setWhiteBalanceMode(QDeclarativeCamera::WhiteBalanceMod \sa whiteBalanceMode */ +/*! + \property QCamera::manualWhiteBalance + + The color temperature used when in manual white balance mode (WhiteBalanceManual). + + \sa whiteBalanceMode +*/ int QDeclarativeCamera::manualWhiteBalance() const { if (!m_isValid) @@ -877,6 +1027,15 @@ void QDeclarativeCamera::setManualWhiteBalance(int colorTemp) const \row \o NotSupportedFeatureError \o The feature is not supported. \endtable */ +/*! + \enum QDeclarativeCamera::Error + \value NoError No errors have occurred. + \value CameraError An error has occurred. + \value InvalidRequestError System resource doesn't support requested functionality. + \value ServiceMissingError No camera service available. + \value NotSupportedFeatureError The feature is not supported. +*/ + /*! \qmlsignal Camera::onCaptureFailed(message) diff --git a/plugins/declarative/systeminfo/qdeclarativenetworkinfo.cpp b/plugins/declarative/systeminfo/qdeclarativenetworkinfo.cpp index edcdf1160c..4d98853ea7 100644 --- a/plugins/declarative/systeminfo/qdeclarativenetworkinfo.cpp +++ b/plugins/declarative/systeminfo/qdeclarativenetworkinfo.cpp @@ -274,7 +274,7 @@ void QDeclarativeNetworkInfo::startSignalStrengthChanged(bool on) /*! \qmlproperty bool NetworkInfo::monitorSignalStrengthChanges - \brief Use the monitorSignalStrengthChanges signal. + \brief Use the signalStrengthChanged signal. */ bool QDeclarativeNetworkInfo::monitorSignalStrengthChanges() { @@ -300,7 +300,7 @@ void QDeclarativeNetworkInfo::startNameChanged(bool on) /*! \qmlproperty bool NetworkInfo::monitorNameChanges - \brief Use the monitorNameChanges signal. + \brief Use the nameChanged signal. */ bool QDeclarativeNetworkInfo::monitorNameChanges() { @@ -527,3 +527,59 @@ QSystemNetworkInfo::NetworkMode QDeclarativeNetworkInfo::mode() { return m_mode; } + + +/*! + \qmlproperty bool NetworkInfo::monitoringCellDataTechnologyChanges + \brief Use the cellDataTechnologyChanges signal. + + \sa QSystemNetworkInfo::cellDataTechnologyChanged + */ +bool QDeclarativeNetworkInfo::monitorCellDataChanges() +{ + return monitoringCellDataTechnologyChanges; +} + +/*! + This function starts the cellDataTechnologyChanges notification + +*/ +void QDeclarativeNetworkInfo::startCellDataChanged(bool on) +{ + monitoringCellDataTechnologyChanges = on; + if (on) { + connect(netInfo(),SIGNAL(cellDataTechnologyChanged(QSystemNetworkInfo::CellDataTechnology)), + this,SIGNAL(cellDataTechnologyChanges(QSystemNetworkInfo::CellDataTechnology)),Qt::UniqueConnection); + } else { + disconnect(netInfo(),SIGNAL(cellDataTechnologyChanged(QSystemNetworkInfo::CellDataTechnology)), + this,SIGNAL(cellDataTechnologyChanges(QSystemNetworkInfo::CellDataTechnology))); + } +} + +/*! + \qmlproperty bool NetworkInfo::monitoringCellIdChanges + \brief Use the cellIdChanges signal. + */ +bool QDeclarativeNetworkInfo::monitorCellIdChanges() +{ + return monitoringCellIdChanges; +} + +/*! + This function starts the cellIdChanges notification + + \sa QSystemNetworkInfo::cellIdChanged + +*/ +void QDeclarativeNetworkInfo::startCellIdChanged(bool on) +{ + monitoringCellIdChanges = on; + if (on) { + connect(netInfo(),SIGNAL(cellIdChanged(int)), + this,SIGNAL(cellIdChanges(int)),Qt::UniqueConnection); + } else { + disconnect(netInfo(),SIGNAL(cellIdChanged(int)), + this,SIGNAL(cellIdChanges(int))); + } +} + diff --git a/plugins/declarative/systeminfo/qdeclarativenetworkinfo_p.h b/plugins/declarative/systeminfo/qdeclarativenetworkinfo_p.h index 36427e58d9..df4e825422 100644 --- a/plugins/declarative/systeminfo/qdeclarativenetworkinfo_p.h +++ b/plugins/declarative/systeminfo/qdeclarativenetworkinfo_p.h @@ -62,6 +62,8 @@ class QDeclarativeNetworkInfo : public QSystemNetworkInfo Q_PROPERTY(bool monitorModeChanges READ monitorModeChanges WRITE startModeChanged) Q_PROPERTY(bool monitorCurrentMobileCountryCodeChanges READ monitorCurrentMobileCountryCodeChanges WRITE startCurrentMobileCountryCodeChanged) Q_PROPERTY(bool monitorCurrentMobileNetworkCodeChanges READ monitorCurrentMobileNetworkCodeChanges WRITE startCurrentMobileNetworkCodeChanged) + Q_PROPERTY(bool monitorCellDataChanges READ monitorCellDataChanges WRITE startCellDataChanged) + Q_PROPERTY(bool monitorCellIdChanges READ monitorCellIdChanges WRITE startCellIdChanged) public: explicit QDeclarativeNetworkInfo(QObject *parent = 0); @@ -90,6 +92,12 @@ public: bool monitorCurrentMobileNetworkCodeChanges(); void startCurrentMobileNetworkCodeChanged(bool on); + bool monitorCellDataChanges(); + void startCellDataChanged(bool on); + + bool monitorCellIdChanges(); + void startCellIdChanged(bool on); + void useMode(QSystemNetworkInfo::NetworkMode curmode); public slots: @@ -105,6 +113,10 @@ Q_SIGNALS: void currentMobileCountryCodeChanged(const QString &newMcc); void currentMobileNetworkCodeChanged(const QString &newMnc); + void cellIdChanges(int cellId); + void cellDataTechnologyChanges(QSystemNetworkInfo::CellDataTechnology cellTech); + + private: QSystemNetworkInfo::NetworkMode m_mode; QString statusToString(QSystemNetworkInfo::NetworkStatus); @@ -116,6 +128,8 @@ private: bool monitoringModeChanges; bool monitoringCurrentMobileCountryCodeChanges; bool monitoringCurrentMobileNetworkCodeChanges; + bool monitoringCellDataTechnologyChanges; + bool monitoringCellIdChanges; private slots: void networkStatusChanged(QSystemNetworkInfo::NetworkMode, QSystemNetworkInfo::NetworkStatus); diff --git a/plugins/multimedia/directshow/camera/camera.pri b/plugins/multimedia/directshow/camera/camera.pri new file mode 100644 index 0000000000..42f5999a21 --- /dev/null +++ b/plugins/multimedia/directshow/camera/camera.pri @@ -0,0 +1,31 @@ +INCLUDEPATH += $$PWD + +DEFINES += QMEDIA_DIRECTSHOW_CAMERA + +win32-g++: DEFINES += QT_NO_WMSDK + +win32: DEFINES += _CRT_SECURE_NO_WARNINGS + +HEADERS += \ + $$PWD/dscameraservice.h \ + $$PWD/dscameracontrol.h \ + $$PWD/dsvideorenderer.h \ + $$PWD/dsvideodevicecontrol.h \ + $$PWD/dsimagecapturecontrol.h \ + $$PWD/dscamerasession.h \ + $$PWD/dsvideowidgetcontrol.h \ + $$PWD/dscameraservice.h \ + $$PWD/directshowglobal.h + + +SOURCES += \ + $$PWD/dscameraservice.cpp \ + $$PWD/dscameracontrol.cpp \ + $$PWD/dsvideorenderer.cpp \ + $$PWD/dsvideodevicecontrol.cpp \ + $$PWD/dsimagecapturecontrol.cpp \ + $$PWD/dscamerasession.cpp \ + $$PWD/dsvideowidgetcontrol.cpp + +INCLUDEPATH += $(DXSDK_DIR)/include +LIBS += -lstrmiids -ldmoguids -luuid -lmsdmo -lole32 -loleaut32 diff --git a/plugins/multimedia/directshow/camera/directshowglobal.h b/plugins/multimedia/directshow/camera/directshowglobal.h new file mode 100644 index 0000000000..76c143798d --- /dev/null +++ b/plugins/multimedia/directshow/camera/directshowglobal.h @@ -0,0 +1,236 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DIRECTSHOWGLOBAL_H +#define DIRECTSHOWGLOBAL_H + +#include <QtCore/qglobal.h> + +#include <dshow.h> + +DEFINE_GUID(MEDIASUBTYPE_I420, + 0x30323449,0x0000,0x0010,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71); + +extern const GUID MEDIASUBTYPE_RGB24; +extern const GUID MEDIASUBTYPE_RGB32; +extern const GUID MEDIASUBTYPE_YUY2; +extern const GUID MEDIASUBTYPE_MJPG; +extern const GUID MEDIASUBTYPE_RGB555; +extern const GUID MEDIASUBTYPE_YVU9; +extern const GUID MEDIASUBTYPE_UYVY; +extern const GUID PIN_CATEGORY_CAPTURE; +extern const GUID PIN_CATEGORY_PREVIEW; + +extern const IID IID_IPropertyBag; +extern const IID IID_ISampleGrabber; +extern const IID IID_ICaptureGraphBuilder2; +extern const IID IID_IAMStreamConfig; + + +extern const CLSID CLSID_CVidCapClassManager; +extern const CLSID CLSID_VideoInputDeviceCategory; +extern const CLSID CLSID_SampleGrabber; +extern const CLSID CLSID_CaptureGraphBuilder2; + +#define SAFE_RELEASE(x) { if(x) x->Release(); x = NULL; } + +typedef struct IFileSinkFilter *LPFILESINKFILTER; +typedef struct IAMCopyCaptureFileProgress *LPAMCOPYCAPTUREFILEPROGRESS; + +#ifndef __ICaptureGraphBuilder2_INTERFACE_DEFINED__ +#define __ICaptureGraphBuilder2_INTERFACE_DEFINED__ +struct ICaptureGraphBuilder2 : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE SetFiltergraph( + /* [in] */ IGraphBuilder *pfg) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFiltergraph( + /* [out] */ IGraphBuilder **ppfg) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetOutputFileName( + /* [in] */ const GUID *pType, + /* [in] */ LPCOLESTR lpstrFile, + /* [out] */ IBaseFilter **ppf, + /* [out] */ IFileSinkFilter **ppSink) = 0; + + virtual /* [local] */ HRESULT STDMETHODCALLTYPE FindInterface( + /* [in] */ const GUID *pCategory, + /* [in] */ const GUID *pType, + /* [in] */ IBaseFilter *pf, + /* [in] */ REFIID riid, + /* [out] */ void **ppint) = 0; + + virtual HRESULT STDMETHODCALLTYPE RenderStream( + /* [in] */ const GUID *pCategory, + /* [in] */ const GUID *pType, + /* [in] */ IUnknown *pSource, + /* [in] */ IBaseFilter *pfCompressor, + /* [in] */ IBaseFilter *pfRenderer) = 0; + + virtual HRESULT STDMETHODCALLTYPE ControlStream( + /* [in] */ const GUID *pCategory, + /* [in] */ const GUID *pType, + /* [in] */ IBaseFilter *pFilter, + /* [in] */ REFERENCE_TIME *pstart, + /* [in] */ REFERENCE_TIME *pstop, + /* [in] */ WORD wStartCookie, + /* [in] */ WORD wStopCookie) = 0; + + virtual HRESULT STDMETHODCALLTYPE AllocCapFile( + /* [in] */ LPCOLESTR lpstr, + /* [in] */ DWORDLONG dwlSize) = 0; + + virtual HRESULT STDMETHODCALLTYPE CopyCaptureFile( + /* [in] */ LPOLESTR lpwstrOld, + /* [in] */ LPOLESTR lpwstrNew, + /* [in] */ int fAllowEscAbort, + /* [in] */ IAMCopyCaptureFileProgress *pCallback) = 0; + + virtual HRESULT STDMETHODCALLTYPE FindPin( + /* [in] */ IUnknown *pSource, + /* [in] */ PIN_DIRECTION pindir, + /* [in] */ const GUID *pCategory, + /* [in] */ const GUID *pType, + /* [in] */ BOOL fUnconnected, + /* [in] */ int num, + /* [out] */ IPin **ppPin) = 0; + +}; +#endif + +#ifndef __IAMStreamConfig_INTERFACE_DEFINED__ +#define __IAMStreamConfig_INTERFACE_DEFINED__ +struct IAMStreamConfig : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE SetFormat( + /* [in] */ AM_MEDIA_TYPE *pmt) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFormat( + /* [out] */ AM_MEDIA_TYPE **ppmt) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetNumberOfCapabilities( + /* [out] */ int *piCount, + /* [out] */ int *piSize) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetStreamCaps( + /* [in] */ int iIndex, + /* [out] */ AM_MEDIA_TYPE **ppmt, + /* [out] */ BYTE *pSCC) = 0; + +}; +#endif + +#ifndef __IErrorLog_INTERFACE_DEFINED__ +#define __IErrorLog_INTERFACE_DEFINED__ +struct IErrorLog : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE AddError( + /* [in] */ LPCOLESTR pszPropName, + /* [in] */ EXCEPINFO *pExcepInfo) = 0; + + }; +#endif + +#ifndef __IPropertyBag_INTERFACE_DEFINED__ +#define __IPropertyBag_INTERFACE_DEFINED__ +struct IPropertyBag : public IUnknown +{ +public: + virtual /* [local] */ HRESULT STDMETHODCALLTYPE Read( + /* [in] */ LPCOLESTR pszPropName, + /* [out][in] */ VARIANT *pVar, + /* [in] */ IErrorLog *pErrorLog) = 0; + + virtual HRESULT STDMETHODCALLTYPE Write( + /* [in] */ LPCOLESTR pszPropName, + /* [in] */ VARIANT *pVar) = 0; + +}; +#endif + +typedef struct IMediaSample *LPMEDIASAMPLE; + +EXTERN_C const IID IID_ISampleGrabberCB; + +#ifndef __ISampleGrabberCB_INTERFACE_DEFINED__ +#define __ISampleGrabberCB_INTERFACE_DEFINED__ + +#undef INTERFACE +#define INTERFACE ISampleGrabberCB +DECLARE_INTERFACE_(ISampleGrabberCB, IUnknown) +{ +// STDMETHOD(QueryInterface) (THIS_ const GUID *, void **) PURE; + STDMETHOD(QueryInterface) (THIS_ REFIID riid, void **) PURE; + STDMETHOD_(ULONG, AddRef) (THIS) PURE; + STDMETHOD_(ULONG, Release) (THIS) PURE; + STDMETHOD_(HRESULT, SampleCB) (THIS_ double, LPMEDIASAMPLE) PURE; + STDMETHOD_(HRESULT, BufferCB) (THIS_ double, BYTE *, long) PURE; +}; +#undef INTERFACE + +#endif + + +#ifndef __ISampleGrabber_INTERFACE_DEFINED__ +#define __ISampleGrabber_INTERFACE_DEFINED__ + +#define INTERFACE ISampleGrabber +DECLARE_INTERFACE_(ISampleGrabber,IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + STDMETHOD(SetOneShot)(THIS_ BOOL) PURE; + STDMETHOD(SetMediaType)(THIS_ const AM_MEDIA_TYPE*) PURE; + STDMETHOD(GetConnectedMediaType)(THIS_ AM_MEDIA_TYPE*) PURE; + STDMETHOD(SetBufferSamples)(THIS_ BOOL) PURE; + STDMETHOD(GetCurrentBuffer)(THIS_ long*,long*) PURE; + STDMETHOD(GetCurrentSample)(THIS_ IMediaSample**) PURE; + STDMETHOD(SetCallback)(THIS_ ISampleGrabberCB *,long) PURE; +}; +#undef INTERFACE +#endif + + +#endif diff --git a/plugins/multimedia/directshow/camera/dscameracontrol.cpp b/plugins/multimedia/directshow/camera/dscameracontrol.cpp new file mode 100644 index 0000000000..b09064c2ba --- /dev/null +++ b/plugins/multimedia/directshow/camera/dscameracontrol.cpp @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/qdebug.h> + +#include "dscameracontrol.h" +#include "dscameraservice.h" +#include "dscamerasession.h" + +QT_BEGIN_NAMESPACE + +DSCameraControl::DSCameraControl(QObject *parent) + :QCameraControl(parent), m_captureMode(QCamera::CaptureStillImage) +{ + m_session = qobject_cast<DSCameraSession*>(parent); + connect(m_session, SIGNAL(stateChanged(QCamera::State)),this, SIGNAL(stateChanged(QCamera::State))); +} + +DSCameraControl::~DSCameraControl() +{ +} + +void DSCameraControl::setState(QCamera::State state) +{ + switch (state) { + case QCamera::ActiveState: + start(); + break; + case QCamera::UnloadedState: /* fall through */ + case QCamera::LoadedState: + stop(); + break; + } +} + +bool DSCameraControl::isCaptureModeSupported(QCamera::CaptureMode mode) const +{ + bool bCaptureSupported = false; + switch (mode) { + case QCamera::CaptureStillImage: + bCaptureSupported = true; + break; + case QCamera::CaptureVideo: + bCaptureSupported = false; + break; + } + return bCaptureSupported; +} + +void DSCameraControl::start() +{ + m_session->record(); +} + +void DSCameraControl::stop() +{ + m_session->stop(); +} + +QCamera::State DSCameraControl::state() const +{ + return (QCamera::State)m_session->state(); +} + +QT_END_NAMESPACE diff --git a/plugins/multimedia/directshow/camera/dscameracontrol.h b/plugins/multimedia/directshow/camera/dscameracontrol.h new file mode 100644 index 0000000000..9b20563d2e --- /dev/null +++ b/plugins/multimedia/directshow/camera/dscameracontrol.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DSCAMERACONTROL_H +#define DSCAMERACONTROL_H + +#include <QtCore/qobject.h> +#include <qcameracontrol.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class DSCameraService; +class DSCameraSession; + + +class DSCameraControl : public QCameraControl +{ + Q_OBJECT +public: + DSCameraControl(QObject *parent = 0); + ~DSCameraControl(); + + void start(); + void stop(); + QCamera::State state() const; + + QCamera::CaptureMode captureMode() const { return m_captureMode; } + void setCaptureMode(QCamera::CaptureMode mode) + { + if (m_captureMode != mode) { + m_captureMode = mode; + emit captureModeChanged(mode); + } + } + + void setState(QCamera::State state); + + QCamera::Status status() const { return QCamera::UnavailableStatus; } + bool isCaptureModeSupported(QCamera::CaptureMode mode) const; + bool canChangeProperty(PropertyChangeType /* changeType */, QCamera::Status /* status */) const {return false; } + +private: + DSCameraSession *m_session; + DSCameraService *m_service; + QCamera::CaptureMode m_captureMode; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif + + diff --git a/plugins/multimedia/directshow/camera/dscameraservice.cpp b/plugins/multimedia/directshow/camera/dscameraservice.cpp new file mode 100644 index 0000000000..9d73da02ca --- /dev/null +++ b/plugins/multimedia/directshow/camera/dscameraservice.cpp @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/qvariant.h> +#include <QtCore/qdebug.h> +#include <QtGui/qwidget.h> +#include <QVideoWidgetControl.h> + + +#include "dscameraservice.h" +#include "dscameracontrol.h" +#include "dscamerasession.h" +#include "dsvideorenderer.h" +#include "dsvideodevicecontrol.h" +#include "dsimagecapturecontrol.h" +#include "dsvideowidgetcontrol.h" + +QT_BEGIN_NAMESPACE + +DSCameraService::DSCameraService(QObject *parent): + QMediaService(parent) +{ + m_session = new DSCameraSession(this); + + m_control = new DSCameraControl(m_session); + + m_videoDevice = new DSVideoDeviceControl(m_session); + + m_videoRenderer = new DSVideoRendererControl(m_session, this); + + m_imageCapture = new DSImageCaptureControl(m_session); + + m_viewFinderWidget = new DSVideoWidgetControl(m_session); + + m_device = QByteArray("default"); +} + +DSCameraService::~DSCameraService() +{ + delete m_control; + delete m_videoDevice; + delete m_videoRenderer; + delete m_imageCapture; + delete m_viewFinderWidget; + delete m_session; +} + +QMediaControl* DSCameraService::requestControl(const char *name) +{ + if(qstrcmp(name,QCameraControl_iid) == 0) + return m_control; + + if (qstrcmp(name, QCameraImageCaptureControl_iid) == 0) + return m_imageCapture; + + if (qstrcmp(name, QVideoWidgetControl_iid) == 0) { + if (m_viewFinderWidget) { + return m_viewFinderWidget; + } + } + + if(qstrcmp(name,QVideoRendererControl_iid) == 0) + return m_videoRenderer; + + if(qstrcmp(name,QVideoDeviceControl_iid) == 0) + return m_videoDevice; + + return 0; +} + +void DSCameraService::releaseControl(QMediaControl *control) +{ + // Implemented as a singleton, so we do nothing. +} + +QT_END_NAMESPACE diff --git a/plugins/multimedia/directshow/camera/dscameraservice.h b/plugins/multimedia/directshow/camera/dscameraservice.h new file mode 100644 index 0000000000..e8a9450fb9 --- /dev/null +++ b/plugins/multimedia/directshow/camera/dscameraservice.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DSCAMERASERVICE_H +#define DSCAMERASERVICE_H + +#include <QtCore/qobject.h> + +#include <qmediaservice.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class DSCameraControl; +class DSCameraSession; +class DSVideoOutputControl; +class DSVideoDeviceControl; +class DSVideoRendererControl; +class DSImageCaptureControl; +class DSVideoWidgetControl; + + +class DSCameraService : public QMediaService +{ + Q_OBJECT + +public: + DSCameraService(QObject *parent = 0); + ~DSCameraService(); + + virtual QMediaControl* requestControl(const char *name); + virtual void releaseControl(QMediaControl *control); + +private: + DSCameraControl *m_control; + DSCameraSession *m_session; + DSVideoOutputControl *m_videoOutput; + DSVideoWidgetControl *m_viewFinderWidget; + DSVideoDeviceControl *m_videoDevice; + DSVideoRendererControl *m_videoRenderer; + DSImageCaptureControl *m_imageCapture; + QByteArray m_device; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/plugins/multimedia/directshow/camera/dscamerasession.cpp b/plugins/multimedia/directshow/camera/dscamerasession.cpp new file mode 100644 index 0000000000..a08fb318ff --- /dev/null +++ b/plugins/multimedia/directshow/camera/dscamerasession.cpp @@ -0,0 +1,1160 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/qdebug.h> +#include <QWidget> +#include <QFile> +#include <QtMultimedia/qabstractvideobuffer.h> +#include <QtMultimedia/qvideosurfaceformat.h> + +#include "dscamerasession.h" +#include "dsvideorenderer.h" +#include "directshowglobal.h" + +QT_BEGIN_NAMESPACE + +// If frames come in quicker than we display them, we allow the queue to build +// up to this number before we start dropping them. +const int LIMIT_FRAME = 5; + +namespace { +// DirectShow helper implementation +void _FreeMediaType(AM_MEDIA_TYPE& mt) +{ + if (mt.cbFormat != 0) { + CoTaskMemFree((PVOID)mt.pbFormat); + mt.cbFormat = 0; + mt.pbFormat = NULL; + } + if (mt.pUnk != NULL) { + // pUnk should not be used. + mt.pUnk->Release(); + mt.pUnk = NULL; + } +} + +} // end namespace + +class SampleGrabberCallbackPrivate : public ISampleGrabberCB +{ +public: + STDMETHODIMP_(ULONG) AddRef() { return 1; } + STDMETHODIMP_(ULONG) Release() { return 2; } + + STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) + { + if (NULL == ppvObject) + return E_POINTER; + if (riid == IID_IUnknown /*__uuidof(IUnknown) */ ) { + *ppvObject = static_cast<IUnknown*>(this); + return S_OK; + } + if (riid == IID_ISampleGrabberCB /*__uuidof(ISampleGrabberCB)*/ ) { + *ppvObject = static_cast<ISampleGrabberCB*>(this); + return S_OK; + } + return E_NOTIMPL; + } + + STDMETHODIMP SampleCB(double Time, IMediaSample *pSample) + { + return E_NOTIMPL; + } + + STDMETHODIMP BufferCB(double Time, BYTE *pBuffer, long BufferLen) + { + if (!cs || active) { + return S_OK; + } + + if ((cs->StillMediaType.majortype != MEDIATYPE_Video) || + (cs->StillMediaType.formattype != FORMAT_VideoInfo) || + (cs->StillMediaType.cbFormat < sizeof(VIDEOINFOHEADER))) { + return VFW_E_INVALIDMEDIATYPE; + } + + active = true; + + if(toggle == true) { + toggle = false; + } + else { + toggle = true; + } + + if(toggle) { + active = false; + return S_OK; + } + + bool check = false; + cs->mutex.lock(); + + if (cs->frames.size() > LIMIT_FRAME) { + check = true; + } + + if (check) { + cs->mutex.unlock(); + // Frames building up. We're going to drop some here + Sleep(100); + active = false; + return S_OK; + } + cs->mutex.unlock(); + + unsigned char* vidData = new unsigned char[BufferLen]; + memcpy(vidData, pBuffer, BufferLen); + + cs->mutex.lock(); + + video_buffer* buf = new video_buffer; + buf->buffer = vidData; + buf->length = BufferLen; + buf->time = (qint64)Time; + + cs->frames.append(buf); + + cs->mutex.unlock(); + + QMetaObject::invokeMethod(cs, "captureFrame", Qt::QueuedConnection); + + active = false; + + return S_OK; + } + + DSCameraSession* cs; + bool active; + bool toggle; +}; + + +DSCameraSession::DSCameraSession(QObject *parent) + : QObject(parent) + ,m_currentImageId(0) +{ + pBuild = NULL; + pGraph = NULL; + pCap = NULL; + pSG_Filter = NULL; + pSG = NULL; + + opened = false; + available = false; + resolutions.clear(); + m_state = QCamera::UnloadedState; + m_device = "default"; + + StillCapCB = new SampleGrabberCallbackPrivate; + StillCapCB->cs = this; + StillCapCB->active = false; + StillCapCB->toggle = false; + + m_output = 0; + m_surface = 0; + m_windowSize = QSize(320,240); + pixelF = QVideoFrame::Format_RGB24; + actualFormat = QVideoSurfaceFormat(m_windowSize,pixelF); + + graph = false; + active = false; + + ::CoInitialize(NULL); +} + +DSCameraSession::~DSCameraSession() +{ + if (opened) { + closeStream(); + } + + CoUninitialize(); + + SAFE_RELEASE(pCap); + SAFE_RELEASE(pSG_Filter); + SAFE_RELEASE(pGraph); + SAFE_RELEASE(pBuild); + + if (StillCapCB) { + delete StillCapCB; + } +} + +int DSCameraSession::captureImage(const QString &fileName) +{ + emit readyForCaptureChanged(false); + + // We're going to do this in one big synchronous call + m_currentImageId++; + if (fileName.isEmpty()) { + m_snapshot = "img.jpg"; + } else { + m_snapshot = fileName; + } + + if (!active) { + startStream(); + } + + return m_currentImageId; +} + +void DSCameraSession::setSurface(QAbstractVideoSurface* surface) +{ + m_surface = surface; +} + +bool DSCameraSession::deviceReady() +{ + return available; +} + +bool DSCameraSession::pictureInProgress() +{ + return m_snapshot.isEmpty(); +} + +int DSCameraSession::framerate() const +{ + return -1; +} + +void DSCameraSession::setFrameRate(int rate) +{ + Q_UNUSED(rate) +} + +int DSCameraSession::brightness() const +{ + return -1; +} + +void DSCameraSession::setBrightness(int b) +{ + Q_UNUSED(b) +} + +int DSCameraSession::contrast() const +{ + return -1; +} + +void DSCameraSession::setContrast(int c) +{ + Q_UNUSED(c) +} + +int DSCameraSession::saturation() const +{ + return -1; +} + +void DSCameraSession::setSaturation(int s) +{ + Q_UNUSED(s) +} + +int DSCameraSession::hue() const +{ + return -1; +} + +void DSCameraSession::setHue(int h) +{ + Q_UNUSED(h) +} + +int DSCameraSession::sharpness() const +{ + return -1; +} + +void DSCameraSession::setSharpness(int s) +{ + Q_UNUSED(s) +} + +int DSCameraSession::zoom() const +{ + return -1; +} + +void DSCameraSession::setZoom(int z) +{ + Q_UNUSED(z) +} + +bool DSCameraSession::backlightCompensation() const +{ + return false; +} + +void DSCameraSession::setBacklightCompensation(bool b) +{ + Q_UNUSED(b) +} + +int DSCameraSession::whitelevel() const +{ + return -1; +} + +void DSCameraSession::setWhitelevel(int w) +{ + Q_UNUSED(w) +} + +int DSCameraSession::rotation() const +{ + return 0; +} + +void DSCameraSession::setRotation(int r) +{ + Q_UNUSED(r) +} + +bool DSCameraSession::flash() const +{ + return false; +} + +void DSCameraSession::setFlash(bool f) +{ + Q_UNUSED(f) +} + +bool DSCameraSession::autofocus() const +{ + return false; +} + +void DSCameraSession::setAutofocus(bool f) +{ + Q_UNUSED(f) +} + +QSize DSCameraSession::frameSize() const +{ + return m_windowSize; +} + +void DSCameraSession::setFrameSize(const QSize& s) +{ + if (supportedResolutions(pixelF).contains(s)) + m_windowSize = s; + else + qWarning() << "frame size if not supported for current pixel format, no change"; +} + +void DSCameraSession::setDevice(const QString &device) +{ + if(opened) + stopStream(); + + if(graph) { + SAFE_RELEASE(pCap); + SAFE_RELEASE(pSG_Filter); + SAFE_RELEASE(pGraph); + SAFE_RELEASE(pBuild); + } + + available = false; + m_state = QCamera::LoadedState; + + CoInitialize(NULL); + + ICreateDevEnum* pDevEnum = NULL; + IEnumMoniker* pEnum = NULL; + + // Create the System device enumerator + HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, + CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, + reinterpret_cast<void**>(&pDevEnum)); + if(SUCCEEDED(hr)) { + // Create the enumerator for the video capture category + hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0); + if (S_OK == hr) { + pEnum->Reset(); + // go through and find all video capture devices + IMoniker* pMoniker = NULL; + while(pEnum->Next(1, &pMoniker, NULL) == S_OK) { + IPropertyBag *pPropBag; + hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, + (void**)(&pPropBag)); + if(FAILED(hr)) { + pMoniker->Release(); + continue; // skip this one + } + // Find the description + WCHAR str[120]; + VARIANT varName; + varName.vt = VT_BSTR; + hr = pPropBag->Read(L"Description", &varName, 0); + if(FAILED(hr)) + hr = pPropBag->Read(L"FriendlyName", &varName, 0); + if(SUCCEEDED(hr)) { + wcsncpy(str, varName.bstrVal, sizeof(str)/sizeof(str[0])); + QString temp(QString::fromUtf16((unsigned short*)str)); + if(temp.contains(device)) { + available = true; + } + } + pPropBag->Release(); + pMoniker->Release(); + } + pEnum->Release(); + } + pDevEnum->Release(); + } + CoUninitialize(); + + if(available) { + m_device = QByteArray(device.toLocal8Bit().constData()); + graph = createFilterGraph(); + if(!graph) + available = false; + } +} + +QList<QVideoFrame::PixelFormat> DSCameraSession::supportedPixelFormats() +{ + return types; +} + +QVideoFrame::PixelFormat DSCameraSession::pixelFormat() const +{ + return pixelF; +} + +void DSCameraSession::setPixelFormat(QVideoFrame::PixelFormat fmt) +{ + pixelF = fmt; +} + +QList<QSize> DSCameraSession::supportedResolutions(QVideoFrame::PixelFormat format) +{ + if (!resolutions.contains(format)) + return QList<QSize>(); + return resolutions.value(format); +} + +bool DSCameraSession::setOutputLocation(const QUrl &sink) +{ + m_sink = sink; + + return true; +} + +QUrl DSCameraSession::outputLocation() const +{ + return m_sink; +} + +qint64 DSCameraSession::position() const +{ + return timeStamp.elapsed(); +} + +int DSCameraSession::state() const +{ + return int(m_state); +} + +void DSCameraSession::record() +{ + if(opened) { + return; + } + + if(m_surface) { + bool match = false; + + if (!m_surface->isFormatSupported(actualFormat)) { + QList<QVideoFrame::PixelFormat> fmts; + foreach(QVideoFrame::PixelFormat f, types) { + if (fmts.contains(f)) { + match = true; + pixelF = f; + actualFormat = QVideoSurfaceFormat(m_windowSize,pixelF); + break; + } + } + } + if (!m_surface->isFormatSupported(actualFormat) && !match) { + // fallback + if (types.contains(QVideoFrame::Format_RGB24)) { + // get RGB24 from camera and convert to RGB32 for surface! + pixelF = QVideoFrame::Format_RGB32; + actualFormat = QVideoSurfaceFormat(m_windowSize,pixelF); + } + } + + if (m_surface->isFormatSupported(actualFormat)) { + m_surface->start(actualFormat); + m_state = QCamera::ActiveState; + emit stateChanged(QCamera::ActiveState); + } else { + qWarning() << "surface doesn't support camera format, cant start"; + m_state = QCamera::LoadedState; + emit stateChanged(QCamera::LoadedState); + return; + } + } else { + qWarning() << "no video surface, cant start"; + m_state = QCamera::LoadedState; + emit stateChanged(QCamera::LoadedState); + return; + } + + opened = startStream(); + + if (!opened) { + qWarning() << "Stream did not open"; + m_state = QCamera::LoadedState; + emit stateChanged(QCamera::LoadedState); + } +} + +void DSCameraSession::pause() +{ + suspendStream(); +} + +void DSCameraSession::stop() +{ + if(!opened) { + return; + } + + stopStream(); + opened = false; + m_state = QCamera::LoadedState; + emit stateChanged(QCamera::LoadedState); +} + +void DSCameraSession::captureFrame() +{ + if(m_surface && frames.count() > 0) { + + QImage image; + + if(pixelF == QVideoFrame::Format_RGB24) { + + mutex.lock(); + + image = QImage(frames.at(0)->buffer,m_windowSize.width(),m_windowSize.height(), + QImage::Format_RGB888).rgbSwapped().mirrored(true); + + QVideoFrame frame(image); + frame.setStartTime(frames.at(0)->time); + + mutex.unlock(); + + m_surface->present(frame); + + } else if (pixelF == QVideoFrame::Format_RGB32) { + + mutex.lock(); + + image = QImage(frames.at(0)->buffer,m_windowSize.width(),m_windowSize.height(), + QImage::Format_RGB888).rgbSwapped().mirrored(true); + + QVideoFrame frame(image.convertToFormat(QImage::Format_RGB32)); + frame.setStartTime(frames.at(0)->time); + + mutex.unlock(); + + m_surface->present(frame); + + } else { + qWarning() << "TODO:captureFrame() format =" << pixelF; + } + + if (m_snapshot.length() > 0) { + emit imageCaptured(m_currentImageId, image); + image.save(m_snapshot,"JPG"); + emit imageSaved(m_currentImageId, m_snapshot); + m_snapshot.clear(); + emit readyForCaptureChanged(true); + } + + mutex.lock(); + if (frames.isEmpty()) { + qWarning() << "Frames over-run"; + } + + video_buffer* buf = frames.takeFirst(); + delete buf->buffer; + delete buf; + mutex.unlock(); + } +} + +HRESULT DSCameraSession::getPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin **ppPin) +{ + *ppPin = 0; + IEnumPins *pEnum = 0; + IPin *pPin = 0; + + HRESULT hr = pFilter->EnumPins(&pEnum); + if(FAILED(hr)) { + return hr; + } + + pEnum->Reset(); + while(pEnum->Next(1, &pPin, NULL) == S_OK) { + PIN_DIRECTION ThisPinDir; + pPin->QueryDirection(&ThisPinDir); + if(ThisPinDir == PinDir) { + pEnum->Release(); + *ppPin = pPin; + return S_OK; + } + pEnum->Release(); + } + pEnum->Release(); + return E_FAIL; +} + +bool DSCameraSession::createFilterGraph() +{ + HRESULT hr; + IMoniker* pMoniker = NULL; + ICreateDevEnum* pDevEnum = NULL; + IEnumMoniker* pEnum = NULL; + + CoInitialize(NULL); + + // Create the filter graph + hr = CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC, + IID_IGraphBuilder, (void**)&pGraph); + if (FAILED(hr)) { + qWarning()<<"failed to create filter graph"; + return false; + } + + // Create the capture graph builder + hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC, + IID_ICaptureGraphBuilder2, (void**)&pBuild); + if (FAILED(hr)) { + qWarning()<<"failed to create graph builder"; + return false; + } + + // Attach the filter graph to the capture graph + hr = pBuild->SetFiltergraph(pGraph); + if (FAILED(hr)) { + qWarning()<<"failed to connect capture graph and filter graph"; + return false; + } + + // Find the Capture device + hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, + CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, + reinterpret_cast<void**>(&pDevEnum)); + if (SUCCEEDED(hr)) { + // Create an enumerator for the video capture category + hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0); + pDevEnum->Release(); + if (S_OK == hr) { + pEnum->Reset(); + //go through and find all video capture devices + while (pEnum->Next(1, &pMoniker, NULL) == S_OK) { + IPropertyBag *pPropBag; + hr = pMoniker->BindToStorage(0, 0, + IID_IPropertyBag, (void**)(&pPropBag)); + if(FAILED(hr)) { + pMoniker->Release(); + continue; // skip this one + } + // Find the description + WCHAR str[120]; + VARIANT varName; + varName.vt = VT_BSTR; + hr = pPropBag->Read(L"FriendlyName", &varName, 0); + if (SUCCEEDED(hr)) { + // check if it is the selected device + wcsncpy(str, varName.bstrVal, sizeof(str)/sizeof(str[0])); + QString output = QString::fromUtf16((unsigned short*)str); + if (m_device.contains(output.toLocal8Bit().constData())) { + hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap); + if (SUCCEEDED(hr)) { + pPropBag->Release(); + pMoniker->Release(); + break; + } + } + } + pPropBag->Release(); + pMoniker->Release(); + } + if (NULL == pCap) + { + if (m_device.contains("default")) + { + pEnum->Reset(); + // still have to loop to discard bind to storage failure case + while (pEnum->Next(1, &pMoniker, NULL) == S_OK) { + IPropertyBag *pPropBag = 0; + + hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)(&pPropBag)); + if (FAILED(hr)) { + pMoniker->Release(); + continue; // Don't panic yet + } + + // No need to get the description, just grab it + + hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap); + pPropBag->Release(); + pMoniker->Release(); + if (SUCCEEDED(hr)) { + break; // done, stop looping through + } + else + { + qWarning() << "Object bind failed"; + } + } + } + } + pEnum->Release(); + } + } + + // Sample grabber filter + hr = CoCreateInstance(CLSID_SampleGrabber, NULL,CLSCTX_INPROC, + IID_IBaseFilter, (void**)&pSG_Filter); + if (FAILED(hr)) { + qWarning() << "failed to create sample grabber"; + return false; + } + + pSG_Filter->QueryInterface(IID_ISampleGrabber, (void**)&pSG); + if (FAILED(hr)) { + qWarning() << "failed to get sample grabber"; + return false; + } + pSG->SetOneShot(FALSE); + pSG->SetBufferSamples(TRUE); + pSG->SetCallback(StillCapCB, 1); + + CoUninitialize(); + + return true; +} + +void DSCameraSession::updateProperties() +{ + HRESULT hr; + AM_MEDIA_TYPE *pmt = NULL; + VIDEOINFOHEADER *pvi = NULL; + VIDEO_STREAM_CONFIG_CAPS scc; + IAMStreamConfig* pConfig = 0; + + hr = pBuild->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,pCap, + IID_IAMStreamConfig, (void**)&pConfig); + if (FAILED(hr)) { + qWarning()<<"failed to get config on capture device"; + return; + } + + int iCount; + int iSize; + hr = pConfig->GetNumberOfCapabilities(&iCount, &iSize); + if (FAILED(hr)) { + qWarning()<<"failed to get capabilities"; + return; + } + + QList<QSize> sizes; + QVideoFrame::PixelFormat f = QVideoFrame::Format_Invalid; + + types.clear(); + resolutions.clear(); + + for (int iIndex = 0; iIndex < iCount; iIndex++) { + hr = pConfig->GetStreamCaps(iIndex, &pmt, reinterpret_cast<BYTE*>(&scc)); + if (hr == S_OK) { + pvi = (VIDEOINFOHEADER*)pmt->pbFormat; + if ((pmt->majortype == MEDIATYPE_Video) && + (pmt->formattype == FORMAT_VideoInfo)) { + // Add types + if (pmt->subtype == MEDIASUBTYPE_RGB24) { + if (!types.contains(QVideoFrame::Format_RGB24)) { + types.append(QVideoFrame::Format_RGB24); + f = QVideoFrame::Format_RGB24; + } + } else if (pmt->subtype == MEDIASUBTYPE_RGB32) { + if (!types.contains(QVideoFrame::Format_RGB32)) { + types.append(QVideoFrame::Format_RGB32); + f = QVideoFrame::Format_RGB32; + } + } else if (pmt->subtype == MEDIASUBTYPE_YUY2) { + if (!types.contains(QVideoFrame::Format_YUYV)) { + types.append(QVideoFrame::Format_YUYV); + f = QVideoFrame::Format_YUYV; + } + } else if (pmt->subtype == MEDIASUBTYPE_MJPG) { + } else if (pmt->subtype == MEDIASUBTYPE_I420) { + if (!types.contains(QVideoFrame::Format_YUV420P)) { + types.append(QVideoFrame::Format_YUV420P); + f = QVideoFrame::Format_YUV420P; + } + } else if (pmt->subtype == MEDIASUBTYPE_RGB555) { + if (!types.contains(QVideoFrame::Format_RGB555)) { + types.append(QVideoFrame::Format_RGB555); + f = QVideoFrame::Format_RGB555; + } + } else if (pmt->subtype == MEDIASUBTYPE_YVU9) { + } else if (pmt->subtype == MEDIASUBTYPE_UYVY) { + if (!types.contains(QVideoFrame::Format_UYVY)) { + types.append(QVideoFrame::Format_UYVY); + f = QVideoFrame::Format_UYVY; + } + } else { + qWarning() << "UNKNOWN FORMAT: " << pmt->subtype.Data1; + } + // Add resolutions + QSize res(pvi->bmiHeader.biWidth, pvi->bmiHeader.biHeight); + if (!resolutions.contains(f)) { + sizes.clear(); + resolutions.insert(f,sizes); + } + resolutions[f].append(res); + } + } + } + pConfig->Release(); +} + +bool DSCameraSession::setProperties() +{ + CoInitialize(NULL); + + HRESULT hr; + AM_MEDIA_TYPE am_media_type; + AM_MEDIA_TYPE *pmt = NULL; + VIDEOINFOHEADER *pvi = NULL; + VIDEO_STREAM_CONFIG_CAPS scc; + + IAMStreamConfig* pConfig = 0; + hr = pBuild->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pCap, + IID_IAMStreamConfig, (void**)&pConfig); + if(FAILED(hr)) { + qWarning()<<"failed to get config on capture device"; + return false; + } + + int iCount; + int iSize; + hr = pConfig->GetNumberOfCapabilities(&iCount, &iSize); + if(FAILED(hr)) { + qWarning()<<"failed to get capabilities"; + return false; + } + + bool setFormatOK = false; + for (int iIndex = 0; iIndex < iCount; iIndex++) { + hr = pConfig->GetStreamCaps(iIndex, &pmt, reinterpret_cast<BYTE*>(&scc)); + if (hr == S_OK) { + pvi = (VIDEOINFOHEADER*)pmt->pbFormat; + + if ((pmt->majortype == MEDIATYPE_Video) && + (pmt->formattype == FORMAT_VideoInfo)) { + if ((actualFormat.frameWidth() == pvi->bmiHeader.biWidth) && + (actualFormat.frameHeight() == pvi->bmiHeader.biHeight)) { + hr = pConfig->SetFormat(pmt); + _FreeMediaType(*pmt); + if(FAILED(hr)) { + qWarning()<<"failed to set format:" << hr; + qWarning()<<"but going to continue"; + continue; // We going to continue + } else { + setFormatOK = true; + break; + } + } + } + } + } + pConfig->Release(); + + if (!setFormatOK) { + qWarning() << "unable to set any format for camera"; + return false; + } + + // Set Sample Grabber config to match capture + ZeroMemory(&am_media_type, sizeof(am_media_type)); + am_media_type.majortype = MEDIATYPE_Video; + + if (actualFormat.pixelFormat() == QVideoFrame::Format_RGB32) + am_media_type.subtype = MEDIASUBTYPE_RGB24; + else if (actualFormat.pixelFormat() == QVideoFrame::Format_RGB24) + am_media_type.subtype = MEDIASUBTYPE_RGB24; + else if (actualFormat.pixelFormat() == QVideoFrame::Format_YUYV) + am_media_type.subtype = MEDIASUBTYPE_YUY2; + else if (actualFormat.pixelFormat() == QVideoFrame::Format_YUV420P) + am_media_type.subtype = MEDIASUBTYPE_I420; + else if (actualFormat.pixelFormat() == QVideoFrame::Format_RGB555) + am_media_type.subtype = MEDIASUBTYPE_RGB555; + else if (actualFormat.pixelFormat() == QVideoFrame::Format_UYVY) + am_media_type.subtype = MEDIASUBTYPE_UYVY; + else { + qWarning()<<"unknown format? for SG"; + return false; + } + + am_media_type.formattype = FORMAT_VideoInfo; + hr = pSG->SetMediaType(&am_media_type); + if (FAILED(hr)) { + qWarning()<<"failed to set video format on grabber"; + return false; + } + + pSG->GetConnectedMediaType(&StillMediaType); + + CoUninitialize(); + + return true; +} + +bool DSCameraSession::openStream() +{ + //Opens the stream for reading and allocates any necessary resources needed + //Return true if success, false otherwise + + if (opened) { + return true; + } + + if (!graph) { + graph = createFilterGraph(); + if(!graph) { + qWarning()<<"failed to create filter graph in openStream"; + return false; + } + } + + CoInitialize(NULL); + + HRESULT hr; + + hr = pGraph->AddFilter(pCap, L"Capture Filter"); + if (FAILED(hr)) { + qWarning()<<"failed to create capture filter"; + return false; + } + + hr = pGraph->AddFilter(pSG_Filter, L"Sample Grabber"); + if (FAILED(hr)) { + qWarning()<<"failed to add sample grabber"; + return false; + } + + hr = pBuild->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, + pCap, NULL, pSG_Filter); + if (FAILED(hr)) { + qWarning() << "failed to renderstream" << hr; + return false; + } + pSG->GetConnectedMediaType(&StillMediaType); + pSG_Filter->Release(); + + CoUninitialize(); + + return true; +} + +void DSCameraSession::closeStream() +{ + // Closes the stream and internally frees any resources used + HRESULT hr; + IMediaControl* pControl = 0; + + hr = pGraph->QueryInterface(IID_IMediaControl,(void**)&pControl); + if (FAILED(hr)) { + qWarning()<<"failed to get stream control"; + return; + } + + hr = pControl->StopWhenReady(); + if (FAILED(hr)) { + qWarning()<<"failed to stop"; + pControl->Release(); + return; + } + + pControl->Release(); + + opened = false; + IPin *pPin = 0; + + if (pCap) + { + hr = getPin(pCap, PINDIR_OUTPUT, &pPin); + if(FAILED(hr)) { + qWarning()<<"failed to disconnect capture filter"; + return; + } + } + + pGraph->Disconnect(pPin); + if (FAILED(hr)) { + qWarning()<<"failed to disconnect grabber filter"; + return; + } + + hr = getPin(pSG_Filter,PINDIR_INPUT,&pPin); + pGraph->Disconnect(pPin); + pGraph->RemoveFilter(pSG_Filter); + pGraph->RemoveFilter(pCap); + + SAFE_RELEASE(pCap); + SAFE_RELEASE(pSG_Filter); + SAFE_RELEASE(pGraph); + SAFE_RELEASE(pBuild); + + graph = false; +} + +bool DSCameraSession::startStream() +{ + // Starts the stream, by emitting either QVideoPackets + // or QvideoFrames, depending on Format chosen + if (!graph) + graph = createFilterGraph(); + + if (!setProperties()) { + qWarning() << "Couldn't set properties (retrying)"; + closeStream(); + if (!openStream()) { + qWarning() << "Retry to open strean failed"; + return false; + } + } + + if (!opened) { + opened = openStream(); + if (!opened) { + qWarning() << "failed to openStream()"; + return false; + } + } + + HRESULT hr; + IMediaControl* pControl = 0; + + hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl); + if (FAILED(hr)) { + qWarning() << "failed to get stream control"; + return false; + } + + hr = pControl->Run(); + pControl->Release(); + + if (FAILED(hr)) { + qWarning() << "failed to start"; + return false; + } + active = true; + return true; +} + +void DSCameraSession::stopStream() +{ + // Stops the stream from emitting packets + HRESULT hr; + + IMediaControl* pControl = 0; + hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl); + if (FAILED(hr)) { + qWarning() << "failed to get stream control"; + return; + } + + hr = pControl->Stop(); + pControl->Release(); + if (FAILED(hr)) { + qWarning() << "failed to stop"; + return; + } + active = false; + + if (opened) { + closeStream(); + } +} + +void DSCameraSession::suspendStream() +{ + // Pauses the stream + HRESULT hr; + + IMediaControl* pControl = 0; + hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl); + if (FAILED(hr)) { + qWarning() << "failed to get stream control"; + return; + } + + hr = pControl->Pause(); + pControl->Release(); + if (FAILED(hr)) { + qWarning() << "failed to pause"; + return; + } + + active = false; +} + +void DSCameraSession::resumeStream() +{ + // Resumes a paused stream + startStream(); +} + +QT_END_NAMESPACE + diff --git a/plugins/multimedia/directshow/camera/dscamerasession.h b/plugins/multimedia/directshow/camera/dscamerasession.h new file mode 100644 index 0000000000..72a0e5077e --- /dev/null +++ b/plugins/multimedia/directshow/camera/dscamerasession.h @@ -0,0 +1,208 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DSCAMERASESSION_H +#define DSCAMERASESSION_H + +#include <QtCore/qobject.h> +#include <QTime> +#include <QUrl> +#include <QMutex> + +#include <qcamera.h> +#include <QtMultimedia/qvideoframe.h> +#include <QtMultimedia/qabstractvideosurface.h> +#include <QtMultimedia/qvideosurfaceformat.h> + +#include <tchar.h> +#include <dshow.h> +#include <objbase.h> +#include <initguid.h> +#pragma comment(lib, "strmiids.lib") +#pragma comment(lib, "ole32.lib") +#include <windows.h> + +#pragma include_alias("dxtrans.h","qedit.h") +#define __IDxtCompositor_INTERFACE_DEFINED__ +#define __IDxtAlphaSetter_INTERFACE_DEFINED__ +#define __IDxtJpeg_INTERFACE_DEFINED__ +#define __IDxtKey_INTERFACE_DEFINED__ +#include <qedit.h> + +struct ICaptureGraphBuilder2; +struct ISampleGrabber; + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class DSVideoRenderer; +class SampleGrabberCallbackPrivate; + + +struct video_buffer { + unsigned char* buffer; + int length; + qint64 time; +}; + +typedef QMap<unsigned int, QList<QSize> > FormatResolutionMap; + +class DSCameraSession : public QObject +{ + Q_OBJECT +public: + DSCameraSession(QObject *parent = 0); + ~DSCameraSession(); + + bool deviceReady(); + bool pictureInProgress(); + + // camera controls + + int framerate() const; + void setFrameRate(int rate); + int brightness() const; + void setBrightness(int b); + int contrast() const; + void setContrast(int c); + int saturation() const; + void setSaturation(int s); + int hue() const; + void setHue(int h); + int sharpness() const; + void setSharpness(int s); + int zoom() const; + void setZoom(int z); + bool backlightCompensation() const; + void setBacklightCompensation(bool); + int whitelevel() const; + void setWhitelevel(int w); + int rotation() const; + void setRotation(int r); + bool flash() const; + void setFlash(bool f); + bool autofocus() const; + void setAutofocus(bool f); + + QSize frameSize() const; + void setFrameSize(const QSize& s); + void setDevice(const QString &device); + QList<QVideoFrame::PixelFormat> supportedPixelFormats(); + QVideoFrame::PixelFormat pixelFormat() const; + void setPixelFormat(QVideoFrame::PixelFormat fmt); + QList<QSize> supportedResolutions(QVideoFrame::PixelFormat format); + + // media control + + bool setOutputLocation(const QUrl &sink); + QUrl outputLocation() const; + qint64 position() const; + int state() const; + void record(); + void pause(); + void stop(); + + void setSurface(QAbstractVideoSurface* surface); + + int captureImage(const QString &fileName); + + AM_MEDIA_TYPE StillMediaType; + QList<video_buffer*> frames; + SampleGrabberCallbackPrivate* StillCapCB; + + QMutex mutex; + +Q_SIGNALS: + void stateChanged(QCamera::State); + void imageCaptured(int id, const QImage &preview); + void imageSaved(int id, const QString &fileName); + void readyForCaptureChanged(bool); + +private Q_SLOTS: + void captureFrame(); + +private: + QVideoSurfaceFormat actualFormat; + QList<QVideoFrame::PixelFormat> types; + + QTime timeStamp; + bool graph; + bool active; + bool opened; + bool available; + QCamera::State m_state; + QByteArray m_device; + QUrl m_sink; + DSVideoRenderer* m_output; + QAbstractVideoSurface* m_surface; + QVideoFrame::PixelFormat pixelF; + QSize m_windowSize; + FormatResolutionMap resolutions; + + ICaptureGraphBuilder2* pBuild; + IGraphBuilder* pGraph; + IBaseFilter* pCap; + IBaseFilter* pSG_Filter; + ISampleGrabber *pSG; + + + QString m_snapshot; + int m_currentImageId; +protected: + HRESULT getPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin **ppPin); + bool createFilterGraph(); + void updateProperties(); + bool setProperties(); + bool openStream(); + void closeStream(); + bool startStream(); + void stopStream(); + void suspendStream(); + void resumeStream(); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + + +#endif diff --git a/plugins/multimedia/directshow/camera/dsimagecapturecontrol.cpp b/plugins/multimedia/directshow/camera/dsimagecapturecontrol.cpp new file mode 100644 index 0000000000..17654c4a53 --- /dev/null +++ b/plugins/multimedia/directshow/camera/dsimagecapturecontrol.cpp @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/QDebug> + +#include "dsimagecapturecontrol.h" + +QT_BEGIN_NAMESPACE + +DSImageCaptureControl::DSImageCaptureControl(DSCameraSession *session) + :QCameraImageCaptureControl(session), m_session(session), m_ready(false) +{ + connect(m_session, SIGNAL(stateChanged(QCamera::State)), SLOT(updateState())); + connect(m_session, SIGNAL(imageCaptured(const int, QImage)), + this, SIGNAL(imageCaptured(const int, QImage))); + connect(m_session, SIGNAL(imageSaved(const int, const QString &)), + this, SIGNAL(imageSaved(const int, const QString &))); + connect(m_session, SIGNAL(readyForCaptureChanged(bool)), + this, SIGNAL(readyForCaptureChanged(bool))); +} + +DSImageCaptureControl::~DSImageCaptureControl() +{ +} + +bool DSImageCaptureControl::isReadyForCapture() const +{ + return m_ready; +} + +int DSImageCaptureControl::capture(const QString &fileName) +{ + return m_session->captureImage(fileName); +} + +void DSImageCaptureControl::updateState() +{ + bool ready = (m_session->state() == QCamera::ActiveState) && + !m_session->pictureInProgress(); + if(m_ready != ready) + emit readyForCaptureChanged(m_ready = ready); +} + +QT_END_NAMESPACE + diff --git a/plugins/multimedia/directshow/camera/dsimagecapturecontrol.h b/plugins/multimedia/directshow/camera/dsimagecapturecontrol.h new file mode 100644 index 0000000000..8eca7b4e70 --- /dev/null +++ b/plugins/multimedia/directshow/camera/dsimagecapturecontrol.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DSIMAGECAPTURECONTROL_H +#define DSIMAGECAPTURECONTROL_H + +#include <qcameraimagecapturecontrol.h> +#include "dscamerasession.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class DSImageCaptureControl : public QCameraImageCaptureControl +{ + Q_OBJECT +public: + DSImageCaptureControl(DSCameraSession *session); + virtual ~DSImageCaptureControl(); + + bool isReadyForCapture() const; + int capture(const QString &fileName); + + virtual QCameraImageCapture::DriveMode driveMode() const { return QCameraImageCapture::SingleImageCapture; } + virtual void setDriveMode(QCameraImageCapture::DriveMode mode) { } + + virtual void cancelCapture() {} + +private slots: + void updateState(); + + +private: + DSCameraSession *m_session; + bool m_ready; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // DSCAPTURECONTROL_H diff --git a/plugins/multimedia/directshow/camera/dsvideodevicecontrol.cpp b/plugins/multimedia/directshow/camera/dsvideodevicecontrol.cpp new file mode 100644 index 0000000000..8c9b030003 --- /dev/null +++ b/plugins/multimedia/directshow/camera/dsvideodevicecontrol.cpp @@ -0,0 +1,168 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QDebug> +#include <QFile> +#include <QtGui/QIcon> + +#include "dsvideodevicecontrol.h" +#include "dscamerasession.h" + +#include <tchar.h> +#include <dshow.h> +#include <objbase.h> +#include <initguid.h> +#include <Ocidl.h> +#include <string.h> + +extern const CLSID CLSID_VideoInputDeviceCategory; + +QT_BEGIN_NAMESPACE + +DSVideoDeviceControl::DSVideoDeviceControl(QObject *parent) + : QVideoDeviceControl(parent) +{ + m_session = qobject_cast<DSCameraSession*>(parent); + + devices.clear(); + descriptions.clear(); + + CoInitialize(NULL); + ICreateDevEnum* pDevEnum = NULL; + IEnumMoniker* pEnum = NULL; + // Create the System device enumerator + HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, + CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, + reinterpret_cast<void**>(&pDevEnum)); + if(SUCCEEDED(hr)) { + // Create the enumerator for the video capture category + hr = pDevEnum->CreateClassEnumerator( + CLSID_VideoInputDeviceCategory, &pEnum, 0); + if (S_OK == hr) { + pEnum->Reset(); + // go through and find all video capture devices + IMoniker* pMoniker = NULL; + while(pEnum->Next(1, &pMoniker, NULL) == S_OK) { + IPropertyBag *pPropBag; + hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, + (void**)(&pPropBag)); + if(FAILED(hr)) { + pMoniker->Release(); + continue; // skip this one + } + // Find the description + WCHAR str[120]; + VARIANT varName; + varName.vt = VT_BSTR; + hr = pPropBag->Read(L"FriendlyName", &varName, 0); + if(SUCCEEDED(hr)) { + wcsncpy(str, varName.bstrVal, sizeof(str)/sizeof(str[0])); + QString temp(QString::fromUtf16((unsigned short*)str)); + devices.append(QString("ds:%1").arg(temp).toLocal8Bit().constData()); + hr = pPropBag->Read(L"Description", &varName, 0); + wcsncpy(str, varName.bstrVal, sizeof(str)/sizeof(str[0])); + QString temp2(QString::fromUtf16((unsigned short*)str)); + descriptions.append(temp2.toLocal8Bit().constData()); + } + pPropBag->Release(); + pMoniker->Release(); + } + pEnum->Release(); + } + pDevEnum->Release(); + } + CoUninitialize(); + + selected = 0; +} + +int DSVideoDeviceControl::deviceCount() const +{ + return devices.count(); +} + +QString DSVideoDeviceControl::deviceName(int index) const +{ + if(index >= 0 && index <= devices.count()) + return devices.at(index); + + return QString(); +} + +QString DSVideoDeviceControl::deviceDescription(int index) const +{ + if(index >= 0 && index <= descriptions.count()) + return descriptions.at(index); + + return QString(); +} + +QIcon DSVideoDeviceControl::deviceIcon(int index) const +{ + Q_UNUSED(index) + + return QIcon(); +} + +int DSVideoDeviceControl::defaultDevice() const +{ + return 0; +} + +int DSVideoDeviceControl::selectedDevice() const +{ + return selected; +} + +void DSVideoDeviceControl::setSelectedDevice(int index) +{ + if(index >= 0 && index <= devices.count()) { + if (m_session) { + QString device = devices.at(index); + if (device.startsWith("ds:")) + device.remove(0,3); + m_session->setDevice(device); + } + selected = index; + } +} + +QT_END_NAMESPACE diff --git a/plugins/multimedia/directshow/camera/dsvideodevicecontrol.h b/plugins/multimedia/directshow/camera/dsvideodevicecontrol.h new file mode 100644 index 0000000000..8391c4edaf --- /dev/null +++ b/plugins/multimedia/directshow/camera/dsvideodevicecontrol.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DSVIDEODEVICECONTROL_H +#define DSVIDEODEVICECONTROL_H + +#include <qvideodevicecontrol.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE +class DSCameraSession; + +//QTM_USE_NAMESPACE + +class DSVideoDeviceControl : public QVideoDeviceControl +{ + Q_OBJECT +public: + DSVideoDeviceControl(QObject *parent = 0); + + int deviceCount() const; + QString deviceName(int index) const; + QString deviceDescription(int index) const; + QIcon deviceIcon(int index) const; + int defaultDevice() const; + int selectedDevice() const; + +public Q_SLOTS: + void setSelectedDevice(int index); + +private: + DSCameraSession* m_session; + + QList<QString> devices; + QList<QString> descriptions; + + int selected; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/plugins/multimedia/directshow/camera/dsvideorenderer.cpp b/plugins/multimedia/directshow/camera/dsvideorenderer.cpp new file mode 100644 index 0000000000..0fbdb15b13 --- /dev/null +++ b/plugins/multimedia/directshow/camera/dsvideorenderer.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/qdebug.h> + +#include "dsvideorenderer.h" + +QT_BEGIN_NAMESPACE + +DSVideoRendererControl::DSVideoRendererControl(DSCameraSession* session, QObject *parent) + :QVideoRendererControl(parent), + m_surface(0), + m_session(session) +{ +} + +DSVideoRendererControl::~DSVideoRendererControl() +{ +} + +QAbstractVideoSurface* DSVideoRendererControl::surface() const +{ + return m_surface; +} + +void DSVideoRendererControl::setSurface(QAbstractVideoSurface *surface) +{ + m_surface = surface; + if(m_session) + m_session->setSurface(m_surface); +} + +QT_END_NAMESPACE + diff --git a/plugins/multimedia/directshow/camera/dsvideorenderer.h b/plugins/multimedia/directshow/camera/dsvideorenderer.h new file mode 100644 index 0000000000..b941504ac9 --- /dev/null +++ b/plugins/multimedia/directshow/camera/dsvideorenderer.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DSVIDEORENDERER_H +#define DSVIDEORENDERER_H + +#include <qvideorenderercontrol.h> +#include "dscamerasession.h" + +class CameraFormatConverter; + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + + +class DSVideoRendererControl : public QVideoRendererControl +{ + Q_OBJECT +public: + DSVideoRendererControl(DSCameraSession* session, QObject *parent = 0); + ~DSVideoRendererControl(); + + QAbstractVideoSurface *surface() const; + void setSurface(QAbstractVideoSurface *surface); + + void setSession(DSCameraSession* session); + +private: + QAbstractVideoSurface* m_surface; + DSCameraSession* m_session; + CameraFormatConverter* converter; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // DSVIDEORENDERER_H diff --git a/plugins/multimedia/directshow/camera/dsvideowidgetcontrol.cpp b/plugins/multimedia/directshow/camera/dsvideowidgetcontrol.cpp new file mode 100644 index 0000000000..8298c0275e --- /dev/null +++ b/plugins/multimedia/directshow/camera/dsvideowidgetcontrol.cpp @@ -0,0 +1,250 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/qcoreevent.h> +#include <QtCore/qtimer.h> + +#include "DSVideoWidgetControl.h" +#include "dscamerasession.h" + +QT_BEGIN_NAMESPACE + +DSVideoWidgetSurface::DSVideoWidgetSurface(QLabel *pWidget, QObject *parent) +{ + widget = pWidget; + myPixmap = 0; +} + +QList<QVideoFrame::PixelFormat> DSVideoWidgetSurface::supportedPixelFormats( + QAbstractVideoBuffer::HandleType handleType) const +{ + if (handleType == QAbstractVideoBuffer::NoHandle) { + return QList<QVideoFrame::PixelFormat>() + << QVideoFrame::Format_RGB32 + << QVideoFrame::Format_RGB24; + } else { + return QList<QVideoFrame::PixelFormat>(); + } +} + + +bool DSVideoWidgetSurface::present(const QVideoFrame &frame) +{ + QVideoFrame myFrame = frame; + myFrame.map(QAbstractVideoBuffer::ReadOnly); + QImage image( + frame.bits(), + frame.width(), + frame.height(), + frame.bytesPerLine(), + imageFormat); + if (image.isNull()) + { + // Try to adapt + QImage image2( + frame.bits(), + frame.width(), + frame.height(), + frame.bytesPerLine(), + QImage::Format_RGB888); + image = image2; + } + myFrame.unmap(); + delete myPixmap; + myPixmap = new QPixmap(QPixmap::fromImage(image).scaled(widget->size())); + widget->setPixmap(*myPixmap); + widget->repaint(); + return true; +} + +void DSVideoWidgetSurface::setImageFormat(QImage::Format fmt) +{ + imageFormat = fmt; +} + +void DSVideoWidgetSurface::updateVideoRect() +{ +} + +void DSVideoWidgetSurface::paint(QPainter *painter) +{ +} + + +DSVideoWidgetControl::DSVideoWidgetControl(DSCameraSession* session, QObject *parent) : + m_session(session), QVideoWidgetControl(parent), + m_widget(new QLabel()), + m_fullScreen(false) +{ + m_widget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + m_widget->setAlignment(Qt::AlignCenter); + m_widget->setAttribute(Qt::WA_NoSystemBackground, true); + + surface = new DSVideoWidgetSurface(m_widget); + + QPalette palette; + palette.setColor(QPalette::Background, Qt::black); + m_widget->setPalette(palette); + m_widget->setAutoFillBackground( true ); + + // Request QEvents + m_widget->installEventFilter(this); + m_windowId = m_widget->effectiveWinId(); + + surface->setImageFormat(QImage::Format_RGB888); + session->setSurface(surface); +} + +DSVideoWidgetControl::~DSVideoWidgetControl() +{ + delete m_widget; +} + +bool DSVideoWidgetControl::eventFilter(QObject *object, QEvent *e) +{ + if (object == m_widget) { + switch (e->type()) { + case QEvent::ParentChange: + case QEvent::WinIdChange: + case QEvent::Show: + m_windowId = m_widget->effectiveWinId(); + emit widgetUpdated(); + break; + case QEvent::Resize: + emit widgetResized(m_widget->size()); + break; + case QEvent::PolishRequest: + m_widget->ensurePolished(); + break; + + default: + // Do nothing + break; + } + } + return false; +} + +QWidget *DSVideoWidgetControl::videoWidget() +{ + return m_widget; +} + +Qt::AspectRatioMode DSVideoWidgetControl::aspectRatioMode() const +{ + return m_aspectRatioMode; +} + +void DSVideoWidgetControl::setAspectRatioMode(Qt::AspectRatioMode ratio) +{ + if (m_aspectRatioMode==ratio) { + return; + } + m_aspectRatioMode = ratio; + + if (m_aspectRatioMode == Qt::KeepAspectRatio) + m_widget->setScaledContents(false); + else { + m_widget->setScaledContents(true); + } +} + +bool DSVideoWidgetControl::isFullScreen() const +{ + return m_fullScreen; +} + +void DSVideoWidgetControl::setFullScreen(bool fullScreen) +{ + if (m_widget && !fullScreen && m_fullScreen) { + m_widget->showNormal(); + m_fullScreen = false; + } else if (m_widget && fullScreen) { + m_widget->showFullScreen(); + m_fullScreen = true; + } + + emit fullScreenChanged(fullScreen); +} + +int DSVideoWidgetControl::brightness() const +{ + return 0; +} + +void DSVideoWidgetControl::setBrightness(int brightness) +{ + Q_UNUSED(brightness); +} + +int DSVideoWidgetControl::contrast() const +{ + return 0; +} + +void DSVideoWidgetControl::setContrast(int contrast) +{ + Q_UNUSED(contrast); +} + +int DSVideoWidgetControl::hue() const +{ + return 0; +} + +void DSVideoWidgetControl::setHue(int hue) +{ + Q_UNUSED(hue); +} + +int DSVideoWidgetControl::saturation() const +{ + return 0; +} + +void DSVideoWidgetControl::setSaturation(int saturation) +{ + Q_UNUSED(saturation); +} + +QT_END_NAMESPACE + +// End of file diff --git a/plugins/multimedia/directshow/camera/dsvideowidgetcontrol.h b/plugins/multimedia/directshow/camera/dsvideowidgetcontrol.h new file mode 100644 index 0000000000..e178274537 --- /dev/null +++ b/plugins/multimedia/directshow/camera/dsvideowidgetcontrol.h @@ -0,0 +1,154 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DSVIDEOWIDGETCONTROL_H +#define DSVIDEOWIDGETCONTROL_H + +#include <QtCore/qobject.h> +#include <QtGui> +#include <QtMultimedia/qvideoframe.h> +#include <QtMultimedia/qabstractvideosurface.h> +#include <QtMultimedia/qvideosurfaceformat.h> + +#include <qvideowidgetcontrol.h> +#include "DsCameraControl.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class DSVideoWidgetSurface : public QAbstractVideoSurface +{ + Q_OBJECT + public: + DSVideoWidgetSurface(QLabel *pWidget, QObject *parent = 0); + + QList<QVideoFrame::PixelFormat> supportedPixelFormats( + QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const; + + bool present(const QVideoFrame &frame); + + QRect videoRect() const { return targetRect; } + void updateVideoRect(); + + void paint(QPainter *painter); + void setImageFormat(QImage::Format fmt); + + private: + QLabel *widget; + QImage::Format imageFormat; + QRect targetRect; + QSize imageSize; + QRect sourceRect; + QPixmap* myPixmap; + }; + +class DSVideoWidgetControl : public QVideoWidgetControl +{ + Q_OBJECT + + DSVideoWidgetSurface* surface; +public: // Constructor & Destructor + + DSVideoWidgetControl(DSCameraSession* session, QObject *parent = 0); + virtual ~DSVideoWidgetControl(); + +public: // QVideoWidgetControl + + QWidget *videoWidget(); + + // Aspect Ratio + Qt::AspectRatioMode aspectRatioMode() const; + void setAspectRatioMode(Qt::AspectRatioMode ratio); + + // Full Screen + bool isFullScreen() const; + void setFullScreen(bool fullScreen); + + // Brightness + int brightness() const; + void setBrightness(int brightness); + + // Contrast + int contrast() const; + void setContrast(int contrast); + + // Hue + int hue() const; + void setHue(int hue); + + // Saturation + int saturation() const; + void setSaturation(int saturation); + +public: // Internal + + bool eventFilter(QObject *object, QEvent *event); + +/* +Q_SIGNALS: // QVideoWidgetControl + + void fullScreenChanged(bool fullScreen); + void brightnessChanged(int brightness); + void contrastChanged(int contrast); + void hueChanged(int hue); + void saturationChanged(int saturation); +*/ + +Q_SIGNALS: // Internal Signals + + void widgetResized(QSize size); + void widgetUpdated(); + +private: // Data + + DSCameraSession* m_session; + QLabel *m_widget; + WId m_windowId; + Qt::AspectRatioMode m_aspectRatioMode; + bool m_fullScreen; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // DSVideoWidgetControl_H diff --git a/plugins/multimedia/directshow/directshow.pro b/plugins/multimedia/directshow/directshow.pro index dc6ee9e87d..b86919470b 100644 --- a/plugins/multimedia/directshow/directshow.pro +++ b/plugins/multimedia/directshow/directshow.pro @@ -21,3 +21,4 @@ SOURCES += dsserviceplugin.cpp !contains(wmsdk_enabled, yes): DEFINES += QT_NO_WMSDK include (player/player.pri) +include (camera/camera.pri) diff --git a/plugins/multimedia/directshow/dsserviceplugin.cpp b/plugins/multimedia/directshow/dsserviceplugin.cpp index d5fbf9c7ea..9c0a214491 100644 --- a/plugins/multimedia/directshow/dsserviceplugin.cpp +++ b/plugins/multimedia/directshow/dsserviceplugin.cpp @@ -45,6 +45,7 @@ #include "dsserviceplugin.h" + #ifdef QMEDIA_DIRECTSHOW_CAMERA #include "dscameraservice.h" #endif @@ -57,6 +58,10 @@ #ifdef QMEDIA_DIRECTSHOW_CAMERA + +extern const CLSID CLSID_VideoInputDeviceCategory; + + #ifndef _STRSAFE_H_INCLUDED_ #include <tchar.h> #endif @@ -66,8 +71,11 @@ #pragma comment(lib, "strmiids.lib") #pragma comment(lib, "ole32.lib") #include <windows.h> +#include <ocidl.h> #endif +QT_USE_NAMESPACE + QStringList DSServicePlugin::keys() const { return QStringList() @@ -91,7 +99,7 @@ QMediaService* DSServicePlugin::create(QString const& key) return new DirectShowPlayerService; #endif - //qDebug() << "unsupported key:" << key; + qDebug() << "unsupported key:" << key; return 0; } @@ -139,11 +147,12 @@ QString DSServicePlugin::deviceDescription(const QByteArray &service, const QByt } #ifdef QMEDIA_DIRECTSHOW_CAMERA + void DSServicePlugin::updateDevices() const { m_cameraDevices.clear(); m_cameraDescriptions.clear(); - + BOOL bFound = TRUE; CoInitialize(NULL); ICreateDevEnum* pDevEnum = NULL; IEnumMoniker* pEnum = NULL; @@ -155,36 +164,46 @@ void DSServicePlugin::updateDevices() const // Create the enumerator for the video capture category hr = pDevEnum->CreateClassEnumerator( CLSID_VideoInputDeviceCategory, &pEnum, 0); - pEnum->Reset(); - // go through and find all video capture devices - IMoniker* pMoniker = NULL; - while(pEnum->Next(1, &pMoniker, NULL) == S_OK) { - IPropertyBag *pPropBag; - hr = pMoniker->BindToStorage(0,0,IID_IPropertyBag, - (void**)(&pPropBag)); - if(FAILED(hr)) { - pMoniker->Release(); - continue; // skip this one - } - // Find the description - WCHAR str[120]; - VARIANT varName; - varName.vt = VT_BSTR; - hr = pPropBag->Read(L"FriendlyName", &varName, 0); - if(SUCCEEDED(hr)) { - StringCchCopyW(str,sizeof(str)/sizeof(str[0]),varName.bstrVal); - QString temp(QString::fromUtf16((unsigned short*)str)); - m_cameraDevices.append(QString("ds:%1").arg(temp).toLocal8Bit().constData()); - hr = pPropBag->Read(L"Description", &varName, 0); - StringCchCopyW(str,sizeof(str)/sizeof(str[0]),varName.bstrVal); - QString temp2(QString::fromUtf16((unsigned short*)str)); - m_cameraDescriptions.append(temp2); - } - pPropBag->Release(); - pMoniker->Release(); - } + if (S_OK == hr) { + pEnum->Reset(); + // go through and find all video capture devices + IMoniker* pMoniker = NULL; + while(pEnum->Next(1, &pMoniker, NULL) == S_OK) { + IPropertyBag *pPropBag; + hr = pMoniker->BindToStorage(0,0,IID_IPropertyBag, + (void**)(&pPropBag)); + if(FAILED(hr)) { + pMoniker->Release(); + continue; // skip this one + } + bFound = TRUE; + // Find the description + WCHAR str[120]; + VARIANT varName; + varName.vt = VT_BSTR; + hr = pPropBag->Read(L"FriendlyName", &varName, 0); + if(SUCCEEDED(hr)) { + wcsncpy(str, varName.bstrVal, sizeof(str)/sizeof(str[0])); + QString temp(QString::fromUtf16((unsigned short*)str)); + m_cameraDevices.append(QString("ds:%1").arg(temp).toLocal8Bit().constData()); + hr = pPropBag->Read(L"Description", &varName, 0); + wcsncpy(str, varName.bstrVal, sizeof(str)/sizeof(str[0])); + QString temp2(QString::fromUtf16((unsigned short*)str)); + m_cameraDescriptions.append(temp2); + } else { + qWarning() << "No friendly name"; + } + pPropBag->Release(); + pMoniker->Release(); + } + pEnum->Release(); + } + pDevEnum->Release(); } CoUninitialize(); + if (!bFound) { + qWarning() << "No camera devices found"; + } } #endif diff --git a/plugins/multimedia/gstreamer/camerabin/camerabincontrol.cpp b/plugins/multimedia/gstreamer/camerabin/camerabincontrol.cpp index 56b9e84bc5..8c5a31b627 100644 --- a/plugins/multimedia/gstreamer/camerabin/camerabincontrol.cpp +++ b/plugins/multimedia/gstreamer/camerabin/camerabincontrol.cpp @@ -87,6 +87,8 @@ CameraBinControl::CameraBinControl(CameraBinSession *session) SLOT(reloadLater())); connect(m_session, SIGNAL(readyChanged(bool)), SLOT(reloadLater())); + connect(m_session, SIGNAL(error(int,QString)), + SLOT(handleCameraError(int,QString))); m_resourcePolicy = new CamerabinResourcePolicy(this); connect(m_resourcePolicy, SIGNAL(resourcesGranted()), @@ -121,6 +123,7 @@ void CameraBinControl::setCaptureMode(QCamera::CaptureMode mode) CamerabinResourcePolicy::ImageCaptureResources : CamerabinResourcePolicy::VideoCaptureResources); } + emit captureModeChanged(mode); } } @@ -293,6 +296,12 @@ void CameraBinControl::handleBusyChanged(bool busy) } } +void CameraBinControl::handleCameraError(int errorCode, const QString &errorString) +{ + emit error(errorCode, errorString); + setState(QCamera::UnloadedState); +} + void CameraBinControl::delayedReload() { #ifdef CAMEABIN_DEBUG diff --git a/plugins/multimedia/gstreamer/camerabin/camerabincontrol.h b/plugins/multimedia/gstreamer/camerabin/camerabincontrol.h index 5e45d7a4df..bab17e5a49 100644 --- a/plugins/multimedia/gstreamer/camerabin/camerabincontrol.h +++ b/plugins/multimedia/gstreamer/camerabin/camerabincontrol.h @@ -82,6 +82,7 @@ private slots: void handleResourcesLost(); void handleBusyChanged(bool); + void handleCameraError(int error, const QString &errorString); private: void updateSupportedResolutions(const QString &device); diff --git a/plugins/multimedia/gstreamer/camerabin/camerabinimagecapture.cpp b/plugins/multimedia/gstreamer/camerabin/camerabinimagecapture.cpp index 18a6b664b9..3df1105bc3 100644 --- a/plugins/multimedia/gstreamer/camerabin/camerabinimagecapture.cpp +++ b/plugins/multimedia/gstreamer/camerabin/camerabinimagecapture.cpp @@ -104,6 +104,12 @@ bool CameraBinImageCapture::isReadyForCapture() const int CameraBinImageCapture::capture(const QString &fileName) { m_requestId++; + + if (!m_ready) { + emit error(m_requestId, QCameraImageCapture::NotReadyError, tr("Camera not ready")); + return m_requestId; + } + #ifdef DEBUG_CAPTURE qDebug() << Q_FUNC_INFO << m_requestId << fileName; #endif diff --git a/plugins/multimedia/gstreamer/camerabin/camerabinrecorder.cpp b/plugins/multimedia/gstreamer/camerabin/camerabinrecorder.cpp index a29831129c..0cd8a5aaf9 100644 --- a/plugins/multimedia/gstreamer/camerabin/camerabinrecorder.cpp +++ b/plugins/multimedia/gstreamer/camerabin/camerabinrecorder.cpp @@ -51,7 +51,6 @@ CameraBinRecorder::CameraBinRecorder(CameraBinSession *session) m_state(QMediaRecorder::StoppedState) { connect(m_session, SIGNAL(stateChanged(QCamera::State)), SLOT(updateState())); - connect(m_session, SIGNAL(error(int,QString)), SIGNAL(error(int,QString))); connect(m_session, SIGNAL(durationChanged(qint64)), SIGNAL(durationChanged(qint64))); connect(m_session, SIGNAL(mutedChanged(bool)), this, SIGNAL(mutedChanged(bool))); } diff --git a/plugins/multimedia/gstreamer/camerabin/camerabinresourcepolicy.cpp b/plugins/multimedia/gstreamer/camerabin/camerabinresourcepolicy.cpp index 0d1357ad16..db9218c4a2 100644 --- a/plugins/multimedia/gstreamer/camerabin/camerabinresourcepolicy.cpp +++ b/plugins/multimedia/gstreamer/camerabin/camerabinresourcepolicy.cpp @@ -47,6 +47,7 @@ //#define DEBUG_RESOURCE_POLICY #include <QtCore/qdebug.h> +#include <QtCore/qset.h> #ifdef HAVE_RESOURCE_POLICY #include <policy/resource.h> @@ -56,57 +57,39 @@ CamerabinResourcePolicy::CamerabinResourcePolicy(QObject *parent) : QObject(parent), - m_resourceSet(NoResources) + m_resourceSet(NoResources), + m_releasingResources(false) { #ifdef HAVE_RESOURCE_POLICY - ResourcePolicy::ResourceSet *resourceSet; - //loaded resource set is also kept requested for image and video capture sets - resourceSet = new ResourcePolicy::ResourceSet("camera", this); - - resourceSet->addResource(ResourcePolicy::VideoRecorderType); - ResourcePolicy::LensCoverResource *lensCoverResource = new ResourcePolicy::LensCoverResource; - lensCoverResource->setOptional(true); - resourceSet->addResourceObject(lensCoverResource); - resourceSet->update(); - - m_resources.append(resourceSet); - m_resourceStatuses.append(Initial); - - //still image resources: - resourceSet = new ResourcePolicy::ResourceSet("camera", this); - resourceSet->addResource(ResourcePolicy::VideoPlaybackType); - resourceSet->addResource(ResourcePolicy::LedsType); - resourceSet->update(); - - m_resources.append(resourceSet); - m_resourceStatuses.append(Initial); - - //video capture resources: - resourceSet = new ResourcePolicy::ResourceSet("camera", this); - - resourceSet->addResource(ResourcePolicy::VideoPlaybackType); - resourceSet->addResource(ResourcePolicy::AudioPlaybackType); - resourceSet->addResource(ResourcePolicy::AudioRecorderType); - resourceSet->addResource(ResourcePolicy::LedsType); - resourceSet->update(); - - m_resources.append(resourceSet); - m_resourceStatuses.append(Initial); - - foreach (ResourcePolicy::ResourceSet *resource, m_resources) { - connect(resource, SIGNAL(resourcesGranted(const QList<ResourcePolicy::ResourceType>)), - this, SLOT(handleResourcesGranted())); - connect(resource, SIGNAL(resourcesDenied()), - this, SLOT(handleResourcesDenied())); - connect(resource, SIGNAL(lostResources()), - this, SLOT(handleResourcesLost())); - } + m_resource = new ResourcePolicy::ResourceSet("camera"); + m_resource->setAlwaysReply(); + m_resource->initAndConnect(); + + connect(m_resource, SIGNAL(resourcesGranted(const QList<ResourcePolicy::ResourceType>)), + SIGNAL(resourcesGranted())); + connect(m_resource, SIGNAL(resourcesDenied()), SIGNAL(resourcesDenied())); + connect(m_resource, SIGNAL(lostResources()), SIGNAL(resourcesLost())); + connect(m_resource, SIGNAL(resourcesReleased()), SLOT(handleResourcesReleased())); #endif } CamerabinResourcePolicy::~CamerabinResourcePolicy() { +#ifdef HAVE_RESOURCE_POLICY + //ensure the resources are released + if (m_resourceSet != NoResources) + setResourceSet(NoResources); + + //don't delete the resource set until resources are released + if (m_releasingResources) { + m_resource->connect(m_resource, SIGNAL(resourcesReleased()), + SLOT(deleteLater())); + } else { + delete m_resource; + m_resource = 0; + } +#endif } CamerabinResourcePolicy::ResourceSet CamerabinResourcePolicy::resourceSet() const @@ -116,8 +99,7 @@ CamerabinResourcePolicy::ResourceSet CamerabinResourcePolicy::resourceSet() cons void CamerabinResourcePolicy::setResourceSet(CamerabinResourcePolicy::ResourceSet set) { - if (m_resourceSet == set) - return; + CamerabinResourcePolicy::ResourceSet oldSet = m_resourceSet; m_resourceSet = set; #ifdef DEBUG_RESOURCE_POLICY @@ -125,108 +107,82 @@ void CamerabinResourcePolicy::setResourceSet(CamerabinResourcePolicy::ResourceSe #endif #ifdef HAVE_RESOURCE_POLICY - m_requestedSets.clear(); + QSet<ResourcePolicy::ResourceType> requestedTypes; + switch (set) { case NoResources: break; case LoadedResources: - m_requestedSets << LoadedResourcesSet; + requestedTypes << ResourcePolicy::LensCoverType //to detect lens cover is opened/closed + << ResourcePolicy::VideoRecorderType //to open camera device + << ResourcePolicy::SnapButtonType; //to detect capture button events break; case ImageCaptureResources: - m_requestedSets << LoadedResourcesSet << ImageResourcesSet; + requestedTypes << ResourcePolicy::LensCoverType + << ResourcePolicy::VideoPlaybackType + << ResourcePolicy::VideoRecorderType + << ResourcePolicy::AudioPlaybackType + << ResourcePolicy::ScaleButtonType + << ResourcePolicy::LedsType + << ResourcePolicy::SnapButtonType; break; case VideoCaptureResources: - m_requestedSets << LoadedResourcesSet << VideoResouresSet; + requestedTypes << ResourcePolicy::LensCoverType + << ResourcePolicy::VideoPlaybackType + << ResourcePolicy::VideoRecorderType + << ResourcePolicy::AudioPlaybackType + << ResourcePolicy::AudioRecorderType + << ResourcePolicy::ScaleButtonType + << ResourcePolicy::LedsType + << ResourcePolicy::SnapButtonType; break; } - //release the resource we don't need any more - for (int i=0; i<m_resources.count(); i++) { - if (!m_requestedSets.contains(i) && m_resourceStatuses[i] != Initial) { - m_resourceStatuses[i] = Initial; - m_resources[i]->release(); - } - } + QSet<ResourcePolicy::ResourceType> currentTypes; + foreach (ResourcePolicy::Resource *resource, m_resource->resources()) + currentTypes << resource->type(); - //and acquire ones we need - foreach (int i, m_requestedSets) { - if (m_resourceStatuses[i] == Initial) { - m_resourceStatuses[i] = RequestedResource; - m_resources[i]->acquire(); - } - } -#endif -} + foreach (ResourcePolicy::ResourceType resourceType, currentTypes - requestedTypes) + m_resource->deleteResource(resourceType); -bool CamerabinResourcePolicy::isResourcesGranted() const -{ - foreach (int i, m_requestedSets) { - if (m_resourceStatuses[i] != GrantedResource) - return false; + foreach (ResourcePolicy::ResourceType resourceType, requestedTypes - currentTypes) { + if (resourceType == ResourcePolicy::LensCoverType) { + ResourcePolicy::LensCoverResource *lensCoverResource = new ResourcePolicy::LensCoverResource; + lensCoverResource->setOptional(true); + m_resource->addResourceObject(lensCoverResource); + } else { + m_resource->addResource(resourceType); + } } - return true; -} - - - -void CamerabinResourcePolicy::handleResourcesGranted() -{ -#ifdef HAVE_RESOURCE_POLICY - for (int i=0; i<m_resources.count(); i++) { - if (sender() == m_resources[i]) { - m_resourceStatuses[i] = GrantedResource; - -#ifdef DEBUG_RESOURCE_POLICY - qDebug() << Q_FUNC_INFO << "Resource granted" << i; -#endif - if (m_requestedSets.contains(i)) { - if (isResourcesGranted()) - emit resourcesGranted(); - } - break; + m_resource->update(); + if (set != NoResources) { + m_resource->acquire(); + } else { + if (oldSet != NoResources) { + m_releasingResources = true; + m_resource->release(); } } #endif } -void CamerabinResourcePolicy::handleResourcesDenied() +bool CamerabinResourcePolicy::isResourcesGranted() const { #ifdef HAVE_RESOURCE_POLICY - for (int i=0; i<m_resources.count(); i++) { - if (sender() == m_resources[i]) { - bool wasGranted = isResourcesGranted(); - m_resourceStatuses[i] = RequestedResource; - -#ifdef DEBUG_RESOURCE_POLICY - qDebug() << Q_FUNC_INFO << "Resource denied" << i << "was granted:" << wasGranted; -#endif - if (wasGranted && m_requestedSets.contains(i)) - emit resourcesDenied(); - - break; - } - } + foreach (ResourcePolicy::Resource *resource, m_resource->resources()) + if (!resource->isOptional() && !resource->isGranted()) + return false; #endif + return true; } -void CamerabinResourcePolicy::handleResourcesLost() +void CamerabinResourcePolicy::handleResourcesReleased() { #ifdef HAVE_RESOURCE_POLICY - for (int i=0; i<m_resources.count(); i++) { - if (sender() == m_resources[i]) { - bool wasGranted = isResourcesGranted(); - m_resourceStatuses[i] = RequestedResource; - #ifdef DEBUG_RESOURCE_POLICY - qDebug() << Q_FUNC_INFO << "Resource lost" << i << "was granted:" << wasGranted; + qDebug() << Q_FUNC_INFO; #endif - - if (wasGranted && m_requestedSets.contains(i)) - emit resourcesLost(); - - break; - } - } + m_releasingResources = false; #endif } diff --git a/plugins/multimedia/gstreamer/camerabin/camerabinresourcepolicy.h b/plugins/multimedia/gstreamer/camerabin/camerabinresourcepolicy.h index 4d30da7cc1..cd2d846881 100644 --- a/plugins/multimedia/gstreamer/camerabin/camerabinresourcepolicy.h +++ b/plugins/multimedia/gstreamer/camerabin/camerabinresourcepolicy.h @@ -43,7 +43,6 @@ #define CAMERARESOURCEPOLICY_H #include <QtCore/qobject.h> -#include <QtCore/qlist.h> namespace ResourcePolicy { class ResourceSet; @@ -74,28 +73,12 @@ Q_SIGNALS: void resourcesLost(); private Q_SLOTS: - void handleResourcesGranted(); - void handleResourcesDenied(); - void handleResourcesLost(); + void handleResourcesReleased(); private: ResourceSet m_resourceSet; - - enum ResourceStatus { - Initial = 0, - RequestedResource, - GrantedResource - }; - - enum { - LoadedResourcesSet = 0, - ImageResourcesSet, - VideoResouresSet - }; - - QList<ResourcePolicy::ResourceSet *> m_resources; - QList<ResourceStatus> m_resourceStatuses; - QList<int> m_requestedSets; + ResourcePolicy::ResourceSet *m_resource; + bool m_releasingResources; }; #endif diff --git a/plugins/multimedia/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp b/plugins/multimedia/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp index 6dec6a5348..7c27618ef7 100644 --- a/plugins/multimedia/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp +++ b/plugins/multimedia/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp @@ -56,13 +56,14 @@ #include <fcntl.h> #include <unistd.h> +//#define DEBUG_PLAYBIN + QGstreamerPlayerControl::QGstreamerPlayerControl(QGstreamerPlayerSession *session, QObject *parent) : QMediaPlayerControl(parent) , m_ownStream(false) , m_session(session) , m_state(QMediaPlayer::StoppedState) , m_mediaStatus(QMediaPlayer::NoMedia) - , m_blockStatusChangedSignal(false) , m_bufferProgress(-1) , m_seekToStartPending(false) , m_pendingSeekPosition(-1) @@ -86,7 +87,7 @@ QGstreamerPlayerControl::QGstreamerPlayerControl(QGstreamerPlayerSession *sessio connect(m_session, SIGNAL(volumeChanged(int)), this, SIGNAL(volumeChanged(int))); connect(m_session, SIGNAL(stateChanged(QMediaPlayer::State)), - this, SLOT(updateState(QMediaPlayer::State))); + this, SLOT(updateSessionState(QMediaPlayer::State))); connect(m_session,SIGNAL(bufferingProgressChanged(int)), this, SLOT(setBufferProgress(int))); connect(m_session, SIGNAL(playbackFinished()), @@ -166,12 +167,7 @@ bool QGstreamerPlayerControl::isSeekable() const QMediaTimeRange QGstreamerPlayerControl::availablePlaybackRanges() const { - QMediaTimeRange ranges; - - if (m_session->isSeekable()) - ranges.addInterval(0, m_session->duration()); - - return ranges; + return m_session->availablePlaybackRanges(); } qreal QGstreamerPlayerControl::playbackRate() const @@ -186,10 +182,15 @@ void QGstreamerPlayerControl::setPlaybackRate(qreal rate) void QGstreamerPlayerControl::setPosition(qint64 pos) { +#ifdef DEBUG_PLAYBIN + qDebug() << Q_FUNC_INFO << pos/1000.0; +#endif + + pushState(); + if (m_mediaStatus == QMediaPlayer::EndOfMedia) { m_mediaStatus = QMediaPlayer::LoadedMedia; m_seekToStartPending = true; - emit mediaStatusChanged(m_mediaStatus); } if (m_session->isSeekable() && m_session->seek(pos)) { @@ -198,15 +199,25 @@ void QGstreamerPlayerControl::setPosition(qint64 pos) } else { m_pendingSeekPosition = pos; } + + popAndNotifyState(); } void QGstreamerPlayerControl::play() { +#ifdef DEBUG_PLAYBIN + qDebug() << Q_FUNC_INFO; +#endif + playOrPause(QMediaPlayer::PlayingState); } void QGstreamerPlayerControl::pause() { +#ifdef DEBUG_PLAYBIN + qDebug() << Q_FUNC_INFO; +#endif + playOrPause(QMediaPlayer::PausedState); } @@ -215,8 +226,7 @@ void QGstreamerPlayerControl::playOrPause(QMediaPlayer::State newState) if (m_mediaStatus == QMediaPlayer::NoMedia) return; - QMediaPlayer::State oldState = m_state; - QMediaPlayer::MediaStatus oldMediaStatus = m_mediaStatus; + pushState(); if (m_mediaStatus == QMediaPlayer::EndOfMedia) { m_mediaStatus = QMediaPlayer::BufferedMedia; @@ -260,29 +270,31 @@ void QGstreamerPlayerControl::playOrPause(QMediaPlayer::State newState) m_mediaStatus = QMediaPlayer::BufferingMedia; } - if (m_state != oldState) - emit stateChanged(m_state); - if (m_mediaStatus != oldMediaStatus) - emit mediaStatusChanged(m_mediaStatus); + popAndNotifyState(); emit positionChanged(position()); } void QGstreamerPlayerControl::stop() { +#ifdef DEBUG_PLAYBIN + qDebug() << Q_FUNC_INFO; +#endif + + pushState(); + if (m_state != QMediaPlayer::StoppedState) { m_state = QMediaPlayer::StoppedState; if (m_resources->isGranted()) m_session->pause(); - updateState(m_session->state()); - if (m_mediaStatus != QMediaPlayer::EndOfMedia) { m_seekToStartPending = true; emit positionChanged(position()); } - emit stateChanged(m_state); } + + popAndNotifyState(); } void QGstreamerPlayerControl::setVolume(int volume) @@ -307,7 +319,12 @@ const QIODevice *QGstreamerPlayerControl::mediaStream() const void QGstreamerPlayerControl::setMedia(const QMediaContent &content, QIODevice *stream) { - QMediaPlayer::State oldState = m_state; +#ifdef DEBUG_PLAYBIN + qDebug() << Q_FUNC_INFO; +#endif + + pushState(); + m_state = QMediaPlayer::StoppedState; QMediaContent oldMedia = m_currentResource; m_pendingSeekPosition = -1; @@ -320,15 +337,11 @@ void QGstreamerPlayerControl::setMedia(const QMediaContent &content, QIODevice * m_currentResource = content; m_stream = stream; - QMediaPlayer::MediaStatus oldStatus = m_mediaStatus; m_state = QMediaPlayer::StoppedState; m_mediaStatus = QMediaPlayer::LoadingMedia; if (m_currentResource != oldMedia) emit mediaChanged(m_currentResource); - if (m_state != oldState && !m_blockStatusChangedSignal) - emit stateChanged(m_state); - if (m_mediaStatus != oldStatus && !m_blockStatusChangedSignal) - emit mediaStatusChanged(m_mediaStatus); + popAndNotifyState(); return; } } else { @@ -367,11 +380,9 @@ void QGstreamerPlayerControl::setMedia(const QMediaContent &content, QIODevice * m_currentResource = content; emit mediaChanged(m_currentResource); emit error(QMediaPlayer::FormatError, tr("Attempting to play invalid Qt resource")); - emit mediaStatusChanged(m_mediaStatus); - if (m_state != oldState) - emit stateChanged(m_state); if (m_state != QMediaPlayer::PlayingState) m_resources->release(); + popAndNotifyState(); return; } m_ownStream = true; @@ -404,12 +415,10 @@ void QGstreamerPlayerControl::setMedia(const QMediaContent &content, QIODevice * m_session->loadFromStream(request, m_stream); } else { m_mediaStatus = QMediaPlayer::InvalidMedia; - emit mediaStatusChanged(m_mediaStatus); - if (m_state != oldState) - emit stateChanged(m_state); emit error(QMediaPlayer::FormatError, tr("Attempting to play invalid user stream")); if (m_state != QMediaPlayer::PlayingState) m_resources->release(); + popAndNotifyState(); return; } } else @@ -429,25 +438,22 @@ void QGstreamerPlayerControl::setMedia(const QMediaContent &content, QIODevice * #else if (!request.url().isEmpty()) { #endif - if (m_mediaStatus != QMediaPlayer::LoadingMedia) - emit mediaStatusChanged(m_mediaStatus = QMediaPlayer::LoadingMedia); + m_mediaStatus = QMediaPlayer::LoadingMedia; m_session->pause(); } else { - if (m_mediaStatus != QMediaPlayer::NoMedia) - emit mediaStatusChanged(m_mediaStatus = QMediaPlayer::NoMedia); + m_mediaStatus = QMediaPlayer::NoMedia; setBufferProgress(0); } if (m_currentResource != oldMedia) emit mediaChanged(m_currentResource); - if (m_state != oldState && !m_blockStatusChangedSignal) - emit stateChanged(m_state); - emit positionChanged(position()); if (content.isNull() && !stream) m_resources->release(); + + popAndNotifyState(); } void QGstreamerPlayerControl::setVideoOutput(QObject *output) @@ -465,14 +471,25 @@ bool QGstreamerPlayerControl::isVideoAvailable() const return m_session->isVideoAvailable(); } -void QGstreamerPlayerControl::updateState(QMediaPlayer::State state) +void QGstreamerPlayerControl::updateSessionState(QMediaPlayer::State state) +{ + pushState(); + + if (state == QMediaPlayer::StoppedState) + m_state = QMediaPlayer::StoppedState; + + updateMediaStatus(); + + popAndNotifyState(); +} + +void QGstreamerPlayerControl::updateMediaStatus() { + pushState(); QMediaPlayer::MediaStatus oldStatus = m_mediaStatus; - QMediaPlayer::State oldState = m_state; - switch (state) { + switch (m_session->state()) { case QMediaPlayer::StoppedState: - m_state = QMediaPlayer::StoppedState; if (m_currentResource.isNull()) m_mediaStatus = QMediaPlayer::NoMedia; else @@ -486,6 +503,8 @@ void QGstreamerPlayerControl::updateState(QMediaPlayer::State state) } else { if (m_bufferProgress == -1 || m_bufferProgress == 100) m_mediaStatus = QMediaPlayer::BufferedMedia; + else + m_mediaStatus = QMediaPlayer::StalledMedia; } break; } @@ -497,18 +516,16 @@ void QGstreamerPlayerControl::updateState(QMediaPlayer::State state) if (oldStatus == QMediaPlayer::EndOfMedia) m_mediaStatus = QMediaPlayer::EndOfMedia; - if (m_state != oldState && !m_blockStatusChangedSignal) - emit stateChanged(m_state); - if (m_mediaStatus != oldStatus && !m_blockStatusChangedSignal) - emit mediaStatusChanged(m_mediaStatus); + popAndNotifyState(); } void QGstreamerPlayerControl::processEOS() { + pushState(); m_mediaStatus = QMediaPlayer::EndOfMedia; emit positionChanged(position()); stop(); - emit mediaStatusChanged(m_mediaStatus); + popAndNotifyState(); } void QGstreamerPlayerControl::setBufferProgress(int progress) @@ -516,31 +533,22 @@ void QGstreamerPlayerControl::setBufferProgress(int progress) if (m_bufferProgress == progress || m_mediaStatus == QMediaPlayer::NoMedia) return; - QMediaPlayer::MediaStatus oldStatus = m_mediaStatus; - +#ifdef DEBUG_PLAYBIN + qDebug() << Q_FUNC_INFO << progress; +#endif m_bufferProgress = progress; - if (m_state == QMediaPlayer::StoppedState) { - m_mediaStatus = QMediaPlayer::LoadedMedia; - } else { - if (m_bufferProgress < 30) { - m_mediaStatus = QMediaPlayer::StalledMedia; - if (m_session->state() == QMediaPlayer::PlayingState) - m_session->pause(); - } else if (m_bufferProgress > 90) { - m_mediaStatus = QMediaPlayer::BufferingMedia; - if (m_state == QMediaPlayer::PlayingState && - m_resources->isGranted() && + if (m_resources->isGranted()) { + if (m_state == QMediaPlayer::PlayingState && + m_bufferProgress == 100 && m_session->state() != QMediaPlayer::PlayingState) - m_session->play(); - } + m_session->play(); - if (m_bufferProgress == 100) - m_mediaStatus = QMediaPlayer::BufferedMedia; + if (m_bufferProgress < 100 && m_session->state() == QMediaPlayer::PlayingState) + m_session->pause(); } - if (m_mediaStatus != oldStatus) - emit mediaStatusChanged(m_mediaStatus); + updateMediaStatus(); emit bufferStatusChanged(m_bufferProgress); } @@ -645,30 +653,21 @@ void QGstreamerPlayerControl::applyPendingSeek(bool isSeekable) void QGstreamerPlayerControl::handleInvalidMedia() { - bool emitMediaStateChanged = false; - if (m_mediaStatus != QMediaPlayer::InvalidMedia) { - m_mediaStatus = QMediaPlayer::InvalidMedia; - emitMediaStateChanged = true; - } - if (m_state != m_session->state()) { - m_state = m_session->state(); - emit stateChanged(m_state); - } - if (emitMediaStateChanged) - emit mediaStatusChanged(m_mediaStatus); + pushState(); + m_mediaStatus = QMediaPlayer::InvalidMedia; + m_state = QMediaPlayer::StoppedState; + popAndNotifyState(); } void QGstreamerPlayerControl::handleResourcesGranted() { + pushState(); + QMediaPlayer::State state = m_state; //preserve m_pendingSeekPosition, it's reset on setMedia qint64 pos = m_pendingSeekPosition; - - //don't emit state changed to stopped at this stage - m_blockStatusChangedSignal = true; setMedia(m_currentResource, m_stream); - m_blockStatusChangedSignal = false; if (pos != -1) setPosition(pos); @@ -676,7 +675,9 @@ void QGstreamerPlayerControl::handleResourcesGranted() if (state != QMediaPlayer::StoppedState) playOrPause(state); else - updateState(m_session->state()); + updateMediaStatus(); + + popAndNotifyState(); } void QGstreamerPlayerControl::handleResourcesLost() @@ -684,22 +685,55 @@ void QGstreamerPlayerControl::handleResourcesLost() //on resource lost the pipeline should be stopped //player status is changed to paused + pushState(); QMediaPlayer::State oldState = m_state; - QMediaPlayer::MediaStatus oldMediaStatus = m_mediaStatus; - qint64 pos = m_session->position(); - m_blockStatusChangedSignal = true; + qint64 pos = m_session->position(); m_session->stop(); - m_blockStatusChangedSignal = false; - m_pendingSeekPosition = pos; if (oldState != QMediaPlayer::StoppedState ) m_state = QMediaPlayer::PausedState; - if (m_state != oldState) - emit stateChanged(m_state); + popAndNotifyState(); +} - if (m_mediaStatus != oldMediaStatus) - emit mediaStatusChanged(m_mediaStatus); +bool QGstreamerPlayerControl::isMediaDownloadEnabled() const +{ + return m_session->property("mediaDownloadEnabled").toBool(); +} + +void QGstreamerPlayerControl::setMediaDownloadEnabled(bool enabled) +{ + m_session->setProperty("mediaDownloadEnabled", enabled); +} + +void QGstreamerPlayerControl::pushState() +{ + m_stateStack.push(m_state); + m_mediaStatusStack.push(m_mediaStatus); +} + +void QGstreamerPlayerControl::popAndNotifyState() +{ + Q_ASSERT(!m_stateStack.isEmpty()); + + QMediaPlayer::State oldState = m_stateStack.pop(); + QMediaPlayer::MediaStatus oldMediaStatus = m_mediaStatusStack.pop(); + + if (m_stateStack.isEmpty()) { + if (m_state != oldState) { +#ifdef DEBUG_PLAYBIN + qDebug() << "State changed:" << m_state; +#endif + emit stateChanged(m_state); + } + + if (m_mediaStatus != oldMediaStatus) { +#ifdef DEBUG_PLAYBIN + qDebug() << "Media status changed:" << m_mediaStatus; +#endif + emit mediaStatusChanged(m_mediaStatus); + } + } } diff --git a/plugins/multimedia/gstreamer/mediaplayer/qgstreamerplayercontrol.h b/plugins/multimedia/gstreamer/mediaplayer/qgstreamerplayercontrol.h index 83a609d32c..5a53a07131 100644 --- a/plugins/multimedia/gstreamer/mediaplayer/qgstreamerplayercontrol.h +++ b/plugins/multimedia/gstreamer/mediaplayer/qgstreamerplayercontrol.h @@ -43,6 +43,7 @@ #define QGSTREAMERPLAYERCONTROL_H #include <QtCore/qobject.h> +#include <QtCore/qstack.h> #include <qmediaplayercontrol.h> #include <qmediaplayer.h> @@ -64,6 +65,7 @@ class PlayerResourcePolicy; class QGstreamerPlayerControl : public QMediaPlayerControl { Q_OBJECT + Q_PROPERTY(bool mediaDownloadEnabled READ isMediaDownloadEnabled WRITE setMediaDownloadEnabled) public: QGstreamerPlayerControl(QGstreamerPlayerSession *session, QObject *parent = 0); @@ -94,6 +96,9 @@ public: const QIODevice *mediaStream() const; void setMedia(const QMediaContent&, QIODevice *); + bool isMediaDownloadEnabled() const; + void setMediaDownloadEnabled(bool enabled); + public Q_SLOTS: void setPosition(qint64 pos); @@ -108,7 +113,8 @@ private Q_SLOTS: void writeFifo(); void fifoReadyWrite(int socket); - void updateState(QMediaPlayer::State); + void updateSessionState(QMediaPlayer::State state); + void updateMediaStatus(); void processEOS(); void setBufferProgress(int progress); void applyPendingSeek(bool isSeekable); @@ -123,11 +129,16 @@ private: void closeFifo(); void playOrPause(QMediaPlayer::State state); + void pushState(); + void popAndNotifyState(); + bool m_ownStream; QGstreamerPlayerSession *m_session; QMediaPlayer::State m_state; QMediaPlayer::MediaStatus m_mediaStatus; - bool m_blockStatusChangedSignal; + QStack<QMediaPlayer::State> m_stateStack; + QStack<QMediaPlayer::MediaStatus> m_mediaStatusStack; + int m_bufferProgress; bool m_seekToStartPending; qint64 m_pendingSeekPosition; diff --git a/plugins/multimedia/gstreamer/mediaplayer/qgstreamerplayersession.cpp b/plugins/multimedia/gstreamer/mediaplayer/qgstreamerplayersession.cpp index 98a3b0cca3..1011d07b8a 100644 --- a/plugins/multimedia/gstreamer/mediaplayer/qgstreamerplayersession.cpp +++ b/plugins/multimedia/gstreamer/mediaplayer/qgstreamerplayersession.cpp @@ -53,6 +53,8 @@ #include <QtCore/qsize.h> #include <QtCore/qtimer.h> #include <QtCore/qdebug.h> +#include <QtCore/qdir.h> +#include <QtGui/qdesktopservices.h> #if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6) || (GST_VERSION_MICRO > 20) #define USE_PLAYBIN2 @@ -87,6 +89,7 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent) m_bus(0), m_videoOutput(0), m_renderer(0), + m_haveQueueElement(false), #if defined(HAVE_GST_APPSRC) m_appSrc(0), #endif @@ -154,6 +157,7 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent) g_object_set(G_OBJECT(m_playbin), "video-sink", m_videoOutputBin, NULL); g_signal_connect(G_OBJECT(m_playbin), "notify::source", G_CALLBACK(playbinNotifySource), this); + g_signal_connect(G_OBJECT(m_playbin), "element-added", G_CALLBACK(handleElementAdded), this); // Initial volume double volume = 1.0; @@ -200,6 +204,7 @@ void QGstreamerPlayerSession::loadFromStream(const QNetworkRequest &request, QIO m_request = request; m_duration = -1; m_lastPosition = 0; + m_haveQueueElement = false; if (m_appSrc) m_appSrc->deleteLater(); @@ -228,6 +233,7 @@ void QGstreamerPlayerSession::loadFromUri(const QNetworkRequest &request) m_request = request; m_duration = -1; m_lastPosition = 0; + m_haveQueueElement = false; if (m_playbin) { m_tags.clear(); @@ -279,6 +285,41 @@ void QGstreamerPlayerSession::setPlaybackRate(qreal rate) } } +QMediaTimeRange QGstreamerPlayerSession::availablePlaybackRanges() const +{ + QMediaTimeRange ranges; +#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 31) + //GST_FORMAT_TIME would be more appropriate, but unfortunately it's not supported. + //with GST_FORMAT_PERCENT media is treated as encoded with constant bitrate. + GstQuery* query = gst_query_new_buffering(GST_FORMAT_PERCENT); + + if (gst_element_query(m_playbin, query)) { + for (guint index = 0; index < gst_query_get_n_buffering_ranges(query); index++) { + gint64 rangeStart = 0; + gint64 rangeStop = 0; + + //This query should return values in GST_FORMAT_PERCENT_MAX range, + //but queue2 returns values in 0..100 range instead + if (gst_query_parse_nth_buffering_range(query, index, &rangeStart, &rangeStop)) + ranges.addInterval(rangeStart * duration() / 100, + rangeStop * duration() / 100); + } + } + + gst_query_unref(query); +#endif + + //without queue2 element in pipeline all the media is considered available + if (ranges.isEmpty() && duration() > 0 && !m_haveQueueElement) + ranges.addInterval(0, duration()); + +#ifdef DEBUG_PLAYBIN + qDebug() << ranges; +#endif + + return ranges; +} + int QGstreamerPlayerSession::activeStream(QMediaStreamsControl::StreamType streamType) const { int streamNumber = -1; @@ -1420,3 +1461,37 @@ void QGstreamerPlayerSession::updateMuted() emit mutedStateChanged(muted); } } + + +void QGstreamerPlayerSession::handleElementAdded(GstBin *bin, GstElement *element, QGstreamerPlayerSession *session) +{ + Q_UNUSED(bin); + //we have to configure queue2 element to enable media downloading + //and reporting available ranges, + //but it's added dynamically to playbin2 + + gchar *elementName = gst_element_get_name(element); + + if (g_str_has_prefix(elementName, "queue2")) { + session->m_haveQueueElement = true; + + if (session->property("mediaDownloadEnabled").toBool()) { + QDir cacheDir(QDesktopServices::storageLocation(QDesktopServices::CacheLocation)); + QString cacheLocation = cacheDir.absoluteFilePath("gstmedia__XXXXXX"); +#ifdef DEBUG_PLAYBIN + qDebug() << "set queue2 temp-location" << cacheLocation; +#endif + g_object_set(G_OBJECT(element), "temp-template", cacheLocation.toUtf8().constData(), NULL); + } else { + g_object_set(G_OBJECT(element), "temp-template", NULL, NULL); + } + } else if (g_str_has_prefix(elementName, "uridecodebin") || + g_str_has_prefix(elementName, "decodebin2")) { + //listen for queue2 element added to uridecodebin/decodebin2 as well. + //Don't touch other bins since they may have unrelated queues + g_signal_connect(element, "element-added", + G_CALLBACK(handleElementAdded), session); + } + + g_free(elementName); +} diff --git a/plugins/multimedia/gstreamer/mediaplayer/qgstreamerplayersession.h b/plugins/multimedia/gstreamer/mediaplayer/qgstreamerplayersession.h index 06e3b567c1..b0304f1ce2 100644 --- a/plugins/multimedia/gstreamer/mediaplayer/qgstreamerplayersession.h +++ b/plugins/multimedia/gstreamer/mediaplayer/qgstreamerplayersession.h @@ -94,6 +94,8 @@ public: qreal playbackRate() const; void setPlaybackRate(qreal rate); + QMediaTimeRange availablePlaybackRanges() const; + QMap<QByteArray ,QVariant> tags() const { return m_tags; } QMap<QtMultimediaKit::MetaData,QVariant> streamProperties(int streamNumber) const { return m_streamProperties[streamNumber]; } int streamCount() const { return m_streamProperties.count(); } @@ -155,6 +157,7 @@ private: static void handleVolumeChange(GObject *o, GParamSpec *p, gpointer d); static void handleMutedChange(GObject *o, GParamSpec *p, gpointer d); static void insertColorSpaceElement(GstElement *element, gpointer data); + static void handleElementAdded(GstBin *bin, GstElement *element, QGstreamerPlayerSession *session); QNetworkRequest m_request; QMediaPlayer::State m_state; @@ -175,6 +178,8 @@ private: QObject *m_videoOutput; QGstreamerVideoRendererInterface *m_renderer; + bool m_haveQueueElement; + #if defined(HAVE_GST_APPSRC) QGstAppSrc *m_appSrc; #endif diff --git a/plugins/multimedia/gstreamer/qgstreamergltexturerenderer.cpp b/plugins/multimedia/gstreamer/qgstreamergltexturerenderer.cpp index fd1d4e5164..98a4736fb2 100644 --- a/plugins/multimedia/gstreamer/qgstreamergltexturerenderer.cpp +++ b/plugins/multimedia/gstreamer/qgstreamergltexturerenderer.cpp @@ -91,22 +91,12 @@ public: QGStreamerGLTextureBuffer(MeegoGstVideoTexture *textureSink, int frameNumber) : QAbstractVideoBuffer(EGLImageTextureHandle), m_textureSink(MEEGO_GST_VIDEO_TEXTURE(textureSink)), - m_frameNumber(frameNumber), - m_sync(0) + m_frameNumber(frameNumber) { -#if defined(GL_TEXTURE_SINK_DEBUG) && GL_TEXTURE_SINK_DEBUG > 1 - qDebug() << "acquire frame" << m_frameNumber; -#endif - if (!meego_gst_video_texture_acquire_frame(m_textureSink,frameNumber)) - qWarning() << Q_FUNC_INFO << "acquire-frame failed" << m_frameNumber; } ~QGStreamerGLTextureBuffer() { -#if defined(GL_TEXTURE_SINK_DEBUG) && GL_TEXTURE_SINK_DEBUG > 1 - qDebug() << "release frame" << m_frameNumber; -#endif - meego_gst_video_texture_release_frame(m_textureSink, m_frameNumber, m_sync); } @@ -117,6 +107,15 @@ public: Q_UNUSED(numBytes); Q_UNUSED(bytesPerLine); + //acquire_frame should really be called at buffer construction time + //but it conflicts with id-less implementation of gst texture sink. +#if defined(GL_TEXTURE_SINK_DEBUG) && GL_TEXTURE_SINK_DEBUG > 1 + qDebug() << "acquire frame" << m_frameNumber; +#endif + if (!meego_gst_video_texture_acquire_frame(m_textureSink,m_frameNumber)) + qWarning() << Q_FUNC_INFO << "acquire-frame failed" << m_frameNumber; + + #if defined(GL_TEXTURE_SINK_DEBUG) && GL_TEXTURE_SINK_DEBUG > 1 qDebug() << "map frame" << m_frameNumber; #endif @@ -136,13 +135,16 @@ public: qDebug() << "unmap frame" << m_frameNumber; #endif - if (!bind_status) { + if (!bind_status) qWarning() << Q_FUNC_INFO << "unbind-frame failed"; - } else { - if (m_sync) - eglDestroySyncKHR(eglGetDisplay((EGLNativeDisplayType)QX11Info::display()), m_sync); - m_sync = eglCreateSyncKHR(eglGetDisplay((EGLNativeDisplayType)QX11Info::display()), EGL_SYNC_FENCE_KHR, NULL); - } + + //release_frame should really be called in destructor + //but this conflicts with id-less implementation of gst texture sink. +#if defined(GL_TEXTURE_SINK_DEBUG) && GL_TEXTURE_SINK_DEBUG > 1 + qDebug() << "release frame" << m_frameNumber; +#endif + EGLSyncKHR sync = eglCreateSyncKHR(eglGetDisplay((EGLNativeDisplayType)QX11Info::display()), EGL_SYNC_FENCE_KHR, NULL); + meego_gst_video_texture_release_frame(m_textureSink, m_frameNumber, sync); } QVariant handle() const @@ -153,7 +155,6 @@ public: private: MeegoGstVideoTexture *m_textureSink; int m_frameNumber; - EGLSyncKHR m_sync; }; diff --git a/plugins/multimedia/symbian/mmf/mediaplayer/s60mediaplayersession.cpp b/plugins/multimedia/symbian/mmf/mediaplayer/s60mediaplayersession.cpp index 8b32042ba9..b68835c2c4 100644 --- a/plugins/multimedia/symbian/mmf/mediaplayer/s60mediaplayersession.cpp +++ b/plugins/multimedia/symbian/mmf/mediaplayer/s60mediaplayersession.cpp @@ -336,7 +336,7 @@ void S60MediaPlayerSession::reset() stopStalledTimer(); doStop(); doClose(); - setPosition(0); + emit positionChanged(0); setState(QMediaPlayer::StoppedState); setMediaStatus(QMediaPlayer::UnknownMediaStatus); diff --git a/plugins/multimedia/symbian/mmf/mediaplayer/s60videoplayersession.cpp b/plugins/multimedia/symbian/mmf/mediaplayer/s60videoplayersession.cpp index 9d123efc6b..23ed2a88c1 100644 --- a/plugins/multimedia/symbian/mmf/mediaplayer/s60videoplayersession.cpp +++ b/plugins/multimedia/symbian/mmf/mediaplayer/s60videoplayersession.cpp @@ -239,8 +239,10 @@ void S60VideoPlayerSession::applicationGainedFocus() m_backendInitiatedPause = false; play(); } - if (QMediaPlayer::PausedState == state()) - m_player->RefreshFrameL(); + if (QMediaPlayer::PausedState == state()) { + TRAPD(err, m_player->RefreshFrameL()); + setError(err); + } } void S60VideoPlayerSession::applicationLostFocus() diff --git a/plugins/organizer/mkcal/mkcalid.h b/plugins/organizer/mkcal/mkcalid.h index b29b0225bb..b1dc7caa01 100644 --- a/plugins/organizer/mkcal/mkcalid.h +++ b/plugins/organizer/mkcal/mkcalid.h @@ -97,7 +97,8 @@ public: #ifndef QT_NO_DEBUG_STREAM QDebug& debugStreamOut(QDebug& dbg) const { - return dbg << m_id << m_rid.dateTime() << managerUri(); + dbg << m_id << m_rid.dateTime() << managerUri(); + return dbg; } #endif uint hash() const diff --git a/plugins/sensors/meego/Sensors.conf b/plugins/sensors/meego/Sensors.conf index f3b7965518..aa3be63a38 100644 --- a/plugins/sensors/meego/Sensors.conf +++ b/plugins/sensors/meego/Sensors.conf @@ -4,7 +4,8 @@ QAmbientLightSensor=meego.als QCompass=meego.compass QMagnetometer=meego.magnetometer QOrientationSensor=meego.orientationsensor -QProximitySensor=meego.proximity +QProximitySensor=meego.proximitysensor QRotationSensor=meego.rotationsensor QTapSensor=meego.tapsensor -QLightSensor=meego.lightsensor
\ No newline at end of file +QLightSensor=meego.lightsensor +QIRProximitySensor=meego.irproximitysensor diff --git a/plugins/sensors/meego/main.cpp b/plugins/sensors/meego/main.cpp index 40981e0fe3..46e5bde767 100644 --- a/plugins/sensors/meego/main.cpp +++ b/plugins/sensors/meego/main.cpp @@ -45,6 +45,7 @@ #include "meegomagnetometer.h" #include "meegoorientationsensor.h" #include "meegoproximitysensor.h" +#include "meegoirproximitysensor.h" #include "meegorotationsensor.h" #include "meegotapsensor.h" #include "meegogyroscope.h" @@ -99,6 +100,8 @@ public: return new meegogyroscope(sensor); if (sensor->identifier() == meegolightsensor::id) return new meegolightsensor(sensor); + if (sensor->identifier() == meegoirproximitysensor::id) + return new meegoirproximitysensor(sensor); return 0; } }; diff --git a/plugins/sensors/meego/meego.pri b/plugins/sensors/meego/meego.pri index 95f586f238..11b1806e5f 100644 --- a/plugins/sensors/meego/meego.pri +++ b/plugins/sensors/meego/meego.pri @@ -8,7 +8,10 @@ HEADERS += meegosensorbase.h \ meegoproximitysensor.h \ meegorotationsensor.h \ meegotapsensor.h \ - meegolightsensor.h + meegolightsensor.h \ + meegoirproximitysensor.h \ + qirproximitysensor.h \ + qirproximitysensor_p.h \ SOURCES += meegosensorbase.cpp \ meegoaccelerometer.cpp \ @@ -18,7 +21,9 @@ SOURCES += meegosensorbase.cpp \ meegomagnetometer.cpp \ meegoorientationsensor.cpp \ meegoproximitysensor.cpp \ + meegoirproximitysensor.cpp \ meegorotationsensor.cpp \ meegotapsensor.cpp \ meegolightsensor.cpp \ + qirproximitysensor.cpp \ main.cpp diff --git a/plugins/sensors/meego/meegoaccelerometer.cpp b/plugins/sensors/meego/meegoaccelerometer.cpp index 4a1d097d6a..3813547dd2 100644 --- a/plugins/sensors/meego/meegoaccelerometer.cpp +++ b/plugins/sensors/meego/meegoaccelerometer.cpp @@ -72,17 +72,15 @@ void meegoaccelerometer::slotFrameAvailable(const QVector<XYZ>& frame) } bool meegoaccelerometer::doConnect(){ - if (m_bufferSize==1? - QObject::connect(m_sensorInterface, SIGNAL(dataAvailable(const XYZ&)), this, SLOT(slotDataAvailable(const XYZ&))): - QObject::connect(m_sensorInterface, SIGNAL(frameAvailable(const QVector<XYZ>& )),this, SLOT(slotFrameAvailable(const QVector<XYZ>& )))) - return true; - return false; + if (m_bufferSize==1) + return QObject::connect(m_sensorInterface, SIGNAL(dataAvailable(const XYZ&)), this, SLOT(slotDataAvailable(const XYZ&))); + return QObject::connect(m_sensorInterface, SIGNAL(frameAvailable(const QVector<XYZ>& )),this, SLOT(slotFrameAvailable(const QVector<XYZ>& ))); } -const QString meegoaccelerometer::sensorName(){ +QString meegoaccelerometer::sensorName() const{ return "accelerometersensor"; } -const qreal meegoaccelerometer::correctionFactor(){return GRAVITY_EARTH_THOUSANDTH;} +qreal meegoaccelerometer::correctionFactor() const{return GRAVITY_EARTH_THOUSANDTH;} diff --git a/plugins/sensors/meego/meegoaccelerometer.h b/plugins/sensors/meego/meegoaccelerometer.h index d34a45a918..357fbe2d8a 100644 --- a/plugins/sensors/meego/meegoaccelerometer.h +++ b/plugins/sensors/meego/meegoaccelerometer.h @@ -59,8 +59,8 @@ public: meegoaccelerometer(QSensor *sensor); protected: virtual bool doConnect(); - virtual const QString sensorName(); - virtual const qreal correctionFactor(); + virtual QString sensorName() const; + virtual qreal correctionFactor() const; private: diff --git a/plugins/sensors/meego/meegoals.cpp b/plugins/sensors/meego/meegoals.cpp index 7e95574114..65d008d749 100644 --- a/plugins/sensors/meego/meegoals.cpp +++ b/plugins/sensors/meego/meegoals.cpp @@ -75,15 +75,12 @@ void meegoals::slotDataAvailable(const Unsigned& data) } bool meegoals::doConnect(){ - if (!(QObject::connect(m_sensorInterface, SIGNAL(ALSChanged(const Unsigned&)), - this, SLOT(slotDataAvailable(const Unsigned&))))){ - return false; - } - return true; + return QObject::connect(m_sensorInterface, SIGNAL(ALSChanged(const Unsigned&)), + this, SLOT(slotDataAvailable(const Unsigned&))); } -const QString meegoals::sensorName(){ +QString meegoals::sensorName() const{ return "alssensor"; } diff --git a/plugins/sensors/meego/meegoals.h b/plugins/sensors/meego/meegoals.h index 0465bd3f36..4bfa093b90 100644 --- a/plugins/sensors/meego/meegoals.h +++ b/plugins/sensors/meego/meegoals.h @@ -59,7 +59,7 @@ public: meegoals(QSensor *sensor); protected: virtual bool doConnect(); - virtual const QString sensorName(); + virtual QString sensorName() const; virtual void start(); diff --git a/plugins/sensors/meego/meegocompass.cpp b/plugins/sensors/meego/meegocompass.cpp index bbb14372a3..2b8d6ad796 100644 --- a/plugins/sensors/meego/meegocompass.cpp +++ b/plugins/sensors/meego/meegocompass.cpp @@ -67,14 +67,11 @@ void meegocompass::slotDataAvailable(const Compass& data) bool meegocompass::doConnect(){ - if (!(QObject::connect(m_sensorInterface, SIGNAL(dataAvailable(const Compass&)), - this, SLOT(slotDataAvailable(const Compass&))))){ - return false; - } - return true; + return QObject::connect(m_sensorInterface, SIGNAL(dataAvailable(const Compass&)), + this, SLOT(slotDataAvailable(const Compass&))); } -const QString meegocompass::sensorName(){ +QString meegocompass::sensorName() const{ return "compasssensor"; } diff --git a/plugins/sensors/meego/meegocompass.h b/plugins/sensors/meego/meegocompass.h index e2c7cf34fa..f8c192a073 100644 --- a/plugins/sensors/meego/meegocompass.h +++ b/plugins/sensors/meego/meegocompass.h @@ -59,7 +59,7 @@ public: meegocompass(QSensor *sensor); protected: virtual bool doConnect(); - virtual const QString sensorName(); + virtual QString sensorName() const; private: QCompassReading m_reading; diff --git a/plugins/sensors/meego/meegogyroscope.cpp b/plugins/sensors/meego/meegogyroscope.cpp index c2a22406e0..1514ee0a6e 100644 --- a/plugins/sensors/meego/meegogyroscope.cpp +++ b/plugins/sensors/meego/meegogyroscope.cpp @@ -73,15 +73,13 @@ void meegogyroscope::slotFrameAvailable(const QVector<XYZ>& frame) } bool meegogyroscope::doConnect(){ - if (m_bufferSize==1? - QObject::connect(m_sensorInterface, SIGNAL(dataAvailable(const XYZ&)), this, SLOT(slotDataAvailable(const XYZ&))): - QObject::connect(m_sensorInterface, SIGNAL(frameAvailable(const QVector<XYZ>& )),this, SLOT(slotFrameAvailable(const QVector<XYZ>& )))) - return true; - return false; + if (m_bufferSize==1) + return QObject::connect(m_sensorInterface, SIGNAL(dataAvailable(const XYZ&)), this, SLOT(slotDataAvailable(const XYZ&))); + return QObject::connect(m_sensorInterface, SIGNAL(frameAvailable(const QVector<XYZ>& )),this, SLOT(slotFrameAvailable(const QVector<XYZ>& ))); } -const QString meegogyroscope::sensorName(){ +QString meegogyroscope::sensorName() const{ return "gyroscopesensor"; } -const qreal meegogyroscope::correctionFactor(){return MILLI;} +qreal meegogyroscope::correctionFactor() const{return MILLI;} diff --git a/plugins/sensors/meego/meegogyroscope.h b/plugins/sensors/meego/meegogyroscope.h index 6048e9bbe2..4887ecfd60 100644 --- a/plugins/sensors/meego/meegogyroscope.h +++ b/plugins/sensors/meego/meegogyroscope.h @@ -59,8 +59,8 @@ public: meegogyroscope(QSensor *sensor); protected: virtual bool doConnect(); - virtual const QString sensorName(); - virtual const qreal correctionFactor(); + virtual QString sensorName() const; + virtual qreal correctionFactor() const; private: diff --git a/plugins/sensors/meego/meegoirproximitysensor.cpp b/plugins/sensors/meego/meegoirproximitysensor.cpp new file mode 100644 index 0000000000..379297bfe0 --- /dev/null +++ b/plugins/sensors/meego/meegoirproximitysensor.cpp @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "meegoirproximitysensor.h" +#define RM680_PS "/dev/bh1770glc_ps" + +char const * const meegoirproximitysensor::id("meego.irproximitysensor"); +bool meegoirproximitysensor::m_initDone = false; + + + +meegoirproximitysensor::meegoirproximitysensor(QSensor *sensor) + : meegosensorbase(sensor) +{ + initSensor<ProximitySensorChannelInterface>(m_initDone); + setReading<QIRProximityReading>(&m_reading); + setDescription(QLatin1String("reflectance as percentage (%) of maximum")); + addOutputRange(0, 100, 1); + addDataRate(10,10); + rangeMax = QFile::exists(RM680_PS)?255:1023; +} + +#ifdef Q_WS_MAEMO_6 +void meegoirproximitysensor::slotDataAvailable(const Proximity& proximity){ + m_reading.setReflectance((float)proximity.reflectance()*100 / rangeMax); + m_reading.setTimestamp(proximity.UnsignedData().timestamp_); + newReadingAvailable(); +} +#endif + + +bool meegoirproximitysensor::doConnect(){ +#ifdef Q_WS_MAEMO_6 + return QObject::connect(m_sensorInterface, SIGNAL(reflectanceDataAvailable(const Proximity&)), + this, SLOT(slotDataAvailable(const Proximity&))); +#endif + return false; +} + + +QString meegoirproximitysensor::sensorName() const{ + return "proximitysensor"; +} + + diff --git a/plugins/sensors/meego/meegoirproximitysensor.h b/plugins/sensors/meego/meegoirproximitysensor.h new file mode 100644 index 0000000000..7625e05487 --- /dev/null +++ b/plugins/sensors/meego/meegoirproximitysensor.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MEEGOIRPROXIMITYSENSOR_H +#define MEEGOIRPROXIMITYSENSOR_H + +#include "meegosensorbase.h" +#include <qirproximitysensor.h> +#include <proximitysensor_i.h> + + +QTM_USE_NAMESPACE + +class meegoirproximitysensor : public meegosensorbase +{ + Q_OBJECT + +public: + static char const * const id; + + meegoirproximitysensor(QSensor *sensor); +protected: + virtual bool doConnect(); + virtual QString sensorName() const; + +private: + QIRProximityReading m_reading; + static bool m_initDone; + int rangeMax; + +private slots: +#ifdef Q_WS_MAEMO_6 + void slotDataAvailable(const Proximity& proximity); +#endif +}; + +#endif diff --git a/plugins/sensors/meego/meegolightsensor.cpp b/plugins/sensors/meego/meegolightsensor.cpp index aa19eb0e11..7793f136b8 100644 --- a/plugins/sensors/meego/meegolightsensor.cpp +++ b/plugins/sensors/meego/meegolightsensor.cpp @@ -59,14 +59,11 @@ void meegolightsensor::slotDataAvailable(const Unsigned& data) } bool meegolightsensor::doConnect(){ - if (!(QObject::connect(m_sensorInterface, SIGNAL(ALSChanged(const Unsigned&)), - this, SLOT(slotDataAvailable(const Unsigned&))))){ - return false; - } - return true; + return QObject::connect(m_sensorInterface, SIGNAL(ALSChanged(const Unsigned&)), + this, SLOT(slotDataAvailable(const Unsigned&))); } -const QString meegolightsensor::sensorName(){ +QString meegolightsensor::sensorName() const{ return "alssensor"; } diff --git a/plugins/sensors/meego/meegolightsensor.h b/plugins/sensors/meego/meegolightsensor.h index 4d77299869..b66cde2957 100644 --- a/plugins/sensors/meego/meegolightsensor.h +++ b/plugins/sensors/meego/meegolightsensor.h @@ -59,7 +59,7 @@ public: meegolightsensor(QSensor *sensor); protected: virtual bool doConnect(); - virtual const QString sensorName(); + virtual QString sensorName() const; private: QLightReading m_reading; diff --git a/plugins/sensors/meego/meegomagnetometer.cpp b/plugins/sensors/meego/meegomagnetometer.cpp index 69b92e4218..069fa815f1 100644 --- a/plugins/sensors/meego/meegomagnetometer.cpp +++ b/plugins/sensors/meego/meegomagnetometer.cpp @@ -86,15 +86,13 @@ void meegomagnetometer::slotFrameAvailable(const QVector<MagneticField>& frame } bool meegomagnetometer::doConnect(){ - if (m_bufferSize==1? - QObject::connect(m_sensorInterface, SIGNAL(dataAvailable(const MagneticField&)), this, SLOT(slotDataAvailable(const MagneticField&))): - QObject::connect(m_sensorInterface, SIGNAL(frameAvailable(const QVector<MagneticField>& )),this, SLOT(slotFrameAvailable(const QVector<MagneticField>& )))) - return true; - return false; + if (m_bufferSize==1) + return QObject::connect(m_sensorInterface, SIGNAL(dataAvailable(const MagneticField&)), this, SLOT(slotDataAvailable(const MagneticField&))); + return QObject::connect(m_sensorInterface, SIGNAL(frameAvailable(const QVector<MagneticField>& )),this, SLOT(slotFrameAvailable(const QVector<MagneticField>& ))); } -const QString meegomagnetometer::sensorName(){ +QString meegomagnetometer::sensorName() const{ return "magnetometersensor"; } -const qreal meegomagnetometer::correctionFactor(){return meegomagnetometer::NANO;} +qreal meegomagnetometer::correctionFactor() const{return meegomagnetometer::NANO;} diff --git a/plugins/sensors/meego/meegomagnetometer.h b/plugins/sensors/meego/meegomagnetometer.h index b95651a4e7..fd2f461f76 100644 --- a/plugins/sensors/meego/meegomagnetometer.h +++ b/plugins/sensors/meego/meegomagnetometer.h @@ -60,8 +60,8 @@ public: protected: virtual bool doConnect(); virtual void start(); - virtual const QString sensorName(); - virtual const qreal correctionFactor(); + virtual QString sensorName() const; + virtual qreal correctionFactor() const; private: diff --git a/plugins/sensors/meego/meegoorientationsensor.cpp b/plugins/sensors/meego/meegoorientationsensor.cpp index de777da886..9bc1d603c8 100644 --- a/plugins/sensors/meego/meegoorientationsensor.cpp +++ b/plugins/sensors/meego/meegoorientationsensor.cpp @@ -71,14 +71,11 @@ void meegoorientationsensor::slotDataAvailable(const Unsigned& data) } bool meegoorientationsensor::doConnect(){ - if (!(QObject::connect(m_sensorInterface, SIGNAL(orientationChanged(const Unsigned&)), - this, SLOT(slotDataAvailable(const Unsigned&))))){ - return false; - } - return true; + return QObject::connect(m_sensorInterface, SIGNAL(orientationChanged(const Unsigned&)), + this, SLOT(slotDataAvailable(const Unsigned&))); } -const QString meegoorientationsensor::sensorName(){ +QString meegoorientationsensor::sensorName() const{ return "orientationsensor"; } diff --git a/plugins/sensors/meego/meegoorientationsensor.h b/plugins/sensors/meego/meegoorientationsensor.h index 038c71bec8..dd58fa8a0f 100644 --- a/plugins/sensors/meego/meegoorientationsensor.h +++ b/plugins/sensors/meego/meegoorientationsensor.h @@ -59,7 +59,7 @@ public: meegoorientationsensor(QSensor *sensor); protected: virtual bool doConnect(); - virtual const QString sensorName(); + virtual QString sensorName() const; virtual void start(); private: diff --git a/plugins/sensors/meego/meegoproximitysensor.cpp b/plugins/sensors/meego/meegoproximitysensor.cpp index 8513f59bf9..fb1c3bcb8b 100644 --- a/plugins/sensors/meego/meegoproximitysensor.cpp +++ b/plugins/sensors/meego/meegoproximitysensor.cpp @@ -41,11 +41,11 @@ #include "meegoproximitysensor.h" -char const * const meegoproximitysensor::id("meego.proximity"); +char const * const meegoproximitysensor::id("meego.proximitysensor"); bool meegoproximitysensor::m_initDone = false; meegoproximitysensor::meegoproximitysensor(QSensor *sensor) - : meegosensorbase(sensor) + : meegosensorbase(sensor), m_exClose(false) { initSensor<ProximitySensorChannelInterface>(m_initDone); setReading<QProximityReading>(&m_reading); @@ -63,9 +63,12 @@ void meegoproximitysensor::start(){ void meegoproximitysensor::slotDataAvailable(const Unsigned& data) { + bool close = data.x()? true: false; + if (close == m_exClose) return; m_reading.setClose(data.x()? true: false); m_reading.setTimestamp(data.UnsignedData().timestamp_); newReadingAvailable(); + m_exClose = close; } bool meegoproximitysensor::doConnect(){ @@ -74,6 +77,6 @@ bool meegoproximitysensor::doConnect(){ } -const QString meegoproximitysensor::sensorName(){ +QString meegoproximitysensor::sensorName() const{ return "proximitysensor"; } diff --git a/plugins/sensors/meego/meegoproximitysensor.h b/plugins/sensors/meego/meegoproximitysensor.h index 6c45ee905e..285b43d785 100644 --- a/plugins/sensors/meego/meegoproximitysensor.h +++ b/plugins/sensors/meego/meegoproximitysensor.h @@ -59,13 +59,14 @@ public: meegoproximitysensor(QSensor *sensor); protected: virtual bool doConnect(); - virtual const QString sensorName(); + virtual QString sensorName() const; virtual void start(); private: QProximityReading m_reading; static bool m_initDone; + bool m_exClose; private slots: void slotDataAvailable(const Unsigned& data); diff --git a/plugins/sensors/meego/meegorotationsensor.cpp b/plugins/sensors/meego/meegorotationsensor.cpp index 5a1943373a..38c285ee62 100644 --- a/plugins/sensors/meego/meegorotationsensor.cpp +++ b/plugins/sensors/meego/meegorotationsensor.cpp @@ -69,13 +69,11 @@ void meegorotationsensor::slotFrameAvailable(const QVector<XYZ>& frame) } bool meegorotationsensor::doConnect(){ - if (m_bufferSize==1? - QObject::connect(m_sensorInterface, SIGNAL(dataAvailable(const XYZ&)), this, SLOT(slotDataAvailable(const XYZ&))): - QObject::connect(m_sensorInterface, SIGNAL(frameAvailable(const QVector<XYZ>& )),this, SLOT(slotFrameAvailable(const QVector<XYZ>& )))) - return true; - return false; + if (m_bufferSize==1) + return QObject::connect(m_sensorInterface, SIGNAL(dataAvailable(const XYZ&)), this, SLOT(slotDataAvailable(const XYZ&))); + return QObject::connect(m_sensorInterface, SIGNAL(frameAvailable(const QVector<XYZ>& )),this, SLOT(slotFrameAvailable(const QVector<XYZ>& ))); } -const QString meegorotationsensor::sensorName(){ +QString meegorotationsensor::sensorName() const{ return "rotationsensor"; } diff --git a/plugins/sensors/meego/meegorotationsensor.h b/plugins/sensors/meego/meegorotationsensor.h index 52b01eca14..8c0e407615 100644 --- a/plugins/sensors/meego/meegorotationsensor.h +++ b/plugins/sensors/meego/meegorotationsensor.h @@ -59,7 +59,7 @@ public: meegorotationsensor(QSensor *sensor); protected: virtual bool doConnect(); - virtual const QString sensorName(); + virtual QString sensorName() const; private: QRotationReading m_reading; diff --git a/plugins/sensors/meego/meegosensorbase.cpp b/plugins/sensors/meego/meegosensorbase.cpp index 71efc4e283..26ffbe6d10 100644 --- a/plugins/sensors/meego/meegosensorbase.cpp +++ b/plugins/sensors/meego/meegosensorbase.cpp @@ -44,15 +44,16 @@ SensorManagerInterface* meegosensorbase::m_remoteSensorManager = 0; - -const float meegosensorbase::GRAVITY_EARTH = 9.80665; -const float meegosensorbase::GRAVITY_EARTH_THOUSANDTH = 0.00980665; +//According to wikipedia link http://en.wikipedia.org/wiki/Standard_gravity +//const float meegosensorbase::GRAVITY_EARTH = 9.812865328; +const float meegosensorbase::GRAVITY_EARTH_THOUSANDTH = 0.009812865328; const int meegosensorbase::KErrNotFound=-1; const int meegosensorbase::KErrInUse=-14; const char* const meegosensorbase::ALWAYS_ON = "alwaysOn"; const char* const meegosensorbase::BUFFER_SIZE = "bufferSize"; const char* const meegosensorbase::MAX_BUFFER_SIZE = "maxBufferSize"; const char* const meegosensorbase::EFFICIENT_BUFFER_SIZE = "efficientBufferSize"; +QStringList meegosensorbase::m_bufferingSensors = QStringList()<<"meego.accelerometer"<<"meego.magnetometer"<<"meego.gyroscope"<<"meego.rotationsensor"; meegosensorbase::meegosensorbase(QSensor *sensor) : QSensorBackend(sensor), m_sensorInterface(0), m_bufferSize(-1), m_prevOutputRange(0), m_efficientBufferSize(1), m_maxBufferSize(1) @@ -91,7 +92,7 @@ void meegosensorbase::start() int l = sensor()->outputRanges().size(); if (l>1){ if (currentRange != m_prevOutputRange){ -#ifdef Q_WS_MAEMO6 +#ifdef Q_WS_MAEMO_6 bool isOk = m_sensorInterface->setDataRangeIndex(currentRange); //NOTE THAT THE CHANGE MIGHT NOT SUCCEED, FIRST COME FIRST SERVED if (!isOk) sensorError(KErrInUse); else m_prevOutputRange = currentRange; @@ -149,8 +150,11 @@ bool meegosensorbase::doConnectAfterCheck(){ int size = bufferSize(); if (size == m_bufferSize) return true; - m_sensorInterface->setBufferSize(size); + if (m_bufferingSensors.contains(sensor()->identifier())) + m_sensorInterface->setBufferSize(size); + else size = 1; + // if multiple->single or single->multiple or if uninitialized if ((m_bufferSize>1 && size==1) || (m_bufferSize==1 && size>1) || m_bufferSize==-1){ m_bufferSize = size; @@ -166,7 +170,7 @@ bool meegosensorbase::doConnectAfterCheck(){ } -const int meegosensorbase::bufferSize(){ +int meegosensorbase::bufferSize() const{ QVariant bufferVariant = sensor()->property(BUFFER_SIZE); int bufferSize = bufferVariant.isValid()?bufferVariant.toInt():1; if (bufferSize==1) return 1; @@ -183,5 +187,5 @@ const int meegosensorbase::bufferSize(){ return bufferSize; } -const qreal meegosensorbase::correctionFactor(){return 1;} +qreal meegosensorbase::correctionFactor() const{return 1;} diff --git a/plugins/sensors/meego/meegosensorbase.h b/plugins/sensors/meego/meegosensorbase.h index 55b32db0df..449584dc44 100644 --- a/plugins/sensors/meego/meegosensorbase.h +++ b/plugins/sensors/meego/meegosensorbase.h @@ -68,9 +68,10 @@ protected: static const float GRAVITY_EARTH_THOUSANDTH; //for speed static const int KErrNotFound; static const int KErrInUse; + static QStringList m_bufferingSensors; void setRanges(qreal correctionFactor=1); - virtual const QString sensorName()=0; + virtual QString sensorName() const=0; template<typename T> void initSensor(bool &initDone) @@ -124,21 +125,28 @@ protected: } //bufferSizes - IntegerRangeList sizes = m_sensorInterface->getAvailableBufferSizes(); - int l = sizes.size(); - for (int i=0; i<l; i++){ - int second = sizes.at(i).second; - m_maxBufferSize = second>m_bufferSize? second:m_maxBufferSize; + if (m_bufferingSensors.contains(sensor()->identifier())){ + + IntegerRangeList sizes = m_sensorInterface->getAvailableBufferSizes(); + int l = sizes.size(); + for (int i=0; i<l; i++){ + int second = sizes.at(i).second; + m_maxBufferSize = second>m_bufferSize? second:m_maxBufferSize; + } + m_maxBufferSize = m_maxBufferSize<0?1:m_maxBufferSize; + //SensorFW guarantees to provide the most efficient size first + //TODO: remove from comments + //m_efficientBufferSize = m_sensorInterface->hwBuffering()? (l>0?sizes.at(0).first:1) : 1; } - m_maxBufferSize = m_maxBufferSize<0?1:m_maxBufferSize; - //SensorFW guarantees to provide the most efficient size first - //TODO: remove from comments -// m_efficientBufferSize = m_sensorInterface->hwBuffering()? (l>0?sizes.at(0).first:1) : 1; + else + m_maxBufferSize = 1; sensor()->setProperty(MAX_BUFFER_SIZE, m_maxBufferSize); sensor()->setProperty(EFFICIENT_BUFFER_SIZE, m_efficientBufferSize); - if (sensor()->type()=="QAmbientLightSensor") return; // SensorFW returns lux values, plugin enumerated values + QString type = sensor()->type(); + if (type=="QAmbientLightSensor") return; // SensorFW returns lux values, plugin enumerated values + if (type=="QIRProximitySensor") return; // SensorFW returns raw reflectance values, plugin % of max reflectance if (name=="accelerometersensor") return; // SensorFW returns milliGs, plugin m/s^2 if (name=="magnetometersensor") return; // SensorFW returns nanoTeslas, plugin Teslas if (name=="gyroscopesensor") return; // SensorFW returns DSPs, plugin milliDSPs @@ -153,10 +161,11 @@ protected: AbstractSensorChannelInterface* m_sensorInterface; int m_bufferSize; - const int bufferSize(); - virtual const qreal correctionFactor(); + int bufferSize() const; + virtual qreal correctionFactor() const; private: + static SensorManagerInterface* m_remoteSensorManager; int m_prevOutputRange; bool doConnectAfterCheck(); diff --git a/plugins/sensors/meego/meegotapsensor.cpp b/plugins/sensors/meego/meegotapsensor.cpp index 5504c91bee..26c4b5de85 100644 --- a/plugins/sensors/meego/meegotapsensor.cpp +++ b/plugins/sensors/meego/meegotapsensor.cpp @@ -102,6 +102,6 @@ bool meegotapsensor::doConnect(){ } -const QString meegotapsensor::sensorName(){ +QString meegotapsensor::sensorName() const{ return "tapsensor"; } diff --git a/plugins/sensors/meego/meegotapsensor.h b/plugins/sensors/meego/meegotapsensor.h index 85b46e9431..dc7be9d958 100644 --- a/plugins/sensors/meego/meegotapsensor.h +++ b/plugins/sensors/meego/meegotapsensor.h @@ -60,7 +60,7 @@ public: protected: virtual bool doConnect(); virtual void start(); - virtual const QString sensorName(); + virtual QString sensorName() const; private: QTapReading m_reading; diff --git a/plugins/sensors/meego/qirproximitysensor.cpp b/plugins/sensors/meego/qirproximitysensor.cpp new file mode 100644 index 0000000000..ff94c3ebfd --- /dev/null +++ b/plugins/sensors/meego/qirproximitysensor.cpp @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qirproximitysensor.h> +#include "qirproximitysensor_p.h" + +QTM_BEGIN_NAMESPACE + +IMPLEMENT_READING(QIRProximityReading) + +/*! + \class QIRProximityReading + \ingroup sensors_reading + \inmodule QtSensors + + \brief The QIRProximityReading class holds readings from the IR proximity sensor. + + The IR (infra-red) proximity sensor detects proximity by beaming out infra-red light + and detecting how much of the light returns. + + The biggest limitation of this technology is that there is no reliable way to turn the + reflectance values into distances unless both the item being detected and the ambient + conditions are known. + + \section2 QIRProximityReading Units + + The sensor reports reflectance as a percentage. That is, 0 indicates nothing was detected + within the range of the sensor and 100 indicates the infra-red signal returned at the full + power level that it was sent at. +*/ + +/*! + \property QIRProximityReading::reflectance + \brief Holds the reflectance value. + + The reflectance is a percentage (from 0 to 100) indicating how much of the transmitted + infra-red light was returned. + + \sa {QIRProximityReading Units} +*/ +qreal QIRProximityReading::reflectance() const +{ + return d->reflectance; +} + +/*! + Sets the reflectance value to \a reflectance. +*/ +void QIRProximityReading::setReflectance(qreal reflectance) +{ + d->reflectance = reflectance; +} + +// ===================================================================== + +/*! + \class QIRProximityFilter + \ingroup sensors_filter + \inmodule QtSensors + + \brief The QIRProximityFilter class is a convenience wrapper around QSensorFilter. + + The only difference is that the filter() method features a pointer to QIRProximityReading + instead of QSensorReading. +*/ + +/*! + \fn QIRProximityFilter::filter(QIRProximityReading *reading) + + Called when \a reading changes. Returns false to prevent the reading from propagating. + + \sa QSensorFilter::filter() +*/ + +char const * const QIRProximitySensor::type("QIRProximitySensor"); + +/*! + \class QIRProximitySensor + \ingroup sensors_type + \inmodule QtSensors + + \brief The QIRProximitySensor class is a convenience wrapper around QSensor. + + The only behavioural difference is that this class sets the type properly. + + This class also features a reading() function that returns a QIRProximityReading instead of a QSensorReading. + + For details about how the sensor works, see \l QIRProximityReading. + + \sa QIRProximityReading +*/ + +/*! + \fn QIRProximitySensor::QIRProximitySensor(QObject *parent) + + Construct the sensor as a child of \a parent. +*/ + +/*! + \fn QIRProximitySensor::~QIRProximitySensor() + + Destroy the sensor. Stops the sensor if it has not already been stopped. +*/ + +/*! + \fn QIRProximitySensor::reading() const + + Returns the reading class for this sensor. + + \sa QSensor::reading() +*/ + + +#include "moc_qirproximitysensor.cpp" +QTM_END_NAMESPACE diff --git a/plugins/sensors/meego/qirproximitysensor.h b/plugins/sensors/meego/qirproximitysensor.h new file mode 100644 index 0000000000..fd57f89d80 --- /dev/null +++ b/plugins/sensors/meego/qirproximitysensor.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QIRPROXIMITYSENSOR_H +#define QIRPROXIMITYSENSOR_H + +#include <qsensor.h> + +QTM_BEGIN_NAMESPACE + +class QIRProximityReadingPrivate; + +class Q_SENSORS_EXPORT QIRProximityReading : public QSensorReading +{ + Q_OBJECT + Q_PROPERTY(qreal reflectance READ reflectance) + DECLARE_READING(QIRProximityReading) +public: + qreal reflectance() const; + void setReflectance(qreal reflectance); +}; + +class Q_SENSORS_EXPORT QIRProximityFilter : public QSensorFilter +{ +public: + virtual bool filter(QIRProximityReading *reading) = 0; +private: + bool filter(QSensorReading *reading) { return filter(static_cast<QIRProximityReading*>(reading)); } +}; + +class Q_SENSORS_EXPORT QIRProximitySensor : public QSensor +{ + Q_OBJECT +public: + explicit QIRProximitySensor(QObject *parent = 0) : QSensor(QIRProximitySensor::type, parent) {} + virtual ~QIRProximitySensor() {} + QIRProximityReading *reading() const { return static_cast<QIRProximityReading*>(QSensor::reading()); } + static char const * const type; +}; + +QTM_END_NAMESPACE + +#endif + diff --git a/plugins/sensors/meego/qirproximitysensor_p.h b/plugins/sensors/meego/qirproximitysensor_p.h new file mode 100644 index 0000000000..e06e929360 --- /dev/null +++ b/plugins/sensors/meego/qirproximitysensor_p.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QIRPROXIMITYSENSOR_P_H +#define QIRPROXIMITYSENSOR_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QTM_BEGIN_NAMESPACE + +class QIRProximityReadingPrivate +{ +public: + QIRProximityReadingPrivate() + : reflectance(0) + { + } + + + + /* + * Note that this class is copied so you may need to implement + * a copy constructor if you have complex types or pointers + * as values. + */ + qreal reflectance; +}; + +QTM_END_NAMESPACE + +#endif diff --git a/plugins/sensors/n900/n900proximitysensor.cpp b/plugins/sensors/n900/n900proximitysensor.cpp index 4248c41c79..46e2c0588d 100644 --- a/plugins/sensors/n900/n900proximitysensor.cpp +++ b/plugins/sensors/n900/n900proximitysensor.cpp @@ -51,12 +51,9 @@ n900proximitysensor::n900proximitysensor(QSensor *sensor) : n900filebasedsensor(sensor) { setReading<QProximityReading>(&m_reading); - // Not sure what rate the hardware runs at. Actually, I don't - // think it's even configurable. I think the proximity state - // is updated via interrupt. This this is really about the poll - // speed. - // Report 1-100 so the app can choose the speed it wants to poll - addDataRate(1, 100); + // The proximity hardware runs at 10Hz. + // Report 1-10 so the app can choose the speed it wants to poll + addDataRate(1, 10); } void n900proximitysensor::start() diff --git a/plugins/sensors/symbian/rotationsensorsym.cpp b/plugins/sensors/symbian/rotationsensorsym.cpp index b4b166ba88..23dc122586 100644 --- a/plugins/sensors/symbian/rotationsensorsym.cpp +++ b/plugins/sensors/symbian/rotationsensorsym.cpp @@ -81,6 +81,7 @@ CRotationSensorSym::CRotationSensorSym(QSensor *sensor):CSensorBackendSym(sensor { setReading<QRotationReading>(&iReading); iBackendData.iSensorType = KSensrvChannelTypeIdRotationData; + sensor->setProperty("hasZ", QVariant(FALSE)); } /* @@ -125,24 +126,6 @@ void CRotationSensorSym::ProcessReading() iReading.setY(iData.iDeviceRotationAboutYAxis - 180); } - if(iData.iDeviceRotationAboutZAxis == TSensrvRotationData::KSensrvRotationUndefined) - { - sensor()->setProperty("hasZ", QVariant(FALSE)); - } - else - { - sensor()->setProperty("hasZ", QVariant(TRUE)); - // For z axis symbian provides reading from 0 to 359 range - // This logic maps value to Qt range -180 to 180 - if(iData.iDeviceRotationAboutZAxis >= 0 && iData.iDeviceRotationAboutZAxis <= 180) - { - iReading.setZ(180 - iData.iDeviceRotationAboutZAxis); - } - else if(iData.iDeviceRotationAboutZAxis > 180 && iData.iDeviceRotationAboutZAxis < 360) - { - iReading.setZ(0 - (iData.iDeviceRotationAboutZAxis - 180)); - } - } // Set the timestamp iReading.setTimestamp(iData.iTimeStamp.Int64()); // Release the lock |