diff options
Diffstat (limited to 'src/de/danoeh/antennapod/service/playback/PlaybackServiceTaskManager.java')
-rw-r--r-- | src/de/danoeh/antennapod/service/playback/PlaybackServiceTaskManager.java | 384 |
1 files changed, 0 insertions, 384 deletions
diff --git a/src/de/danoeh/antennapod/service/playback/PlaybackServiceTaskManager.java b/src/de/danoeh/antennapod/service/playback/PlaybackServiceTaskManager.java deleted file mode 100644 index 680ec2e2f..000000000 --- a/src/de/danoeh/antennapod/service/playback/PlaybackServiceTaskManager.java +++ /dev/null @@ -1,384 +0,0 @@ -package de.danoeh.antennapod.service.playback; - -import android.content.Context; -import android.util.Log; - -import org.apache.commons.lang3.Validate; - -import de.danoeh.antennapod.BuildConfig; -import de.danoeh.antennapod.feed.EventDistributor; -import de.danoeh.antennapod.feed.FeedItem; -import de.danoeh.antennapod.storage.DBReader; -import de.danoeh.antennapod.util.playback.Playable; - -import java.util.List; -import java.util.concurrent.*; - -/** - * Manages the background tasks of PlaybackSerivce, i.e. - * the sleep timer, the position saver, the widget updater and - * the queue loader. - * <p/> - * The PlaybackServiceTaskManager(PSTM) uses a callback object (PSTMCallback) - * to notify the PlaybackService about updates from the running tasks. - */ -public class PlaybackServiceTaskManager { - private static final String TAG = "PlaybackServiceTaskManager"; - - /** - * Update interval of position saver in milliseconds. - */ - public static final int POSITION_SAVER_WAITING_INTERVAL = 5000; - /** - * Notification interval of widget updater in milliseconds. - */ - public static final int WIDGET_UPDATER_NOTIFICATION_INTERVAL = 1500; - - private static final int SCHED_EX_POOL_SIZE = 2; - private final ScheduledThreadPoolExecutor schedExecutor; - - private ScheduledFuture positionSaverFuture; - private ScheduledFuture widgetUpdaterFuture; - private ScheduledFuture sleepTimerFuture; - private volatile Future<List<FeedItem>> queueFuture; - private volatile Future chapterLoaderFuture; - - private SleepTimer sleepTimer; - - private final Context context; - private final PSTMCallback callback; - - /** - * Sets up a new PSTM. This method will also start the queue loader task. - * - * @param context - * @param callback A PSTMCallback object for notifying the user about updates. Must not be null. - */ - public PlaybackServiceTaskManager(Context context, PSTMCallback callback) { - Validate.notNull(context); - Validate.notNull(callback); - - this.context = context; - this.callback = callback; - schedExecutor = new ScheduledThreadPoolExecutor(SCHED_EX_POOL_SIZE, new ThreadFactory() { - @Override - public Thread newThread(Runnable r) { - Thread t = new Thread(r); - t.setPriority(Thread.MIN_PRIORITY); - return t; - } - }); - loadQueue(); - EventDistributor.getInstance().register(eventDistributorListener); - } - - private final EventDistributor.EventListener eventDistributorListener = new EventDistributor.EventListener() { - @Override - public void update(EventDistributor eventDistributor, Integer arg) { - if ((EventDistributor.QUEUE_UPDATE & arg) != 0) { - cancelQueueLoader(); - loadQueue(); - } - } - }; - - private synchronized boolean isQueueLoaderActive() { - return queueFuture != null && !queueFuture.isDone(); - } - - private synchronized void cancelQueueLoader() { - if (isQueueLoaderActive()) { - queueFuture.cancel(true); - } - } - - private synchronized void loadQueue() { - if (!isQueueLoaderActive()) { - queueFuture = schedExecutor.submit(new Callable<List<FeedItem>>() { - @Override - public List<FeedItem> call() throws Exception { - return DBReader.getQueue(context); - } - }); - } - } - - /** - * Returns the queue if it is already loaded or null if it hasn't been loaded yet. - * In order to wait until the queue has been loaded, use getQueue() - */ - public synchronized List<FeedItem> getQueueIfLoaded() { - if (queueFuture.isDone()) { - try { - return queueFuture.get(); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (ExecutionException e) { - e.printStackTrace(); - } - } - return null; - } - - /** - * Returns the queue or waits until the PSTM has loaded the queue from the database. - */ - public synchronized List<FeedItem> getQueue() throws InterruptedException { - try { - return queueFuture.get(); - } catch (ExecutionException e) { - throw new IllegalArgumentException(e); - } - } - - /** - * Starts the position saver task. If the position saver is already active, nothing will happen. - */ - public synchronized void startPositionSaver() { - if (!isPositionSaverActive()) { - Runnable positionSaver = new Runnable() { - @Override - public void run() { - callback.positionSaverTick(); - } - }; - positionSaverFuture = schedExecutor.scheduleWithFixedDelay(positionSaver, POSITION_SAVER_WAITING_INTERVAL, - POSITION_SAVER_WAITING_INTERVAL, TimeUnit.MILLISECONDS); - - if (BuildConfig.DEBUG) Log.d(TAG, "Started PositionSaver"); - } else { - if (BuildConfig.DEBUG) Log.d(TAG, "Call to startPositionSaver was ignored."); - } - } - - /** - * Returns true if the position saver is currently running. - */ - public synchronized boolean isPositionSaverActive() { - return positionSaverFuture != null && !positionSaverFuture.isCancelled() && !positionSaverFuture.isDone(); - } - - /** - * Cancels the position saver. If the position saver is not running, nothing will happen. - */ - public synchronized void cancelPositionSaver() { - if (isPositionSaverActive()) { - positionSaverFuture.cancel(false); - if (BuildConfig.DEBUG) Log.d(TAG, "Cancelled PositionSaver"); - } - } - - /** - * Starts the widget updater task. If the widget updater is already active, nothing will happen. - */ - public synchronized void startWidgetUpdater() { - if (!isWidgetUpdaterActive()) { - Runnable widgetUpdater = new Runnable() { - @Override - public void run() { - callback.onWidgetUpdaterTick(); - } - }; - widgetUpdaterFuture = schedExecutor.scheduleWithFixedDelay(widgetUpdater, WIDGET_UPDATER_NOTIFICATION_INTERVAL, - WIDGET_UPDATER_NOTIFICATION_INTERVAL, TimeUnit.MILLISECONDS); - - if (BuildConfig.DEBUG) Log.d(TAG, "Started WidgetUpdater"); - } else { - if (BuildConfig.DEBUG) Log.d(TAG, "Call to startWidgetUpdater was ignored."); - } - } - - /** - * Starts a new sleep timer with the given waiting time. If another sleep timer is already active, it will be - * cancelled first. - * After waitingTime has elapsed, onSleepTimerExpired() will be called. - * - * @throws java.lang.IllegalArgumentException if waitingTime <= 0 - */ - public synchronized void setSleepTimer(long waitingTime) { - Validate.isTrue(waitingTime > 0, "Waiting time <= 0"); - - if (BuildConfig.DEBUG) - Log.d(TAG, "Setting sleep timer to " + Long.toString(waitingTime) - + " milliseconds"); - if (isSleepTimerActive()) { - sleepTimerFuture.cancel(true); - } - sleepTimer = new SleepTimer(waitingTime); - sleepTimerFuture = schedExecutor.schedule(sleepTimer, 0, TimeUnit.MILLISECONDS); - } - - /** - * Returns true if the sleep timer is currently active. - */ - public synchronized boolean isSleepTimerActive() { - return sleepTimer != null && sleepTimerFuture != null && !sleepTimerFuture.isCancelled() && !sleepTimerFuture.isDone() && sleepTimer.isWaiting; - } - - /** - * Disables the sleep timer. If the sleep timer is not active, nothing will happen. - */ - public synchronized void disableSleepTimer() { - if (isSleepTimerActive()) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Disabling sleep timer"); - sleepTimerFuture.cancel(true); - } - } - - /** - * Returns the current sleep timer time or 0 if the sleep timer is not active. - */ - public synchronized long getSleepTimerTimeLeft() { - if (isSleepTimerActive()) { - return sleepTimer.getWaitingTime(); - } else { - return 0; - } - } - - - /** - * Returns true if the widget updater is currently running. - */ - public synchronized boolean isWidgetUpdaterActive() { - return widgetUpdaterFuture != null && !widgetUpdaterFuture.isCancelled() && !widgetUpdaterFuture.isDone(); - } - - /** - * Cancels the widget updater. If the widget updater is not running, nothing will happen. - */ - public synchronized void cancelWidgetUpdater() { - if (isWidgetUpdaterActive()) { - widgetUpdaterFuture.cancel(false); - if (BuildConfig.DEBUG) Log.d(TAG, "Cancelled WidgetUpdater"); - } - } - - private synchronized void cancelChapterLoader() { - if (isChapterLoaderActive()) { - chapterLoaderFuture.cancel(true); - } - } - - private synchronized boolean isChapterLoaderActive() { - return chapterLoaderFuture != null && !chapterLoaderFuture.isDone(); - } - - /** - * Starts a new thread that loads the chapter marks from a playable object. If another chapter loader is already active, - * it will be cancelled first. - * On completion, the callback's onChapterLoaded method will be called. - */ - public synchronized void startChapterLoader(final Playable media) { - Validate.notNull(media); - - if (isChapterLoaderActive()) { - cancelChapterLoader(); - } - - Runnable chapterLoader = new Runnable() { - @Override - public void run() { - if (BuildConfig.DEBUG) - Log.d(TAG, "Chapter loader started"); - if (media.getChapters() == null) { - media.loadChapterMarks(); - if (!Thread.currentThread().isInterrupted() && media.getChapters() != null) { - callback.onChapterLoaded(media); - } - } - if (BuildConfig.DEBUG) - Log.d(TAG, "Chapter loader stopped"); - } - }; - chapterLoaderFuture = schedExecutor.submit(chapterLoader); - } - - - /** - * Cancels all tasks. The PSTM will be in the initial state after execution of this method. - */ - public synchronized void cancelAllTasks() { - cancelPositionSaver(); - cancelWidgetUpdater(); - disableSleepTimer(); - cancelQueueLoader(); - cancelChapterLoader(); - } - - /** - * Cancels all tasks and shuts down the internal executor service of the PSTM. The object should not be used after - * execution of this method. - */ - public synchronized void shutdown() { - EventDistributor.getInstance().unregister(eventDistributorListener); - cancelAllTasks(); - schedExecutor.shutdown(); - } - - /** - * Sleeps for a given time and then pauses playback. - */ - private class SleepTimer implements Runnable { - private static final String TAG = "SleepTimer"; - private static final long UPDATE_INTERVALL = 1000L; - private volatile long waitingTime; - private volatile boolean isWaiting; - - public SleepTimer(long waitingTime) { - super(); - this.waitingTime = waitingTime; - isWaiting = true; - } - - @Override - public void run() { - if (BuildConfig.DEBUG) - Log.d(TAG, "Starting"); - while (waitingTime > 0) { - try { - Thread.sleep(UPDATE_INTERVALL); - waitingTime -= UPDATE_INTERVALL; - - if (waitingTime <= 0) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Waiting completed"); - postExecute(); - if (!Thread.currentThread().isInterrupted()) { - callback.onSleepTimerExpired(); - } - - } - } catch (InterruptedException e) { - Log.d(TAG, "Thread was interrupted while waiting"); - break; - } - } - postExecute(); - } - - protected void postExecute() { - isWaiting = false; - } - - public long getWaitingTime() { - return waitingTime; - } - - public boolean isWaiting() { - return isWaiting; - } - - } - - public static interface PSTMCallback { - void positionSaverTick(); - - void onSleepTimerExpired(); - - void onWidgetUpdaterTick(); - - void onChapterLoaded(Playable media); - } -} |