com.tomtom.camera.api.v2.CameraApiV2.java Source code

Java tutorial

Introduction

Here is the source code for com.tomtom.camera.api.v2.CameraApiV2.java

Source

/*
 * Copyright (C) 2012-2016. TomTom International BV (http://tomtom.com).
 *
 * 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.
 */

package com.tomtom.camera.api.v2;

import android.graphics.Bitmap;

import com.google.common.io.ByteStreams;
import com.google.gson.Gson;
import com.squareup.okhttp.ConnectionPool;
import com.tomtom.camera.api.BanditOkHttpClient;
import com.tomtom.camera.api.CameraApi;
import com.tomtom.camera.api.CameraApiCallback;
import com.tomtom.camera.api.converter.CameraApiGsonConverter;
import com.tomtom.camera.api.model.CameraLicenseFile;
import com.tomtom.camera.api.model.CameraSettings;
import com.tomtom.camera.api.model.CameraStatus;
import com.tomtom.camera.api.model.CameraTime;
import com.tomtom.camera.api.model.Capabilities;
import com.tomtom.camera.api.model.Firmware;
import com.tomtom.camera.api.model.Highlight;
import com.tomtom.camera.api.model.Image;
import com.tomtom.camera.api.model.ImageMode;
import com.tomtom.camera.api.model.ImageSessions;
import com.tomtom.camera.api.model.Images;
import com.tomtom.camera.api.model.LogFile;
import com.tomtom.camera.api.model.RecordingCapabilities;
import com.tomtom.camera.api.model.RecordingHighlight;
import com.tomtom.camera.api.model.Scene;
import com.tomtom.camera.api.model.SceneCapabilities;
import com.tomtom.camera.api.model.SensorDataCollection;
import com.tomtom.camera.api.model.Settings;
import com.tomtom.camera.api.model.TranscodingCapabilities;
import com.tomtom.camera.api.model.Video;
import com.tomtom.camera.api.model.VideoHighlights;
import com.tomtom.camera.api.model.VideoMode;
import com.tomtom.camera.api.model.VideoSessions;
import com.tomtom.camera.api.model.Videos;
import com.tomtom.camera.api.model.ViewfinderStatus;
import com.tomtom.camera.api.model.capability.Framerate;
import com.tomtom.camera.api.model.capability.Resolution;
import com.tomtom.camera.util.ApiUtil;
import com.tomtom.camera.util.Logger;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import retrofit.Callback;
import retrofit.RestAdapter;
import retrofit.RetrofitError;
import retrofit.client.OkClient;
import retrofit.client.Response;
import retrofit.mime.TypedFile;

/**
 * Concrete implementation of {@link CameraApi}, interface used for Camera API interactions
 */
public class CameraApiV2 implements CameraApi {

    private static final String TAG = "CameraApiWrapperV2";

    private static final int HTTP_READ_TIMEOUT_SECONDS = 120;
    private static final int MAX_RETRY_COUNT = 5;

    RetrofitCameraApiV2 mCameraApi;

    BanditOkHttpClient mDownloadHttpClient;
    RetrofitDownloadApiV2 mDownloadApi;

    public CameraApiV2(String baseUrl) {
        RestAdapter cameraApiAdapter = new RestAdapter.Builder()
                .setClient(new OkClient(BanditOkHttpClient.getSharedInstance())).setEndpoint(baseUrl)
                .setConverter(new CameraApiGsonConverter(ApiUtil.getDateHandlingGson())).build();
        mCameraApi = cameraApiAdapter.create(RetrofitCameraApiV2.class);

        mDownloadHttpClient = new BanditOkHttpClient();
        mDownloadHttpClient.setConnectionPool(new ConnectionPool(BanditOkHttpClient.MAX_IDLE_HTTP_CONNECTIONS,
                BanditOkHttpClient.KEEP_ALIVE_TIMEOUT_MS));
        mDownloadHttpClient.setReadTimeout(HTTP_READ_TIMEOUT_SECONDS, TimeUnit.SECONDS);

        RestAdapter downloadApiAdapter = new RestAdapter.Builder().setClient(new OkClient(mDownloadHttpClient))
                .setEndpoint(baseUrl).setConverter(new CameraApiGsonConverter(ApiUtil.getDateHandlingGson()))
                .build();
        mDownloadApi = downloadApiAdapter.create(RetrofitDownloadApiV2.class);
    }

