Hook up clicks on albums and artists
This commit is contained in:
parent
565c4a42cc
commit
da087bd3ac
@ -40,4 +40,4 @@
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<supports-screens android:smallScreens="true" />
|
||||
</manifest>
|
||||
</manifest>
|
||||
|
5
res/values/ids.xml
Normal file
5
res/values/ids.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<item type="id" name="list" />
|
||||
<item type="id" name="song" />
|
||||
</resources>
|
@ -235,6 +235,8 @@ public abstract class AbstractAdapter extends BaseAdapter implements Filterable
|
||||
return null;
|
||||
return mAllObjects[i];
|
||||
}
|
||||
if (i >= mObjects.size())
|
||||
return null;
|
||||
return mObjects.get(i);
|
||||
}
|
||||
|
||||
@ -242,11 +244,4 @@ public abstract class AbstractAdapter extends BaseAdapter implements Filterable
|
||||
{
|
||||
return get(i);
|
||||
}
|
||||
|
||||
public long getItemId(int i)
|
||||
{
|
||||
if (mObjects != null && mObjects.isEmpty())
|
||||
return 0;
|
||||
return get(i).id;
|
||||
}
|
||||
}
|
@ -16,4 +16,12 @@ public class AlbumAdapter extends AbstractAdapter {
|
||||
upper.setText(song.album);
|
||||
lower.setText(song.artist);
|
||||
}
|
||||
|
||||
public long getItemId(int i)
|
||||
{
|
||||
Song song = get(i);
|
||||
if (song == null)
|
||||
return 0;
|
||||
return song.albumId;
|
||||
}
|
||||
}
|
@ -33,4 +33,12 @@ public class ArtistAdapter extends AbstractAdapter {
|
||||
Song song = get(position);
|
||||
upper.setText(song.artist);
|
||||
}
|
||||
|
||||
public long getItemId(int i)
|
||||
{
|
||||
Song song = get(i);
|
||||
if (song == null)
|
||||
return 0;
|
||||
return song.artistId;
|
||||
}
|
||||
}
|
@ -25,6 +25,7 @@ import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.kreed.vanilla.IPlaybackService;
|
||||
@ -48,6 +49,7 @@ import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.PowerManager;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.provider.MediaStore;
|
||||
import android.telephony.PhoneStateListener;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.Log;
|
||||
@ -65,8 +67,12 @@ public class PlaybackService extends Service implements Runnable, MediaPlayer.On
|
||||
public static final String EVENT_STATE_CHANGED = "org.kreed.vanilla.event.STATE_CHANGED";
|
||||
public static final String EVENT_SONG_CHANGED = "org.kreed.vanilla.event.SONG_CHANGED";
|
||||
|
||||
public static int ACTION_PLAY = 0;
|
||||
public static int ACTION_ENQUEUE = 1;
|
||||
public static final int ACTION_PLAY = 0;
|
||||
public static final int ACTION_ENQUEUE = 1;
|
||||
|
||||
public static final int TYPE_SONG = 0;
|
||||
public static final int TYPE_ALBUM = 1;
|
||||
public static final int TYPE_ARTIST = 2;
|
||||
|
||||
public static final int STATE_NORMAL = 0;
|
||||
public static final int STATE_NO_MEDIA = 1;
|
||||
@ -339,6 +345,7 @@ public class PlaybackService extends Service implements Runnable, MediaPlayer.On
|
||||
in.close();
|
||||
|
||||
Song song = new Song(ids[mCurrentSong]);
|
||||
song.populate();
|
||||
if (song.path == null) {
|
||||
stateLoaded = false;
|
||||
} else {
|
||||
@ -488,7 +495,7 @@ public class PlaybackService extends Service implements Runnable, MediaPlayer.On
|
||||
|
||||
private void retrieveSongs()
|
||||
{
|
||||
mSongs = Song.getAllSongIds();
|
||||
mSongs = Song.getAllSongIds(null);
|
||||
if (mSongs == null)
|
||||
updateState(STATE_NO_MEDIA);
|
||||
else if (mState == STATE_NO_MEDIA)
|
||||
@ -633,9 +640,9 @@ public class PlaybackService extends Service implements Runnable, MediaPlayer.On
|
||||
return true;
|
||||
}
|
||||
|
||||
private Song randomSong()
|
||||
private int randomSong()
|
||||
{
|
||||
return new Song(mSongs[mRandom.nextInt(mSongs.length)]);
|
||||
return mSongs[mRandom.nextInt(mSongs.length)];
|
||||
}
|
||||
|
||||
private Song getSong(int delta)
|
||||
@ -643,9 +650,10 @@ public class PlaybackService extends Service implements Runnable, MediaPlayer.On
|
||||
if (mSongTimeline == null)
|
||||
return null;
|
||||
|
||||
Song song;
|
||||
|
||||
synchronized (mSongTimeline) {
|
||||
int pos = mCurrentSong + delta;
|
||||
|
||||
if (pos < 0)
|
||||
return null;
|
||||
|
||||
@ -656,18 +664,18 @@ public class PlaybackService extends Service implements Runnable, MediaPlayer.On
|
||||
if (pos == size) {
|
||||
if (mSongs == null)
|
||||
return null;
|
||||
mSongTimeline.add(randomSong());
|
||||
mSongTimeline.add(new Song(randomSong()));
|
||||
}
|
||||
|
||||
Song song = mSongTimeline.get(pos);
|
||||
|
||||
if (song.path == null) {
|
||||
song = randomSong();
|
||||
mSongTimeline.set(pos, song);
|
||||
}
|
||||
|
||||
return song;
|
||||
song = mSongTimeline.get(pos);
|
||||
}
|
||||
|
||||
if (!song.populate()) {
|
||||
song.id = randomSong();
|
||||
song.populate();
|
||||
}
|
||||
|
||||
return song;
|
||||
}
|
||||
|
||||
private void updateWidgets(Song song)
|
||||
@ -714,42 +722,93 @@ public class PlaybackService extends Service implements Runnable, MediaPlayer.On
|
||||
if (id == -1) {
|
||||
mQueuePos = 0;
|
||||
} else {
|
||||
int action = intent.getIntExtra("action", ACTION_PLAY);
|
||||
int actionRes;
|
||||
int type = intent.getIntExtra("type", TYPE_SONG);
|
||||
boolean enqueue = intent.getIntExtra("action", ACTION_PLAY) == ACTION_ENQUEUE;
|
||||
|
||||
Song song = new Song(id);
|
||||
int[] songs;
|
||||
Song first;
|
||||
|
||||
if (type == TYPE_SONG)
|
||||
songs = new int[] { id };
|
||||
else if (type == TYPE_ALBUM)
|
||||
songs = Song.getAllSongIds(MediaStore.Audio.Media.ALBUM_ID + "=" + id);
|
||||
else if (type == TYPE_ARTIST)
|
||||
songs = Song.getAllSongIds(MediaStore.Audio.Media.ARTIST_ID + "=" + id);
|
||||
else
|
||||
break;
|
||||
|
||||
if (songs.length == 0)
|
||||
break;
|
||||
|
||||
for (int i = songs.length; --i != 0; ) {
|
||||
int j = mRandom.nextInt(i + 1);
|
||||
int tmp = songs[j];
|
||||
songs[j] = songs[i];
|
||||
songs[i] = tmp;
|
||||
}
|
||||
|
||||
synchronized (mSongTimeline) {
|
||||
int i;
|
||||
if (enqueue) {
|
||||
int i = mCurrentSong + mQueuePos + 1;
|
||||
|
||||
if (action == ACTION_ENQUEUE) {
|
||||
i = mCurrentSong + 1 + mQueuePos++;
|
||||
actionRes = R.string.enqueued;
|
||||
for (int j = 0; j != songs.length; ++i, ++j) {
|
||||
Song song = new Song(songs[j]);
|
||||
if (i < mSongTimeline.size())
|
||||
mSongTimeline.set(i, song);
|
||||
else
|
||||
mSongTimeline.add(song);
|
||||
}
|
||||
|
||||
first = mSongTimeline.get(mCurrentSong + mQueuePos + 1);
|
||||
|
||||
mQueuePos += songs.length;
|
||||
} else {
|
||||
i = mCurrentSong;
|
||||
actionRes = R.string.playing;
|
||||
List<Song> view = mSongTimeline.subList(mCurrentSong + 1, mSongTimeline.size());
|
||||
List<Song> queue = mQueuePos == 0 ? null : new ArrayList<Song>(view);
|
||||
view.clear();
|
||||
|
||||
for (int i = 0; i != songs.length; ++i)
|
||||
mSongTimeline.add(new Song(songs[i]));
|
||||
|
||||
if (queue != null)
|
||||
mSongTimeline.addAll(queue);
|
||||
|
||||
mQueuePos += songs.length - 1;
|
||||
|
||||
first = mSongTimeline.get(mCurrentSong + 1);
|
||||
}
|
||||
|
||||
if (i < mSongTimeline.size())
|
||||
mSongTimeline.set(i, song);
|
||||
else
|
||||
mSongTimeline.add(song);
|
||||
}
|
||||
|
||||
String text = getResources().getString(actionRes, song.title);
|
||||
Toast.makeText(ContextApplication.getContext(), text, Toast.LENGTH_SHORT).show();
|
||||
|
||||
if (action == ACTION_PLAY) {
|
||||
setCurrentSong(0);
|
||||
if (mState != STATE_PLAYING)
|
||||
play();
|
||||
first.populate();
|
||||
String title;
|
||||
switch (type) {
|
||||
case TYPE_ARTIST:
|
||||
title = first.artist;
|
||||
break;
|
||||
case TYPE_SONG:
|
||||
title = first.title;
|
||||
break;
|
||||
case TYPE_ALBUM:
|
||||
title = first.album;
|
||||
break;
|
||||
default:
|
||||
title = null;
|
||||
}
|
||||
|
||||
String text = getResources().getString(enqueue ? R.string.enqueued : R.string.playing, title);
|
||||
Toast.makeText(PlaybackService.this, text, Toast.LENGTH_SHORT).show();
|
||||
|
||||
if (!enqueue)
|
||||
mHandler.sendEmptyMessage(TRACK_CHANGED);
|
||||
|
||||
mHandler.removeMessages(SAVE_STATE);
|
||||
mHandler.sendEmptyMessageDelayed(SAVE_STATE, 5000);
|
||||
}
|
||||
break;
|
||||
case TRACK_CHANGED:
|
||||
setCurrentSong(+1);
|
||||
if (mState != STATE_PLAYING)
|
||||
play();
|
||||
break;
|
||||
case RELEASE_WAKE_LOCK:
|
||||
if (mWakeLock != null && mWakeLock.isHeld())
|
||||
@ -802,4 +861,4 @@ public class PlaybackService extends Service implements Runnable, MediaPlayer.On
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -54,6 +54,14 @@ public class Song implements Parcelable {
|
||||
public Song(int id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public boolean populate()
|
||||
{
|
||||
if (path != null)
|
||||
return true;
|
||||
if (id == -1)
|
||||
return false;
|
||||
|
||||
Uri media = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
||||
String[] projection = {
|
||||
@ -68,31 +76,40 @@ public class Song implements Parcelable {
|
||||
ContentResolver resolver = ContextApplication.getContext().getContentResolver();
|
||||
Cursor cursor = resolver.query(media, projection, selection, null, null);
|
||||
|
||||
if (cursor != null && cursor.moveToNext()) {
|
||||
path = cursor.getString(0);
|
||||
title = cursor.getString(1);
|
||||
album = cursor.getString(2);
|
||||
artist = cursor.getString(3);
|
||||
albumId = cursor.getInt(4);
|
||||
cursor.close();
|
||||
|
||||
media = MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI;
|
||||
String[] albumProjection = { MediaStore.Audio.Albums.ALBUM_ART };
|
||||
String albumSelection = MediaStore.Audio.Albums._ID + "==" + albumId;
|
||||
|
||||
cursor = resolver.query(media, albumProjection, albumSelection, null, null);
|
||||
if (cursor != null && cursor.moveToNext()) {
|
||||
coverPath = cursor.getString(0);
|
||||
cursor.close();
|
||||
}
|
||||
if (cursor == null || !cursor.moveToNext()) {
|
||||
id = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
path = cursor.getString(0);
|
||||
title = cursor.getString(1);
|
||||
album = cursor.getString(2);
|
||||
artist = cursor.getString(3);
|
||||
albumId = cursor.getInt(4);
|
||||
cursor.close();
|
||||
|
||||
media = MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI;
|
||||
String[] albumProjection = { MediaStore.Audio.Albums.ALBUM_ART };
|
||||
String albumSelection = MediaStore.Audio.Albums._ID + "==" + albumId;
|
||||
|
||||
cursor = resolver.query(media, albumProjection, albumSelection, null, null);
|
||||
if (cursor != null && cursor.moveToNext()) {
|
||||
coverPath = cursor.getString(0);
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static int[] getAllSongIds()
|
||||
public static int[] getAllSongIds(String selection)
|
||||
{
|
||||
Uri media = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
||||
String[] projection = { MediaStore.Audio.Media._ID };
|
||||
String selection = MediaStore.Audio.Media.IS_MUSIC + "!=0";
|
||||
String isMusic = MediaStore.Audio.Media.IS_MUSIC + "!=0";
|
||||
if (selection == null)
|
||||
selection = isMusic;
|
||||
else
|
||||
selection += " AND " + isMusic;
|
||||
|
||||
ContentResolver resolver = ContextApplication.getContext().getContentResolver();
|
||||
Cursor cursor = resolver.query(media, projection, selection, null, null);
|
||||
|
@ -42,4 +42,12 @@ public class SongAdapter extends AbstractAdapter {
|
||||
upper.setText(song.title);
|
||||
lower.setText(song.artist);
|
||||
}
|
||||
|
||||
public long getItemId(int i)
|
||||
{
|
||||
Song song = get(i);
|
||||
if (song == null)
|
||||
return 0;
|
||||
return song.id;
|
||||
}
|
||||
}
|
@ -47,12 +47,25 @@ public class SongSelector extends TabActivity implements AdapterView.OnItemClick
|
||||
private TextView mTextFilter;
|
||||
private AbstractAdapter[] mAdapters = new AbstractAdapter[3];
|
||||
|
||||
private void initializeListView(int id, BaseAdapter adapter)
|
||||
private ListView mArtistView;
|
||||
private ListView mAlbumView;
|
||||
|
||||
private int listToMediaType(Object list)
|
||||
{
|
||||
if (list == mArtistView)
|
||||
return PlaybackService.TYPE_ARTIST;
|
||||
if (list == mAlbumView)
|
||||
return PlaybackService.TYPE_ALBUM;
|
||||
return PlaybackService.TYPE_SONG;
|
||||
}
|
||||
|
||||
private ListView initializeListView(int id, BaseAdapter adapter)
|
||||
{
|
||||
ListView view = (ListView)findViewById(id);
|
||||
view.setOnItemClickListener(this);
|
||||
view.setOnCreateContextMenuListener(this);
|
||||
view.setAdapter(adapter);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -75,11 +88,11 @@ public class SongSelector extends TabActivity implements AdapterView.OnItemClick
|
||||
mAdapters[0] = new ArtistAdapter(this, songs);
|
||||
mAdapters[0].setExpanderListener(this);
|
||||
|
||||
initializeListView(R.id.artist_list, mAdapters[0]);
|
||||
mArtistView = initializeListView(R.id.artist_list, mAdapters[0]);
|
||||
|
||||
mTextFilter = (TextView)findViewById(R.id.filter_text);
|
||||
mTextFilter.addTextChangedListener(this);
|
||||
|
||||
|
||||
View clearButton = findViewById(R.id.clear_button);
|
||||
clearButton.setOnClickListener(this);
|
||||
|
||||
@ -98,7 +111,7 @@ public class SongSelector extends TabActivity implements AdapterView.OnItemClick
|
||||
{
|
||||
mAdapters[1] = new AlbumAdapter(SongSelector.this, songs);
|
||||
mAdapters[1].setExpanderListener(SongSelector.this);
|
||||
initializeListView(R.id.album_list, mAdapters[1]);
|
||||
mAlbumView = initializeListView(R.id.album_list, mAdapters[1]);
|
||||
|
||||
mAdapters[2] = new SongAdapter(SongSelector.this, songs);
|
||||
initializeListView(R.id.song_list, mAdapters[2]);
|
||||
@ -116,19 +129,20 @@ public class SongSelector extends TabActivity implements AdapterView.OnItemClick
|
||||
return mTextFilter.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
private void pushSong(int action, int id)
|
||||
private Intent buildSongIntent(int action, int type, int id)
|
||||
{
|
||||
Intent intent = new Intent(this, PlaybackService.class);
|
||||
intent.putExtra("id", id);
|
||||
intent.putExtra("type", type);
|
||||
intent.putExtra("action", action);
|
||||
startService(intent);
|
||||
intent.putExtra("id", id);
|
||||
return intent;
|
||||
}
|
||||
|
||||
public void onItemClick(AdapterView<?> list, View view, int pos, long id)
|
||||
{
|
||||
if (mHandler.hasMessages(MSG_ITEM_CLICK, view)) {
|
||||
mHandler.removeMessages(MSG_ITEM_CLICK, view);
|
||||
pushSong(PlaybackService.ACTION_ENQUEUE, (int)id);
|
||||
startService(buildSongIntent(PlaybackService.ACTION_ENQUEUE, listToMediaType(list), (int)id));
|
||||
} else {
|
||||
Message message = mHandler.obtainMessage(MSG_ITEM_CLICK, view);
|
||||
message.arg1 = (int)id;
|
||||
@ -170,7 +184,9 @@ public class SongSelector extends TabActivity implements AdapterView.OnItemClick
|
||||
{
|
||||
switch (message.what) {
|
||||
case MSG_ITEM_CLICK:
|
||||
pushSong(PlaybackService.ACTION_PLAY, message.arg1);
|
||||
int type = listToMediaType(((View)message.obj).getParent());
|
||||
int id = message.arg1;
|
||||
startService(buildSongIntent(PlaybackService.ACTION_PLAY, type, id));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -180,24 +196,18 @@ public class SongSelector extends TabActivity implements AdapterView.OnItemClick
|
||||
private static final int MENU_ENQUEUE = 1;
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo)
|
||||
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo info)
|
||||
{
|
||||
menu.add(0, MENU_PLAY, 0, R.string.play);
|
||||
menu.add(0, MENU_ENQUEUE, 0, R.string.enqueue);
|
||||
int type = listToMediaType(view);
|
||||
int id = (int)((AdapterView.AdapterContextMenuInfo)info).id;
|
||||
menu.add(0, MENU_PLAY, 0, R.string.play).setIntent(buildSongIntent(PlaybackService.ACTION_PLAY, type, id));
|
||||
menu.add(0, MENU_ENQUEUE, 0, R.string.enqueue).setIntent(buildSongIntent(PlaybackService.ACTION_ENQUEUE, type, id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem item)
|
||||
{
|
||||
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
|
||||
switch (item.getItemId()) {
|
||||
case MENU_PLAY:
|
||||
pushSong(PlaybackService.ACTION_PLAY, (int)info.id);
|
||||
break;
|
||||
case MENU_ENQUEUE:
|
||||
pushSong(PlaybackService.ACTION_ENQUEUE, (int)info.id);
|
||||
break;
|
||||
}
|
||||
startService(item.getIntent());
|
||||
return true;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user