Skip to content

Commit e04d0bd

Browse files
author
Chris Bellew
committed
Chromecast changes so that the chromecast can notify the client of what media it is playing upon connecting to it; Proper canceling of search dialogs.
1 parent cd837aa commit e04d0bd

File tree

13 files changed

+189
-120
lines changed

13 files changed

+189
-120
lines changed

Voice Control For Plex/src/main/java/com/atomjack/vcfp/CastPlayerManager.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ public interface CastListener {
139139
void onCastDisconnected();
140140
void onCastPlayerStateChanged(PlayerState state);
141141
void onCastPlayerTimeUpdate(int seconds);
142-
void onCastPlayerPlaylistAdvance(String key);
142+
void onCastPlayerPlaylistAdvance(PlexMedia media);
143143
void onCastPlayerState(PlayerState state, PlexMedia media);
144144
};
145145

@@ -217,6 +217,11 @@ private void setCastConsumer() {
217217
castConsumer = new VCFPCastConsumer() {
218218
private Runnable onConnectedRunnable;
219219

220+
@Override
221+
public void onApplicationDisconnected(int errorCode) {
222+
// super.onApplicationDisconnected(errorCode);
223+
}
224+
220225
@Override
221226
public void onDataMessageReceived(String message) {
222227
// Logger.d("DATA MESSAGE RECEIVED: %s", message);
@@ -230,9 +235,10 @@ public void onDataMessageReceived(String message) {
230235
}
231236
} else if(obj.has("event") && obj.getString("event").equals("timeUpdate") && obj.has("currentTime")) {
232237
listener.onCastPlayerTimeUpdate(obj.getInt("currentTime"));
233-
} else if(obj.has("event") && obj.getString("event").equals("playlistAdvance") && obj.has("key")) {
234-
Logger.d("[CastPlayerManager] playlistAdvance: %s", obj.getString("key"));
235-
listener.onCastPlayerPlaylistAdvance(obj.getString("key"));
238+
} else if(obj.has("event") && obj.getString("event").equals("playlistAdvance") && obj.has("media")) {
239+
Logger.d("[CastPlayerManager] playlistAdvance");
240+
nowPlayingMedia = VoiceControlForPlexApplication.gsonRead.fromJson(obj.getString("media"), PlexTrack.class);
241+
listener.onCastPlayerPlaylistAdvance(nowPlayingMedia);
236242
} else if(obj.has("event") && obj.getString("event").equals("getPlaybackState") && obj.has("state")) {
237243
currentState = PlayerState.getState(obj.getString("state"));
238244
PlexMedia media = null;

Voice Control For Plex/src/main/java/com/atomjack/vcfp/GDMService.java

Lines changed: 47 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -26,49 +26,45 @@ public GDMService() {
2626
protected void onHandleIntent(Intent intent) {
2727
try
2828
{
29-
int port = intent.getIntExtra(PORT, 32414); // Default port, for Plex Media Servers (Clients use 32412)
30-
DatagramSocket socket = new DatagramSocket(32420);
31-
socket.setBroadcast(true);
32-
String data = "M-SEARCH * HTTP/1.1";
33-
DatagramPacket packet = new DatagramPacket(data.getBytes(), data.length(), getBroadcastAddress(), port);
34-
socket.send(packet);
35-
Logger.i("Search Packet Broadcasted");
29+
int port = intent.getIntExtra(PORT, 32414); // Default port, for Plex Media Servers (Clients use 32412)
30+
DatagramSocket socket = new DatagramSocket(32420);
31+
socket.setBroadcast(true);
32+
String data = "M-SEARCH * HTTP/1.1";
33+
DatagramPacket packet = new DatagramPacket(data.getBytes(), data.length(), getBroadcastAddress(), port);
34+
socket.send(packet);
35+
Logger.i("Search Packet Broadcasted");
3636

37-
byte[] buf = new byte[8096];
38-
packet = new DatagramPacket(buf, buf.length);
39-
socket.setSoTimeout(2000);
40-
boolean listening = true;
41-
while (listening)
42-
{
43-
try
44-
{
45-
socket.receive(packet);
46-
String packetData = new String(packet.getData());
47-
if (packetData.startsWith("HTTP/1.0 200 OK") ||
48-
packetData.startsWith("HELLO * HTTP/1.0")) // A version of the Roku is known to send this invalid response.
49-
{
50-
Logger.i("PMS Packet Received");
51-
//Broadcast Received Packet
52-
Intent packetBroadcast = new Intent(GDMService.MSG_RECEIVED);
53-
packetBroadcast.putExtra("data", packetData);
54-
packetBroadcast.putExtra("ipaddress", packet.getAddress().toString());
55-
packetBroadcast.putExtra(VoiceControlForPlexApplication.Intent.EXTRA_CLASS, intent.getSerializableExtra(VoiceControlForPlexApplication.Intent.EXTRA_CLASS));
56-
LocalBroadcastManager.getInstance(this).sendBroadcast(packetBroadcast);
57-
}
58-
}
59-
catch (SocketTimeoutException e)
60-
{
61-
Logger.w("Socket Timeout");
62-
socket.close();
63-
listening = false;
64-
Intent socketBroadcast = new Intent(GDMService.SOCKET_CLOSED);
65-
socketBroadcast.putExtra(VoiceControlForPlexApplication.Intent.EXTRA_SILENT, intent.getBooleanExtra(VoiceControlForPlexApplication.Intent.EXTRA_SILENT, false));
66-
socketBroadcast.putExtra(VoiceControlForPlexApplication.Intent.EXTRA_CLASS, intent.getSerializableExtra(VoiceControlForPlexApplication.Intent.EXTRA_CLASS));
37+
byte[] buf = new byte[8096];
38+
packet = new DatagramPacket(buf, buf.length);
39+
socket.setSoTimeout(2000);
40+
boolean listening = true;
41+
while (listening) {
42+
try {
43+
socket.receive(packet);
44+
String packetData = new String(packet.getData());
45+
if (packetData.startsWith("HTTP/1.0 200 OK") ||
46+
packetData.startsWith("HELLO * HTTP/1.0")) // A version of the Roku is known to send this invalid response.
47+
{
48+
Logger.i("PMS Packet Received");
49+
//Broadcast Received Packet
50+
Intent packetBroadcast = new Intent(GDMService.MSG_RECEIVED);
51+
packetBroadcast.putExtra("data", packetData);
52+
packetBroadcast.putExtra("ipaddress", packet.getAddress().toString());
53+
packetBroadcast.putExtra(VoiceControlForPlexApplication.Intent.EXTRA_CLASS, intent.getSerializableExtra(VoiceControlForPlexApplication.Intent.EXTRA_CLASS));
54+
LocalBroadcastManager.getInstance(this).sendBroadcast(packetBroadcast);
55+
}
56+
} catch (SocketTimeoutException e) {
57+
Logger.w("Socket Timeout");
58+
socket.close();
59+
listening = false;
60+
Intent socketBroadcast = new Intent(GDMService.SOCKET_CLOSED);
61+
socketBroadcast.putExtra(VoiceControlForPlexApplication.Intent.EXTRA_SILENT, intent.getBooleanExtra(VoiceControlForPlexApplication.Intent.EXTRA_SILENT, false));
62+
socketBroadcast.putExtra(VoiceControlForPlexApplication.Intent.EXTRA_CLASS, intent.getSerializableExtra(VoiceControlForPlexApplication.Intent.EXTRA_CLASS));
6763
socketBroadcast.putExtra(VoiceControlForPlexApplication.Intent.SCAN_TYPE, intent.getStringExtra(VoiceControlForPlexApplication.Intent.SCAN_TYPE));
6864
socketBroadcast.putExtra(VoiceControlForPlexApplication.Intent.EXTRA_CONNECT_TO_CLIENT, intent.getBooleanExtra(VoiceControlForPlexApplication.Intent.EXTRA_CONNECT_TO_CLIENT, false));
69-
LocalBroadcastManager.getInstance(this).sendBroadcast(socketBroadcast);
70-
}
71-
}
65+
LocalBroadcastManager.getInstance(this).sendBroadcast(socketBroadcast);
66+
}
67+
}
7268
}
7369
catch (IOException e)
7470
{
@@ -78,17 +74,17 @@ protected void onHandleIntent(Intent intent) {
7874
}
7975

8076
//Builds the broadcast address based on the local network
81-
protected InetAddress getBroadcastAddress() throws IOException
82-
{
83-
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
84-
DhcpInfo dhcp = wifi.getDhcpInfo();
85-
// handle null somehow
77+
protected InetAddress getBroadcastAddress() throws IOException
78+
{
79+
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
80+
DhcpInfo dhcp = wifi.getDhcpInfo();
81+
// handle null somehow
8682

87-
int broadcast = (dhcp.ipAddress & dhcp.netmask) | ~dhcp.netmask;
88-
byte[] quads = new byte[4];
89-
for (int k = 0; k < 4; k++)
90-
quads[k] = (byte) (broadcast >> k * 8);
91-
return InetAddress.getByAddress(quads);
92-
}
83+
int broadcast = (dhcp.ipAddress & dhcp.netmask) | ~dhcp.netmask;
84+
byte[] quads = new byte[4];
85+
for (int k = 0; k < 4; k++)
86+
quads[k] = (byte) (broadcast >> k * 8);
87+
return InetAddress.getByAddress(quads);
88+
}
9389

9490
}

Voice Control For Plex/src/main/java/com/atomjack/vcfp/LocalScan.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import android.content.Context;
55
import android.content.DialogInterface;
66
import android.content.Intent;
7+
import android.support.v4.content.LocalBroadcastManager;
78
import android.view.View;
89
import android.widget.AdapterView;
910
import android.widget.CheckBox;
@@ -15,6 +16,8 @@
1516

1617
import java.util.concurrent.ConcurrentHashMap;
1718

19+
import us.nineworlds.serenity.GDMReceiver;
20+
1821
public class LocalScan {
1922
private Context context;
2023
private Class theClass;
@@ -45,6 +48,7 @@ public void searchForPlexServers(boolean silent) {
4548
searchDialog.setContentView(R.layout.search_popup);
4649
searchDialog.setTitle(context.getResources().getString(R.string.searching_for_plex_servers));
4750

51+
searchDialog.setOnCancelListener(searchDialogCancel);
4852
searchDialog.show();
4953
}
5054

@@ -56,6 +60,15 @@ public void searchForPlexServers(boolean silent) {
5660
context.startService(mServiceIntent);
5761
}
5862

63+
private DialogInterface.OnCancelListener searchDialogCancel = new DialogInterface.OnCancelListener() {
64+
@Override
65+
public void onCancel(DialogInterface dialogInterface) {
66+
Logger.d("Broadcasting cancel to gdmreceiver");
67+
Intent cancelBroadcast = new Intent(GDMReceiver.ACTION_CANCEL);
68+
LocalBroadcastManager.getInstance(context).sendBroadcast(cancelBroadcast);
69+
}
70+
};
71+
5972
public void showPlexServers() {
6073
showPlexServers(null);
6174
}
@@ -103,6 +116,7 @@ public void searchForPlexClients(boolean connectToClient) {
103116

104117
searchDialog.setContentView(R.layout.search_popup);
105118
searchDialog.setTitle(context.getResources().getString(R.string.searching_for_plex_clients));
119+
searchDialog.setOnCancelListener(searchDialogCancel);
106120

107121
searchDialog.show();
108122

Voice Control For Plex/src/main/java/com/atomjack/vcfp/RemoteScan.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ public class RemoteScan {
2626
private static AsyncHttpClient client = new AsyncHttpClient();
2727
private static Serializer serial = new Persister();
2828

29+
private static boolean cancel = false;
30+
2931
public interface RefreshResourcesResponseHandler {
3032
void onSuccess();
3133
void onFailure(int statusCode);
@@ -39,6 +41,9 @@ public static void refreshResources(String authToken) {
3941
refreshResources(authToken, null, true);
4042
}
4143

44+
public static void cancelScan() {
45+
cancel = true;
46+
}
4247

4348
public static void refreshResources(String authToken, final RefreshResourcesResponseHandler responseHandler, boolean silent) {
4449
VoiceControlForPlexApplication.hasDoneClientScan = true;
@@ -49,6 +54,10 @@ public static void refreshResources(String authToken, final RefreshResourcesResp
4954
@Override
5055
public void onSuccess(int statusCode, org.apache.http.Header[] headers, byte[] responseBody) {
5156
try {
57+
if(cancel) {
58+
cancel = false;
59+
return;
60+
}
5261
MediaContainer mediaContainer = new MediaContainer();
5362

5463
try {
@@ -71,12 +80,6 @@ public void onSuccess(int statusCode, org.apache.http.Header[] headers, byte[] r
7180
servers.add(server);
7281
} else if(device.provides.contains("player")) {
7382
Logger.d("Device %s is a player", device.name);
74-
// PlexClient mClient = PlexClient.fromDevice(device);
75-
// if(VoiceControlForPlexApplication.clients == null)
76-
// VoiceControlForPlexApplication.clients = new HashMap<String, PlexClient>();
77-
// if(!VoiceControlForPlexApplication.clients.containsKey(mClient.name)) {
78-
// VoiceControlForPlexApplication.clients.put(mClient.name, mClient);
79-
// }
8083
}
8184
}
8285
// Preferences.put(Preferences.SAVED_CLIENTS, gson.toJson(VoiceControlForPlexApplication.clients));
@@ -110,6 +113,10 @@ public void run() {
110113
@Override
111114
public void onFailure(int statusCode, org.apache.http.Header[] headers, byte[] responseBody, java.lang.Throwable error) {
112115
Logger.d("Failure getting resources: %d", statusCode);
116+
if(cancel) {
117+
cancel = false;
118+
return;
119+
}
113120
error.printStackTrace();
114121
if(responseHandler != null)
115122
responseHandler.onFailure(statusCode);

Voice Control For Plex/src/main/java/com/atomjack/vcfp/VoiceControlForPlexApplication.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public final static class Intent {
9595
public final static String SCAN_TYPE_SERVER = "com.atomjack.vcfp.intent.scan_type_server";
9696
public final static String EXTRA_SERVERS = "com.atomjack.vcfp.intent.extra_servers";
9797
public final static String EXTRA_CLIENTS = "com.atomjack.vcfp.intent.extra_clients";
98-
public final static String ARGUMENTS = "com.atomjack.vcfp.intent.ARGUMENTS";
98+
public final static String ARGUMENTS = "com.atomjack.vcfp.intent.ARGUMENTS";
9999

100100
public final static String SHOWRESOURCE = "com.atomjack.vcfp.intent.SHOWRESOURCE";
101101

Voice Control For Plex/src/main/java/com/atomjack/vcfp/activities/CastActivity.java

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ public void onCastPlayerStateChanged(PlayerState state) {
257257
isSeeking = false;
258258
if(state == PlayerState.STOPPED) {
259259
Logger.d("[CastActivity] media player is idle, finishing");
260+
mNotifyMgr.cancel(mNotificationId);
260261
finish();
261262
} else
262263
setState(state);
@@ -275,14 +276,9 @@ public void onCastPlayerTimeUpdate(int seconds) {
275276
}
276277

277278
@Override
278-
public void onCastPlayerPlaylistAdvance(String key) {
279-
for(PlexMedia track : nowPlayingAlbum) {
280-
if(track.key.equals(key)) {
281-
nowPlayingMedia = track;
282-
setupUI();
283-
showNowPlaying(false);
284-
break;
285-
}
286-
}
279+
public void onCastPlayerPlaylistAdvance(PlexMedia media) {
280+
nowPlayingMedia = media;
281+
setupUI();
282+
showNowPlaying(false);
287283
}
288284
}

Voice Control For Plex/src/main/java/com/atomjack/vcfp/activities/MainActivity.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@
33
import java.io.File;
44
import java.io.FileOutputStream;
55
import java.io.InputStream;
6-
import java.lang.reflect.Type;
76
import java.util.ArrayList;
87
import java.util.HashMap;
9-
import java.util.Map;
108
import java.util.UUID;
119
import java.util.concurrent.Executors;
1210
import java.util.concurrent.Future;
@@ -22,11 +20,9 @@
2220
import android.content.DialogInterface;
2321
import android.content.Intent;
2422
import android.content.IntentFilter;
25-
import android.content.SharedPreferences;
2623
import android.content.pm.PackageInfo;
2724
import android.content.pm.PackageManager;
2825
import android.content.res.AssetManager;
29-
import android.net.ConnectivityManager;
3026
import android.net.Uri;
3127
import android.os.Bundle;
3228
import android.os.Environment;
@@ -73,7 +69,6 @@
7369
import com.cubeactive.martin.inscription.WhatsNewDialog;
7470
import com.google.android.gms.cast.CastDevice;
7571
import com.google.android.gms.cast.CastMediaControlIntent;
76-
import com.google.gson.reflect.TypeToken;
7772
import com.loopj.android.http.AsyncHttpClient;
7873
import com.loopj.android.http.AsyncHttpResponseHandler;
7974
import com.loopj.android.http.RequestParams;
@@ -313,6 +308,12 @@ public void onItemClick(AdapterView<?> adapter, View view, int position,
313308
searchDialog.setContentView(R.layout.search_popup);
314309
searchDialog.setTitle(getResources().getString(R.string.searching_for_plex_servers));
315310

311+
searchDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
312+
@Override
313+
public void onCancel(DialogInterface dialogInterface) {
314+
RemoteScan.cancelScan();
315+
}
316+
});
316317
searchDialog.show();
317318
RemoteScan.refreshResources(authToken, new RemoteScan.RefreshResourcesResponseHandler() {
318319
@Override
@@ -929,6 +930,7 @@ protected void onResume() {
929930
IntentFilter filters = new IntentFilter();
930931
filters.addAction(GDMService.MSG_RECEIVED);
931932
filters.addAction(GDMService.SOCKET_CLOSED);
933+
filters.addAction(GDMReceiver.ACTION_CANCEL);
932934
LocalBroadcastManager.getInstance(this).registerReceiver(gdmReceiver,
933935
filters);
934936
}
@@ -998,6 +1000,10 @@ public void onRouteRemoved(MediaRouter router, MediaRouter.RouteInfo route) {
9981000
Logger.d("Cast Client %s has gone missing. Removing.", route.getName());
9991001
VoiceControlForPlexApplication.castClients.remove(route.getName());
10001002
Preferences.put(Preferences.SAVED_CAST_CLIENTS, gsonWrite.toJson(VoiceControlForPlexApplication.castClients));
1003+
// If the "select a plex client" dialog is showing, refresh the list of clients
1004+
if(localScan.isDeviceDialogShowing()) {
1005+
localScan.deviceSelectDialogRefresh();
1006+
}
10011007
}
10021008
}
10031009

Voice Control For Plex/src/main/java/com/atomjack/vcfp/activities/ShortcutProviderActivity.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ protected void onResume() {
149149
IntentFilter filters = new IntentFilter();
150150
filters.addAction(GDMService.MSG_RECEIVED);
151151
filters.addAction(GDMService.SOCKET_CLOSED);
152+
filters.addAction(GDMReceiver.ACTION_CANCEL);
152153
LocalBroadcastManager.getInstance(this).registerReceiver(gdmReceiver,
153154
filters);
154155
}

Voice Control For Plex/src/main/java/com/atomjack/vcfp/activities/VCFPActivity.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ public abstract class VCFPActivity extends ActionBarActivity implements PlexSubs
8888
protected boolean continuing = false;
8989

9090
int mNotificationId = 0;
91-
NotificationManager mNotifyMgr;
91+
protected NotificationManager mNotifyMgr;
9292

9393
protected NetworkMonitor networkMonitor;
9494

@@ -399,7 +399,7 @@ protected void setCastIconActive() {
399399
public void onCastConnected(PlexClient _client) {
400400
Logger.d("[VCFPActivity] onCastConnected");
401401
onSubscribed(_client);
402-
castPlayerManager.getPlaybackState();
402+
// castPlayerManager.getPlaybackState();
403403
}
404404

405405
@Override
@@ -674,7 +674,7 @@ public void onDisconnected() {
674674
}
675675

676676
@Override
677-
public void onCastPlayerPlaylistAdvance(String key) {
677+
public void onCastPlayerPlaylistAdvance(PlexMedia media) {
678678

679679
}
680680
}

0 commit comments

Comments
 (0)