From 3fb045128634149205bd7478d62853ccf34c251d Mon Sep 17 00:00:00 2001 From: SmolAlli Date: Tue, 10 Feb 2026 17:04:45 +1100 Subject: [PATCH 1/4] Fix issues with shared memory not initializing on certain systems --- .gitignore | 5 +- as64core/capture_shmem.py | 48 ++++++++------- build_appimage.sh | 2 +- obs-plugin/autosplit64plus-framegrabber.so | Bin 43232 -> 0 bytes obs-plugin/src/autosplit64plus-framegrabber.c | 58 +++++++++--------- obs-plugin/src/constants.h | 4 +- 6 files changed, 61 insertions(+), 56 deletions(-) delete mode 100644 obs-plugin/autosplit64plus-framegrabber.so diff --git a/.gitignore b/.gitignore index dbf1d43..8458ff7 100644 --- a/.gitignore +++ b/.gitignore @@ -152,4 +152,7 @@ build.sh AppDir/ build_artifacts/ linuxdeploy-*.AppImage -appimagetool-*.AppImage \ No newline at end of file +appimagetool-*.AppImage + +generated_reset_*.jpg +*.so \ No newline at end of file diff --git a/as64core/capture_shmem.py b/as64core/capture_shmem.py index 75b53bd..337adf4 100644 --- a/as64core/capture_shmem.py +++ b/as64core/capture_shmem.py @@ -15,6 +15,7 @@ class SharedMemoryCapture(object): def __init__(self): self.shmem_handle = None self.shmem = None + self.shmem_fd = None self.width = 0 self.height = 0 self.linesize = 0 @@ -38,13 +39,13 @@ def open_shmem(self): # Linux implementation shm_path = f"/dev/shm/{SHMEM_NAME}" if not os.path.exists(shm_path): - debug_info = f"Path checked: {shm_path}\n" - if os.path.exists("/dev/shm"): - debug_info += f"Contents of /dev/shm: {os.listdir('/dev/shm')}" - else: - debug_info += "/dev/shm directory does not exist!" - - raise Exception(f"Could not find OBS Grabber Plugin!\n\n{debug_info}\n\nPlease make sure the plugin is enabled and OBS is running.") + debug_info = f"Path checked: {shm_path}\n" + if os.path.exists("/dev/shm"): + debug_info += f"Contents of /dev/shm: {os.listdir('/dev/shm')}" + else: + debug_info += "/dev/shm directory does not exist!" + + raise Exception(f"Could not find OBS Grabber Plugin!\n\n{debug_info}\n\nPlease make sure the plugin is enabled and OBS is running.") # We need to open the file to get a file descriptor self.shmem_fd = open(shm_path, "r+b") @@ -91,23 +92,24 @@ def _update_dimensions(self): header = np.frombuffer(shmem_header.read(16), dtype=np.uint32) shmem_header.close() else: - if not hasattr(self, 'shmem_fd') or not self.shmem_fd: - # Try to open if we have the file - if os.path.exists(f"/dev/shm/{SHMEM_NAME}"): - self.open_shmem() - else: - return # Can't update dimensions if not open/exists + if not hasattr(self, 'shmem_fd') or not self.shmem_fd: + print(f"hasattr: {hasattr(self, 'shmem_fd')} shmem_fd: {self.shmem_fd}") + # Try to open if we have the file + if os.path.exists(f"/dev/shm/{SHMEM_NAME}"): + self.open_shmem() + else: + return # Can't update dimensions if not open/exists - # Map header using the file descriptor - # We use the existing FD. - try: - shmem_header = mmap.mmap(self.shmem_fd.fileno(), 16, access=mmap.ACCESS_READ) - shmem_header.seek(0) - header = np.frombuffer(shmem_header.read(16), dtype=np.uint32) - shmem_header.close() - except Exception as e: - print(f"Error reading shmem header: {e}") - return + # Map header using the file descriptor + # We use the existing FD. + try: + shmem_header = mmap.mmap(self.shmem_fd.fileno(), 16, access=mmap.ACCESS_READ) + shmem_header.seek(0) + header = np.frombuffer(shmem_header.read(16), dtype=np.uint32) + shmem_header.close() + except Exception as e: + print(f"Error reading shmem header: {e}") + return new_width = int(header[0]) new_height = int(header[1]) diff --git a/build_appimage.sh b/build_appimage.sh index 10a70ba..0e06c92 100755 --- a/build_appimage.sh +++ b/build_appimage.sh @@ -10,7 +10,7 @@ BUILD_ROOT="/tmp/as64_build_$(date +%s)" APP_DIR="$BUILD_ROOT/AppDir" BUILD_DIR="$BUILD_ROOT/build_artifacts" # Path to host Python 3.11 installation to bundle -PYTHON_HOST_PATH="/home/poke/.pyenv/versions/3.11.9" +PYTHON_HOST_PATH="/home/$USER/.pyenv/versions/3.11.9" echo "Build started at $(date)" echo "Build root: $BUILD_ROOT" diff --git a/obs-plugin/autosplit64plus-framegrabber.so b/obs-plugin/autosplit64plus-framegrabber.so deleted file mode 100644 index 8e66ad6dfdad29803b25088028a0e491c61404e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43232 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 diff --git a/obs-plugin/src/autosplit64plus-framegrabber.c b/obs-plugin/src/autosplit64plus-framegrabber.c index d174a38..87e9e8c 100644 --- a/obs-plugin/src/autosplit64plus-framegrabber.c +++ b/obs-plugin/src/autosplit64plus-framegrabber.c @@ -66,7 +66,7 @@ static void *filter_create(obs_data_t *settings, obs_source_t *source) { struct filter_data *filter = bzalloc(sizeof(struct filter_data)); if (!filter) { - blog(LOG_ERROR, "Failed to allocate filter data"); + blog(LOG_ERROR, "%s Failed to allocate filter data", PREFIX); return NULL; } @@ -74,14 +74,14 @@ static void *filter_create(obs_data_t *settings, obs_source_t *source) filter->is_valid = !filter_instance_exists; if (!filter->is_valid) { - blog(LOG_WARNING, "AS64+ Frame grabber: Only one instance allowed"); + blog(LOG_WARNING, "%s AS64+ Frame grabber: Only one instance allowed", PREFIX); return filter; // Return filter anyway so properties can show error } filter_instance_exists = true; filter->render = gs_texrender_create(GS_BGRA, GS_ZS_NONE); if (!filter->render) { - blog(LOG_ERROR, "Failed to create texture renderer"); + blog(LOG_ERROR, "%s Failed to create texture renderer", PREFIX); bfree(filter); return NULL; } @@ -98,15 +98,15 @@ static void *filter_create(obs_data_t *settings, obs_source_t *source) * @param data Pointer to the filter data * @return Pointer to the created properties */ -// static bool github_button_clicked(obs_properties_t *props, obs_property_t *property, void *data) -// { -// #ifdef _WIN32 -// system("start " GITHUB_URL); -// #else -// system("xdg-open " GITHUB_URL); -// #endif -// return false; -// } +static bool github_button_clicked(obs_properties_t *props, obs_property_t *property, void *data) +{ +#ifdef _WIN32 + system("start " GITHUB_URL); +#else + system("xdg-open " GITHUB_URL); +#endif + return false; +} // static bool discord_button_clicked(obs_properties_t *props, obs_property_t *property, void *data) // { @@ -138,7 +138,7 @@ static obs_properties_t *filter_properties(void *data) OBS_TEXT_INFO); // Social links - directly in props instead of a group for horizontal layout - // obs_properties_add_button(props, "github_link", "📂 GitHub Repository", github_button_clicked); + obs_properties_add_button(props, "github_link", "📂 GitHub Repository", github_button_clicked); // obs_properties_add_button(props, "discord_link", "💬 Join Discord", discord_button_clicked); // Version and author info - directly use the constants @@ -170,15 +170,15 @@ static bool open_shmem(struct filter_data *filter, uint32_t width, uint32_t heig filter->pBuf = MapViewOfFile(filter->shmem, FILE_MAP_ALL_ACCESS, 0, 0, 16 + width * height * 4); if (filter->pBuf) { filter->shmem_valid = true; - blog(LOG_INFO, "Opened shared memory connection"); + blog(LOG_INFO, "%s Opened shared memory connection", PREFIX); return true; } else { - blog(LOG_ERROR, "Failed to map shared memory: %lu", GetLastError()); + blog(LOG_ERROR, "%s Failed to map shared memory: %lu", PREFIX, GetLastError()); CloseHandle(filter->shmem); filter->shmem = NULL; } } else { - blog(LOG_ERROR, "Failed to create shared memory: %lu", GetLastError()); + blog(LOG_ERROR, "%s Failed to create shared memory: %lu", PREFIX, GetLastError()); } return false; #else @@ -189,12 +189,12 @@ static bool open_shmem(struct filter_data *filter, uint32_t width, uint32_t heig filter->shmem_fd = shm_open(name, O_CREAT | O_RDWR, 0666); if (filter->shmem_fd == -1) { - blog(LOG_ERROR, "Failed to create shared memory: %s", strerror(errno)); + blog(LOG_ERROR, "%s Failed to create shared memory: %s", PREFIX, strerror(errno)); return false; } if (ftruncate(filter->shmem_fd, size) == -1) { - blog(LOG_ERROR, "Failed to resize shared memory: %s", strerror(errno)); + blog(LOG_ERROR, "%s Failed to resize shared memory: %s", PREFIX, strerror(errno)); close(filter->shmem_fd); filter->shmem_fd = -1; return false; @@ -202,7 +202,7 @@ static bool open_shmem(struct filter_data *filter, uint32_t width, uint32_t heig filter->pBuf = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, filter->shmem_fd, 0); if (filter->pBuf == MAP_FAILED) { - blog(LOG_ERROR, "Failed to map shared memory: %s", strerror(errno)); + blog(LOG_ERROR, "%s Failed to map shared memory: %s", PREFIX, strerror(errno)); close(filter->shmem_fd); filter->shmem_fd = -1; filter->pBuf = NULL; @@ -210,7 +210,7 @@ static bool open_shmem(struct filter_data *filter, uint32_t width, uint32_t heig } filter->shmem_valid = true; - blog(LOG_INFO, "Opened shared memory connection"); + blog(LOG_INFO, "%s Opened shared memory connection", PREFIX); return true; #endif } @@ -238,9 +238,9 @@ static bool close_shmem(struct filter_data *filter) #ifdef _WIN32 if (filter->shmem) { if (CloseHandle(filter->shmem)) { - blog(LOG_INFO, "Closed the shared memory"); + blog(LOG_INFO, "%s Closed the shared memory", PREFIX); } else { - blog(LOG_ERROR, "Failed to close the shared memory: %lu", GetLastError()); + blog(LOG_ERROR, "%s Failed to close the shared memory: %lu", PREFIX, GetLastError()); } filter->shmem = NULL; } @@ -251,7 +251,7 @@ static bool close_shmem(struct filter_data *filter) // We do not unlink here to allow ensuring other processes can still see it if needed, // but typically we might want to unlink? // For now, mirroring Windows behavior of just closing handle. - blog(LOG_INFO, "Closed the shared memory"); + blog(LOG_INFO, "%s Closed the shared memory", PREFIX); } #endif filter->shmem_valid = false; @@ -283,7 +283,7 @@ static bool copy_to_shared_memory(struct filter_data *filter, uint32_t width, ui memcpy((uint8_t *)filter->pBuf + 16, filter->image_data, width * height * 4); return true; } else { - blog(LOG_ERROR, "Shared memory view is not mapped"); + blog(LOG_ERROR, "%s Shared memory view is not mapped", PREFIX); filter->shmem_valid = false; } @@ -331,7 +331,7 @@ static void filter_render(void *data, gs_effect_t *effect) gs_stagesurface_destroy(filter->staging); filter->staging = gs_stagesurface_create(width, height, GS_BGRA); if (!filter->staging) { - blog(LOG_ERROR, "Failed to allocate staging surface for %dx%d", width, height); + blog(LOG_ERROR, "%s Failed to allocate staging surface for %dx%d", PREFIX, width, height); obs_source_skip_video_filter(filter->context); return; } @@ -341,7 +341,7 @@ static void filter_render(void *data, gs_effect_t *effect) filter->image_data = brealloc(filter->image_data, width * height * 4); } if (!filter->image_data) { - blog(LOG_ERROR, "Failed to allocate image data for %dx%d", width, height); + blog(LOG_ERROR, "%s Failed to allocate image data for %dx%d", PREFIX, width, height); obs_source_skip_video_filter(filter->context); return; } @@ -377,12 +377,12 @@ static void filter_render(void *data, gs_effect_t *effect) } gs_stagesurface_unmap(filter->staging); } else { - // blog(LOG_WARNING, "Failed to map staging surface"); + // blog(LOG_WARNING, "%s Failed to map staging surface", PREFIX); } copy_to_shared_memory(filter, width, height); } else { - blog(LOG_ERROR, "Failed to begin texture render"); + blog(LOG_ERROR, "%s Failed to begin texture render", PREFIX); } gs_texture_t *tex = gs_texrender_get_texture(filter->render); @@ -390,7 +390,7 @@ static void filter_render(void *data, gs_effect_t *effect) // gs_draw_sprite(tex, 0, width, height); obs_source_skip_video_filter(filter->context); } else { - blog(LOG_ERROR, "Failed to get texture from render target"); + blog(LOG_ERROR, "%s Failed to get texture from render target", PREFIX); } } diff --git a/obs-plugin/src/constants.h b/obs-plugin/src/constants.h index 75dcd07..e42ec40 100644 --- a/obs-plugin/src/constants.h +++ b/obs-plugin/src/constants.h @@ -2,5 +2,5 @@ #define PLUGIN_VERSION "\nVersion: 0.3.0" #define PLUGIN_AUTHOR "Author: Davi Be, Poke711, SmolAlli" -#define GITHUB_URL "https://github.com/DaviBe92/AutoSplit64plus" -#define DISCORD_URL "https://discord.gg/VmrQQBpPSK" +#define GITHUB_URL "https://github.com/Poke711/AutoSplit64plusLinux" +#define PREFIX "AS64: " \ No newline at end of file From fc46bc9ba3ca28e9b7476e7cfcb5cae532690e75 Mon Sep 17 00:00:00 2001 From: SmolAlli Date: Thu, 12 Feb 2026 15:08:01 +1100 Subject: [PATCH 2/4] Add build.bat for non-appimage distribution --- .gitignore | 10 ++++------ README.md | 3 +++ build.bat | 5 +++-- build.sh | 20 ++++++++++++++++++++ templates/generated_reset_one.jpg | Bin 13317 -> 0 bytes templates/generated_reset_two.jpg | Bin 49751 -> 0 bytes 6 files changed, 30 insertions(+), 8 deletions(-) create mode 100755 build.sh delete mode 100644 templates/generated_reset_one.jpg delete mode 100644 templates/generated_reset_two.jpg diff --git a/.gitignore b/.gitignore index 8458ff7..7a8fc51 100644 --- a/.gitignore +++ b/.gitignore @@ -145,14 +145,12 @@ dmypy.json *.iml out gen -build.sh +obs-plugin/build.sh # AppImage Build Artifacts *.AppImage AppDir/ build_artifacts/ -linuxdeploy-*.AppImage -appimagetool-*.AppImage - -generated_reset_*.jpg -*.so \ No newline at end of file +*.so +templates/generated_reset_*.jpg +*.tar.gz \ No newline at end of file diff --git a/README.md b/README.md index e89d1a6..4d80673 100644 --- a/README.md +++ b/README.md @@ -32,3 +32,6 @@ This will generate `AutoSplit64plus-x86_64.AppImage` in the root directory. ### Using the AppImage 1. Make it executable: `chmod +x AutoSplit64plus-x86_64.AppImage` 2. Run it: `./AutoSplit64plus-x86_64.AppImage` + +## Known issues: +Having a filter on the same source as the OBS plugin that has errors (i.e. doesn't have the relevant plugin installed) will cause shared memory to not initialize properly on the plugin side. \ No newline at end of file diff --git a/build.bat b/build.bat index 4bbb28c..f4775aa 100644 --- a/build.bat +++ b/build.bat @@ -3,12 +3,13 @@ call .venv\Scripts\activate.bat pyinstaller ^ --noconfirm ^ --name "AutoSplit64plus" ^ ---splash "resources\gui\icons\as64plus.png" ^ ---icon "resources\gui\icons\as64plus.ico" ^ +--splash "resources\gui\icons\icon.png" ^ +--icon "resources\gui\icons\icon.ico" ^ --noconsole ^ --clean ^ --noupx ^ --contents-directory "libraries" ^ +--onefile AutoSplit64.py xcopy /E /I /Y logic dist\AutoSplit64plus\logic diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..794d21f --- /dev/null +++ b/build.sh @@ -0,0 +1,20 @@ +source .venv/bin/activate + +pyinstaller \ +--noconfirm \ +--name "AutoSplit64plus" \ +--splash "resources/gui/icons/icon.png" \ +--icon "resources/gui/icons/icon.ico" \ +--noconsole \ +--clean \ +--noupx \ +--contents-directory "libraries" \ +AutoSplit64.py + +cp -r logic dist/AutoSplit64plus/logic +cp -r resources dist/AutoSplit64plus/resources +cp -r routes dist/AutoSplit64plus/routes +cp -r templates dist/AutoSplit64plus/templates +cp defaults.ini dist/AutoSplit64plus/ + +tar -czvf Autosplit64.tar.gz ./dist/AutoSplit64plus diff --git a/templates/generated_reset_one.jpg b/templates/generated_reset_one.jpg deleted file mode 100644 index f25237ff72cdc8b9ee1eda6ab4213227855f8fc7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13317 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 diff --git a/templates/generated_reset_two.jpg b/templates/generated_reset_two.jpg deleted file mode 100644 index 744010638cc6a38e1f42bb7b4a2b0cb691c51816..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49751 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 m$AHw-VE;#a6MiC From d612d4a876d361cf8b76f06af0c0a52c99adc766 Mon Sep 17 00:00:00 2001 From: SmolAlli Date: Thu, 12 Feb 2026 20:53:45 +1100 Subject: [PATCH 3/4] guhh websocket?? --- as64core/livesplit.py | 70 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 56 insertions(+), 14 deletions(-) diff --git a/as64core/livesplit.py b/as64core/livesplit.py index a81aec8..2f7b938 100644 --- a/as64core/livesplit.py +++ b/as64core/livesplit.py @@ -6,10 +6,32 @@ except ImportError: win32file = None win32pipe = None + CONNECTIONS = set() + import time +import websockets +import asyncio +import threading from . import config + +async def register(websocket): + CONNECTIONS.add(websocket) + try: + await websocket.wait_closed() + finally: + CONNECTIONS.remove(websocket) + +def websocket_func(): + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + ws_server = websockets.serve(register, 'localhost', 5678) + + loop.run_until_complete(ws_server) + loop.run_forever() + loop.close() + # Connect to LiveSplit and return socket def connect() -> object: # Get connection type from config @@ -39,7 +61,13 @@ def connect() -> object: ls_socket.connect((config.get("connection", "ls_host"), config.get("connection", "ls_port"))) return ls_socket except: - return False + try: + # Initialise websocket + server = threading.Thread(target=websocket_func, daemon=True) + server.start() + finally: + return "websocket" + else: return False @@ -48,18 +76,27 @@ def disconnect(ls_socket) -> None: # Check if connection even exists if ls_socket is False: return - ls_socket.close() + try: + ls_socket.close() + except: + # for websocket + return def check_connection(ls_socket) -> bool: - # Check if connection has been established - if (ls_socket == False): - return False - # Check if communication is possible and response is received - if split_index(ls_socket) is False: + try: + if ls_socket == "websocket": + return True + # Check if connection has been established + if (ls_socket == False): + return False + # Check if communication is possible and response is received + if split_index(ls_socket) is False: + return False + else: + return True + except: return False - else: - return True def send(ls_socket, command) -> None: @@ -70,6 +107,8 @@ def send(ls_socket, command) -> None: ls_socket.send(command.encode('utf-8')) # If it is a pipe: else: + if ls_socket == "websocket": + websockets.broadcast(CONNECTIONS, '{"command": "' + command + '"}') if win32file is None: return @@ -80,21 +119,24 @@ def send(ls_socket, command) -> None: raise Exception("LiveSplit connection lost") def split(ls_socket) -> None: - send(ls_socket, "startorsplit\r\n") + send(ls_socket, "splitOrStart" if ls_socket == "websocket" else "startorsplit\r\n") + # send(ls_socket, "startorsplit\r\n") def reset(ls_socket) -> None: - send(ls_socket, "reset\r\n") + send(ls_socket, "reset" if ls_socket == "websocket" else "reset\r\n") def restart(ls_socket) -> None: - send(ls_socket, "reset\r\nstarttimer\r\n") + send(ls_socket, "reset" if ls_socket == "websocket" else "reset\r\nstarttimer\r\n") + if ls_socket == "websocket": + send(ls_socket, "splitOrStart") def skip(ls_socket) -> None: - send(ls_socket, "skipsplit\r\n") + send(ls_socket, "skipSplit" if ls_socket == "websocket" else "skipsplit\r\n") def undo(ls_socket) -> None: - send(ls_socket, "unsplit\r\n") + send(ls_socket, "undoSplit" if ls_socket == "websocket" else "unsplit\r\n") def split_index(ls_socket): From 5a820ece78f7a437aae4eb4c2edc542c9ffbaaee Mon Sep 17 00:00:00 2001 From: SmolAlli Date: Fri, 13 Feb 2026 13:43:52 +1100 Subject: [PATCH 4/4] Remove stuff accidentally added --- build.bat | 1 - 1 file changed, 1 deletion(-) diff --git a/build.bat b/build.bat index f4775aa..71a5a12 100644 --- a/build.bat +++ b/build.bat @@ -9,7 +9,6 @@ pyinstaller ^ --clean ^ --noupx ^ --contents-directory "libraries" ^ ---onefile AutoSplit64.py xcopy /E /I /Y logic dist\AutoSplit64plus\logic