    @Override
    public void getCameraStatus(CameraApiCallback<CameraStatus> callback) {
        mCameraApi.getCameraStatus(
                new CallbackAdapter<CameraStatusV2, CameraStatus>(new CameraCallback<CameraStatus>(callback)));
    }

    @Override
    public void setRecordingStatus(boolean isRecording, CameraApiCallback<Void> callback) {
        RecordingStatusV2 recordingStatusV1 = new RecordingStatusV2(isRecording);
        mCameraApi.setRecordingStatus(recordingStatusV1, new CameraCallback<Void>(callback));
    }

    @Override
    public void setViewfinderStatus(ViewfinderStatus viewfinderStatus, CameraApiCallback<Void> callback) {
        ViewfinderStatusV2 viewfinderStatusV2;
        if (viewfinderStatus.isActive()) {
            viewfinderStatusV2 = ViewfinderStatusV2.createStart(viewfinderStatus.getStreamingPort());
        } else {
            viewfinderStatusV2 = ViewfinderStatusV2.createStop();
        }

        mCameraApi.setViewfinderStatus(viewfinderStatusV2, new CameraCallback<Void>(callback));
    }

    @Override
    public void getRecordingCapabilities(CameraApiCallback<RecordingCapabilities> callback) {
        mCameraApi.getRecordingCapabilities(new CallbackAdapter<RecordingCapabilitiesV2, RecordingCapabilities>(
                new CameraCallback<RecordingCapabilities>(callback)));
    }

    @Override
    public void getTranscodingCapabilities(final CameraApiCallback<TranscodingCapabilities> callback) {
        mCameraApi.getTranscodingCapabilities(new CameraCallback<TranscodingCapabilitiesResponse>(
                new CameraApiCallback<TranscodingCapabilitiesResponse>() {
                    @Override
                    public void success(TranscodingCapabilitiesResponse transcodingCapabilitiesResponse) {
                        TranscodingCapabilitiesV2 transcodingCapabilitiesV2 = new TranscodingCapabilitiesV2(
                                transcodingCapabilitiesResponse.mTranscodingCapabilities);
                        callback.success(transcodingCapabilitiesV2);
                    }

                    @Override
                    public void error(int statusCode) {
                        callback.error(statusCode);
                    }

                    @Override
                    public void failure(Throwable t) {
                        callback.failure(t);
                    }
                }));
    }

    @Override
    public void getSceneCapabilities(CameraApiCallback<SceneCapabilities> callback) {
        mCameraApi.getScenesCapabilities(new CameraCallback<SceneCapabilitiesV2>(callback));
    }

    @Override
    public void getCapabilities(final CameraApiCallback<Capabilities> callback) {
        mCameraApi.getRecordingCapabilities(new Callback<RecordingCapabilitiesV2>() {
            final CameraCallback<Capabilities> cameraCallback = new CameraCallback<>(callback);
            int retryCount = 0;

            @Override
            public void success(final RecordingCapabilitiesV2 recordingCapabilitiesV2, Response response) {
                Logger.debug(TAG, response.getBody().toString());
                mCameraApi.getTranscodingCapabilities(new Callback<TranscodingCapabilitiesResponse>() {
                    @Override
                    public void success(final TranscodingCapabilitiesResponse transcodingCapabilitiesResponse,
                            Response response) {
                        Logger.debug(TAG, response.getBody().toString());
                        mCameraApi.getScenesCapabilities(new Callback<SceneCapabilitiesV2>() {
                            @Override
                            public void success(SceneCapabilitiesV2 sceneCapabilitiesV2, Response response) {
                                Logger.debug(TAG, response.getBody().toString());
                                TranscodingCapabilitiesV2 transcodingCapabilitiesV2 = new TranscodingCapabilitiesV2(
                                        transcodingCapabilitiesResponse.mTranscodingCapabilities);
                                CapabilitiesV2 capabilitiesV2 = new CapabilitiesV2(recordingCapabilitiesV2,
                                        transcodingCapabilitiesV2, sceneCapabilitiesV2);
                                cameraCallback.success(capabilitiesV2, response);
                            }

                            @Override
                            public void failure(RetrofitError error) {
                                Logger.debug(TAG, error.getMessage());
                                if (retryCount < MAX_RETRY_COUNT) {
                                    retryCount++;
                                    mCameraApi.getScenesCapabilities(this);
                                } else {
                                    cameraCallback.failure(error);
                                }
                            }
                        });
                    }

                    @Override
                    public void failure(RetrofitError error) {
                        Logger.debug(TAG, error.getMessage());
                        if (retryCount < MAX_RETRY_COUNT) {
                            retryCount++;
                            mCameraApi.getTranscodingCapabilities(this);
                        } else {
                            cameraCallback.failure(error);
                        }
                    }
                });
            }

            @Override
            public void failure(RetrofitError error) {
                Logger.debug(TAG, error.getMessage());
                if (retryCount < MAX_RETRY_COUNT) {
                    retryCount++;
                    mCameraApi.getRecordingCapabilities(this);
                } else {
                    callback.failure(error);
                }
            }
        });
    }

