103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar/* 203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * Copyright (C) 2013 The Android Open Source Project 303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * 403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * Licensed under the Apache License, Version 2.0 (the "License"); 503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * you may not use this file except in compliance with the License. 603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * You may obtain a copy of the License at 703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * 803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * http://www.apache.org/licenses/LICENSE-2.0 903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * 1003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * Unless required by applicable law or agreed to in writing, software 1103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * distributed under the License is distributed on an "AS IS" BASIS, 1203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * See the License for the specific language governing permissions and 1403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * limitations under the License. 1503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar */ 1603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 1703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnarpackage android.media; 1803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 19d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viveretteimport android.graphics.Canvas; 20a460ea1a2c178a2c1816b1a983333166726ad579Robert Shihimport android.media.MediaPlayer.TrackInfo; 2103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnarimport android.os.Handler; 2203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnarimport android.util.Log; 2303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnarimport android.util.LongSparseArray; 2403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnarimport android.util.Pair; 2503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 2603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnarimport java.util.Iterator; 2703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnarimport java.util.NoSuchElementException; 2803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnarimport java.util.SortedMap; 2903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnarimport java.util.TreeMap; 3003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnarimport java.util.Vector; 3103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 3203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar/** 3303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * A subtitle track abstract base class that is responsible for parsing and displaying 3403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * an instance of a particular type of subtitle. 3503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * 3603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * @hide 3703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar */ 3803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnarpublic abstract class SubtitleTrack implements MediaTimeProvider.OnMediaTimeListener { 3903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar private static final String TAG = "SubtitleTrack"; 4003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar private long mLastUpdateTimeMs; 4103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar private long mLastTimeMs; 4203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 4303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar private Runnable mRunnable; 4403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 4503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** @hide TODO private */ 4603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar final protected LongSparseArray<Run> mRunsByEndTime = new LongSparseArray<Run>(); 4703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** @hide TODO private */ 4803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar final protected LongSparseArray<Run> mRunsByID = new LongSparseArray<Run>(); 4903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 5003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** @hide TODO private */ 5103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar protected CueList mCues; 5203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** @hide TODO private */ 5303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar final protected Vector<Cue> mActiveCues = new Vector<Cue>(); 5403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** @hide */ 5503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar protected boolean mVisible; 5603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 5703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** @hide */ 5803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public boolean DEBUG = false; 5903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 6003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** @hide */ 6103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar protected Handler mHandler = new Handler(); 6203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 6303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar private MediaFormat mFormat; 6403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 6503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public SubtitleTrack(MediaFormat format) { 6603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mFormat = format; 6703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mCues = new CueList(); 6803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar clearActiveCues(); 6903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mLastTimeMs = -1; 7003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 7103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 7203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** @hide */ 73d486f9656a6f9d6c056d84fce39f3db8d1614e1dLajos Molnar public final MediaFormat getFormat() { 7403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar return mFormat; 7503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 7603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 7703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar private long mNextScheduledTimeMs = -1; 7803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 7938c209b938b371d8852a104815c508c49ceabca6Robert Shih protected void onData(SubtitleData data) { 8038c209b938b371d8852a104815c508c49ceabca6Robert Shih long runID = data.getStartTimeUs() + 1; 8138c209b938b371d8852a104815c508c49ceabca6Robert Shih onData(data.getData(), true /* eos */, runID); 8238c209b938b371d8852a104815c508c49ceabca6Robert Shih setRunDiscardTimeMs( 8338c209b938b371d8852a104815c508c49ceabca6Robert Shih runID, 8438c209b938b371d8852a104815c508c49ceabca6Robert Shih (data.getStartTimeUs() + data.getDurationUs()) / 1000); 8538c209b938b371d8852a104815c508c49ceabca6Robert Shih } 8638c209b938b371d8852a104815c508c49ceabca6Robert Shih 8703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** 8803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * Called when there is input data for the subtitle track. The 8903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * complete subtitle for a track can include multiple whole units 9003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * (runs). Each of these units can have multiple sections. The 9103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * contents of a run are submitted in sequential order, with eos 9203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * indicating the last section of the run. Calls from different 9303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * runs must not be intermixed. 9403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * 95079fa9683dc062f154333a661f5e84a5ac5e43c7Chong Zhang * @param data subtitle data byte buffer 9603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * @param eos true if this is the last section of the run. 9703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * @param runID mostly-unique ID for this run of data. Subtitle cues 9803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * with runID of 0 are discarded immediately after 9903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * display. Cues with runID of ~0 are discarded 10003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * only at the deletion of the track object. Cues 10103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * with other runID-s are discarded at the end of the 10203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * run, which defaults to the latest timestamp of 10303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * any of its cues (with this runID). 10403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar */ 105079fa9683dc062f154333a661f5e84a5ac5e43c7Chong Zhang public abstract void onData(byte[] data, boolean eos, long runID); 10603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 10703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** 108d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * Called when adding the subtitle rendering widget to the view hierarchy, 109d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * as well as when showing or hiding the subtitle track, or when the video 11003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * surface position has changed. 11103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * 112d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * @return the widget that renders this subtitle track. For most renderers 113d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * there should be a single shared instance that is used for all 114d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * tracks supported by that renderer, as at most one subtitle track 115d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * is visible at one time. 11603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar */ 117d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette public abstract RenderingWidget getRenderingWidget(); 11803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 11903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** 12003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * Called when the active cues have changed, and the contents of the subtitle 12103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * view should be updated. 12203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * 12303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * @hide 12403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar */ 12503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public abstract void updateView(Vector<Cue> activeCues); 12603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 12703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** @hide */ 12803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar protected synchronized void updateActiveCues(boolean rebuild, long timeMs) { 12903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar // out-of-order times mean seeking or new active cues being added 13003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar // (during their own timespan) 13103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (rebuild || mLastUpdateTimeMs > timeMs) { 13203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar clearActiveCues(); 13303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 13403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 13503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar for(Iterator<Pair<Long, Cue> > it = 13603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mCues.entriesBetween(mLastUpdateTimeMs, timeMs).iterator(); it.hasNext(); ) { 13703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar Pair<Long, Cue> event = it.next(); 13803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar Cue cue = event.second; 13903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 14003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (cue.mEndTimeMs == event.first) { 14103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar // remove past cues 14203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (DEBUG) Log.v(TAG, "Removing " + cue); 14303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mActiveCues.remove(cue); 14403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (cue.mRunID == 0) { 14503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar it.remove(); 14603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 14703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } else if (cue.mStartTimeMs == event.first) { 14803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar // add new cues 14903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar // TRICKY: this will happen in start order 15003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (DEBUG) Log.v(TAG, "Adding " + cue); 15103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (cue.mInnerTimesMs != null) { 15203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar cue.onTime(timeMs); 15303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 15403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mActiveCues.add(cue); 15503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } else if (cue.mInnerTimesMs != null) { 15603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar // cue is modified 15703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar cue.onTime(timeMs); 15803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 15903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 16003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 16103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /* complete any runs */ 16203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar while (mRunsByEndTime.size() > 0 && 16303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mRunsByEndTime.keyAt(0) <= timeMs) { 16403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar removeRunsByEndTimeIndex(0); // removes element 16503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 16603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mLastUpdateTimeMs = timeMs; 16703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 16803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 16903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar private void removeRunsByEndTimeIndex(int ix) { 17003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar Run run = mRunsByEndTime.valueAt(ix); 17103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar while (run != null) { 17203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar Cue cue = run.mFirstCue; 17303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar while (cue != null) { 17403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mCues.remove(cue); 17503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar Cue nextCue = cue.mNextInRun; 17603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar cue.mNextInRun = null; 17703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar cue = nextCue; 17803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 17903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mRunsByID.remove(run.mRunID); 18003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar Run nextRun = run.mNextRunAtEndTimeMs; 18103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar run.mPrevRunAtEndTimeMs = null; 18203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar run.mNextRunAtEndTimeMs = null; 18303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar run = nextRun; 18403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 18503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mRunsByEndTime.removeAt(ix); 18603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 18703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 18803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar @Override 18903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar protected void finalize() throws Throwable { 19003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /* remove all cues (untangle all cross-links) */ 19103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar int size = mRunsByEndTime.size(); 19203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar for(int ix = size - 1; ix >= 0; ix--) { 19303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar removeRunsByEndTimeIndex(ix); 19403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 19503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 19603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar super.finalize(); 19703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 19803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 19903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar private synchronized void takeTime(long timeMs) { 20003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mLastTimeMs = timeMs; 20103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 20203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 20303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** @hide */ 20403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar protected synchronized void clearActiveCues() { 20503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (DEBUG) Log.v(TAG, "Clearing " + mActiveCues.size() + " active cues"); 20603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mActiveCues.clear(); 20703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mLastUpdateTimeMs = -1; 20803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 20903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 21003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** @hide */ 211d486f9656a6f9d6c056d84fce39f3db8d1614e1dLajos Molnar protected void scheduleTimedEvents() { 21203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /* get times for the next event */ 21303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (mTimeProvider != null) { 21403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mNextScheduledTimeMs = mCues.nextTimeAfter(mLastTimeMs); 21503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (DEBUG) Log.d(TAG, "sched @" + mNextScheduledTimeMs + " after " + mLastTimeMs); 21603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mTimeProvider.notifyAt( 21703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mNextScheduledTimeMs >= 0 ? 21803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar (mNextScheduledTimeMs * 1000) : MediaTimeProvider.NO_TIME, 21903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar this); 22003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 22103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 22203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 22303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** 22403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * @hide 22503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar */ 22603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar @Override 22703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public void onTimedEvent(long timeUs) { 22803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (DEBUG) Log.d(TAG, "onTimedEvent " + timeUs); 22903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar synchronized (this) { 23003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar long timeMs = timeUs / 1000; 23103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar updateActiveCues(false, timeMs); 23203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar takeTime(timeMs); 23303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 23403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar updateView(mActiveCues); 23503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar scheduleTimedEvents(); 23603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 23703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 23803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** 23903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * @hide 24003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar */ 24103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar @Override 24203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public void onSeek(long timeUs) { 24303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (DEBUG) Log.d(TAG, "onSeek " + timeUs); 24403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar synchronized (this) { 24503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar long timeMs = timeUs / 1000; 24603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar updateActiveCues(true, timeMs); 24703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar takeTime(timeMs); 24803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 24903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar updateView(mActiveCues); 25003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar scheduleTimedEvents(); 25103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 25203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 25303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** 25403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar * @hide 25503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar */ 25603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar @Override 25703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public void onStop() { 25803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar synchronized (this) { 25903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (DEBUG) Log.d(TAG, "onStop"); 26003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar clearActiveCues(); 26103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mLastTimeMs = -1; 26203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 26303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar updateView(mActiveCues); 26403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mNextScheduledTimeMs = -1; 26503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mTimeProvider.notifyAt(MediaTimeProvider.NO_TIME, this); 26603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 26703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 26803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** @hide */ 26903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar protected MediaTimeProvider mTimeProvider; 27003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 27103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** @hide */ 27203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public void show() { 27303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (mVisible) { 27403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar return; 27503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 27603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 27703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mVisible = true; 2783cdf7c5b622a8fbb20410736bdab5888d0e1873cRobert Shih RenderingWidget renderingWidget = getRenderingWidget(); 2793cdf7c5b622a8fbb20410736bdab5888d0e1873cRobert Shih if (renderingWidget != null) { 2803cdf7c5b622a8fbb20410736bdab5888d0e1873cRobert Shih renderingWidget.setVisible(true); 2813cdf7c5b622a8fbb20410736bdab5888d0e1873cRobert Shih } 28203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (mTimeProvider != null) { 28303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mTimeProvider.scheduleUpdate(this); 28403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 28503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 28603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 28703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** @hide */ 28803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public void hide() { 28903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (!mVisible) { 29003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar return; 29103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 29203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 29303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (mTimeProvider != null) { 29403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mTimeProvider.cancelNotifications(this); 29503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 2963cdf7c5b622a8fbb20410736bdab5888d0e1873cRobert Shih RenderingWidget renderingWidget = getRenderingWidget(); 2973cdf7c5b622a8fbb20410736bdab5888d0e1873cRobert Shih if (renderingWidget != null) { 2983cdf7c5b622a8fbb20410736bdab5888d0e1873cRobert Shih renderingWidget.setVisible(false); 2993cdf7c5b622a8fbb20410736bdab5888d0e1873cRobert Shih } 30003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mVisible = false; 30103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 30203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 30303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** @hide */ 30403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar protected synchronized boolean addCue(Cue cue) { 30503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mCues.add(cue); 30603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 30703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (cue.mRunID != 0) { 30803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar Run run = mRunsByID.get(cue.mRunID); 30903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (run == null) { 31003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar run = new Run(); 31103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mRunsByID.put(cue.mRunID, run); 31203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar run.mEndTimeMs = cue.mEndTimeMs; 31303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } else if (run.mEndTimeMs < cue.mEndTimeMs) { 31403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar run.mEndTimeMs = cue.mEndTimeMs; 31503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 31603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 31703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar // link-up cues in the same run 31803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar cue.mNextInRun = run.mFirstCue; 31903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar run.mFirstCue = cue; 32003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 32103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 32203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar // if a cue is added that should be visible, need to refresh view 32303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar long nowMs = -1; 32403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (mTimeProvider != null) { 32503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar try { 32603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar nowMs = mTimeProvider.getCurrentTimeUs( 32703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar false /* precise */, true /* monotonic */) / 1000; 32803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } catch (IllegalStateException e) { 32903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar // handle as it we are not playing 33003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 33103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 33203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 33303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (DEBUG) Log.v(TAG, "mVisible=" + mVisible + ", " + 33403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar cue.mStartTimeMs + " <= " + nowMs + ", " + 33503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar cue.mEndTimeMs + " >= " + mLastTimeMs); 33603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 33703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (mVisible && 33803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar cue.mStartTimeMs <= nowMs && 33903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar // we don't trust nowMs, so check any cue since last callback 34003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar cue.mEndTimeMs >= mLastTimeMs) { 34103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (mRunnable != null) { 34203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mHandler.removeCallbacks(mRunnable); 34303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 34403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar final SubtitleTrack track = this; 34503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar final long thenMs = nowMs; 34603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mRunnable = new Runnable() { 34703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar @Override 34803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public void run() { 34903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar // even with synchronized, it is possible that we are going 35003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar // to do multiple updates as the runnable could be already 35103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar // running. 35203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar synchronized (track) { 35303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mRunnable = null; 35403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar updateActiveCues(true, thenMs); 35503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar updateView(mActiveCues); 35603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 35703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 35803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar }; 35903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar // delay update so we don't update view on every cue. TODO why 10? 36003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (mHandler.postDelayed(mRunnable, 10 /* delay */)) { 36103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (DEBUG) Log.v(TAG, "scheduling update"); 36203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } else { 36303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (DEBUG) Log.w(TAG, "failed to schedule subtitle view update"); 36403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 36503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar return true; 36603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 36703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 36803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (mVisible && 36903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar cue.mEndTimeMs >= mLastTimeMs && 37003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar (cue.mStartTimeMs < mNextScheduledTimeMs || 37103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mNextScheduledTimeMs < 0)) { 37203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar scheduleTimedEvents(); 37303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 37403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 37503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar return false; 37603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 37703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 37803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** @hide */ 379d486f9656a6f9d6c056d84fce39f3db8d1614e1dLajos Molnar public synchronized void setTimeProvider(MediaTimeProvider timeProvider) { 38003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (mTimeProvider == timeProvider) { 38103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar return; 38203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 38303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (mTimeProvider != null) { 38403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mTimeProvider.cancelNotifications(this); 38503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 38603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mTimeProvider = timeProvider; 38703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (mTimeProvider != null) { 38803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mTimeProvider.scheduleUpdate(this); 38903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 39003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 39103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 39203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 39303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** @hide */ 39403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar static class CueList { 39503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar private static final String TAG = "CueList"; 39603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar // simplistic, inefficient implementation 39703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar private SortedMap<Long, Vector<Cue> > mCues; 39803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public boolean DEBUG = false; 39903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 40003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar private boolean addEvent(Cue cue, long timeMs) { 40103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar Vector<Cue> cues = mCues.get(timeMs); 40203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (cues == null) { 40303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar cues = new Vector<Cue>(2); 40403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mCues.put(timeMs, cues); 40503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } else if (cues.contains(cue)) { 40603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar // do not duplicate cues 40703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar return false; 40803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 40903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 41003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar cues.add(cue); 41103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar return true; 41203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 41303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 41403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar private void removeEvent(Cue cue, long timeMs) { 41503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar Vector<Cue> cues = mCues.get(timeMs); 41603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (cues != null) { 41703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar cues.remove(cue); 41803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (cues.size() == 0) { 41903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mCues.remove(timeMs); 42003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 42103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 42203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 42303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 42403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public void add(Cue cue) { 42503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar // ignore non-positive-duration cues 42603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (cue.mStartTimeMs >= cue.mEndTimeMs) 42703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar return; 42803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 42903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (!addEvent(cue, cue.mStartTimeMs)) { 43003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar return; 43103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 43203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 43303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar long lastTimeMs = cue.mStartTimeMs; 43403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (cue.mInnerTimesMs != null) { 43503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar for (long timeMs: cue.mInnerTimesMs) { 43603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (timeMs > lastTimeMs && timeMs < cue.mEndTimeMs) { 43703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar addEvent(cue, timeMs); 43803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar lastTimeMs = timeMs; 43903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 44003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 44103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 44203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 44303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar addEvent(cue, cue.mEndTimeMs); 44403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 44503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 44603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public void remove(Cue cue) { 44703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar removeEvent(cue, cue.mStartTimeMs); 44803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (cue.mInnerTimesMs != null) { 44903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar for (long timeMs: cue.mInnerTimesMs) { 45003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar removeEvent(cue, timeMs); 45103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 45203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 45303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar removeEvent(cue, cue.mEndTimeMs); 45403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 45503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 45603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public Iterable<Pair<Long, Cue>> entriesBetween( 45703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar final long lastTimeMs, final long timeMs) { 45803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar return new Iterable<Pair<Long, Cue> >() { 45903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar @Override 46003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public Iterator<Pair<Long, Cue> > iterator() { 46103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (DEBUG) Log.d(TAG, "slice (" + lastTimeMs + ", " + timeMs + "]="); 46203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar try { 46303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar return new EntryIterator( 46403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mCues.subMap(lastTimeMs + 1, timeMs + 1)); 46503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } catch(IllegalArgumentException e) { 46603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar return new EntryIterator(null); 46703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 46803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 46903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar }; 47003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 47103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 47203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public long nextTimeAfter(long timeMs) { 47303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar SortedMap<Long, Vector<Cue>> tail = null; 47403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar try { 47503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar tail = mCues.tailMap(timeMs + 1); 47603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (tail != null) { 47703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar return tail.firstKey(); 47803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } else { 47903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar return -1; 48003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 48103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } catch(IllegalArgumentException e) { 48203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar return -1; 48303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } catch(NoSuchElementException e) { 48403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar return -1; 48503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 48603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 48703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 48803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar class EntryIterator implements Iterator<Pair<Long, Cue> > { 48903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar @Override 49003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public boolean hasNext() { 49103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar return !mDone; 49203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 49303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 49403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar @Override 49503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public Pair<Long, Cue> next() { 49603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (mDone) { 49703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar throw new NoSuchElementException(""); 49803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 49903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mLastEntry = new Pair<Long, Cue>( 50003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mCurrentTimeMs, mListIterator.next()); 50103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mLastListIterator = mListIterator; 50203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (!mListIterator.hasNext()) { 50303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar nextKey(); 50403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 50503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar return mLastEntry; 50603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 50703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 50803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar @Override 50903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public void remove() { 51003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar // only allow removing end tags 51103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (mLastListIterator == null || 51203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mLastEntry.second.mEndTimeMs != mLastEntry.first) { 51303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar throw new IllegalStateException(""); 51403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 51503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 51603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar // remove end-cue 51703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mLastListIterator.remove(); 51803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mLastListIterator = null; 51903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (mCues.get(mLastEntry.first).size() == 0) { 52003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mCues.remove(mLastEntry.first); 52103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 52203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 52303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar // remove rest of the cues 52403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar Cue cue = mLastEntry.second; 52503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar removeEvent(cue, cue.mStartTimeMs); 52603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (cue.mInnerTimesMs != null) { 52703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar for (long timeMs: cue.mInnerTimesMs) { 52803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar removeEvent(cue, timeMs); 52903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 53003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 53103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 53203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 53303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public EntryIterator(SortedMap<Long, Vector<Cue> > cues) { 53403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (DEBUG) Log.v(TAG, cues + ""); 53503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mRemainingCues = cues; 53603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mLastListIterator = null; 53703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar nextKey(); 53803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 53903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 54003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar private void nextKey() { 54103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar do { 54203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar try { 54303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (mRemainingCues == null) { 54403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar throw new NoSuchElementException(""); 54503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 54603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mCurrentTimeMs = mRemainingCues.firstKey(); 54703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mListIterator = 54803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mRemainingCues.get(mCurrentTimeMs).iterator(); 54903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar try { 55003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mRemainingCues = 55103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mRemainingCues.tailMap(mCurrentTimeMs + 1); 55203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } catch (IllegalArgumentException e) { 55303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mRemainingCues = null; 55403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 55503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mDone = false; 55603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } catch (NoSuchElementException e) { 55703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mDone = true; 55803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mRemainingCues = null; 55903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mListIterator = null; 56003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar return; 56103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 56203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } while (!mListIterator.hasNext()); 56303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 56403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 56503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar private long mCurrentTimeMs; 56603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar private Iterator<Cue> mListIterator; 56703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar private boolean mDone; 56803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar private SortedMap<Long, Vector<Cue> > mRemainingCues; 56903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar private Iterator<Cue> mLastListIterator; 57003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar private Pair<Long,Cue> mLastEntry; 57103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 57203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 57303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar CueList() { 57403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mCues = new TreeMap<Long, Vector<Cue>>(); 57503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 57603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 57703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 57803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** @hide */ 57903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public static class Cue { 58003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public long mStartTimeMs; 58103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public long mEndTimeMs; 58203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public long[] mInnerTimesMs; 58303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public long mRunID; 58403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 58503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** @hide */ 58603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public Cue mNextInRun; 58703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 58803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public void onTime(long timeMs) { } 58903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 59003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 59103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** @hide update mRunsByEndTime (with default end time) */ 59203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar protected void finishedRun(long runID) { 59303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (runID != 0 && runID != ~0) { 59403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar Run run = mRunsByID.get(runID); 59503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (run != null) { 59603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar run.storeByEndTimeMs(mRunsByEndTime); 59703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 59803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 59903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 60003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 60103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** @hide update mRunsByEndTime with given end time */ 60203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public void setRunDiscardTimeMs(long runID, long timeMs) { 60303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (runID != 0 && runID != ~0) { 60403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar Run run = mRunsByID.get(runID); 60503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (run != null) { 60603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar run.mEndTimeMs = timeMs; 60703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar run.storeByEndTimeMs(mRunsByEndTime); 60803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 60903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 61003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 61103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 6123cdf7c5b622a8fbb20410736bdab5888d0e1873cRobert Shih /** @hide whether this is a text track who fires events instead getting rendered */ 613a460ea1a2c178a2c1816b1a983333166726ad579Robert Shih public int getTrackType() { 614a460ea1a2c178a2c1816b1a983333166726ad579Robert Shih return getRenderingWidget() == null 615a460ea1a2c178a2c1816b1a983333166726ad579Robert Shih ? TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT 616a460ea1a2c178a2c1816b1a983333166726ad579Robert Shih : TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE; 6173cdf7c5b622a8fbb20410736bdab5888d0e1873cRobert Shih } 6183cdf7c5b622a8fbb20410736bdab5888d0e1873cRobert Shih 6193cdf7c5b622a8fbb20410736bdab5888d0e1873cRobert Shih 62003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar /** @hide */ 62103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar private static class Run { 62203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public Cue mFirstCue; 62303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public Run mNextRunAtEndTimeMs; 62403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public Run mPrevRunAtEndTimeMs; 62503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public long mEndTimeMs = -1; 62603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public long mRunID = 0; 62703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar private long mStoredEndTimeMs = -1; 62803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 62903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public void storeByEndTimeMs(LongSparseArray<Run> runsByEndTime) { 63003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar // remove old value if any 63103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar int ix = runsByEndTime.indexOfKey(mStoredEndTimeMs); 63203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (ix >= 0) { 63303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (mPrevRunAtEndTimeMs == null) { 63403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar assert(this == runsByEndTime.valueAt(ix)); 63503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (mNextRunAtEndTimeMs == null) { 63603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar runsByEndTime.removeAt(ix); 63703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } else { 63803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar runsByEndTime.setValueAt(ix, mNextRunAtEndTimeMs); 63903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 64003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 64103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar removeAtEndTimeMs(); 64203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 64303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 64403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar // add new value 64503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (mEndTimeMs >= 0) { 64603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mPrevRunAtEndTimeMs = null; 64703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mNextRunAtEndTimeMs = runsByEndTime.get(mEndTimeMs); 64803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (mNextRunAtEndTimeMs != null) { 64903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mNextRunAtEndTimeMs.mPrevRunAtEndTimeMs = this; 65003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 65103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar runsByEndTime.put(mEndTimeMs, this); 65203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mStoredEndTimeMs = mEndTimeMs; 65303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 65403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 65503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 65603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar public void removeAtEndTimeMs() { 65703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar Run prev = mPrevRunAtEndTimeMs; 65803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar 65903c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (mPrevRunAtEndTimeMs != null) { 66003c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mPrevRunAtEndTimeMs.mNextRunAtEndTimeMs = mNextRunAtEndTimeMs; 66103c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mPrevRunAtEndTimeMs = null; 66203c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 66303c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar if (mNextRunAtEndTimeMs != null) { 66403c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mNextRunAtEndTimeMs.mPrevRunAtEndTimeMs = prev; 66503c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar mNextRunAtEndTimeMs = null; 66603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 66703c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 66803c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar } 669d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette 670d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette /** 671d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * Interface for rendering subtitles onto a Canvas. 672d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette */ 673d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette public interface RenderingWidget { 674d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette /** 675d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * Sets the widget's callback, which is used to send updates when the 676d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * rendered data has changed. 677d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * 678d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * @param callback update callback 679d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette */ 680d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette public void setOnChangedListener(OnChangedListener callback); 681d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette 682d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette /** 683d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * Sets the widget's size. 684d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * 685d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * @param width width in pixels 686d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * @param height height in pixels 687d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette */ 688d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette public void setSize(int width, int height); 689d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette 690d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette /** 691d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * Sets whether the widget should draw subtitles. 692d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * 693d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * @param visible true if subtitles should be drawn, false otherwise 694d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette */ 695d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette public void setVisible(boolean visible); 696d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette 697d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette /** 698d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * Renders subtitles onto a {@link Canvas}. 699d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * 700d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * @param c canvas on which to render subtitles 701d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette */ 702d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette public void draw(Canvas c); 703d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette 704d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette /** 705d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * Called when the widget is attached to a window. 706d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette */ 707d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette public void onAttachedToWindow(); 708d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette 709d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette /** 710d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * Called when the widget is detached from a window. 711d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette */ 712d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette public void onDetachedFromWindow(); 713d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette 714d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette /** 715d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * Callback used to send updates about changes to rendering data. 716d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette */ 717d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette public interface OnChangedListener { 718d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette /** 719d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * Called when the rendering data has changed. 720d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * 721d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * @param renderingWidget the widget whose data has changed 722d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette */ 723d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette public void onChanged(RenderingWidget renderingWidget); 724d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette } 725d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette } 72603c25794b66b0d01e0e850042713f8009c787dc2Lajos Molnar} 727