kokolihapihvi / RockSniffer

RockSniffer application
MIT License
76 stars 29 forks source link

Proposal: Discord RPC Album Art #47

Closed sdasda7777 closed 11 months ago

sdasda7777 commented 12 months ago

I am hereby proposing a feature that album art be shown in the Discord RPC status. To clarify I am uncertain if it should be the default or not, either is fine by me.

The album art (or rather its URL) can be obtained completely legally by querying remote APIs that are authorized to store the album art. This result can even be cached for the given session to reduce the requests necessary and improve the latency.

I am willing to implement this if this sounds interesting. I have experience with implementing this for the VLC player.

kokolihapihvi commented 12 months ago

Hi.

That is what I originally wanted to do with the RPC, but apps like Spotify are using some special agreement to display cover art in the RPC. For usual discord applications there are 300 asset slots you may upload images to and display them by name/key.

If there is a way to do this, that didn't exist back when I originally added RPC support, this would be a nice feature.

sdasda7777 commented 12 months ago

Yes, but even if there wasn't the 300 slot limitation, this approach still wouldn't work, because it wouldn't be legal. However as far as I know, you can use any URL as the largeImageKey value, in which case it gets resolved when displaying to users, at least that is my experience. I will look into it later today or tomorrow.

sdasda7777 commented 12 months ago

Yup, it's really that simple (but I had to update the DiscordRichPresent package, the old version actually just threw an exception):

rp.Assets.LargeImageKey = "https://i.scdn.co/image/ab67616d0000b273aad730647e5a249a0792bc72";

image

kokolihapihvi commented 12 months ago

Interesting, this should be possible to do then, if you have a service that allows finding an album cover, and permits using their CDN in this way.

sdasda7777 commented 12 months ago

Hey, by the way, I seem to have troubles with getting the state with the cloned version: it always just says "Browsing Menus" instead of what I am really doing. Any ideas why that might be? The standalone version works just fine (e.g. "Browing Menus\nMain Menu", "Browing Menus\nLearn A Song", ...).

kokolihapihvi commented 12 months ago

You'll have to debug that on your end, it's working for me even after upgrading the DiscordRichPresence package to v1.2.1.24

sdasda7777 commented 12 months ago

Okay, but the RSMemoryReadout is literally always {"", "", UNKNOWN, null, "", 0}. I added conditional breakpoint to the Sniffer_OnMemoryReadout method to trigger when the stage isn't "", and it just never triggers. Also tried running without debugger, with no change. Are you sure there isn't something else I need to do, like copy some dependency or something? 🤔

kokolihapihvi commented 12 months ago

If memory readouts are failing completely, the solution is usually to run it as admin, several users have reported that over the years and I've never been able to figure out why it happens.

I'm not sure how to help you there, maybe try setting breakpoints earlier in the memory readout process and see what's causing the readout to be invalid, is it successfully reading memory at all, what checks are failing and causing it to not produce a valid readout, etc.

sdasda7777 commented 12 months ago

Yeah, tracked it down to the read of the pointers, the failure happens all the way there. Running as admin doesn't seem to help, unfortunately 🤔

It seems as though the MemoryHelper.ReadStringFromMemory() gets an IntPtr.Zero as an argument. That happens because of this check in FollowPointers(), but I'm not sure I understand what it actually means:

//Add offsets
foreach (int offset in offsets)
{
    finalAddress = MemoryHelper.FollowPointer(rsProcessHandle, finalAddress, offset);

    //If any of the offsets points to 0, return zero
    if (finalAddress.ToInt32() == offset)
    {
        return IntPtr.Zero; // returns here, even though finalAdress.ToInt32() isn't 0???
    }
}
kokolihapihvi commented 12 months ago

If you look at the FollowPointer method, it is adding offset to the read pointer address, so if the pointer address was 0, it will return 0 + offset, which is why it is checked like that. The pointer paths should be identical in the downloaded version and in the one you build, doesn't make sense that only one works.

At this point this discussion is turning pretty technical, if you want to talk to me directly, you can find me on discord with the same nickname.

sdasda7777 commented 12 months ago

In case anyone is curious what the issue was, I did only git pull instead of git pull --recurse-submodules, so the submodules had out of date pointers 🤦‍♂️