void BbVideoDeviceSelectorControl::enumerateDevices(QList<QByteArray> *devices, QStringList *descriptions)
{
    devices->clear();
    descriptions->clear();

    camera_unit_t cameras[10];

    unsigned int knownCameras = 0;
    const camera_error_t result = camera_get_supported_cameras(10, &knownCameras, cameras);
    if (result != CAMERA_EOK) {
        qWarning() << "Unable to retrieve supported camera types:" << result;
        return;
    }

    for (unsigned int i = 0; i < knownCameras; ++i) {
        switch (cameras[i]) {
        case CAMERA_UNIT_FRONT:
            devices->append(BbCameraSession::cameraIdentifierFront());
            descriptions->append(tr("Front Camera"));
            break;
        case CAMERA_UNIT_REAR:
            devices->append(BbCameraSession::cameraIdentifierRear());
            descriptions->append(tr("Rear Camera"));
            break;
        case CAMERA_UNIT_DESKTOP:
            devices->append(BbCameraSession::cameraIdentifierDesktop());
            descriptions->append(tr("Desktop Camera"));
            break;
        default:
            break;
        }
    }
}
// NOTE, in this code I am purposely ignoring error return codes for the sake of clarity while
// walking through the code.  Normally, you should check the return codes for errors, as this
// will greatly help to isolate bugs.
static int
init_camera()
{
    camera_error_t err;
    unsigned int num;
    unsigned int i;
    camera_unit_t cams[CAMERA_UNIT_NUM_UNITS];
    camera_unit_t unit;
    // here are 2 ways to determine which cameras are available on a given device...
#if 0
    // METHOD 1
    // inventory the available camera units
    // NOTE: to just find the number of available cameras: camera_get_cameras(0, &num, NULL);

    camera_get_supported_cameras(CAMERA_UNIT_NUM_UNITS,
                                 &num,
                                 cams);
    for (i=0; i<num; i++) {
        fprintf(stderr, "found camera unit %d\n", cams[i]);
    }
#else
    // METHOD 2
    // inventory cameras which support a given feature set - in this case PHOTO & BURST

    camera_feature_t features[] = { CAMERA_FEATURE_PHOTO, CAMERA_FEATURE_BURST };
    camera_unit_t next = CAMERA_UNIT_NONE;
    num = 0;
	// note that this is an iterating function call which returns only one "next" unit at a time
	while (camera_find_capable(features,
							   sizeof(features)/sizeof(*features),
							   next,
							   &next) == CAMERA_EOK) {
        cams[num++] = next;
        fprintf(stderr, "camera unit %d supports the required features\n", next);
    }
#endif

    // open the first camera found
    unit = cams[0];
    fprintf(stderr, "selecting camera unit %d\n", unit);
    err = camera_open(unit,
                      CAMERA_MODE_RW | CAMERA_MODE_ROLL,
                      &handle);
    if (err != CAMERA_EOK) {
        fprintf(stderr, "camera_open() failed: %d\n", err);
        return err;
    }

    // This is the minimal required configuration for a viewfinder.
    // NOTE: we need to enable burst mode when starting the viewfinder.
    // the maximum burst framerate is 15fps.  don't trust me?  you can query
    // camera_get_photo_vf_framerates() to determine the capabilities.
    err = camera_set_photovf_property(handle,
                                      CAMERA_IMGPROP_WIN_GROUPID, vf_group,
                                      CAMERA_IMGPROP_WIN_ID, "my_viewfinder",
                                      CAMERA_IMGPROP_BURSTMODE, 1,
                                      CAMERA_IMGPROP_FRAMERATE, (double)15.0);  // max for burst is 15fps.
    if (err != CAMERA_EOK) {
        // NOTE: if you need to narrow down which setting is causing an error,
        // consider breaking the above command down into multiple calls.
        // be aware that some values must be changed together though (eg. height & width)
        // in order to pass range-checking
        fprintf(stderr, "camera_set_photovf_property() failed: %d\n", err);
    } else {

        // a valid photovf and photo configuration are required before starting
        // the viewfinder.
        // the defaults for both will always be sane, however if certain properties
        // are changed in one, they may need to be changed in the other.
        // resolution is one such example (aspect ratios must match).
        // here is an example configuration for photo properties - setting up the burst divisor.
        // this is only valid in burst viewfinder mode, and will cause the camera service to
        // only deliver every 3rd frame.  (note that fractional rates are allowed).
        // why provide a divisor instead of just setting 5fps?
        camera_set_photo_property(handle,
                                  CAMERA_IMGPROP_BURSTDIVISOR, (double)3.0);  // DOUBLE!

        // callbacks are optional, however status callback is useful for detecting asynchronous events
        // unless your application requires processing of viewfinder frame data, don't bother with
        // a viewfinder callback, as it incurs some additional ipc overhead.  remember, the viewfinder
        // window itself is already rendered by the camera service, not your app.
        // NOTE: we are passing main_bps_chid as the void* arg which will then
        // be delivered to all callbacks. main_bps_chid is already a global variable,
        // so this isn't necessary, but is just done here to illustrate the convention.
        err = camera_start_photo_viewfinder(handle,
                                            NULL, //&viewfinder_callback,
                                            &status_callback,
                                            (void*)main_bps_chid);   // user-defined arg.
        if (err != CAMERA_EOK) {
            fprintf(stderr, "camera_start_photo_viewfinder() failed: %d\n", err);
        } else {
            // successfully started viewfinder
            // if it's a front-facing camera, we should mirror the viewfinder once
            // we receive it.
            if (unit == CAMERA_UNIT_FRONT) {
                shouldmirror = true;
            }
            return 0;
        }
    }
    // clean up on error
    camera_close(handle);
    handle = CAMERA_HANDLE_INVALID;
    return err;
}
// NOTE, in this code I am purposely ignoring error return codes for the sake of clarity while
// walking through the code.  Normally, you should check the return codes for errors, as this
// will greatly help to isolate bugs.
static int
init_camera()
{
    camera_error_t err;
    unsigned int num;
    unsigned int i;
    camera_unit_t cams[CAMERA_UNIT_NUM_UNITS];
    camera_unit_t unit;
    // here are 2 ways to determine which cameras are available on a given device...
#if 1
    // METHOD 1
    // inventory the available camera units
    // NOTE: to just find the number of available cameras: camera_get_cameras(0, &num, NULL);

    camera_get_supported_cameras(CAMERA_UNIT_NUM_UNITS,
                                 &num,
                                 cams);
    for (i=0; i<num; i++) {
        fprintf(stderr, "found camera unit %d\n", cams[i]);
    }
#else
    // METHOD 2
    // inventory cameras which support a given feature set - in this case PHOTO & VIDEO

    camera_feature_t features[] = { CAMERA_FEATURE_PHOTO, CAMERA_FEATURE_VIDEO };
    camera_unit_t next = CAMERA_UNIT_NONE;
    num = 0;
        // note that this is an iterating function call which returns only one "next" unit at a time
	while (camera_find_capable(features,
							   sizeof(features)/sizeof(*features),
							   next,
							   &next) == CAMERA_EOK) {
        cams[num++] = next;
        fprintf(stderr, "camera unit %d supports the required features\n", next);
    }
#endif

    // open the first camera found
    unit = cams[0];
    fprintf(stderr, "selecting camera unit %d\n", unit);
    err = camera_open(unit,
                      CAMERA_MODE_RW | CAMERA_MODE_ROLL,
                      &handle);
    if (err != CAMERA_EOK) {
        fprintf(stderr, "camera_open() failed: %d\n", err);
        return err;
    }

    // This is the minimal required configuration for a viewfinder.
    err = camera_set_photovf_property(handle,
                                      CAMERA_IMGPROP_WIN_GROUPID, vf_group,
                                      CAMERA_IMGPROP_WIN_ID, "my_viewfinder");
#if 0
    // here is a more complex example configuration:
    err = camera_set_photovf_property(handle,
                                      CAMERA_IMGPROP_WIN_GROUPID, vfWndGroupId,
                                      CAMERA_IMGPROP_WIN_ID, vfWndWindowId,
                                      CAMERA_IMGPROP_WIDTH, w,
                                      CAMERA_IMGPROP_HEIGHT, h,
                                      CAMERA_IMGPROP_HWOVERLAY, 1,
#ifdef DO_PHOTO_180
                                      CAMERA_IMGPROP_ROTATION, (rotation+180) % 360,
#else
                                      CAMERA_IMGPROP_ROTATION, rotation,
#endif
#ifdef DO_BURST
                                      CAMERA_IMGPROP_BURSTMODE, 1,
#endif
                                      CAMERA_IMGPROP_FRAMERATE, 15.0);
#endif
    if (err != CAMERA_EOK) {
        // NOTE: if you need to narrow down which setting is causing an error,
        // consider breaking the above command down into multiple calls.
        // be aware that some values must be changed together though (eg. height & width)
        // in order to pass range-checking
        fprintf(stderr, "camera_set_photovf_property() failed: %d\n", err);
    } else {
        
        // a valid photovf and photo configuration are required before starting
        // the viewfinder.
        // the defaults for both will always be sane, however if certain properties
        // are changed in one, they may need to be changed in the other.
        // resolution is one such example (aspect ratios must match).
        // here is an example configuration for photo properties. (just updating rotation)
        camera_set_photo_property(handle,
                                  CAMERA_IMGPROP_ROTATION, 180);

        // callbacks are optional, however status callback is useful for detecting asynchronous events
        // unless your application requires processing of viewfinder frame data, don't bother with
        // a viewfinder callback, as it incurs some additional ipc overhead.  remember, the viewfinder
        // window itself is already rendered by the camera service, not your app.
        err = camera_start_photo_viewfinder(handle,
                                            &viewfinder_callback,
                                            &status_callback,
                                            (void*)123);   // arbitrary user argument
        if (err != CAMERA_EOK) {
            fprintf(stderr, "camera_start_photo_viewfinder() failed: %d\n", err);
        } else {
            // successfully started viewfinder
            // if it's a front-facing camera, we should mirror the viewfinder once
            // we receive it.
            if (unit == CAMERA_UNIT_FRONT) {
                shouldmirror = true;
            }
            return 0;
        }
    }
    // clean up on error
    camera_close(handle);
    handle = CAMERA_HANDLE_INVALID;
    return err;
}