Make long pressing song info display additional metadata

This commit is contained in:
Christopher Eby 2012-03-09 15:32:44 -06:00
parent a0b1628c2c
commit 4669b8ea37
4 changed files with 242 additions and 8 deletions

View File

@ -85,6 +85,32 @@ THE SOFTWARE.
android:paddingBottom="5dip"
android:paddingLeft="15dip"
android:paddingRight="15dip" />
<TableLayout
android:id="@+id/extra_info"
android:visibility="gone"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TableRow>
<TextView android:text="@string/genre" />
<TextView android:id="@+id/genre" android:paddingLeft="5dip" />
</TableRow>
<TableRow>
<TextView android:text="@string/track" />
<TextView android:id="@+id/track" android:paddingLeft="5dip" />
</TableRow>
<TableRow>
<TextView android:text="@string/year" />
<TextView android:id="@+id/year" android:paddingLeft="5dip" />
</TableRow>
<TableRow>
<TextView android:text="@string/composer" />
<TextView android:id="@+id/composer" android:paddingLeft="5dip" />
</TableRow>
<TableRow>
<TextView android:text="@string/format" />
<TextView android:id="@+id/format" android:paddingLeft="5dip" />
</TableRow>
</TableLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/controls_bottom"

View File

@ -41,6 +41,10 @@ THE SOFTWARE.
<string name="queue_cleared">Queue cleared.</string>
<string name="cover_art">Cover art</string>
<string name="close_notification">Close notification</string>
<string name="genre">Genre</string>
<string name="track">Track</string>
<string name="composer">Composer</string>
<string name="format">Format</string>
<!-- New Playlist Dialog -->
<string name="choose_playlist_name">Choose Playlist Name</string>

View File

@ -0,0 +1,62 @@
/*
* 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.media.MediaMetadataRetriever;
/**
* Wrapper around MediaMetadataRetriever to allow compatibility with older
* versions of Android.
*/
public class CompatMetadata {
/**
* The wrapped MediaMetadataRetriever instance.
*/
private final MediaMetadataRetriever mData;
/**
* Create an MediaMetadataRetriever attached to the file at the given path.
*/
public CompatMetadata(String path)
{
MediaMetadataRetriever data = new MediaMetadataRetriever();
data.setDataSource(path);
mData = data;
}
/**
* Call {@link MediaMetadataRetriever#extractMetadata(int)}.
*/
public String extractMetadata(int keyCode)
{
return mData.extractMetadata(keyCode);
}
/**
* Call {@link MediaMetadataRetriever#release()}.
*/
public void release()
{
mData.release();
}
}

View File

