/* This file is part of Subsonic. Subsonic is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Subsonic is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Subsonic. If not, see . Copyright 2009 (C) Sindre Mehus */ package org.moire.ultrasonic.util; import android.content.Context; import android.util.Log; import org.moire.ultrasonic.data.ActiveServerProvider; import org.moire.ultrasonic.domain.MusicDirectory; import org.moire.ultrasonic.service.MusicService; import org.moire.ultrasonic.service.MusicServiceFactory; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; /** * @author Sindre Mehus * @version $Id$ */ public class ShufflePlayBuffer { private static final String TAG = ShufflePlayBuffer.class.getSimpleName(); private static final int CAPACITY = 50; private static final int REFILL_THRESHOLD = 40; private final List buffer = new ArrayList(); private final Context context; private ScheduledExecutorService executorService; private int currentServer; public boolean isEnabled = false; public ShufflePlayBuffer(Context context) { this.context = context; } public void onCreate() { executorService = Executors.newSingleThreadScheduledExecutor(); Runnable runnable = new Runnable() { @Override public void run() { refill(); } }; executorService.scheduleWithFixedDelay(runnable, 1, 10, TimeUnit.SECONDS); Log.i(TAG, "ShufflePlayBuffer created"); } public void onDestroy() { executorService.shutdown(); Log.i(TAG, "ShufflePlayBuffer destroyed"); } public List get(int size) { clearBufferIfNecessary(); List result = new ArrayList(size); synchronized (buffer) { while (!buffer.isEmpty() && result.size() < size) { result.add(buffer.remove(buffer.size() - 1)); } } Log.i(TAG, String.format("Taking %d songs from shuffle play buffer. %d remaining.", result.size(), buffer.size())); return result; } private void refill() { if (!isEnabled) return; // Check if active server has changed. clearBufferIfNecessary(); if (buffer.size() > REFILL_THRESHOLD || (!Util.isNetworkConnected(context) && !ActiveServerProvider.Companion.isOffline(context))) { return; } try { MusicService service = MusicServiceFactory.getMusicService(context); int n = CAPACITY - buffer.size(); MusicDirectory songs = service.getRandomSongs(n, context, null); synchronized (buffer) { buffer.addAll(songs.getChildren()); Log.i(TAG, String.format("Refilled shuffle play buffer with %d songs.", songs.getChildren().size())); } } catch (Exception x) { Log.w(TAG, "Failed to refill shuffle play buffer.", x); } } private void clearBufferIfNecessary() { synchronized (buffer) { if (currentServer != ActiveServerProvider.Companion.getActiveServerId(context)) { currentServer = ActiveServerProvider.Companion.getActiveServerId(context); buffer.clear(); } } } }