Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Joystick Interposer Fixes for SDL, Wine, Retroarch and RPCS3 #173

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

danisla
Copy link
Member

@danisla danisla commented Jan 21, 2025

Changes

Application Specific

Retroarch

To use with retroarch, edit your retroarch.cfg (at ~/.config/retroarch/retroarch.cfg) and set:

input_joypad_driver = "linuxraw"

RPCS3

Select SDL as controller handler then select Selkies Controller 1 from the device list.
Screenshot from 2025-02-07 00-08-58

Wine

Run wine control and then open the Game Controllers app to test joystick support.
Screenshot from 2025-02-07 00-10-19

Testing

nvidia-egl-desktop:24.04

Dockerfile.egl.jstest:

FROM ghcr.io/selkies-project/nvidia-egl-desktop:24.04
ARG CACHEBUST

USER root

# Update interposer library and selkies python
RUN cd /opt && git clone https://github.com/selkies-project/selkies-gstreamer.git -b fix-js-interposer
RUN \
    cd /opt/selkies-gstreamer && \
    cp src/selkies_gstreamer/gamepad.py src/selkies_gstreamer/webrtc_input.py /usr/local/lib/python3.*/dist-packages/selkies_gstreamer/
RUN \
    cd /opt/selkies-gstreamer/addons/js-interposer && \
    make deps && \
    make
# Workaround until entrypoint segfault is resolved.
RUN \
    echo 'cp /opt/selkies-gstreamer/addons/js-interposer/selkies_joystick_interposer.so /usr/lib/x86_64-linux-gnu/selkies_joystick_interposer.so' >> /etc/bash.bashrc && \
    echo 'cp /opt/selkies-gstreamer/addons/js-interposer/selkies_joystick_interposer_i386.so /usr/lib/i386-linux-gnu/selkies_joystick_interposer.so' >> /etc/bash.bashrc

# Update entrypoint scripts
RUN \
    cd /opt && git clone https://github.com/selkies-project/docker-nvidia-egl-desktop.git -b update-joystick-support && \
    cd docker-nvidia-egl-desktop && \
    cp entrypoint.sh /etc/entrypoint.sh && \
    cp selkies-gstreamer-entrypoint.sh /etc/selkies-gstreamer-entrypoint.sh && \
    chmod +x /etc/entrypoint.sh /etc/selkies-gstreamer-entrypoint.sh
    
USER ubuntu

Build and run:

docker build --build-arg CACHEBUST=$(date +%s) -f Dockerfile.egl.jstest -t ghcr.io/selkies-project/nvidia-egl-desktop:24.04-jstest .
docker run --rm --name egl -it -d --gpus 1 --tmpfs /dev/shm:rw -e TZ=UTC -e DISPLAY_SIZEW=1920 -e DISPLAY_SIZEH=1080 -e DISPLAY_REFRESH=60 -e DISPLAY_DPI=96 -e DISPLAY_CDEPTH=24 -e SELKIES_ENABLE_BASIC_AUTH=false -e SELKIES_ENCODER=nvh264enc -e SELKIES_VIDEO_BITRATE=8000 -e SELKIES_FRAMERATE=60 -e SELKIES_AUDIO_BITRATE=128000 -p 8080:8080 ghcr.io/selkies-project/nvidia-egl-desktop:24.04-jstest

gst-py-example:main-ubuntu24.04

Dockerfile.example.jstest

FROM ghcr.io/selkies-project/selkies-gstreamer/gst-py-example:main-ubuntu24.04
ARG CACHEBUST

USER root

# Update interposer library and selkies python
RUN cd /opt && git clone https://github.com/selkies-project/selkies-gstreamer.git -b fix-js-interposer
RUN \
    cd /opt/selkies-gstreamer && \
    cp src/selkies_gstreamer/gamepad.py src/selkies_gstreamer/webrtc_input.py /usr/local/lib/python3.*/dist-packages/selkies_gstreamer/
RUN \
    cd /opt/selkies-gstreamer/addons/js-interposer && \
    make deps && \
    make
RUN \
    cp /opt/selkies-gstreamer/addons/js-interposer/selkies_joystick_interposer.so /usr/lib/x86_64-linux-gnu/selkies_joystick_interposer.so && \
    cp /opt/selkies-gstreamer/addons/js-interposer/selkies_joystick_interposer_i386.so /usr/lib/i386-linux-gnu/selkies_joystick_interposer.so

# Update entrypoint script
RUN \
    cp /opt/selkies-gstreamer/addons/example/entrypoint.sh /etc/entrypoint.sh && \
    cp /opt/selkies-gstreamer/addons/example/selkies-gstreamer-entrypoint.sh /etc/selkies-gstreamer-entrypoint.sh
    
USER ubuntu

Build:

docker build --build-arg CACHEBUST=$(date +%s) -f Dockerfile.example.jstest -t ghcr.io/selkies-project/selkies-gstreamer/gst-py-example:main-ubuntu24.04-jstest .

Run:

docker run --name selkies -it -d --rm -e SELKIES_ENABLE_BASIC_AUTH=false -e SELKIES_TURN_PROTOCOL=udp -e SELKIES_TURN_PORT=3478 -e TURN_MIN_PORT=65534 -e TURN_MAX_PORT=65535 -p 8080:8080 -p 3478:3478 -p 3478:3478/udp -p 65534-65535:65534-65535 -p 65534-65535:65534-65535/udp ghcr.io/selkies-project/selkies-gstreamer/gst-py-example:main-ubuntu24.04-jstest

