1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.videoeditor.service;
18
19import java.io.IOException;
20
21import android.content.Context;
22import android.media.videoeditor.MediaItem;
23import android.media.videoeditor.Transition;
24import android.media.videoeditor.TransitionAlpha;
25import android.media.videoeditor.TransitionCrossfade;
26import android.media.videoeditor.TransitionFadeBlack;
27import android.media.videoeditor.TransitionSliding;
28
29import com.android.videoeditor.R;
30import com.android.videoeditor.TransitionType;
31import com.android.videoeditor.util.FileUtils;
32
33/**
34 * This class represents a transition in the user interface
35 */
36public class MovieTransition {
37    // The unique id of the transition
38    private final String mUniqueId;
39    private final Class<?> mTypeClass;
40    private final int mType;
41    private final int mBehavior;
42    private final int mSlidingDirection;
43    private final String mAlphaMaskFilename;
44    private final int mAlphaMaskResId;
45    private final int mAlphaMaskBlendingPercent;
46    private final boolean mAlphaInvert;
47    private long mDurationMs;
48
49    private long mAppDurationMs;
50
51    /**
52     * Constructor
53     *
54     * @param transition The transition
55     */
56    MovieTransition(Transition transition) {
57        mTypeClass = transition.getClass();
58        mUniqueId = transition.getId();
59        mAppDurationMs = mDurationMs = transition.getDuration();
60        mBehavior = transition.getBehavior();
61        if (transition instanceof TransitionSliding) {
62            mSlidingDirection = ((TransitionSliding)transition).getDirection();
63        } else {
64            mSlidingDirection = -1;
65        }
66
67        if (transition instanceof TransitionAlpha) {
68            final TransitionAlpha ta = (TransitionAlpha)transition;
69            mAlphaMaskFilename = ta.getMaskFilename();
70            mAlphaMaskResId = 0;
71            mAlphaMaskBlendingPercent = ta.getBlendingPercent();
72            mAlphaInvert = ta.isInvert();
73        } else {
74            mAlphaMaskFilename = null;
75            mAlphaMaskResId = 0;
76            mAlphaMaskBlendingPercent = 0;
77            mAlphaInvert = false;
78        }
79
80        mType = toType();
81    }
82
83    /**
84     * Constructor
85     *
86     * @param type The transition type
87     * @param id The transition id
88     * @param durationMs The duration in milliseconds
89     * @param behavior The behavior
90     */
91    MovieTransition(Class<?> type, String id, long durationMs, int behavior) {
92        mTypeClass = type;
93        mUniqueId = id;
94        mAppDurationMs = mDurationMs = durationMs;
95        mBehavior = behavior;
96        mSlidingDirection = -1;
97        mAlphaMaskFilename = null;
98        mAlphaMaskResId = 0;
99        mAlphaMaskBlendingPercent = 0;
100        mAlphaInvert = false;
101
102        mType = toType();
103    }
104
105    /**
106     * Constructor for sliding transitions
107     *
108     * @param type The transition type
109     * @param id The transition id
110     * @param durationMs The duration in milliseconds
111     * @param behavior The behavior
112     * @param slidingDirection The sliding direction
113     */
114    MovieTransition(Class<?> type, String id, long durationMs, int behavior,
115            int slidingDirection) {
116        mTypeClass = type;
117        mUniqueId = id;
118        mAppDurationMs = mDurationMs = durationMs;
119        mBehavior = behavior;
120        mSlidingDirection = slidingDirection;
121        mAlphaMaskFilename = null;
122        mAlphaMaskResId = 0;
123        mAlphaMaskBlendingPercent = 0;
124        mAlphaInvert = false;
125
126        mType = toType();
127    }
128
129    /**
130     * Constructor for alpha transitions
131     *
132     * @param type The transition type
133     * @param id The transition id
134     * @param durationMs The duration in milliseconds
135     * @param behavior The behavior
136     * @param maskResId The mask resource id
137     * @param blendingPercent The blending (in percentages)
138     * @param invert true to invert the direction of the alpha blending
139     */
140    MovieTransition(Class<?> type, String id, long durationMs, int behavior,
141            int maskResId, int blendingPercent, boolean invert) {
142        mTypeClass = type;
143        mUniqueId = id;
144        mAppDurationMs = mDurationMs = durationMs;
145        mBehavior = behavior;
146        mSlidingDirection = -1;
147        mAlphaMaskFilename = null;
148        mAlphaMaskResId = maskResId;
149        mAlphaMaskBlendingPercent = blendingPercent;
150        mAlphaInvert = invert;
151
152        mType = toType();
153    }
154
155    /**
156     * @return The type class of the transition
157     */
158    public Class<?> getTypeClass() {
159        return mTypeClass;
160    }
161
162    /**
163     * @return The type of the transition
164     */
165    public int getType() {
166        return mType;
167    }
168
169    /**
170     * @return The id of the transition
171     */
172    public String getId() {
173        return mUniqueId;
174    }
175
176    /**
177     * Set the duration of the transition.
178     *
179     * @param durationMs the duration of the transition in milliseconds
180     */
181    void setDuration(long durationMs) {
182        mDurationMs = durationMs;
183    }
184
185    /**
186     * @return the duration of the transition in milliseconds
187     */
188    long getDuration() {
189        return mDurationMs;
190    }
191
192    /**
193     * Set the duration of the transition
194     *
195     * @param durationMs The duration in milliseconds
196     */
197    public void setAppDuration(long durationMs) {
198        mAppDurationMs = durationMs;
199    }
200
201    /**
202     * @return The duration of the transition
203     */
204    public long getAppDuration() {
205        return mAppDurationMs;
206    }
207
208    /**
209     * @return The behavior
210     */
211    public int getBehavior() {
212        return mBehavior;
213    }
214
215    /**
216     * @return The sliding direction (only for TransitionSliding)
217     */
218    public int getSlidingDirection() {
219        return mSlidingDirection;
220    }
221
222    /**
223     * @return The alpha mask filename
224     */
225    public String getAlphaMaskFilename() {
226        return mAlphaMaskFilename;
227    }
228
229    /**
230     * @return The alpha mask resource id
231     */
232    public int getAlphaMaskResId() {
233        return mAlphaMaskResId;
234    }
235
236    /**
237     * @return The alpha blending percentage
238     */
239    public int getAlphaMaskBlendingPercent() {
240        return mAlphaMaskBlendingPercent;
241    }
242
243    /**
244     * @return true if the direction of the alpha blending is inverted
245     */
246    public boolean isAlphaInverted() {
247        return mAlphaInvert;
248    }
249
250    /**
251     * Create a VideoEditor transition
252     *
253     * @param context the context
254     * @param afterMediaItem Add the transition after this media item
255     * @param beforeMediaItem Add the transition before this media item
256     *
257     * @return The transition
258     */
259    Transition buildTransition(Context context, MediaItem afterMediaItem,
260            MediaItem beforeMediaItem) throws IOException {
261        if (TransitionCrossfade.class.equals(mTypeClass)) {
262            return new TransitionCrossfade(ApiService.generateId(), afterMediaItem,
263                    beforeMediaItem, mDurationMs, mBehavior);
264        } else if (TransitionAlpha.class.equals(mTypeClass)) {
265            return new TransitionAlpha(ApiService.generateId(), afterMediaItem,
266                    beforeMediaItem, mDurationMs, mBehavior,
267                    FileUtils.getMaskFilename(context, mAlphaMaskResId), mAlphaMaskBlendingPercent,
268                    mAlphaInvert);
269        } else if (TransitionFadeBlack.class.equals(mTypeClass)) {
270            return new TransitionFadeBlack(ApiService.generateId(), afterMediaItem,
271                    beforeMediaItem, mDurationMs, mBehavior);
272        } else if (TransitionSliding.class.equals(mTypeClass)) {
273            return new TransitionSliding(ApiService.generateId(), afterMediaItem,
274                    beforeMediaItem, mDurationMs, mBehavior, mSlidingDirection);
275        } else {
276            return null;
277        }
278    }
279
280    /**
281     * Convert the type to an integer
282     *
283     * @return The type
284     */
285    private int toType() {
286        if (TransitionCrossfade.class.equals(mTypeClass)) {
287            return TransitionType.TRANSITION_TYPE_CROSSFADE;
288        } else if (TransitionAlpha.class.equals(mTypeClass)) {
289            final int rawId = FileUtils.getMaskRawId(mAlphaMaskFilename);
290            switch (rawId) {
291                case R.raw.mask_contour: {
292                    return TransitionType.TRANSITION_TYPE_ALPHA_CONTOUR;
293                }
294
295                case R.raw.mask_diagonal: {
296                    return TransitionType.TRANSITION_TYPE_ALPHA_DIAGONAL;
297                }
298
299                default: {
300                    throw new IllegalArgumentException("Unknown id for: " + mAlphaMaskFilename);
301                }
302            }
303        } else if (TransitionFadeBlack.class.equals(mTypeClass)) {
304            return TransitionType.TRANSITION_TYPE_FADE_BLACK;
305        } else if (TransitionSliding.class.equals(mTypeClass)) {
306            switch (mSlidingDirection) {
307                case TransitionSliding.DIRECTION_BOTTOM_OUT_TOP_IN: {
308                    return TransitionType.TRANSITION_TYPE_SLIDING_BOTTOM_OUT_TOP_IN;
309                }
310
311                case TransitionSliding.DIRECTION_LEFT_OUT_RIGHT_IN: {
312                    return TransitionType.TRANSITION_TYPE_SLIDING_LEFT_OUT_RIGHT_IN;
313                }
314
315                case TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN: {
316                    return TransitionType.TRANSITION_TYPE_SLIDING_RIGHT_OUT_LEFT_IN;
317                }
318
319                case TransitionSliding.DIRECTION_TOP_OUT_BOTTOM_IN: {
320                    return TransitionType.TRANSITION_TYPE_SLIDING_TOP_OUT_BOTTOM_IN;
321                }
322
323                default: {
324                    throw new IllegalArgumentException("Unknown direction: " + mSlidingDirection);
325                }
326            }
327        } else {
328            throw new IllegalArgumentException("Unknown type: " + mTypeClass);
329        }
330    }
331
332    /*
333     * {@inheritDoc}
334     */
335    @Override
336    public boolean equals(Object object) {
337        if (!(object instanceof MovieTransition)) {
338            return false;
339        }
340        return mUniqueId.equals(((MovieTransition)object).mUniqueId);
341    }
342
343    /*
344     * {@inheritDoc}
345     */
346    @Override
347    public int hashCode() {
348        return mUniqueId.hashCode();
349    }
350}
351