blob: 66b3472a8b0d761d8bb0196bcc25240b9d6e2988 [file] [log] [blame]
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.music;
import android.app.ListActivity;
import android.app.SearchManager;
import android.content.AsyncQueryHandler;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import com.android.internal.database.ArrayListCursor;
import com.android.music.TrackBrowserActivity.MyQueryHandler;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.media.AudioManager;
import android.media.MediaFile;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.ViewGroup.OnHierarchyChangeListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
import java.util.ArrayList;
public class QueryBrowserActivity extends ListActivity implements MusicUtils.Defs
{
private final static int PLAY_NOW = 0;
private final static int ADD_TO_QUEUE = 1;
private final static int PLAY_NEXT = 2;
private final static int PLAY_ARTIST = 3;
private final static int EXPLORE_ARTIST = 4;
private final static int PLAY_ALBUM = 5;
private final static int EXPLORE_ALBUM = 6;
private final static int REQUERY = 3;
private MyQueryHandler mQueryHandler;
private String mFilterString = "";
public QueryBrowserActivity()
{
}
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle icicle)
{
super.onCreate(icicle);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
MusicUtils.bindToService(this);
if (icicle == null) {
Intent intent = getIntent();
mFilterString = intent.getStringExtra(SearchManager.QUERY);
}
if (mFilterString == null) {
mFilterString = "";
}
setContentView(R.layout.query_activity);
mTrackList = (ListView) findViewById(android.R.id.list);
mQueryHandler = new MyQueryHandler(getContentResolver());
mQueryCursor = (Cursor) getLastNonConfigurationInstance();
if (mQueryCursor == null) {
//Log.i("@@@", "starting query");
setTitle(R.string.working_songs);
getQueryCursor(mQueryHandler);
} else {
init(mQueryCursor);
}
}
@Override
public Object onRetainNonConfigurationInstance() {
Cursor c = mQueryCursor;
mQueryCursor = null;
return c;
}
class MyQueryHandler extends AsyncQueryHandler {
MyQueryHandler(ContentResolver res) {
super(res);
}
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
Log.i("@@@", "query complete");
init(cursor);
}
}
@Override
public void onDestroy() {
MusicUtils.unbindFromService(this);
super.onDestroy();
if (mQueryCursor != null) {
mQueryCursor.close();
}
}
public void init(Cursor c) {
mQueryCursor = c;
ListView lv = getListView();
lv.setTextFilterEnabled(true);
if (mQueryCursor == null) {
MusicUtils.displayDatabaseError(this);
setListAdapter(null);
lv.setFocusable(false);
return;
}
// Map Cursor columns to views defined in media_list_item.xml
QueryListAdapter adapter = new QueryListAdapter(
this,
R.layout.track_list_item,
mQueryCursor,
new String[] {},
new int[] {});
setListAdapter(adapter);
if (mFilterString.length() != 0) {
// Hack. Can be removed once ListView supports starting filtering with a given string
lv.setOnHierarchyChangeListener(mHierarchyListener);
}
}
OnHierarchyChangeListener mHierarchyListener = new OnHierarchyChangeListener() {
public void onChildViewAdded(View parent, View child) {
((ListView)parent).setOnHierarchyChangeListener(null);
// need to do this here to be sure all the views have been initialized
startFilteringWithString(mFilterString);
}
public void onChildViewRemoved(View parent, View child) {
}
};
private KeyEvent eventForChar(char c) {
int code = -1;
if (c >= 'a' && c <= 'z') {
code = KeyEvent.KEYCODE_A + (c - 'a');
} else if (c >= 'A' && c <= 'Z') {
code = KeyEvent.KEYCODE_A + (c - 'A');
} else if (c >= '0' && c <= '9') {
code = KeyEvent.KEYCODE_0 + (c - '0');
}
if (code != -1) {
return new KeyEvent(KeyEvent.ACTION_DOWN, code);
}
return null;
}
private void startFilteringWithString(String filterstring) {
ListView lv = getListView();
for (int i = 0; i < filterstring.length(); i++) {
KeyEvent event = eventForChar(filterstring.charAt(i));
if (event != null) {
lv.onKeyDown(event.getKeyCode(), event);
}
}
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id)
{
// Dialog doesn't allow us to wait for a result, so we need to store
// the info we need for when the dialog posts its result
mQueryCursor.moveToPosition(position);
if (mQueryCursor.isBeforeFirst() || mQueryCursor.isAfterLast()) {
return;
}
String selectedType = mQueryCursor.getString(mQueryCursor.getColumnIndexOrThrow(
MediaStore.Audio.Media.MIME_TYPE));
if ("artist".equals(selectedType)) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/album");
intent.putExtra("artist", Long.valueOf(id).toString());
startActivity(intent);
} else if ("album".equals(selectedType)) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track");
intent.putExtra("album", Long.valueOf(id).toString());
startActivity(intent);
} else if (position >= 0 && id >= 0){
int [] list = new int[] { (int) id };
MusicUtils.playAll(this, list, 0);
} else {
Log.e("QueryBrowser", "invalid position/id: " + position + "/" + id);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case USE_AS_RINGTONE: {
// Set the system setting to make this the current ringtone
MusicUtils.setRingtone(this, mTrackList.getSelectedItemId());
return true;
}
}
return super.onOptionsItemSelected(item);
}
private Cursor getQueryCursor(AsyncQueryHandler async) {
String[] ccols = new String[] {
"_id", // this will be the artist, album or track ID
MediaStore.Audio.Media.MIME_TYPE, // mimetype of audio file, or "artist" or "album"
SearchManager.SUGGEST_COLUMN_TEXT_1,
"data1",
"data2"
};
Uri search = Uri.parse("content://media/external/audio/" +
SearchManager.SUGGEST_URI_PATH_QUERY + "/" + Uri.encode(mFilterString));
Cursor ret = null;
if (async != null) {
async.startQuery(0, null, search, ccols, null, null, null);
} else {
ret = MusicUtils.query(this, search, ccols, null, null, null);
}
return ret;
}
class QueryListAdapter extends SimpleCursorAdapter {
QueryListAdapter(Context context, int layout, Cursor cursor, String[] from, int[] to) {
super(context, layout, cursor, from, to);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
TextView tv1 = (TextView) view.findViewById(R.id.line1);
TextView tv2 = (TextView) view.findViewById(R.id.line2);
ImageView iv = (ImageView) view.findViewById(R.id.icon);
ViewGroup.LayoutParams p = iv.getLayoutParams();
if (p == null) {
// seen this happen, not sure why
DatabaseUtils.dumpCursor(cursor);
return;
}
p.width = ViewGroup.LayoutParams.WRAP_CONTENT;
p.height = ViewGroup.LayoutParams.WRAP_CONTENT;
String mimetype = cursor.getString(cursor.getColumnIndexOrThrow(
MediaStore.Audio.Media.MIME_TYPE));
if (mimetype == null) {
mimetype = "audio/";
}
if (mimetype.equals("artist")) {
iv.setImageResource(R.drawable.ic_search_category_music_artist);
String name = cursor.getString(cursor.getColumnIndexOrThrow(
SearchManager.SUGGEST_COLUMN_TEXT_1));
String displayname = name;
if (name.equals(MediaFile.UNKNOWN_STRING)) {
displayname = context.getString(R.string.unknown_artist_name);
}
tv1.setText(displayname);
int numalbums = cursor.getInt(cursor.getColumnIndexOrThrow("data1"));
int numsongs = cursor.getInt(cursor.getColumnIndexOrThrow("data2"));
String songs_albums = MusicUtils.makeAlbumsSongsLabel(context,
numalbums, numsongs, name.equals(MediaFile.UNKNOWN_STRING));
tv2.setText(songs_albums);
} else if (mimetype.equals("album")) {
iv.setImageResource(R.drawable.ic_search_category_music_album);
String name = cursor.getString(cursor.getColumnIndexOrThrow(
SearchManager.SUGGEST_COLUMN_TEXT_1));
String displayname = name;
if (name.equals(MediaFile.UNKNOWN_STRING)) {
displayname = context.getString(R.string.unknown_album_name);
}
tv1.setText(displayname);
name = cursor.getString(cursor.getColumnIndexOrThrow("data1"));
displayname = name;
if (name.equals(MediaFile.UNKNOWN_STRING)) {
displayname = context.getString(R.string.unknown_artist_name);
}
tv2.setText(displayname);
} else if(mimetype.startsWith("audio/") ||
mimetype.equals("application/ogg") ||
mimetype.equals("application/x-ogg")) {
iv.setImageResource(R.drawable.ic_search_category_music_song);
String name = cursor.getString(cursor.getColumnIndexOrThrow(
SearchManager.SUGGEST_COLUMN_TEXT_1));
tv1.setText(name);
String displayname = cursor.getString(cursor.getColumnIndexOrThrow("data1"));
if (name.equals(MediaFile.UNKNOWN_STRING)) {
displayname = context.getString(R.string.unknown_artist_name);
}
name = cursor.getString(cursor.getColumnIndexOrThrow("data2"));
if (name.equals(MediaFile.UNKNOWN_STRING)) {
name = context.getString(R.string.unknown_artist_name);
}
tv2.setText(displayname + " - " + name);
}
}
@Override
public void changeCursor(Cursor cursor) {
super.changeCursor(cursor);
mQueryCursor = cursor;
}
@Override
public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
mFilterString = constraint.toString();
return getQueryCursor(null);
}
}
private ListView mTrackList;
private Cursor mQueryCursor;
}