Renamed package to gramophone

This commit is contained in:
Karim Abou Zeid 2015-03-05 16:50:16 +01:00
commit c28a75c61a
95 changed files with 412 additions and 415 deletions

View file

@ -0,0 +1,42 @@
package com.kabouzeid.gramophone.helper;
import android.content.Context;
import android.content.pm.PackageManager;
import android.util.Log;
import com.afollestad.materialdialogs.MaterialDialog;
import com.kabouzeid.gramophone.R;
/**
* Created by karim on 05.02.15.
*/
public class AboutDeveloperDialogHelper {
public static final String TAG = AboutDeveloperDialogHelper.class.getSimpleName();
public static MaterialDialog getDialog(final Context context) {
MaterialDialog dialog = new MaterialDialog.Builder(context)
.title(context.getResources().getString(R.string.app_name) + " " + getCurrentVersionName(context))
.iconRes(R.drawable.ic_launcher)
.content(context.getResources().getText(R.string.credits))
.positiveText(context.getResources().getString(R.string.ok))
.callback(new MaterialDialog.ButtonCallback() {
@Override
public void onPositive(MaterialDialog dialog) {
super.onPositive(dialog);
dialog.dismiss();
}
})
.build();
return dialog;
}
private static String getCurrentVersionName(final Context context) {
String versionName = "";
try {
versionName = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "Unable to get current app version number.", e);
}
return versionName;
}
}

View file

