MusicUtils.java revision 3b55356662437499c38418629a38c8fb08880302
1792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project/*
2792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project *
4792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * you may not use this file except in compliance with the License.
6792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * You may obtain a copy of the License at
7792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project *
8792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project *
10792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * See the License for the specific language governing permissions and
14792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project * limitations under the License.
15792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project */
16792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
17792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectpackage com.android.music;
18792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
19792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.app.Activity;
20792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.content.ComponentName;
21792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.content.ContentResolver;
22792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.content.ContentUris;
23792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.content.ContentValues;
24792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.content.Context;
25f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissenimport android.content.ContextWrapper;
26792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.content.Intent;
27792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.content.ServiceConnection;
28792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.content.SharedPreferences;
29792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.content.SharedPreferences.Editor;
30792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.content.res.Resources;
31792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.database.Cursor;
32792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.graphics.Bitmap;
33792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.graphics.BitmapFactory;
34792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.graphics.Canvas;
35792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.graphics.ColorFilter;
363193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissenimport android.graphics.ColorMatrix;
373193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissenimport android.graphics.ColorMatrixColorFilter;
383193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissenimport android.graphics.Matrix;
393193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissenimport android.graphics.Paint;
40792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.graphics.PixelFormat;
41792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.graphics.drawable.BitmapDrawable;
42792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.graphics.drawable.Drawable;
43792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.net.Uri;
44792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.os.Environment;
45792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.os.ParcelFileDescriptor;
467a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissenimport android.os.RemoteException;
47792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.provider.MediaStore;
48792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.provider.Settings;
497a05298d5af6f796f3a260fa60b11d1c029b4207Marco Nelissenimport android.text.TextUtils;
50792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.util.Log;
51ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissenimport android.view.Menu;
52ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissenimport android.view.MenuItem;
53792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.view.SubMenu;
54792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.view.View;
55ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissenimport android.view.ViewGroup;
56792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.view.Window;
57f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissenimport android.view.MenuItem.OnMenuItemClickListener;
58ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissenimport android.widget.TabWidget;
59792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.widget.TextView;
60792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectimport android.widget.Toast;
61792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
627a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissenimport java.io.File;
637a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissenimport java.io.FileDescriptor;
647a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissenimport java.io.FileNotFoundException;
657a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissenimport java.io.IOException;
667a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissenimport java.io.InputStream;
677a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissenimport java.util.Arrays;
687a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissenimport java.util.Formatter;
697a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissenimport java.util.HashMap;
707a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissenimport java.util.Locale;
717a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen
72792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Projectpublic class MusicUtils {
73792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
74792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    private static final String TAG = "MusicUtils";
75792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
76792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    public interface Defs {
77792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        public final static int OPEN_URL = 0;
78792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        public final static int ADD_TO_PLAYLIST = 1;
79792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        public final static int USE_AS_RINGTONE = 2;
80792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        public final static int PLAYLIST_SELECTED = 3;
81792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        public final static int NEW_PLAYLIST = 4;
82792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        public final static int PLAY_SELECTION = 5;
83792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        public final static int GOTO_START = 6;
84792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        public final static int GOTO_PLAYBACK = 7;
85792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        public final static int PARTY_SHUFFLE = 8;
86792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        public final static int SHUFFLE_ALL = 9;
87792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        public final static int DELETE_ITEM = 10;
88792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        public final static int SCAN_DONE = 11;
89792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        public final static int QUEUE = 12;
90792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        public final static int CHILD_MENU_BASE = 13; // this should be the last item
91792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
92792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
93792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    public static String makeAlbumsLabel(Context context, int numalbums, int numsongs, boolean isUnknown) {
94792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        // There are two formats for the albums/songs information:
95792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        // "N Song(s)"  - used for unknown artist/album
96792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        // "N Album(s)" - used for known albums
97792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
98792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        StringBuilder songs_albums = new StringBuilder();
99792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
100792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        Resources r = context.getResources();
101792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (isUnknown) {
102792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            if (numsongs == 1) {
103792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                songs_albums.append(context.getString(R.string.onesong));
104792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            } else {
105792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                String f = r.getQuantityText(R.plurals.Nsongs, numsongs).toString();
106792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                sFormatBuilder.setLength(0);
107792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                sFormatter.format(f, Integer.valueOf(numsongs));
108792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                songs_albums.append(sFormatBuilder);
109792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
110792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        } else {
111792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            String f = r.getQuantityText(R.plurals.Nalbums, numalbums).toString();
112792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            sFormatBuilder.setLength(0);
113792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            sFormatter.format(f, Integer.valueOf(numalbums));
114792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            songs_albums.append(sFormatBuilder);
115792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            songs_albums.append(context.getString(R.string.albumsongseparator));
116792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
117792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        return songs_albums.toString();
118792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
119792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
120792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    /**
121792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project     * This is now only used for the query screen
122792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project     */
123792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    public static String makeAlbumsSongsLabel(Context context, int numalbums, int numsongs, boolean isUnknown) {
124792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        // There are several formats for the albums/songs information:
125792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        // "1 Song"   - used if there is only 1 song
126792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        // "N Songs" - used for the "unknown artist" item
127792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        // "1 Album"/"N Songs"
128792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        // "N Album"/"M Songs"
129792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        // Depending on locale, these may need to be further subdivided
130792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
131792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        StringBuilder songs_albums = new StringBuilder();
132792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
133792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (numsongs == 1) {
134792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            songs_albums.append(context.getString(R.string.onesong));
135792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        } else {
136792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            Resources r = context.getResources();
137792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            if (! isUnknown) {
138792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                String f = r.getQuantityText(R.plurals.Nalbums, numalbums).toString();
139792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                sFormatBuilder.setLength(0);
140792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                sFormatter.format(f, Integer.valueOf(numalbums));
141792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                songs_albums.append(sFormatBuilder);
142792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                songs_albums.append(context.getString(R.string.albumsongseparator));
143792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
144792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            String f = r.getQuantityText(R.plurals.Nsongs, numsongs).toString();
145792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            sFormatBuilder.setLength(0);
146792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            sFormatter.format(f, Integer.valueOf(numsongs));
147792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            songs_albums.append(sFormatBuilder);
148792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
149792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        return songs_albums.toString();
150792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
151792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
152792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    public static IMediaPlaybackService sService = null;
153792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    private static HashMap<Context, ServiceBinder> sConnectionMap = new HashMap<Context, ServiceBinder>();
154792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
155f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen    public static class ServiceToken {
156f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen        ContextWrapper mWrappedContext;
157f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen        ServiceToken(ContextWrapper context) {
158f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen            mWrappedContext = context;
159f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen        }
160f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen    }
161f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen
1623b55356662437499c38418629a38c8fb08880302Marco Nelissen    public static ServiceToken bindToService(Activity context) {
163792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        return bindToService(context, null);
164792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
165792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
1663b55356662437499c38418629a38c8fb08880302Marco Nelissen    public static ServiceToken bindToService(Activity context, ServiceConnection callback) {
1673b55356662437499c38418629a38c8fb08880302Marco Nelissen        Activity realActivity = context.getParent();
1683b55356662437499c38418629a38c8fb08880302Marco Nelissen        if (realActivity == null) {
1693b55356662437499c38418629a38c8fb08880302Marco Nelissen            realActivity = context;
1703b55356662437499c38418629a38c8fb08880302Marco Nelissen        }
1713b55356662437499c38418629a38c8fb08880302Marco Nelissen        ContextWrapper cw = new ContextWrapper(realActivity);
172f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen        cw.startService(new Intent(cw, MediaPlaybackService.class));
173792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        ServiceBinder sb = new ServiceBinder(callback);
174f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen        if (cw.bindService((new Intent()).setClass(cw, MediaPlaybackService.class), sb, 0)) {
175f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen            sConnectionMap.put(cw, sb);
176f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen            return new ServiceToken(cw);
177f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen        }
1783b55356662437499c38418629a38c8fb08880302Marco Nelissen        Log.e("Music", "Failed to bind to service");
179f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen        return null;
180792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
181f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen
182f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen    public static void unbindFromService(ServiceToken token) {
1833b55356662437499c38418629a38c8fb08880302Marco Nelissen        if (token == null) {
1843b55356662437499c38418629a38c8fb08880302Marco Nelissen            Log.e("MusicUtils", "Trying to unbind with null token");
1853b55356662437499c38418629a38c8fb08880302Marco Nelissen            return;
1863b55356662437499c38418629a38c8fb08880302Marco Nelissen        }
187f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen        ContextWrapper cw = token.mWrappedContext;
188f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen        ServiceBinder sb = sConnectionMap.remove(cw);
189792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (sb == null) {
190792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            Log.e("MusicUtils", "Trying to unbind for unknown Context");
191792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            return;
192792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
193f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen        cw.unbindService(sb);
194792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (sConnectionMap.isEmpty()) {
195792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            // presumably there is nobody interested in the service at this point,
196792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            // so don't hang on to the ServiceConnection
197792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            sService = null;
198792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
199792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
200792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
201792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    private static class ServiceBinder implements ServiceConnection {
202792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        ServiceConnection mCallback;
203792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        ServiceBinder(ServiceConnection callback) {
204792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            mCallback = callback;
205792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
206792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
207792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        public void onServiceConnected(ComponentName className, android.os.IBinder service) {
208792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            sService = IMediaPlaybackService.Stub.asInterface(service);
209792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            initAlbumArtCache();
210792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            if (mCallback != null) {
211792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                mCallback.onServiceConnected(className, service);
212792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
213792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
214792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
215792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        public void onServiceDisconnected(ComponentName className) {
216792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            if (mCallback != null) {
217792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                mCallback.onServiceDisconnected(className);
218792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
219792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            sService = null;
220792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
221792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
222792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
223bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen    public static long getCurrentAlbumId() {
224792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (sService != null) {
225792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            try {
226792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                return sService.getAlbumId();
227792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            } catch (RemoteException ex) {
228792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
229792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
230792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        return -1;
231792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
232792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
233bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen    public static long getCurrentArtistId() {
234792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (MusicUtils.sService != null) {
235792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            try {
236792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                return sService.getArtistId();
237792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            } catch (RemoteException ex) {
238792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
239792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
240792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        return -1;
241792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
242792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
243bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen    public static long getCurrentAudioId() {
244792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (MusicUtils.sService != null) {
245792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            try {
246792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                return sService.getAudioId();
247792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            } catch (RemoteException ex) {
248792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
249792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
250792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        return -1;
251792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
252792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
253792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    public static int getCurrentShuffleMode() {
254792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        int mode = MediaPlaybackService.SHUFFLE_NONE;
255792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (sService != null) {
256792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            try {
257792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                mode = sService.getShuffleMode();
258792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            } catch (RemoteException ex) {
259792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
260792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
261792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        return mode;
262792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
263792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
264ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen    public static void togglePartyShuffle() {
265ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        if (sService != null) {
266ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            int shuffle = getCurrentShuffleMode();
267ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            try {
268ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                if (shuffle == MediaPlaybackService.SHUFFLE_AUTO) {
269ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                    sService.setShuffleMode(MediaPlaybackService.SHUFFLE_NONE);
270ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                } else {
271ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                    sService.setShuffleMode(MediaPlaybackService.SHUFFLE_AUTO);
272ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                }
273ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            } catch (RemoteException ex) {
274ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            }
275ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        }
276ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen    }
277ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen
278ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen    public static void setPartyShuffleMenuIcon(Menu menu) {
279ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        MenuItem item = menu.findItem(Defs.PARTY_SHUFFLE);
280ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        if (item != null) {
281ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            int shuffle = MusicUtils.getCurrentShuffleMode();
282ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            if (shuffle == MediaPlaybackService.SHUFFLE_AUTO) {
283ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                item.setIcon(R.drawable.ic_menu_party_shuffle);
284ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                item.setTitle(R.string.party_shuffle_off);
285ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            } else {
286ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                item.setIcon(R.drawable.ic_menu_party_shuffle);
287ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                item.setTitle(R.string.party_shuffle);
288ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            }
289ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        }
290ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen    }
291ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen
292792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    /*
293792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project     * Returns true if a file is currently opened for playback (regardless
294792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project     * of whether it's playing or paused).
295792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project     */
296792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    public static boolean isMusicLoaded() {
297792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (MusicUtils.sService != null) {
298792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            try {
299792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                return sService.getPath() != null;
300792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            } catch (RemoteException ex) {
301792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
302792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
303792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        return false;
304792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
305792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
306bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen    private final static long [] sEmptyList = new long[0];
307f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen
308bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen    public static long [] getSongListForCursor(Cursor cursor) {
309792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (cursor == null) {
310792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            return sEmptyList;
311792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
312792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        int len = cursor.getCount();
313bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen        long [] list = new long[len];
314792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        cursor.moveToFirst();
315792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        int colidx = -1;
316792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        try {
317792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            colidx = cursor.getColumnIndexOrThrow(MediaStore.Audio.Playlists.Members.AUDIO_ID);
318792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        } catch (IllegalArgumentException ex) {
319792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            colidx = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media._ID);
320792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
321792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        for (int i = 0; i < len; i++) {
322bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen            list[i] = cursor.getLong(colidx);
323792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            cursor.moveToNext();
324792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
325792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        return list;
326792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
327792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
328bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen    public static long [] getSongListForArtist(Context context, long id) {
329792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        final String[] ccols = new String[] { MediaStore.Audio.Media._ID };
330792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        String where = MediaStore.Audio.Media.ARTIST_ID + "=" + id + " AND " +
331792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        MediaStore.Audio.Media.IS_MUSIC + "=1";
332792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        Cursor cursor = query(context, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
333792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                ccols, where, null,
334792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                MediaStore.Audio.Media.ALBUM_KEY + ","  + MediaStore.Audio.Media.TRACK);
335792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
336792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (cursor != null) {
337bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen            long [] list = getSongListForCursor(cursor);
338792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            cursor.close();
339792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            return list;
340792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
341792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        return sEmptyList;
342792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
343792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
344bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen    public static long [] getSongListForAlbum(Context context, long id) {
345792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        final String[] ccols = new String[] { MediaStore.Audio.Media._ID };
346792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        String where = MediaStore.Audio.Media.ALBUM_ID + "=" + id + " AND " +
347792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                MediaStore.Audio.Media.IS_MUSIC + "=1";
348792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        Cursor cursor = query(context, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
349792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                ccols, where, null, MediaStore.Audio.Media.TRACK);
350792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
351792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (cursor != null) {
352bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen            long [] list = getSongListForCursor(cursor);
353792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            cursor.close();
354792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            return list;
355792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
356792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        return sEmptyList;
357792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
358792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
359bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen    public static long [] getSongListForPlaylist(Context context, long plid) {
360792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        final String[] ccols = new String[] { MediaStore.Audio.Playlists.Members.AUDIO_ID };
361792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        Cursor cursor = query(context, MediaStore.Audio.Playlists.Members.getContentUri("external", plid),
362792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                ccols, null, null, MediaStore.Audio.Playlists.Members.DEFAULT_SORT_ORDER);
363792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
364792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (cursor != null) {
365bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen            long [] list = getSongListForCursor(cursor);
366792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            cursor.close();
367792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            return list;
368792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
369792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        return sEmptyList;
370792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
371792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
372792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    public static void playPlaylist(Context context, long plid) {
373bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen        long [] list = getSongListForPlaylist(context, plid);
374792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (list != null) {
375792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            playAll(context, list, -1, false);
376792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
377792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
378792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
379bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen    public static long [] getAllSongs(Context context) {
380792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        Cursor c = query(context, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
381792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                new String[] {MediaStore.Audio.Media._ID}, MediaStore.Audio.Media.IS_MUSIC + "=1",
382792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                null, null);
383792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        try {
384792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            if (c == null || c.getCount() == 0) {
385792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                return null;
386792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
387792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            int len = c.getCount();
388bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen            long [] list = new long[len];
389792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            for (int i = 0; i < len; i++) {
390792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                c.moveToNext();
391bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen                list[i] = c.getLong(0);
392792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
393792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
394792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            return list;
395792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        } finally {
396792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            if (c != null) {
397792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                c.close();
398792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
399792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
400792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
401792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
402792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    /**
403792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project     * Fills out the given submenu with items for "new playlist" and
404792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project     * any existing playlists. When the user selects an item, the
405792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project     * application will receive PLAYLIST_SELECTED with the Uri of
406792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project     * the selected playlist, NEW_PLAYLIST if a new playlist
407792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project     * should be created, and QUEUE if the "current playlist" was
408792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project     * selected.
409792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project     * @param context The context to use for creating the menu items
410792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project     * @param sub The submenu to add the items to.
411792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project     */
412792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    public static void makePlaylistMenu(Context context, SubMenu sub) {
413792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        String[] cols = new String[] {
414792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                MediaStore.Audio.Playlists._ID,
415792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                MediaStore.Audio.Playlists.NAME
416792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        };
417792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        ContentResolver resolver = context.getContentResolver();
418792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (resolver == null) {
419792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            System.out.println("resolver = null");
420792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        } else {
421792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            String whereclause = MediaStore.Audio.Playlists.NAME + " != ''";
422792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            Cursor cur = resolver.query(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
423792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                cols, whereclause, null,
424792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                MediaStore.Audio.Playlists.NAME);
425792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            sub.clear();
426792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            sub.add(1, Defs.QUEUE, 0, R.string.queue);
427792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            sub.add(1, Defs.NEW_PLAYLIST, 0, R.string.new_playlist);
428792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            if (cur != null && cur.getCount() > 0) {
429792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                //sub.addSeparator(1, 0);
430792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                cur.moveToFirst();
431792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                while (! cur.isAfterLast()) {
432792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    Intent intent = new Intent();
433bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen                    intent.putExtra("playlist", cur.getLong(0));
434792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project//                    if (cur.getInt(0) == mLastPlaylistSelected) {
435792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project//                        sub.add(0, MusicBaseActivity.PLAYLIST_SELECTED, cur.getString(1)).setIntent(intent);
436792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project//                    } else {
437792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                        sub.add(1, Defs.PLAYLIST_SELECTED, 0, cur.getString(1)).setIntent(intent);
438792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project//                    }
439792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    cur.moveToNext();
440792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                }
441792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
442792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            if (cur != null) {
443792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                cur.close();
444792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
445792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
446792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
447792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
448792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    public static void clearPlaylist(Context context, int plid) {
449792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
450792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", plid);
451792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        context.getContentResolver().delete(uri, null, null);
452792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        return;
453792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
454792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
455bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen    public static void deleteTracks(Context context, long [] list) {
456792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
457792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        String [] cols = new String [] { MediaStore.Audio.Media._ID,
458792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                MediaStore.Audio.Media.DATA, MediaStore.Audio.Media.ALBUM_ID };
459792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        StringBuilder where = new StringBuilder();
460792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        where.append(MediaStore.Audio.Media._ID + " IN (");
461792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        for (int i = 0; i < list.length; i++) {
462792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            where.append(list[i]);
463792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            if (i < list.length - 1) {
464792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                where.append(",");
465792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
466792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
467792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        where.append(")");
468792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        Cursor c = query(context, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, cols,
469792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                where.toString(), null, null);
470792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
471792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (c != null) {
472792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
473792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            // step 1: remove selected tracks from the current playlist, as well
474792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            // as from the album art cache
475792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            try {
476792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                c.moveToFirst();
477792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                while (! c.isAfterLast()) {
478792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    // remove from current playlist
479bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen                    long id = c.getLong(0);
480792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    sService.removeTrack(id);
481792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    // remove from album art cache
482bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen                    long artIndex = c.getLong(2);
483792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    synchronized(sArtCache) {
484792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                        sArtCache.remove(artIndex);
485792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    }
486792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    c.moveToNext();
487792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                }
488792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            } catch (RemoteException ex) {
489792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
490792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
491792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            // step 2: remove selected tracks from the database
492792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            context.getContentResolver().delete(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, where.toString(), null);
493792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
494792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            // step 3: remove files from card
495792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            c.moveToFirst();
496792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            while (! c.isAfterLast()) {
497792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                String name = c.getString(1);
498792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                File f = new File(name);
499792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                try {  // File.delete can throw a security exception
500792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    if (!f.delete()) {
501792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                        // I'm not sure if we'd ever get here (deletion would
502792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                        // have to fail, but no exception thrown)
503792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                        Log.e("MusicUtils", "Failed to delete file " + name);
504792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    }
505792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    c.moveToNext();
506792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                } catch (SecurityException ex) {
507792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    c.moveToNext();
508792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                }
509792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
510792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            c.close();
511792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
512792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
513792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        String message = context.getResources().getQuantityString(
514792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                R.plurals.NNNtracksdeleted, list.length, Integer.valueOf(list.length));
515792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
516792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
517792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        // We deleted a number of tracks, which could affect any number of things
518792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        // in the media content domain, so update everything.
519792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        context.getContentResolver().notifyChange(Uri.parse("content://media"), null);
520792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
521792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
522bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen    public static void addToCurrentPlaylist(Context context, long [] list) {
523792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (sService == null) {
524792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            return;
525792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
526792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        try {
527792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            sService.enqueue(list, MediaPlaybackService.LAST);
528792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            String message = context.getResources().getQuantityString(
529792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    R.plurals.NNNtrackstoplaylist, list.length, Integer.valueOf(list.length));
530792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
531792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        } catch (RemoteException ex) {
532792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
533792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
534f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen
535f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen    private static ContentValues[] sContentValuesCache = null;
536f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen
537f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen    /**
538f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen     * @param ids The source array containing all the ids to be added to the playlist
539f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen     * @param offset Where in the 'ids' array we start reading
540f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen     * @param len How many items to copy during this pass
541f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen     * @param base The play order offset to use for this pass
542f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen     */
543f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen    private static void makeInsertItems(long[] ids, int offset, int len, int base) {
544f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen        // adjust 'len' if would extend beyond the end of the source array
545f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen        if (offset + len > ids.length) {
546f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen            len = ids.length - offset;
547f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen        }
548f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen        // allocate the ContentValues array, or reallocate if it is the wrong size
549f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen        if (sContentValuesCache == null || sContentValuesCache.length != len) {
550f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen            sContentValuesCache = new ContentValues[len];
551f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen        }
552f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen        // fill in the ContentValues array with the right values for this pass
553f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen        for (int i = 0; i < len; i++) {
554f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen            if (sContentValuesCache[i] == null) {
555f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen                sContentValuesCache[i] = new ContentValues();
556f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen            }
557f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen
558f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen            sContentValuesCache[i].put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, base + offset + i);
559f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen            sContentValuesCache[i].put(MediaStore.Audio.Playlists.Members.AUDIO_ID, ids[offset + i]);
560f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen        }
561f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen    }
562792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
563bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen    public static void addToPlaylist(Context context, long [] ids, long playlistid) {
564792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (ids == null) {
565792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            // this shouldn't happen (the menuitems shouldn't be visible
566792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            // unless the selected item represents something playable
567792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            Log.e("MusicBase", "ListSelection null");
568792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        } else {
569792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            int size = ids.length;
570792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            ContentResolver resolver = context.getContentResolver();
571792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            // need to determine the number of items currently in the playlist,
572792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            // so the play_order field can be maintained.
573792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            String[] cols = new String[] {
574792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    "count(*)"
575792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            };
576792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", playlistid);
577792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            Cursor cur = resolver.query(uri, cols, null, null, null);
578792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            cur.moveToFirst();
579792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            int base = cur.getInt(0);
580792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            cur.close();
581f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen            int numinserted = 0;
582f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen            for (int i = 0; i < size; i += 1000) {
583f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen                makeInsertItems(ids, i, 1000, base);
584f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen                numinserted += resolver.bulkInsert(uri, sContentValuesCache);
585792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
586792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            String message = context.getResources().getQuantityString(
587f33a575c2b09095d58ad7af527113f767e4c37b1Marco Nelissen                    R.plurals.NNNtrackstoplaylist, numinserted, numinserted);
588792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
589792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            //mLastPlaylistSelected = playlistid;
590792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
591792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
592792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
593792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    public static Cursor query(Context context, Uri uri, String[] projection,
5944248ed203f66145f8be7cda2cfd937ec450c9609Marco Nelissen            String selection, String[] selectionArgs, String sortOrder, int limit) {
595792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        try {
596792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            ContentResolver resolver = context.getContentResolver();
597792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            if (resolver == null) {
598792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                return null;
599792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
6004248ed203f66145f8be7cda2cfd937ec450c9609Marco Nelissen            if (limit > 0) {
6014248ed203f66145f8be7cda2cfd937ec450c9609Marco Nelissen                uri = uri.buildUpon().appendQueryParameter("limit", "" + limit).build();
6024248ed203f66145f8be7cda2cfd937ec450c9609Marco Nelissen            }
603792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            return resolver.query(uri, projection, selection, selectionArgs, sortOrder);
604792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project         } catch (UnsupportedOperationException ex) {
605792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            return null;
606792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
607792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
608792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
6094248ed203f66145f8be7cda2cfd937ec450c9609Marco Nelissen    public static Cursor query(Context context, Uri uri, String[] projection,
6104248ed203f66145f8be7cda2cfd937ec450c9609Marco Nelissen            String selection, String[] selectionArgs, String sortOrder) {
6114248ed203f66145f8be7cda2cfd937ec450c9609Marco Nelissen        return query(context, uri, projection, selection, selectionArgs, sortOrder, 0);
6124248ed203f66145f8be7cda2cfd937ec450c9609Marco Nelissen    }
613792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
614792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    public static boolean isMediaScannerScanning(Context context) {
615792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        boolean result = false;
616792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        Cursor cursor = query(context, MediaStore.getMediaScannerUri(),
617792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                new String [] { MediaStore.MEDIA_SCANNER_VOLUME }, null, null, null);
618792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (cursor != null) {
619792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            if (cursor.getCount() == 1) {
620792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                cursor.moveToFirst();
621792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                result = "external".equals(cursor.getString(0));
622792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
623792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            cursor.close();
624792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
625792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
626792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        return result;
627792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
628792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
629792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    public static void setSpinnerState(Activity a) {
630792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (isMediaScannerScanning(a)) {
631792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            // start the progress spinner
632792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            a.getWindow().setFeatureInt(
633792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    Window.FEATURE_INDETERMINATE_PROGRESS,
634792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    Window.PROGRESS_INDETERMINATE_ON);
635792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
636792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            a.getWindow().setFeatureInt(
637792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    Window.FEATURE_INDETERMINATE_PROGRESS,
638792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    Window.PROGRESS_VISIBILITY_ON);
639792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        } else {
640792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            // stop the progress spinner
641792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            a.getWindow().setFeatureInt(
642792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    Window.FEATURE_INDETERMINATE_PROGRESS,
643792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    Window.PROGRESS_VISIBILITY_OFF);
644792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
645792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
646792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
6477a05298d5af6f796f3a260fa60b11d1c029b4207Marco Nelissen    private static String mLastSdStatus;
6487a05298d5af6f796f3a260fa60b11d1c029b4207Marco Nelissen
649792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    public static void displayDatabaseError(Activity a) {
65098b177710b6a9bb2de7498d68e10a0d7f53c2f06Marco Nelissen        if (a.isFinishing()) {
65198b177710b6a9bb2de7498d68e10a0d7f53c2f06Marco Nelissen            // When switching tabs really fast, we can end up with a null
65298b177710b6a9bb2de7498d68e10a0d7f53c2f06Marco Nelissen            // cursor (not sure why), which will bring us here.
65398b177710b6a9bb2de7498d68e10a0d7f53c2f06Marco Nelissen            // Don't bother showing an error message in that case.
65498b177710b6a9bb2de7498d68e10a0d7f53c2f06Marco Nelissen            return;
65598b177710b6a9bb2de7498d68e10a0d7f53c2f06Marco Nelissen        }
65698b177710b6a9bb2de7498d68e10a0d7f53c2f06Marco Nelissen
657792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        String status = Environment.getExternalStorageState();
658792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        int title = R.string.sdcard_error_title;
659792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        int message = R.string.sdcard_error_message;
660792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
661792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (status.equals(Environment.MEDIA_SHARED) ||
662792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                status.equals(Environment.MEDIA_UNMOUNTED)) {
663792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            title = R.string.sdcard_busy_title;
664792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            message = R.string.sdcard_busy_message;
665792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        } else if (status.equals(Environment.MEDIA_REMOVED)) {
666792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            title = R.string.sdcard_missing_title;
667792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            message = R.string.sdcard_missing_message;
668792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        } else if (status.equals(Environment.MEDIA_MOUNTED)){
669792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            // The card is mounted, but we didn't get a valid cursor.
670792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            // This probably means the mediascanner hasn't started scanning the
671792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            // card yet (there is a small window of time during boot where this
672792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            // will happen).
673792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            a.setTitle("");
674792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            Intent intent = new Intent();
675792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            intent.setClass(a, ScanningProgress.class);
676792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            a.startActivityForResult(intent, Defs.SCAN_DONE);
6777a05298d5af6f796f3a260fa60b11d1c029b4207Marco Nelissen        } else if (!TextUtils.equals(mLastSdStatus, status)) {
6787a05298d5af6f796f3a260fa60b11d1c029b4207Marco Nelissen            mLastSdStatus = status;
679792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            Log.d(TAG, "sd card: " + status);
680792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
681792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
682792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        a.setTitle(title);
683792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        View v = a.findViewById(R.id.sd_message);
684792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (v != null) {
685792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            v.setVisibility(View.VISIBLE);
686792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
687792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        v = a.findViewById(R.id.sd_icon);
688792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (v != null) {
689792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            v.setVisibility(View.VISIBLE);
690792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
691792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        v = a.findViewById(android.R.id.list);
692792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (v != null) {
693792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            v.setVisibility(View.GONE);
694792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
6959e0f1fde0956ee7f5b76b77df7aea9b936e2c3a9Marco Nelissen        v = a.findViewById(R.id.buttonbar);
6969e0f1fde0956ee7f5b76b77df7aea9b936e2c3a9Marco Nelissen        if (v != null) {
6979e0f1fde0956ee7f5b76b77df7aea9b936e2c3a9Marco Nelissen            v.setVisibility(View.GONE);
6989e0f1fde0956ee7f5b76b77df7aea9b936e2c3a9Marco Nelissen        }
699792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        TextView tv = (TextView) a.findViewById(R.id.sd_message);
700792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        tv.setText(message);
701792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
702792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
703792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    public static void hideDatabaseError(Activity a) {
704792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        View v = a.findViewById(R.id.sd_message);
705792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (v != null) {
706792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            v.setVisibility(View.GONE);
707792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
708792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        v = a.findViewById(R.id.sd_icon);
709792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (v != null) {
710792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            v.setVisibility(View.GONE);
711792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
712792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        v = a.findViewById(android.R.id.list);
713792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (v != null) {
714792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            v.setVisibility(View.VISIBLE);
715792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
716792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
717792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
718792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    static protected Uri getContentURIForPath(String path) {
719792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        return Uri.fromFile(new File(path));
720792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
721792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
722792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
723792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    /*  Try to use String.format() as little as possible, because it creates a
724792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project     *  new Formatter every time you call it, which is very inefficient.
725792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project     *  Reusing an existing Formatter more than tripled the speed of
726792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project     *  makeTimeString().
727792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project     *  This Formatter/StringBuilder are also used by makeAlbumSongsLabel()
728792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project     */
729792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    private static StringBuilder sFormatBuilder = new StringBuilder();
730792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    private static Formatter sFormatter = new Formatter(sFormatBuilder, Locale.getDefault());
731792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    private static final Object[] sTimeArgs = new Object[5];
732792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
733792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    public static String makeTimeString(Context context, long secs) {
7341e5a567390e41045cba6abac1d2c94eb8f59fc30Marco Nelissen        String durationformat = context.getString(
7351e5a567390e41045cba6abac1d2c94eb8f59fc30Marco Nelissen                secs < 3600 ? R.string.durationformatshort : R.string.durationformatlong);
736792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
737792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        /* Provide multiple arguments so the format can be changed easily
738792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project         * by modifying the xml.
739792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project         */
740792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        sFormatBuilder.setLength(0);
741792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
742792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        final Object[] timeArgs = sTimeArgs;
743792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        timeArgs[0] = secs / 3600;
744792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        timeArgs[1] = secs / 60;
745792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        timeArgs[2] = (secs / 60) % 60;
746792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        timeArgs[3] = secs;
747792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        timeArgs[4] = secs % 60;
748792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
749792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        return sFormatter.format(durationformat, timeArgs).toString();
750792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
751792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
752792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    public static void shuffleAll(Context context, Cursor cursor) {
753792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        playAll(context, cursor, 0, true);
754792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
755792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
756792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    public static void playAll(Context context, Cursor cursor) {
757792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        playAll(context, cursor, 0, false);
758792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
759792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
760792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    public static void playAll(Context context, Cursor cursor, int position) {
761792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        playAll(context, cursor, position, false);
762792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
763792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
764bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen    public static void playAll(Context context, long [] list, int position) {
765792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        playAll(context, list, position, false);
766792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
767792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
768792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    private static void playAll(Context context, Cursor cursor, int position, boolean force_shuffle) {
769792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
770bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen        long [] list = getSongListForCursor(cursor);
771792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        playAll(context, list, position, force_shuffle);
772792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
773792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
774bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen    private static void playAll(Context context, long [] list, int position, boolean force_shuffle) {
775792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (list.length == 0 || sService == null) {
776792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            Log.d("MusicUtils", "attempt to play empty song list");
777792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            // Don't try to play empty playlists. Nothing good will come of it.
778792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            String message = context.getString(R.string.emptyplaylist, list.length);
779792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
780792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            return;
781792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
782792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        try {
783792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            if (force_shuffle) {
784792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                sService.setShuffleMode(MediaPlaybackService.SHUFFLE_NORMAL);
785792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
786bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen            long curid = sService.getAudioId();
787792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            int curpos = sService.getQueuePosition();
788792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            if (position != -1 && curpos == position && curid == list[position]) {
789792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                // The selected file is the file that's currently playing;
790792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                // figure out if we need to restart with a new playlist,
791792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                // or just launch the playback activity.
792bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen                long [] playlist = sService.getQueue();
793792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                if (Arrays.equals(list, playlist)) {
794792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    // we don't need to set a new list, but we should resume playback if needed
795792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    sService.play();
796792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    return; // the 'finally' block will still run
797792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                }
798792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
799792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            if (position < 0) {
800792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                position = 0;
801792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
802792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            sService.open(list, force_shuffle ? -1 : position);
803792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            sService.play();
804792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        } catch (RemoteException ex) {
805792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        } finally {
806ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            Intent intent = new Intent(context, MediaPlaybackActivity.class)
807792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
808792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            context.startActivity(intent);
809792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
810792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
811792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
812792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    public static void clearQueue() {
813792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        try {
814792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            sService.removeTracks(0, Integer.MAX_VALUE);
815792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        } catch (RemoteException ex) {
816792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
817792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
818792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
819792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    // A really simple BitmapDrawable-like class, that doesn't do
820792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    // scaling, dithering or filtering.
821792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    private static class FastBitmapDrawable extends Drawable {
822792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        private Bitmap mBitmap;
823792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        public FastBitmapDrawable(Bitmap b) {
824792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            mBitmap = b;
825792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
826792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        @Override
827792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        public void draw(Canvas canvas) {
828792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            canvas.drawBitmap(mBitmap, 0, 0, null);
829792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
830792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        @Override
831792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        public int getOpacity() {
832792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            return PixelFormat.OPAQUE;
833792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
834792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        @Override
835792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        public void setAlpha(int alpha) {
836792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
837792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        @Override
838792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        public void setColorFilter(ColorFilter cf) {
839792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
840792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
841792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
842792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    private static int sArtId = -2;
843792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    private static Bitmap mCachedBit = null;
844792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    private static final BitmapFactory.Options sBitmapOptionsCache = new BitmapFactory.Options();
845792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    private static final BitmapFactory.Options sBitmapOptions = new BitmapFactory.Options();
846792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    private static final Uri sArtworkUri = Uri.parse("content://media/external/audio/albumart");
847bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen    private static final HashMap<Long, Drawable> sArtCache = new HashMap<Long, Drawable>();
848792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    private static int sArtCacheId = -1;
849792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
850792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    static {
851792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        // for the cache,
852792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        // 565 is faster to decode and display
853792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        // and we don't want to dither here because the image will be scaled down later
854792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        sBitmapOptionsCache.inPreferredConfig = Bitmap.Config.RGB_565;
855792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        sBitmapOptionsCache.inDither = false;
856792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
857792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        sBitmapOptions.inPreferredConfig = Bitmap.Config.RGB_565;
858792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        sBitmapOptions.inDither = false;
859792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
860792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
861792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    public static void initAlbumArtCache() {
862792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        try {
863792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            int id = sService.getMediaMountedCount();
864792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            if (id != sArtCacheId) {
865792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                clearAlbumArtCache();
866792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                sArtCacheId = id;
867792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
868792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        } catch (RemoteException e) {
869792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            e.printStackTrace();
870792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
871792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
872792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
873792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    public static void clearAlbumArtCache() {
874792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        synchronized(sArtCache) {
875792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            sArtCache.clear();
876792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
877792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
878792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
879bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen    public static Drawable getCachedArtwork(Context context, long artIndex, BitmapDrawable defaultArtwork) {
880792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        Drawable d = null;
881792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        synchronized(sArtCache) {
882792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            d = sArtCache.get(artIndex);
883792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
884792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (d == null) {
885792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            d = defaultArtwork;
886792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            final Bitmap icon = defaultArtwork.getBitmap();
887792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            int w = icon.getWidth();
888792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            int h = icon.getHeight();
889792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            Bitmap b = MusicUtils.getArtworkQuick(context, artIndex, w, h);
890792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            if (b != null) {
891792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                d = new FastBitmapDrawable(b);
892792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                synchronized(sArtCache) {
893792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    // the cache may have changed since we checked
894792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    Drawable value = sArtCache.get(artIndex);
895792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    if (value == null) {
896792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                        sArtCache.put(artIndex, d);
897792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    } else {
898792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                        d = value;
899792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    }
900792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                }
901792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
902792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
903792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        return d;
904792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
905792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
906792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    // Get album art for specified album. This method will not try to
907792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    // fall back to getting artwork directly from the file, nor will
908792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    // it attempt to repair the database.
909bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen    private static Bitmap getArtworkQuick(Context context, long album_id, int w, int h) {
910792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        // NOTE: There is in fact a 1 pixel border on the right side in the ImageView
911792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        // used to display this drawable. Take it into account now, so we don't have to
912792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        // scale later.
913792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        w -= 1;
914792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        ContentResolver res = context.getContentResolver();
915792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        Uri uri = ContentUris.withAppendedId(sArtworkUri, album_id);
916792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (uri != null) {
917792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            ParcelFileDescriptor fd = null;
918792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            try {
919792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                fd = res.openFileDescriptor(uri, "r");
920792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                int sampleSize = 1;
921792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
922792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                // Compute the closest power-of-two scale factor
923792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                // and pass that to sBitmapOptionsCache.inSampleSize, which will
924792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                // result in faster decoding and better quality
925792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                sBitmapOptionsCache.inJustDecodeBounds = true;
926792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                BitmapFactory.decodeFileDescriptor(
927792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                        fd.getFileDescriptor(), null, sBitmapOptionsCache);
928792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                int nextWidth = sBitmapOptionsCache.outWidth >> 1;
929792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                int nextHeight = sBitmapOptionsCache.outHeight >> 1;
930792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                while (nextWidth>w && nextHeight>h) {
931792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    sampleSize <<= 1;
932792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    nextWidth >>= 1;
933792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    nextHeight >>= 1;
934792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                }
935792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
936792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                sBitmapOptionsCache.inSampleSize = sampleSize;
937792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                sBitmapOptionsCache.inJustDecodeBounds = false;
938792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                Bitmap b = BitmapFactory.decodeFileDescriptor(
939792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                        fd.getFileDescriptor(), null, sBitmapOptionsCache);
940792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
941792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                if (b != null) {
942792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    // finally rescale to exactly the size we need
943792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    if (sBitmapOptionsCache.outWidth != w || sBitmapOptionsCache.outHeight != h) {
944792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                        Bitmap tmp = Bitmap.createScaledBitmap(b, w, h, true);
945792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                        // Bitmap.createScaledBitmap() can return the same bitmap
946792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                        if (tmp != b) b.recycle();
947792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                        b = tmp;
948792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    }
949792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                }
950792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
951792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                return b;
952792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            } catch (FileNotFoundException e) {
953792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            } finally {
954792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                try {
955792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    if (fd != null)
956792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                        fd.close();
957792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                } catch (IOException e) {
958792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                }
959792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
960792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
961792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        return null;
962792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
9633193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen
964792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    /** Get album art for specified album. You should not pass in the album id
965792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project     * for the "unknown" album here (use -1 instead)
9663193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen     * This method always returns the default album art icon when no album art is found.
967792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project     */
968bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen    public static Bitmap getArtwork(Context context, long song_id, long album_id) {
9693193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        return getArtwork(context, song_id, album_id, true);
9703193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen    }
9713193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen
9723193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen    /** Get album art for specified album. You should not pass in the album id
9733193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen     * for the "unknown" album here (use -1 instead)
9743193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen     */
9753193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen    public static Bitmap getArtwork(Context context, long song_id, long album_id,
9763193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen            boolean allowdefault) {
977792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
978792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (album_id < 0) {
979792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            // This is something that is not in the database, so get the album art directly
980792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            // from the file.
9817a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen            if (song_id >= 0) {
9827a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen                Bitmap bm = getArtworkFromFile(context, song_id, -1);
9837a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen                if (bm != null) {
9847a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen                    return bm;
9857a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen                }
986792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
9873193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen            if (allowdefault) {
9883193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen                return getDefaultArtwork(context);
9893193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen            }
9903193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen            return null;
991792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
992792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
993792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        ContentResolver res = context.getContentResolver();
994792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        Uri uri = ContentUris.withAppendedId(sArtworkUri, album_id);
995792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        if (uri != null) {
996792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            InputStream in = null;
997792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            try {
998792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                in = res.openInputStream(uri);
999792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                return BitmapFactory.decodeStream(in, null, sBitmapOptions);
1000792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            } catch (FileNotFoundException ex) {
1001792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                // The album art thumbnail does not actually exist. Maybe the user deleted it, or
1002792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                // maybe it never existed to begin with.
10037a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen                Bitmap bm = getArtworkFromFile(context, song_id, album_id);
1004792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                if (bm != null) {
1005756c3f57f11a7bb3bf1cf1333ee8ffbc51039748Marco Nelissen                    if (bm.getConfig() == null) {
1006756c3f57f11a7bb3bf1cf1333ee8ffbc51039748Marco Nelissen                        bm = bm.copy(Bitmap.Config.RGB_565, false);
10073193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen                        if (bm == null && allowdefault) {
10087a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen                            return getDefaultArtwork(context);
1009792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                        }
1010792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    }
10113193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen                } else if (allowdefault) {
10127a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen                    bm = getDefaultArtwork(context);
1013792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                }
1014792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                return bm;
1015792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            } finally {
1016792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                try {
1017792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    if (in != null) {
1018792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                        in.close();
1019792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                    }
1020792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                } catch (IOException ex) {
1021792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                }
1022792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
1023792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
1024792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
1025792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        return null;
1026792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
1027792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
1028792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    // get album art for specified file
1029792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    private static final String sExternalMediaUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI.toString();
1030bd447b61c42589133257fb7992ccbed18a507a46Marco Nelissen    private static Bitmap getArtworkFromFile(Context context, long songid, long albumid) {
1031792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        Bitmap bm = null;
1032792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        byte [] art = null;
1033792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        String path = null;
1034792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
10357a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen        if (albumid < 0 && songid < 0) {
10367a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen            throw new IllegalArgumentException("Must specify an album or a song id");
1037792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
10387a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen
10397a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen        try {
10407a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen            if (albumid < 0) {
10417a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen                Uri uri = Uri.parse("content://media/external/audio/media/" + songid + "/albumart");
10427a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen                ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(uri, "r");
10437a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen                if (pfd != null) {
10447a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen                    FileDescriptor fd = pfd.getFileDescriptor();
10457a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen                    bm = BitmapFactory.decodeFileDescriptor(fd);
1046792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                }
10477a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen            } else {
10487a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen                Uri uri = ContentUris.withAppendedId(sArtworkUri, albumid);
10497a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen                ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(uri, "r");
10507a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen                if (pfd != null) {
10517a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen                    FileDescriptor fd = pfd.getFileDescriptor();
10527a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen                    bm = BitmapFactory.decodeFileDescriptor(fd);
1053792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                }
1054792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
10557a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen        } catch (FileNotFoundException ex) {
10567a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen            //
1057792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
10587a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen        if (bm != null) {
10597a16cc726fd83eff0095f3f82364d1438773218fMarco Nelissen            mCachedBit = bm;
1060792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
1061792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        return bm;
1062792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
1063792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
1064792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    private static Bitmap getDefaultArtwork(Context context) {
1065792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        BitmapFactory.Options opts = new BitmapFactory.Options();
1066792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
1067792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        return BitmapFactory.decodeStream(
1068792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                context.getResources().openRawResource(R.drawable.albumart_mp_unknown), null, opts);
1069792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
1070792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
1071792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    static int getIntPref(Context context, String name, int def) {
1072792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        SharedPreferences prefs =
1073792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            context.getSharedPreferences("com.android.music", Context.MODE_PRIVATE);
1074792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        return prefs.getInt(name, def);
1075792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
1076792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
1077792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    static void setIntPref(Context context, String name, int value) {
1078792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        SharedPreferences prefs =
1079792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            context.getSharedPreferences("com.android.music", Context.MODE_PRIVATE);
1080792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        Editor ed = prefs.edit();
1081792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        ed.putInt(name, value);
1082792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        ed.commit();
1083792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
1084792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
1085792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    static void setRingtone(Context context, long id) {
1086792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        ContentResolver resolver = context.getContentResolver();
1087792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        // Set the flag in the database to mark this as a ringtone
1088792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        Uri ringUri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id);
1089792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        try {
1090792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            ContentValues values = new ContentValues(2);
1091792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            values.put(MediaStore.Audio.Media.IS_RINGTONE, "1");
1092792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            values.put(MediaStore.Audio.Media.IS_ALARM, "1");
1093792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            resolver.update(ringUri, values, null, null);
1094792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        } catch (UnsupportedOperationException ex) {
1095792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            // most likely the card just got unmounted
1096792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            Log.e(TAG, "couldn't set ringtone flag for id " + id);
1097792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            return;
1098792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
1099792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
1100792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        String[] cols = new String[] {
1101792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                MediaStore.Audio.Media._ID,
1102792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                MediaStore.Audio.Media.DATA,
1103792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                MediaStore.Audio.Media.TITLE
1104792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        };
1105792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project
1106792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        String where = MediaStore.Audio.Media._ID + "=" + id;
1107792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        Cursor cursor = query(context, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
1108792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                cols, where , null, null);
1109792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        try {
1110792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            if (cursor != null && cursor.getCount() == 1) {
1111792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                // Set the system setting to make this the current ringtone
1112792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                cursor.moveToFirst();
1113792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                Settings.System.putString(resolver, Settings.System.RINGTONE, ringUri.toString());
1114792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                String message = context.getString(R.string.ringtone_set, cursor.getString(2));
1115792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
1116792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
1117792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        } finally {
1118792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            if (cursor != null) {
1119792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project                cursor.close();
1120792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project            }
1121792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project        }
1122792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project    }
1123ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen
1124ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen    static int sActiveTabIndex = -1;
1125ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen
112619cea9e16c54364a6a1df53cd617ba0a9c65b386Marco Nelissen    static boolean updateButtonBar(Activity a, int highlight) {
1127ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        final TabWidget ll = (TabWidget) a.findViewById(R.id.buttonbar);
1128ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        boolean withtabs = false;
1129ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        Intent intent = a.getIntent();
1130ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        if (intent != null) {
1131ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            withtabs = intent.getBooleanExtra("withtabs", false);
1132ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        }
1133ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen
1134ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        if (highlight == 0 || !withtabs) {
1135ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            ll.setVisibility(View.GONE);
113619cea9e16c54364a6a1df53cd617ba0a9c65b386Marco Nelissen            return withtabs;
1137ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        } else if (withtabs) {
1138ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            ll.setVisibility(View.VISIBLE);
1139ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        }
1140ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        for (int i = ll.getChildCount() - 1; i >= 0; i--) {
1141ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen
1142ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            View v = ll.getChildAt(i);
1143ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            boolean isActive = (v.getId() == highlight);
1144ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            if (isActive) {
1145ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                ll.setCurrentTab(i);
1146ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                sActiveTabIndex = i;
1147ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            }
1148333bf1945f859968dcb9783b694aa64b788fc771Jeff Hamilton            v.setTag(i);
1149ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            v.setOnFocusChangeListener(new View.OnFocusChangeListener() {
1150ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen
1151ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                public void onFocusChange(View v, boolean hasFocus) {
1152ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                    if (hasFocus) {
1153ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                        for (int i = 0; i < ll.getTabCount(); i++) {
1154ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                            if (ll.getChildTabViewAt(i) == v) {
1155ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                                ll.setCurrentTab(i);
1156ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                                processTabClick((Activity)ll.getContext(), v, ll.getChildAt(sActiveTabIndex).getId());
1157ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                                break;
1158ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                            }
1159ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                        }
1160ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                    }
1161ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                }});
1162ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen
1163ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            v.setOnClickListener(new View.OnClickListener() {
1164ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen
1165ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                public void onClick(View v) {
1166ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                    processTabClick((Activity)ll.getContext(), v, ll.getChildAt(sActiveTabIndex).getId());
1167ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                }});
1168ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        }
116919cea9e16c54364a6a1df53cd617ba0a9c65b386Marco Nelissen        return withtabs;
1170ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen    }
1171ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen
1172ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen    static void processTabClick(Activity a, View v, int current) {
1173ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        int id = v.getId();
1174ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        if (id == current) {
1175ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            return;
1176ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        }
1177333bf1945f859968dcb9783b694aa64b788fc771Jeff Hamilton
1178333bf1945f859968dcb9783b694aa64b788fc771Jeff Hamilton        final TabWidget ll = (TabWidget) a.findViewById(R.id.buttonbar);
1179333bf1945f859968dcb9783b694aa64b788fc771Jeff Hamilton        ll.setCurrentTab((Integer) v.getTag());
1180333bf1945f859968dcb9783b694aa64b788fc771Jeff Hamilton
1181ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        activateTab(a, id);
1182ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        if (id != R.id.nowplayingtab) {
1183ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            setIntPref(a, "activetab", id);
1184ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        }
1185ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen    }
1186ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen
1187ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen    static void activateTab(Activity a, int id) {
1188ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        Intent intent = new Intent(Intent.ACTION_PICK);
1189ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        switch (id) {
1190ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            case R.id.artisttab:
1191ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/artistalbum");
1192ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                break;
1193ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            case R.id.albumtab:
1194ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/album");
1195ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                break;
1196ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            case R.id.songtab:
1197ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track");
1198ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                break;
1199ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            case R.id.playlisttab:
1200ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                intent.setDataAndType(Uri.EMPTY, MediaStore.Audio.Playlists.CONTENT_TYPE);
1201ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                break;
1202ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            case R.id.nowplayingtab:
1203ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                intent = new Intent(a, MediaPlaybackActivity.class);
1204ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                a.startActivity(intent);
1205ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                // fall through and return
1206ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            default:
1207ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                return;
1208ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        }
1209ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        intent.putExtra("withtabs", true);
1210ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
1211ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        a.startActivity(intent);
1212ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        a.finish();
1213ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        a.overridePendingTransition(0, 0);
1214ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen    }
1215ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen
1216ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen    static void updateNowPlaying(Activity a) {
1217ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        View nowPlayingView = a.findViewById(R.id.nowplaying);
1218ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        if (nowPlayingView == null) {
1219ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            return;
1220ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        }
1221ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        try {
1222ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            boolean withtabs = false;
1223ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            Intent intent = a.getIntent();
1224ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            if (intent != null) {
1225ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                withtabs = intent.getBooleanExtra("withtabs", false);
1226ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            }
1227ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            if (true && MusicUtils.sService != null && MusicUtils.sService.getAudioId() != -1) {
1228ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                TextView title = (TextView) nowPlayingView.findViewById(R.id.title);
1229ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                TextView artist = (TextView) nowPlayingView.findViewById(R.id.artist);
1230ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                title.setText(MusicUtils.sService.getTrackName());
1231ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                String artistName = MusicUtils.sService.getArtistName();
1232f4d4b342061ade12eb7903f454df62814179906fMarco Nelissen                if (MediaStore.UNKNOWN_STRING.equals(artistName)) {
1233ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                    artistName = a.getString(R.string.unknown_artist_name);
1234ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                }
1235ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                artist.setText(artistName);
1236ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                //mNowPlayingView.setOnFocusChangeListener(mFocuser);
1237ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                //mNowPlayingView.setOnClickListener(this);
1238ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                nowPlayingView.setVisibility(View.VISIBLE);
1239ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                nowPlayingView.setOnClickListener(new View.OnClickListener() {
1240ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen
1241ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                    public void onClick(View v) {
1242ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                        Context c = v.getContext();
1243ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                        c.startActivity(new Intent(c, MediaPlaybackActivity.class));
1244ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                    }});
1245ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen                return;
1246ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen            }
1247ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        } catch (RemoteException ex) {
1248ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        }
1249ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen        nowPlayingView.setVisibility(View.GONE);
1250ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen    }
1251ec0c57a414c3563ebbf5767d92787a6a3f4a8820Marco Nelissen
12523193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen    static void setBackground(View v, Bitmap bm) {
12533193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen
12543193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        if (bm == null) {
12553193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen            v.setBackgroundResource(0);
12563193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen            return;
12573193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        }
12583193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen
12593193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        int vwidth = v.getWidth();
12603193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        int vheight = v.getHeight();
12613193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        int bwidth = bm.getWidth();
12623193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        int bheight = bm.getHeight();
12633193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        float scalex = (float) vwidth / bwidth;
12643193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        float scaley = (float) vheight / bheight;
12653193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        float scale = Math.max(scalex, scaley) * 1.3f;
12663193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen
12673193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        Bitmap.Config config = Bitmap.Config.ARGB_8888;
12683193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        Bitmap bg = Bitmap.createBitmap(vwidth, vheight, config);
12693193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        Canvas c = new Canvas(bg);
12703193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        Paint paint = new Paint();
12713193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        paint.setAntiAlias(true);
12723193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        paint.setFilterBitmap(true);
12733193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        ColorMatrix greymatrix = new ColorMatrix();
12743193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        greymatrix.setSaturation(0);
12753193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        ColorMatrix darkmatrix = new ColorMatrix();
12763193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        darkmatrix.setScale(.3f, .3f, .3f, 1.0f);
12773193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        greymatrix.postConcat(darkmatrix);
12783193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        ColorFilter filter = new ColorMatrixColorFilter(greymatrix);
12793193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        paint.setColorFilter(filter);
12803193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        Matrix matrix = new Matrix();
12813193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        matrix.setTranslate(-bwidth/2, -bheight/2); // move bitmap center to origin
12823193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        matrix.postRotate(10);
12833193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        matrix.postScale(scale, scale);
12843193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        matrix.postTranslate(vwidth/2, vheight/2);  // Move bitmap center to view center
12853193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        c.drawBitmap(bm, matrix, paint);
12863193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen        v.setBackgroundDrawable(new BitmapDrawable(bg));
12873193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen    }
12883193d7dda28d5c31b318b024db4df40b949071d5Marco Nelissen
128987bbf3c40cd044c3daa9fad28fb94e8570fcae05Marco Nelissen    static int getCardId(Context context) {
129087bbf3c40cd044c3daa9fad28fb94e8570fcae05Marco Nelissen        ContentResolver res = context.getContentResolver();
129187bbf3c40cd044c3daa9fad28fb94e8570fcae05Marco Nelissen        Cursor c = res.query(Uri.parse("content://media/external/fs_id"), null, null, null, null);
129287bbf3c40cd044c3daa9fad28fb94e8570fcae05Marco Nelissen        int id = -1;
129387bbf3c40cd044c3daa9fad28fb94e8570fcae05Marco Nelissen        if (c != null) {
129487bbf3c40cd044c3daa9fad28fb94e8570fcae05Marco Nelissen            c.moveToFirst();
129587bbf3c40cd044c3daa9fad28fb94e8570fcae05Marco Nelissen            id = c.getInt(0);
129687bbf3c40cd044c3daa9fad28fb94e8570fcae05Marco Nelissen            c.close();
129787bbf3c40cd044c3daa9fad28fb94e8570fcae05Marco Nelissen        }
129887bbf3c40cd044c3daa9fad28fb94e8570fcae05Marco Nelissen        return id;
129987bbf3c40cd044c3daa9fad28fb94e8570fcae05Marco Nelissen    }
1300792a2206a4f05f6bd13fce902d3663892d2947afThe Android Open Source Project}
1301