|
@@ -54,20 +54,33 @@ public class MPRISSource implements MediaSource {
|
54
|
54
|
this.source = source;
|
55
|
55
|
this.service = service;
|
56
|
56
|
|
57
|
|
- final List<String> info = source.doDBusCall("org.mpris." + service, "/",
|
58
|
|
- "org.freedesktop.MediaPlayer.Identity");
|
|
57
|
+ final String info = getFirstValue("org.mpris.MediaPlayer2.Identity");
|
59
|
58
|
|
60
|
59
|
if (info.isEmpty()) {
|
61
|
60
|
throw new IllegalArgumentException("No service with that name found");
|
62
|
61
|
}
|
63
|
62
|
|
64
|
|
- this.name = info.get(0).replace(' ', '_');
|
|
63
|
+ this.name = info.replace(' ', '_');
|
|
64
|
+ }
|
|
65
|
+
|
|
66
|
+ /**
|
|
67
|
+ * Get the first line of the output for a dbus call to the given function
|
|
68
|
+ * against this service in the /org/mpris/MediaPlayer2 obejct.
|
|
69
|
+ *
|
|
70
|
+ * @param function Function to get data for.
|
|
71
|
+ * @return First line of output.
|
|
72
|
+ */
|
|
73
|
+ protected String getFirstValue(final String function) {
|
|
74
|
+ final List<String> info = source.doDBusCall("org.mpris." + service,
|
|
75
|
+ "/org/mpris/MediaPlayer2", function);
|
|
76
|
+
|
|
77
|
+ return info.isEmpty() ? "" : info.get(0);
|
65
|
78
|
}
|
66
|
79
|
|
67
|
80
|
/** {@inheritDoc} */
|
68
|
81
|
@Override
|
69
|
82
|
public MediaSourceState getState() {
|
70
|
|
- final char[] status = getStatus();
|
|
83
|
+ final String status = getStatus();
|
71
|
84
|
|
72
|
85
|
if (status == null) {
|
73
|
86
|
data = null;
|
|
@@ -76,11 +89,11 @@ public class MPRISSource implements MediaSource {
|
76
|
89
|
|
77
|
90
|
data = getTrackInfo();
|
78
|
91
|
|
79
|
|
- if (status[0] == '0') {
|
|
92
|
+ if (status.equalsIgnoreCase("Playing")) {
|
80
|
93
|
return MediaSourceState.PLAYING;
|
81
|
|
- } else if (status[0] == '1') {
|
|
94
|
+ } else if (status.equalsIgnoreCase("Paused")) {
|
82
|
95
|
return MediaSourceState.PAUSED;
|
83
|
|
- } else if (status[0] == '2') {
|
|
96
|
+ } else if (status.equalsIgnoreCase("Stopped")) {
|
84
|
97
|
return MediaSourceState.STOPPED;
|
85
|
98
|
} else {
|
86
|
99
|
return MediaSourceState.NOTKNOWN;
|
|
@@ -108,31 +121,46 @@ public class MPRISSource implements MediaSource {
|
108
|
121
|
/** {@inheritDoc} */
|
109
|
122
|
@Override
|
110
|
123
|
public String getArtist() {
|
111
|
|
- return getData("artist");
|
|
124
|
+ return getData("xesam:artist");
|
112
|
125
|
}
|
113
|
126
|
|
114
|
127
|
/** {@inheritDoc} */
|
115
|
128
|
@Override
|
116
|
129
|
public String getTitle() {
|
117
|
|
- return getData("title");
|
|
130
|
+ return getData("xesam:title");
|
118
|
131
|
}
|
119
|
132
|
|
120
|
133
|
/** {@inheritDoc} */
|
121
|
134
|
@Override
|
122
|
135
|
public String getAlbum() {
|
123
|
|
- return getData("album");
|
|
136
|
+ return getData("xesam:album");
|
124
|
137
|
}
|
125
|
138
|
|
126
|
139
|
/** {@inheritDoc} */
|
127
|
140
|
@Override
|
128
|
141
|
public String getLength() {
|
129
|
|
- return getData("time");
|
|
142
|
+ try {
|
|
143
|
+ final Long len = Long.parseLong(getData("mpris:length"));
|
|
144
|
+ return duration(len / 1000);
|
|
145
|
+ } catch (final NumberFormatException nfe) {
|
|
146
|
+ return "Unknown";
|
|
147
|
+ }
|
130
|
148
|
}
|
131
|
149
|
|
132
|
150
|
/** {@inheritDoc} */
|
133
|
151
|
@Override
|
134
|
152
|
public String getTime() {
|
135
|
|
- return "Unknown";
|
|
153
|
+ try {
|
|
154
|
+ final String position = getFirstValue("org.mpris.MediaPlayer2.Player.Position");
|
|
155
|
+ final Long len = Long.parseLong(position);
|
|
156
|
+ if (len == 0) {
|
|
157
|
+ return "Unknown";
|
|
158
|
+ } else {
|
|
159
|
+ return duration(len / 1000);
|
|
160
|
+ }
|
|
161
|
+ } catch (final NumberFormatException nfe) {
|
|
162
|
+ return "Unknown";
|
|
163
|
+ }
|
136
|
164
|
}
|
137
|
165
|
|
138
|
166
|
/** {@inheritDoc} */
|
|
@@ -144,7 +172,7 @@ public class MPRISSource implements MediaSource {
|
144
|
172
|
/** {@inheritDoc} */
|
145
|
173
|
@Override
|
146
|
174
|
public String getBitrate() {
|
147
|
|
- return getData("audio-bitrate");
|
|
175
|
+ return "Unknown";
|
148
|
176
|
}
|
149
|
177
|
|
150
|
178
|
/**
|
|
@@ -153,11 +181,8 @@ public class MPRISSource implements MediaSource {
|
153
|
181
|
* @return A map of metadata returned by the MPRIS service
|
154
|
182
|
*/
|
155
|
183
|
protected Map<String, String> getTrackInfo() {
|
156
|
|
- // If only there were a standard...
|
157
|
184
|
final List<String> list = source.doDBusCall("org.mpris." + service,
|
158
|
|
- "/Player", "org.freedesktop.MediaPlayer.GetMetadata");
|
159
|
|
- list.addAll(source.doDBusCall("org.mpris." + service,
|
160
|
|
- "/Player", "org.freedesktop.MediaPlayer.GetMetaData"));
|
|
185
|
+ "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player.Metadata");
|
161
|
186
|
return DBusMediaSource.parseDictionary(list);
|
162
|
187
|
}
|
163
|
188
|
|
|
@@ -166,35 +191,46 @@ public class MPRISSource implements MediaSource {
|
166
|
191
|
*
|
167
|
192
|
* @return The returned status or null if the service isn't running
|
168
|
193
|
*/
|
169
|
|
- protected char[] getStatus() {
|
170
|
|
- if (source.doDBusCall("org.mpris." + service, "/",
|
171
|
|
- "org.freedesktop.MediaPlayer.Identity").isEmpty()) {
|
172
|
|
- // Calling dbus-send can seemingly start applications that have
|
173
|
|
- // quit (not entirely sure how), so check that it's running first.
|
|
194
|
+ protected String getStatus() {
|
|
195
|
+ if (getFirstValue("org.mpris.MediaPlayer2.Identity").isEmpty()) {
|
174
|
196
|
return null;
|
175
|
197
|
}
|
176
|
198
|
|
177
|
|
- final List<String> res = DBusMediaSource.getInfo(new String[]{
|
178
|
|
- "/usr/bin/dbus-send", "--print-reply", "--dest=org.mpris." + service,
|
179
|
|
- "/Player", "org.freedesktop.MediaPlayer.GetStatus"
|
180
|
|
- });
|
|
199
|
+ return getFirstValue("org.mpris.MediaPlayer2.Player.PlaybackStatus");
|
|
200
|
+ }
|
181
|
201
|
|
182
|
|
- if (res.isEmpty()) {
|
183
|
|
- return null;
|
|
202
|
+ /**
|
|
203
|
+ * Get the duration in seconds as a string.
|
|
204
|
+ *
|
|
205
|
+ * @param seconds Input to get duration for
|
|
206
|
+ * @return Duration as a string
|
|
207
|
+ */
|
|
208
|
+ private String duration(final long secondsInput) {
|
|
209
|
+ final StringBuilder result = new StringBuilder();
|
|
210
|
+ final long hours = secondsInput / 3600;
|
|
211
|
+ final long minutes = secondsInput / 60 % 60;
|
|
212
|
+ final long seconds = secondsInput % 60;
|
|
213
|
+
|
|
214
|
+ if (hours > 0) {
|
|
215
|
+ if (hours < 10) {
|
|
216
|
+ result.append('0');
|
|
217
|
+ }
|
|
218
|
+
|
|
219
|
+ result.append(hours).append(":");
|
184
|
220
|
}
|
185
|
221
|
|
186
|
|
- final char[] result = new char[4];
|
187
|
|
- int i = 0;
|
|
222
|
+ if (minutes < 10) {
|
|
223
|
+ result.append('0');
|
|
224
|
+ }
|
188
|
225
|
|
189
|
|
- for (String line : res) {
|
190
|
|
- final String tline = line.trim();
|
|
226
|
+ result.append(minutes).append(":");
|
191
|
227
|
|
192
|
|
- if (tline.startsWith("int32")) {
|
193
|
|
- result[i++] = tline.charAt(tline.length() - 1);
|
194
|
|
- }
|
|
228
|
+ if (seconds < 10) {
|
|
229
|
+ result.append('0');
|
195
|
230
|
}
|
196
|
231
|
|
197
|
|
- return result;
|
198
|
|
- }
|
|
232
|
+ result.append(seconds);
|
199
|
233
|
|
|
234
|
+ return result.toString();
|
|
235
|
+ }
|
200
|
236
|
}
|