Added playing or queueing artist/album/genre from music screen
Implemented context menus in GridView items in AlbumListFragment, ArtistListFragment and AudioGenreListFragment. This allows the user to add everything from an artist, album, or genre by popping up the context menu and selecting either play or Add to playlist. Created a new class utils/MediaManager to hold any methods related to managing media. Added methods play(...) and queueAudio(...) to add musiclist items to the current playlist and start playing.
This commit is contained in:
parent
dab9bc055e
commit
a7874de0e4
|
@ -41,6 +41,7 @@ import android.widget.AdapterView;
|
|||
import android.widget.CursorAdapter;
|
||||
import android.widget.GridView;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
@ -49,10 +50,12 @@ import org.xbmc.kore.host.HostInfo;
|
|||
import org.xbmc.kore.host.HostManager;
|
||||
import org.xbmc.kore.jsonrpc.ApiException;
|
||||
import org.xbmc.kore.jsonrpc.event.MediaSyncEvent;
|
||||
import org.xbmc.kore.jsonrpc.type.PlaylistType;
|
||||
import org.xbmc.kore.provider.MediaContract;
|
||||
import org.xbmc.kore.provider.MediaDatabase;
|
||||
import org.xbmc.kore.service.LibrarySyncService;
|
||||
import org.xbmc.kore.utils.LogUtils;
|
||||
import org.xbmc.kore.utils.MediaManager;
|
||||
import org.xbmc.kore.utils.UIUtils;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
|
@ -341,7 +344,7 @@ public class AlbumListFragment extends Fragment
|
|||
final int YEAR = 6;
|
||||
}
|
||||
|
||||
private static class AlbumsAdapter extends CursorAdapter {
|
||||
private class AlbumsAdapter extends CursorAdapter {
|
||||
|
||||
private HostManager hostManager;
|
||||
private int artWidth, artHeight;
|
||||
|
@ -396,6 +399,11 @@ public class AlbumListFragment extends Fragment
|
|||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
||||
thumbnail, viewHolder.albumTitle,
|
||||
viewHolder.artView, artWidth, artHeight);
|
||||
|
||||
// For the popupmenu
|
||||
ImageView contextMenu = (ImageView)view.findViewById(R.id.list_context_menu);
|
||||
contextMenu.setTag(viewHolder);
|
||||
contextMenu.setOnClickListener(albumlistItemMenuClickListener);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -411,4 +419,32 @@ public class AlbumListFragment extends Fragment
|
|||
int albumId;
|
||||
String albumTitle;
|
||||
}
|
||||
|
||||
private View.OnClickListener albumlistItemMenuClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
final ViewHolder viewHolder = (ViewHolder)v.getTag();
|
||||
|
||||
final PlaylistType.Item playListItem = new PlaylistType.Item();
|
||||
playListItem.albumid = viewHolder.albumId;
|
||||
|
||||
final PopupMenu popupMenu = new PopupMenu(getActivity(), v);
|
||||
popupMenu.getMenuInflater().inflate(R.menu.musiclist_item, popupMenu.getMenu());
|
||||
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_play:
|
||||
MediaManager.play(AlbumListFragment.this, playListItem);
|
||||
return true;
|
||||
case R.id.action_queue:
|
||||
MediaManager.queueAudio(AlbumListFragment.this, playListItem);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
popupMenu.show();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import android.widget.AdapterView;
|
|||
import android.widget.CursorAdapter;
|
||||
import android.widget.GridView;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
@ -49,10 +50,12 @@ import org.xbmc.kore.host.HostInfo;
|
|||
import org.xbmc.kore.host.HostManager;
|
||||
import org.xbmc.kore.jsonrpc.ApiException;
|
||||
import org.xbmc.kore.jsonrpc.event.MediaSyncEvent;
|
||||
import org.xbmc.kore.jsonrpc.type.PlaylistType;
|
||||
import org.xbmc.kore.provider.MediaContract;
|
||||
import org.xbmc.kore.provider.MediaDatabase;
|
||||
import org.xbmc.kore.service.LibrarySyncService;
|
||||
import org.xbmc.kore.utils.LogUtils;
|
||||
import org.xbmc.kore.utils.MediaManager;
|
||||
import org.xbmc.kore.utils.UIUtils;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
|
@ -84,7 +87,6 @@ public class ArtistListFragment extends Fragment
|
|||
// Activity listener
|
||||
private OnArtistSelectedListener listenerActivity;
|
||||
|
||||
private HostManager hostManager;
|
||||
private HostInfo hostInfo;
|
||||
private EventBus bus;
|
||||
|
||||
|
@ -103,8 +105,7 @@ public class ArtistListFragment extends Fragment
|
|||
ButterKnife.inject(this, root);
|
||||
|
||||
bus = EventBus.getDefault();
|
||||
hostManager = HostManager.getInstance(getActivity());
|
||||
hostInfo = hostManager.getHostInfo();
|
||||
hostInfo = HostManager.getInstance(getActivity()).getHostInfo();
|
||||
|
||||
swipeRefreshLayout.setOnRefreshListener(this);
|
||||
//UIUtils.setSwipeRefreshLayoutColorScheme(swipeRefreshLayout);
|
||||
|
@ -305,7 +306,7 @@ public class ArtistListFragment extends Fragment
|
|||
final int THUMBNAIL = 4;
|
||||
}
|
||||
|
||||
private static class ArtistsAdapter extends CursorAdapter {
|
||||
private class ArtistsAdapter extends CursorAdapter {
|
||||
|
||||
private HostManager hostManager;
|
||||
private int artWidth, artHeight;
|
||||
|
@ -354,6 +355,11 @@ public class ArtistListFragment extends Fragment
|
|||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
||||
thumbnail, viewHolder.artistName,
|
||||
viewHolder.artView, artWidth, artHeight);
|
||||
|
||||
// For the popupmenu
|
||||
ImageView contextMenu = (ImageView)view.findViewById(R.id.list_context_menu);
|
||||
contextMenu.setTag(viewHolder);
|
||||
contextMenu.setOnClickListener(artistlistItemMenuClickListener);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -368,4 +374,32 @@ public class ArtistListFragment extends Fragment
|
|||
int artistId;
|
||||
String artistName;
|
||||
}
|
||||
|
||||
private View.OnClickListener artistlistItemMenuClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
final ViewHolder viewHolder = (ViewHolder)v.getTag();
|
||||
|
||||
final PlaylistType.Item playListItem = new PlaylistType.Item();
|
||||
playListItem.artistid = viewHolder.artistId;
|
||||
|
||||
final PopupMenu popupMenu = new PopupMenu(getActivity(), v);
|
||||
popupMenu.getMenuInflater().inflate(R.menu.musiclist_item, popupMenu.getMenu());
|
||||
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_play:
|
||||
MediaManager.play(ArtistListFragment.this, playListItem);
|
||||
return true;
|
||||
case R.id.action_queue:
|
||||
MediaManager.queueAudio(ArtistListFragment.this, playListItem);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
popupMenu.show();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import android.widget.AdapterView;
|
|||
import android.widget.CursorAdapter;
|
||||
import android.widget.GridView;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
@ -49,9 +50,11 @@ import org.xbmc.kore.host.HostInfo;
|
|||
import org.xbmc.kore.host.HostManager;
|
||||
import org.xbmc.kore.jsonrpc.ApiException;
|
||||
import org.xbmc.kore.jsonrpc.event.MediaSyncEvent;
|
||||
import org.xbmc.kore.jsonrpc.type.PlaylistType;
|
||||
import org.xbmc.kore.provider.MediaContract;
|
||||
import org.xbmc.kore.service.LibrarySyncService;
|
||||
import org.xbmc.kore.utils.LogUtils;
|
||||
import org.xbmc.kore.utils.MediaManager;
|
||||
import org.xbmc.kore.utils.UIUtils;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
|
@ -291,7 +294,7 @@ public class AudioGenresListFragment extends Fragment
|
|||
final int THUMBNAIL = 3;
|
||||
}
|
||||
|
||||
private static class AudioGenresAdapter extends CursorAdapter {
|
||||
private class AudioGenresAdapter extends CursorAdapter {
|
||||
|
||||
private HostManager hostManager;
|
||||
private int artWidth, artHeight;
|
||||
|
@ -337,6 +340,11 @@ public class AudioGenresListFragment extends Fragment
|
|||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
||||
thumbnail, viewHolder.genreTitle,
|
||||
viewHolder.artView, artWidth, artHeight);
|
||||
|
||||
// For the popupmenu
|
||||
ImageView contextMenu = (ImageView)view.findViewById(R.id.list_context_menu);
|
||||
contextMenu.setTag(viewHolder);
|
||||
contextMenu.setOnClickListener(genrelistItemMenuClickListener);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -350,4 +358,32 @@ public class AudioGenresListFragment extends Fragment
|
|||
int genreId;
|
||||
String genreTitle;
|
||||
}
|
||||
|
||||
private View.OnClickListener genrelistItemMenuClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
final ViewHolder viewHolder = (ViewHolder)v.getTag();
|
||||
|
||||
final PlaylistType.Item playListItem = new PlaylistType.Item();
|
||||
playListItem.genreid = viewHolder.genreId;
|
||||
|
||||
final PopupMenu popupMenu = new PopupMenu(getActivity(), v);
|
||||
popupMenu.getMenuInflater().inflate(R.menu.musiclist_item, popupMenu.getMenu());
|
||||
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_play:
|
||||
MediaManager.play(AudioGenresListFragment.this, playListItem);
|
||||
return true;
|
||||
case R.id.action_queue:
|
||||
MediaManager.queueAudio(AudioGenresListFragment.this, playListItem);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
popupMenu.show();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* Copyright 2015 Synced Synapse. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.xbmc.kore.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Handler;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.xbmc.kore.R;
|
||||
import org.xbmc.kore.Settings;
|
||||
import org.xbmc.kore.host.HostManager;
|
||||
import org.xbmc.kore.jsonrpc.ApiCallback;
|
||||
import org.xbmc.kore.jsonrpc.method.Player;
|
||||
import org.xbmc.kore.jsonrpc.method.Playlist;
|
||||
import org.xbmc.kore.jsonrpc.type.PlaylistType;
|
||||
import org.xbmc.kore.ui.RemoteActivity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class MediaManager {
|
||||
|
||||
/**
|
||||
* Clears current playlist and starts playing item
|
||||
* @param fragment Fragment instance from which this method is called
|
||||
* @param item PlaylistType.Item that needs to be played
|
||||
*/
|
||||
public static void play(final Fragment fragment, final PlaylistType.Item item) {
|
||||
HostManager hostManager = HostManager.getInstance(fragment.getActivity());
|
||||
|
||||
final Handler callbackHandler = new Handler();
|
||||
|
||||
final Context context = fragment.getActivity();
|
||||
|
||||
Player.Open action = new Player.Open(item);
|
||||
action.execute(hostManager.getConnection(), new ApiCallback<String>() {
|
||||
@Override
|
||||
public void onSuccess(String result) {
|
||||
if (!fragment.isAdded()) return;
|
||||
boolean switchToRemote = PreferenceManager
|
||||
.getDefaultSharedPreferences(context)
|
||||
.getBoolean(Settings.KEY_PREF_SWITCH_TO_REMOTE_AFTER_MEDIA_START,
|
||||
Settings.DEFAULT_PREF_SWITCH_TO_REMOTE_AFTER_MEDIA_START);
|
||||
if (switchToRemote) {
|
||||
Intent launchIntent = new Intent(context, RemoteActivity.class);
|
||||
context.startActivity(launchIntent);
|
||||
} else {
|
||||
Toast.makeText(context, R.string.now_playing, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int errorCode, String description) {
|
||||
if (!fragment.isAdded()) return;
|
||||
// Got an error, show toast
|
||||
String errorMessage = context.getString(R.string.error_play_media_file, description);
|
||||
Toast.makeText(context, errorMessage, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
}, callbackHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears current playlist and starts playing item
|
||||
* @param fragment Fragment instance from which this method is called
|
||||
* @param item PlaylistType.Item that needs to be added to the current audio playlist
|
||||
*/
|
||||
public static void queueAudio(final Fragment fragment, final PlaylistType.Item item) {
|
||||
Playlist.GetPlaylists getPlaylists = new Playlist.GetPlaylists();
|
||||
|
||||
final Handler callbackHandler = new Handler();
|
||||
|
||||
final Context context = fragment.getActivity();
|
||||
|
||||
final HostManager hostManager = HostManager.getInstance(fragment.getActivity());
|
||||
|
||||
getPlaylists.execute(hostManager.getConnection(), new ApiCallback<ArrayList<PlaylistType.GetPlaylistsReturnType>>() {
|
||||
@Override
|
||||
public void onSuccess(ArrayList<PlaylistType.GetPlaylistsReturnType> result) {
|
||||
if (!fragment.isAdded()) return;
|
||||
// Ok, loop through the playlists, looking for the audio one
|
||||
int audioPlaylistId = -1;
|
||||
for (PlaylistType.GetPlaylistsReturnType playlist : result) {
|
||||
if (playlist.type.equals(PlaylistType.GetPlaylistsReturnType.AUDIO)) {
|
||||
audioPlaylistId = playlist.playlistid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If found, add to playlist
|
||||
if (audioPlaylistId != -1) {
|
||||
Playlist.Add action = new Playlist.Add(audioPlaylistId, item);
|
||||
action.execute(hostManager.getConnection(), new ApiCallback<String>() {
|
||||
@Override
|
||||
public void onSuccess(String result) {
|
||||
if (!fragment.isAdded()) return;
|
||||
Toast.makeText(context, R.string.item_added_to_playlist, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int errorCode, String description) {
|
||||
if (!fragment.isAdded()) return;
|
||||
// Got an error, show toast
|
||||
String errorMessage = context.getString(R.string.error_queue_media_file, description);
|
||||
Toast.makeText(context, errorMessage, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
}, callbackHandler);
|
||||
} else {
|
||||
Toast.makeText(context, R.string.no_suitable_playlist, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int errorCode, String description) {
|
||||
if (!fragment.isAdded()) return;
|
||||
// Got an error, show toast
|
||||
Toast.makeText(context, R.string.error_getting_playlist, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
}, callbackHandler);
|
||||
}
|
||||
}
|
|
@ -58,5 +58,16 @@
|
|||
android:layout_alignLeft="@id/title"
|
||||
android:layout_alignParentBottom="true"
|
||||
style="@style/TextAppearance.Medialist.OtherInfo"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/list_context_menu"
|
||||
android:layout_width="@dimen/default_icon_size"
|
||||
android:layout_height="@dimen/default_icon_size"
|
||||
android:padding="@dimen/default_icon_padding"
|
||||
android:layout_alignTop="@id/art"
|
||||
android:layout_alignParentRight="true"
|
||||
style="@style/Widget.Button.Borderless"
|
||||
android:src="?attr/iconOverflow"
|
||||
android:contentDescription="@string/action_options"/>
|
||||
</RelativeLayout>
|
||||
</android.support.v7.widget.CardView>
|
|
@ -35,9 +35,10 @@
|
|||
android:contentDescription="@string/poster"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical">
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
|
@ -53,5 +54,16 @@
|
|||
android:paddingBottom="0dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/list_context_menu"
|
||||
android:layout_width="@dimen/default_icon_size"
|
||||
android:layout_height="@dimen/default_icon_size"
|
||||
android:padding="@dimen/default_icon_padding"
|
||||
android:layout_alignTop="@id/art"
|
||||
android:layout_alignParentRight="true"
|
||||
style="@style/Widget.Button.Borderless"
|
||||
android:src="?attr/iconOverflow"
|
||||
android:contentDescription="@string/action_options"/>
|
||||
</LinearLayout>
|
||||
</android.support.v7.widget.CardView>
|
|
@ -34,11 +34,23 @@
|
|||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
style="@style/TextAppearance.Medialist.Title"
|
||||
android:paddingTop="0dp"
|
||||
android:paddingBottom="0dp"
|
||||
android:gravity="center_vertical"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/list_context_menu"
|
||||
android:layout_width="@dimen/default_icon_size"
|
||||
android:layout_height="@dimen/default_icon_size"
|
||||
android:padding="@dimen/default_icon_padding"
|
||||
android:layout_alignTop="@id/art"
|
||||
android:layout_alignParentRight="true"
|
||||
style="@style/Widget.Button.Borderless"
|
||||
android:src="?attr/iconOverflow"
|
||||
android:contentDescription="@string/action_options"/>
|
||||
</LinearLayout>
|
||||
</android.support.v7.widget.CardView>
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2015 Synced Synapse. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<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"
|
||||
android:title="@string/play"
|
||||
android:orderInCategory="1"
|
||||
app:showAsAction="never" />
|
||||
<item android:id="@+id/action_queue"
|
||||
android:title="@string/add_to_playlist"
|
||||
android:orderInCategory="2"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
Loading…
Reference in New Issue