@ -0,0 +1,285 @@
package com.kabouzeid.gramophone.helper;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.util.Log;
import com.kabouzeid.gramophone.App;
import com.kabouzeid.gramophone.interfaces.OnMusicRemoteEventListener;
import com.kabouzeid.gramophone.misc.AppKeys;
import com.kabouzeid.gramophone.model.MusicRemoteEvent;
import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.service.MusicService;
import com.kabouzeid.gramophone.util.InternalStorageUtil;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Created by karim on 29.11.14.
*/
public class MusicPlayerRemote implements OnMusicRemoteEventListener {
private static final String TAG = MusicPlayerRemote.class.getSimpleName();
private App app;
private int position = -1;
private List<Song> playingQueue;
private List<Song> restoredOriginalQueue;
private List<OnMusicRemoteEventListener> onMusicRemoteEventListeners;
private MusicService musicService;
private Intent musicServiceIntent;
private boolean musicBound = false;
private ServiceConnection musicConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
MusicService.MusicBinder binder = (MusicService.MusicBinder) service;
musicService = binder.getService();
musicBound = true;
musicService.restorePreviousState(restoredOriginalQueue, playingQueue, position);
musicService.addOnMusicRemoteEventListener(MusicPlayerRemote.this);
notifyOnMusicRemoteEventListeners(MusicRemoteEvent.SERVICE_CONNECTED);
}
@Override
public void onServiceDisconnected(ComponentName name) {
musicBound = false;
notifyOnMusicRemoteEventListeners(MusicRemoteEvent.SERVICE_DISCONNECTED);
}
};
public MusicPlayerRemote(Context context) {
app = (App) context.getApplicationContext();
playingQueue = new ArrayList<>();
restoredOriginalQueue = new ArrayList<>();
onMusicRemoteEventListeners = new ArrayList<>();
startAndBindService();
}
private void startAndBindService() {
if (musicServiceIntent == null) {
musicServiceIntent = new Intent(app, MusicService.class);
app.bindService(musicServiceIntent, musicConnection, Context.BIND_AUTO_CREATE);
app.startService(musicServiceIntent);
}
}
public boolean playSongAt(final int position) {
if (musicBound) {
musicService.playSongAt(position);
}
return false;
}
public void pauseSong() {
if (musicBound) {
musicService.pausePlaying();
}
}
public void playNextSong() {
if (musicBound) {
musicService.playNextSong();
}
}
public void playPreviousSong() {
if (musicBound) {
musicService.back();
}
}
public void back() {
if (musicBound) {
musicService.back();
}
}
public boolean isPlaying() {
if (musicBound) {
return musicService.isPlaying();
}
return false;
}
public void resumePlaying() {
if (musicBound) {
musicService.resumePlaying();
}
}
public long getCurrentSongId() {
if (musicBound) {
return musicService.getCurrentSongId();
}
try {
return playingQueue.get(position).id;
} catch (Exception e) {
return -1;
}
}
public void openQueue(final List<Song> playingQueue, final int startPosition, final boolean startPlaying) {
this.playingQueue = playingQueue;
if (musicBound) {
musicService.openQueue(this.playingQueue, startPosition, startPlaying);
}
}
public Song getCurrentSong() {
final int position = getPosition();
if (position != -1) {
return getPlayingQueue().get(position);
}
return new Song();
}
public int getPosition() {
if (musicBound) {
position = musicService.getPosition();
}
return position;
}
private void setPosition(int position) {
this.position = position;
if (musicBound) {
musicService.setPosition(position);
}
}
public List<Song> getPlayingQueue() {
if (musicBound) {
playingQueue = musicService.getPlayingQueue();
}
return playingQueue;
}
public int getSongProgressMillis() {
if (isPlayerPrepared()) {
return musicService.getSongProgressMillis();
}
return -1;
}
public boolean isPlayerPrepared() {
if (musicBound) {
return musicService.isPlayerPrepared();
}
return false;
}
public int getSongDurationMillis() {
if (isPlayerPrepared()) {
return musicService.getSongDurationMillis();
}
return -1;
}
public boolean isMusicBound() {
return musicBound;
}
public void seekTo(int millis) {
if (musicBound) {
musicService.seekTo(millis);
}
}
public int getRepeatMode() {
if (musicBound) {
return musicService.getRepeatMode();
}
return app.getDefaultSharedPreferences().getInt(AppKeys.SP_REPEAT_MODE, 0);
}
public int getShuffleMode() {
if (musicBound) {
return musicService.getShuffleMode();
}
return app.getDefaultSharedPreferences().getInt(AppKeys.SP_SHUFFLE_MODE, 0);
}
public boolean cycleRepeatMode() {
if (musicBound) {
musicService.cycleRepeatMode();
return true;
}
return false;
}
public boolean toggleShuffleMode() {
if (musicBound) {
musicService.toggleShuffle();
return true;
}
return false;
}
public void moveSong(int from, int to) {
final int currentPosition = getPosition();
Song songToMove = getPlayingQueue().remove(from);
getPlayingQueue().add(to, songToMove);
if (from > currentPosition && to <= currentPosition) {
setPosition(getPosition() + 1);
} else if (from < currentPosition && to >= currentPosition) {
setPosition(getPosition() - 1);
} else if (from == currentPosition) {
setPosition(to);
}
}
@Override
public void onMusicRemoteEvent(MusicRemoteEvent event) {
notifyOnMusicRemoteEventListeners(event.getAction());
}
private void notifyOnMusicRemoteEventListeners(int event) {
MusicRemoteEvent musicRemoteEvent = new MusicRemoteEvent(event);
for (OnMusicRemoteEventListener listener : onMusicRemoteEventListeners) {
listener.onMusicRemoteEvent(musicRemoteEvent);
}
}
public void addOnMusicRemoteEventListener(OnMusicRemoteEventListener onMusicRemoteEventListener) {
onMusicRemoteEventListeners.add(onMusicRemoteEventListener);
}
public void removeOnMusicRemoteEventListener(OnMusicRemoteEventListener onMusicRemoteEventListener) {
onMusicRemoteEventListeners.remove(onMusicRemoteEventListener);
}
public void removeAllOnMusicRemoteEventListeners() {
onMusicRemoteEventListeners.clear();
}
@SuppressWarnings("unchecked")
public void restorePreviousState() {
try {
List restoredQueue = (ArrayList<Song>) InternalStorageUtil.readObject(app, AppKeys.IS_PLAYING_QUEUE);
List restoredOriginalQueue = (ArrayList<Song>) InternalStorageUtil.readObject(app, AppKeys.IS_ORIGINAL_PLAYING_QUEUE);
int restoredPosition = (int) InternalStorageUtil.readObject(app, AppKeys.IS_POSITION_IN_QUEUE);
if (musicBound) {
musicService.restorePreviousState(restoredOriginalQueue, restoredQueue, restoredPosition);
}
playingQueue = restoredQueue;
this.restoredOriginalQueue = restoredOriginalQueue;
position = restoredPosition;
notifyOnMusicRemoteEventListeners(MusicRemoteEvent.STATE_RESTORED);
Log.i(TAG, "restored last state");
} catch (IOException | ClassNotFoundException | ClassCastException e) {
Log.e(TAG, "error while restoring music service state", e);
playingQueue = new ArrayList<>();
position = -1;
}
}
}

View file

