Changeset View
Changeset View
Standalone View
Standalone View
src/org/kde/kdeconnect/Plugins/MprisPlugin/MprisPlugin.java
Show All 27 Lines | |||||
28 | import android.support.v4.content.ContextCompat; | 28 | import android.support.v4.content.ContextCompat; | ||
29 | import android.util.Log; | 29 | import android.util.Log; | ||
30 | 30 | | |||
31 | import org.kde.kdeconnect.NetworkPackage; | 31 | import org.kde.kdeconnect.NetworkPackage; | ||
32 | import org.kde.kdeconnect.Plugins.Plugin; | 32 | import org.kde.kdeconnect.Plugins.Plugin; | ||
33 | import org.kde.kdeconnect_tp.R; | 33 | import org.kde.kdeconnect_tp.R; | ||
34 | 34 | | |||
35 | import java.util.ArrayList; | 35 | import java.util.ArrayList; | ||
36 | import java.util.Collections; | ||||
36 | import java.util.HashMap; | 37 | import java.util.HashMap; | ||
38 | import java.util.Iterator; | ||||
37 | import java.util.List; | 39 | import java.util.List; | ||
40 | import java.util.Map; | ||||
38 | 41 | | |||
39 | public class MprisPlugin extends Plugin { | 42 | public class MprisPlugin extends Plugin { | ||
40 | 43 | public static class MprisPlayer { | |||
41 | public final static String PACKAGE_TYPE_MPRIS = "kdeconnect.mpris"; | | |||
42 | public final static String PACKAGE_TYPE_MPRIS_REQUEST = "kdeconnect.mpris.request"; | | |||
43 | | ||||
44 | private String player = ""; | 44 | private String player = ""; | ||
45 | private boolean playing = false; | 45 | private boolean playing = false; | ||
46 | private String currentSong = ""; | 46 | private String currentSong = ""; | ||
47 | private int volume = 50; | 47 | private int volume = 50; | ||
48 | private long length = -1; | 48 | private long length = -1; | ||
49 | private long lastPosition; | 49 | private long lastPosition = 0; | ||
50 | private long lastPositionTime; | 50 | private long lastPositionTime; | ||
51 | private boolean playAllowed = true; | 51 | private boolean playAllowed = true; | ||
52 | private boolean pauseAllowed = true; | 52 | private boolean pauseAllowed = true; | ||
53 | private boolean goNextAllowed = true; | 53 | private boolean goNextAllowed = true; | ||
54 | private boolean goPreviousAllowed = true; | 54 | private boolean goPreviousAllowed = true; | ||
55 | private boolean seekAllowed = true; | 55 | private boolean seekAllowed = true; | ||
56 | | ||||
57 | public MprisPlayer() { | ||||
58 | lastPositionTime = System.currentTimeMillis(); | ||||
59 | } | ||||
60 | | ||||
61 | public String getCurrentSong() { | ||||
62 | return currentSong; | ||||
63 | } | ||||
64 | | ||||
65 | public String getPlayer() { | ||||
66 | return player; | ||||
67 | } | ||||
68 | | ||||
69 | public int getVolume() { | ||||
70 | return volume; | ||||
71 | } | ||||
72 | | ||||
73 | public long getLength(){ return length; } | ||||
74 | | ||||
75 | public boolean isPlaying() { | ||||
76 | return playing; | ||||
77 | } | ||||
78 | | ||||
79 | public boolean isPlayAllowed() { | ||||
80 | return playAllowed; | ||||
81 | } | ||||
82 | | ||||
83 | public boolean isPauseAllowed() { | ||||
84 | return pauseAllowed; | ||||
85 | } | ||||
86 | | ||||
87 | public boolean isGoNextAllowed() { | ||||
88 | return goNextAllowed; | ||||
89 | } | ||||
90 | | ||||
91 | public boolean isGoPreviousAllowed() { | ||||
92 | return goPreviousAllowed; | ||||
93 | } | ||||
94 | | ||||
95 | public boolean isSeekAllowed() { | ||||
96 | return seekAllowed; | ||||
97 | } | ||||
98 | | ||||
99 | public long getPosition(){ | ||||
100 | if(playing) { | ||||
101 | return lastPosition + (System.currentTimeMillis() - lastPositionTime); | ||||
102 | } else { | ||||
103 | return lastPosition; | ||||
104 | } | ||||
105 | } | ||||
106 | } | ||||
107 | | ||||
108 | public final static String PACKAGE_TYPE_MPRIS = "kdeconnect.mpris"; | ||||
109 | public final static String PACKAGE_TYPE_MPRIS_REQUEST = "kdeconnect.mpris.request"; | ||||
110 | | ||||
111 | private HashMap<String, MprisPlayer> players = new HashMap<>(); | ||||
56 | private HashMap<String,Handler> playerStatusUpdated = new HashMap<>(); | 112 | private HashMap<String,Handler> playerStatusUpdated = new HashMap<>(); | ||
57 | 113 | | |||
58 | private List<String> playerList = new ArrayList<>(); | | |||
59 | private HashMap<String,Handler> playerListUpdated = new HashMap<>(); | 114 | private HashMap<String,Handler> playerListUpdated = new HashMap<>(); | ||
60 | 115 | | |||
61 | @Override | 116 | @Override | ||
62 | public String getDisplayName() { | 117 | public String getDisplayName() { | ||
63 | return context.getResources().getString(R.string.pref_plugin_mpris); | 118 | return context.getResources().getString(R.string.pref_plugin_mpris); | ||
64 | } | 119 | } | ||
65 | 120 | | |||
66 | @Override | 121 | @Override | ||
Show All 9 Lines | |||||
76 | @Override | 131 | @Override | ||
77 | public boolean hasSettings() { | 132 | public boolean hasSettings() { | ||
78 | return true; | 133 | return true; | ||
79 | } | 134 | } | ||
80 | 135 | | |||
81 | @Override | 136 | @Override | ||
82 | public boolean onCreate() { | 137 | public boolean onCreate() { | ||
83 | requestPlayerList(); | 138 | requestPlayerList(); | ||
84 | lastPositionTime = System.currentTimeMillis(); | | |||
85 | return true; | 139 | return true; | ||
86 | } | 140 | } | ||
87 | 141 | | |||
88 | @Override | 142 | @Override | ||
89 | public void onDestroy() { | 143 | public void onDestroy() { | ||
90 | playerList.clear(); | 144 | players.clear(); | ||
91 | } | 145 | } | ||
92 | 146 | | |||
93 | public void sendAction(String player, String action) { | 147 | public void sendAction(String player, String action) { | ||
94 | NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MPRIS_REQUEST); | 148 | NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MPRIS_REQUEST); | ||
95 | np.set("player", player); | 149 | np.set("player", player); | ||
96 | np.set("action", action); | 150 | np.set("action", action); | ||
97 | device.sendPackage(np); | 151 | device.sendPackage(np); | ||
98 | } | 152 | } | ||
99 | public void sendAction(String action) { | | |||
100 | sendAction(player, action); | | |||
101 | } | | |||
102 | 153 | | |||
103 | public void setVolume(int volume) { | 154 | public void setVolume(String player, int volume) { | ||
104 | NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MPRIS_REQUEST); | 155 | NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MPRIS_REQUEST); | ||
105 | np.set("player", player); | 156 | np.set("player", player); | ||
106 | np.set("setVolume",volume); | 157 | np.set("setVolume",volume); | ||
107 | device.sendPackage(np); | 158 | device.sendPackage(np); | ||
108 | } | 159 | } | ||
109 | 160 | | |||
110 | public void setPosition(int position) { | 161 | public void setPosition(String player, int position) { | ||
111 | NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MPRIS_REQUEST); | 162 | NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MPRIS_REQUEST); | ||
112 | np.set("player", player); | 163 | np.set("player", player); | ||
113 | np.set("SetPosition", position); | 164 | np.set("SetPosition", position); | ||
114 | device.sendPackage(np); | 165 | device.sendPackage(np); | ||
115 | this.lastPosition = position; | 166 | | ||
116 | this.lastPositionTime = System.currentTimeMillis(); | 167 | MprisPlayer playerStatus = players.get(player); | ||
168 | if (playerStatus != null) { | ||||
169 | playerStatus.lastPosition = position; | ||||
170 | playerStatus.lastPositionTime = System.currentTimeMillis(); | ||||
171 | } | ||||
117 | } | 172 | } | ||
118 | 173 | | |||
119 | public void Seek(int offset) { | 174 | public void Seek(String player, int offset) { | ||
120 | NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MPRIS_REQUEST); | 175 | NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MPRIS_REQUEST); | ||
121 | np.set("player", player); | 176 | np.set("player", player); | ||
122 | np.set("Seek", offset); | 177 | np.set("Seek", offset); | ||
123 | device.sendPackage(np); | 178 | device.sendPackage(np); | ||
124 | } | 179 | } | ||
125 | 180 | | |||
126 | @Override | 181 | @Override | ||
127 | public boolean onPackageReceived(NetworkPackage np) { | 182 | public boolean onPackageReceived(NetworkPackage np) { | ||
128 | | ||||
129 | if (np.has("nowPlaying") || np.has("volume") || np.has("isPlaying") || np.has("length") || np.has("pos")) { | 183 | if (np.has("nowPlaying") || np.has("volume") || np.has("isPlaying") || np.has("length") || np.has("pos")) { | ||
130 | if (np.getString("player").equals(player)) { | 184 | MprisPlayer playerStatus = players.get(np.getString("player")); | ||
131 | currentSong = np.getString("nowPlaying", currentSong); | 185 | if (playerStatus != null) { | ||
132 | volume = np.getInt("volume", volume); | 186 | playerStatus.currentSong = np.getString("nowPlaying", playerStatus.currentSong); | ||
133 | length = np.getLong("length", length); | 187 | playerStatus.volume = np.getInt("volume", playerStatus.volume); | ||
188 | playerStatus.length = np.getLong("length", playerStatus.length); | ||||
134 | if(np.has("pos")){ | 189 | if(np.has("pos")){ | ||
135 | lastPosition = np.getLong("pos", lastPosition); | 190 | playerStatus.lastPosition = np.getLong("pos", playerStatus.lastPosition); | ||
136 | lastPositionTime = System.currentTimeMillis(); | 191 | playerStatus.lastPositionTime = System.currentTimeMillis(); | ||
137 | } | 192 | } | ||
138 | playing = np.getBoolean("isPlaying", playing); | 193 | playerStatus.playing = np.getBoolean("isPlaying", playerStatus.playing); | ||
139 | playAllowed = np.getBoolean("canPlay", playAllowed); | 194 | playerStatus.playAllowed = np.getBoolean("canPlay", playerStatus.playAllowed); | ||
140 | pauseAllowed = np.getBoolean("canPause", pauseAllowed); | 195 | playerStatus.pauseAllowed = np.getBoolean("canPause", playerStatus.pauseAllowed); | ||
141 | goNextAllowed = np.getBoolean("canGoNext", goNextAllowed); | 196 | playerStatus.goNextAllowed = np.getBoolean("canGoNext", playerStatus.goNextAllowed); | ||
142 | goPreviousAllowed = np.getBoolean("canGoPrevious", goPreviousAllowed); | 197 | playerStatus.goPreviousAllowed = np.getBoolean("canGoPrevious", playerStatus.goPreviousAllowed); | ||
143 | seekAllowed = np.getBoolean("canSeek", seekAllowed); | 198 | playerStatus.seekAllowed = np.getBoolean("canSeek", playerStatus.seekAllowed); | ||
144 | for (String key : playerStatusUpdated.keySet()) { | 199 | for (String key : playerStatusUpdated.keySet()) { | ||
145 | try { | 200 | try { | ||
146 | playerStatusUpdated.get(key).dispatchMessage(new Message()); | 201 | playerStatusUpdated.get(key).dispatchMessage(new Message()); | ||
147 | } catch(Exception e) { | 202 | } catch(Exception e) { | ||
148 | e.printStackTrace(); | 203 | e.printStackTrace(); | ||
149 | Log.e("MprisControl","Exception"); | 204 | Log.e("MprisControl","Exception"); | ||
150 | playerStatusUpdated.remove(key); | 205 | playerStatusUpdated.remove(key); | ||
151 | } | 206 | } | ||
152 | } | 207 | } | ||
153 | } | 208 | } | ||
154 | } | 209 | } | ||
155 | 210 | | |||
156 | List<String> newPlayerList = np.getStringList("playerList"); | 211 | List<String> newPlayerList = np.getStringList("playerList"); | ||
157 | if (newPlayerList != null) { | 212 | if (newPlayerList != null) { | ||
158 | boolean equals = false; | 213 | boolean equals = true; | ||
159 | if (newPlayerList.size() == playerList.size()) { | 214 | for (String newPlayer : newPlayerList) { | ||
160 | equals = true; | 215 | if (!players.containsKey(newPlayer)) { | ||
161 | for (int i=0; i<newPlayerList.size(); i++) { | | |||
162 | if (!newPlayerList.get(i).equals(playerList.get(i))) { | | |||
163 | equals = false; | 216 | equals = false; | ||
217 | | ||||
218 | MprisPlayer player = new MprisPlayer(); | ||||
219 | player.player = newPlayer; | ||||
220 | players.put(newPlayer, player); | ||||
221 | | ||||
222 | //Immediately ask for the data of this player | ||||
223 | requestPlayerStatus(newPlayer); | ||||
224 | } | ||||
225 | } | ||||
226 | Iterator<HashMap.Entry<String, MprisPlayer>> iter = players.entrySet().iterator(); | ||||
227 | while (iter.hasNext()) { | ||||
228 | String oldPlayer = iter.next().getKey(); | ||||
229 | | ||||
230 | boolean found = false; | ||||
231 | for (String newPlayer : newPlayerList) { | ||||
232 | if (newPlayer.equals(oldPlayer)) { | ||||
233 | found = true; | ||||
164 | break; | 234 | break; | ||
165 | } | 235 | } | ||
166 | } | 236 | } | ||
237 | | ||||
238 | if (!found) { | ||||
239 | iter.remove(); | ||||
240 | equals = false; | ||||
241 | } | ||||
167 | } | 242 | } | ||
168 | if (!equals) { | 243 | if (!equals) { | ||
169 | playerList = newPlayerList; | | |||
170 | for (String key : playerListUpdated.keySet()) { | 244 | for (String key : playerListUpdated.keySet()) { | ||
171 | try { | 245 | try { | ||
172 | playerListUpdated.get(key).dispatchMessage(new Message()); | 246 | playerListUpdated.get(key).dispatchMessage(new Message()); | ||
173 | } catch(Exception e) { | 247 | } catch(Exception e) { | ||
174 | e.printStackTrace(); | 248 | e.printStackTrace(); | ||
175 | Log.e("MprisControl","Exception"); | 249 | Log.e("MprisControl","Exception"); | ||
176 | playerListUpdated.remove(key); | 250 | playerListUpdated.remove(key); | ||
177 | } | 251 | } | ||
Show All 15 Lines | |||||
193 | } | 267 | } | ||
194 | 268 | | |||
195 | public void setPlayerStatusUpdatedHandler(String id, Handler h) { | 269 | public void setPlayerStatusUpdatedHandler(String id, Handler h) { | ||
196 | playerStatusUpdated.put(id, h); | 270 | playerStatusUpdated.put(id, h); | ||
197 | 271 | | |||
198 | h.dispatchMessage(new Message()); | 272 | h.dispatchMessage(new Message()); | ||
199 | 273 | | |||
200 | //Get the status if this is the first handler we have | 274 | //Get the status if this is the first handler we have | ||
201 | if (playerListUpdated.size() == 1) { | 275 | if (playerListUpdated.size() == 1 && !players.isEmpty()) { | ||
202 | requestPlayerStatus(); | 276 | requestPlayerStatus(getPlayerList().get(0)); | ||
203 | } | 277 | } | ||
204 | } | 278 | } | ||
205 | 279 | | |||
206 | public void setPlayerListUpdatedHandler(String id, Handler h) { | 280 | public void setPlayerListUpdatedHandler(String id, Handler h) { | ||
207 | playerListUpdated.put(id,h); | 281 | playerListUpdated.put(id,h); | ||
208 | 282 | | |||
209 | h.dispatchMessage(new Message()); | 283 | h.dispatchMessage(new Message()); | ||
210 | 284 | | |||
211 | //Get the status if this is the first handler we have | 285 | //Get the status if this is the first handler we have | ||
212 | if (playerListUpdated.size() == 1) { | 286 | if (playerListUpdated.size() == 1) { | ||
213 | requestPlayerList(); | 287 | requestPlayerList(); | ||
214 | } | 288 | } | ||
215 | } | 289 | } | ||
216 | 290 | | |||
217 | public void setPlayer(String player) { | | |||
218 | if (player == null || player.equals(this.player)) return; | | |||
219 | this.player = player; | | |||
220 | currentSong = ""; | | |||
221 | volume = 50; | | |||
222 | playing = false; | | |||
223 | playAllowed = true; | | |||
224 | pauseAllowed = true; | | |||
225 | goNextAllowed = true; | | |||
226 | goPreviousAllowed = true; | | |||
227 | seekAllowed = true; | | |||
228 | for (String key : playerStatusUpdated.keySet()) { | | |||
229 | try { | | |||
230 | playerStatusUpdated.get(key).dispatchMessage(new Message()); | | |||
231 | } catch(Exception e) { | | |||
232 | e.printStackTrace(); | | |||
233 | Log.e("MprisControl","Exception"); | | |||
234 | playerStatusUpdated.remove(key); | | |||
235 | } | | |||
236 | } | | |||
237 | requestPlayerStatus(); | | |||
238 | } | | |||
239 | | ||||
240 | public List<String> getPlayerList() { | 291 | public List<String> getPlayerList() { | ||
241 | return playerList; | 292 | List<String> playerlist = new ArrayList<>(players.keySet()); | ||
242 | } | 293 | Collections.sort(playerlist); | ||
243 | 294 | return playerlist; | |||
244 | public String getCurrentSong() { | | |||
245 | return currentSong; | | |||
246 | } | | |||
247 | | ||||
248 | public String getPlayer() { | | |||
249 | return player; | | |||
250 | } | | |||
251 | | ||||
252 | public int getVolume() { | | |||
253 | return volume; | | |||
254 | } | | |||
255 | | ||||
256 | public long getLength(){ return length; } | | |||
257 | | ||||
258 | public boolean isPlaying() { | | |||
259 | return playing; | | |||
260 | } | | |||
261 | | ||||
262 | public boolean isPlayAllowed() { | | |||
263 | return playAllowed; | | |||
264 | } | | |||
265 | | ||||
266 | public boolean isPauseAllowed() { | | |||
267 | return pauseAllowed; | | |||
268 | } | 295 | } | ||
269 | 296 | | |||
270 | public boolean isGoNextAllowed() { | 297 | public MprisPlayer getPlayerStatus(String player) { | ||
271 | return goNextAllowed; | 298 | return players.get(player); | ||
272 | } | | |||
273 | | ||||
274 | public boolean isGoPreviousAllowed() { | | |||
275 | return goPreviousAllowed; | | |||
276 | } | | |||
277 | | ||||
278 | public boolean isSeekAllowed() { | | |||
279 | return seekAllowed; | | |||
280 | } | | |||
281 | | ||||
282 | public long getPosition(){ | | |||
283 | if(playing) { | | |||
284 | return lastPosition + (System.currentTimeMillis() - lastPositionTime); | | |||
285 | } else { | | |||
286 | return lastPosition; | | |||
287 | } | | |||
288 | } | 299 | } | ||
289 | 300 | | |||
290 | private void requestPlayerList() { | 301 | private void requestPlayerList() { | ||
291 | NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MPRIS_REQUEST); | 302 | NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MPRIS_REQUEST); | ||
292 | np.set("requestPlayerList",true); | 303 | np.set("requestPlayerList",true); | ||
293 | device.sendPackage(np); | 304 | device.sendPackage(np); | ||
294 | } | 305 | } | ||
295 | 306 | | |||
296 | private void requestPlayerStatus() { | 307 | private void requestPlayerStatus(String player) { | ||
297 | NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MPRIS_REQUEST); | 308 | NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MPRIS_REQUEST); | ||
298 | np.set("player",player); | 309 | np.set("player", player); | ||
299 | np.set("requestNowPlaying",true); | 310 | np.set("requestNowPlaying",true); | ||
300 | np.set("requestVolume",true); | 311 | np.set("requestVolume",true); | ||
301 | device.sendPackage(np); | 312 | device.sendPackage(np); | ||
302 | } | 313 | } | ||
303 | 314 | | |||
304 | @Override | 315 | @Override | ||
305 | public boolean hasMainActivity() { | 316 | public boolean hasMainActivity() { | ||
306 | return true; | 317 | return true; | ||
Show All 15 Lines |