/*
* Copyright (C) 2015 Naman Dwivedi
*
* Licensed under the GNU General Public License v3
*
* This is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*/
package com.naman14.timber.utils;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Color;
import android.media.MediaMetadataRetriever;
import android.media.audiofx.AudioEffect;
import android.net.Uri;
import android.os.Build;
import android.provider.BaseColumns;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.util.TypedValue;
import android.widget.Toast;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.naman14.timber.MusicPlayer;
import com.naman14.timber.R;
import com.naman14.timber.provider.RecentStore;
import com.naman14.timber.provider.SongPlayCount;
import java.io.File;
public class TimberUtils {
public static final String MUSIC_ONLY_SELECTION = MediaStore.Audio.AudioColumns.IS_MUSIC + "=1"
+ " AND " + MediaStore.Audio.AudioColumns.TITLE + " != ''";
public static boolean isMarshmallow() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
}
public static boolean isLollipop() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
}
public static boolean isJellyBeanMR2() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2;
}
public static boolean isJellyBean() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
}
public static boolean isJellyBeanMR1() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1;
}
public static Uri getAlbumArtUri(long albumId) {
return ContentUris.withAppendedId(Uri.parse("content://media/external/audio/albumart"), albumId);
}
public static String getAlbumArtForFile(String filePath) {
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
mmr.setDataSource(filePath);
return mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
}
public static final String makeCombinedString(final Context context, final String first,
final String second) {
final String formatter = context.getResources().getString(R.string.combine_two_strings);
return String.format(formatter, first, second);
}
public static final String makeLabel(final Context context, final int pluralInt,
final int number) {
return context.getResources().getQuantityString(pluralInt, number, number);
}
public static final String makeShortTimeString(final Context context, long secs) {
long hours, mins;
hours = secs / 3600;
secs %= 3600;
mins = secs / 60;
secs %= 60;
final String durationFormat = context.getResources().getString(
hours == 0 ? R.string.durationformatshort : R.string.durationformatlong);
return String.format(durationFormat, hours, mins, secs);
}
public static int getActionBarHeight(Context context) {
int mActionBarHeight;
TypedValue mTypedValue = new TypedValue();
context.getTheme().resolveAttribute(R.attr.actionBarSize, mTypedValue, true);
mActionBarHeight = TypedValue.complexToDimensionPixelSize(mTypedValue.data, context.getResources().getDisplayMetrics());
return mActionBarHeight;
}
public static final int getSongCountForPlaylist(final Context context, final long playlistId) {
Cursor c = context.getContentResolver().query(
MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId),
new String[]{BaseColumns._ID}, MUSIC_ONLY_SELECTION, null, null);
if (c != null) {
int count = 0;
if (c.moveToFirst()) {
count = c.getCount();
}
c.close();
c = null;
return count;
}
return 0;
}
public static boolean hasEffectsPanel(final Activity activity) {
final PackageManager packageManager = activity.getPackageManager();
return packageManager.resolveActivity(createEffectsIntent(),
PackageManager.MATCH_DEFAULT_ONLY) != null;
}
public static Intent createEffectsIntent() {
final Intent effects = new Intent(AudioEffect.ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL);
effects.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, MusicPlayer.getAudioSessionId());
return effects;
}
public static int getBlackWhiteColor(int color) {
double darkness = 1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255;
if (darkness >= 0.5) {
return Color.WHITE;
} else return Color.BLACK;
}
public enum IdType {
NA(0),
Artist(1),
Album(2),
Playlist(3);
public final int mId;
IdType(final int id) {
mId = id;
}
public static IdType getTypeById(int id) {
for (IdType type : values()) {
if (type.mId == id) {
return type;
}
}
throw new IllegalArgumentException("Unrecognized id: " + id);
}
}
public enum PlaylistType {
LastAdded(-1, R.string.playlist_last_added),
RecentlyPlayed(-2, R.string.playlist_recently_played),
TopTracks(-3, R.string.playlist_top_tracks);
public long mId;
public int mTitleId;
PlaylistType(long id, int titleId) {
mId = id;
mTitleId = titleId;
}
public static PlaylistType getTypeById(long id) {
for (PlaylistType type : PlaylistType.values()) {
if (type.mId == id) {
return type;
}
}
return null;
}
}
public static void removeFromPlaylist(final Context context, final long id,
final long playlistId) {
final Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId);
final ContentResolver resolver = context.getContentResolver();
resolver.delete(uri, MediaStore.Audio.Playlists.Members.AUDIO_ID + " = ? ", new String[]{
Long.toString(id)
});
}
public static void clearTopTracks(Context context) {
SongPlayCount.getInstance(context).deleteAll();
}
public static void clearRecent(Context context) {
RecentStore.getInstance(context).deleteAll();
}
public static void clearLastAdded(Context context) {
PreferencesUtility.getInstance(context)
.setLastAddedCutoff(System.currentTimeMillis());
}
public static void showDeleteDialog(final Context context, final String name, final long[] list, final RecyclerView.Adapter adapter, final int pos) {
new MaterialDialog.Builder(context)
.title("Delete song?")
.content("Are you sure you want to delete " + name + " ?")
.positiveText("Delete")
.negativeText("Cancel")
.onPositive(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
TimberUtils.deleteTracks(context, list);
adapter.notifyItemRemoved(pos);
}
})
.onNegative(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
dialog.dismiss();
}
})
.show();
}
public static void deleteTracks(final Context context, final long[] list) {
final String[] projection = new String[]{
BaseColumns._ID, MediaStore.MediaColumns.DATA, MediaStore.Audio.AudioColumns.ALBUM_ID
};
final StringBuilder selection = new StringBuilder();
selection.append(BaseColumns._ID + " IN (");
for (int i = 0; i < list.length; i++) {
selection.append(list[i]);
if (i < list.length - 1) {
selection.append(",");
}
}
selection.append(")");
final Cursor c = context.getContentResolver().query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, projection, selection.toString(),
null, null);
if (c != null) {
// Step 1: Remove selected tracks from the current playlist, as well
// as from the album art cache
c.moveToFirst();
while (!c.isAfterLast()) {
// Remove from current playlist
final long id = c.getLong(0);
MusicPlayer.removeTrack(id);
// Remove the track from the play count
SongPlayCount.getInstance(context).removeItem(id);
// Remove any items in the recents database
RecentStore.getInstance(context).removeItem(id);
c.moveToNext();
}
// Step 2: Remove selected tracks from the database
context.getContentResolver().delete(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
selection.toString(), null);
// Step 3: Remove files from card
c.moveToFirst();
while (!c.isAfterLast()) {
final String name = c.getString(1);
final File f = new File(name);
try { // File.delete can throw a security exception
if (!f.delete()) {
// I'm not sure if we'd ever get here (deletion would
// have to fail, but no exception thrown)
Log.e("MusicUtils", "Failed to delete file " + name);
}
c.moveToNext();
} catch (final SecurityException ex) {
c.moveToNext();
}
}
c.close();
}
final String message = makeLabel(context, R.plurals.NNNtracksdeleted, list.length);
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
context.getContentResolver().notifyChange(Uri.parse("content://media"), null);
MusicPlayer.refresh();
}
public static void shareTrack(final Context context, long id) {
final String[] projection = new String[]{
BaseColumns._ID, MediaStore.MediaColumns.DATA, MediaStore.Audio.AudioColumns.ALBUM_ID
};
final StringBuilder selection = new StringBuilder();
selection.append(BaseColumns._ID + " IN (");
selection.append(id);
selection.append(")");
final Cursor c = context.getContentResolver().query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, projection, selection.toString(),
null, null);
if (c == null) {
return;
}
c.moveToFirst();
try {
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("audio/*");
share.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(c.getString(1))));
context.startActivity(Intent.createChooser(share, "Share"));
c.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}