Playing queue dialog finished

- rearranged code structure
This commit is contained in:
Karim Abou Zeid 2015-01-27 16:15:45 +01:00
commit 9ba8a07383
16 changed files with 254 additions and 123 deletions

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.kabouzeid.materialmusic"
xmlns:android="http://schemas.android.com/apk/res/android">
<manifest
package="com.kabouzeid.materialmusic"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

View file

@ -1,17 +1,26 @@
package com.kabouzeid.materialmusic.adapter;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.PopupMenu;
import android.widget.TextView;
import com.kabouzeid.materialmusic.App;
import com.kabouzeid.materialmusic.R;
import com.kabouzeid.materialmusic.adapter.songadapter.SongAdapter;
import com.kabouzeid.materialmusic.helper.SongDetailDialogHelper;
import com.kabouzeid.materialmusic.loader.SongFileLoader;
import com.kabouzeid.materialmusic.misc.AppKeys;
import com.kabouzeid.materialmusic.model.Song;
import com.kabouzeid.materialmusic.ui.activities.tageditor.SongTagEditorActivity;
import java.io.File;
import java.util.List;
/**
@ -20,11 +29,13 @@ import java.util.List;
public class PlayingQueueAdapter extends ArrayAdapter<Song> {
private Context context;
private App app;
private SongAdapter.GoToAble goToAble;
public PlayingQueueAdapter(Context context, List<Song> playList) {
public PlayingQueueAdapter(Context context, SongAdapter.GoToAble goToAble, List<Song> playList) {
super(context, R.layout.item_playlist, playList);
this.context = context;
app = (App) context.getApplicationContext();
this.goToAble = goToAble;
}
@Override
@ -35,6 +46,7 @@ public class PlayingQueueAdapter extends ArrayAdapter<Song> {
}
final TextView title = (TextView) convertView.findViewById(R.id.song_title);
final ImageView playingIndicator = (ImageView) convertView.findViewById(R.id.playing_indicator);
final ImageView overflowButton = (ImageView) convertView.findViewById(R.id.menu);
title.setText(song.title);
if (app.getMusicPlayerRemote().getPosition() == position) {
@ -44,6 +56,43 @@ public class PlayingQueueAdapter extends ArrayAdapter<Song> {
playingIndicator.setVisibility(View.GONE);
playingIndicator.setImageBitmap(null);
}
overflowButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
PopupMenu popupMenu = new PopupMenu(context, v);
popupMenu.inflate(R.menu.menu_song);
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_tag_editor:
Intent intent = new Intent(context, SongTagEditorActivity.class);
intent.putExtra(AppKeys.E_ID, song.id);
context.startActivity(intent);
return true;
case R.id.action_details:
String songFilePath = SongFileLoader.getSongFile(context, song.id);
File songFile = new File(songFilePath);
SongDetailDialogHelper.getDialog(context, songFile).show();
return true;
case R.id.action_go_to_album:
if (goToAble != null) {
goToAble.goToAlbum(song.albumId);
}
return true;
case R.id.action_go_to_artist:
if (goToAble != null) {
goToAble.goToArtist(song.artistId);
}
return true;
}
return false;
}
});
popupMenu.show();
}
});
return convertView;
}
}

View file

@ -1,19 +1,30 @@
package com.kabouzeid.materialmusic.helper;
import android.content.Context;
import android.view.View;
import android.widget.AdapterView;
import com.afollestad.materialdialogs.MaterialDialog;
import com.kabouzeid.materialmusic.App;
import com.kabouzeid.materialmusic.R;
import com.kabouzeid.materialmusic.adapter.PlayingQueueAdapter;
import com.kabouzeid.materialmusic.adapter.songadapter.SongAdapter;
import com.kabouzeid.materialmusic.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) {
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)
@ -33,8 +44,15 @@ public class PlayingQueueDialogHelper {
})
.build();
final DragSortListView dragSortListView = (DragSortListView) dialog.getCustomView().findViewById(R.id.dragSortListView);
final PlayingQueueAdapter playingQueueAdapter = new PlayingQueueAdapter(context, app.getMusicPlayerRemote().getPlayingQueue());
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) {

View file

@ -10,18 +10,19 @@ public class MusicRemoteEvent {
public static final int STOP = 3;
public static final int NEXT = 4;
public static final int PREV = 5;
public static final int TRACK_CHANGED = 6;
public static final int SONG_COMPLETED = 6;
public static final int QUEUE_COMPLETED = 7;
public static final int SONG_COMPLETED = 7;
public static final int QUEUE_COMPLETED = 8;
public static final int SERVICE_CONNECTED = 8;
public static final int SERVICE_DISCONNECTED = 9;
public static final int SERVICE_CONNECTED = 9;
public static final int SERVICE_DISCONNECTED = 10;
public static final int STATE_SAVED = 10;
public static final int STATE_RESTORED = 11;
public static final int STATE_SAVED = 11;
public static final int STATE_RESTORED = 12;
public static final int SHUFFLE_MODE_CHANGED = 12;
public static final int REPEAT_MODE_CHANGED = 13;
public static final int SHUFFLE_MODE_CHANGED = 13;
public static final int REPEAT_MODE_CHANGED = 14;
private int action;

View file

@ -21,6 +21,10 @@ public class AlbumJSONStore extends SQLiteOpenHelper {
sInstance = new AlbumJSONStore(context.getApplicationContext());
}
return sInstance;
}
public static void deleteDatabase(final Context context) {
context.deleteDatabase(DATABASE_NAME);
} @Override
public void onCreate(final SQLiteDatabase db) {
db.execSQL("CREATE TABLE IF NOT EXISTS " + AlbumJSONColumns.NAME +
@ -29,14 +33,6 @@ public class AlbumJSONStore extends SQLiteOpenHelper {
);
}
public static void deleteDatabase(final Context context) {
context.deleteDatabase(DATABASE_NAME);
} @Override
public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + AlbumJSONColumns.NAME);
onCreate(db);
}
public void addAlbumJSON(final String albumAndArtistName, final String JSON) {
if (albumAndArtistName == null || JSON == null) {
return;
@ -80,6 +76,10 @@ public class AlbumJSONStore extends SQLiteOpenHelper {
cursor.close();
}
return null;
} @Override
public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + AlbumJSONColumns.NAME);
onCreate(db);
}
public void removeItem(final String albumAndArtistName) {
@ -100,4 +100,5 @@ public class AlbumJSONStore extends SQLiteOpenHelper {
}

View file

@ -21,6 +21,10 @@ public class ArtistJSONStore extends SQLiteOpenHelper {
sInstance = new ArtistJSONStore(context.getApplicationContext());
}
return sInstance;
}
public static void deleteDatabase(final Context context) {
context.deleteDatabase(DATABASE_NAME);
} @Override
public void onCreate(final SQLiteDatabase db) {
db.execSQL("CREATE TABLE IF NOT EXISTS " + ArtistJSONColumns.NAME +
@ -29,14 +33,6 @@ public class ArtistJSONStore extends SQLiteOpenHelper {
);
}
public static void deleteDatabase(final Context context) {
context.deleteDatabase(DATABASE_NAME);
} @Override
public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + ArtistJSONColumns.NAME);
onCreate(db);
}
public void addArtistJSON(final String artistName, final String JSON) {
if (artistName == null || JSON == null) {
return;
@ -80,6 +76,10 @@ public class ArtistJSONStore extends SQLiteOpenHelper {
cursor.close();
}
return null;
} @Override
public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + ArtistJSONColumns.NAME);
onCreate(db);
}
public void removeItem(final String artistName) {
@ -100,4 +100,5 @@ public class ArtistJSONStore extends SQLiteOpenHelper {
}

View file

@ -299,6 +299,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
} else {
Toast.makeText(this, getResources().getString(R.string.audio_focus_denied), Toast.LENGTH_SHORT).show();
}
notifyOnMusicRemoteEventListeners(MusicRemoteEvent.TRACK_CHANGED);
}
private boolean requestFocus() {

View file

@ -18,8 +18,11 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import com.afollestad.materialdialogs.MaterialDialog;
import com.kabouzeid.materialmusic.R;
import com.kabouzeid.materialmusic.helper.PlayingQueueDialogHelper;
import com.kabouzeid.materialmusic.interfaces.KabSearchAbleFragment;
import com.kabouzeid.materialmusic.interfaces.KabViewsDisableAble;
import com.kabouzeid.materialmusic.interfaces.OnMusicRemoteEventListener;
@ -85,7 +88,6 @@ public class MainActivity extends AbsFabActivity
}
private void setUpToolBar() {
toolbarTitle = getTitle();
toolbar = (Toolbar) findViewById(R.id.toolbar);
statusBar = findViewById(R.id.statusBar);
setSupportActionBar(toolbar);
@ -253,7 +255,14 @@ public class MainActivity extends AbsFabActivity
case R.id.action_current_playing:
openCurrentPlayingIfPossible(null);
return true;
case R.id.action_playing_queue:
final MaterialDialog materialDialog = PlayingQueueDialogHelper.getDialog(this, this);
if (materialDialog != null) {
materialDialog.show();
} else {
Toast.makeText(this, getResources().getString(R.string.nothing_playing), Toast.LENGTH_SHORT).show();
}
return true;
}
return super.onOptionsItemSelected(item);
}

View file

@ -16,6 +16,7 @@ import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import com.afollestad.materialdialogs.MaterialDialog;
import com.kabouzeid.materialmusic.R;
@ -356,10 +357,7 @@ public class MusicControllerActivity extends AbsFabActivity implements OnMusicRe
public void onMusicRemoteEvent(MusicRemoteEvent event) {
super.onMusicRemoteEvent(event);
switch (event.getAction()) {
case MusicRemoteEvent.NEXT:
updateCurrentSong();
break;
case MusicRemoteEvent.PREV:
case MusicRemoteEvent.TRACK_CHANGED:
updateCurrentSong();
break;
case MusicRemoteEvent.REPEAT_MODE_CHANGED:
@ -399,8 +397,12 @@ public class MusicControllerActivity extends AbsFabActivity implements OnMusicRe
super.onBackPressed();
return true;
case R.id.action_playing_queue:
final MaterialDialog materialDialog = PlayingQueueDialogHelper.getDialog(this);
materialDialog.show();
final MaterialDialog materialDialog = PlayingQueueDialogHelper.getDialog(this, this);
if (materialDialog != null) {
materialDialog.show();
} else {
Toast.makeText(this, getResources().getString(R.string.nothing_playing), Toast.LENGTH_SHORT).show();
}
return true;
case R.id.action_tag_editor:
Intent intent = new Intent(this, SongTagEditorActivity.class);

View file

@ -75,40 +75,6 @@ public class AlbumTagEditorActivity extends AbsTagEditorActivity implements Text
year.setText(getSongYear());
}
@Override
protected void save() {
Artwork artwork = null;
Map<FieldKey, String> fieldKeyValueMap = new EnumMap<>(FieldKey.class);
fieldKeyValueMap.put(FieldKey.ALBUM, albumTitle.getText().toString());
//android seems not to recognize album_artist field so we additionally write the normal artist field
fieldKeyValueMap.put(FieldKey.ARTIST, albumArtistName.getText().toString());
fieldKeyValueMap.put(FieldKey.ALBUM_ARTIST, albumArtistName.getText().toString());
fieldKeyValueMap.put(FieldKey.GENRE, genreName.getText().toString());
fieldKeyValueMap.put(FieldKey.YEAR, year.getText().toString());
try {
albumArtFile = MusicUtil.getAlbumArtFile(this, String.valueOf(getId()));
} catch (IOException e) {
Log.e(TAG, "error while creating albumArtFile", e);
}
if (albumArtBitmap != null && albumArtFile != null) {
try {
albumArtBitmap.compress(Bitmap.CompressFormat.PNG, 0, new FileOutputStream(albumArtFile));
artwork = ArtworkFactory.createArtworkFromFile(albumArtFile);
MusicUtil.insertAlbumArt(this, getId(), albumArtFile.getAbsolutePath());
} catch (IOException e) {
Log.e(TAG, "error while trying to create the artwork from file", e);
}
}
writeValuesToFiles(fieldKeyValueMap, artwork, deleteAlbumArt);
}
@Override
protected int getContentViewResId() {
return R.layout.activity_album_tag_editor;
}
@Override
protected void loadCurrentImage() {
setImageBitmap(getAlbumArt());
@ -147,6 +113,57 @@ public class AlbumTagEditorActivity extends AbsTagEditorActivity implements Text
searchWebFor(query);
}
@Override
protected void deleteImage() {
setImageRes(R.drawable.default_album_art);
deleteAlbumArt = true;
dataChanged();
}
@Override
protected void save() {
Artwork artwork = null;
Map<FieldKey, String> fieldKeyValueMap = new EnumMap<>(FieldKey.class);
fieldKeyValueMap.put(FieldKey.ALBUM, albumTitle.getText().toString());
//android seems not to recognize album_artist field so we additionally write the normal artist field
fieldKeyValueMap.put(FieldKey.ARTIST, albumArtistName.getText().toString());
fieldKeyValueMap.put(FieldKey.ALBUM_ARTIST, albumArtistName.getText().toString());
fieldKeyValueMap.put(FieldKey.GENRE, genreName.getText().toString());
fieldKeyValueMap.put(FieldKey.YEAR, year.getText().toString());
try {
albumArtFile = MusicUtil.getAlbumArtFile(this, String.valueOf(getId()));
} catch (IOException e) {
Log.e(TAG, "error while creating albumArtFile", e);
}
if (albumArtBitmap != null && albumArtFile != null) {
try {
albumArtBitmap.compress(Bitmap.CompressFormat.PNG, 0, new FileOutputStream(albumArtFile));
artwork = ArtworkFactory.createArtworkFromFile(albumArtFile);
MusicUtil.insertAlbumArt(this, getId(), albumArtFile.getAbsolutePath());
} catch (IOException e) {
Log.e(TAG, "error while trying to create the artwork from file", e);
}
}
writeValuesToFiles(fieldKeyValueMap, artwork, deleteAlbumArt);
}
@Override
protected int getContentViewResId() {
return R.layout.activity_album_tag_editor;
}
@Override
protected List<String> getSongPaths() {
List<Song> songs = AlbumSongLoader.getAlbumSongList(this, getId());
List<Integer> songIds = new ArrayList<>();
for (Song song : songs) {
songIds.add(song.id);
}
return SongFileLoader.getSongFiles(this, songIds);
}
@Override
protected void loadImageFromFile(final Uri selectedFileUri) {
DisplayImageOptions options = new DisplayImageOptions.Builder()
@ -167,23 +184,6 @@ public class AlbumTagEditorActivity extends AbsTagEditorActivity implements Text
}
}
@Override
protected void deleteImage() {
setImageRes(R.drawable.default_album_art);
deleteAlbumArt = true;
dataChanged();
}
@Override
protected List<String> getSongPaths() {
List<Song> songs = AlbumSongLoader.getAlbumSongList(this, getId());
List<Integer> songIds = new ArrayList<>();
for (Song song : songs) {
songIds.add(song.id);
}
return SongFileLoader.getSongFiles(this, songIds);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {

View file

@ -64,6 +64,26 @@ public class SongTagEditorActivity extends AbsTagEditorActivity implements TextW
trackNumber.setText(getTrackNumber());
}
@Override
protected void loadCurrentImage() {
}
@Override
protected void getImageFromLastFM() {
}
@Override
protected void searchImageOnWeb() {
}
@Override
protected void deleteImage() {
}
@Override
protected void save() {
Map<FieldKey, String> fieldKeyValueMap = new EnumMap<>(FieldKey.class);
@ -82,18 +102,10 @@ public class SongTagEditorActivity extends AbsTagEditorActivity implements TextW
}
@Override
protected void loadCurrentImage() {
}
@Override
protected void getImageFromLastFM() {
}
@Override
protected void searchImageOnWeb() {
protected List<String> getSongPaths() {
List<Integer> tempIdList = new ArrayList<>();
tempIdList.add(getId());
return SongFileLoader.getSongFiles(this, tempIdList);
}
@Override
@ -101,18 +113,6 @@ public class SongTagEditorActivity extends AbsTagEditorActivity implements TextW
}
@Override
protected void deleteImage() {
}
@Override
protected List<String> getSongPaths() {
List<Integer> tempIdList = new ArrayList<>();
tempIdList.add(getId());
return SongFileLoader.getSongFiles(this, tempIdList);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {

View file

@ -13,13 +13,14 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<TextView android:id="@android:id/text1"
style="@style/ThemeOverlay.AppCompat.Light"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:gravity="center"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:textColor="@color/white"
android:textSize="14sp"/>
<TextView
android:id="@android:id/text1"
style="@style/ThemeOverlay.AppCompat.Light"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:gravity="center"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:textColor="@color/white"
android:textSize="14sp"/>

View file

@ -7,7 +7,7 @@
android:id="@+id/action_current_playing"
android:icon="@drawable/music_box"
android:title="@string/action_current_playing"
app:showAsAction="ifRoom"/>
app:showAsAction="always"/>
<item
android:id="@+id/action_search"
@ -16,6 +16,12 @@
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="collapseActionView|ifRoom"/>
<item
android:id="@+id/action_playing_queue"
android:icon="@drawable/playlist"
android:title="@string/action_playing_queue"
app:showAsAction="never"/>
<item
android:id="@+id/action_settings"
android:icon="@drawable/settings"

View file

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_play_next"
android:title="@string/action_play_next"
app:showAsAction="never"/>
<item
android:id="@+id/action_remove_from_playing_queue"
android:title="@string/action_remove_from_playing_queue"
app:showAsAction="never"/>
<item
android:id="@+id/action_add_to_current_playing"
android:title="@string/action_add_to_playing_queue"
app:showAsAction="never"/>
<item
android:id="@+id/action_add_to_playlist"
android:title="@string/action_add_to_playlist"
app:showAsAction="never"/>
<item
android:id="@+id/action_go_to_album"
android:title="@string/action_go_to_album"
app:showAsAction="never"/>
<item
android:id="@+id/action_go_to_artist"
android:title="@string/action_go_to_artist"
app:showAsAction="never"/>
<item
android:id="@+id/action_tag_editor"
android:title="@string/action_tag_editor"
app:showAsAction="never"/>
<item
android:id="@+id/action_details"
android:title="@string/action_details"
app:showAsAction="never"/>
<item
android:id="@+id/action_delete_from_disk"
android:title="@string/action_delete_from_disk"
app:showAsAction="never"/>
</menu>

View file

@ -7,7 +7,7 @@
app:showAsAction="never"/>
<item
android:id="@+id/action_add_to_current_playing"
android:title="@string/action_add_to_current_playing"
android:title="@string/action_add_to_playing_queue"
app:showAsAction="never"/>
<item
android:id="@+id/action_add_to_playlist"

View file

@ -9,12 +9,13 @@
<string name="action_playing_queue">Playing queue</string>
<string name="action_search">Search</string>
<string name="action_play_next">Play next</string>
<string name="action_add_to_current_playing">Add to playing queue"</string>
<string name="action_add_to_playlist">Add to playlist..."</string>
<string name="action_add_to_playing_queue">Add to playing queue"</string>
<string name="action_remove_from_playing_queue">Remove from playing queue</string>
<string name="action_add_to_playlist">Add to playlist…"</string>
<string name="action_tag_editor">Tag Editor"</string>
<string name="action_delete_from_disk">Delete from disk"</string>
<string name="action_details">Details</string>
<string name="action_go_to">Go to...</string>
<string name="action_go_to">Go to</string>
<string name="albums">Albums</string>
<string name="artists">Artists</string>
<string name="genres">Genres</string>
@ -55,7 +56,7 @@
<string name="label_track_length">Length</string>
<string name="label_bit_rate">Bitrate</string>
<string name="label_sampling_rate">Sampling rate</string>
<string name="ok">ok</string>
<string name="ok">OK</string>
<string name="action_go_to_artist">Go to artist</string>
<string name="action_go_to_album">Go to album</string>
<string name="label_current_playing_queue">Playing queue</string>