Compare commits

...

21 commits
1.0 ... main

Author SHA1 Message Date
4fbbb6e31e Fix PKGBUILD (sha256sum)
All checks were successful
Create releases with ArchLinux pkg / check-and-build-and-release (push) Successful in 1s
2024-07-21 17:48:44 +09:00
6026bef0a0 Minor fixes
All checks were successful
Create releases with ArchLinux pkg / check-and-build-and-release (push) Successful in 1s
2024-07-21 13:05:39 +09:00
2c9f3b0452 Tweak "--wait" time max
All checks were successful
Create releases with ArchLinux pkg / check-and-build-and-release (push) Successful in 12s
2024-07-21 12:51:43 +09:00
ea6f59fbc5 Fix client arg parse
All checks were successful
Create releases with ArchLinux pkg / check-and-build-and-release (push) Successful in 12s
2024-07-21 12:45:08 +09:00
257ba1db6c Impl "--wait"
All checks were successful
Create releases with ArchLinux pkg / check-and-build-and-release (push) Successful in 15s
"--wait" causes the server to wait for the action to complete before
sending a response to the client.
2024-07-21 12:37:21 +09:00
041f73c317 Update workflow/action
All checks were successful
Create releases with ArchLinux pkg / check-and-build-and-release (push) Successful in 5s
2024-06-15 11:17:00 +09:00
741111fe8c Add forgejo action to make releases for tags
All checks were successful
Create releases with ArchLinux pkg / check-and-build-and-release (push) Successful in 5s
2024-01-29 13:38:58 +09:00
287e3d98d8 Update LICENSE year 2024-01-27 22:09:49 +09:00
b40f3daff7 Refactor archLinuxPackaging/PKGBUILD 2024-01-27 21:57:32 +09:00
2d7ddc1c2f Update archlinux packaging 2024-01-26 17:54:26 +09:00
4c708a2b9a Version 1.3.0
Allow toggling streaming and replay-buffer.
2024-01-26 17:37:03 +09:00
0376d6cf4b Update archLinux packaging 2024-01-26 17:11:40 +09:00
d4becec995 Version 1.2.1
Fix client error on toggle recording.
Fix extra newline in output when toggling recording from client.
2024-01-26 17:08:43 +09:00
5700e720af Update archlinux packaging 2024-01-26 16:54:59 +09:00
3a9ac9e58c Version 1.2
Fix CMakeLists.txt.

Add new feature to "--toggle-recording" from client.

Set debug optimization flag to "-Og".
2024-01-26 16:50:25 +09:00
190b013e2d Update archLinuxPackaging/PKGBUILD 2023-08-14 11:50:12 +09:00
640ae65d07 Add support for controlling the replay buffer 2023-08-14 11:35:36 +09:00
a18c507472 Update README.md 2023-08-13 16:03:51 +09:00
056139a718 Update README.md 2023-08-13 16:03:03 +09:00
43ab2cc04c Add README.md 2023-08-13 16:01:19 +09:00
8911bdab50 Add PKGBUILD 2023-08-13 15:45:01 +09:00
9 changed files with 358 additions and 30 deletions

View file