@ -25,6 +25,7 @@ package org.kreed.vanilla;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.media.MediaMetadataRetriever;
import android.os.Build;
import android.os.Bundle;
import android.os.Message;
@ -39,6 +40,7 @@ import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TableLayout;
import android.widget.TextView;
/**
@ -58,6 +60,7 @@ public class FullPlaybackActivity extends PlaybackActivity
private SeekBar mSeekBar;
private TextView mElapsedView;
private TextView mDurationView;
private TableLayout mExtraInfo;
private TextView mTitle;
private TextView mAlbum;
@ -67,7 +70,10 @@ public class FullPlaybackActivity extends PlaybackActivity
* True if the controls are visible (play, next, seek bar, etc).
*/
private boolean mControlsVisible;
/**
* True if the extra info is visible.
*/
private boolean mExtraInfoVisible;
/**
* Current song duration in milliseconds.
*/
@ -92,6 +98,17 @@ public class FullPlaybackActivity extends PlaybackActivity
*/
private Song mCurrentSong;
private String mGenre;
private TextView mGenreView;
private String mTrack;
private TextView mTrackView;
private String mYear;
private TextView mYearView;
private String mComposer;
private TextView mComposerView;
private String mFormat;
private TextView mFormatView;
@Override
public void onCreate(Bundle icicle)
{
@ -139,8 +156,10 @@ public class FullPlaybackActivity extends PlaybackActivity
nextButton.setOnClickListener(this);
View controlsTop = findViewById(R.id.controls_top);
if (controlsTop != null)
if (controlsTop != null) {
controlsTop.setOnClickListener(this);
controlsTop.setOnLongClickListener(this);
}
mTitle = (TextView)findViewById(R.id.title);
mAlbum = (TextView)findViewById(R.id.album);
@ -152,6 +171,13 @@ public class FullPlaybackActivity extends PlaybackActivity
mSeekBar.setMax(1000);
mSeekBar.setOnSeekBarChangeListener(this);
mExtraInfo = (TableLayout)findViewById(R.id.extra_info);
mGenreView = (TextView)findViewById(R.id.genre);
mTrackView = (TextView)findViewById(R.id.track);
mYearView = (TextView)findViewById(R.id.year);
mComposerView = (TextView)findViewById(R.id.composer);
mFormatView = (TextView)findViewById(R.id.format);
mShuffleButton = (ImageButton)findViewById(R.id.shuffle);
mShuffleButton.setOnClickListener(this);
registerForContextMenu(mShuffleButton);
@ -160,6 +186,7 @@ public class FullPlaybackActivity extends PlaybackActivity
registerForContextMenu(mEndButton);
setControlsVisible(settings.getBoolean("visible_controls", true));
setExtraInfoVisible(settings.getBoolean("visible_extra_info", false));
setDuration(0);
}
@ -269,6 +296,10 @@ public class FullPlaybackActivity extends PlaybackActivity
mCurrentSong = song;
updateProgress();
if (mExtraInfoVisible) {
mHandler.sendEmptyMessage(MSG_LOAD_EXTRA_INFO);
}
}
/**
@ -389,7 +420,9 @@ public class FullPlaybackActivity extends PlaybackActivity
}
/**
* Toggles the visibility of the playback controls.
* Set the visibility of the controls views.
*
* @param visible True to show, false to hide
*/
private void setControlsVisible(boolean visible)
{
@ -406,6 +439,89 @@ public class FullPlaybackActivity extends PlaybackActivity
}
}
/**
* Set the visibility of the extra metadata view.
*
* @param visible True to show, false to hide
*/
private void setExtraInfoVisible(boolean visible)
{
if (mExtraInfo == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD_MR1)
return;
mExtraInfo.setVisibility(visible ? View.VISIBLE : View.GONE);
mExtraInfoVisible = visible;
if (visible && !mHandler.hasMessages(MSG_LOAD_EXTRA_INFO)) {
mHandler.sendEmptyMessage(MSG_LOAD_EXTRA_INFO);
}
}
/**
* Retrieve the extra metadata for the current song.
*/
private void loadExtraInfo()
{
Song song = mCurrentSong;
if (song == null) {
mGenre = null;
mTrack = null;
mYear = null;
mComposer = null;
mFormat = null;
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD_MR1) {
CompatMetadata data = new CompatMetadata(song.path);
mGenre = data.extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE);
mTrack = data.extractMetadata(MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER);
String composer = data.extractMetadata(MediaMetadataRetriever.METADATA_KEY_COMPOSER);
if (composer == null)
composer = data.extractMetadata(MediaMetadataRetriever.METADATA_KEY_WRITER);
mComposer = composer;
String year = data.extractMetadata(MediaMetadataRetriever.METADATA_KEY_YEAR);
if (year == null || "0".equals(year)) {
year = null;
} else {
int dash = year.indexOf('-');
if (dash != -1)
year = year.substring(0, dash);
}
mYear = year;
StringBuilder sb = new StringBuilder(12);
sb.append(decodeMimeType(data.extractMetadata(MediaMetadataRetriever.METADATA_KEY_MIMETYPE)));
String bitrate = data.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE);
if (bitrate.length() > 3) {
sb.append(' ');
sb.append(bitrate.substring(0, bitrate.length() - 3));
sb.append("kbps");
}
mFormat = sb.toString();
data.release();
}
mUiHandler.sendEmptyMessage(MSG_COMMIT_INFO);
}
/**
* Decode the given mime type into a more human-friendly description.
*/
private String decodeMimeType(String mime)
{
if ("audio/mpeg".equals(mime)) {
return "MP3";
} else if ("audio/mp4".equals(mime)) {
return "AAC";
} else if ("audio/vorbis".equals(mime)) {
return "Ogg Vorbis";
} else if ("audio/flac".equals(mime)) {
return "FLAC";
}
return mime;
}
/**
* Update the seekbar progress with the current song progress. This must be
* called on the UI Handler.
@ -415,21 +531,40 @@ public class FullPlaybackActivity extends PlaybackActivity
* Save the hidden_controls preference to storage.
*/
private static final int MSG_SAVE_CONTROLS = 14;
/**
* Call {@link #loadExtraInfo()}.
*/
private static final int MSG_LOAD_EXTRA_INFO = 15;
/**
* Pass obj to mExtraInfo.setText()
*/
private static final int MSG_COMMIT_INFO = 16;
@Override
public boolean handleMessage(Message message)
{
switch (message.what) {
case MSG_SAVE_CONTROLS: {
SharedPreferences settings = PlaybackService.getSettings(this);
SharedPreferences.Editor editor = settings.edit();
SharedPreferences.Editor editor = PlaybackService.getSettings(this).edit();
editor.putBoolean("visible_controls", mControlsVisible);
editor.putBoolean("visible_extra_info", mExtraInfoVisible);
editor.commit();
break;
}
case MSG_UPDATE_PROGRESS:
updateProgress();
break;
case MSG_LOAD_EXTRA_INFO:
loadExtraInfo();
break;
case MSG_COMMIT_INFO: {
mGenreView.setText(mGenre);
mTrackView.setText(mTrack);
mYearView.setText(mYear);
mComposerView.setText(mComposer);
mFormatView.setText(mFormat);
break;
}
default:
return super.handleMessage(message);
}
@ -483,11 +618,18 @@ public class FullPlaybackActivity extends PlaybackActivity
@Override
public boolean onLongClick(View view)
{
if (view.getId() == R.id.cover_view) {
switch (view.getId()) {
case R.id.cover_view:
performAction(mCoverLongPressAction);
return true;
break;
case R.id.controls_top:
setExtraInfoVisible(!mExtraInfoVisible);
mHandler.sendEmptyMessage(MSG_SAVE_CONTROLS);
break;
default:
return false;
}
return false;
return true;
}
}