    @Override
    public void startPreview(String videoId, float startPositionSecs, float lengthSecs, int port,
            CameraApiCallback<Void> callback) {
        Logger.debug(TAG,
                "Starting preview on " + port + " for " + videoId + " " + startPositionSecs + " " + lengthSecs);
        PreviewV2 previewV2 = new PreviewV2(true, startPositionSecs, lengthSecs, videoId, port);
        mCameraApi.setPreviewStatus(previewV2, new CameraCallback<Void>(callback));
    }

    @Override
    public void stopPreview(String videoId, int previewPort, CameraApiCallback<Void> callback) {
        Logger.debug(TAG, "Stopping preview on " + previewPort);
        PreviewV2 previewV2 = new PreviewV2(false, previewPort, videoId);
        mCameraApi.setPreviewStatus(previewV2, new CameraCallback<Void>(callback));
    }

    @Override
    public void getVideoFiles(int count, CameraApiCallback<Videos> callback) {
        mCameraApi.getVideoFiles(count,
                new CallbackAdapter<VideosV2, Videos>(new CameraCallback<Videos>(callback)));
    }

    @Override
    public void getVideoSessions(int count, int offset, CameraApiCallback<VideoSessions> cameraApiCallback) {
        mCameraApi.getVideoSessions(count, offset, new CallbackAdapter<VideoSessionsV2, VideoSessions>(
                new CameraCallback<VideoSessions>(cameraApiCallback)));
    }

    @Override
    public void getVideoThumbnail(String videoId, float offsetSeconds, CameraApiCallback<Bitmap> callback) {
        mCameraApi.getVideoThumbnail(videoId, offsetSeconds, new CameraCallback<Bitmap>(callback));
    }

    @Override
    public void getHighlightThumbnail(String videoId, String highlightId, CameraApiCallback<Bitmap> callback) {
        mCameraApi.getHighlightThumbnail(videoId, highlightId, new CameraCallback<Bitmap>(callback));
    }

    @Override
    public void deleteVideo(String videoId, CameraApiCallback<Void> callback) {
        mCameraApi.deleteVideo(videoId, new CameraCallback<Void>(callback));
    }

    @Override
    public void getVideoHighlights(String videoId, CameraApiCallback<VideoHighlights> callback) {
        mCameraApi.getVideoHighlights(videoId, new CallbackAdapter<VideoHighlightsV2, VideoHighlights>(
                new CameraCallback<VideoHighlights>(callback)));
    }

    @Override
    public void addHighlightsToVideo(final Video video, final List<Highlight> highlights,
            final CameraApiCallback<VideoHighlights> callback) {
        final ArrayList<HighlightV2> highlightsV2 = new ArrayList<>(highlights.size());
        final CameraCallback<VideoHighlights> cameraCallback = new CameraCallback<>(callback);
        for (Highlight highlight : highlights) {
            HighlightV2 highlightV2 = new HighlightV2(highlight);
            highlightsV2.add(highlightV2);
        }
        VideoHighlightsV2 videoHighlightsV2 = new VideoHighlightsV2();
        videoHighlightsV2.mItems = highlightsV2;
        Logger.debug(TAG, "Highlights to be set: " + new Gson().toJson(videoHighlightsV2));
        mCameraApi.setHighlightsToVideo(video.getVideoId(), videoHighlightsV2, new Callback<VideoHighlightsV2>() {
            @Override
            public void success(VideoHighlightsV2 videoHighlightsV2, Response response) {
                for (int i = 0; i < highlightsV2.size(); i++) {
                    String id = videoHighlightsV2.getVideoHighlights().get(i).getId();
                    highlightsV2.get(i).mId = id;
                    highlightsV2.get(i).mVideoFile = video;
                    Float delOffsecs = videoHighlightsV2.getVideoHighlights().get(i).getDeliveredOffsetSecs();
                    highlightsV2.get(i).setDeliveredOffsetSecs(delOffsecs);
                    Float delLenSecs = videoHighlightsV2.getVideoHighlights().get(i).getDeliveredLengthSecs();
                    highlightsV2.get(i).setmDeliveredLengthSecs(delLenSecs);
                }
                videoHighlightsV2.mItems = highlightsV2;
                cameraCallback.success(videoHighlightsV2, response);
            }

            @Override
            public void failure(RetrofitError error) {
                cameraCallback.failure(error);
            }
        });
    }

