// Copyright 2009 Google Inc.
// Copyright 2011 NPR
//
// 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 org.npr.android.news;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.*;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.*;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.SlidingDrawer.OnDrawerCloseListener;
import android.widget.SlidingDrawer.OnDrawerOpenListener;
import org.npr.android.util.DisplayUtils;
import org.npr.android.util.PlaylistEntry;
import org.npr.android.util.PlaylistProvider;
import org.npr.android.util.PlaylistRepository;
import org.npr.android.widget.DragListener;
import org.npr.android.widget.DragNDropListView;
import org.npr.android.widget.DropListener;
public class PlaylistView extends FrameLayout implements OnClickListener,
OnSeekBarChangeListener, OnDrawerOpenListener, OnDrawerCloseListener,
AdapterView.OnItemClickListener, DragListener, DropListener {
private static final String LOG_TAG = PlaylistView.class.getName();
private final Context context;
private PlaylistAdapter playlistAdapter;
private PlaylistRepository playlist;
private SlidingDrawer drawer;
private RelativeLayout handle;
private RelativeLayout playerContracted;
private RelativeLayout playerExpanded;
private TextView playerStatus;
private TextView contractedPlayerStatus;
private TextView newsItemText;
private TextView contractedNewsItemText;
private SeekBar progressBar;
private boolean changingProgress;
private TextView lengthText;
private boolean playPauseShowsPlay;
private ImageButton rewindButton;
private ImageButton rewind30Button;
private ImageButton playPauseButton;
private ImageButton fastForwardButton;
private ImageButton contractedPlayButton;
private DragNDropListView listView;
private Button clearPlayedSegments;
private Button clearPlaylist;
private boolean playEnabled;
private boolean moveControlsEnabled;
private boolean rewindEnabled;
private boolean fastForwardEnabled;
private int touchSlop;
private int startX;
private int startY;
private boolean cancelDown;
private Playable storedPlayable = null;
private enum ClickedItem {
rewind, rewind30, playPause, fastForward, contractedPlay, progressbar
}
private ClickedItem clickedItem;
private BroadcastReceiver changeReceiver;
private BroadcastReceiver updateReceiver;
private BroadcastReceiver closeReceiver;
private BroadcastReceiver errorReceiver;
private BroadcastReceiver playlistChangedReceiver;
private GestureDetector gestureDetector;
private final Handler handler = new Handler() {
@Override
public void handleMessage(final Message msg) {
switch (msg.what) {
case ListItemGestureListener.MSG_FLING:
final PlaylistEntry entry = getPlaylistEntryAtPosition(msg.arg1);
View listItem = listView.getChildAt(msg.arg1 -
listView.getFirstVisiblePosition());
Animation fling = AnimationUtils.loadAnimation(
context,
msg.arg2 < 0 ? R.anim.playlist_remove_left :
R.anim.playlist_remove_right
);
fling.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationEnd(Animation animation) {
playlist.delete(entry);
updatePlaylist();
}
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
listItem.startAnimation(fling);
break;
}
}
};
public PlaylistView(Context context) {
super(context);
this.context = context;
}
public PlaylistView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
}
public PlaylistView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context = context;
}
/**
* Returns a pointer to the SlidingDrawer for the
* player window.
*
* @return The player's SlidingDrawer
*/
public SlidingDrawer getPlayerDrawer() {
return drawer;
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
init();
}
private void init() {
ViewGroup.inflate(context, R.layout.playlist, this);
playlist = new PlaylistRepository(context.getApplicationContext(),
context.getContentResolver());
drawer = (SlidingDrawer) findViewById(R.id.drawer);
drawer.setOnDrawerOpenListener(this);
drawer.setOnDrawerCloseListener(this);
touchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
handle = (RelativeLayout) findViewById(R.id.handle);
playerContracted = (RelativeLayout) findViewById(R.id.player_contracted);
playerExpanded = (RelativeLayout) findViewById(R.id.player_expanded);
playerStatus = (TextView) findViewById(R.id.status);
contractedPlayerStatus = (TextView) findViewById(R.id.contracted_status);
newsItemText = (TextView) findViewById(R.id.news_item_text);
contractedNewsItemText = (TextView) findViewById(R.id
.contracted_news_item_text);
progressBar = (SeekBar) findViewById(R.id.stream_progress_bar);
progressBar.setOnSeekBarChangeListener(this);
changingProgress = false;
lengthText = (TextView) findViewById(R.id.stream_length_display_text);
lengthText.setText("0:00 / 0:00");
playPauseShowsPlay = true;
contractedPlayButton = (ImageButton) findViewById(R.id
.contracted_play_pause);
rewindButton = (ImageButton) findViewById(R.id.stream_rewind_button);
rewind30Button = (ImageButton) findViewById(R.id.stream_rewind_30_button);
playPauseButton = (ImageButton) findViewById(R.id.stream_play_pause_button);
fastForwardButton = (ImageButton) findViewById(R.id
.stream_fastforward_button);
clearPlayedSegments = (Button) findViewById(R.id.clear_played_segments);
clearPlayedSegments.setOnClickListener(this);
clearPlaylist = (Button) findViewById(R.id.clear_playlist);
clearPlaylist.setOnClickListener(this);
Cursor cursor = queryPlaylist();
playlistAdapter = new PlaylistAdapter(context, cursor);
changeReceiver = new PlaybackChangeReceiver();
Intent intent = context.registerReceiver(changeReceiver,
new IntentFilter(PlaybackService.SERVICE_CHANGE_NAME));
if (intent != null) {
changeReceiver.onReceive(context, intent);
} else {
Log.d(LOG_TAG, "Call clearPlayer from init");
clearPlayer();
}
updateReceiver = new PlaybackUpdateReceiver();
intent = context.registerReceiver(updateReceiver,
new IntentFilter(PlaybackService.SERVICE_UPDATE_NAME));
if (intent != null) {
updateReceiver.onReceive(context, intent);
}
closeReceiver = new PlaybackCloseReceiver();
context.registerReceiver(closeReceiver,
new IntentFilter(PlaybackService.SERVICE_CLOSE_NAME));
errorReceiver = new PlaybackErrorReceiver();
context.registerReceiver(errorReceiver,
new IntentFilter(PlaybackService.SERVICE_ERROR_NAME));
playlistChangedReceiver = new PlaylistChangedReceiver();
context.registerReceiver(playlistChangedReceiver,
new IntentFilter(PlaylistRepository.PLAYLIST_CHANGED));
listView = (DragNDropListView) findViewById(R.id.playlist);
listView.setAdapter(playlistAdapter);
listView.setOnItemClickListener(this);
listView.setDragListener(this);
listView.setDropListener(this);
// Gesture detection
gestureDetector = new GestureDetector(getContext(),
new ListItemGestureListener(listView, handler)
);
View.OnTouchListener gestureListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
};
listView.setOnTouchListener(gestureListener);
if (context instanceof Activity) {
((Activity) context).registerForContextMenu(listView);
}
refreshList();
}
private Cursor queryPlaylist()
{
Cursor cursor = context.getContentResolver().query(PlaylistProvider
.CONTENT_URI, null, null, null, PlaylistProvider.Items.PLAY_ORDER);
return cursor;
}
private void refreshList() {
if (playlistAdapter != null) {
playlistAdapter.changeCursor( queryPlaylist() );
playlistAdapter.notifyDataSetChanged();
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
// Emulator calls detach twice, so clear receiver
if (changeReceiver != null) {
context.unregisterReceiver(changeReceiver);
changeReceiver = null;
}
if (updateReceiver != null) {
context.unregisterReceiver(updateReceiver);
updateReceiver = null;
}
if (closeReceiver != null) {
context.unregisterReceiver(closeReceiver);
closeReceiver = null;
}
if (errorReceiver != null) {
context.unregisterReceiver(errorReceiver);
errorReceiver = null;
}
if (playlistChangedReceiver != null) {
context.unregisterReceiver(playlistChangedReceiver);
playlistChangedReceiver = null;
}
if (playlistAdapter != null) {
playlistAdapter.close();
playlistAdapter = null;
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.clear_playlist:
Intent intent = new Intent(context, PlaybackService.class);
intent.setAction(PlaybackService.SERVICE_CLEAR_PLAYER);
context.startService(intent);
playlist.clearAll();
refreshList();
configurePlayerControls();
break;
case R.id.clear_played_segments:
playlist.clearPlayed();
refreshList();
configurePlayerControls();
break;
}
}
protected void playEntryNow(final PlaylistEntry entry) {
playNow(
Playable.PlayableFactory.fromPlaylistEntry(entry),
PlaybackService.SERVICE_PLAY_ENTRY
);
}
protected void playSingleNow(final Playable playable) {
playNow(playable, PlaybackService.SERVICE_PLAY_SINGLE);
}
private void playNow(final Playable playable, String action) {
startPlaylistSpinners();
Intent intent = new Intent(context, PlaybackService.class);
intent.setAction(action);
intent.putExtra(Playable.PLAYABLE_TYPE, playable);
context.startService(intent);
newsItemText.setText(playable.getTitle());
contractedNewsItemText.setText(playable.getTitle());
playlistAdapter.setActiveId(Long.toString(playable.getId()));
refreshList();
configurePlayerControls();
}
private void configurePlayerControls() {
if (playlist.getItemCount() > 0) {
clearPlaylist.setEnabled(true);
clearPlayedSegments.setEnabled(playlist.getReadCount() > 0);
} else {
clearPlaylist.setEnabled(false);
clearPlayedSegments.setEnabled(false);
}
String activeId = playlistAdapter.getActiveId();
if (activeId != null) {
playerStatus.setText(R.string.msg_player_now_playing);
contractedPlayerStatus.setText(R.string.msg_player_now_playing);
if (!activeId.equals("-1")) {
playEnabled = true;
moveControlsEnabled = true;
rewindEnabled = !playlist.isFirstEntry(activeId);
fastForwardEnabled = !playlist.isLastEntry(activeId);
} else {
playEnabled = true;
moveControlsEnabled = true;
rewindEnabled = false;
fastForwardEnabled = (playlist.getFirstUnreadEntry() != null);
}
} else {
Playable firstUnreadEntry = playlist.getFirstUnreadEntry();
if (firstUnreadEntry != null) {
playerStatus.setText(R.string.msg_player_ready_to_play);
contractedPlayerStatus.setText(R.string.msg_player_ready_to_play);
String title = firstUnreadEntry.getTitle();
newsItemText.setText(title);
contractedNewsItemText.setText(title);
} else {
playerStatus.setText(R.string.msg_player_nothing_to_play);
contractedPlayerStatus.setText(R.string.msg_player_nothing_to_play);
newsItemText.setText("");
contractedNewsItemText.setText("");
}
playEnabled = (firstUnreadEntry != null);
moveControlsEnabled = false;
rewindEnabled = false;
fastForwardEnabled = false;
}
}
private void clearPlayer() {
playlistAdapter.setActiveId(null);
configurePlayerControls();
progressBar.setProgress(0);
progressBar.setSecondaryProgress(0);
lengthText.setText("0:00 / 0:00");
stopPlaylistSpinners();
}
private class PlaybackChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
try {
Context serviceContext = context.createPackageContext(context.getPackageName(),
Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
Bundle bundle = intent.getExtras();
bundle.setClassLoader(serviceContext.getClassLoader());
storedPlayable = bundle.getParcelable(Playable.PLAYABLE_TYPE);
if (storedPlayable != null) {
newsItemText.setText(storedPlayable.getTitle());
contractedNewsItemText.setText(storedPlayable.getTitle());
playlistAdapter.setActiveId(Long.toString(storedPlayable.getId()));
}
} catch (PackageManager.NameNotFoundException e) {
Log.e(LOG_TAG, "Name not found exception in playback change", e);
}
refreshList();
configurePlayerControls();
showPlayPause(false);
}
}
private class PlaybackUpdateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
int duration = intent.getIntExtra(PlaybackService.EXTRA_DURATION, 1);
// Drop out if no duration is given (flicker?)
if (duration == 1) {
Log.v(LOG_TAG, "Playback update; no duration dropout");
return;
}
int position = intent.getIntExtra(PlaybackService.EXTRA_POSITION, 0);
int downloaded = intent.getIntExtra(PlaybackService.EXTRA_DOWNLOADED, 1);
Log.v(LOG_TAG, "Playback update; position = " + position + " millsecs; " +
"downloaded = " + duration + " millsecs");
boolean isPlaying = intent.getBooleanExtra(PlaybackService
.EXTRA_IS_PLAYING, false);
if (!changingProgress) {
progressBar.setMax(duration);
progressBar.setProgress(position);
}
progressBar.setSecondaryProgress(downloaded);
// StringBuilder much faster than String.Format
StringBuilder length = new StringBuilder(13);
length.append(position / 60000);
length.append(':');
int secs = position / 1000 % 60;
if (secs < 10) {
length.append('0');
}
length.append(secs);
length.append(" / ");
length.append(duration / 60000);
length.append(':');
secs = duration / 1000 % 60;
if (secs < 10) {
length.append('0');
}
length.append(secs);
lengthText.setText(length.toString());
if (position > 0) {
// Streams have no 'downloaded' amount
if (downloaded == 0 || downloaded >= position) {
stopPlaylistSpinners();
} else if (isPlaying) {
startPlaylistSpinners();
}
}
if (isPlaying == playPauseShowsPlay) {
if (isPlaying) {
if (storedPlayable == null || !storedPlayable.isStream()) {
playPauseButton.setImageResource(R.drawable.pause_button_normal);
playPauseButton.setContentDescription(getResources().getString(R.string.acd_pause_button));
contractedPlayButton.setImageResource(R.drawable.pause_button_normal);
contractedPlayButton.setContentDescription(getResources().getString(R.string.acd_pause_button));
} else {
playPauseButton.setImageResource(R.drawable.stop_button_normal);
playPauseButton.setContentDescription(getResources().getString(R.string.acd_stop_button));
contractedPlayButton.setImageResource(R.drawable.stop_button_normal);
contractedPlayButton.setContentDescription(getResources().getString(R.string.acd_stop_button));
}
playPauseShowsPlay = false;
} else {
playPauseButton.setImageResource(R.drawable.play_button_normal);
playPauseButton.setContentDescription(getResources().getString(R.string.acd_play_button));
contractedPlayButton.setImageResource(R.drawable.play_button_normal);
contractedPlayButton.setContentDescription(getResources().getString(R.string.acd_play_button));
playPauseShowsPlay = true;
}
}
}
}
private class PlaybackCloseReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(LOG_TAG, "Playback close received - calling clear player");
clearPlayer();
refreshList();
}
}
private class PlaybackErrorReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(LOG_TAG, "Playback error received - toasting message");
String message = context.getString(R.string.msg_unknown_error);
int error = intent.getIntExtra(PlaybackService.EXTRA_ERROR, -1);
if (error == PlaybackService.PLAYBACK_SERVICE_ERROR.Playback.ordinal()) {
message = context.getString(R.string.msg_playback_error);
} else if (error == PlaybackService.PLAYBACK_SERVICE_ERROR.Connection.ordinal()) {
message = context.getString(R.string.msg_playback_connection_error);
} else if (error == PlaybackService.PLAYBACK_SERVICE_ERROR.InvalidPlayable.ordinal()) {
message = context.getString(R.string.msg_playback_invalid_playable_error);
clearPlayer();
}
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
}
}
private class PlaylistChangedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
configurePlayerControls();
}
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
seekBar.setProgress(progress);
if (fromUser) {
Intent intent = new Intent(context, PlaybackService.class);
intent.setAction(PlaybackService.SERVICE_SEEK_TO);
intent.putExtra(PlaybackService.EXTRA_SEEK_TO, progress);
context.startService(intent);
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
changingProgress = true;
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
changingProgress = false;
}
@Override
public void onDrawerOpened() {
handle.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
DisplayUtils.convertToDIP(context, 150)));
playerContracted.setVisibility(View.GONE);
playerExpanded.setVisibility(View.VISIBLE);
refreshList();
}
@Override
public void onDrawerClosed() {
handle.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
DisplayUtils.convertToDIP(context, 95)));
playerContracted.setVisibility(View.VISIBLE);
playerExpanded.setVisibility(View.GONE);
}
public boolean isExpanded() {
return drawer.isOpened();
}
public void setExpanded(boolean expanded) {
if (expanded) {
drawer.animateOpen();
} else {
drawer.animateClose();
}
}
private boolean ViewContainsXY(View v, int x, int y) {
Rect r = new Rect();
v.getDrawingRect(r);
offsetDescendantRectToMyCoords(v, r);
return r.contains(x, y);
}
private void closeDrawerIfPastThreshold(int y) {
Rect r = new Rect();
drawer.getDrawingRect(r);
if ((y - startY) > (r.height() / 3)) {
drawer.close();
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
final int x = (int) event.getX(), y = (int) event.getY();
if (isExpanded()) {
if (ViewContainsXY(playPauseButton, x, y)) {
clickedItem = ClickedItem.playPause;
return true;
} else if (ViewContainsXY(rewindButton, x, y)) {
clickedItem = ClickedItem.rewind;
return true;
} else if (ViewContainsXY(rewind30Button, x, y)) {
clickedItem = ClickedItem.rewind30;
return true;
} else if (ViewContainsXY(fastForwardButton, x, y)) {
clickedItem = ClickedItem.fastForward;
return true;
} else if (ViewContainsXY(progressBar, x, y)) {
clickedItem = ClickedItem.progressbar;
return true;
}
} else {
if (ViewContainsXY(contractedPlayButton, x, y)) {
clickedItem = ClickedItem.contractedPlay;
return true;
}
}
}
return false;
}
private void showPlayPause(boolean showPressed) {
if (playPauseShowsPlay) {
if (showPressed) {
playPauseButton.setImageResource(R.drawable.play_button_pressed);
contractedPlayButton.setImageResource(R.drawable.play_button_pressed);
} else {
playPauseButton.setImageResource(R.drawable.play_button_normal);
contractedPlayButton.setImageResource(R.drawable.play_button_normal);
}
} else {
if (storedPlayable == null || !storedPlayable.isStream()) {
if (showPressed) {
playPauseButton.setImageResource(R.drawable.pause_button_pressed);
contractedPlayButton.setImageResource(R.drawable.pause_button_pressed);
} else {
playPauseButton.setImageResource(R.drawable.pause_button_normal);
contractedPlayButton.setImageResource(R.drawable.pause_button_normal);
}
} else {
if (showPressed) {
playPauseButton.setImageResource(R.drawable.stop_button_pressed);
contractedPlayButton.setImageResource(R.drawable.stop_button_pressed);
} else {
playPauseButton.setImageResource(R.drawable.stop_button_normal);
contractedPlayButton.setImageResource(R.drawable.stop_button_normal);
}
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (clickedItem != null) {
final int x = (int) event.getX(), y = (int) event.getY();
switch (clickedItem) {
case playPause:
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (ViewContainsXY(playPauseButton, x, y)) {
if (playEnabled) {
showPlayPause(true);
}
startY = y;
cancelDown = false;
return true;
}
break;
case MotionEvent.ACTION_MOVE:
if (!ViewContainsXY(playPauseButton, x, y)) {
if (playEnabled) {
showPlayPause(false);
}
cancelDown = true;
return true;
}
break;
case MotionEvent.ACTION_UP:
if (playEnabled && !cancelDown) {
playPauseShowsPlay = !playPauseShowsPlay;
if (playPauseShowsPlay) {
stopPlaylistSpinners();
} else {
startPlaylistSpinners();
}
showPlayPause(false);
Intent intent = new Intent(context, PlaybackService.class);
intent.setAction(PlaybackService.SERVICE_TOGGLE_PLAY);
intent.putExtra(Playable.PLAYABLE_TYPE, storedPlayable);
context.startService(intent);
} else {
closeDrawerIfPastThreshold(y);
}
clickedItem = null;
return true;
}
break;
case rewind:
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (ViewContainsXY(rewindButton, x, y)) {
if (rewindEnabled) {
rewindButton.setImageResource(R.drawable.rew_pressed);
}
startY = y;
cancelDown = false;
return true;
}
break;
case MotionEvent.ACTION_MOVE:
if (!ViewContainsXY(rewindButton, x, y)) {
if (rewindEnabled) {
rewindButton.setImageResource(R.drawable.rew_normal);
}
cancelDown = true;
return false;
}
break;
case MotionEvent.ACTION_UP:
if (rewindEnabled && !cancelDown) {
rewindButton.setImageResource(R.drawable.rew_normal);
Intent intent = new Intent(context, PlaybackService.class);
intent.setAction(PlaybackService.SERVICE_PLAY_PREVIOUS);
context.startService(intent);
} else {
closeDrawerIfPastThreshold(y);
}
clickedItem = null;
return true;
}
break;
case rewind30:
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (ViewContainsXY(rewind30Button, x, y)) {
if (moveControlsEnabled) {
rewind30Button.setImageResource(R.drawable.rew_30_pressed);
}
startY = y;
cancelDown = false;
return true;
}
break;
case MotionEvent.ACTION_MOVE:
if (!ViewContainsXY(rewind30Button, x, y)) {
if (moveControlsEnabled) {
rewind30Button.setImageResource(R.drawable.rew_30_normal);
}
cancelDown = true;
return false;
}
break;
case MotionEvent.ACTION_UP:
if (moveControlsEnabled && !cancelDown) {
rewind30Button.setImageResource(R.drawable.rew_30_normal);
Intent intent = new Intent(context, PlaybackService.class);
intent.setAction(PlaybackService.SERVICE_BACK_30);
context.startService(intent);
} else {
closeDrawerIfPastThreshold(y);
}
clickedItem = null;
return true;
}
break;
case fastForward:
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (ViewContainsXY(fastForwardButton, x, y)) {
if (fastForwardEnabled) {
fastForwardButton.setImageResource(R.drawable.ffwd_pressed);
}
startY = y;
cancelDown = false;
return true;
}
break;
case MotionEvent.ACTION_MOVE:
if (!ViewContainsXY(fastForwardButton, x, y)) {
if (fastForwardEnabled) {
fastForwardButton.setImageResource(R.drawable.ffwd_normal);
}
cancelDown = true;
return false;
}
break;
case MotionEvent.ACTION_UP:
if (fastForwardEnabled && !cancelDown) {
fastForwardButton.setImageResource(R.drawable.ffwd_normal);
Intent intent = new Intent(context, PlaybackService.class);
intent.setAction(PlaybackService.SERVICE_PLAY_NEXT);
context.startService(intent);
} else {
closeDrawerIfPastThreshold(y);
}
clickedItem = null;
return true;
}
break;
case contractedPlay:
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (ViewContainsXY(contractedPlayButton, x, y)) {
if (playEnabled) {
showPlayPause(true);
}
startY = y;
cancelDown = false;
return true;
}
break;
case MotionEvent.ACTION_MOVE:
if (!ViewContainsXY(contractedPlayButton, x, y)) {
if (playEnabled) {
showPlayPause(false);
}
cancelDown = true;
return false;
}
break;
case MotionEvent.ACTION_UP:
if (playEnabled && !cancelDown) {
playPauseShowsPlay = !playPauseShowsPlay;
if (playPauseShowsPlay) {
stopPlaylistSpinners();
} else {
startPlaylistSpinners();
}
showPlayPause(false);
Intent intent = new Intent(context, PlaybackService.class);
intent.setAction(PlaybackService.SERVICE_TOGGLE_PLAY);
intent.putExtra(Playable.PLAYABLE_TYPE, storedPlayable);
context.startService(intent);
} else {
Rect r = new Rect();
drawer.getDrawingRect(r);
if ((startY - y) > (r.height() / 3)) {
drawer.open();
}
}
clickedItem = null;
return true;
}
break;
case progressbar:
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (ViewContainsXY(progressBar, x, y)) {
startX = x;
startY = y;
return true;
}
break;
case MotionEvent.ACTION_MOVE:
boolean xMovement = Math.abs(x - startX) >= touchSlop;
if (moveControlsEnabled && xMovement) {
progressBar.onTouchEvent(event);
} else if (Math.abs(y - startY) >= touchSlop && !xMovement) {
cancelDown = true;
}
return true;
case MotionEvent.ACTION_UP:
if (moveControlsEnabled && !cancelDown) {
progressBar.onTouchEvent(event);
} else {
closeDrawerIfPastThreshold(y);
}
clickedItem = null;
return true;
}
break;
}
}
return false;
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
PlaylistEntry entry = getPlaylistEntryAtPosition(position);
playEntryNow(entry);
}
/**
* Returns a PlaylistEntry for the item at the given position in the
* playlist.
*
* @param position The position of the item starting at 0
* @return A PlaylistEntry or null of the position is invalid or cannot be
* found.
*/
public PlaylistEntry getPlaylistEntryAtPosition(int position) {
PlaylistEntry entry = null;
DragNDropListView listView = (DragNDropListView) findViewById(R.id.playlist);
Cursor c = (Cursor) listView.getItemAtPosition(position);
if (c != null) {
c.moveToPosition(position);
long playlistId = c.getLong(c.getColumnIndex(PlaylistProvider.Items._ID));
Log.d(LOG_TAG, "clicked on position " + position + ", id " + playlistId);
entry = playlist.getPlaylistItemFromId(playlistId);
if (entry == null) {
Log.e(LOG_TAG, "Couldn't find playlist item " + playlistId +
" at position" + position);
}
}
return entry;
}
private void startPlaylistSpinners() {
ProgressBar loadingIndicator =
(ProgressBar) findViewById(R.id.player_loading_indicator);
if (loadingIndicator != null) {
loadingIndicator.setVisibility(View.VISIBLE);
} else {
Log.w(LOG_TAG, "Can't find loading indicator. Expanded? " + isExpanded());
}
loadingIndicator =
(ProgressBar) findViewById(R.id.player_loading_indicator_contracted);
if (loadingIndicator != null) {
loadingIndicator.setVisibility(View.VISIBLE);
}
}
private void stopPlaylistSpinners() {
ProgressBar loadingIndicator =
(ProgressBar) findViewById(R.id.player_loading_indicator);
if (loadingIndicator != null) {
loadingIndicator.setVisibility(View.INVISIBLE);
}
loadingIndicator =
(ProgressBar) findViewById(R.id.player_loading_indicator_contracted);
if (loadingIndicator != null) {
loadingIndicator.setVisibility(View.INVISIBLE);
}
}
@Override
public void onStartDrag(View itemView) {
drawer.lock();
itemView.setVisibility(View.INVISIBLE);
}
@Override
public void onDrag(int x, int y, ListView listView) {
}
@Override
public void onStopDrag(View itemView) {
itemView.setVisibility(View.VISIBLE);
drawer.unlock();
}
@Override
public void onDrop(int from, int to) {
playlist.move(from, to);
refreshList();
}
public void updatePlaylist() {
refreshList();
configurePlayerControls();
if (playlist.getItemCount() == 0) {
Intent intent = new Intent(context, PlaybackService.class);
intent.setAction(PlaybackService.SERVICE_CLEAR_PLAYER);
context.startService(intent);
}
}
public String getActiveId() {
return playlistAdapter.getActiveId();
}
}