@ -0,0 +1,178 @@
package com.kabouzeid.gramophone.helper;
/**
* Created by karim on 27.12.14.
*/
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.support.v4.app.NotificationCompat;
import android.widget.RemoteViews;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.service.MusicService;
import com.kabouzeid.gramophone.ui.activities.MusicControllerActivity;
import com.kabouzeid.gramophone.util.MusicUtil;
import com.nostra13.universalimageloader.core.ImageLoader;
public class PlayingNotificationHelper {
public static final String TAG = PlayingNotificationHelper.class.getSimpleName();
public static final int NOTIFICATION_ID = 1337;
private final MusicService service;
private final NotificationManager notificationManager;
private Notification notification = null;
private RemoteViews notificationLayout;
private RemoteViews notificationLayoutExpanded;
public PlayingNotificationHelper(final MusicService service) {
this.service = service;
notificationManager = (NotificationManager) service
.getSystemService(Context.NOTIFICATION_SERVICE);
}
public void buildNotification(Song song, final boolean isPlaying) {
notificationLayout = new RemoteViews(service.getPackageName(),
R.layout.notification_playing);
notificationLayoutExpanded = new RemoteViews(service.getPackageName(),
R.layout.notification_playing_expanded);
setUpCollapsedLayout(song);
setUpExpandedLayout(song);
setUpPlaybackActions(isPlaying);
setUpExpandedPlaybackActions(isPlaying);
notification = new NotificationCompat.Builder(service)
.setSmallIcon(R.drawable.notification_icon)
.setContentIntent(getOpenMusicControllerPendingIntent())
.setCategory(NotificationCompat.CATEGORY_PROGRESS)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setContent(notificationLayout)
.build();
notification.bigContentView = notificationLayoutExpanded;
service.startForeground(NOTIFICATION_ID, notification);
}
private PendingIntent getOpenMusicControllerPendingIntent() {
Intent result = new Intent(service, MusicControllerActivity.class);
TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(service);
taskStackBuilder.addParentStack(MusicControllerActivity.class);
taskStackBuilder.addNextIntent(result);
return taskStackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
}
private void setUpExpandedPlaybackActions(boolean isPlaying) {
notificationLayoutExpanded.setOnClickPendingIntent(R.id.button_toggle_play_pause,
retrievePlaybackActions(1));
notificationLayoutExpanded.setOnClickPendingIntent(R.id.button_next,
retrievePlaybackActions(2));
notificationLayoutExpanded.setOnClickPendingIntent(R.id.button_prev,
retrievePlaybackActions(3));
notificationLayoutExpanded.setOnClickPendingIntent(R.id.button_quit,
retrievePlaybackActions(4));
notificationLayoutExpanded.setImageViewResource(R.id.button_toggle_play_pause,
isPlaying ? R.drawable.ic_pause_white_48dp : R.drawable.ic_play_arrow_white_48dp);
}
private void setUpPlaybackActions(boolean isPlaying) {
notificationLayout.setOnClickPendingIntent(R.id.button_toggle_play_pause,
retrievePlaybackActions(1));
notificationLayout.setOnClickPendingIntent(R.id.button_next,
retrievePlaybackActions(2));
notificationLayout.setOnClickPendingIntent(R.id.button_quit,
retrievePlaybackActions(4));
notificationLayout.setImageViewResource(R.id.button_toggle_play_pause,
isPlaying ? R.drawable.ic_pause_white_48dp : R.drawable.ic_play_arrow_white_48dp);
}
private PendingIntent retrievePlaybackActions(final int which) {
Intent action;
PendingIntent pendingIntent;
final ComponentName serviceName = new ComponentName(service, MusicService.class);
switch (which) {
case 1:
action = new Intent(MusicService.ACTION_TOGGLE_PLAYBACK);
action.setComponent(serviceName);
pendingIntent = PendingIntent.getService(service, 1, action, 0);
return pendingIntent;
case 2:
action = new Intent(MusicService.ACTION_SKIP);
action.setComponent(serviceName);
pendingIntent = PendingIntent.getService(service, 2, action, 0);
return pendingIntent;
case 3:
action = new Intent(MusicService.ACTION_REWIND);
action.setComponent(serviceName);
pendingIntent = PendingIntent.getService(service, 3, action, 0);
return pendingIntent;
case 4:
action = new Intent(MusicService.ACTION_QUIT);
action.setComponent(serviceName);
pendingIntent = PendingIntent.getService(service, 4, action, 0);
return pendingIntent;
default:
break;
}
return null;
}
private void setUpCollapsedLayout(Song song) {
loadAlbumArt(notificationLayout, MusicUtil.getAlbumArtUri(song.albumId).toString());
notificationLayout.setTextViewText(R.id.song_title, song.title);
notificationLayout.setTextViewText(R.id.song_artist, song.title);
}
private static void loadAlbumArt(RemoteViews notificationView, String albumArtUri) {
Bitmap albumArtBitmap = ImageLoader.getInstance().loadImageSync(albumArtUri);
if (albumArtBitmap == null) {
notificationView.setImageViewResource(R.id.album_art, R.drawable.default_album_art);
} else {
notificationView.setImageViewBitmap(R.id.album_art, albumArtBitmap);
}
}
private void setUpExpandedLayout(Song song) {
loadAlbumArt(notificationLayoutExpanded, MusicUtil.getAlbumArtUri(song.albumId).toString());
notificationLayoutExpanded.setTextViewText(R.id.song_title, song.title);
notificationLayoutExpanded.setTextViewText(R.id.song_artist, song.artistName);
notificationLayoutExpanded.setTextViewText(R.id.album_title, song.albumName);
}
public void killNotification() {
service.stopForeground(true);
notification = null;
}
public void updatePlayState(final boolean isPlaying) {
if (notification == null || notificationManager == null) {
return;
}
if (notificationLayout != null) {
notificationLayout.setImageViewResource(R.id.button_toggle_play_pause,
isPlaying ? R.drawable.ic_pause_white_48dp : R.drawable.ic_play_arrow_white_48dp);
}
if (notificationLayoutExpanded != null) {
notificationLayoutExpanded.setImageViewResource(R.id.button_toggle_play_pause,
isPlaying ? R.drawable.ic_pause_white_48dp : R.drawable.ic_play_arrow_white_48dp);
}
notificationManager.notify(NOTIFICATION_ID, notification);
}
}

