Shake actions
Also moves Action into its own file since it is now also used in PlaybackService
This commit is contained in:
parent
7a34f5db51
commit
44897e85d2
37
res/layout/shake_pref.xml
Normal file
37
res/layout/shake_pref.xml
Normal file
@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2012 Christopher Eby <kreed@kreed.org>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<TextView
|
||||
android:id="@+id/value"
|
||||
android:padding="5dip"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="right" />
|
||||
<SeekBar
|
||||
android:id="@+id/seek_bar"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
@ -159,6 +159,12 @@ THE SOFTWARE.
|
||||
<string name="default_action_title">Default Action</string>
|
||||
<string name="default_playlist_action_title">Default Playlist Action</string>
|
||||
|
||||
<string name="pref_shake">Accelerometer Shake</string>
|
||||
<string name="enable_shake_title">Enable Accelerometer Shake</string>
|
||||
<string name="enable_shake_summary">Only active when music is playing. Does not work when screen is off on some devices.</string>
|
||||
<string name="shake_action_title">Accelerometer Shake Action</string>
|
||||
<string name="shake_threshold_title">Shake Force Threshold</string>
|
||||
|
||||
<string name="pref_misc">Miscellaneous Features</string>
|
||||
<string name="disable_lockscreen_title">Disable Lockscreen</string>
|
||||
<string name="disable_lockscreen_summary">Do not show the lockscreen with the library screen or playback screen open.</string>
|
||||
|
@ -123,6 +123,27 @@ THE SOFTWARE.
|
||||
android:entryValues="@array/entry_values"
|
||||
android:defaultValue="3" />
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="@string/pref_shake">
|
||||
<CheckBoxPreference
|
||||
android:key="enable_shake"
|
||||
android:title="@string/enable_shake_title"
|
||||
android:summary="@string/enable_shake_summary"
|
||||
android:defaultValue="false" />
|
||||
<org.kreed.vanilla.ListPreferenceSummary
|
||||
android:key="shake_action"
|
||||
android:title="@string/shake_action_title"
|
||||
android:entries="@array/swipe_action_entries"
|
||||
android:entryValues="@array/swipe_action_values"
|
||||
android:defaultValue="NextSong"
|
||||
android:dependency="enable_shake" />
|
||||
<!-- Might be nice to show something indicating the current shake force for this preference. -->
|
||||
<org.kreed.vanilla.ShakeThresholdPreference
|
||||
android:key="shake_threshold"
|
||||
android:negativeButtonText="@null"
|
||||
android:dialogLayout="@layout/shake_pref"
|
||||
android:title="@string/shake_threshold_title"
|
||||
android:dependency="enable_shake" />
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="@string/pref_misc">
|
||||
<CheckBoxPreference
|
||||
android:key="disable_lockscreen"
|
||||
|
107
src/org/kreed/vanilla/Action.java
Normal file
107
src/org/kreed/vanilla/Action.java
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Christopher Eby <kreed@kreed.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.kreed.vanilla;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
/**
|
||||
* Various actions that can be passed to {@link PlaybackService#performAction(Action, PlaybackActivity)}.
|
||||
*/
|
||||
enum Action {
|
||||
/**
|
||||
* Dummy action: do nothing.
|
||||
*/
|
||||
Nothing,
|
||||
/**
|
||||
* Open the library activity.
|
||||
*/
|
||||
Library,
|
||||
/**
|
||||
* If playing music, pause. Otherwise, start playing.
|
||||
*/
|
||||
PlayPause,
|
||||
/**
|
||||
* Skip to the next song.
|
||||
*/
|
||||
NextSong,
|
||||
/**
|
||||
* Go back to the previous song.
|
||||
*/
|
||||
PreviousSong,
|
||||
/**
|
||||
* Skip to the first song from the next album.
|
||||
*/
|
||||
NextAlbum,
|
||||
/**
|
||||
* Skip to the last song from the previous album.
|
||||
*/
|
||||
PreviousAlbum,
|
||||
/**
|
||||
* Cycle the repeat mode.
|
||||
*/
|
||||
Repeat,
|
||||
/**
|
||||
* Cycle the shuffle mode.
|
||||
*/
|
||||
Shuffle,
|
||||
/**
|
||||
* Enqueue the rest of the current album.
|
||||
*/
|
||||
EnqueueAlbum,
|
||||
/**
|
||||
* Enqueue the rest of the songs by the current artist.
|
||||
*/
|
||||
EnqueueArtist,
|
||||
/**
|
||||
* Enqueue the rest of the songs in the current genre.
|
||||
*/
|
||||
EnqueueGenre,
|
||||
/**
|
||||
* Clear the queue of all remaining songs.
|
||||
*/
|
||||
ClearQueue,
|
||||
/**
|
||||
* Toggle the controls in the playback activity.
|
||||
*/
|
||||
ToggleControls;
|
||||
|
||||
/**
|
||||
* Retrieve an action from the given SharedPreferences.
|
||||
*
|
||||
* @param prefs The SharedPreferences instance to load from.
|
||||
* @param key The preference key to load.
|
||||
* @param def The value to return if the key is not found or cannot be loaded.
|
||||
* @return The loaded action or def if no action could be loaded.
|
||||
*/
|
||||
public static Action getAction(SharedPreferences prefs, String key, Action def)
|
||||
{
|
||||
try {
|
||||
String pref = prefs.getString(key, null);
|
||||
if (pref == null)
|
||||
return def;
|
||||
return Enum.valueOf(Action.class, pref);
|
||||
} catch (Exception e) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
}
|
@ -177,8 +177,8 @@ public class FullPlaybackActivity extends PlaybackActivity
|
||||
startActivity(new Intent(this, FullPlaybackActivity.class));
|
||||
}
|
||||
|
||||
mCoverPressAction = getAction(settings, "cover_press_action", Action.ToggleControls);
|
||||
mCoverLongPressAction = getAction(settings, "cover_longpress_action", Action.PlayPause);
|
||||
mCoverPressAction = Action.getAction(settings, "cover_press_action", Action.ToggleControls);
|
||||
mCoverLongPressAction = Action.getAction(settings, "cover_longpress_action", Action.PlayPause);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -435,14 +435,13 @@ public class FullPlaybackActivity extends PlaybackActivity
|
||||
mSeekBarTracking = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performAction(Action action)
|
||||
{
|
||||
if (action == Action.ToggleControls) {
|
||||
setControlsVisible(!mControlsVisible);
|
||||
mHandler.sendEmptyMessage(MSG_SAVE_CONTROLS);
|
||||
} else {
|
||||
super.performAction(action);
|
||||
PlaybackService.get(this).performAction(action, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,23 +52,6 @@ public class PlaybackActivity extends Activity
|
||||
View.OnClickListener,
|
||||
CoverView.Callback
|
||||
{
|
||||
enum Action {
|
||||
Nothing,
|
||||
Library,
|
||||
PlayPause,
|
||||
NextSong,
|
||||
PreviousSong,
|
||||
NextAlbum,
|
||||
PreviousAlbum,
|
||||
Repeat,
|
||||
Shuffle,
|
||||
EnqueueAlbum,
|
||||
EnqueueArtist,
|
||||
EnqueueGenre,
|
||||
ClearQueue,
|
||||
ToggleControls,
|
||||
}
|
||||
|
||||
private Action mUpAction;
|
||||
private Action mDownAction;
|
||||
|
||||
@ -119,26 +102,6 @@ public class PlaybackActivity extends Activity
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an action from the given SharedPreferences.
|
||||
*
|
||||
* @param prefs The SharedPreferences instance to load from.
|
||||
* @param key The preference key.
|
||||
* @param def The value to return if the key is not found or cannot be loaded.
|
||||
* @return An action
|
||||
*/
|
||||
public static Action getAction(SharedPreferences prefs, String key, Action def)
|
||||
{
|
||||
try {
|
||||
String pref = prefs.getString(key, null);
|
||||
if (pref == null)
|
||||
return def;
|
||||
return Enum.valueOf(Action.class, pref);
|
||||
} catch (Exception e) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart()
|
||||
{
|
||||
@ -150,8 +113,8 @@ public class PlaybackActivity extends Activity
|
||||
startService(new Intent(this, PlaybackService.class));
|
||||
|
||||
SharedPreferences prefs = PlaybackService.getSettings(this);
|
||||
mUpAction = getAction(prefs, "swipe_up_action", Action.Nothing);
|
||||
mDownAction = getAction(prefs, "swipe_down_action", Action.Nothing);
|
||||
mUpAction = Action.getAction(prefs, "swipe_up_action", Action.Nothing);
|
||||
mDownAction = Action.getAction(prefs, "swipe_down_action", Action.Nothing);
|
||||
|
||||
Window window = getWindow();
|
||||
if (prefs.getBoolean("disable_lockscreen", false))
|
||||
@ -411,63 +374,16 @@ public class PlaybackActivity extends Activity
|
||||
PlaybackService.get(this).enqueueFromCurrent(type);
|
||||
}
|
||||
|
||||
public void performAction(Action action)
|
||||
{
|
||||
switch (action) {
|
||||
case Nothing:
|
||||
break;
|
||||
case Library:
|
||||
openLibrary(null);
|
||||
break;
|
||||
case PlayPause:
|
||||
playPause();
|
||||
break;
|
||||
case NextSong:
|
||||
shiftCurrentSong(SongTimeline.SHIFT_NEXT_SONG);
|
||||
break;
|
||||
case PreviousSong:
|
||||
shiftCurrentSong(SongTimeline.SHIFT_PREVIOUS_SONG);
|
||||
break;
|
||||
case NextAlbum:
|
||||
shiftCurrentSong(SongTimeline.SHIFT_NEXT_ALBUM);
|
||||
break;
|
||||
case PreviousAlbum:
|
||||
shiftCurrentSong(SongTimeline.SHIFT_PREVIOUS_ALBUM);
|
||||
break;
|
||||
case Repeat:
|
||||
cycleFinishAction();
|
||||
break;
|
||||
case Shuffle:
|
||||
cycleShuffle();
|
||||
break;
|
||||
case EnqueueAlbum:
|
||||
enqueue(MediaUtils.TYPE_ALBUM);
|
||||
break;
|
||||
case EnqueueArtist:
|
||||
enqueue(MediaUtils.TYPE_ARTIST);
|
||||
break;
|
||||
case EnqueueGenre:
|
||||
enqueue(MediaUtils.TYPE_GENRE);
|
||||
break;
|
||||
case ClearQueue:
|
||||
PlaybackService.get(this).clearQueue();
|
||||
Toast.makeText(this, R.string.queue_cleared, Toast.LENGTH_SHORT).show();
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid action: " + action);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void upSwipe()
|
||||
{
|
||||
performAction(mUpAction);
|
||||
PlaybackService.get(this).performAction(mUpAction, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downSwipe()
|
||||
{
|
||||
performAction(mDownAction);
|
||||
PlaybackService.get(this).performAction(mDownAction, this);
|
||||
}
|
||||
|
||||
private static final int GROUP_SHUFFLE = 100;
|
||||
|
@ -37,6 +37,10 @@ import android.content.res.TypedArray;
|
||||
import android.database.ContentObserver;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.media.AudioManager;
|
||||
import android.media.MediaPlayer;
|
||||
import android.os.Build;
|
||||
@ -70,6 +74,7 @@ public final class PlaybackService extends Service
|
||||
, MediaPlayer.OnErrorListener
|
||||
, SharedPreferences.OnSharedPreferenceChangeListener
|
||||
, SongTimeline.Callback
|
||||
, SensorEventListener
|
||||
{
|
||||
/**
|
||||
* Name of the state file.
|
||||
@ -269,6 +274,10 @@ public final class PlaybackService extends Service
|
||||
private PowerManager.WakeLock mWakeLock;
|
||||
private NotificationManager mNotificationManager;
|
||||
private AudioManager mAudioManager;
|
||||
/**
|
||||
* The SensorManager service.
|
||||
*/
|
||||
private SensorManager mSensorManager;
|
||||
|
||||
SongTimeline mTimeline;
|
||||
private Song mCurrentSong;
|
||||
@ -308,6 +317,32 @@ public final class PlaybackService extends Service
|
||||
*/
|
||||
private boolean mDuckedLoss;
|
||||
|
||||
/**
|
||||
* Minimum time in milliseconds between shake actions.
|
||||
*/
|
||||
private static final int MIN_SHAKE_PERIOD = 500;
|
||||
|
||||
/**
|
||||
* Magnitude of last sensed acceleration.
|
||||
*/
|
||||
private float mAccelLast;
|
||||
/**
|
||||
* Filtered acceleration used for shake detection.
|
||||
*/
|
||||
private float mAccelFiltered;
|
||||
/**
|
||||
* Elapsed realtime of last shake action.
|
||||
*/
|
||||
private long mLastShakeTime;
|
||||
/**
|
||||
* Minimum jerk required for shake.
|
||||
*/
|
||||
private float mShakeThreshold;
|
||||
/**
|
||||
* What to do when an accelerometer shake is detected.
|
||||
*/
|
||||
private Action mShakeAction;
|
||||
|
||||
@Override
|
||||
public void onCreate()
|
||||
{
|
||||
@ -325,6 +360,7 @@ public final class PlaybackService extends Service
|
||||
|
||||
mNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
|
||||
mAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
|
||||
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
|
||||
CompatFroyo.createAudioFocus();
|
||||
@ -347,6 +383,8 @@ public final class PlaybackService extends Service
|
||||
mInvertNotification = settings.getBoolean("notification_inverted_color", false);
|
||||
mNotificationAction = createNotificationAction(settings);
|
||||
mHeadsetPause = getSettings(this).getBoolean("headset_pause", true);
|
||||
mShakeAction = settings.getBoolean("enable_shake", false) ? Action.getAction(settings, "shake_action", Action.NextSong) : Action.Nothing;
|
||||
mShakeThreshold = settings.getInt("shake_threshold", 80) / 10.0f;
|
||||
|
||||
PowerManager powerManager = (PowerManager)getSystemService(POWER_SERVICE);
|
||||
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "VanillaMusicLock");
|
||||
@ -380,6 +418,10 @@ public final class PlaybackService extends Service
|
||||
synchronized (sWait) {
|
||||
sWait.notifyAll();
|
||||
}
|
||||
|
||||
mAccelFiltered = 0.0f;
|
||||
mAccelLast = SensorManager.GRAVITY_EARTH;
|
||||
setupSensor();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -456,6 +498,9 @@ public final class PlaybackService extends Service
|
||||
// we haven't registered the receiver yet
|
||||
}
|
||||
|
||||
if (mShakeAction != Action.Nothing)
|
||||
mSensorManager.unregisterListener(this);
|
||||
|
||||
if (mWakeLock != null && mWakeLock.isHeld())
|
||||
mWakeLock.release();
|
||||
|
||||
@ -473,6 +518,17 @@ public final class PlaybackService extends Service
|
||||
return sSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the accelerometer.
|
||||
*/
|
||||
private void setupSensor()
|
||||
{
|
||||
if (mShakeAction == Action.Nothing || (mState & FLAG_PLAYING) == 0)
|
||||
mSensorManager.unregisterListener(this);
|
||||
else
|
||||
mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_UI);
|
||||
}
|
||||
|
||||
private void loadPreference(String key)
|
||||
{
|
||||
SharedPreferences settings = getSettings(this);
|
||||
@ -515,6 +571,11 @@ public final class PlaybackService extends Service
|
||||
mStockBroadcast = settings.getBoolean(key, false);
|
||||
} else if ("headset_play".equals(key)) {
|
||||
mHeadsetPlay = settings.getBoolean(key, false);
|
||||
} else if ("enable_shake".equals(key) || "shake_action".equals(key)) {
|
||||
mShakeAction = settings.getBoolean("enable_shake", false) ? Action.getAction(settings, "shake_action", Action.NextSong) : Action.Nothing;
|
||||
setupSensor();
|
||||
} else if ("shake_threshold".equals(key)) {
|
||||
mShakeThreshold = settings.getInt("shake_threshold", 80) / 10.0f;
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
|
||||
@ -603,6 +664,8 @@ public final class PlaybackService extends Service
|
||||
if (mWakeLock != null && mWakeLock.isHeld())
|
||||
mWakeLock.release();
|
||||
}
|
||||
|
||||
setupSensor();
|
||||
}
|
||||
|
||||
if ((toggled & FLAG_NO_MEDIA) != 0 && (state & FLAG_NO_MEDIA) != 0) {
|
||||
@ -1547,4 +1610,114 @@ public final class PlaybackService extends Service
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSensorChanged(SensorEvent se)
|
||||
{
|
||||
double x = se.values[0];
|
||||
double y = se.values[1];
|
||||
double z = se.values[2];
|
||||
|
||||
float accel = (float)Math.sqrt(x*x + y*y + z*z);
|
||||
float delta = accel - mAccelLast;
|
||||
mAccelLast = accel;
|
||||
|
||||
float filtered = mAccelFiltered * 0.9f + delta;
|
||||
mAccelFiltered = filtered;
|
||||
|
||||
if (filtered > mShakeThreshold) {
|
||||
long now = SystemClock.elapsedRealtime();
|
||||
if (now - mLastShakeTime > MIN_SHAKE_PERIOD) {
|
||||
mLastShakeTime = now;
|
||||
performAction(mShakeAction, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccuracyChanged(Sensor sensor, int accuracy)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the given action.
|
||||
*
|
||||
* @param action The action to execute.
|
||||
* @param receiver Optional. If non-null, update the PlaybackActivity with
|
||||
* new song or state from the executed action. The activity will still be
|
||||
* updated by the broadcast if not passed here; passing it just makes the
|
||||
* update immediate.
|
||||
*/
|
||||
public void performAction(Action action, PlaybackActivity receiver)
|
||||
{
|
||||
switch (action) {
|
||||
case Nothing:
|
||||
break;
|
||||
case Library:
|
||||
Intent intent = new Intent(this, LibraryActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
startActivity(intent);
|
||||
break;
|
||||
case PlayPause: {
|
||||
int state = playPause();
|
||||
if (receiver != null)
|
||||
receiver.setState(state);
|
||||
break;
|
||||
}
|
||||
case NextSong: {
|
||||
Song song = shiftCurrentSong(SongTimeline.SHIFT_NEXT_SONG);
|
||||
if (receiver != null)
|
||||
receiver.setSong(song);
|
||||
break;
|
||||
}
|
||||
case PreviousSong: {
|
||||
Song song = shiftCurrentSong(SongTimeline.SHIFT_PREVIOUS_SONG);
|
||||
if (receiver != null)
|
||||
receiver.setSong(song);
|
||||
break;
|
||||
}
|
||||
case NextAlbum: {
|
||||
Song song = shiftCurrentSong(SongTimeline.SHIFT_NEXT_ALBUM);
|
||||
if (receiver != null)
|
||||
receiver.setSong(song);
|
||||
break;
|
||||
}
|
||||
case PreviousAlbum: {
|
||||
Song song = shiftCurrentSong(SongTimeline.SHIFT_PREVIOUS_ALBUM);
|
||||
if (receiver != null)
|
||||
receiver.setSong(song);
|
||||
break;
|
||||
}
|
||||
case Repeat: {
|
||||
int state = cycleFinishAction();
|
||||
if (receiver != null)
|
||||
receiver.setState(state);
|
||||
break;
|
||||
}
|
||||
case Shuffle: {
|
||||
int state = cycleShuffle();
|
||||
if (receiver != null)
|
||||
receiver.setState(state);
|
||||
break;
|
||||
}
|
||||
case EnqueueAlbum:
|
||||
enqueueFromCurrent(MediaUtils.TYPE_ALBUM);
|
||||
break;
|
||||
case EnqueueArtist:
|
||||
enqueueFromCurrent(MediaUtils.TYPE_ARTIST);
|
||||
break;
|
||||
case EnqueueGenre:
|
||||
enqueueFromCurrent(MediaUtils.TYPE_GENRE);
|
||||
break;
|
||||
case ClearQueue:
|
||||
clearQueue();
|
||||
Toast.makeText(this, R.string.queue_cleared, Toast.LENGTH_SHORT).show();
|
||||
break;
|
||||
case ToggleControls:
|
||||
// Handled in FullPlaybackActivity.performAction
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid action: " + action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
103
src/org/kreed/vanilla/ShakeThresholdPreference.java
Normal file
103
src/org/kreed/vanilla/ShakeThresholdPreference.java
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Christopher Eby <kreed@kreed.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.kreed.vanilla;
|
||||
|
||||
import android.content.Context;
|
||||
import android.preference.DialogPreference;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* SeekBar preference to set the shake force threshold.
|
||||
*/
|
||||
public class ShakeThresholdPreference extends DialogPreference implements SeekBar.OnSeekBarChangeListener {
|
||||
/**
|
||||
* TextView to display current threshold.
|
||||
*/
|
||||
private TextView mValueText;
|
||||
|
||||
public ShakeThresholdPreference(Context context, AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getSummary()
|
||||
{
|
||||
return getSummary(getPersistedInt(80));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the summary for the given value.
|
||||
*
|
||||
* @param value The force threshold.
|
||||
* @return A string representation of the threshold.
|
||||
*/
|
||||
private static String getSummary(int value)
|
||||
{
|
||||
return String.valueOf(value / 10.0f);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View onCreateDialogView()
|
||||
{
|
||||
View view = super.onCreateDialogView();
|
||||
int value = getPersistedInt(80);
|
||||
|
||||
mValueText = (TextView)view.findViewById(R.id.value);
|
||||
mValueText.setText(getSummary(value));
|
||||
|
||||
SeekBar seekBar = (SeekBar)view.findViewById(R.id.seek_bar);
|
||||
seekBar.setMax(150);
|
||||
seekBar.setProgress(value);
|
||||
seekBar.setOnSeekBarChangeListener(this);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDialogClosed(boolean positiveResult)
|
||||
{
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
|
||||
{
|
||||
if (fromUser) {
|
||||
mValueText.setText(getSummary(progress));
|
||||
persistInt(progress);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar)
|
||||
{
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user