• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.music;
18 
19 import android.app.Activity;
20 import android.content.ContentResolver;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.SharedPreferences;
24 import android.content.SharedPreferences.Editor;
25 import android.content.res.Resources;
26 import android.database.Cursor;
27 import android.graphics.Bitmap;
28 import android.graphics.Canvas;
29 import android.graphics.ColorFilter;
30 import android.graphics.PixelFormat;
31 import android.graphics.drawable.BitmapDrawable;
32 import android.graphics.drawable.Drawable;
33 import android.media.MediaMetadata;
34 import android.media.session.MediaController;
35 import android.net.Uri;
36 import android.provider.MediaStore;
37 import android.view.View;
38 import android.widget.TabWidget;
39 import android.widget.TextView;
40 import com.android.music.utils.LogHelper;
41 import com.android.music.utils.MusicProvider;
42 
43 import java.util.Formatter;
44 import java.util.Iterator;
45 import java.util.Locale;
46 
47 /*
48 Static methods useful for activities
49  */
50 public class MusicUtils {
51     private static final String TAG = LogHelper.makeLogTag(MusicUtils.class);
52 
53     public static final String TAG_MEDIA_ID = "__MEDIA_ID";
54     public static final String TAG_PARENT_ITEM = "__PARENT_ITEM";
55     public static final String TAG_WITH_TABS = "__WITH_TABS";
56 
57     // A really simple BitmapDrawable-like class, that doesn't do
58     // scaling, dithering or filtering.
59     private static class FastBitmapDrawable extends Drawable {
60         private Bitmap mBitmap;
FastBitmapDrawable(Bitmap b)61         public FastBitmapDrawable(Bitmap b) {
62             mBitmap = b;
63         }
64         @Override
draw(Canvas canvas)65         public void draw(Canvas canvas) {
66             canvas.drawBitmap(mBitmap, 0, 0, null);
67         }
68         @Override
getOpacity()69         public int getOpacity() {
70             return PixelFormat.OPAQUE;
71         }
72         @Override
setAlpha(int alpha)73         public void setAlpha(int alpha) {}
74         @Override
setColorFilter(ColorFilter cf)75         public void setColorFilter(ColorFilter cf) {}
76     }
77 
resizeBitmap(Bitmap bitmap, Bitmap ref)78     public static Bitmap resizeBitmap(Bitmap bitmap, Bitmap ref) {
79         int w = ref.getWidth();
80         int h = ref.getHeight();
81         return Bitmap.createScaledBitmap(bitmap, w, h, false);
82     }
83 
getDrawableBitmap(Bitmap bitmap, BitmapDrawable defaultArtwork)84     public static Drawable getDrawableBitmap(Bitmap bitmap, BitmapDrawable defaultArtwork) {
85         final Bitmap icon = defaultArtwork.getBitmap();
86         int w = icon.getWidth();
87         int h = icon.getHeight();
88         bitmap = Bitmap.createScaledBitmap(bitmap, w, h, false);
89         return new FastBitmapDrawable(bitmap);
90     }
91 
makeAlbumsLabel( Context context, int numalbums, int numsongs, boolean isUnknown)92     public static String makeAlbumsLabel(
93             Context context, int numalbums, int numsongs, boolean isUnknown) {
94         // There are two formats for the albums/songs information:
95         // "N Song(s)"  - used for unknown artist/album
96         // "N Album(s)" - used for known albums
97 
98         StringBuilder songs_albums = new StringBuilder();
99 
100         Resources r = context.getResources();
101         if (isUnknown) {
102             if (numsongs == 1) {
103                 songs_albums.append(context.getString(R.string.onesong));
104             } else {
105                 String f = r.getQuantityText(R.plurals.Nsongs, numsongs).toString();
106                 sFormatBuilder.setLength(0);
107                 sFormatter.format(f, Integer.valueOf(numsongs));
108                 songs_albums.append(sFormatBuilder);
109             }
110         } else {
111             String f = r.getQuantityText(R.plurals.Nalbums, numalbums).toString();
112             sFormatBuilder.setLength(0);
113             sFormatter.format(f, Integer.valueOf(numalbums));
114             songs_albums.append(sFormatBuilder);
115             songs_albums.append(context.getString(R.string.albumsongseparator));
116         }
117         return songs_albums.toString();
118     }
119 
120     /**
121      * This is now only used for the query screen
122      */
makeAlbumsSongsLabel( Context context, int numalbums, int numsongs, boolean isUnknown)123     public static String makeAlbumsSongsLabel(
124             Context context, int numalbums, int numsongs, boolean isUnknown) {
125         // There are several formats for the albums/songs information:
126         // "1 Song"   - used if there is only 1 song
127         // "N Songs" - used for the "unknown artist" item
128         // "1 Album"/"N Songs"
129         // "N Album"/"M Songs"
130         // Depending on locale, these may need to be further subdivided
131 
132         StringBuilder songs_albums = new StringBuilder();
133 
134         if (numsongs == 1) {
135             songs_albums.append(context.getString(R.string.onesong));
136         } else {
137             Resources r = context.getResources();
138             if (!isUnknown) {
139                 String f = r.getQuantityText(R.plurals.Nalbums, numalbums).toString();
140                 sFormatBuilder.setLength(0);
141                 sFormatter.format(f, Integer.valueOf(numalbums));
142                 songs_albums.append(sFormatBuilder);
143                 songs_albums.append(context.getString(R.string.albumsongseparator));
144             }
145             String f = r.getQuantityText(R.plurals.Nsongs, numsongs).toString();
146             sFormatBuilder.setLength(0);
147             sFormatter.format(f, Integer.valueOf(numsongs));
148             songs_albums.append(sFormatBuilder);
149         }
150         return songs_albums.toString();
151     }
152 
153     /*  Try to use String.format() as little as possible, because it creates a
154      *  new Formatter every time you call it, which is very inefficient.
155      *  Reusing an existing Formatter more than tripled the speed of
156      *  makeTimeString().
157      *  This Formatter/StringBuilder are also used by makeAlbumSongsLabel()
158      */
159     private static StringBuilder sFormatBuilder = new StringBuilder();
160     private static Formatter sFormatter = new Formatter(sFormatBuilder, Locale.getDefault());
161     private static final Object[] sTimeArgs = new Object[5];
162 
makeTimeString(Context context, long secs)163     public static String makeTimeString(Context context, long secs) {
164         String durationformat = context.getString(
165                 secs < 3600 ? R.string.durationformatshort : R.string.durationformatlong);
166 
167         /* Provide multiple arguments so the format can be changed easily
168          * by modifying the xml.
169          */
170         sFormatBuilder.setLength(0);
171 
172         final Object[] timeArgs = sTimeArgs;
173         timeArgs[0] = secs / 3600;
174         timeArgs[1] = secs / 60;
175         timeArgs[2] = (secs / 60) % 60;
176         timeArgs[3] = secs;
177         timeArgs[4] = secs % 60;
178 
179         return sFormatter.format(durationformat, timeArgs).toString();
180     }
181 
getIntPref(Context context, String name, int def)182     static int getIntPref(Context context, String name, int def) {
183         SharedPreferences prefs =
184                 context.getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE);
185         return prefs.getInt(name, def);
186     }
187 
setIntPref(Context context, String name, int value)188     static void setIntPref(Context context, String name, int value) {
189         SharedPreferences prefs =
190                 context.getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE);
191         Editor ed = prefs.edit();
192         ed.putInt(name, value);
193         SharedPreferencesCompat.apply(ed);
194     }
195 
196     static int sActiveTabIndex = -1;
197 
updateButtonBar(Activity a, int highlight)198     static boolean updateButtonBar(Activity a, int highlight) {
199         final TabWidget ll = (TabWidget) a.findViewById(R.id.buttonbar);
200         boolean withtabs = false;
201         Intent intent = a.getIntent();
202         if (intent != null) {
203             withtabs = intent.getBooleanExtra(MusicUtils.TAG_WITH_TABS, false);
204         }
205 
206         if (highlight == 0 || !withtabs) {
207             ll.setVisibility(View.GONE);
208             return withtabs;
209         } else if (withtabs) {
210             ll.setVisibility(View.VISIBLE);
211         }
212         for (int i = ll.getChildCount() - 1; i >= 0; i--) {
213             View v = ll.getChildAt(i);
214             boolean isActive = (v.getId() == highlight);
215             if (isActive) {
216                 ll.setCurrentTab(i);
217                 sActiveTabIndex = i;
218             }
219             v.setTag(i);
220             v.setOnFocusChangeListener(new View.OnFocusChangeListener() {
221 
222                 public void onFocusChange(View v, boolean hasFocus) {
223                     if (hasFocus) {
224                         for (int i = 0; i < ll.getTabCount(); i++) {
225                             if (ll.getChildTabViewAt(i) == v) {
226                                 ll.setCurrentTab(i);
227                                 processTabClick((Activity) ll.getContext(), v,
228                                         ll.getChildAt(sActiveTabIndex).getId());
229                                 break;
230                             }
231                         }
232                     }
233                 }
234             });
235 
236             v.setOnClickListener(new View.OnClickListener() {
237 
238                 public void onClick(View v) {
239                     processTabClick(
240                             (Activity) ll.getContext(), v, ll.getChildAt(sActiveTabIndex).getId());
241                 }
242             });
243         }
244         return withtabs;
245     }
246 
processTabClick(Activity a, View v, int current)247     static void processTabClick(Activity a, View v, int current) {
248         int id = v.getId();
249         if (id == current) {
250             return;
251         }
252 
253         final TabWidget ll = (TabWidget) a.findViewById(R.id.buttonbar);
254 
255         activateTab(a, id);
256         if (id != R.id.nowplayingtab) {
257             ll.setCurrentTab((Integer) v.getTag());
258             setIntPref(a, "activetab", id);
259         }
260     }
261 
activateTab(Activity a, int id)262     static void activateTab(Activity a, int id) {
263         Intent intent = new Intent(Intent.ACTION_PICK);
264         switch (id) {
265             case R.id.artisttab:
266                 intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/artistalbum");
267                 break;
268             case R.id.albumtab:
269                 intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/album");
270                 break;
271             case R.id.songtab:
272                 intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track");
273                 break;
274             case R.id.playlisttab:
275                 intent.setDataAndType(Uri.EMPTY, MediaStore.Audio.Playlists.CONTENT_TYPE);
276                 break;
277             case R.id.nowplayingtab:
278                 intent = new Intent(a, MediaPlaybackActivity.class);
279                 a.startActivity(intent);
280             // fall through and return
281             default:
282                 return;
283         }
284         intent.putExtra(MusicUtils.TAG_WITH_TABS, true);
285         intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
286         a.startActivity(intent);
287         a.finish();
288         a.overridePendingTransition(0, 0);
289     }
290 
updateNowPlaying(Activity a)291     static void updateNowPlaying(Activity a) {
292         View nowPlayingView = a.findViewById(R.id.nowplaying);
293         if (nowPlayingView == null) {
294             return;
295         }
296         MediaController controller = a.getMediaController();
297         if (controller != null) {
298             MediaMetadata metadata = controller.getMetadata();
299             if (metadata != null) {
300                 TextView title = (TextView) nowPlayingView.findViewById(R.id.title);
301                 TextView artist = (TextView) nowPlayingView.findViewById(R.id.artist);
302                 title.setText(metadata.getString(MediaMetadata.METADATA_KEY_TITLE));
303                 String artistName = metadata.getString(MediaMetadata.METADATA_KEY_ARTIST);
304                 if (MusicProvider.UNKOWN.equals(artistName)) {
305                     artistName = a.getString(R.string.unknown_artist_name);
306                 }
307                 artist.setText(artistName);
308                 nowPlayingView.setVisibility(View.VISIBLE);
309                 nowPlayingView.setOnClickListener(new View.OnClickListener() {
310                     public void onClick(View v) {
311                         Context c = v.getContext();
312                         c.startActivity(new Intent(c, MediaPlaybackActivity.class));
313                     }
314                 });
315                 return;
316             }
317         }
318         nowPlayingView.setVisibility(View.GONE);
319     }
320 }
321