View file

@ -0,0 +1,65 @@
package com.kabouzeid.gramophone.helper;
import android.content.Context;
import android.view.View;
import android.widget.AdapterView;
import com.afollestad.materialdialogs.MaterialDialog;
import com.kabouzeid.gramophone.App;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.adapter.PlayingQueueAdapter;
import com.kabouzeid.gramophone.adapter.songadapter.SongAdapter;
import com.kabouzeid.gramophone.model.Song;
import com.mobeta.android.dslv.DragSortListView;
import java.util.List;
/**
* Created by karim on 24.01.15.
*/
public class PlayingQueueDialogHelper {
public static MaterialDialog getDialog(Context context, SongAdapter.GoToAble goToAble) {
final App app = (App) context.getApplicationContext();
List<Song> playingQueue = app.getMusicPlayerRemote().getPlayingQueue();
if (playingQueue.isEmpty()) {
return null;
}
MaterialDialog dialog = new MaterialDialog.Builder(context)
.title(context.getResources().getString(R.string.label_current_playing_queue))
.customView(R.layout.dialog_playlist, false)
.positiveText(context.getResources().getString(R.string.close))
.negativeText(context.getResources().getString(R.string.save_as_playlist))
.callback(new MaterialDialog.ButtonCallback() {
@Override
public void onPositive(MaterialDialog dialog) {
super.onPositive(dialog);
dialog.dismiss();
}
@Override
public void onNegative(MaterialDialog dialog) {
super.onNegative(dialog);
}
})
.build();
final DragSortListView dragSortListView = (DragSortListView) dialog.getCustomView().findViewById(R.id.dragSortListView);
final PlayingQueueAdapter playingQueueAdapter = new PlayingQueueAdapter(context, goToAble, playingQueue);
dragSortListView.setAdapter(playingQueueAdapter);
dragSortListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
app.getMusicPlayerRemote().playSongAt(position);
playingQueueAdapter.notifyDataSetChanged();
}
});
dragSortListView.setDropListener(new DragSortListView.DropListener() {
@Override
public void drop(int from, int to) {
app.getMusicPlayerRemote().moveSong(from, to);
playingQueueAdapter.notifyDataSetChanged();
}
});
return dialog;
}
}

View file

