Add support for OnAVStart event and tweak HostConnectionOberver

This commit is contained in:
Synced Synapse 2019-02-08 16:42:33 +00:00 committed by Martijn Brekhof
parent e60df7e8ac
commit c043c04264
4 changed files with 233 additions and 154 deletions

View File

@ -58,10 +58,10 @@ public class HostConnectionObserver
public interface ApplicationEventsObserver {
/**
* Notifies the observer that volume has changed
* @param volume
* @param muted
* @param volume Volume level
* @param muted Is muted
*/
public void applicationOnVolumeChanged(int volume, boolean muted);
void applicationOnVolumeChanged(int volume, boolean muted);
}
/**
@ -72,13 +72,13 @@ public class HostConnectionObserver
* Constants for possible events. Useful to save the last event and compare with the
* current one to check for differences
*/
public static final int PLAYER_NO_RESULT = 0,
int PLAYER_NO_RESULT = 0,
PLAYER_CONNECTION_ERROR = 1,
PLAYER_IS_PLAYING = 2,
PLAYER_IS_PAUSED = 3,
PLAYER_IS_STOPPED = 4;
public void playerOnPropertyChanged(NotificationsData notificationsData);
void playerOnPropertyChanged(NotificationsData notificationsData);
/**
* Notifies that something is playing
@ -86,7 +86,7 @@ public class HostConnectionObserver
* @param getPropertiesResult Properties obtained by a call to {@link org.xbmc.kore.jsonrpc.method.Player.GetProperties}
* @param getItemResult Currently playing item, obtained by a call to {@link org.xbmc.kore.jsonrpc.method.Player.GetItem}
*/
public void playerOnPlay(PlayerType.GetActivePlayersReturnType getActivePlayerResult,
void playerOnPlay(PlayerType.GetActivePlayersReturnType getActivePlayerResult,
PlayerType.PropertyValue getPropertiesResult,
ListType.ItemsAll getItemResult);
@ -96,41 +96,41 @@ public class HostConnectionObserver
* @param getPropertiesResult Properties obtained by a call to {@link org.xbmc.kore.jsonrpc.method.Player.GetProperties}
* @param getItemResult Currently paused item, obtained by a call to {@link org.xbmc.kore.jsonrpc.method.Player.GetItem}
*/
public void playerOnPause(PlayerType.GetActivePlayersReturnType getActivePlayerResult,
void playerOnPause(PlayerType.GetActivePlayersReturnType getActivePlayerResult,
PlayerType.PropertyValue getPropertiesResult,
ListType.ItemsAll getItemResult);
/**
* Notifies that media is stopped/nothing is playing
*/
public void playerOnStop();
void playerOnStop();
/**
* Called when we get a connection error
* @param errorCode
* @param description
* @param errorCode Code
* @param description Description
*/
public void playerOnConnectionError(int errorCode, String description);
void playerOnConnectionError(int errorCode, String description);
/**
* Notifies that we don't have a result yet
*/
public void playerNoResultsYet();
void playerNoResultsYet();
/**
* Notifies that XBMC has quit/shutdown/sleep
*/
public void systemOnQuit();
void systemOnQuit();
/**
* Notifies that XBMC has requested input
*/
public void inputOnInputRequested(String title, String type, String value);
void inputOnInputRequested(String title, String type, String value);
/**
* Notifies the observer that it this is stopping
*/
public void observerOnStopObserving();
void observerOnStopObserving();
}
/**
@ -141,33 +141,26 @@ public class HostConnectionObserver
/**
* The list of observers
*/
private List<PlayerEventsObserver> playerEventsObservers = new ArrayList<PlayerEventsObserver>();
private List<PlayerEventsObserver> playerEventsObservers = new ArrayList<>();
private List<ApplicationEventsObserver> applicationEventsObservers = new ArrayList<>();
// /**
// * Handlers for which observer, on which to notify them
// */
// private Map<PlayerEventsObserver, Handler> observerHandlerMap = new HashMap<PlayerEventsObserver, Handler>();
// Associate the Handler with the UI thread
private Handler checkerHandler = new Handler(Looper.getMainLooper());
private Runnable httpCheckerRunnable = new Runnable() {
@Override
public void run() {
final int HTTP_NOTIFICATION_CHECK_INTERVAL = 3000;
boolean keepChecking = false;
if ( ! playerEventsObservers.isEmpty() ) {
keepChecking = true;
final int HTTP_NOTIFICATION_CHECK_INTERVAL = 2000;
// If no one is listening to this, just exit
if (playerEventsObservers.isEmpty() && applicationEventsObservers.isEmpty())
return;
if (!playerEventsObservers.isEmpty())
checkWhatsPlaying();
}
if ( ! applicationEventsObservers.isEmpty() ) {
keepChecking = true;
if (!applicationEventsObservers.isEmpty())
getApplicationProperties();
}
if (keepChecking)
checkerHandler.postDelayed(this, HTTP_NOTIFICATION_CHECK_INTERVAL);
checkerHandler.postDelayed(this, HTTP_NOTIFICATION_CHECK_INTERVAL);
}
};
@ -184,24 +177,16 @@ public class HostConnectionObserver
ping.execute(connection, new ApiCallback<String>() {
@Override
public void onSuccess(String result) {
boolean keepChecking = false;
// Ok, we've got a ping, if there are playerEventsObservers and
// we were in a error or uninitialized state, update
if ((! playerEventsObservers.isEmpty()) &&
if ((!playerEventsObservers.isEmpty()) &&
((hostState.lastCallResult == PlayerEventsObserver.PLAYER_NO_RESULT) ||
(hostState.lastCallResult == PlayerEventsObserver.PLAYER_CONNECTION_ERROR))) {
LogUtils.LOGD(TAG, "Checking what's playing because we don't have info about it");
checkWhatsPlaying();
keepChecking = true;
}
if ( ! applicationEventsObservers.isEmpty() ) {
getApplicationProperties();
keepChecking = true;
}
if (keepChecking)
checkerHandler.postDelayed(tcpCheckerRunnable, PING_AFTER_SUCCESS_CHECK_INTERVAL);
checkerHandler.postDelayed(tcpCheckerRunnable, PING_AFTER_SUCCESS_CHECK_INTERVAL);
}
@Override
@ -235,8 +220,6 @@ public class HostConnectionObserver
public HostState hostState;
private HostConnectionObserver() {}
public HostConnectionObserver(HostConnection connection) {
this.hostState = new HostState();
this.connection = connection;
@ -250,7 +233,7 @@ public class HostConnectionObserver
if (this.connection == null)
return;
if ( ! playerEventsObservers.contains(observer) )
if (!playerEventsObservers.contains(observer))
playerEventsObservers.add(observer);
if (replyImmediately) replyWithLastResult(observer);
@ -263,9 +246,8 @@ public class HostConnectionObserver
connection.registerSystemNotificationsObserver(this, checkerHandler);
connection.registerInputNotificationsObserver(this, checkerHandler);
}
startCheckerHandler();
}
startCheckerHandler();
}
/**
@ -274,7 +256,6 @@ public class HostConnectionObserver
*/
public void unregisterPlayerObserver(PlayerEventsObserver observer) {
playerEventsObservers.remove(observer);
// observerHandlerMap.remove(observer);
LogUtils.LOGD(TAG, "Unregistering player observer " + observer.getClass().getSimpleName() +
". Still got " + playerEventsObservers.size() +
@ -295,13 +276,13 @@ public class HostConnectionObserver
/**
* Registers a new observer that will be notified about application events
* @param observer Observer
* @param replyImmediately
* @param replyImmediately Wether to immediatlely issue a reply with the current status
*/
public void registerApplicationObserver(ApplicationEventsObserver observer, boolean replyImmediately) {
if (this.connection == null)
return;
if (! applicationEventsObservers.contains(observer) )
if (!applicationEventsObservers.contains(observer))
applicationEventsObservers.add(observer);
if (replyImmediately) {
@ -318,9 +299,8 @@ public class HostConnectionObserver
if (connection.getProtocol() == HostConnection.PROTOCOL_TCP) {
connection.registerApplicationNotificationsObserver(this, checkerHandler);
}
startCheckerHandler();
}
startCheckerHandler();
}
/**
@ -343,6 +323,19 @@ public class HostConnectionObserver
}
}
private void startCheckerHandler() {
// Check if checkerHandler is already running, to prevent multiple runnables to be posted
// when multiple observers are registered.
if (checkerHandler.hasMessages(0))
return;
if (connection.getProtocol() == HostConnection.PROTOCOL_TCP) {
checkerHandler.post(tcpCheckerRunnable);
} else {
checkerHandler.post(httpCheckerRunnable);
}
}
/**
* Unregisters all observers
*/
@ -372,35 +365,48 @@ public class HostConnectionObserver
/**
* The {@link HostConnection.PlayerNotificationsObserver} interface methods
* Start the chain calls to get whats playing
*/
public void onPlay(org.xbmc.kore.jsonrpc.notification.Player.OnPlay notification) {
// Just start our chain calls
chainCallGetActivePlayers();
// Ignore this if Kodi is Leia or higher, as we'll be properly notified via OnAVStart
// See https://github.com/xbmc/Kore/issues/602 and https://github.com/xbmc/xbmc/pull/13726
if (connection.getHostInfo().isLeiaOrLater()) {
LogUtils.LOGD(TAG, "OnPlay notification ignored. Will wait for OnAVStart.");
return;
}
checkWhatsPlaying();
}
public void onResume(org.xbmc.kore.jsonrpc.notification.Player.OnResume notification) {
// Just start our chain calls
chainCallGetActivePlayers();
checkWhatsPlaying();
}
public void onPause(org.xbmc.kore.jsonrpc.notification.Player.OnPause notification) {
// Just start our chain calls
chainCallGetActivePlayers();
checkWhatsPlaying();
}
public void onSpeedChanged(org.xbmc.kore.jsonrpc.notification.Player.OnSpeedChanged notification) {
// Just start our chain calls
chainCallGetActivePlayers();
checkWhatsPlaying();
}
public void onSeek(org.xbmc.kore.jsonrpc.notification.Player.OnSeek notification) {
// Just start our chain calls
chainCallGetActivePlayers();
checkWhatsPlaying();
}
public void onStop(org.xbmc.kore.jsonrpc.notification.Player.OnStop notification) {
// Just start our chain calls
notifyNothingIsPlaying(playerEventsObservers);
// We could directly notify that nothing is playing here, but in Kodi Leia everytime
// there's a playlist change, onStop is triggered, which caused the UI to display
// that nothing was being played. Checking what's playing prevents this.
checkWhatsPlaying();
}
public void onAVStart(org.xbmc.kore.jsonrpc.notification.Player.OnAVStart notification) {
checkWhatsPlaying();
}
public void onAVChange(org.xbmc.kore.jsonrpc.notification.Player.OnAVChange notification) {
// Just ignore this, as it is fired by Kodi very often, and we're only
// interested in play/resume/stop changes
}
/**
@ -448,18 +454,6 @@ public class HostConnectionObserver
}
}
private void startCheckerHandler() {
// Check if checkerHandler is already running, to prevent multiple runnables to be posted
// when multiple observers are registered.
if ( checkerHandler.hasMessages(0) )
return;
if (connection.getProtocol() == HostConnection.PROTOCOL_TCP) {
checkerHandler.post(tcpCheckerRunnable);
} else {
checkerHandler.post(httpCheckerRunnable);
}
}
private void getApplicationProperties() {
org.xbmc.kore.jsonrpc.method.Application.GetProperties getProperties =
new org.xbmc.kore.jsonrpc.method.Application.GetProperties(org.xbmc.kore.jsonrpc.method.Application.GetProperties.VOLUME,
@ -483,10 +477,23 @@ public class HostConnectionObserver
}, checkerHandler);
}
/**
* Indicator set when we are calling Kodi to check what's playing, so that we don't call it
* while there are still pending calls
*/
private boolean checkingWhatsPlaying = false;
/**
* Checks whats playing and notifies observers
*/
private void checkWhatsPlaying() {
// We don't properly protect this against race conditions because it's
// not worth the trouble - we can safely call Kodi multiple times.
if (checkingWhatsPlaying) {
LogUtils.LOGD(TAG, "Already checking whats playing, returning");
return;
}
checkingWhatsPlaying = true;
LogUtils.LOGD(TAG, "Checking whats playing");
// Start the calls: Player.GetActivePlayers -> Player.GetProperties -> Player.GetItem
@ -627,6 +634,7 @@ public class HostConnectionObserver
* @param observers List of observers
*/
private void notifyConnectionError(final int errorCode, final String description, List<PlayerEventsObserver> observers) {
checkingWhatsPlaying = false;
// Reply if different from last result
if (forceReply ||
(hostState.lastCallResult != PlayerEventsObserver.PLAYER_CONNECTION_ERROR) ||
@ -652,22 +660,15 @@ public class HostConnectionObserver
*/
private void notifyConnectionError(final int errorCode, final String description, PlayerEventsObserver observer) {
observer.playerOnConnectionError(errorCode, description);
// Handler observerHandler = observerHandlerMap.get(observer);
// observerHandler.post(new Runnable() {
// @Override
// public void run() {
// observer.playerOnConnectionError(errorCode, description);
// }
// });
}
/**
* Nothing is playing, notify observers calling playerOnStop
* Only notifies them if the result is different from the last one
* @param observers List of observers
*/
private void notifyNothingIsPlaying(List<PlayerEventsObserver> observers) {
checkingWhatsPlaying = false;
// Reply if forced or different from last result
if (forceReply ||
(hostState.lastCallResult != PlayerEventsObserver.PLAYER_IS_STOPPED)) {
@ -706,15 +707,16 @@ public class HostConnectionObserver
/**
* Something is playing or paused, notify observers
* Only notifies them if the result is different from the last one
* @param getActivePlayersResult
* @param getPropertiesResult
* @param getItemResult
* @param getActivePlayersResult Previous call result
* @param getPropertiesResult Previous call result
* @param getItemResult Previous call result
* @param observers List of observers
*/
private void notifySomethingIsPlaying(final PlayerType.GetActivePlayersReturnType getActivePlayersResult,
final PlayerType.PropertyValue getPropertiesResult,
final ListType.ItemsAll getItemResult,
List<PlayerEventsObserver> observers) {
checkingWhatsPlaying = false;
int currentCallResult = (getPropertiesResult.speed == 0) ?
PlayerEventsObserver.PLAYER_IS_PAUSED : PlayerEventsObserver.PLAYER_IS_PLAYING;
if (forceReply ||
@ -740,7 +742,7 @@ public class HostConnectionObserver
if ((currentCallResult == PlayerEventsObserver.PLAYER_IS_PLAYING) &&
(connection.getProtocol() == HostConnection.PROTOCOL_TCP) &&
(getPropertiesResult.time.ToSeconds() == 0)) {
LogUtils.LOGD(TAG, "Scheduling new call to check what's playing.");
LogUtils.LOGD(TAG, "Scheduling new call to check what's playing because time is 0.");
final int RECHECK_INTERVAL = 3000;
checkerHandler.postDelayed(new Runnable() {
@Override
@ -750,15 +752,14 @@ public class HostConnectionObserver
}
}, RECHECK_INTERVAL);
}
}
/**
* Something is playing or paused, notify a specific observer
* Always notifies the observer, and doesn't save results in last call
* @param getActivePlayersResult
* @param getPropertiesResult
* @param getItemResult
* @param getActivePlayersResult Previous call result
* @param getPropertiesResult Previous call result
* @param getItemResult Previous call result
* @param observer Specific observer
*/
private void notifySomethingIsPlaying(final PlayerType.GetActivePlayersReturnType getActivePlayersResult,
@ -801,8 +802,9 @@ public class HostConnectionObserver
* Forces a refresh of the current cached results
*/
public void forceRefreshResults() {
LogUtils.LOGD(TAG, "Forcing a refresh");
forceReply = true;
chainCallGetActivePlayers();
checkWhatsPlaying();
}
public HostState getHostState() {

View File

@ -307,7 +307,11 @@ public class HostInfo {
return kodiVersionMajor >= KODI_V17_KRYPTON;
}
/**
public boolean isLeiaOrLater() {
return kodiVersionMajor >= KODI_V18_LEIA;
}
/**
* Returns the URL of the host
* @return HTTP URL eg. http://192.168.1.1:8080
*/

View File

@ -77,6 +77,8 @@ public class HostConnection {
void onSpeedChanged(Player.OnSpeedChanged notification);
void onSeek(Player.OnSeek notification);
void onStop(Player.OnStop notification);
void onAVStart(Player.OnAVStart notification);
void onAVChange(Player.OnAVChange notification);
}
/**
@ -126,25 +128,25 @@ public class HostConnection {
* {@link java.util.HashMap} that will hold the {@link MethodCallInfo} with the information
* necessary to respond to clients (TCP only)
*/
private final HashMap<String, MethodCallInfo<?>> clientCallbacks = new HashMap<String, MethodCallInfo<?>>();
private final HashMap<String, MethodCallInfo<?>> clientCallbacks = new HashMap<>();
/**
* The observers that will be notified of player notifications
*/
private final HashMap<PlayerNotificationsObserver, Handler> playerNotificationsObservers =
new HashMap<PlayerNotificationsObserver, Handler>();
new HashMap<>();
/**
* The observers that will be notified of system notifications
*/
private final HashMap<SystemNotificationsObserver, Handler> systemNotificationsObservers =
new HashMap<SystemNotificationsObserver, Handler>();
new HashMap<>();
/**
* The observers that will be notified of input notifications
*/
private final HashMap<InputNotificationsObserver, Handler> inputNotificationsObservers =
new HashMap<InputNotificationsObserver, Handler>();
new HashMap<>();
/**
* The observers that will be notified of application notifications
@ -317,10 +319,9 @@ public class HostConnection {
" on host: " + hostInfo.getJsonRpcHttpEndpoint());
if (protocol == PROTOCOL_TCP) {
/**
* Do not call this from the runnable below as it may cause a race condition
* with {@link #updateClientCallback(int, ApiCallback, Handler)}
*/
// Do not call this from the runnable below as it may cause a race condition
// with {@link #updateClientCallback(int, ApiCallback, Handler)}
//
// Save this method/callback for any later response
addClientCallback(method, callback, handler);
}
@ -411,10 +412,10 @@ public class HostConnection {
/**
* Stores the method and callback to handle asynchronous responses.
* Note this is only needed for requests over TCP.
* @param method
* @param callback
* @param handler
* @param <T>
* @param method Method
* @param callback Callback
* @param handler Handler
* @param <T> Method/Callback type
*/
private <T> void addClientCallback(final ApiMethod<T> method, final ApiCallback<T> callback,
final Handler handler) {
@ -437,7 +438,7 @@ public class HostConnection {
}
return;
}
clientCallbacks.put(methodId, new MethodCallInfo<T>(method, callback, handler));
clientCallbacks.put(methodId, new MethodCallInfo<>(method, callback, handler));
}
}
@ -489,7 +490,7 @@ public class HostConnection {
httpClient.setAuthenticator(new Authenticator() {
@Override
public Request authenticate(Proxy proxy, Response response) throws IOException {
public Request authenticate(Proxy proxy, Response response) {
if (TextUtils.isEmpty(hostInfo.getUsername()))
return null;
@ -498,7 +499,7 @@ public class HostConnection {
}
@Override
public Request authenticateProxy(Proxy proxy, Response response) throws IOException {
public Request authenticateProxy(Proxy proxy, Response response) {
return null;
}
});
@ -517,7 +518,7 @@ public class HostConnection {
/**
* Send an OkHttp POST request
* @param request Request to send
* @throws ApiException
* @throws ApiException {@link ApiException} if request can't be sent
*/
private Response sendOkHttpRequest(final OkHttpClient client, final Request request) throws ApiException {
try {
@ -543,7 +544,7 @@ public class HostConnection {
* Reads the response from the server
* @param response Response from OkHttp
* @return Response body string
* @throws ApiException
* @throws ApiException {@link ApiException} if response can't be read/processed
*/
private String handleOkHttpResponse(Response response) throws ApiException {
try {
@ -582,7 +583,7 @@ public class HostConnection {
* If it is an error (contains the error tag), returns an {@link ApiException} with the info.
* @param response JSON response
* @return {@link com.fasterxml.jackson.databind.node.ObjectNode} constructed
* @throws ApiException
* @throws ApiException Exception trown if we can't parse the response
*/
private ObjectNode parseJsonResponse(String response) throws ApiException {
// LogUtils.LOGD(TAG, "Parsing JSON response");
@ -661,7 +662,7 @@ public class HostConnection {
* Send a TCP request
* @param socket Socket to write to
* @param request Request to send
* @throws ApiException
* @throws ApiException Exception if can't send
*/
private void sendTcpRequest(Socket socket, String request) throws ApiException {
try {
@ -713,7 +714,7 @@ public class HostConnection {
ignoreTcpResponse = false;
ignore = true;
}
LogUtils.LOGD(TAG, "ignore tcp response - " + ignore);
//LogUtils.LOGD(TAG, "ignore tcp response - " + ignore);
return ignore;
}
@ -726,10 +727,10 @@ public class HostConnection {
String notificationName = jsonResponse.get(ApiNotification.METHOD_NODE).asText();
ObjectNode params = (ObjectNode)jsonResponse.get(ApiNotification.PARAMS_NODE);
if (notificationName.equals(Player.OnPause.NOTIFICATION_NAME)) {
switch (notificationName) {
case Player.OnPause.NOTIFICATION_NAME: {
final Player.OnPause apiNotification = new Player.OnPause(params);
for (final PlayerNotificationsObserver observer :
playerNotificationsObservers.keySet()) {
for (final PlayerNotificationsObserver observer : playerNotificationsObservers.keySet()) {
Handler handler = playerNotificationsObservers.get(observer);
postOrRunNow(handler, new Runnable() {
@Override
@ -738,10 +739,11 @@ public class HostConnection {
}
});
}
} else if (notificationName.equals(Player.OnPlay.NOTIFICATION_NAME)) {
break;
}
case Player.OnPlay.NOTIFICATION_NAME: {
final Player.OnPlay apiNotification = new Player.OnPlay(params);
for (final PlayerNotificationsObserver observer :
playerNotificationsObservers.keySet()) {
for (final PlayerNotificationsObserver observer : playerNotificationsObservers.keySet()) {
Handler handler = playerNotificationsObservers.get(observer);
postOrRunNow(handler, new Runnable() {
@Override
@ -750,10 +752,11 @@ public class HostConnection {
}
});
}
} else if (notificationName.equals(Player.OnResume.NOTIFICATION_NAME)) {
break;
}
case Player.OnResume.NOTIFICATION_NAME: {
final Player.OnResume apiNotification = new Player.OnResume(params);
for (final PlayerNotificationsObserver observer :
playerNotificationsObservers.keySet()) {
for (final PlayerNotificationsObserver observer : playerNotificationsObservers.keySet()) {
Handler handler = playerNotificationsObservers.get(observer);
postOrRunNow(handler, new Runnable() {
@Override
@ -762,10 +765,11 @@ public class HostConnection {
}
});
}
} else if (notificationName.equals(Player.OnSeek.NOTIFICATION_NAME)) {
break;
}
case Player.OnSeek.NOTIFICATION_NAME: {
final Player.OnSeek apiNotification = new Player.OnSeek(params);
for (final PlayerNotificationsObserver observer :
playerNotificationsObservers.keySet()) {
for (final PlayerNotificationsObserver observer : playerNotificationsObservers.keySet()) {
Handler handler = playerNotificationsObservers.get(observer);
postOrRunNow(handler, new Runnable() {
@Override
@ -774,10 +778,11 @@ public class HostConnection {
}
});
}
} else if (notificationName.equals(Player.OnSpeedChanged.NOTIFICATION_NAME)) {
break;
}
case Player.OnSpeedChanged.NOTIFICATION_NAME: {
final Player.OnSpeedChanged apiNotification = new Player.OnSpeedChanged(params);
for (final PlayerNotificationsObserver observer :
playerNotificationsObservers.keySet()) {
for (final PlayerNotificationsObserver observer : playerNotificationsObservers.keySet()) {
Handler handler = playerNotificationsObservers.get(observer);
postOrRunNow(handler, new Runnable() {
@Override
@ -786,10 +791,11 @@ public class HostConnection {
}
});
}
} else if (notificationName.equals(Player.OnStop.NOTIFICATION_NAME)) {
break;
}
case Player.OnStop.NOTIFICATION_NAME: {
final Player.OnStop apiNotification = new Player.OnStop(params);
for (final PlayerNotificationsObserver observer :
playerNotificationsObservers.keySet()) {
for (final PlayerNotificationsObserver observer : playerNotificationsObservers.keySet()) {
Handler handler = playerNotificationsObservers.get(observer);
postOrRunNow(handler, new Runnable() {
@Override
@ -798,10 +804,37 @@ public class HostConnection {
}
});
}
} else if (notificationName.equals(Player.OnPropertyChanged.NOTIFICATION_NAME)) {
break;
}
case Player.OnAVStart.NOTIFICATION_NAME: {
final Player.OnAVStart apiNotification = new Player.OnAVStart(params);
for (final PlayerNotificationsObserver observer : playerNotificationsObservers.keySet()) {
Handler handler = playerNotificationsObservers.get(observer);
postOrRunNow(handler, new Runnable() {
@Override
public void run() {
observer.onAVStart(apiNotification);
}
});
}
break;
}
case Player.OnAVChange.NOTIFICATION_NAME: {
final Player.OnAVChange apiNotification = new Player.OnAVChange(params);
for (final PlayerNotificationsObserver observer : playerNotificationsObservers.keySet()) {
Handler handler = playerNotificationsObservers.get(observer);
postOrRunNow(handler, new Runnable() {
@Override
public void run() {
observer.onAVChange(apiNotification);
}
});
}
break;
}
case Player.OnPropertyChanged.NOTIFICATION_NAME: {
final Player.OnPropertyChanged apiNotification = new Player.OnPropertyChanged(params);
for (final PlayerNotificationsObserver observer :
playerNotificationsObservers.keySet()) {
for (final PlayerNotificationsObserver observer : playerNotificationsObservers.keySet()) {
Handler handler = playerNotificationsObservers.get(observer);
postOrRunNow(handler, new Runnable() {
@Override
@ -810,10 +843,11 @@ public class HostConnection {
}
});
}
} else if (notificationName.equals(System.OnQuit.NOTIFICATION_NAME)) {
break;
}
case System.OnQuit.NOTIFICATION_NAME: {
final System.OnQuit apiNotification = new System.OnQuit(params);
for (final SystemNotificationsObserver observer :
systemNotificationsObservers.keySet()) {
for (final SystemNotificationsObserver observer : systemNotificationsObservers.keySet()) {
Handler handler = systemNotificationsObservers.get(observer);
postOrRunNow(handler, new Runnable() {
@Override
@ -822,10 +856,11 @@ public class HostConnection {
}
});
}
} else if (notificationName.equals(System.OnRestart.NOTIFICATION_NAME)) {
break;
}
case System.OnRestart.NOTIFICATION_NAME: {
final System.OnRestart apiNotification = new System.OnRestart(params);
for (final SystemNotificationsObserver observer :
systemNotificationsObservers.keySet()) {
for (final SystemNotificationsObserver observer : systemNotificationsObservers.keySet()) {
Handler handler = systemNotificationsObservers.get(observer);
postOrRunNow(handler, new Runnable() {
@Override
@ -834,10 +869,11 @@ public class HostConnection {
}
});
}
} else if (notificationName.equals(System.OnSleep.NOTIFICATION_NAME)) {
break;
}
case System.OnSleep.NOTIFICATION_NAME: {
final System.OnSleep apiNotification = new System.OnSleep(params);
for (final SystemNotificationsObserver observer :
systemNotificationsObservers.keySet()) {
for (final SystemNotificationsObserver observer : systemNotificationsObservers.keySet()) {
Handler handler = systemNotificationsObservers.get(observer);
postOrRunNow(handler, new Runnable() {
@Override
@ -846,10 +882,11 @@ public class HostConnection {
}
});
}
} else if (notificationName.equals(Input.OnInputRequested.NOTIFICATION_NAME)) {
break;
}
case Input.OnInputRequested.NOTIFICATION_NAME: {
final Input.OnInputRequested apiNotification = new Input.OnInputRequested(params);
for (final InputNotificationsObserver observer :
inputNotificationsObservers.keySet()) {
for (final InputNotificationsObserver observer : inputNotificationsObservers.keySet()) {
Handler handler = inputNotificationsObservers.get(observer);
postOrRunNow(handler, new Runnable() {
@Override
@ -858,11 +895,11 @@ public class HostConnection {
}
});
}
} else if (notificationName.equals(Application.OnVolumeChanged.NOTIFICATION_NAME)) {
final Application.OnVolumeChanged apiNotification =
new Application.OnVolumeChanged(params);
for (final ApplicationNotificationsObserver observer :
applicationNotificationsObservers.keySet()) {
break;
}
case Application.OnVolumeChanged.NOTIFICATION_NAME: {
final Application.OnVolumeChanged apiNotification = new Application.OnVolumeChanged(params);
for (final ApplicationNotificationsObserver observer : applicationNotificationsObservers.keySet()) {
Handler handler = applicationNotificationsObservers.get(observer);
postOrRunNow(handler, new Runnable() {
@Override
@ -871,8 +908,8 @@ public class HostConnection {
}
});
}
}
break;
}}
LogUtils.LOGD(TAG, "Got a notification: " + jsonResponse.get("method").textValue());
} else {
String methodId = jsonResponse.get(ApiMethod.ID_NODE).asText();

View File

@ -158,6 +158,42 @@ public class Player {
public String getNotificationName() { return NOTIFICATION_NAME; }
}
/**
* Player.OnAVStart notification
* Will be triggered on playback start if the first frame was drawn.
* If there is no ID available extra information will be provided
*/
public static class OnAVStart extends ApiNotification {
public static final String NOTIFICATION_NAME = "Player.OnAVStart";
public final NotificationsData data;
public OnAVStart(ObjectNode node) {
super(node);
data = new NotificationsData(node.get(NotificationsData.DATA_NODE));
}
public String getNotificationName() { return NOTIFICATION_NAME; }
}
/**
* Player.OnAVChange notification
* Audio- or videostream has changed.
* If there is no ID available extra information will be provided
*/
public static class OnAVChange extends ApiNotification {
public static final String NOTIFICATION_NAME = "Player.OnAVChange";
public final NotificationsData data;
public OnAVChange(ObjectNode node) {
super(node);
data = new NotificationsData(node.get(NotificationsData.DATA_NODE));
}
public String getNotificationName() { return NOTIFICATION_NAME; }
}
/**
* Notification data for Player
*/