Change share intent behaviour: if a video is already playing, queue the shared file, otherwise start playing it immediately.

Defined playlist types in the correct place
This commit is contained in:
Synced Synapse 2015-04-10 19:51:44 +01:00
parent 611dafc101
commit 4a297c2e35
5 changed files with 140 additions and 98 deletions

View File

@ -25,6 +25,11 @@ import org.xbmc.kore.utils.JsonUtils;
*/
public class PlaylistType {
// Playlist types
public static final int MUSIC_PLAYLISTID = 0;
public static final int VIDEO_PLAYLISTID = 1;
public static final int PICTURE_PLAYLISTID = 2;
/**
* GetPlaylists return type
*/

View File

@ -39,6 +39,7 @@ import android.widget.Toast;
import org.xbmc.kore.R;
import org.xbmc.kore.host.HostManager;
import org.xbmc.kore.jsonrpc.ApiCallback;
import org.xbmc.kore.jsonrpc.HostConnection;
import org.xbmc.kore.jsonrpc.method.Files;
import org.xbmc.kore.jsonrpc.method.Player;
import org.xbmc.kore.jsonrpc.method.Playlist;
@ -49,7 +50,6 @@ import org.xbmc.kore.jsonrpc.type.PlaylistType;
import org.xbmc.kore.utils.LogUtils;
import org.xbmc.kore.utils.UIUtils;
import org.xbmc.kore.utils.Utils;
import org.xbmc.kore.utils.jsonrpcCommonCalls;
import java.util.ArrayList;
import java.util.LinkedList;
@ -70,9 +70,6 @@ public class MediaFileListFragment extends Fragment {
public static final String ROOT_PATH_CONTENTS = "rootPathContents";
public static final String ROOT_VISITED = "rootVisited";
private static final String ADDON_SOURCE = "addons:";
private static final int MUSIC_PLAYLISTID = 0;
private static final int VIDEO_PLAYLISTID = 1;
private static final int PICTURE_PLAYLISTID = 2;
private HostManager hostManager;
/**
@ -82,7 +79,7 @@ public class MediaFileListFragment extends Fragment {
String mediaType = Files.Media.MUSIC;
String parentDirectory = null;
int playlistId = MUSIC_PLAYLISTID; // this is the ID of the music player
int playlistId = PlaylistType.MUSIC_PLAYLISTID; // this is the ID of the music player
private MediaFileListAdapter adapter = null;
boolean browseRootAlready = false;
@ -121,9 +118,9 @@ public class MediaFileListFragment extends Fragment {
if (args != null) {
mediaType = args.getString(MEDIA_TYPE, Files.Media.MUSIC);
if (mediaType.equalsIgnoreCase(Files.Media.VIDEO)) {
playlistId = VIDEO_PLAYLISTID;
playlistId = PlaylistType.VIDEO_PLAYLISTID;
} else if (mediaType.equalsIgnoreCase(Files.Media.PICTURES)) {
playlistId = PICTURE_PLAYLISTID;
playlistId = PlaylistType.PICTURE_PLAYLISTID;
}
}
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_generic_media_list, container, false);
@ -154,9 +151,9 @@ public class MediaFileListFragment extends Fragment {
mediaType = savedInstanceState.getString(MEDIA_TYPE);
//currentPath = savedInstanceState.getString(CURRENT_PATH);
if (mediaType.equalsIgnoreCase(Files.Media.VIDEO)) {
playlistId = VIDEO_PLAYLISTID;
playlistId = PlaylistType.VIDEO_PLAYLISTID;
} else if (mediaType.equalsIgnoreCase(Files.Media.PICTURES)) {
playlistId = PICTURE_PLAYLISTID;
playlistId = PlaylistType.PICTURE_PLAYLISTID;
}
ArrayList<FileLocation> list = savedInstanceState.getParcelableArrayList(PATH_CONTENTS);
rootFileLocation = savedInstanceState.getParcelableArrayList(ROOT_PATH_CONTENTS);
@ -339,6 +336,10 @@ public class MediaFileListFragment extends Fragment {
}
/**
* Starts playing the given media file
* @param filename Filename to start playing
*/
private void playMediaFile(final String filename) {
PlaylistType.Item item = new PlaylistType.Item();
item.file = filename;
@ -347,7 +348,7 @@ public class MediaFileListFragment extends Fragment {
@Override
public void onSuccess(String result) {
while (mediaQueueFileLocation.size() > 0) {
queueMediaFile(mediaQueueFileLocation.poll());
queueMediaFile(mediaQueueFileLocation.poll().file);
}
}
@ -361,14 +362,19 @@ public class MediaFileListFragment extends Fragment {
}, callbackHandler);
}
private void queueMediaFile(final FileLocation loc) {
/**
* Queues the given media file on the active playlist, and starts it if nothing is playing
* @param filename File to queue
*/
private void queueMediaFile(final String filename) {
final HostConnection connection = hostManager.getConnection();
PlaylistType.Item item = new PlaylistType.Item();
item.file = loc.file;
item.file = filename;
Playlist.Add action = new Playlist.Add(playlistId, item);
action.execute(hostManager.getConnection(), new ApiCallback<String>() {
action.execute(connection, new ApiCallback<String>() {
@Override
public void onSuccess(String result ) {
jsonrpcCommonCalls.startPlaylistIfNoActivePlayers(getActivity(), playlistId, callbackHandler);
startPlaylistIfNoActivePlayers(connection, playlistId, callbackHandler);
}
@Override
@ -379,6 +385,47 @@ public class MediaFileListFragment extends Fragment {
Toast.LENGTH_SHORT).show();
}
}, callbackHandler);
}
/**
* Starts a playlist if no active players are playing
* @param connection Host connection
* @param playlistId PlaylistId to start
* @param callbackHandler Handler on which to post method callbacks
*/
private void startPlaylistIfNoActivePlayers(final HostConnection connection,
final int playlistId,
final Handler callbackHandler) {
Player.GetActivePlayers action = new Player.GetActivePlayers();
action.execute(connection, new ApiCallback<ArrayList<PlayerType.GetActivePlayersReturnType>>() {
@Override
public void onSuccess(ArrayList<PlayerType.GetActivePlayersReturnType> result ) {
// find out if any player is running. If it is not, start one
if (result.isEmpty()) {
Player.Open action = new Player.Open(playlistId);
action.execute(connection, new ApiCallback<String>() {
@Override
public void onSuccess(String result) { }
@Override
public void onError(int errorCode, String description) {
if (!isAdded()) return;
Toast.makeText(getActivity(),
String.format(getString(R.string.error_play_media_file), description),
Toast.LENGTH_SHORT).show();
}
}, callbackHandler);
}
}
@Override
public void onError(int errorCode, String description) {
if (!isAdded()) return;
Toast.makeText(getActivity(),
String.format(getString(R.string.error_get_active_player), description),
Toast.LENGTH_SHORT).show();
}
}, callbackHandler);
}
@ -428,7 +475,7 @@ public class MediaFileListFragment extends Fragment {
switch (item.getItemId()) {
case R.id.action_queue_item:
queueMediaFile(loc);
queueMediaFile(loc.file);
return true;
case R.id.action_play_item:
playMediaFile(loc.file);

View File

@ -203,7 +203,7 @@ public class PlaylistFragment extends Fragment
// return super.onContextItemSelected(item);
// }
private void forceRefreshPlaylist() {
public void forceRefreshPlaylist() {
// If we are playing something, refresh playlist
if ((lastCallResult == PLAYER_IS_PLAYING) || (lastCallResult == PLAYER_IS_PAUSED)) {
setupPlaylistInfo(lastGetActivePlayerResult, lastGetPropertiesResult, lastGetItemResult);

View File

@ -37,6 +37,7 @@ import org.xbmc.kore.Settings;
import org.xbmc.kore.host.HostConnectionObserver;
import org.xbmc.kore.host.HostManager;
import org.xbmc.kore.jsonrpc.ApiCallback;
import org.xbmc.kore.jsonrpc.HostConnection;
import org.xbmc.kore.jsonrpc.method.Application;
import org.xbmc.kore.jsonrpc.method.AudioLibrary;
import org.xbmc.kore.jsonrpc.method.GUI;
@ -55,7 +56,6 @@ import org.xbmc.kore.ui.views.CirclePageIndicator;
import org.xbmc.kore.utils.LogUtils;
import org.xbmc.kore.utils.TabsAdapter;
import org.xbmc.kore.utils.UIUtils;
import org.xbmc.kore.utils.jsonrpcCommonCalls;
import java.net.MalformedURLException;
import java.net.URL;
@ -331,22 +331,85 @@ public class RemoteActivity extends BaseActivity
final String videoId = getYouTubeVideoId(youTubeUri);
if (videoId == null) return;
String kodiAddonUrl = "plugin://plugin.video.youtube/?path=/root/search&action=play_video&videoid="
final String kodiAddonUrl = "plugin://plugin.video.youtube/?path=/root/search&action=play_video&videoid="
+ videoId;
queueMediaFile(VIDEO_PLAYLISTID, kodiAddonUrl, new Handler());
// Check if any video player is active and play or queue the file depending on that
final HostConnection connection = hostManager.getConnection();
final Handler callbackHandler = new Handler();
Player.GetActivePlayers getActivePlayers = new Player.GetActivePlayers();
getActivePlayers.execute(connection, new ApiCallback<ArrayList<PlayerType.GetActivePlayersReturnType>>() {
@Override
public void onSuccess(ArrayList<PlayerType.GetActivePlayersReturnType> result) {
boolean videoIsPlaying = false;
for (PlayerType.GetActivePlayersReturnType player : result) {
if (player.type.equals(PlayerType.GetActivePlayersReturnType.VIDEO))
videoIsPlaying = true;
}
if (videoIsPlaying) {
LogUtils.LOGD(TAG, "Video is playing");
queueMediaFile(kodiAddonUrl, connection, callbackHandler);
} else {
LogUtils.LOGD(TAG, "Nothing is playing");
playMediaFile(kodiAddonUrl, connection, callbackHandler);
}
}
@Override
public void onError(int errorCode, String description) {
LogUtils.LOGD(TAG, "Couldn't get active player when handling start intent.");
Toast.makeText(RemoteActivity.this,
String.format(getString(R.string.error_get_active_player), description),
Toast.LENGTH_SHORT).show();
}
}, callbackHandler);
}
private static final int VIDEO_PLAYLISTID = 1;
private void queueMediaFile(final int playlistId, final String file, final Handler callbackHandler) {
/**
* Plays the given media file
* @param file File to play
* @param connection Host connection
* @param callbackHandler Handler to use for posting callbacks
*/
private void playMediaFile(final String file, final HostConnection connection, final Handler callbackHandler) {
PlaylistType.Item item = new PlaylistType.Item();
item.file = file;
Playlist.Add action = new Playlist.Add(playlistId, item);
action.execute(hostManager.getConnection(), new ApiCallback<String>() {
Player.Open action = new Player.Open(item);
action.execute(connection, new ApiCallback<String>() {
@Override
public void onSuccess(String result ) { }
@Override
public void onError(int errorCode, String description) {
Toast.makeText(RemoteActivity.this,
String.format(getString(R.string.error_play_media_file), description),
Toast.LENGTH_SHORT).show();
}
}, callbackHandler);
}
/**
* Queues the given media file
* @param file File to play
* @param connection Host connection
* @param callbackHandler Handler to use for posting callbacks
*/
private void queueMediaFile(final String file, final HostConnection connection, final Handler callbackHandler) {
PlaylistType.Item item = new PlaylistType.Item();
item.file = file;
Playlist.Add action = new Playlist.Add(PlaylistType.VIDEO_PLAYLISTID, item);
action.execute(connection, new ApiCallback<String>() {
@Override
public void onSuccess(String result ) {
jsonrpcCommonCalls.startPlaylistIfNoActivePlayers(RemoteActivity.this, playlistId, callbackHandler);
// Force a refresh of the playlist fragment
String tag = "android:switcher:" + viewPager.getId() + ":" + 3;
PlaylistFragment playlistFragment = (PlaylistFragment)getSupportFragmentManager()
.findFragmentByTag(tag);
if (playlistFragment != null) {
playlistFragment.forceRefreshPlaylist();
}
}
@Override
@ -356,11 +419,9 @@ public class RemoteActivity extends BaseActivity
Toast.LENGTH_SHORT).show();
}
}, callbackHandler);
}
/**
* Returns the YouTube Uri that the YouTube app passes in EXTRA_TEXT
* YouTube sends something like: [Video title]: [YouTube URL] so we need

View File

@ -1,71 +0,0 @@
/*
* 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.os.Handler;
import org.xbmc.kore.host.HostManager;
import org.xbmc.kore.jsonrpc.ApiCallback;
import org.xbmc.kore.jsonrpc.HostConnection;
import org.xbmc.kore.jsonrpc.method.Player;
import org.xbmc.kore.jsonrpc.type.PlayerType;
import java.util.ArrayList;
/**
* Common jsonrpc method calls, that appear more than once on the code
*/
public class jsonrpcCommonCalls {
/**
* Starts a playlist if no active players are playing
*
* @param context Context
* @param playlistId PlaylistID
* @param callbackHandler Handler on which to post method callbacks
*/
public static void startPlaylistIfNoActivePlayers(final Context context, final int playlistId, final Handler callbackHandler) {
final HostConnection connection = HostManager.getInstance(context).getConnection();
Player.GetActivePlayers action = new Player.GetActivePlayers();
action.execute(connection, new ApiCallback<ArrayList<PlayerType.GetActivePlayersReturnType>>() {
@Override
public void onSuccess(ArrayList<PlayerType.GetActivePlayersReturnType> result ) {
// find out if any player is running. If it is not, start one
if (result.size() == 0) {
startPlaying(connection, playlistId, callbackHandler);
}
}
@Override
public void onError(int errorCode, String description) { }
}, callbackHandler);
}
private static void startPlaying(final HostConnection connection, final int playlistId, final Handler callbackHandler) {
Player.Open action = new Player.Open(playlistId);
action.execute(connection, new ApiCallback<String>() {
@Override
public void onSuccess(String result ) {
}
@Override
public void onError(int errorCode, String description) { }
}, callbackHandler);
}
}