@ -0,0 +1,21 @@
package com.kabouzeid.gramophone.helper;
import com.kabouzeid.gramophone.model.Song;
import java.util.Collections;
import java.util.List;
/**
* Created by karim on 24.01.15.
*/
public class ShuffleHelper {
public static void makeShuffleList(List<Song> listToShuffle, final int current) {
if (current >= 0) {
Song song = listToShuffle.remove(current);
Collections.shuffle(listToShuffle);
listToShuffle.add(0, song);
} else {
Collections.shuffle(listToShuffle);
}
}
}

View file

@ -0,0 +1,84 @@
package com.kabouzeid.gramophone.helper;
import android.content.Context;
import android.text.Html;
import android.text.Spanned;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import com.afollestad.materialdialogs.MaterialDialog;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.util.MusicUtil;
import com.kabouzeid.gramophone.util.Util;
import org.jaudiotagger.audio.AudioFile;
import org.jaudiotagger.audio.AudioFileIO;
import org.jaudiotagger.audio.AudioHeader;
import org.jaudiotagger.audio.exceptions.CannotReadException;
import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException;
import org.jaudiotagger.audio.exceptions.ReadOnlyFileException;
import org.jaudiotagger.tag.TagException;
import java.io.File;
import java.io.IOException;
/**
* Created by karim on 19.01.15.
*/
public class SongDetailDialogHelper {
public static final String TAG = SongDetailDialogHelper.class.getSimpleName();
public static MaterialDialog getDialog(final Context context, final File songFile) {
MaterialDialog dialog = new MaterialDialog.Builder(context)
.customView(R.layout.dialog_file_details, true)
.title(context.getResources().getString(R.string.label_details))
.positiveText(context.getResources().getString(R.string.ok))
.callback(new MaterialDialog.ButtonCallback() {
@Override
public void onPositive(MaterialDialog dialog) {
dialog.dismiss();
}
})
.build();
View dialogView = dialog.getCustomView();
final TextView fileName = (TextView) dialogView.findViewById(R.id.file_name);
final TextView filePath = (TextView) dialogView.findViewById(R.id.file_path);
final TextView fileSize = (TextView) dialogView.findViewById(R.id.file_size);
final TextView fileFormat = (TextView) dialogView.findViewById(R.id.file_format);
final TextView trackLength = (TextView) dialogView.findViewById(R.id.track_length);
final TextView bitRate = (TextView) dialogView.findViewById(R.id.bitrate);
final TextView samplingRate = (TextView) dialogView.findViewById(R.id.sampling_rate);
fileName.setText(makeTextWithTitle(context, R.string.label_file_name, "-"));
filePath.setText(makeTextWithTitle(context, R.string.label_file_path, "-"));
fileSize.setText(makeTextWithTitle(context, R.string.label_file_size, "-"));
fileFormat.setText(makeTextWithTitle(context, R.string.label_file_format, "-"));
trackLength.setText(makeTextWithTitle(context, R.string.label_track_length, "-"));
bitRate.setText(makeTextWithTitle(context, R.string.label_bit_rate, "-"));
samplingRate.setText(makeTextWithTitle(context, R.string.label_sampling_rate, "-"));
try {
if (songFile != null && songFile.exists()) {
AudioFile audioFile = AudioFileIO.read(songFile);
AudioHeader audioHeader = audioFile.getAudioHeader();
fileName.setText(makeTextWithTitle(context, R.string.label_file_name, songFile.getName()));
filePath.setText(makeTextWithTitle(context, R.string.label_file_path, songFile.getAbsolutePath()));
fileSize.setText(makeTextWithTitle(context, R.string.label_file_size, Util.getFileSizeString(songFile.length())));
fileFormat.setText(makeTextWithTitle(context, R.string.label_file_format, audioHeader.getFormat()));
trackLength.setText(makeTextWithTitle(context, R.string.label_track_length, MusicUtil.getReadableDurationString(audioHeader.getTrackLength() * 1000)));
bitRate.setText(makeTextWithTitle(context, R.string.label_bit_rate, audioHeader.getBitRate() + " kb/s"));
samplingRate.setText(makeTextWithTitle(context, R.string.label_sampling_rate, audioHeader.getSampleRate() + " Hz"));
}
} catch (CannotReadException | IOException | TagException | ReadOnlyFileException | InvalidAudioFrameException e) {
Log.e(TAG, "error while reading the song file", e);
}
return dialog;
}
private static Spanned makeTextWithTitle(Context context, int titleResId, String text) {
return Html.fromHtml("<b>" + context.getResources().getString(titleResId) + ": " + "</b>" + text);
}
}