1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "base/basictypes.h"
8 #include "nsDOMClassInfo.h"
10 #include "CameraRecorderProfiles.h"
11 #include "DOMCameraControl.h"
12 #include "DOMCameraCapabilities.h"
13 #include "CameraCommon.h"
15 using namespace mozilla
;
16 using namespace mozilla::dom
;
18 DOMCI_DATA(CameraCapabilities
, nsICameraCapabilities
)
20 NS_INTERFACE_MAP_BEGIN(DOMCameraCapabilities
)
21 NS_INTERFACE_MAP_ENTRY(nsISupports
)
22 NS_INTERFACE_MAP_ENTRY(nsICameraCapabilities
)
23 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CameraCapabilities
)
26 NS_IMPL_ADDREF(DOMCameraCapabilities
)
27 NS_IMPL_RELEASE(DOMCameraCapabilities
)
30 ParseZoomRatioItemAndAdd(JSContext
* aCx
, JS::Handle
<JSObject
*> aArray
,
31 uint32_t aIndex
, const char* aStart
, char** aEnd
)
34 // make 'aEnd' follow the same semantics as strchr().
39 * The by-100 divisor is Gonk-specific. For now, assume other platforms
40 * return actual fractional multipliers.
42 double d
= strtod(aStart
, aEnd
);
47 JS::Rooted
<JS::Value
> v(aCx
, JS_NumberValue(d
));
49 if (!JS_SetElement(aCx
, aArray
, aIndex
, &v
)) {
50 return NS_ERROR_FAILURE
;
57 ParseStringItemAndAdd(JSContext
* aCx
, JS::Handle
<JSObject
*> aArray
,
58 uint32_t aIndex
, const char* aStart
, char** aEnd
)
63 s
= JS_NewStringCopyN(aCx
, aStart
, *aEnd
- aStart
);
65 s
= JS_NewStringCopyZ(aCx
, aStart
);
68 return NS_ERROR_OUT_OF_MEMORY
;
71 JS::Rooted
<JS::Value
> v(aCx
, STRING_TO_JSVAL(s
));
72 if (!JS_SetElement(aCx
, aArray
, aIndex
, &v
)) {
73 return NS_ERROR_FAILURE
;
80 ParseDimensionItemAndAdd(JSContext
* aCx
, JS::Handle
<JSObject
*> aArray
,
81 uint32_t aIndex
, const char* aStart
, char** aEnd
)
86 // make 'aEnd' follow the same semantics as strchr().
90 JS::Rooted
<JS::Value
> w(aCx
, INT_TO_JSVAL(strtol(aStart
, &x
, 10)));
91 JS::Rooted
<JS::Value
> h(aCx
, INT_TO_JSVAL(strtol(x
+ 1, aEnd
, 10)));
93 JS::Rooted
<JSObject
*> o(aCx
, JS_NewObject(aCx
, nullptr, nullptr, nullptr));
95 return NS_ERROR_OUT_OF_MEMORY
;
98 if (!JS_SetProperty(aCx
, o
, "width", w
)) {
99 return NS_ERROR_FAILURE
;
101 if (!JS_SetProperty(aCx
, o
, "height", h
)) {
102 return NS_ERROR_FAILURE
;
105 JS::Rooted
<JS::Value
> v(aCx
, OBJECT_TO_JSVAL(o
));
106 if (!JS_SetElement(aCx
, aArray
, aIndex
, &v
)) {
107 return NS_ERROR_FAILURE
;
114 DOMCameraCapabilities::ParameterListToNewArray(JSContext
* aCx
,
115 JS::MutableHandle
<JSObject
*> aArray
,
117 ParseItemAndAddFunc aParseItemAndAdd
)
119 NS_ENSURE_TRUE(mCamera
, NS_ERROR_NOT_AVAILABLE
);
121 const char* value
= mCamera
->GetParameterConstChar(aKey
);
123 // in case we get nonsense data back
128 aArray
.set(JS_NewArrayObject(aCx
, 0, nullptr));
130 return NS_ERROR_OUT_OF_MEMORY
;
133 const char* p
= value
;
140 * In C's string.h, strchr() is declared as returning 'char*'; in C++'s
141 * cstring, it is declared as returning 'const char*', _except_ in MSVC,
142 * where the C version is declared to return const like the C++ version.
144 * Unfortunately, for both cases, strtod() and strtol() take a 'char**' as
145 * the end-of-conversion pointer, so we need to cast away strchr()'s
146 * const-ness here to make the MSVC build everything happy.
148 q
= const_cast<char*>(strchr(p
, ','));
149 if (q
!= p
) { // skip consecutive delimiters, just in case
150 rv
= aParseItemAndAdd(aCx
, aArray
, index
, p
, &q
);
151 NS_ENSURE_SUCCESS(rv
, rv
);
160 return JS_FreezeObject(aCx
, aArray
) ? NS_OK
: NS_ERROR_FAILURE
;
164 DOMCameraCapabilities::StringListToNewObject(JSContext
* aCx
, JS::Value
* aArray
, uint32_t aKey
)
166 JS::Rooted
<JSObject
*> array(aCx
);
168 nsresult rv
= ParameterListToNewArray(aCx
, &array
, aKey
, ParseStringItemAndAdd
);
169 NS_ENSURE_SUCCESS(rv
, rv
);
171 *aArray
= OBJECT_TO_JSVAL(array
);
176 DOMCameraCapabilities::DimensionListToNewObject(JSContext
* aCx
, JS::Value
* aArray
, uint32_t aKey
)
178 JS::Rooted
<JSObject
*> array(aCx
);
181 rv
= ParameterListToNewArray(aCx
, &array
, aKey
, ParseDimensionItemAndAdd
);
182 NS_ENSURE_SUCCESS(rv
, rv
);
184 *aArray
= OBJECT_TO_JSVAL(array
);
188 /* readonly attribute jsval previewSizes; */
190 DOMCameraCapabilities::GetPreviewSizes(JSContext
* cx
, JS::Value
* aPreviewSizes
)
192 return DimensionListToNewObject(cx
, aPreviewSizes
, CAMERA_PARAM_SUPPORTED_PREVIEWSIZES
);
195 /* readonly attribute jsval pictureSizes; */
197 DOMCameraCapabilities::GetPictureSizes(JSContext
* cx
, JS::Value
* aPictureSizes
)
199 return DimensionListToNewObject(cx
, aPictureSizes
, CAMERA_PARAM_SUPPORTED_PICTURESIZES
);
202 /* readonly attribute jsval thumbnailSizes; */
204 DOMCameraCapabilities::GetThumbnailSizes(JSContext
* cx
, JS::Value
* aThumbnailSizes
)
206 return DimensionListToNewObject(cx
, aThumbnailSizes
, CAMERA_PARAM_SUPPORTED_JPEG_THUMBNAIL_SIZES
);
209 /* readonly attribute jsval fileFormats; */
211 DOMCameraCapabilities::GetFileFormats(JSContext
* cx
, JS::Value
* aFileFormats
)
213 return StringListToNewObject(cx
, aFileFormats
, CAMERA_PARAM_SUPPORTED_PICTUREFORMATS
);
216 /* readonly attribute jsval whiteBalanceModes; */
218 DOMCameraCapabilities::GetWhiteBalanceModes(JSContext
* cx
, JS::Value
* aWhiteBalanceModes
)
220 return StringListToNewObject(cx
, aWhiteBalanceModes
, CAMERA_PARAM_SUPPORTED_WHITEBALANCES
);
223 /* readonly attribute jsval sceneModes; */
225 DOMCameraCapabilities::GetSceneModes(JSContext
* cx
, JS::Value
* aSceneModes
)
227 return StringListToNewObject(cx
, aSceneModes
, CAMERA_PARAM_SUPPORTED_SCENEMODES
);
230 /* readonly attribute jsval effects; */
232 DOMCameraCapabilities::GetEffects(JSContext
* cx
, JS::Value
* aEffects
)
234 return StringListToNewObject(cx
, aEffects
, CAMERA_PARAM_SUPPORTED_EFFECTS
);
237 /* readonly attribute jsval flashModes; */
239 DOMCameraCapabilities::GetFlashModes(JSContext
* cx
, JS::Value
* aFlashModes
)
241 return StringListToNewObject(cx
, aFlashModes
, CAMERA_PARAM_SUPPORTED_FLASHMODES
);
244 /* readonly attribute jsval focusModes; */
246 DOMCameraCapabilities::GetFocusModes(JSContext
* cx
, JS::Value
* aFocusModes
)
248 return StringListToNewObject(cx
, aFocusModes
, CAMERA_PARAM_SUPPORTED_FOCUSMODES
);
251 /* readonly attribute long maxFocusAreas; */
253 DOMCameraCapabilities::GetMaxFocusAreas(JSContext
* cx
, int32_t* aMaxFocusAreas
)
255 NS_ENSURE_TRUE(mCamera
, NS_ERROR_NOT_AVAILABLE
);
257 const char* value
= mCamera
->GetParameterConstChar(CAMERA_PARAM_SUPPORTED_MAXFOCUSAREAS
);
259 // in case we get nonsense data back
264 *aMaxFocusAreas
= atoi(value
);
268 /* readonly attribute double minExposureCompensation; */
270 DOMCameraCapabilities::GetMinExposureCompensation(JSContext
* cx
, double* aMinExposureCompensation
)
272 NS_ENSURE_TRUE(mCamera
, NS_ERROR_NOT_AVAILABLE
);
274 const char* value
= mCamera
->GetParameterConstChar(CAMERA_PARAM_SUPPORTED_MINEXPOSURECOMPENSATION
);
276 // in case we get nonsense data back
277 *aMinExposureCompensation
= 0;
281 *aMinExposureCompensation
= atof(value
);
285 /* readonly attribute double maxExposureCompensation; */
287 DOMCameraCapabilities::GetMaxExposureCompensation(JSContext
* cx
, double* aMaxExposureCompensation
)
289 NS_ENSURE_TRUE(mCamera
, NS_ERROR_NOT_AVAILABLE
);
291 const char* value
= mCamera
->GetParameterConstChar(CAMERA_PARAM_SUPPORTED_MAXEXPOSURECOMPENSATION
);
293 // in case we get nonsense data back
294 *aMaxExposureCompensation
= 0;
298 *aMaxExposureCompensation
= atof(value
);
302 /* readonly attribute double stepExposureCompensation; */
304 DOMCameraCapabilities::GetStepExposureCompensation(JSContext
* cx
, double* aStepExposureCompensation
)
306 NS_ENSURE_TRUE(mCamera
, NS_ERROR_NOT_AVAILABLE
);
308 const char* value
= mCamera
->GetParameterConstChar(CAMERA_PARAM_SUPPORTED_EXPOSURECOMPENSATIONSTEP
);
310 // in case we get nonsense data back
311 *aStepExposureCompensation
= 0;
315 *aStepExposureCompensation
= atof(value
);
319 /* readonly attribute long maxMeteringAreas; */
321 DOMCameraCapabilities::GetMaxMeteringAreas(JSContext
* cx
, int32_t* aMaxMeteringAreas
)
323 NS_ENSURE_TRUE(mCamera
, NS_ERROR_NOT_AVAILABLE
);
325 const char* value
= mCamera
->GetParameterConstChar(CAMERA_PARAM_SUPPORTED_MAXMETERINGAREAS
);
327 // in case we get nonsense data back
328 *aMaxMeteringAreas
= 0;
332 *aMaxMeteringAreas
= atoi(value
);
336 /* readonly attribute jsval zoomRatios; */
338 DOMCameraCapabilities::GetZoomRatios(JSContext
* cx
, JS::Value
* aZoomRatios
)
340 NS_ENSURE_TRUE(mCamera
, NS_ERROR_NOT_AVAILABLE
);
342 const char* value
= mCamera
->GetParameterConstChar(CAMERA_PARAM_SUPPORTED_ZOOM
);
343 if (!value
|| strcmp(value
, "true") != 0) {
344 // if zoom is not supported, return a null object
345 *aZoomRatios
= JSVAL_NULL
;
349 JS::Rooted
<JSObject
*> array(cx
);
351 nsresult rv
= ParameterListToNewArray(cx
, &array
, CAMERA_PARAM_SUPPORTED_ZOOMRATIOS
, ParseZoomRatioItemAndAdd
);
352 NS_ENSURE_SUCCESS(rv
, rv
);
354 *aZoomRatios
= OBJECT_TO_JSVAL(array
);
358 /* readonly attribute jsval videoSizes; */
360 DOMCameraCapabilities::GetVideoSizes(JSContext
* cx
, JS::Value
* aVideoSizes
)
362 NS_ENSURE_TRUE(mCamera
, NS_ERROR_NOT_AVAILABLE
);
364 nsTArray
<mozilla::idl::CameraSize
> sizes
;
365 nsresult rv
= mCamera
->GetVideoSizes(sizes
);
366 NS_ENSURE_SUCCESS(rv
, rv
);
367 if (sizes
.Length() == 0) {
368 // video recording not supported, return a null object
369 *aVideoSizes
= JSVAL_NULL
;
373 JS::Rooted
<JSObject
*> array(cx
, JS_NewArrayObject(cx
, 0, nullptr));
375 return NS_ERROR_OUT_OF_MEMORY
;
378 for (uint32_t i
= 0; i
< sizes
.Length(); ++i
) {
379 JS::Rooted
<JSObject
*> o(cx
, JS_NewObject(cx
, nullptr, nullptr, nullptr));
380 JS::Rooted
<JS::Value
> v(cx
, INT_TO_JSVAL(sizes
[i
].width
));
381 if (!JS_SetProperty(cx
, o
, "width", v
)) {
382 return NS_ERROR_FAILURE
;
384 v
= INT_TO_JSVAL(sizes
[i
].height
);
385 if (!JS_SetProperty(cx
, o
, "height", v
)) {
386 return NS_ERROR_FAILURE
;
389 v
= OBJECT_TO_JSVAL(o
);
390 if (!JS_SetElement(cx
, array
, i
, &v
)) {
391 return NS_ERROR_FAILURE
;
395 *aVideoSizes
= OBJECT_TO_JSVAL(array
);
399 /* readonly attribute jsval recorderProfiles; */
401 DOMCameraCapabilities::GetRecorderProfiles(JSContext
* cx
, JS::Value
* aRecorderProfiles
)
403 NS_ENSURE_TRUE(mCamera
, NS_ERROR_NOT_AVAILABLE
);
405 nsRefPtr
<RecorderProfileManager
> profileMgr
= mCamera
->GetRecorderProfileManager();
407 *aRecorderProfiles
= JSVAL_NULL
;
411 JS::Rooted
<JSObject
*> o(cx
);
412 nsresult rv
= profileMgr
->GetJsObject(cx
, o
.address());
413 NS_ENSURE_SUCCESS(rv
, rv
);
415 *aRecorderProfiles
= OBJECT_TO_JSVAL(o
);