    @Override
    public void deleteVideoHighlights(String videoId, CameraApiCallback<Void> callback) {
        mCameraApi.deleteVideoHighlights(videoId, new CameraCallback<Void>(callback));
    }

    @Override
    public void getHighlight(String videoId, String highlightId, CameraApiCallback<Highlight> callback) {
        mCameraApi.getHighlight(videoId, highlightId,
                new CallbackAdapter<HighlightV2, Highlight>(new CameraCallback<Highlight>(callback)));
    }

    @Override
    public void updateHighlight(String videoId, String highlightId, Highlight updatedHighlight,
            CameraApiCallback<Void> callback) {
        HighlightV2 updatedHighlightV2 = new HighlightV2(updatedHighlight);
        mCameraApi.updateHighlight(videoId, highlightId, updatedHighlightV2, new CameraCallback<Void>(callback));
    }

    @Override
    public void deleteHighlight(String videoId, String highlightId, CameraApiCallback<Void> callback) {
        mCameraApi.deleteHighlight(videoId, highlightId, new CameraCallback<Void>(callback));
    }

    @Override
    public void addHighlightToRecording(CameraApiCallback<Void> callback) {
        RecordingHighlight recordingHighlight = new RecordingHighlight();
        mCameraApi.addHighlightToRecording(recordingHighlight, new CameraCallback<Void>(callback));
    }

    @Override
    public void getSettings(CameraApiCallback<Settings> callback) {
        mCameraApi.getSettings(new CallbackAdapter<SettingsV2, Settings>(new CameraCallback<Settings>(callback)));
    }

    @Override
    public void setCameraSettings(CameraSettings cameraSettings, CameraApiCallback<Void> callback) {
        CameraSettingsV2 cameraSettingsV2 = new CameraSettingsV2(cameraSettings);
        mCameraApi.setCameraSettings(cameraSettingsV2, new CameraCallback<Void>(callback));
    }