@ -0,0 +1,71 @@
name: Create releases with ArchLinux pkg
on:
push:
branches:
- '*'
jobs:
check-and-build-and-release:
runs-on: x86_64_archLinux
steps:
- name: Get tags
run: |
curl --fail-with-body -X 'GET' \
'https://git.seodisparate.com/api/v1/repos/stephenseo/obs-studio-plugin-unix-socket-control/tags' \
-H 'accept: application/json' -o tags.json -w '%output{header_count}%header{x-total-count}' 2>/dev/null \
- name: Fetch repo
run: git clone https://git.seodisparate.com/stephenseo/obs-studio-plugin-unix-socket-control.git obs_usc
- name: Fetch PKGBUILD
run: pushd obs_usc >&/dev/null && git checkout main && popd >&/dev/null && cp obs_usc/archLinuxPackaging/PKGBUILD ./
- name: Check tags and build per release
run: |
SAVED_DIR="$(pwd)"
TAG_COUNT="$(cat ./header_count)"
for ((i=0; i<$TAG_COUNT; ++i)); do
echo "$(jq ".[$i].name" < ./tags.json | tr -d '"')" >> tempList
done
sort -V < tempList > versionList
for ((i=0; i<$TAG_COUNT; ++i)); do
cd "$SAVED_DIR"
TAG_NAME="$(sed -n "$((i+1))p" ./versionList)"
curl -X 'GET' "https://git.seodisparate.com/api/v1/repos/stephenseo/obs-studio-plugin-unix-socket-control/releases/tags/${TAG_NAME}" -H 'accept: application/json' -w '%output{http_code}%{http_code}' >&/dev/null
if [[ $(cat ./http_code) != "404" ]]; then
continue
fi
echo "Trying to build and release \"$TAG_NAME\"..."
mkdir -p "build_${TAG_NAME}" || continue
cp ./PKGBUILD "build_${TAG_NAME}/" || continue
sed -i "s/^pkgver=.*\$/pkgver=${TAG_NAME}/" "build_${TAG_NAME}/PKGBUILD" || continue
sed -i 's/^pkgrel=.*$/pkgrel=1/' "build_${TAG_NAME}/PKGBUILD" || continue
sed -i 's/^sha256sums=.*$/sha256sums=("SKIP")/' "build_${TAG_NAME}/PKGBUILD" || continue
cd "build_${TAG_NAME}" || continue
makepkg || continue
curl --fail-with-body -X 'POST' \
"https://git.seodisparate.com/api/v1/repos/stephenseo/obs-studio-plugin-unix-socket-control/releases" \
-H 'accept: application/json' \
-H "Authorization: token ${GITHUB_TOKEN}" \
-H 'Content-Type: application/json' \
-d "{
\"name\": \"OBS Plugin Unix Socket Control version ${TAG_NAME}\",
\"body\": \"\",
\"tag_name\": \"${TAG_NAME}\"
}" > release_response.json || continue
curl --fail-with-body -X 'POST' \
"https://git.seodisparate.com/api/v1/repos/stephenseo/obs-studio-plugin-unix-socket-control/releases/$(jq .id < release_response.json)/assets" \
-H 'accept: application/json' \
-H "Authorization: token ${GITHUB_TOKEN}" \
-H 'Content-Type: multipart/form-data' \
-F "attachment=@obs-studio-plugin-unix-socket-control-${TAG_NAME}-1-x86_64.pkg.tar.zst;type=application/zstd" > release_asset.json || continue
done

View file

@ -1,9 +1,16 @@
cmake_minimum_required(VERSION 3.25) cmake_minimum_required(VERSION 3.25)
project(obs-studio-plugin-unix-socket-control)
set(obs_usc_VERSION_MAJOR 1)
set(obs_usc_VERSION_MINOR 4)
set(obs_usc_VERSION_PATCH 0)
set(obs_usc_VERSION_STR "${obs_usc_VERSION_MAJOR}.${obs_usc_VERSION_MINOR}.${obs_usc_VERSION_PATCH}")
project(obs-studio-plugin-unix-socket-control VERSION "${obs_usc_VERSION_STR}")
add_compile_options( add_compile_options(
-Wall -Wextra -Wpedantic -Wall -Wextra -Wpedantic
$<$<CONFIG:DEBUG>:-O0> $<$<CONFIG:DEBUG>:-Og>
) )
if(NOT DEFINED CMAKE_BUILD_TYPE OR NOT CMAKE_BUILD_TYPE) if(NOT DEFINED CMAKE_BUILD_TYPE OR NOT CMAKE_BUILD_TYPE)

View file

@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2023 Stephen Seo Copyright (c) 2023-2024 Stephen Seo
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

11
README.md Normal file
View file

@ -0,0 +1,11 @@
# obs-studio-plugin-unix-socket-control
An obs-studio plugin that accepts commands over a unix socket to start/stop
recording/streaming or shows recording/streaming active status.
When building the plugin, an obs-studio plugin and a client program is built.
This exists because obs-studio keyboard shortcuts don't work on Wayland, and I
wanted a workaround to tell obs-studio to start/stop recording (via the use of
invoking a toggle script that uses this plugin's client with a configured Sway
keyboard shortcut).

View file

