1 /* 2 * Copyright (C) 2008 Esmertec AG. 3 * Copyright (C) 2008 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package com.android.mms.ui; 19 20 import com.android.mms.R; 21 import android.drm.mobile1.DrmException; 22 import com.android.mms.model.AudioModel; 23 import com.android.mms.model.ImageModel; 24 import com.android.mms.model.LayoutModel; 25 import com.android.mms.model.MediaModel; 26 import com.android.mms.model.Model; 27 import com.android.mms.model.RegionMediaModel; 28 import com.android.mms.model.RegionModel; 29 import com.android.mms.model.SlideModel; 30 import com.android.mms.model.SlideshowModel; 31 import com.android.mms.model.TextModel; 32 import com.android.mms.model.VideoModel; 33 import com.android.mms.model.MediaModel.MediaAction; 34 import com.android.mms.ui.AdaptableSlideViewInterface.OnSizeChangedListener; 35 36 import android.content.Context; 37 import android.os.Handler; 38 import android.util.Config; 39 import android.util.Log; 40 import android.widget.Toast; 41 42 /** 43 * A basic presenter of slides. 44 */ 45 public class SlideshowPresenter extends Presenter { 46 private static final String TAG = "SlideshowPresenter"; 47 private static final boolean DEBUG = false; 48 private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV; 49 50 protected int mLocation; 51 protected final int mSlideNumber; 52 53 protected float mWidthTransformRatio; 54 protected float mHeightTransformRatio; 55 56 // Since only the original thread that created a view hierarchy can touch 57 // its views, we have to use Handler to manage the views in the some 58 // callbacks such as onModelChanged(). 59 protected final Handler mHandler = new Handler(); 60 61 public SlideshowPresenter(Context context, ViewInterface view, Model model) { 62 super(context, view, model); 63 mLocation = 0; 64 mSlideNumber = ((SlideshowModel) mModel).size(); 65 66 if (view instanceof AdaptableSlideViewInterface) { 67 ((AdaptableSlideViewInterface) view).setOnSizeChangedListener( 68 mViewSizeChangedListener); 69 } 70 } 71 72 private final OnSizeChangedListener mViewSizeChangedListener = 73 new OnSizeChangedListener() { 74 public void onSizeChanged(int width, int height) { 75 LayoutModel layout = ((SlideshowModel) mModel).getLayout(); 76 mWidthTransformRatio = getWidthTransformRatio( 77 width, layout.getLayoutWidth()); 78 mHeightTransformRatio = getHeightTransformRatio( 79 height, layout.getLayoutHeight()); 80 // The ratio indicates how to reduce the source to match the View, 81 // so the larger one should be used. 82 float ratio = mWidthTransformRatio > mHeightTransformRatio ? 83 mWidthTransformRatio : mHeightTransformRatio; 84 mWidthTransformRatio = ratio; 85 mHeightTransformRatio = ratio; 86 if (LOCAL_LOGV) { 87 Log.v(TAG, "ratio_w = " + mWidthTransformRatio 88 + ", ratio_h = " + mHeightTransformRatio); 89 } 90 } 91 }; 92 93 private float getWidthTransformRatio(int width, int layoutWidth) { 94 if (width > 0) { 95 return (float) layoutWidth / (float) width; 96 } 97 return 1.0f; 98 } 99 100 private float getHeightTransformRatio(int height, int layoutHeight) { 101 if (height > 0) { 102 return (float) layoutHeight / (float) height; 103 } 104 return 1.0f; 105 } 106 107 private int transformWidth(int width) { 108 return (int) (width / mWidthTransformRatio); 109 } 110 111 private int transformHeight(int height) { 112 return (int) (height / mHeightTransformRatio); 113 } 114 115 @Override 116 public void present() { 117 presentSlide((SlideViewInterface) mView, ((SlideshowModel) mModel).get(mLocation)); 118 } 119 120 /** 121 * @param view 122 * @param model 123 */ 124 protected void presentSlide(SlideViewInterface view, SlideModel model) { 125 view.reset(); 126 127 try { 128 for (MediaModel media : model) { 129 if (media instanceof RegionMediaModel) { 130 presentRegionMedia(view, (RegionMediaModel) media, true); 131 } else if (media.isAudio()) { 132 presentAudio(view, (AudioModel) media, true); 133 } 134 } 135 } catch (DrmException e) { 136 Log.e(TAG, e.getMessage(), e); 137 Toast.makeText(mContext, 138 mContext.getString(R.string.insufficient_drm_rights), 139 Toast.LENGTH_SHORT).show(); 140 } 141 } 142 143 /** 144 * @param view 145 * @throws DrmException 146 */ 147 protected void presentRegionMedia(SlideViewInterface view, 148 RegionMediaModel rMedia, boolean dataChanged) 149 throws DrmException { 150 RegionModel r = (rMedia).getRegion(); 151 if (rMedia.isText()) { 152 presentText(view, (TextModel) rMedia, r, dataChanged); 153 } else if (rMedia.isImage()) { 154 presentImage(view, (ImageModel) rMedia, r, dataChanged); 155 } else if (rMedia.isVideo()) { 156 presentVideo(view, (VideoModel) rMedia, r, dataChanged); 157 } 158 } 159 160 protected void presentAudio(SlideViewInterface view, AudioModel audio, 161 boolean dataChanged) throws DrmException { 162 // Set audio only when data changed. 163 if (dataChanged) { 164 view.setAudio(audio.getUriWithDrmCheck(), audio.getSrc(), audio.getExtras()); 165 } 166 167 MediaAction action = audio.getCurrentAction(); 168 if (action == MediaAction.START) { 169 view.startAudio(); 170 } else if (action == MediaAction.PAUSE) { 171 view.pauseAudio(); 172 } else if (action == MediaAction.STOP) { 173 view.stopAudio(); 174 } else if (action == MediaAction.SEEK) { 175 view.seekAudio(audio.getSeekTo()); 176 } 177 } 178 179 protected void presentText(SlideViewInterface view, TextModel text, 180 RegionModel r, boolean dataChanged) { 181 if (dataChanged) { 182 view.setText(text.getSrc(), text.getText()); 183 } 184 185 if (view instanceof AdaptableSlideViewInterface) { 186 ((AdaptableSlideViewInterface) view).setTextRegion( 187 transformWidth(r.getLeft()), 188 transformHeight(r.getTop()), 189 transformWidth(r.getWidth()), 190 transformHeight(r.getHeight())); 191 } 192 view.setTextVisibility(text.isVisible()); 193 } 194 195 /** 196 * @param view 197 * @param image 198 * @param r 199 * @throws DrmException 200 */ 201 protected void presentImage(SlideViewInterface view, ImageModel image, 202 RegionModel r, boolean dataChanged) throws DrmException { 203 if (dataChanged) { 204 view.setImage(image.getSrc(), image.getBitmapWithDrmCheck()); 205 } 206 207 if (view instanceof AdaptableSlideViewInterface) { 208 ((AdaptableSlideViewInterface) view).setImageRegion( 209 transformWidth(r.getLeft()), 210 transformHeight(r.getTop()), 211 transformWidth(r.getWidth()), 212 transformHeight(r.getHeight())); 213 } 214 view.setImageRegionFit(r.getFit()); 215 view.setImageVisibility(image.isVisible()); 216 } 217 218 /** 219 * @param view 220 * @param video 221 * @param r 222 * @throws DrmException 223 */ 224 protected void presentVideo(SlideViewInterface view, VideoModel video, 225 RegionModel r, boolean dataChanged) throws DrmException { 226 if (dataChanged) { 227 view.setVideo(video.getSrc(), video.getUriWithDrmCheck()); 228 } 229 230 if (view instanceof AdaptableSlideViewInterface) { 231 ((AdaptableSlideViewInterface) view).setVideoRegion( 232 transformWidth(r.getLeft()), 233 transformHeight(r.getTop()), 234 transformWidth(r.getWidth()), 235 transformHeight(r.getHeight())); 236 } 237 view.setVideoVisibility(video.isVisible()); 238 239 MediaAction action = video.getCurrentAction(); 240 if (action == MediaAction.START) { 241 view.startVideo(); 242 } else if (action == MediaAction.PAUSE) { 243 view.pauseVideo(); 244 } else if (action == MediaAction.STOP) { 245 view.stopVideo(); 246 } else if (action == MediaAction.SEEK) { 247 view.seekVideo(video.getSeekTo()); 248 } 249 } 250 251 public void setLocation(int location) { 252 mLocation = location; 253 } 254 255 public int getLocation() { 256 return mLocation; 257 } 258 259 public void goBackward() { 260 if (mLocation > 0) { 261 mLocation--; 262 } 263 } 264 265 public void goForward() { 266 if (mLocation < (mSlideNumber - 1)) { 267 mLocation++; 268 } 269 } 270 271 public void onModelChanged(final Model model, final boolean dataChanged) { 272 final SlideViewInterface view = (SlideViewInterface) mView; 273 274 // FIXME: Should be optimized. 275 if (model instanceof SlideshowModel) { 276 // TODO: 277 } else if (model instanceof SlideModel) { 278 if (((SlideModel) model).isVisible()) { 279 mHandler.post(new Runnable() { 280 public void run() { 281 presentSlide(view, (SlideModel) model); 282 } 283 }); 284 } else { 285 mHandler.post(new Runnable() { 286 public void run() { 287 goForward(); 288 } 289 }); 290 } 291 } else if (model instanceof MediaModel) { 292 if (model instanceof RegionMediaModel) { 293 mHandler.post(new Runnable() { 294 public void run() { 295 try { 296 presentRegionMedia(view, (RegionMediaModel) model, dataChanged); 297 } catch (DrmException e) { 298 Log.e(TAG, e.getMessage(), e); 299 Toast.makeText(mContext, 300 mContext.getString(R.string.insufficient_drm_rights), 301 Toast.LENGTH_SHORT).show(); 302 } 303 } 304 }); 305 } else if (((MediaModel) model).isAudio()) { 306 mHandler.post(new Runnable() { 307 public void run() { 308 try { 309 presentAudio(view, (AudioModel) model, dataChanged); 310 } catch (DrmException e) { 311 Log.e(TAG, e.getMessage(), e); 312 Toast.makeText(mContext, 313 mContext.getString(R.string.insufficient_drm_rights), 314 Toast.LENGTH_SHORT).show(); 315 } 316 } 317 }); 318 } 319 } else if (model instanceof RegionModel) { 320 // TODO: 321 } 322 } 323 } 324