dom/camera/GonkCameraParameters.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /*
michael@0 2 * Copyright (C) 2013-2014 Mozilla Foundation
michael@0 3 *
michael@0 4 * Licensed under the Apache License, Version 2.0 (the "License");
michael@0 5 * you may not use this file except in compliance with the License.
michael@0 6 * You may obtain a copy of the License at
michael@0 7 *
michael@0 8 * http://www.apache.org/licenses/LICENSE-2.0
michael@0 9 *
michael@0 10 * Unless required by applicable law or agreed to in writing, software
michael@0 11 * distributed under the License is distributed on an "AS IS" BASIS,
michael@0 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
michael@0 13 * See the License for the specific language governing permissions and
michael@0 14 * limitations under the License.
michael@0 15 */
michael@0 16
michael@0 17 #include "GonkCameraParameters.h"
michael@0 18 #include "camera/CameraParameters.h"
michael@0 19 #include "ICameraControl.h"
michael@0 20 #include "CameraCommon.h"
michael@0 21
michael@0 22 using namespace mozilla;
michael@0 23 using namespace android;
michael@0 24
michael@0 25 /* static */ const char*
michael@0 26 GonkCameraParameters::Parameters::GetTextKey(uint32_t aKey)
michael@0 27 {
michael@0 28 switch (aKey) {
michael@0 29 case CAMERA_PARAM_PREVIEWSIZE:
michael@0 30 return KEY_PREVIEW_SIZE;
michael@0 31 case CAMERA_PARAM_PREVIEWFORMAT:
michael@0 32 return KEY_PREVIEW_FORMAT;
michael@0 33 case CAMERA_PARAM_PREVIEWFRAMERATE:
michael@0 34 return KEY_PREVIEW_FRAME_RATE;
michael@0 35 case CAMERA_PARAM_EFFECT:
michael@0 36 return KEY_EFFECT;
michael@0 37 case CAMERA_PARAM_WHITEBALANCE:
michael@0 38 return KEY_WHITE_BALANCE;
michael@0 39 case CAMERA_PARAM_SCENEMODE:
michael@0 40 return KEY_SCENE_MODE;
michael@0 41 case CAMERA_PARAM_FLASHMODE:
michael@0 42 return KEY_FLASH_MODE;
michael@0 43 case CAMERA_PARAM_FOCUSMODE:
michael@0 44 return KEY_FOCUS_MODE;
michael@0 45 case CAMERA_PARAM_ZOOM:
michael@0 46 return KEY_ZOOM;
michael@0 47 case CAMERA_PARAM_METERINGAREAS:
michael@0 48 return KEY_METERING_AREAS;
michael@0 49 case CAMERA_PARAM_FOCUSAREAS:
michael@0 50 return KEY_FOCUS_AREAS;
michael@0 51 case CAMERA_PARAM_FOCALLENGTH:
michael@0 52 return KEY_FOCAL_LENGTH;
michael@0 53 case CAMERA_PARAM_FOCUSDISTANCENEAR:
michael@0 54 return KEY_FOCUS_DISTANCES;
michael@0 55 case CAMERA_PARAM_FOCUSDISTANCEOPTIMUM:
michael@0 56 return KEY_FOCUS_DISTANCES;
michael@0 57 case CAMERA_PARAM_FOCUSDISTANCEFAR:
michael@0 58 return KEY_FOCUS_DISTANCES;
michael@0 59 case CAMERA_PARAM_EXPOSURECOMPENSATION:
michael@0 60 return KEY_EXPOSURE_COMPENSATION;
michael@0 61 case CAMERA_PARAM_THUMBNAILQUALITY:
michael@0 62 return KEY_JPEG_THUMBNAIL_QUALITY;
michael@0 63 case CAMERA_PARAM_PICTURE_SIZE:
michael@0 64 return KEY_PICTURE_SIZE;
michael@0 65 case CAMERA_PARAM_PICTURE_FILEFORMAT:
michael@0 66 return KEY_PICTURE_FORMAT;
michael@0 67 case CAMERA_PARAM_PICTURE_ROTATION:
michael@0 68 return KEY_ROTATION;
michael@0 69 case CAMERA_PARAM_PICTURE_DATETIME:
michael@0 70 // Not every platform defines a KEY_EXIF_DATETIME;
michael@0 71 // for those that don't, we use the raw string key, and if the platform
michael@0 72 // doesn't support it, it will be ignored.
michael@0 73 //
michael@0 74 // See bug 832494.
michael@0 75 return "exif-datetime";
michael@0 76 case CAMERA_PARAM_VIDEOSIZE:
michael@0 77 return KEY_VIDEO_SIZE;
michael@0 78 case CAMERA_PARAM_ISOMODE:
michael@0 79 // Not every platform defines KEY_ISO_MODE;
michael@0 80 // for those that don't, we use the raw string key.
michael@0 81 return "iso";
michael@0 82 case CAMERA_PARAM_LUMINANCE:
michael@0 83 return "luminance-condition";
michael@0 84 case CAMERA_PARAM_SCENEMODE_HDR_RETURNNORMALPICTURE:
michael@0 85 // Not every platform defines KEY_QC_HDR_NEED_1X;
michael@0 86 // for those that don't, we use the raw string key.
michael@0 87 return "hdr-need-1x";
michael@0 88
michael@0 89 case CAMERA_PARAM_SUPPORTED_PREVIEWSIZES:
michael@0 90 return KEY_SUPPORTED_PREVIEW_SIZES;
michael@0 91 case CAMERA_PARAM_SUPPORTED_PICTURESIZES:
michael@0 92 return KEY_SUPPORTED_PICTURE_SIZES;
michael@0 93 case CAMERA_PARAM_SUPPORTED_VIDEOSIZES:
michael@0 94 return KEY_SUPPORTED_VIDEO_SIZES;
michael@0 95 case CAMERA_PARAM_SUPPORTED_PICTUREFORMATS:
michael@0 96 return KEY_SUPPORTED_PICTURE_FORMATS;
michael@0 97 case CAMERA_PARAM_SUPPORTED_WHITEBALANCES:
michael@0 98 return KEY_SUPPORTED_WHITE_BALANCE;
michael@0 99 case CAMERA_PARAM_SUPPORTED_SCENEMODES:
michael@0 100 return KEY_SUPPORTED_SCENE_MODES;
michael@0 101 case CAMERA_PARAM_SUPPORTED_EFFECTS:
michael@0 102 return KEY_SUPPORTED_EFFECTS;
michael@0 103 case CAMERA_PARAM_SUPPORTED_FLASHMODES:
michael@0 104 return KEY_SUPPORTED_FLASH_MODES;
michael@0 105 case CAMERA_PARAM_SUPPORTED_FOCUSMODES:
michael@0 106 return KEY_SUPPORTED_FOCUS_MODES;
michael@0 107 case CAMERA_PARAM_SUPPORTED_MAXFOCUSAREAS:
michael@0 108 return KEY_MAX_NUM_FOCUS_AREAS;
michael@0 109 case CAMERA_PARAM_SUPPORTED_MAXMETERINGAREAS:
michael@0 110 return KEY_MAX_NUM_METERING_AREAS;
michael@0 111 case CAMERA_PARAM_SUPPORTED_MINEXPOSURECOMPENSATION:
michael@0 112 return KEY_MIN_EXPOSURE_COMPENSATION;
michael@0 113 case CAMERA_PARAM_SUPPORTED_MAXEXPOSURECOMPENSATION:
michael@0 114 return KEY_MAX_EXPOSURE_COMPENSATION;
michael@0 115 case CAMERA_PARAM_SUPPORTED_EXPOSURECOMPENSATIONSTEP:
michael@0 116 return KEY_EXPOSURE_COMPENSATION_STEP;
michael@0 117 case CAMERA_PARAM_SUPPORTED_ZOOM:
michael@0 118 return KEY_ZOOM_SUPPORTED;
michael@0 119 case CAMERA_PARAM_SUPPORTED_ZOOMRATIOS:
michael@0 120 return KEY_ZOOM_RATIOS;
michael@0 121 case CAMERA_PARAM_SUPPORTED_MAXDETECTEDFACES:
michael@0 122 return KEY_MAX_NUM_DETECTED_FACES_HW;
michael@0 123 case CAMERA_PARAM_SUPPORTED_JPEG_THUMBNAIL_SIZES:
michael@0 124 return KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES;
michael@0 125 case CAMERA_PARAM_SUPPORTED_ISOMODES:
michael@0 126 // Not every platform defines KEY_SUPPORTED_ISO_MODES;
michael@0 127 // for those that don't, we use the raw string key.
michael@0 128 return "iso-values";
michael@0 129 default:
michael@0 130 DOM_CAMERA_LOGE("Unhandled camera parameter value %u\n", aKey);
michael@0 131 return nullptr;
michael@0 132 }
michael@0 133 }
michael@0 134
michael@0 135 GonkCameraParameters::GonkCameraParameters()
michael@0 136 : mLock(PR_NewRWLock(PR_RWLOCK_RANK_NONE, "GonkCameraParameters.Lock"))
michael@0 137 , mDirty(false)
michael@0 138 , mInitialized(false)
michael@0 139 {
michael@0 140 MOZ_COUNT_CTOR(GonkCameraParameters);
michael@0 141 if (!mLock) {
michael@0 142 MOZ_CRASH("OOM getting new PRRWLock");
michael@0 143 }
michael@0 144 }
michael@0 145
michael@0 146 GonkCameraParameters::~GonkCameraParameters()
michael@0 147 {
michael@0 148 MOZ_COUNT_DTOR(GonkCameraParameters);
michael@0 149 if (mLock) {
michael@0 150 PR_DestroyRWLock(mLock);
michael@0 151 mLock = nullptr;
michael@0 152 }
michael@0 153 }
michael@0 154
michael@0 155 nsresult
michael@0 156 GonkCameraParameters::MapIsoToGonk(const nsAString& aIso, nsACString& aIsoOut)
michael@0 157 {
michael@0 158 if (aIso.EqualsASCII("hjr")) {
michael@0 159 aIsoOut = "ISO_HJR";
michael@0 160 } else if (aIso.EqualsASCII("auto")) {
michael@0 161 aIsoOut = "auto";
michael@0 162 } else {
michael@0 163 nsAutoCString v = NS_LossyConvertUTF16toASCII(aIso);
michael@0 164 unsigned int iso;
michael@0 165 if (sscanf(v.get(), "%u", &iso) != 1) {
michael@0 166 return NS_ERROR_FAILURE;
michael@0 167 }
michael@0 168 aIsoOut = nsPrintfCString("ISO%u", iso);
michael@0 169 }
michael@0 170
michael@0 171 return NS_OK;
michael@0 172 }
michael@0 173
michael@0 174 nsresult
michael@0 175 GonkCameraParameters::MapIsoFromGonk(const char* aIso, nsAString& aIsoOut)
michael@0 176 {
michael@0 177 if (strcmp(aIso, "ISO_HJR") == 0) {
michael@0 178 aIsoOut.AssignASCII("hjr");
michael@0 179 } else if (strcmp(aIso, "auto") == 0) {
michael@0 180 aIsoOut.AssignASCII("auto");
michael@0 181 } else {
michael@0 182 unsigned int iso;
michael@0 183 if (sscanf(aIso, "ISO%u", &iso) != 1) {
michael@0 184 return NS_ERROR_FAILURE;
michael@0 185 }
michael@0 186 aIsoOut.AppendInt(iso);
michael@0 187 }
michael@0 188
michael@0 189 return NS_OK;
michael@0 190 }
michael@0 191
michael@0 192 // Any members that need to be initialized on the first parameter pull
michael@0 193 // need to get handled in here.
michael@0 194 nsresult
michael@0 195 GonkCameraParameters::Initialize()
michael@0 196 {
michael@0 197 nsresult rv;
michael@0 198
michael@0 199 rv = GetImpl(CAMERA_PARAM_SUPPORTED_MINEXPOSURECOMPENSATION, mExposureCompensationMin);
michael@0 200 if (NS_FAILED(rv)) {
michael@0 201 NS_WARNING("Failed to initialize minimum exposure compensation");
michael@0 202 mExposureCompensationMin = 0;
michael@0 203 }
michael@0 204 rv = GetImpl(CAMERA_PARAM_SUPPORTED_EXPOSURECOMPENSATIONSTEP, mExposureCompensationStep);
michael@0 205 if (NS_FAILED(rv)) {
michael@0 206 NS_WARNING("Failed to initialize exposure compensation step size");
michael@0 207 mExposureCompensationStep = 0;
michael@0 208 }
michael@0 209
michael@0 210 rv = GetListAsArray(CAMERA_PARAM_SUPPORTED_ZOOMRATIOS, mZoomRatios);
michael@0 211 if (NS_FAILED(rv)) {
michael@0 212 // zoom is not supported
michael@0 213 mZoomRatios.Clear();
michael@0 214 }
michael@0 215 for (uint32_t i = 1; i < mZoomRatios.Length(); ++i) {
michael@0 216 // Make sure the camera gave us a properly sorted zoom ratio list!
michael@0 217 if (mZoomRatios[i] < mZoomRatios[i - 1]) {
michael@0 218 NS_WARNING("Zoom ratios list is out of order, discarding");
michael@0 219 DOM_CAMERA_LOGE("zoom[%d]=%fx < zoom[%d]=%fx is out of order\n",
michael@0 220 i, mZoomRatios[i] / 100.0, i - 1, mZoomRatios[i - 1] / 100.0);
michael@0 221 mZoomRatios.Clear();
michael@0 222 break;
michael@0 223 }
michael@0 224 }
michael@0 225 if (mZoomRatios.Length() == 0) {
michael@0 226 // Always report that we support at least 1.0x zoom.
michael@0 227 *mZoomRatios.AppendElement() = 100;
michael@0 228 }
michael@0 229
michael@0 230 // The return code from GetListAsArray() doesn't matter. If it fails,
michael@0 231 // the isoModes array will be empty, and the subsequent loop won't
michael@0 232 // execute.
michael@0 233 nsTArray<nsCString> isoModes;
michael@0 234 GetListAsArray(CAMERA_PARAM_SUPPORTED_ISOMODES, isoModes);
michael@0 235 for (uint32_t i = 0; i < isoModes.Length(); ++i) {
michael@0 236 nsString v;
michael@0 237 rv = MapIsoFromGonk(isoModes[i].get(), v);
michael@0 238 if (NS_SUCCEEDED(rv)) {
michael@0 239 *mIsoModes.AppendElement() = v;
michael@0 240 }
michael@0 241 }
michael@0 242
michael@0 243 mInitialized = true;
michael@0 244 return NS_OK;
michael@0 245 }
michael@0 246
michael@0 247 // Handle nsAStrings
michael@0 248 nsresult
michael@0 249 GonkCameraParameters::SetTranslated(uint32_t aKey, const nsAString& aValue)
michael@0 250 {
michael@0 251 if (aKey == CAMERA_PARAM_ISOMODE) {
michael@0 252 nsAutoCString v;
michael@0 253 nsresult rv = MapIsoToGonk(aValue, v);
michael@0 254 if (NS_FAILED(rv)) {
michael@0 255 return rv;
michael@0 256 }
michael@0 257 return SetImpl(aKey, v.get());
michael@0 258 }
michael@0 259
michael@0 260 return SetImpl(aKey, NS_ConvertUTF16toUTF8(aValue).get());
michael@0 261 }
michael@0 262
michael@0 263 nsresult
michael@0 264 GonkCameraParameters::GetTranslated(uint32_t aKey, nsAString& aValue)
michael@0 265 {
michael@0 266 const char* val;
michael@0 267 nsresult rv = GetImpl(aKey, val);
michael@0 268 if (NS_FAILED(rv)) {
michael@0 269 return rv;
michael@0 270 }
michael@0 271 if (aKey == CAMERA_PARAM_ISOMODE) {
michael@0 272 rv = MapIsoFromGonk(val, aValue);
michael@0 273 } else if(val) {
michael@0 274 aValue.AssignASCII(val);
michael@0 275 } else {
michael@0 276 aValue.Truncate(0);
michael@0 277 }
michael@0 278 return rv;
michael@0 279 }
michael@0 280
michael@0 281 // Handle ICameraControl::Sizes
michael@0 282 nsresult
michael@0 283 GonkCameraParameters::SetTranslated(uint32_t aKey, const ICameraControl::Size& aSize)
michael@0 284 {
michael@0 285 if (aSize.width > INT_MAX || aSize.height > INT_MAX) {
michael@0 286 // AOSP can only handle signed ints.
michael@0 287 DOM_CAMERA_LOGE("Camera parameter aKey=%d out of bounds (width=%u, height=%u)\n",
michael@0 288 aSize.width, aSize.height);
michael@0 289 return NS_ERROR_INVALID_ARG;
michael@0 290 }
michael@0 291
michael@0 292 nsresult rv;
michael@0 293
michael@0 294 switch (aKey) {
michael@0 295 case CAMERA_PARAM_THUMBNAILSIZE:
michael@0 296 // This is a special case--for some reason the thumbnail size
michael@0 297 // is accessed as two separate values instead of a tuple.
michael@0 298 // XXXmikeh - make this restore the original values on error
michael@0 299 rv = SetImpl(Parameters::KEY_JPEG_THUMBNAIL_WIDTH, static_cast<int>(aSize.width));
michael@0 300 if (NS_SUCCEEDED(rv)) {
michael@0 301 rv = SetImpl(Parameters::KEY_JPEG_THUMBNAIL_HEIGHT, static_cast<int>(aSize.height));
michael@0 302 }
michael@0 303 break;
michael@0 304
michael@0 305 case CAMERA_PARAM_VIDEOSIZE:
michael@0 306 // "record-size" is probably deprecated in later ICS;
michael@0 307 // might need to set "video-size" instead of "record-size";
michael@0 308 // for the time being, set both. See bug 795332.
michael@0 309 rv = SetImpl("record-size", nsPrintfCString("%ux%u", aSize.width, aSize.height).get());
michael@0 310 if (NS_FAILED(rv)) {
michael@0 311 break;
michael@0 312 }
michael@0 313 // intentional fallthrough
michael@0 314
michael@0 315 default:
michael@0 316 rv = SetImpl(aKey, nsPrintfCString("%ux%u", aSize.width, aSize.height).get());
michael@0 317 break;
michael@0 318 }
michael@0 319
michael@0 320 if (NS_FAILED(rv)) {
michael@0 321 DOM_CAMERA_LOGE("Camera parameter aKey=%d failed to set (0x%x)\n", aKey, rv);
michael@0 322 }
michael@0 323 return rv;
michael@0 324 }
michael@0 325
michael@0 326 nsresult
michael@0 327 GonkCameraParameters::GetTranslated(uint32_t aKey, ICameraControl::Size& aSize)
michael@0 328 {
michael@0 329 nsresult rv;
michael@0 330
michael@0 331 if (aKey == CAMERA_PARAM_THUMBNAILSIZE) {
michael@0 332 int width;
michael@0 333 int height;
michael@0 334
michael@0 335 rv = GetImpl(Parameters::KEY_JPEG_THUMBNAIL_WIDTH, width);
michael@0 336 if (NS_FAILED(rv) || width < 0) {
michael@0 337 return NS_ERROR_FAILURE;
michael@0 338 }
michael@0 339 rv = GetImpl(Parameters::KEY_JPEG_THUMBNAIL_HEIGHT, height);
michael@0 340 if (NS_FAILED(rv) || height < 0) {
michael@0 341 return NS_ERROR_FAILURE;
michael@0 342 }
michael@0 343
michael@0 344 aSize.width = static_cast<uint32_t>(width);
michael@0 345 aSize.height = static_cast<uint32_t>(height);
michael@0 346 return NS_OK;
michael@0 347 }
michael@0 348
michael@0 349 const char* value;
michael@0 350 rv = GetImpl(aKey, value);
michael@0 351 if (NS_FAILED(rv) || !value || *value == '\0') {
michael@0 352 DOM_CAMERA_LOGW("Camera parameter aKey=%d not available (0x%x)\n", aKey, rv);
michael@0 353 return NS_ERROR_NOT_AVAILABLE;
michael@0 354 }
michael@0 355 if (sscanf(value, "%ux%u", &aSize.width, &aSize.height) != 2) {
michael@0 356 DOM_CAMERA_LOGE("Camera parameter aKey=%d size tuple '%s' is invalid\n", aKey, value);
michael@0 357 return NS_ERROR_FAILURE;
michael@0 358 }
michael@0 359 return NS_OK;
michael@0 360 }
michael@0 361
michael@0 362 // Handle arrays of ICameraControl::Regions
michael@0 363 nsresult
michael@0 364 GonkCameraParameters::SetTranslated(uint32_t aKey, const nsTArray<ICameraControl::Region>& aRegions)
michael@0 365 {
michael@0 366 uint32_t length = aRegions.Length();
michael@0 367
michael@0 368 if (!length) {
michael@0 369 // This tells the camera driver to revert to automatic regioning.
michael@0 370 return SetImpl(aKey, "(0,0,0,0,0)");
michael@0 371 }
michael@0 372
michael@0 373 nsCString s;
michael@0 374
michael@0 375 for (uint32_t i = 0; i < length; ++i) {
michael@0 376 const ICameraControl::Region* r = &aRegions[i];
michael@0 377 s.AppendPrintf("(%d,%d,%d,%d,%d),", r->top, r->left, r->bottom, r->right, r->weight);
michael@0 378 }
michael@0 379
michael@0 380 // remove the trailing comma
michael@0 381 s.Trim(",", false, true, true);
michael@0 382
michael@0 383 return SetImpl(aKey, s.get());
michael@0 384 }
michael@0 385
michael@0 386 nsresult
michael@0 387 GonkCameraParameters::GetTranslated(uint32_t aKey, nsTArray<ICameraControl::Region>& aRegions)
michael@0 388 {
michael@0 389 aRegions.Clear();
michael@0 390
michael@0 391 const char* value;
michael@0 392 nsresult rv = GetImpl(aKey, value);
michael@0 393 if (NS_FAILED(rv) || !value || *value == '\0') {
michael@0 394 return NS_ERROR_FAILURE;
michael@0 395 }
michael@0 396
michael@0 397 const char* p = value;
michael@0 398 uint32_t count = 1;
michael@0 399
michael@0 400 // count the number of regions in the string
michael@0 401 while ((p = strstr(p, "),("))) {
michael@0 402 ++count;
michael@0 403 p += 3;
michael@0 404 }
michael@0 405
michael@0 406 aRegions.SetCapacity(count);
michael@0 407 ICameraControl::Region* r;
michael@0 408
michael@0 409 // parse all of the region sets
michael@0 410 uint32_t i;
michael@0 411 for (i = 0, p = value; p && i < count; ++i, p = strchr(p + 1, '(')) {
michael@0 412 r = aRegions.AppendElement();
michael@0 413 if (sscanf(p, "(%d,%d,%d,%d,%u)", &r->top, &r->left, &r->bottom, &r->right, &r->weight) != 5) {
michael@0 414 DOM_CAMERA_LOGE("%s:%d : region tuple has bad format: '%s'\n", __func__, __LINE__, p);
michael@0 415 aRegions.Clear();
michael@0 416 return NS_ERROR_FAILURE;
michael@0 417 }
michael@0 418 }
michael@0 419
michael@0 420 return NS_OK;
michael@0 421 }
michael@0 422
michael@0 423 // Handle ICameraControl::Positions
michael@0 424 nsresult
michael@0 425 GonkCameraParameters::SetTranslated(uint32_t aKey, const ICameraControl::Position& aPosition)
michael@0 426 {
michael@0 427 MOZ_ASSERT(aKey == CAMERA_PARAM_PICTURE_LOCATION);
michael@0 428
michael@0 429 // Add any specified location information -- we don't care if these fail.
michael@0 430 if (!isnan(aPosition.latitude)) {
michael@0 431 DOM_CAMERA_LOGI("setting picture latitude to %lf\n", aPosition.latitude);
michael@0 432 SetImpl(Parameters::KEY_GPS_LATITUDE, nsPrintfCString("%lf", aPosition.latitude).get());
michael@0 433 }
michael@0 434 if (!isnan(aPosition.longitude)) {
michael@0 435 DOM_CAMERA_LOGI("setting picture longitude to %lf\n", aPosition.longitude);
michael@0 436 SetImpl(Parameters::KEY_GPS_LONGITUDE, nsPrintfCString("%lf", aPosition.longitude).get());
michael@0 437 }
michael@0 438 if (!isnan(aPosition.altitude)) {
michael@0 439 DOM_CAMERA_LOGI("setting picture altitude to %lf\n", aPosition.altitude);
michael@0 440 SetImpl(Parameters::KEY_GPS_ALTITUDE, nsPrintfCString("%lf", aPosition.altitude).get());
michael@0 441 }
michael@0 442 if (!isnan(aPosition.timestamp)) {
michael@0 443 DOM_CAMERA_LOGI("setting picture timestamp to %lf\n", aPosition.timestamp);
michael@0 444 SetImpl(Parameters::KEY_GPS_TIMESTAMP, nsPrintfCString("%lf", aPosition.timestamp).get());
michael@0 445 }
michael@0 446 return NS_OK;
michael@0 447 }
michael@0 448
michael@0 449 // Handle int64_ts
michael@0 450 nsresult
michael@0 451 GonkCameraParameters::SetTranslated(uint32_t aKey, const int64_t& aValue)
michael@0 452 {
michael@0 453 switch (aKey) {
michael@0 454 case CAMERA_PARAM_PICTURE_DATETIME:
michael@0 455 {
michael@0 456 // Add the non-GPS timestamp. The EXIF date/time field is formatted as
michael@0 457 // "YYYY:MM:DD HH:MM:SS", without room for a time-zone; as such, the time
michael@0 458 // is meant to be stored as a local time. Since we are given seconds from
michael@0 459 // Epoch GMT, we use localtime_r() to handle the conversion.
michael@0 460 time_t time = aValue;
michael@0 461 if (time != aValue) {
michael@0 462 DOM_CAMERA_LOGE("picture date/time '%llu' is too far in the future\n", aValue);
michael@0 463 return NS_ERROR_INVALID_ARG;
michael@0 464 }
michael@0 465
michael@0 466 struct tm t;
michael@0 467 if (!localtime_r(&time, &t)) {
michael@0 468 DOM_CAMERA_LOGE("picture date/time couldn't be converted to local time: (%d) %s\n", errno, strerror(errno));
michael@0 469 return NS_ERROR_FAILURE;
michael@0 470 }
michael@0 471
michael@0 472 char dateTime[20];
michael@0 473 if (!strftime(dateTime, sizeof(dateTime), "%Y:%m:%d %T", &t)) {
michael@0 474 DOM_CAMERA_LOGE("picture date/time couldn't be converted to string\n");
michael@0 475 return NS_ERROR_FAILURE;
michael@0 476 }
michael@0 477
michael@0 478 DOM_CAMERA_LOGI("setting picture date/time to %s\n", dateTime);
michael@0 479
michael@0 480 return SetImpl(CAMERA_PARAM_PICTURE_DATETIME, dateTime);
michael@0 481 }
michael@0 482
michael@0 483 case CAMERA_PARAM_ISOMODE:
michael@0 484 {
michael@0 485 if (aValue > INT32_MAX) {
michael@0 486 DOM_CAMERA_LOGW("Can't set ISO mode = %lld, too big\n", aValue);
michael@0 487 return NS_ERROR_INVALID_ARG;
michael@0 488 }
michael@0 489
michael@0 490 nsString s;
michael@0 491 s.AppendInt(aValue);
michael@0 492 return SetTranslated(CAMERA_PARAM_ISOMODE, s);
michael@0 493 }
michael@0 494 }
michael@0 495
michael@0 496 // You can't actually pass 64-bit parameters to Gonk. :(
michael@0 497 int32_t v = static_cast<int32_t>(aValue);
michael@0 498 if (static_cast<int64_t>(v) != aValue) {
michael@0 499 return NS_ERROR_INVALID_ARG;;
michael@0 500 }
michael@0 501 return SetImpl(aKey, v);
michael@0 502 }
michael@0 503
michael@0 504 nsresult
michael@0 505 GonkCameraParameters::GetTranslated(uint32_t aKey, int64_t& aValue)
michael@0 506 {
michael@0 507 int val;
michael@0 508 nsresult rv = GetImpl(aKey, val);
michael@0 509 if (NS_FAILED(rv)) {
michael@0 510 return rv;
michael@0 511 }
michael@0 512 aValue = val;
michael@0 513 return NS_OK;
michael@0 514 }
michael@0 515
michael@0 516 // Handle doubles
michael@0 517 nsresult
michael@0 518 GonkCameraParameters::SetTranslated(uint32_t aKey, const double& aValue)
michael@0 519 {
michael@0 520 int index;
michael@0 521 int value;
michael@0 522
michael@0 523 switch (aKey) {
michael@0 524 case CAMERA_PARAM_EXPOSURECOMPENSATION:
michael@0 525 if (mExposureCompensationStep == 0) {
michael@0 526 DOM_CAMERA_LOGE("Exposure compensation not supported, can't set %f\n", aValue);
michael@0 527 return NS_ERROR_NOT_AVAILABLE;
michael@0 528 }
michael@0 529
michael@0 530 /**
michael@0 531 * Convert from real value to a Gonk index, round
michael@0 532 * to the nearest step; index is 1-based.
michael@0 533 */
michael@0 534 index =
michael@0 535 (aValue - mExposureCompensationMin + mExposureCompensationStep / 2) /
michael@0 536 mExposureCompensationStep + 1;
michael@0 537 DOM_CAMERA_LOGI("Exposure compensation = %f --> index = %d\n", aValue, index);
michael@0 538 return SetImpl(CAMERA_PARAM_EXPOSURECOMPENSATION, index);
michael@0 539
michael@0 540 case CAMERA_PARAM_ZOOM:
michael@0 541 {
michael@0 542 /**
michael@0 543 * Convert from a real zoom multipler (e.g. 2.5x) to
michael@0 544 * the index of the nearest supported value.
michael@0 545 */
michael@0 546 value = aValue * 100.0;
michael@0 547
michael@0 548 if (value <= mZoomRatios[0]) {
michael@0 549 index = 0;
michael@0 550 } else if (value >= mZoomRatios.LastElement()) {
michael@0 551 index = mZoomRatios.Length() - 1;
michael@0 552 } else {
michael@0 553 // mZoomRatios is sorted, so we can binary search it
michael@0 554 int bottom = 0;
michael@0 555 int top = mZoomRatios.Length() - 1;
michael@0 556
michael@0 557 while (top >= bottom) {
michael@0 558 index = (top + bottom) / 2;
michael@0 559 if (value == mZoomRatios[index]) {
michael@0 560 // exact match
michael@0 561 break;
michael@0 562 }
michael@0 563 if (value > mZoomRatios[index] && value < mZoomRatios[index + 1]) {
michael@0 564 // the specified zoom value lies in this interval
michael@0 565 break;
michael@0 566 }
michael@0 567 if (value > mZoomRatios[index]) {
michael@0 568 bottom = index + 1;
michael@0 569 } else {
michael@0 570 top = index - 1;
michael@0 571 }
michael@0 572 }
michael@0 573 }
michael@0 574 DOM_CAMERA_LOGI("Zoom = %fx --> index = %d\n", aValue, index);
michael@0 575 }
michael@0 576 return SetImpl(CAMERA_PARAM_ZOOM, index);
michael@0 577 }
michael@0 578
michael@0 579 return SetImpl(aKey, aValue);
michael@0 580 }
michael@0 581
michael@0 582 nsresult
michael@0 583 GonkCameraParameters::GetTranslated(uint32_t aKey, double& aValue)
michael@0 584 {
michael@0 585 double val;
michael@0 586 int index = 0;
michael@0 587 double focusDistance[3];
michael@0 588 const char* s;
michael@0 589 nsresult rv;
michael@0 590
michael@0 591 switch (aKey) {
michael@0 592 case CAMERA_PARAM_ZOOM:
michael@0 593 rv = GetImpl(aKey, index);
michael@0 594 if (NS_SUCCEEDED(rv) && index >= 0) {
michael@0 595 val = mZoomRatios[index] / 100.0;
michael@0 596 } else {
michael@0 597 // return 1x when zooming is not supported
michael@0 598 val = 1.0;
michael@0 599 rv = NS_OK;
michael@0 600 }
michael@0 601 break;
michael@0 602
michael@0 603 /**
michael@0 604 * The gonk camera parameters API only exposes one focus distance property
michael@0 605 * that contains "Near,Optimum,Far" distances, in metres, where 'Far' may
michael@0 606 * be 'Infinity'.
michael@0 607 */
michael@0 608 case CAMERA_PARAM_FOCUSDISTANCEFAR:
michael@0 609 ++index;
michael@0 610 // intentional fallthrough
michael@0 611
michael@0 612 case CAMERA_PARAM_FOCUSDISTANCEOPTIMUM:
michael@0 613 ++index;
michael@0 614 // intentional fallthrough
michael@0 615
michael@0 616 case CAMERA_PARAM_FOCUSDISTANCENEAR:
michael@0 617 rv = GetImpl(aKey, s);
michael@0 618 if (NS_SUCCEEDED(rv)) {
michael@0 619 if (sscanf(s, "%lf,%lf,%lf", &focusDistance[0], &focusDistance[1], &focusDistance[2]) == 3) {
michael@0 620 val = focusDistance[index];
michael@0 621 } else {
michael@0 622 val = 0.0;
michael@0 623 }
michael@0 624 }
michael@0 625 break;
michael@0 626
michael@0 627 case CAMERA_PARAM_EXPOSURECOMPENSATION:
michael@0 628 rv = GetImpl(aKey, index);
michael@0 629 if (NS_SUCCEEDED(rv)) {
michael@0 630 if (!index) {
michael@0 631 // NaN indicates automatic exposure compensation
michael@0 632 val = NAN;
michael@0 633 } else {
michael@0 634 val = (index - 1) * mExposureCompensationStep + mExposureCompensationMin;
michael@0 635 DOM_CAMERA_LOGI("index = %d --> compensation = %f\n", index, val);
michael@0 636 }
michael@0 637 }
michael@0 638 break;
michael@0 639
michael@0 640 default:
michael@0 641 rv = GetImpl(aKey, val);
michael@0 642 break;
michael@0 643 }
michael@0 644
michael@0 645 if (NS_SUCCEEDED(rv)) {
michael@0 646 aValue = val;
michael@0 647 }
michael@0 648 return rv;
michael@0 649 }
michael@0 650
michael@0 651 // Handle ints
michael@0 652 nsresult
michael@0 653 GonkCameraParameters::SetTranslated(uint32_t aKey, const int& aValue)
michael@0 654 {
michael@0 655 return SetImpl(aKey, aValue);
michael@0 656 }
michael@0 657
michael@0 658 nsresult
michael@0 659 GonkCameraParameters::GetTranslated(uint32_t aKey, int& aValue)
michael@0 660 {
michael@0 661 return GetImpl(aKey, aValue);
michael@0 662 }
michael@0 663
michael@0 664 // Handle uint32_ts -- Gonk only speaks int
michael@0 665 nsresult
michael@0 666 GonkCameraParameters::SetTranslated(uint32_t aKey, const uint32_t& aValue)
michael@0 667 {
michael@0 668 if (aValue > INT_MAX) {
michael@0 669 return NS_ERROR_INVALID_ARG;
michael@0 670 }
michael@0 671
michael@0 672 int val = static_cast<int>(aValue);
michael@0 673 return SetImpl(aKey, val);
michael@0 674 }
michael@0 675
michael@0 676 nsresult
michael@0 677 GonkCameraParameters::GetTranslated(uint32_t aKey, uint32_t& aValue)
michael@0 678 {
michael@0 679 int val;
michael@0 680 nsresult rv = GetImpl(aKey, val);
michael@0 681 if (NS_FAILED(rv)) {
michael@0 682 return rv;
michael@0 683 }
michael@0 684 if (val < 0) {
michael@0 685 return NS_ERROR_FAILURE;
michael@0 686 }
michael@0 687
michael@0 688 aValue = val;
michael@0 689 return NS_OK;
michael@0 690 }
michael@0 691
michael@0 692 // Handle bools
michael@0 693 nsresult
michael@0 694 GonkCameraParameters::SetTranslated(uint32_t aKey, const bool& aValue)
michael@0 695 {
michael@0 696 return SetImpl(aKey, aValue);
michael@0 697 }
michael@0 698
michael@0 699 nsresult
michael@0 700 GonkCameraParameters::GetTranslated(uint32_t aKey, bool& aValue)
michael@0 701 {
michael@0 702 return GetImpl(aKey, aValue);
michael@0 703 }
michael@0 704
michael@0 705 nsresult
michael@0 706 ParseItem(const char* aStart, const char* aEnd, ICameraControl::Size* aItem)
michael@0 707 {
michael@0 708 if (sscanf(aStart, "%ux%u", &aItem->width, &aItem->height) == 2) {
michael@0 709 return NS_OK;
michael@0 710 }
michael@0 711
michael@0 712 DOM_CAMERA_LOGE("Size tuple has bad format: '%s'\n", __func__, __LINE__, aStart);
michael@0 713 return NS_ERROR_FAILURE;
michael@0 714 }
michael@0 715
michael@0 716 nsresult
michael@0 717 ParseItem(const char* aStart, const char* aEnd, nsAString* aItem)
michael@0 718 {
michael@0 719 if (aEnd) {
michael@0 720 aItem->AssignASCII(aStart, aEnd - aStart);
michael@0 721 } else {
michael@0 722 aItem->AssignASCII(aStart);
michael@0 723 }
michael@0 724 return NS_OK;
michael@0 725 }
michael@0 726
michael@0 727 nsresult
michael@0 728 ParseItem(const char* aStart, const char* aEnd, nsACString* aItem)
michael@0 729 {
michael@0 730 if (aEnd) {
michael@0 731 aItem->AssignASCII(aStart, aEnd - aStart);
michael@0 732 } else {
michael@0 733 aItem->AssignASCII(aStart);
michael@0 734 }
michael@0 735 return NS_OK;
michael@0 736 }
michael@0 737
michael@0 738 nsresult
michael@0 739 ParseItem(const char* aStart, const char* aEnd, double* aItem)
michael@0 740 {
michael@0 741 if (sscanf(aStart, "%lf", aItem) == 1) {
michael@0 742 return NS_OK;
michael@0 743 }
michael@0 744
michael@0 745 return NS_ERROR_FAILURE;
michael@0 746 }
michael@0 747
michael@0 748 nsresult
michael@0 749 ParseItem(const char* aStart, const char* aEnd, int* aItem)
michael@0 750 {
michael@0 751 if (sscanf(aStart, "%d", aItem) == 1) {
michael@0 752 return NS_OK;
michael@0 753 }
michael@0 754
michael@0 755 return NS_ERROR_FAILURE;
michael@0 756 }
michael@0 757
michael@0 758 template<class T> nsresult
michael@0 759 GonkCameraParameters::GetListAsArray(uint32_t aKey, nsTArray<T>& aArray)
michael@0 760 {
michael@0 761 const char* p;
michael@0 762 nsresult rv = GetImpl(aKey, p);
michael@0 763 if (NS_FAILED(rv)) {
michael@0 764 return rv;
michael@0 765 }
michael@0 766
michael@0 767 aArray.Clear();
michael@0 768
michael@0 769 // If there is no value available, just return the empty array.
michael@0 770 if (!p) {
michael@0 771 DOM_CAMERA_LOGI("Camera parameter %d not available (value is null)\n", aKey);
michael@0 772 return NS_OK;
michael@0 773 }
michael@0 774 if (*p == '\0') {
michael@0 775 DOM_CAMERA_LOGI("Camera parameter %d not available (value is empty string)\n", aKey);
michael@0 776 return NS_OK;
michael@0 777 }
michael@0 778
michael@0 779 const char* comma;
michael@0 780
michael@0 781 while (p) {
michael@0 782 T* v = aArray.AppendElement();
michael@0 783 if (!v) {
michael@0 784 aArray.Clear();
michael@0 785 return NS_ERROR_OUT_OF_MEMORY;
michael@0 786 }
michael@0 787 comma = strchr(p, ',');
michael@0 788 if (comma != p) {
michael@0 789 rv = ParseItem(p, comma, v);
michael@0 790 if (NS_FAILED(rv)) {
michael@0 791 aArray.Clear();
michael@0 792 return rv;
michael@0 793 }
michael@0 794 p = comma;
michael@0 795 }
michael@0 796 if (p) {
michael@0 797 ++p;
michael@0 798 }
michael@0 799 }
michael@0 800
michael@0 801 return NS_OK;
michael@0 802 }
michael@0 803
michael@0 804 nsresult
michael@0 805 GonkCameraParameters::GetTranslated(uint32_t aKey, nsTArray<nsString>& aValues)
michael@0 806 {
michael@0 807 if (aKey == CAMERA_PARAM_SUPPORTED_ISOMODES) {
michael@0 808 aValues = mIsoModes;
michael@0 809 return NS_OK;
michael@0 810 }
michael@0 811
michael@0 812 return GetListAsArray(aKey, aValues);
michael@0 813 }
michael@0 814
michael@0 815 nsresult
michael@0 816 GonkCameraParameters::GetTranslated(uint32_t aKey, nsTArray<double>& aValues)
michael@0 817 {
michael@0 818 if (aKey == CAMERA_PARAM_SUPPORTED_ZOOMRATIOS) {
michael@0 819 aValues.Clear();
michael@0 820 for (uint32_t i = 0; i < mZoomRatios.Length(); ++i) {
michael@0 821 *aValues.AppendElement() = mZoomRatios[i] / 100.0;
michael@0 822 }
michael@0 823 return NS_OK;
michael@0 824 }
michael@0 825
michael@0 826 return GetListAsArray(aKey, aValues);
michael@0 827 }
michael@0 828
michael@0 829 nsresult
michael@0 830 GonkCameraParameters::GetTranslated(uint32_t aKey, nsTArray<ICameraControl::Size>& aSizes)
michael@0 831 {
michael@0 832 return GetListAsArray(aKey, aSizes);
michael@0 833 }
michael@0 834

mercurial