@danisla danisla marked this pull request as draft January 22, 2025 07:14
@danisla danisla changed the title Fix issues with joystick interposer and Retroarch Joystick Interposer Fixes for SDL, wine, Retroarch and RPCS3 Feb 7, 2025
@ehfd ehfd self-requested a review February 7, 2025 08:26
@ehfd
Copy link
Member

ehfd commented Feb 7, 2025

@danisla Feel free to switch from Draft PR if you are ready.

@danisla
Copy link
Member Author

danisla commented Feb 7, 2025

@danisla Feel free to switch from Draft PR if you are ready.

@ehfd I temporarily remove the Conga build steps because they were failing, can you help resolve the errors? You can run the conga docker build locally and see the same failures.

@ehfd
Copy link
Member

ehfd commented Feb 7, 2025

That is in order for the near future. I know the source of error.

@danisla
Copy link
Member Author

danisla commented Feb 7, 2025

That is in order for the near future. I know the source of error.

Ok maybe we’ll just leave it disabled for now and you can re-enable it the build steps later.

@ehfd
Copy link
Member

ehfd commented Feb 7, 2025

Anyways, when you are ready, press "Ready for review" and I'll directly make necessary edits.

@danisla
Copy link
Member Author

danisla commented Feb 8, 2025

I'm seeing a segfault during the entrypoint when running with the nvidia-egl-desktop:24.04 image.

/etc/entrypoint.sh: line 89:   200 Segmentation fault      (core dumped) /usr/bin/Xvfb "${DISPLAY}" -screen 0 "8192x4096x${DISPLAY_CDEPTH}" -dpi "${DISPLAY_DPI}" +extension "COMPOSITE" +extension "DAMAGE" +extension "GLX" +extension "RANDR" +extension "RENDER" +extension "MIT-SHM" +extension "XFIXES" +extension "XTEST" +iglx +render -nolisten "tcp" -ac -noreset -shmem

It looks like the LD_PRELOAD is interfering with the entrypoint.

Moving this back to draft to fix the entrypoint issue.

@danisla danisla marked this pull request as draft February 8, 2025 17:57
@ehfd
Copy link
Member

ehfd commented Feb 9, 2025

#175 #171

@danisla I am seeing that this issue might also be relevant, although separate.

The concern I have with #171 is whether the below can be made more simple in any way; need a sufficient understanding of the websockets package. This is mostly redundant except allows 'body' type to be either bytes or string.

    def custom_response(self, status, custom_headers, body):
        """A wrapper indentical to https://github.com/python-websockets/websockets/blob/main/src/websockets/server.py#L482 
        but allows 'body' type to be either bytes or string.
        """
        status = http.HTTPStatus(status)
        headers = Headers(
            [
                ("Date", email.utils.formatdate(usegmt=True)),
                ("Connection", "close"),
                ("Content-Length", str(len(body))),
                ("Content-Type", "text/plain; charset=utf-8"),
            ]
        )

        # overriding and appending headers if provided
        for key, value in custom_headers:
            if headers.get(key) is not None:
                del headers[key]
            headers[key] = value

        # Expecting bytes, but if it's string then convert to bytes
        if isinstance(body, str):
            body = body.encode()
        return Response(status.value, status.phrase, headers, body)

@danisla
Copy link
Member Author

danisla commented Feb 9, 2025

#175 #171

@danisla I am seeing that this issue might also be relevant, although separate.

The concern I have with #171 is whether the below can be made more simple in any way; need a sufficient understanding of the websockets package. This is mostly redundant except allows 'body' type to be either bytes or string.

    def custom_response(self, status, custom_headers, body):
        """A wrapper indentical to https://github.com/python-websockets/websockets/blob/main/src/websockets/server.py#L482 
        but allows 'body' type to be either bytes or string.
        """
        status = http.HTTPStatus(status)
        headers = Headers(
            [
                ("Date", email.utils.formatdate(usegmt=True)),
                ("Connection", "close"),
                ("Content-Length", str(len(body))),
                ("Content-Type", "text/plain; charset=utf-8"),
            ]
        )

        # overriding and appending headers if provided
        for key, value in custom_headers:
            if headers.get(key) is not None:
                del headers[key]
            headers[key] = value

        # Expecting bytes, but if it's string then convert to bytes
        if isinstance(body, str):
            body = body.encode()
        return Response(status.value, status.phrase, headers, body)

This doesn't seem related to the joystick interposer function, so we'll solve it in the respective issue.

@danisla danisla marked this pull request as ready for review February 9, 2025 07:18
@ehfd
Copy link
Member

ehfd commented Feb 9, 2025

Yeah, just for reference.

@ehfd ehfd changed the title Joystick Interposer Fixes for SDL, wine, Retroarch and RPCS3 Joystick Interposer Fixes for SDL, Wine, Retroarch and RPCS3 Feb 11, 2025
@ehfd
Copy link
Member

ehfd commented Feb 11, 2025

@danisla For the purpose of documentation, what are the exhaustive interface (and/or driver) options that this interposer now supports?

(e.g. joydev, udev/evdev, sdl1/2, hid, etc...)

And can one use udev and sdl2 options here if one chooses so? https://docs.libretro.com/guides/input-controller-drivers/#linux

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Joystick Interposer cannot be detected as a controller device in Steam Proton/Wine and RPCS3
2 participants