    @Override
    public void getLog(final CameraApiCallback<LogFile> logFileCallback) {
        mCameraApi.getLog(new Callback() {
            @Override
            public void success(Object o, final Response response) {
                int code = response.getStatus();
                boolean isSuccess = code >= 200 && code < 300;
                if (isSuccess) {
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                String log = new String(ByteStreams.toByteArray(response.getBody().in()));
                                LogFile logFile = new LogFile(log);
                                logFileCallback.success(logFile);

                            } catch (IOException e) {
                                Logger.exception(e);
                                logFileCallback.failure(e);
                            }
                        }
                    }).start();
                } else {
                    logFileCallback.error(code);
                }
            }

            @Override
            public void failure(RetrofitError error) {
                logFileCallback.failure(error.getCause());
            }
        });
    }

    @Override
    public void updateFirmware(TypedFile firmwareFile, CameraApiCallback<Void> callback) {
        mCameraApi.upgradeFirmware(firmwareFile, new CameraCallback<Void>(callback));
    }

    @Override
    public void updateQuickGps(TypedFile quickGpsFile, CameraApiCallback<Void> callback) {
        mCameraApi.updateQuickgps(quickGpsFile, new CameraCallback<Void>(callback));
    }

    @Override
    public void updateGlonass(TypedFile glonassFile, CameraApiCallback<Void> callback) {
        mCameraApi.updateGlonass(glonassFile, new CameraCallback<Void>(callback));
    }

    @Override
    public void switchToVideoMode(Video.Mode videoMode, final CameraApiCallback<Settings> callback) {
        VideoModeV2 videoModeV2 = new VideoModeV2(videoMode, null, null, null, null);
        final CameraCallback<Settings> cameraCallback = new CameraCallback<>(callback);
        mCameraApi.switchToVideoMode(videoModeV2, new Callback<VideoModeV2>() {
            @Override
            public void success(VideoModeV2 videoModeV2, Response response) {
                mCameraApi.getSettings(new CallbackAdapter<SettingsV2, Settings>(cameraCallback));
            }

            @Override
            public void failure(RetrofitError error) {
                cameraCallback.failure(error);
            }
        });
    }

    @Override
    public void switchToImageMode(Image.Mode imageMode, final CameraApiCallback<Settings> callback) {
        ImageModeV2 imageModeV2 = new ImageModeV2(imageMode);
        final CameraCallback<Settings> cameraCallback = new CameraCallback<>(callback);
        mCameraApi.switchToImageMode(imageModeV2, new Callback<ImageModeV2>() {
            @Override
            public void success(ImageModeV2 imageModeV2, Response response) {
                mCameraApi.getSettings(new CallbackAdapter<SettingsV2, Settings>(cameraCallback));
            }

            @Override
            public void failure(RetrofitError error) {
                cameraCallback.failure(error);
            }
        });
    }

    @Override
    public void setVideoMode(VideoMode videoMode, CameraApiCallback<Void> callback) {
        VideoModeV2 videoModeV2 = new VideoModeV2(videoMode.getMode(), videoMode.getResolution(),
                videoMode.getFramerate(), videoMode.getFieldOfView(), videoMode.getSlowMotionRate(),
                videoMode.getIntervalSecs());
        mCameraApi.setVideoMode(videoModeV2, new CameraCallback<Void>(callback));
    }

    @Override
    public void setImageMode(ImageMode imageMode, CameraApiCallback<Void> callback) {
        ImageModeV2 imageModeV2 = new ImageModeV2(imageMode.getMode(), imageMode.getResolution(),
                imageMode.getDurationSecs(), imageMode.getIntervalSecs(), imageMode.getCount());
        mCameraApi.setImageMode(imageModeV2, new CameraCallback<Void>(callback));
    }

    @Override
    public void setScene(Scene scene, CameraApiCallback<Void> callback) {
        SceneV2 sceneV2 = new SceneV2(scene);
        mCameraApi.setScene(sceneV2, new CameraCallback<Void>(callback));
    }

    @Override
    public void getFirmware(CameraApiCallback<Firmware> callback) {
        mCameraApi.getFirmware(new CallbackAdapter<FirmwareV2, Firmware>(new CameraCallback<Firmware>(callback)));
    }

    @Override
    public void getImageContent(String imageId, CameraApiCallback<Bitmap> callback) {
        mCameraApi.getImageContent(imageId, new CameraCallback<Bitmap>(callback));
    }

    @Override
    public void getImage(String imageId, CameraApiCallback<Image> callback) {
        mCameraApi.getImage(imageId, new CallbackAdapter<ImageV2, Image>(new CameraCallback<Image>(callback)));
    }

    @Override
    public void getImages(Map<String, String> params, CameraApiCallback<Images> callback) {
        mCameraApi.getImages(params, new CallbackAdapter<ImagesV2, Images>(new CameraCallback<Images>(callback)));
    }

    @Override
    public void getImageSessions(int count, int offset, CameraApiCallback<ImageSessions> imageSessionsCallback) {
        mCameraApi.getImageSessions(count, offset, new CallbackAdapter<ImageSessionsV2, ImageSessions>(
                new CameraCallback<ImageSessions>(imageSessionsCallback)));
    }

    @Override
    public void deleteImage(String imageId, CameraApiCallback<Void> callback) {
        mCameraApi.deleteImage(imageId, new CameraCallback<Void>(callback));
    }

    @Override
    public void getLicenseFile(final CameraApiCallback<CameraLicenseFile> cameraLicenceCallback) {
        mCameraApi.getLicenseFile(new Callback() {
            @Override
            public void success(Object o, final Response response) {
                int code = response.getStatus();
                boolean isSuccess = code >= 200 && code < 300;
                if (isSuccess) {
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                CameraLicenseFile cameraLicenseFile = new CameraLicenseFile(
                                        ByteStreams.toByteArray(response.getBody().in()));
                                cameraLicenceCallback.success(cameraLicenseFile);

                            } catch (IOException e) {
                                Logger.exception(e);
                                cameraLicenceCallback.failure(e);
                            }
                        }
                    }).start();
                } else {
                    cameraLicenceCallback.error(code);
                }
            }

            @Override
            public void failure(RetrofitError error) {
                cameraLicenceCallback.failure(error.getCause());
            }
        });
    }

    @Override
    public void getHighlightActionData(String videoId, String highlightId,
            CameraApiCallback<SensorDataCollection> callback) {
        mCameraApi.getHighlightActionData(videoId, highlightId,
                new CallbackAdapter<SensorDataCollectionV2, SensorDataCollection>(
                        new CameraCallback<SensorDataCollection>(callback)));
    }

    @Override
    public void getVideoActionData(String videoId, Map<String, String> filter,
            CameraApiCallback<SensorDataCollection> callback) {
        mCameraApi.getVideoActionData(videoId, filter,
                new CallbackAdapter<SensorDataCollectionV2, SensorDataCollection>(
                        new CameraCallback<SensorDataCollection>(callback)));
    }

    @Override
    public void getPhotoFromVideo(String videoId, float offset, CameraApiCallback<Response> callback) {
        mCameraApi.getPhotoFromVideo(videoId, offset, new CameraCallback<Response>(callback));
    }

    public void setGpsEnabled(boolean isEnabled, CameraApiCallback<Void> callback) {
        CameraSettingsV2.Builder builder = new CameraSettingsV2.Builder().gpsEnabled(isEnabled);
        mCameraApi.setCameraSettings(builder.build(), new CameraCallback<Void>(callback));
    }

    @Override
    public void setRotationEnabled(boolean enabled, CameraApiCallback<Void> callback) {
        CameraSettingsV2.Builder builder = new CameraSettingsV2.Builder().rotationEnabled(enabled);
        mCameraApi.setCameraSettings(builder.build(), new CameraCallback<Void>(callback));
    }

    @Override
    public void setExternalMicEnabled(boolean isEnabled, CameraApiCallback<Void> externalMicCallback) {
        CameraSettingsV2.Builder builder = new CameraSettingsV2.Builder().externalMic(isEnabled);
        mCameraApi.setCameraSettings(builder.build(), new CameraCallback<Void>(externalMicCallback));
    }

    @Override
    public void getTime(CameraApiCallback<CameraTime> callback) {
        mCameraApi.getCameraTime(
                new CallbackAdapter<CameraTimeV2, CameraTime>(new CameraCallback<CameraTime>(callback)));
    }

    @Override
    public void setTime(Date date, CameraApiCallback<Void> callback) {
        CameraTimeV2 cameratimeV2 = new CameraTimeV2();
        cameratimeV2.setDate(date);
        mCameraApi.setCameraTime(cameratimeV2, new CameraCallback<Void>(callback));
    }

    /***
     * DOWNLOAD API implementation
     */

    @Override
    public Response downloadVideo(String videoId) {
        return mDownloadApi.downloadVideo(videoId);
    }

    @Override
    public Response downloadHighlight(String videoId, String highlightId, Resolution resolution,
            Framerate framerate) {
        String strResolution = resolution != null ? resolution.value() : null;
        String strFramerate = framerate != null ? framerate.value() : null;
        return mDownloadApi.downloadTag(videoId, highlightId, strResolution, strFramerate);
    }

    @Override
    public Response downloadPhoto(String photoId) {
        return mDownloadApi.downloadImageContent(photoId);
    }

    @Override
    public void cancelCurrentDownload() {
        mDownloadHttpClient.cancelCurrentDownloadRequest();
    }

    private static class CameraCallback<T> implements Callback<T> {

        CameraApiCallback<T> mCameraApiCallback;

        public CameraCallback(CameraApiCallback cameraApiCallback) {
            mCameraApiCallback = cameraApiCallback;
        }

        @Override
        public void failure(RetrofitError error) {
            mCameraApiCallback.failure(error);
        }

        @Override
        public void success(T t, Response response) {
            int code = response.getStatus();
            boolean isSuccess = code >= 200 && code < 300;
            if (isSuccess) {
                mCameraApiCallback.success(t);
            } else {
                mCameraApiCallback.error(code);
            }
        }
    }

    /***
     * @param <I> Api model V2 implementation file which callback CameraApiV2 consumes,
     *            package-private
     * @param <O> Wrapped Api interface callback which is propagated to the caller
     */
    private static class CallbackAdapter<I extends O, O> implements Callback<I> {

        private CameraCallback<O> mOutputCallback;

        private CallbackAdapter(CameraCallback<O> outputCallback) {
            mOutputCallback = outputCallback;
        }

        @Override
        public void success(I i, Response response) {
            mOutputCallback.success(i, response);
        }

        @Override
        public void failure(RetrofitError error) {
            Logger.debug(TAG, error.getUrl() + (error.getKind() != null ? error.getKind().name() : "No kind") + " "
                    + (error.getMessage() != null ? error.getMessage() : "No error message for "));
            mOutputCallback.failure(error);
        }
    }

}