import android.content.ServiceConnection;
import android.database.Cursor;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
import com.cyanogenmod.eleven.loaders.PlaylistSongLoader;
import com.cyanogenmod.eleven.loaders.SongLoader;
import com.cyanogenmod.eleven.loaders.TopTracksLoader;
+import com.cyanogenmod.eleven.locale.LocaleUtils;
import com.cyanogenmod.eleven.menu.FragmentMenuItems;
import com.cyanogenmod.eleven.model.Album;
import com.cyanogenmod.eleven.model.AlbumArtistDetails;
import java.io.File;
import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
import java.util.WeakHashMap;
/**
public static IElevenService mService = null;
- private static int sForegroundActivities = 0;
-
private static final WeakHashMap<Context, ServiceBinder> mConnectionMap;
private static final long[] sEmptyList;
public static final String MUSIC_ONLY_SELECTION = MediaStore.Audio.AudioColumns.IS_MUSIC + "=1"
+ " AND " + MediaStore.Audio.AudioColumns.TITLE + " != ''"; //$NON-NLS-2$
+ public static final long UPDATE_FREQUENCY_MS = 500;
+ public static final long UPDATE_FREQUENCY_FAST_MS = 30;
+
static {
mConnectionMap = new WeakHashMap<Context, ServiceBinder>();
sEmptyList = new long[0];
}
final ContextWrapper contextWrapper = new ContextWrapper(realActivity);
contextWrapper.startService(new Intent(contextWrapper, MusicPlaybackService.class));
- final ServiceBinder binder = new ServiceBinder(callback);
+ final ServiceBinder binder = new ServiceBinder(callback,
+ contextWrapper.getApplicationContext());
if (contextWrapper.bindService(
new Intent().setClass(contextWrapper, MusicPlaybackService.class), binder, 0)) {
mConnectionMap.put(contextWrapper, binder);
public static final class ServiceBinder implements ServiceConnection {
private final ServiceConnection mCallback;
+ private final Context mContext;
/**
* Constructor of <code>ServiceBinder</code>
*
* @param context The {@link ServiceConnection} to use
*/
- public ServiceBinder(final ServiceConnection callback) {
+ public ServiceBinder(final ServiceConnection callback, final Context context) {
mCallback = callback;
+ mContext = context;
}
@Override
if (mCallback != null) {
mCallback.onServiceConnected(className, service);
}
+ MusicUtils.initPlaybackServiceWithSettings(mContext);
}
@Override
}
/**
+ * Initialize playback service with values from Settings
+ */
+ public static void initPlaybackServiceWithSettings(final Context context) {
+ MusicUtils.setShakeToPlayEnabled(
+ PreferenceUtils.getInstance(context).getShakeToPlay());
+ MusicUtils.setShowAlbumArtOnLockscreen(
+ PreferenceUtils.getInstance(context).getShowAlbumArtOnLockscreen());
+ }
+
+ /**
+ * Set shake to play status
+ */
+ public static void setShakeToPlayEnabled(final boolean enabled) {
+ try {
+ if (mService != null) {
+ mService.setShakeToPlayEnabled(enabled);
+ }
+ } catch (final RemoteException ignored) {
+ }
+ }
+
+ /**
+ * Set show album art on lockscreen
+ */
+ public static void setShowAlbumArtOnLockscreen(final boolean enabled) {
+ try {
+ if (mService != null) {
+ mService.setLockscreenAlbumArt(enabled);
+ }
+ } catch (final RemoteException ignored) {
+ }
+ }
+
+ /**
* Changes to the next track asynchronously
*/
public static void asyncNext(final Context context) {
if (forceShuffle) {
mService.setShuffleMode(MusicPlaybackService.SHUFFLE_NORMAL);
}
- final long currentId = mService.getAudioId();
- final int currentQueuePosition = getQueuePosition();
- if (position != -1 && currentQueuePosition == position && currentId == list[position]) {
- final long[] playlist = getQueue();
- if (Arrays.equals(list, playlist)) {
- mService.play();
- return;
- }
- }
if (position < 0) {
position = 0;
}
}
/**
- * Used to build and show a notification when Apollo is sent into the
- * background
- *
- * @param context The {@link Context} to use.
- */
- public static void notifyForegroundStateChanged(final Context context, boolean inForeground) {
- int old = sForegroundActivities;
- if (inForeground) {
- sForegroundActivities++;
- } else {
- sForegroundActivities--;
- }
-
- if (old == 0 || sForegroundActivities == 0) {
- final Intent intent = new Intent(context, MusicPlaybackService.class);
- intent.setAction(MusicPlaybackService.FOREGROUND_STATE_CHANGED);
- intent.putExtra(MusicPlaybackService.NOW_IN_FOREGROUND, sForegroundActivities != 0);
- context.startService(intent);
- }
- }
-
- /**
* Perminately deletes item(s) from the user's device
*
* @param context The {@link Context} to use.
* This will take a name, removes things like "the", "an", etc
* as well as special characters, then find the localized label
* @param name Name to get the label of
- * @param trimName boolean flag to run the trimmer on the name
* @return the localized label of the bucket that the name falls into
*/
- public static String getLocalizedBucketLetter(String name, boolean trimName) {
+ public static String getLocalizedBucketLetter(String name) {
if (name == null || name.length() == 0) {
return null;
}
- if (trimName) {
- name = getTrimmedName(name);
- }
+ name = getTrimmedName(name);
if (name.length() > 0) {
- String lbl = LocaleUtils.getInstance().getLabel(name);
- // For now let's cap it to latin alphabet and the # sign
- // since chinese characters are resulting in " " and other random
- // characters but the sort doesn't match the sql sort so it is
- // not quite sorted
- if (lbl != null && lbl.length() > 0) {
- char ch = lbl.charAt(0);
- if ((ch < 'A' || ch > 'Z') && ch != '#') {
- return null;
- }
- }
-
- if (lbl != null && lbl.length() > 0) {
- return lbl;
- }
+ return LocaleUtils.getInstance().getLabel(name);
}
return null;
}
/**
- * Determines the correct item attribute to use for a given sort request and generates the
- * localized bucket for that attribute
- * @param item
- * @param sortOrder
- * @param <T>
- * @return
- */
- public static <T> String getLocalizedBucketLetterByAttribute(T item, String sortOrder) {
- if (item instanceof Song) {
- // we aren't 'trimming' certain attributes - a flag for such attributes
- boolean trimName = true;
- String attributeToLocalize = ((Song)item).mSongName;
-
- // select Song attribute based on the sort order
- if (sortOrder.equals(SortOrder.SongSortOrder.SONG_ARTIST) ) {
- attributeToLocalize = ((Song)item).mArtistName;
- trimName = false;
- } else if (sortOrder.equals(SortOrder.SongSortOrder.SONG_ALBUM) ) {
- attributeToLocalize = ((Song)item).mAlbumName;
- }
-
- return getLocalizedBucketLetter(attributeToLocalize, trimName);
- } else if (item instanceof Artist) {
- return getLocalizedBucketLetter(((Artist)item).mArtistName, true);
- } else if (item instanceof Album) {
- // we aren't 'trimming' certain attributes - a flag for such attributes
- boolean trimName = true;
- String attributeToLocalize = ((Album)item).mAlbumName;
-
- if (sortOrder.equals(SortOrder.AlbumSortOrder.ALBUM_ARTIST) ) {
- attributeToLocalize = ((Album)item).mArtistName;
- trimName = false;
- }
-
- return getLocalizedBucketLetter(attributeToLocalize, trimName);
- }
-
- return null;
- }
-
- /**
*
* @param sortOrder values are mostly derived from SortOrder.class or could also be any sql
* order clause
public static boolean isSortOrderDesending(String sortOrder) {
return sortOrder.endsWith(" DESC");
}
+
+ /**
+ * Takes a collection of items and builds a comma-separated list of them
+ * @param items collection of items
+ * @return comma-separted list of items
+ */
+ public static final <E> String buildCollectionAsString(Collection<E> items) {
+ Iterator<E> iterator = items.iterator();
+ StringBuilder str = new StringBuilder();
+ if (iterator.hasNext()) {
+ str.append(iterator.next());
+ while (iterator.hasNext()) {
+ str.append(",");
+ str.append(iterator.next());
+ }
+ }
+
+ return str.toString();
+ }
}