## -*- coding: utf-8 -*-
/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * !! Do not include this file directly !!
 *
 * Include camera_metadata.h instead.
 */

/**
 * ! Do not edit this file directly !
 *
 * Generated automatically from camera_metadata_tags.mako
 */

/** TODO: Nearly every enum in this file needs a description */

/**
 * Top level hierarchy definitions for camera metadata. *_INFO sections are for
 * the static metadata that can be retrived without opening the camera device.
 * New sections must be added right before ANDROID_SECTION_COUNT to maintain
 * existing enumerations.
 */
typedef enum camera_metadata_section {
  % for i in find_all_sections(metadata):
    ${path_name(i) | csym},
  % endfor
    ANDROID_SECTION_COUNT,

    VENDOR_SECTION = 0x8000
} camera_metadata_section_t;

/**
 * Hierarchy positions in enum space. All vendor extension tags must be
 * defined with tag >= VENDOR_SECTION_START
 */
typedef enum camera_metadata_section_start {
  % for i in find_all_sections(metadata):
    ${path_name(i) + '.start' | csym,ljust(30)} = ${path_name(i) | csym,pad(64)} << 16,
  % endfor
    VENDOR_SECTION_START           = VENDOR_SECTION            << 16
} camera_metadata_section_start_t;

/**
 * Main enum for defining camera metadata tags.  New entries must always go
 * before the section _END tag to preserve existing enumeration values.  In
 * addition, the name and type of the tag needs to be added to
 * system/media/camera/src/camera_metadata_tag_info.c
 */
enum camera_metadata_tag {
    % for sec in find_all_sections(metadata):
      % for idx,entry in enumerate(find_unique_entries(sec)):
        % if idx == 0:
    ${entry.name | csym,ljust(30)} = ${path_name(find_parent_section(entry)) | csym}_START,
        % else:
    ${entry.name | csym},
        % endif
      % endfor
    ${path_name(sec) | csym}_END,

    %endfor
} camera_metadata_tag_t;

/**
 * Enumeration definitions for the various entries that need them
 */

% for sec in find_all_sections(metadata):
  % for entry in find_unique_entries(sec):
    % if entry.type == 'enum':
// ${entry.name | csym}
typedef enum camera_metadata_enum_${csym(entry.name).lower()} {
      % for val in entry.enum.values:
        % if val.id is None:
    ${entry.name | csym}_${val.name},
        % else:
    ${'%s_%s'%(csym(entry.name), val.name) | pad(65)} = ${val.id},
        % endif
      % endfor
} camera_metadata_enum_${csym(entry.name).lower()}_t;

    % endif
  % endfor

%endfor

int camera_metadata_enum_snprint(uint32_t tag,
                                 uint32_t value,
                                 char *dst,
                                 size_t size) {
    const char *msg = "error: not an enum";
    int ret = -1;

    switch(tag) {
    % for sec in find_all_sections(metadata):
      % for idx,entry in enumerate(find_unique_entries(sec)):
        case ${entry.name | csym}: {
          % if entry.type == 'enum':
            switch (value) {
              % for val in entry.enum.values:
                case ${entry.name | csym}_${val.name}:
                    msg = "${val.name}";
                    ret = 0;
                    break;
              % endfor
                default:
                    msg = "error: enum value out of range";
            }
          % endif
            break;
        }
      % endfor

    %endfor
    }

    snprintf(dst, size, msg);
    return ret;
}

