2012-09-04 18:01:56 -07:00
/* This Source Code Form is subject to the terms of the Mozilla Public
* License , v . 2.0 . If a copy of the MPL was not distributed with this file ,
* You can obtain one at http : //mozilla.org/MPL/2.0/. */
# include "base/basictypes.h"
# include "nsCOMPtr.h"
# include "nsDOMClassInfo.h"
# include "jsapi.h"
# include "nsThread.h"
2013-01-24 18:45:36 -08:00
# include "mozilla/dom/ContentChild.h"
2012-09-04 18:01:56 -07:00
# include "mozilla/Services.h"
2013-01-24 18:45:36 -08:00
# include "mozilla/unused.h"
2012-09-04 18:01:56 -07:00
# include "nsIObserverService.h"
2012-09-28 22:30:52 -07:00
# include "nsIDOMDeviceStorage.h"
2013-01-24 18:45:36 -08:00
# include "nsXULAppAPI.h"
2012-09-04 18:01:56 -07:00
# include "DOMCameraManager.h"
# include "DOMCameraCapabilities.h"
# include "DOMCameraControl.h"
# include "CameraCommon.h"
using namespace mozilla ;
using namespace dom ;
DOMCI_DATA ( CameraControl , nsICameraControl )
2012-12-02 00:54:51 -08:00
NS_IMPL_CYCLE_COLLECTION_1 ( nsDOMCameraControl ,
mDOMCapabilities )
2012-09-04 18:01:56 -07:00
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION ( nsDOMCameraControl )
NS_INTERFACE_MAP_ENTRY ( nsISupports )
NS_INTERFACE_MAP_ENTRY ( nsICameraControl )
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO ( CameraControl )
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF ( nsDOMCameraControl )
NS_IMPL_CYCLE_COLLECTING_RELEASE ( nsDOMCameraControl )
nsDOMCameraControl : : ~ nsDOMCameraControl ( )
{
DOM_CAMERA_LOGT ( " %s:%d : this=%p \n " , __func__ , __LINE__ , this ) ;
}
/* readonly attribute nsICameraCapabilities capabilities; */
NS_IMETHODIMP
nsDOMCameraControl : : GetCapabilities ( nsICameraCapabilities * * aCapabilities )
{
if ( ! mDOMCapabilities ) {
mDOMCapabilities = new DOMCameraCapabilities ( mCameraControl ) ;
}
nsCOMPtr < nsICameraCapabilities > capabilities = mDOMCapabilities ;
capabilities . forget ( aCapabilities ) ;
return NS_OK ;
}
/* attribute DOMString effect; */
NS_IMETHODIMP
nsDOMCameraControl : : GetEffect ( nsAString & aEffect )
{
return mCameraControl - > Get ( CAMERA_PARAM_EFFECT , aEffect ) ;
}
NS_IMETHODIMP
nsDOMCameraControl : : SetEffect ( const nsAString & aEffect )
{
return mCameraControl - > Set ( CAMERA_PARAM_EFFECT , aEffect ) ;
}
/* attribute DOMString whiteBalanceMode; */
NS_IMETHODIMP
nsDOMCameraControl : : GetWhiteBalanceMode ( nsAString & aWhiteBalanceMode )
{
return mCameraControl - > Get ( CAMERA_PARAM_WHITEBALANCE , aWhiteBalanceMode ) ;
}
NS_IMETHODIMP
nsDOMCameraControl : : SetWhiteBalanceMode ( const nsAString & aWhiteBalanceMode )
{
return mCameraControl - > Set ( CAMERA_PARAM_WHITEBALANCE , aWhiteBalanceMode ) ;
}
/* attribute DOMString sceneMode; */
NS_IMETHODIMP
nsDOMCameraControl : : GetSceneMode ( nsAString & aSceneMode )
{
return mCameraControl - > Get ( CAMERA_PARAM_SCENEMODE , aSceneMode ) ;
}
NS_IMETHODIMP
nsDOMCameraControl : : SetSceneMode ( const nsAString & aSceneMode )
{
return mCameraControl - > Set ( CAMERA_PARAM_SCENEMODE , aSceneMode ) ;
}
/* attribute DOMString flashMode; */
NS_IMETHODIMP
nsDOMCameraControl : : GetFlashMode ( nsAString & aFlashMode )
{
return mCameraControl - > Get ( CAMERA_PARAM_FLASHMODE , aFlashMode ) ;
}
NS_IMETHODIMP
nsDOMCameraControl : : SetFlashMode ( const nsAString & aFlashMode )
{
return mCameraControl - > Set ( CAMERA_PARAM_FLASHMODE , aFlashMode ) ;
}
/* attribute DOMString focusMode; */
NS_IMETHODIMP
nsDOMCameraControl : : GetFocusMode ( nsAString & aFocusMode )
{
return mCameraControl - > Get ( CAMERA_PARAM_FOCUSMODE , aFocusMode ) ;
}
NS_IMETHODIMP
nsDOMCameraControl : : SetFocusMode ( const nsAString & aFocusMode )
{
return mCameraControl - > Set ( CAMERA_PARAM_FOCUSMODE , aFocusMode ) ;
}
/* attribute double zoom; */
NS_IMETHODIMP
nsDOMCameraControl : : GetZoom ( double * aZoom )
{
return mCameraControl - > Get ( CAMERA_PARAM_ZOOM , aZoom ) ;
}
NS_IMETHODIMP
nsDOMCameraControl : : SetZoom ( double aZoom )
{
return mCameraControl - > Set ( CAMERA_PARAM_ZOOM , aZoom ) ;
}
/* attribute jsval meteringAreas; */
NS_IMETHODIMP
nsDOMCameraControl : : GetMeteringAreas ( JSContext * cx , JS : : Value * aMeteringAreas )
{
return mCameraControl - > Get ( cx , CAMERA_PARAM_METERINGAREAS , aMeteringAreas ) ;
}
NS_IMETHODIMP
nsDOMCameraControl : : SetMeteringAreas ( JSContext * cx , const JS : : Value & aMeteringAreas )
{
return mCameraControl - > SetMeteringAreas ( cx , aMeteringAreas ) ;
}
/* attribute jsval focusAreas; */
NS_IMETHODIMP
nsDOMCameraControl : : GetFocusAreas ( JSContext * cx , JS : : Value * aFocusAreas )
{
return mCameraControl - > Get ( cx , CAMERA_PARAM_FOCUSAREAS , aFocusAreas ) ;
}
NS_IMETHODIMP
nsDOMCameraControl : : SetFocusAreas ( JSContext * cx , const JS : : Value & aFocusAreas )
{
return mCameraControl - > SetFocusAreas ( cx , aFocusAreas ) ;
}
/* readonly attribute double focalLength; */
NS_IMETHODIMP
nsDOMCameraControl : : GetFocalLength ( double * aFocalLength )
{
return mCameraControl - > Get ( CAMERA_PARAM_FOCALLENGTH , aFocalLength ) ;
}
/* readonly attribute double focusDistanceNear; */
NS_IMETHODIMP
nsDOMCameraControl : : GetFocusDistanceNear ( double * aFocusDistanceNear )
{
return mCameraControl - > Get ( CAMERA_PARAM_FOCUSDISTANCENEAR , aFocusDistanceNear ) ;
}
/* readonly attribute double focusDistanceOptimum; */
NS_IMETHODIMP
nsDOMCameraControl : : GetFocusDistanceOptimum ( double * aFocusDistanceOptimum )
{
return mCameraControl - > Get ( CAMERA_PARAM_FOCUSDISTANCEOPTIMUM , aFocusDistanceOptimum ) ;
}
/* readonly attribute double focusDistanceFar; */
NS_IMETHODIMP
nsDOMCameraControl : : GetFocusDistanceFar ( double * aFocusDistanceFar )
{
return mCameraControl - > Get ( CAMERA_PARAM_FOCUSDISTANCEFAR , aFocusDistanceFar ) ;
}
/* void setExposureCompensation (const JS::Value& aCompensation, JSContext* cx); */
NS_IMETHODIMP
nsDOMCameraControl : : SetExposureCompensation ( const JS : : Value & aCompensation , JSContext * cx )
{
if ( aCompensation . isNullOrUndefined ( ) ) {
// use NaN to switch the camera back into auto mode
return mCameraControl - > Set ( CAMERA_PARAM_EXPOSURECOMPENSATION , NAN ) ;
}
double compensation ;
if ( ! JS_ValueToNumber ( cx , aCompensation , & compensation ) ) {
return NS_ERROR_INVALID_ARG ;
}
return mCameraControl - > Set ( CAMERA_PARAM_EXPOSURECOMPENSATION , compensation ) ;
}
/* readonly attribute double exposureCompensation; */
NS_IMETHODIMP
nsDOMCameraControl : : GetExposureCompensation ( double * aExposureCompensation )
{
return mCameraControl - > Get ( CAMERA_PARAM_EXPOSURECOMPENSATION , aExposureCompensation ) ;
}
/* attribute nsICameraShutterCallback onShutter; */
NS_IMETHODIMP
nsDOMCameraControl : : GetOnShutter ( nsICameraShutterCallback * * aOnShutter )
{
2012-09-30 17:37:47 -07:00
return mCameraControl - > Get ( aOnShutter ) ;
2012-09-04 18:01:56 -07:00
}
NS_IMETHODIMP
nsDOMCameraControl : : SetOnShutter ( nsICameraShutterCallback * aOnShutter )
{
2012-09-30 17:37:47 -07:00
return mCameraControl - > Set ( aOnShutter ) ;
}
/* attribute nsICameraClosedCallback onClosed; */
NS_IMETHODIMP
nsDOMCameraControl : : GetOnClosed ( nsICameraClosedCallback * * aOnClosed )
{
return mCameraControl - > Get ( aOnClosed ) ;
}
NS_IMETHODIMP
nsDOMCameraControl : : SetOnClosed ( nsICameraClosedCallback * aOnClosed )
{
return mCameraControl - > Set ( aOnClosed ) ;
2012-09-04 18:01:56 -07:00
}
2012-11-02 13:11:50 -07:00
/* attribute nsICameraRecorderStateChange onRecorderStateChange; */
NS_IMETHODIMP
nsDOMCameraControl : : GetOnRecorderStateChange ( nsICameraRecorderStateChange * * aOnRecorderStateChange )
{
return mCameraControl - > Get ( aOnRecorderStateChange ) ;
}
NS_IMETHODIMP
nsDOMCameraControl : : SetOnRecorderStateChange ( nsICameraRecorderStateChange * aOnRecorderStateChange )
{
return mCameraControl - > Set ( aOnRecorderStateChange ) ;
}
2012-10-23 15:30:28 -07:00
/* [implicit_jscontext] void startRecording (in jsval aOptions, in nsIDOMDeviceStorage storageArea, in DOMString filename, in nsICameraStartRecordingCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
2012-09-04 18:01:56 -07:00
NS_IMETHODIMP
2012-10-23 15:30:28 -07:00
nsDOMCameraControl : : StartRecording ( const JS : : Value & aOptions , nsIDOMDeviceStorage * storageArea , const nsAString & filename , nsICameraStartRecordingCallback * onSuccess , nsICameraErrorCallback * onError , JSContext * cx )
2012-09-04 18:01:56 -07:00
{
NS_ENSURE_TRUE ( onSuccess , NS_ERROR_INVALID_ARG ) ;
2012-10-23 15:30:28 -07:00
NS_ENSURE_TRUE ( storageArea , NS_ERROR_INVALID_ARG ) ;
2013-02-11 11:37:50 -08:00
mozilla : : idl : : CameraStartRecordingOptions options ;
2012-11-02 13:11:50 -07:00
// Default values, until the dictionary parser can handle them.
options . rotation = 0 ;
options . maxFileSizeBytes = 0 ;
options . maxVideoLengthMs = 0 ;
2012-10-23 15:30:28 -07:00
nsresult rv = options . Init ( cx , & aOptions ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2012-09-04 18:01:56 -07:00
nsCOMPtr < nsIObserverService > obs = mozilla : : services : : GetObserverService ( ) ;
if ( ! obs ) {
NS_WARNING ( " Could not get the Observer service for CameraControl::StartRecording. " ) ;
return NS_ERROR_FAILURE ;
}
obs - > NotifyObservers ( nullptr ,
" recording-device-events " ,
NS_LITERAL_STRING ( " starting " ) . get ( ) ) ;
2013-01-24 18:45:36 -08:00
// Forward recording events to parent process.
// The events are gathered in chrome process and used for recording indicator
if ( XRE_GetProcessType ( ) ! = GeckoProcessType_Default ) {
unused < < ContentChild : : GetSingleton ( ) - > SendRecordingDeviceEvents ( NS_LITERAL_STRING ( " starting " ) ) ;
}
2012-09-04 18:01:56 -07:00
2012-12-11 02:14:06 -08:00
# ifdef MOZ_B2G
if ( ! mAudioChannelAgent ) {
mAudioChannelAgent = do_CreateInstance ( " @mozilla.org/audiochannelagent;1 " ) ;
if ( mAudioChannelAgent ) {
// Camera app will stop recording when it falls to the background, so no callback is necessary.
mAudioChannelAgent - > Init ( AUDIO_CHANNEL_CONTENT , nullptr ) ;
// Video recording doesn't output any sound, so it's not necessary to check canPlay.
bool canPlay ;
mAudioChannelAgent - > StartPlaying ( & canPlay ) ;
}
}
# endif
2012-10-23 15:30:28 -07:00
nsCOMPtr < nsIFile > folder ;
storageArea - > GetRootDirectory ( getter_AddRefs ( folder ) ) ;
return mCameraControl - > StartRecording ( & options , folder , filename , onSuccess , onError ) ;
2012-09-04 18:01:56 -07:00
}
/* void stopRecording (); */
NS_IMETHODIMP
nsDOMCameraControl : : StopRecording ( )
{
nsCOMPtr < nsIObserverService > obs = mozilla : : services : : GetObserverService ( ) ;
if ( ! obs ) {
NS_WARNING ( " Could not get the Observer service for CameraControl::StopRecording. " ) ;
return NS_ERROR_FAILURE ;
}
obs - > NotifyObservers ( nullptr ,
" recording-device-events " ,
NS_LITERAL_STRING ( " shutdown " ) . get ( ) ) ;
2013-01-24 18:45:36 -08:00
// Forward recording events to parent process.
// The events are gathered in chrome process and used for recording indicator
if ( XRE_GetProcessType ( ) ! = GeckoProcessType_Default ) {
unused < < ContentChild : : GetSingleton ( ) - > SendRecordingDeviceEvents ( NS_LITERAL_STRING ( " shutdown " ) ) ;
}
2012-09-04 18:01:56 -07:00
2012-12-11 02:14:06 -08:00
# ifdef MOZ_B2G
if ( mAudioChannelAgent ) {
mAudioChannelAgent - > StopPlaying ( ) ;
mAudioChannelAgent = nullptr ;
}
# endif
2012-09-04 18:01:56 -07:00
return mCameraControl - > StopRecording ( ) ;
}
/* [implicit_jscontext] void getPreviewStream (in jsval aOptions, in nsICameraPreviewStreamCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
NS_IMETHODIMP
nsDOMCameraControl : : GetPreviewStream ( const JS : : Value & aOptions , nsICameraPreviewStreamCallback * onSuccess , nsICameraErrorCallback * onError , JSContext * cx )
{
NS_ENSURE_TRUE ( onSuccess , NS_ERROR_INVALID_ARG ) ;
2013-02-11 11:37:50 -08:00
mozilla : : idl : : CameraSize size ;
2012-09-04 18:01:56 -07:00
nsresult rv = size . Init ( cx , & aOptions ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
return mCameraControl - > GetPreviewStream ( size , onSuccess , onError ) ;
}
/* void resumePreview(); */
NS_IMETHODIMP
nsDOMCameraControl : : ResumePreview ( )
{
return mCameraControl - > StartPreview ( nullptr ) ;
}
/* void autoFocus (in nsICameraAutoFocusCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
NS_IMETHODIMP
nsDOMCameraControl : : AutoFocus ( nsICameraAutoFocusCallback * onSuccess , nsICameraErrorCallback * onError )
{
NS_ENSURE_TRUE ( onSuccess , NS_ERROR_INVALID_ARG ) ;
return mCameraControl - > AutoFocus ( onSuccess , onError ) ;
}
/* void takePicture (in jsval aOptions, in nsICameraTakePictureCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
NS_IMETHODIMP
nsDOMCameraControl : : TakePicture ( const JS : : Value & aOptions , nsICameraTakePictureCallback * onSuccess , nsICameraErrorCallback * onError , JSContext * cx )
{
NS_ENSURE_TRUE ( onSuccess , NS_ERROR_INVALID_ARG ) ;
2013-02-11 11:37:50 -08:00
mozilla : : idl : : CameraPictureOptions options ;
mozilla : : idl : : CameraSize size ;
mozilla : : idl : : CameraPosition pos ;
2012-09-04 18:01:56 -07:00
nsresult rv = options . Init ( cx , & aOptions ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
rv = size . Init ( cx , & options . pictureSize ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
/**
* Default values , until the dictionary parser can handle them .
* NaN indicates no value provided .
*/
pos . latitude = NAN ;
pos . longitude = NAN ;
pos . altitude = NAN ;
pos . timestamp = NAN ;
rv = pos . Init ( cx , & options . position ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2013-01-18 13:06:28 -08:00
return mCameraControl - > TakePicture ( size , options . rotation , options . fileFormat , pos , options . dateTime , onSuccess , onError ) ;
2012-09-04 18:01:56 -07:00
}
2012-09-28 22:30:52 -07:00
/* [implicit_jscontext] void GetPreviewStreamVideoMode (in jsval aOptions, in nsICameraPreviewStreamCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
NS_IMETHODIMP
nsDOMCameraControl : : GetPreviewStreamVideoMode ( const JS : : Value & aOptions , nsICameraPreviewStreamCallback * onSuccess , nsICameraErrorCallback * onError , JSContext * cx )
{
NS_ENSURE_TRUE ( onSuccess , NS_ERROR_INVALID_ARG ) ;
2013-02-11 11:37:50 -08:00
mozilla : : idl : : CameraRecorderOptions options ;
2012-09-28 22:30:52 -07:00
nsresult rv = options . Init ( cx , & aOptions ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
return mCameraControl - > GetPreviewStreamVideoMode ( & options , onSuccess , onError ) ;
}
2012-12-23 07:54:54 -08:00
NS_IMETHODIMP
nsDOMCameraControl : : ReleaseHardware ( nsICameraReleaseCallback * onSuccess , nsICameraErrorCallback * onError )
{
return mCameraControl - > ReleaseHardware ( onSuccess , onError ) ;
}
2012-09-04 18:01:56 -07:00
class GetCameraResult : public nsRunnable
{
public :
2012-09-30 17:37:47 -07:00
GetCameraResult ( nsDOMCameraControl * aDOMCameraControl , nsresult aResult , nsICameraGetCameraCallback * onSuccess , nsICameraErrorCallback * onError , uint64_t aWindowId )
2012-09-04 18:01:56 -07:00
: mDOMCameraControl ( aDOMCameraControl )
, mResult ( aResult )
, mOnSuccessCb ( onSuccess )
, mOnErrorCb ( onError )
2012-09-30 17:37:47 -07:00
, mWindowId ( aWindowId )
2012-09-04 18:01:56 -07:00
{ }
NS_IMETHOD Run ( )
{
MOZ_ASSERT ( NS_IsMainThread ( ) ) ;
2012-09-30 17:37:47 -07:00
if ( nsDOMCameraManager : : IsWindowStillActive ( mWindowId ) ) {
DOM_CAMERA_LOGT ( " %s : this=%p -- BEFORE CALLBACK \n " , __func__ , this ) ;
if ( NS_FAILED ( mResult ) ) {
if ( mOnErrorCb ) {
mOnErrorCb - > HandleEvent ( NS_LITERAL_STRING ( " FAILURE " ) ) ;
}
} else {
if ( mOnSuccessCb ) {
mOnSuccessCb - > HandleEvent ( mDOMCameraControl ) ;
}
2012-09-04 18:01:56 -07:00
}
2012-09-30 17:37:47 -07:00
DOM_CAMERA_LOGT ( " %s : this=%p -- AFTER CALLBACK \n " , __func__ , this ) ;
2012-09-04 18:01:56 -07:00
}
/**
* Finally , release the extra reference to the DOM - facing camera control .
* See the nsDOMCameraControl constructor for the corresponding call to
* NS_ADDREF_THIS ( ) .
*/
NS_RELEASE ( mDOMCameraControl ) ;
return NS_OK ;
}
protected :
/**
* ' mDOMCameraControl ' is a raw pointer to a previously ADDREF ( ) ed object ,
* which is released in Run ( ) .
*/
nsDOMCameraControl * mDOMCameraControl ;
nsresult mResult ;
nsCOMPtr < nsICameraGetCameraCallback > mOnSuccessCb ;
nsCOMPtr < nsICameraErrorCallback > mOnErrorCb ;
2012-09-30 17:37:47 -07:00
uint64_t mWindowId ;
2012-09-04 18:01:56 -07:00
} ;
nsresult
2012-09-30 17:37:47 -07:00
nsDOMCameraControl : : Result ( nsresult aResult , nsICameraGetCameraCallback * onSuccess , nsICameraErrorCallback * onError , uint64_t aWindowId )
2012-09-04 18:01:56 -07:00
{
2012-09-30 17:37:47 -07:00
nsCOMPtr < GetCameraResult > getCameraResult = new GetCameraResult ( this , aResult , onSuccess , onError , aWindowId ) ;
2012-09-04 18:01:56 -07:00
return NS_DispatchToMainThread ( getCameraResult ) ;
}
2012-09-30 17:37:47 -07:00
void
nsDOMCameraControl : : Shutdown ( )
{
DOM_CAMERA_LOGI ( " %s:%d \n " , __func__ , __LINE__ ) ;
mCameraControl - > Shutdown ( ) ;
}