Skip to content

Commit 3cc16b9

Browse files
committed
improve address search of track id, add unregisterListener, version 1.0.4
1 parent 21a77e1 commit 3cc16b9

File tree

12 files changed

+120
-35
lines changed

12 files changed

+120
-35
lines changed

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ repositories {
1414
}
1515
1616
dependencies {
17-
implementation 'com.github.LabyStudio:java-spotify-api:1.0.3:all'
17+
implementation 'com.github.LabyStudio:java-spotify-api:1.0.4:all'
1818
}
1919
```
2020

@@ -83,4 +83,7 @@ api.registerListener(new SpotifyListener() {
8383
// api.stop();
8484
}
8585
});
86+
87+
// Initialize the API
88+
api.initialize();
8689
```

build.gradle

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ plugins {
44
}
55

66
group 'de.labystudio'
7-
version '1.0.3'
7+
version '1.0.4'
88

99
compileJava {
1010
sourceCompatibility = '1.8'
@@ -20,6 +20,19 @@ dependencies {
2020
implementation group: 'net.java.dev.jna', name: 'jna-platform', version: '4.5.0'
2121
}
2222

23+
sourceSets {
24+
main {
25+
java {
26+
srcDir 'src/main/java'
27+
srcDir 'src/test/java'
28+
}
29+
30+
resources {
31+
srcDir 'src/main/resources'
32+
srcDir 'src/test/resources'
33+
}
34+
}
35+
}
2336

2437
java {
2538
withSourcesJar()

src/main/java/de/labystudio/spotifyapi/SpotifyAPI.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,15 @@ default boolean hasTrack() {
8585
*/
8686
void registerListener(SpotifyListener listener);
8787

88+
/**
89+
* Unregisters a listener.
90+
*
91+
* @param listener the listener to unregister
92+
*/
93+
void unregisterListener(SpotifyListener listener);
94+
8895
/**
8996
* Disconnect from the Spotify application and stop all background tasks.
90-
* It will also remove all listeners.
9197
*/
9298
void stop();
9399
}

src/main/java/de/labystudio/spotifyapi/platform/AbstractSpotifyAPI.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public void registerListener(SpotifyListener listener) {
2424
}
2525

2626
@Override
27-
public void stop() {
28-
this.listeners.clear();
27+
public void unregisterListener(SpotifyListener listener) {
28+
this.listeners.remove(listener);
2929
}
3030
}

src/main/java/de/labystudio/spotifyapi/platform/osx/OSXSpotifyApi.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,10 @@ public boolean isPlaying() {
4444
public boolean isConnected() {
4545
return false; // TODO Implement OSX SpotifyAPI
4646
}
47+
48+
@Override
49+
public void stop() {
50+
51+
}
52+
4753
}

src/main/java/de/labystudio/spotifyapi/platform/windows/WinSpotifyAPI.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,6 @@ public boolean isConnected() {
160160

161161
@Override
162162
public void stop() {
163-
super.stop();
164-
165163
if (this.task != null) {
166164
this.task.cancel(true);
167165
this.task = null;

src/main/java/de/labystudio/spotifyapi/platform/windows/api/WinApi.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ default String getWindowTitle(WinDef.HWND window) {
9898
return Native.toString(Arrays.copyOf(buffer, length));
9999
}
100100

101-
default Map<Long, Long> getModules(int pid) {
101+
default Map<Long, Long> getModules(long pid) {
102102
Map<Long, Long> map = new HashMap<>();
103103

104104
WinNT.HANDLE snapshot = Kernel32.INSTANCE.CreateToolhelp32Snapshot(
@@ -117,7 +117,7 @@ default Map<Long, Long> getModules(int pid) {
117117
return map;
118118
}
119119

120-
default long getModuleAddress(int pid, String moduleName) {
120+
default long getModuleAddress(long pid, String moduleName) {
121121
WinNT.HANDLE snapshot = Kernel32.INSTANCE.CreateToolhelp32Snapshot(
122122
Tlhelp32.TH32CS_SNAPMODULE,
123123
new WinDef.DWORD(pid)

src/main/java/de/labystudio/spotifyapi/platform/windows/api/WinProcess.java

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,16 +148,63 @@ public long findInMemory(long address, long size, byte[] searchBytes) {
148148
public long findInMemory(long address, long size, byte[] searchBytes, SearchCondition condition) {
149149
long cursor = address;
150150
long maxAddress = size - address;
151+
int index = 0;
151152
while (cursor < maxAddress) {
152153
long target = this.findInMemory(cursor, maxAddress, searchBytes);
153-
if (condition.matches(target)) {
154+
if (condition.matches(target, index)) {
154155
return target;
155156
}
156157
cursor = target + 1;
158+
index++;
157159
}
158160
return -1;
159161
}
160162

163+
/**
164+
* Find the address of a text inside the memory.
165+
* If there are multiple matches of the text, the given index will be used to select the correct one.
166+
*
167+
* @param start The address to start searching from.
168+
* @param text The text to search for.
169+
* @param index The amount of matches to skip
170+
* @return The address of the text at the given index
171+
*/
172+
public long findAddressOfText(long start, String text, int index) {
173+
long maxAddress = this.getMaxProcessAddress();
174+
return this.findInMemory(start, maxAddress, text.getBytes(), (address, matchIndex) -> matchIndex == index);
175+
}
176+
177+
/**
178+
* Find multiple strings inside the memory.
179+
* It will start searching with the first string and continue with the next at the position where the previous was found.
180+
*
181+
* @param path The list of strings to search for.
182+
* @return The addresses of the strings.
183+
*/
184+
public long findAddressUsingPath(String... path) {
185+
long cursor = -1;
186+
for (String part : path) {
187+
cursor = this.findAddressOfText(cursor + 1, part, 0);
188+
if (cursor == -1) {
189+
return -1;
190+
}
191+
}
192+
return cursor;
193+
}
194+
195+
/**
196+
* Find the first address of the modules.
197+
*
198+
* @return The address of the first module.
199+
*/
200+
public long getFirstModuleAddress() {
201+
long minAddress = Long.MAX_VALUE;
202+
for (Map.Entry<Long, Long> module : this.getModules(this.processId).entrySet()) {
203+
minAddress = Math.min(minAddress, module.getKey() + module.getValue());
204+
}
205+
return minAddress;
206+
}
207+
161208
/**
162209
* Find the highest process address.
163210
* The highest process address is determined by the highest module address + module size.
@@ -224,9 +271,10 @@ public interface SearchCondition {
224271
* Called for each matching address.
225272
*
226273
* @param address The address of the matching bytes.
274+
* @param index The index of the match.
227275
* @return True if the address matches the criteria.
228276
*/
229-
boolean matches(long address);
277+
boolean matches(long address, int index);
230278
}
231279

232280
}

src/main/java/de/labystudio/spotifyapi/platform/windows/api/spotify/SpotifyProcess.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
*/
1111
public class SpotifyProcess extends WinProcess {
1212

13-
private static final byte[] PREFIX_TRACK_ID = "spotify:track:".getBytes();
1413
private static final byte[] PREFIX_CONTEXT = new byte[]{0x63, 0x6F, 0x6E, 0x74, 0x65, 0x78, 0x74};
1514

1615
private final long addressTrackId;
@@ -29,17 +28,17 @@ public class SpotifyProcess extends WinProcess {
2928
public SpotifyProcess() {
3029
super("Spotify.exe");
3130

31+
// Get the highest addresses of the modules
3232
long highestAddress = this.getMaxProcessAddress();
3333

3434
// Find addresses of playback states (Located in the chrome_elf.dll module)
35-
this.addressTrackId = this.findInMemory(
36-
0,
37-
highestAddress,
38-
PREFIX_TRACK_ID,
39-
address -> this.isTrackIdValid(this.readTrackId(address))
35+
this.addressTrackId = this.findAddressUsingPath(
36+
"This program cannot be run in DOS mode",
37+
"This program cannot be run in DOS mode",
38+
"chrome_elf.dll",
39+
"spotify:track:"
4040
);
41-
// Check if we have found the addresses
42-
if (this.addressTrackId == -1) {
41+
if (this.addressTrackId == -1 || !this.isTrackIdValid(this.getTrackId())) {
4342
throw new IllegalStateException("Could not find track id in memory");
4443
}
4544

@@ -51,7 +50,7 @@ public SpotifyProcess() {
5150
0,
5251
highestAddress,
5352
PREFIX_CONTEXT,
54-
address -> {
53+
(address, index) -> {
5554
PlaybackAccessor accessor = new PlaybackAccessor(this, address);
5655
return accessor.isValid() && accessor.isPlaying() == isPlaying; // Check if address is valid
5756
}

src/main/java/de/labystudio/spotifyapi/platform/windows/api/spotify/SpotifyTitle.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,6 @@ public static SpotifyTitle of(String title) {
5656
}
5757

5858
String[] split = title.split(DELIMITER);
59-
return new SpotifyTitle(split[0], split[1]);
59+
return new SpotifyTitle(split[1], split[0]);
6060
}
6161
}

0 commit comments

Comments
 (0)