@ -0,0 +1,22 @@
pkgname=obs-studio-plugin-unix-socket-control
pkgver=1.4.0
pkgrel=1
pkgdesc="An obs studio plugin to command obs to start/stop recording/streaming via unix socket"
arch=(x86_64)
url="https://git.seodisparate.com/stephenseo/obs-studio-plugin-unix-socket-control"
license=('MIT')
depends=(obs-studio)
makedepends=(cmake)
source=("${pkgname}_${pkgver}.tar.gz::$url/archive/$pkgver.tar.gz")
sha256sums=(6e0f1d4d48e9a26382aaea7e1969788373c301b685c49cd916d7f518ac148265)
build() {
cd "$pkgname"
cmake -S . -B buildRelease -DCMAKE_BUILD_TYPE=Release
make -C buildRelease
}
package() {
install -D -m555 "$srcdir/$pkgname/buildRelease/libunix-socket-control.so" "$pkgdir/usr/lib/obs-plugins/lib$pkgname.so"
install -D -m555 "$srcdir/$pkgname/buildRelease/unix-socket-control-client" "$pkgdir/usr/bin/$pkgname-client"
}

View file

@ -11,14 +11,21 @@
// local includes // local includes
#include "common_constants.h" #include "common_constants.h"
void print_usage(char *name) { void print_usage(const char *name) {
printf("Usage:\n"); printf("Usage:\n");
printf(" %s\n", name); printf(" %s\n", name);
printf(" [--start-recording \n"); printf(" [--start-recording \n");
printf(" | --stop-recording\n"); printf(" | --stop-recording\n");
printf(" | --toggle-recording\n");
printf(" | --start-streaming\n"); printf(" | --start-streaming\n");
printf(" | --stop-streaming\n"); printf(" | --stop-streaming\n");
printf(" | --toggle-streaming\n");
printf(" | --start-replay-buffer\n");
printf(" | --stop-replay-buffer\n");
printf(" | --toggle-replay-buffer\n");
printf(" | --save-replay-buffer\n");
printf(" | --get-status]\n"); printf(" | --get-status]\n");
printf(" --wait\n");
} }
void cleanup_data_socket(int *data_socket) { void cleanup_data_socket(int *data_socket) {
@ -30,25 +37,56 @@ void cleanup_data_socket(int *data_socket) {
int main(int argc, char **argv) { int main(int argc, char **argv) {
UnixSocketEventType type = UNIX_SOCKET_EVENT_NOP; UnixSocketEventType type = UNIX_SOCKET_EVENT_NOP;
if (argc == 2) { const char *program_name = argv[0];
if (strncmp(argv[1], "--start-recording", 17) == 0) { ++argv;
type = UNIX_SOCKET_EVENT_START_RECORDING; --argc;
} else if (strncmp(argv[1], "--stop-recording", 16) == 0) { if (argc == 0) {
type = UNIX_SOCKET_EVENT_STOP_RECORDING; print_usage(program_name);
} else if (strncmp(argv[1], "--start-streaming", 17) == 0) { return 1;
type = UNIX_SOCKET_EVENT_START_STREAMING; }
} else if (strncmp(argv[1], "--stop-streaming", 16) == 0) { while (argc != 0) {
type = UNIX_SOCKET_EVENT_STOP_STREAMING; if (strncmp(argv[0], "--start-recording", 17) == 0) {
} else if (strncmp(argv[1], "--get-status", 12) == 0) { type = UNIX_SOCKET_EVENT_START_RECORDING |
type = UNIX_SOCKET_EVENT_GET_STATUS; (UNIX_SOCKET_EVENT_WAIT & type);
} else if (strncmp(argv[0], "--stop-recording", 16) == 0) {
type = UNIX_SOCKET_EVENT_STOP_RECORDING |
(UNIX_SOCKET_EVENT_WAIT & type);
} else if (strncmp(argv[0], "--start-streaming", 17) == 0) {
type = UNIX_SOCKET_EVENT_START_STREAMING |
(UNIX_SOCKET_EVENT_WAIT & type);
} else if (strncmp(argv[0], "--toggle-recording", 18) == 0) {
type = UNIX_SOCKET_EVENT_TOGGLE_RECORDING |
(UNIX_SOCKET_EVENT_WAIT & type);
} else if (strncmp(argv[0], "--stop-streaming", 16) == 0) {
type = UNIX_SOCKET_EVENT_STOP_STREAMING |
(UNIX_SOCKET_EVENT_WAIT & type);
} else if (strncmp(argv[0], "--toggle-streaming", 18) == 0) {
type = UNIX_SOCKET_EVENT_TOGGLE_STREAMING |
(UNIX_SOCKET_EVENT_WAIT & type);
} else if (strncmp(argv[0], "--start-replay-buffer", 21) == 0) {
type = UNIX_SOCKET_EVENT_START_REPLAY_BUFFER |
(UNIX_SOCKET_EVENT_WAIT & type);
} else if (strncmp(argv[0], "--stop-replay-buffer", 20) == 0) {
type = UNIX_SOCKET_EVENT_STOP_REPLAY_BUFFER |
(UNIX_SOCKET_EVENT_WAIT & type);
} else if (strncmp(argv[0], "--toggle-replay-buffer", 22) == 0) {
type = UNIX_SOCKET_EVENT_TOGGLE_REPLAY_BUFFER |
(UNIX_SOCKET_EVENT_WAIT & type);
} else if (strncmp(argv[0], "--save-replay-buffer", 20) == 0) {
type = UNIX_SOCKET_EVENT_SAVE_REPLAY_BUFFER |
(UNIX_SOCKET_EVENT_WAIT & type);
} else if (strncmp(argv[0], "--get-status", 12) == 0) {
type = UNIX_SOCKET_EVENT_GET_STATUS |
(UNIX_SOCKET_EVENT_WAIT & type);
} else if (strncmp(argv[0], "--wait", 6) == 0) {
type |= UNIX_SOCKET_EVENT_WAIT;
} else { } else {
puts("ERROR: Invalid arg!"); puts("ERROR: Invalid arg!");
print_usage(argv[0]); print_usage(program_name);
return 2; return 2;
} }
} else { ++argv;
print_usage(argv[0]); --argc;
return 1;
} }
char socket_filename[108]; char socket_filename[108];
@ -58,7 +96,7 @@ int main(int argc, char **argv) {
struct sockaddr_un addr; struct sockaddr_un addr;
int ret; int ret;
__attribute__((cleanup(cleanup_data_socket))) int data_socket = -1; __attribute__((cleanup(cleanup_data_socket))) int data_socket = -1;
char send_buf = (char)type; unsigned char send_buf = (unsigned char)type;
char buffer[8]; char buffer[8];
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
@ -94,26 +132,78 @@ int main(int argc, char **argv) {
} }
if (type == UNIX_SOCKET_EVENT_GET_STATUS && buffer[0] == UNIX_SOCKET_EVENT_GET_STATUS) { if (type == UNIX_SOCKET_EVENT_GET_STATUS && buffer[0] == UNIX_SOCKET_EVENT_GET_STATUS) {
printf("Is recording: %s\nIs streaming: %s\n", printf("Is recording: %s\nIs streaming: %s\nReplay buffer active: %s\n",
(buffer[1] & 1) != 0 ? "true" : "false", (buffer[1] & 1) != 0 ? "true" : "false",
(buffer[1] & 2) != 0 ? "true" : "false"); (buffer[1] & 2) != 0 ? "true" : "false",
} else if (buffer[0] != UNIX_SOCKET_EVENT_NOP) { (buffer[1] & 4) != 0 ? "true" : "false");
} else if (buffer[0] != UNIX_SOCKET_EVENT_NOP
&& buffer[0] != UNIX_SOCKET_EVENT_TOGGLE_RECORDING
&& buffer[0] != UNIX_SOCKET_EVENT_TOGGLE_STREAMING
&& buffer[0] != UNIX_SOCKET_EVENT_TOGGLE_REPLAY_BUFFER) {
// Error. TODO handle this. // Error. TODO handle this.
return 7; return 7;
} else { } else {
switch(type) { switch(type & UNIX_SOCKET_EVENT_MASK) {
case UNIX_SOCKET_EVENT_START_RECORDING: case UNIX_SOCKET_EVENT_START_RECORDING:
puts("Sent event \"start recording\"!"); puts("Sent event \"start recording\"!");
break; break;
case UNIX_SOCKET_EVENT_STOP_RECORDING: case UNIX_SOCKET_EVENT_STOP_RECORDING:
puts("Sent event \"stop recording\"!"); puts("Sent event \"stop recording\"!");
break; break;
case UNIX_SOCKET_EVENT_TOGGLE_RECORDING:
switch(buffer[1]) {
case UNIX_SOCKET_EVENT_START_RECORDING:
puts("Sent event \"toggle recording\", recording STARTED!");
break;
case UNIX_SOCKET_EVENT_STOP_RECORDING:
puts("Sent event \"toggle recording\", recording STOPPED!");
break;
default:
puts("Sent event \"toggle recording\", recording status UNKNOWN!");
break;
}
break;
case UNIX_SOCKET_EVENT_START_STREAMING: case UNIX_SOCKET_EVENT_START_STREAMING:
puts("Sent event \"start streaming\"!"); puts("Sent event \"start streaming\"!");
break; break;
case UNIX_SOCKET_EVENT_STOP_STREAMING: case UNIX_SOCKET_EVENT_STOP_STREAMING:
puts("Sent event \"stop streaming\"!"); puts("Sent event \"stop streaming\"!");
break; break;
case UNIX_SOCKET_EVENT_TOGGLE_STREAMING:
switch(buffer[1]) {
case UNIX_SOCKET_EVENT_START_STREAMING:
puts("Sent event \"toggle streaming\", stream STARTED!");
break;
case UNIX_SOCKET_EVENT_STOP_STREAMING:
puts("Sent event \"toggle streaming\", stream STOPPED!");
break;
default:
puts("Sent event \"toggle streaming\", stream status UNKNOWN!");
break;
}
break;
case UNIX_SOCKET_EVENT_START_REPLAY_BUFFER:
puts("Sent event \"start replay-buffer\"!");
break;
case UNIX_SOCKET_EVENT_STOP_REPLAY_BUFFER:
puts("Sent event \"stop replay-buffer\"!");
break;
case UNIX_SOCKET_EVENT_TOGGLE_REPLAY_BUFFER:
switch(buffer[1]) {
case UNIX_SOCKET_EVENT_START_REPLAY_BUFFER:
puts("Sent event \"toggle replay-buffer\", replay-buffer STARTED!");
break;
case UNIX_SOCKET_EVENT_STOP_REPLAY_BUFFER:
puts("Sent event \"toggle replay-buffer\", replay-buffer STOPPED!");
break;
default:
puts("Sent event \"toggle replay-buffer\", replay-buffer status UNKNOWN!");
break;
}
break;
case UNIX_SOCKET_EVENT_SAVE_REPLAY_BUFFER:
puts("Sent event \"save replay-buffer\"!");
break;
default: default:
// Error. TODO handle this // Error. TODO handle this
return 8; return 8;

View file

@ -9,7 +9,15 @@ typedef enum UnixSocketEventType {
UNIX_SOCKET_EVENT_STOP_RECORDING, UNIX_SOCKET_EVENT_STOP_RECORDING,
UNIX_SOCKET_EVENT_START_STREAMING, UNIX_SOCKET_EVENT_START_STREAMING,
UNIX_SOCKET_EVENT_STOP_STREAMING, UNIX_SOCKET_EVENT_STOP_STREAMING,
UNIX_SOCKET_EVENT_GET_STATUS UNIX_SOCKET_EVENT_GET_STATUS,
UNIX_SOCKET_EVENT_START_REPLAY_BUFFER,
UNIX_SOCKET_EVENT_STOP_REPLAY_BUFFER,
UNIX_SOCKET_EVENT_SAVE_REPLAY_BUFFER,
UNIX_SOCKET_EVENT_TOGGLE_RECORDING,
UNIX_SOCKET_EVENT_TOGGLE_STREAMING,
UNIX_SOCKET_EVENT_TOGGLE_REPLAY_BUFFER,
UNIX_SOCKET_EVENT_WAIT = 0x80,
UNIX_SOCKET_EVENT_MASK = 0x7F
} UnixSocketEventType; } UnixSocketEventType;
#endif #endif

View file

@ -1,4 +1,5 @@
#include "socket.h" #include "socket.h"
#include "common_constants.h"
// standard library includes // standard library includes
#include <stdlib.h> #include <stdlib.h>
@ -15,6 +16,22 @@
// obs-studio includes // obs-studio includes
#include <obs-frontend-api.h> #include <obs-frontend-api.h>
void internal_wait_on_obs_frontend_event(UnixSocketHandler *handler, UnixSocketEventType event) {
if (is_unix_socket_handler_valid(handler) && (event & UNIX_SOCKET_EVENT_WAIT) != 0) {
struct timespec duration;
duration.tv_sec = 0;
duration.tv_nsec = 1000000;
unsigned int ticks = 0;
while(atomic_load(&handler->callback_var) != (event & UNIX_SOCKET_EVENT_MASK)) {
if (++ticks > 5000) {
break;
} else {
thrd_sleep(&duration, 0);
}
}
}
}
int unix_socket_handler_thread_function(void *ud) { int unix_socket_handler_thread_function(void *ud) {
UnixSocketHandler *handler = (UnixSocketHandler*)ud; UnixSocketHandler *handler = (UnixSocketHandler*)ud;
@ -56,6 +73,8 @@ int unix_socket_handler_thread_function(void *ud) {
} }
mtx_unlock(handler->mutex); mtx_unlock(handler->mutex);
atomic_store(&handler->callback_var, 0);
ret = read(data_socket, buffer, sizeof(buffer)); ret = read(data_socket, buffer, sizeof(buffer));
if (ret == -1) { if (ret == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) { if (errno == EAGAIN || errno == EWOULDBLOCK) {
@ -71,19 +90,45 @@ int unix_socket_handler_thread_function(void *ud) {
break; break;
} }
if (buffer[0] == UNIX_SOCKET_EVENT_START_RECORDING) { if ((buffer[0] & UNIX_SOCKET_EVENT_MASK) == UNIX_SOCKET_EVENT_START_RECORDING) {
obs_frontend_recording_start(); obs_frontend_recording_start();
internal_wait_on_obs_frontend_event(handler, buffer[0]);
ret_buffer[0] = UNIX_SOCKET_EVENT_NOP; ret_buffer[0] = UNIX_SOCKET_EVENT_NOP;
} else if (buffer[0] == UNIX_SOCKET_EVENT_STOP_RECORDING) { } else if ((buffer[0] & UNIX_SOCKET_EVENT_MASK) == UNIX_SOCKET_EVENT_STOP_RECORDING) {
obs_frontend_recording_stop(); obs_frontend_recording_stop();
internal_wait_on_obs_frontend_event(handler, buffer[0]);
ret_buffer[0] = UNIX_SOCKET_EVENT_NOP; ret_buffer[0] = UNIX_SOCKET_EVENT_NOP;
} else if (buffer[0] == UNIX_SOCKET_EVENT_START_STREAMING) { } else if ((buffer[0] & UNIX_SOCKET_EVENT_MASK) == UNIX_SOCKET_EVENT_TOGGLE_RECORDING) {
ret_buffer[0] = UNIX_SOCKET_EVENT_TOGGLE_RECORDING;
if (obs_frontend_recording_active()) {
obs_frontend_recording_stop();
internal_wait_on_obs_frontend_event(handler, UNIX_SOCKET_EVENT_STOP_RECORDING | (buffer[0] & UNIX_SOCKET_EVENT_WAIT));
ret_buffer[1] = UNIX_SOCKET_EVENT_STOP_RECORDING;
} else {
obs_frontend_recording_start();
internal_wait_on_obs_frontend_event(handler, UNIX_SOCKET_EVENT_START_RECORDING | (buffer[0] & UNIX_SOCKET_EVENT_WAIT));
ret_buffer[1] = UNIX_SOCKET_EVENT_START_RECORDING;
}
} else if ((buffer[0] & UNIX_SOCKET_EVENT_MASK) == UNIX_SOCKET_EVENT_START_STREAMING) {
obs_frontend_streaming_start(); obs_frontend_streaming_start();
internal_wait_on_obs_frontend_event(handler, buffer[0]);
ret_buffer[0] = UNIX_SOCKET_EVENT_NOP; ret_buffer[0] = UNIX_SOCKET_EVENT_NOP;
} else if (buffer[0] == UNIX_SOCKET_EVENT_STOP_STREAMING) { } else if ((buffer[0] & UNIX_SOCKET_EVENT_MASK) == UNIX_SOCKET_EVENT_STOP_STREAMING) {
obs_frontend_streaming_stop(); obs_frontend_streaming_stop();
internal_wait_on_obs_frontend_event(handler, buffer[0]);
ret_buffer[0] = UNIX_SOCKET_EVENT_NOP; ret_buffer[0] = UNIX_SOCKET_EVENT_NOP;
} else if (buffer[0] == UNIX_SOCKET_EVENT_GET_STATUS) { } else if ((buffer[0] & UNIX_SOCKET_EVENT_MASK) == UNIX_SOCKET_EVENT_TOGGLE_STREAMING) {
ret_buffer[0] = UNIX_SOCKET_EVENT_TOGGLE_STREAMING;
if (obs_frontend_streaming_active()) {
obs_frontend_streaming_stop();
internal_wait_on_obs_frontend_event(handler, UNIX_SOCKET_EVENT_STOP_STREAMING | (buffer[0] & UNIX_SOCKET_EVENT_WAIT));
ret_buffer[1] = UNIX_SOCKET_EVENT_STOP_STREAMING;
} else {
obs_frontend_streaming_start();
internal_wait_on_obs_frontend_event(handler, UNIX_SOCKET_EVENT_START_STREAMING | (buffer[0] & UNIX_SOCKET_EVENT_WAIT));
ret_buffer[1] = UNIX_SOCKET_EVENT_START_STREAMING;
}
} else if ((buffer[0] & UNIX_SOCKET_EVENT_MASK) == UNIX_SOCKET_EVENT_GET_STATUS) {
ret_buffer[0] = UNIX_SOCKET_EVENT_GET_STATUS; ret_buffer[0] = UNIX_SOCKET_EVENT_GET_STATUS;
if (obs_frontend_recording_active()) { if (obs_frontend_recording_active()) {
ret_buffer[1] |= 1; ret_buffer[1] |= 1;
@ -91,6 +136,37 @@ int unix_socket_handler_thread_function(void *ud) {
if (obs_frontend_streaming_active()) { if (obs_frontend_streaming_active()) {
ret_buffer[1] |= 2; ret_buffer[1] |= 2;
} }
if (obs_frontend_replay_buffer_active()) {
ret_buffer[1] |= 4;
}
} else if ((buffer[0] & UNIX_SOCKET_EVENT_MASK) == UNIX_SOCKET_EVENT_START_REPLAY_BUFFER) {
obs_frontend_replay_buffer_start();
internal_wait_on_obs_frontend_event(handler, buffer[0]);
ret_buffer[0] = UNIX_SOCKET_EVENT_NOP;
} else if ((buffer[0] & UNIX_SOCKET_EVENT_MASK) == UNIX_SOCKET_EVENT_STOP_REPLAY_BUFFER) {
obs_frontend_replay_buffer_stop();
internal_wait_on_obs_frontend_event(handler, buffer[0]);
ret_buffer[0] = UNIX_SOCKET_EVENT_NOP;
} else if ((buffer[0] & UNIX_SOCKET_EVENT_MASK) == UNIX_SOCKET_EVENT_TOGGLE_REPLAY_BUFFER) {
ret_buffer[0] = UNIX_SOCKET_EVENT_TOGGLE_REPLAY_BUFFER;
if (obs_frontend_replay_buffer_active()) {
obs_frontend_replay_buffer_stop();
internal_wait_on_obs_frontend_event(handler, UNIX_SOCKET_EVENT_STOP_REPLAY_BUFFER | (buffer[0] & UNIX_SOCKET_EVENT_WAIT));
ret_buffer[1] = UNIX_SOCKET_EVENT_STOP_REPLAY_BUFFER;
} else {
obs_frontend_replay_buffer_start();
internal_wait_on_obs_frontend_event(handler, UNIX_SOCKET_EVENT_START_REPLAY_BUFFER | (buffer[0] & UNIX_SOCKET_EVENT_WAIT));
ret_buffer[1] = UNIX_SOCKET_EVENT_START_REPLAY_BUFFER;
}
} else if ((buffer[0] & UNIX_SOCKET_EVENT_MASK) == UNIX_SOCKET_EVENT_SAVE_REPLAY_BUFFER) {
if (obs_frontend_replay_buffer_active()) {
obs_frontend_replay_buffer_save();
internal_wait_on_obs_frontend_event(handler, buffer[0]);
ret_buffer[0] = UNIX_SOCKET_EVENT_NOP;
} else {
ret = -1;
break;
}
} }
ret = 0; ret = 0;
break; break;
@ -119,6 +195,11 @@ void init_unix_socket_handler(UnixSocketHandler *handler) {
umask(S_IRWXO); umask(S_IRWXO);
// Set up atomic value.
atomic_init(&handler->callback_var, 0);
obs_frontend_add_event_callback(unix_socket_handler_frontend_event_callback, handler);
// Set up unix socket. // Set up unix socket.
handler->socket_descriptor = socket(AF_UNIX, SOCK_SEQPACKET, 0); handler->socket_descriptor = socket(AF_UNIX, SOCK_SEQPACKET, 0);
if (handler->socket_descriptor == -1) { if (handler->socket_descriptor == -1) {
@ -221,3 +302,35 @@ void cleanup_unix_socket_handler(UnixSocketHandler *handler) {
int is_unix_socket_handler_valid(const UnixSocketHandler *handler) { int is_unix_socket_handler_valid(const UnixSocketHandler *handler) {
return handler->flags == 0xFFFFFFFFFFFFFFFF ? 0 : 1; return handler->flags == 0xFFFFFFFFFFFFFFFF ? 0 : 1;
} }
void unix_socket_handler_frontend_event_callback(enum obs_frontend_event event,
void *ud) {
UnixSocketHandler *handler = ud;
if (is_unix_socket_handler_valid(handler)) {
switch (event) {
case OBS_FRONTEND_EVENT_RECORDING_STARTED:
atomic_store(&handler->callback_var, UNIX_SOCKET_EVENT_START_RECORDING);
break;
case OBS_FRONTEND_EVENT_RECORDING_STOPPED:
atomic_store(&handler->callback_var, UNIX_SOCKET_EVENT_STOP_RECORDING);
break;
case OBS_FRONTEND_EVENT_STREAMING_STARTED:
atomic_store(&handler->callback_var, UNIX_SOCKET_EVENT_START_STREAMING);
break;
case OBS_FRONTEND_EVENT_STREAMING_STOPPED:
atomic_store(&handler->callback_var, UNIX_SOCKET_EVENT_STOP_STREAMING);
break;
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTED:
atomic_store(&handler->callback_var, UNIX_SOCKET_EVENT_START_REPLAY_BUFFER);
break;
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPED:
atomic_store(&handler->callback_var, UNIX_SOCKET_EVENT_STOP_REPLAY_BUFFER);
break;
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVED:
atomic_store(&handler->callback_var, UNIX_SOCKET_EVENT_SAVE_REPLAY_BUFFER);
break;
default:
break;
}
}
}

View file

@ -4,11 +4,15 @@
// standard library includes // standard library includes
#include <stdint.h> #include <stdint.h>
#include <threads.h> #include <threads.h>
#include <stdatomic.h>
// unix includes // unix includes
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>
// third party includes
#include <obs-frontend-api.h>
// local includes // local includes
#include "common_constants.h" #include "common_constants.h"
@ -20,6 +24,7 @@ typedef struct UnixSocketHandler {
struct sockaddr_un name; struct sockaddr_un name;
thrd_t *thread; thrd_t *thread;
mtx_t *mutex; mtx_t *mutex;
atomic_uint callback_var;
/* /*
* ???? 0001 - thread should stop * ???? 0001 - thread should stop
*/ */
@ -32,5 +37,6 @@ typedef struct UnixSocketHandler {
void init_unix_socket_handler(UnixSocketHandler *handler); void init_unix_socket_handler(UnixSocketHandler *handler);
void cleanup_unix_socket_handler(UnixSocketHandler *handler); void cleanup_unix_socket_handler(UnixSocketHandler *handler);
int is_unix_socket_handler_valid(const UnixSocketHandler *handler); int is_unix_socket_handler_valid(const UnixSocketHandler *handler);
void unix_socket_handler_frontend_event_callback(enum obs_frontend_event event, void *ud);
#endif #endif