From a15cb041654ae307add0b998b526c87c3f42bf5f Mon Sep 17 00:00:00 2001 From: David Moc Date: Tue, 2 Jun 2026 13:50:21 +0200 Subject: Add plugin hooks and mode plugins --- src/media.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) (limited to 'src/media.c') diff --git a/src/media.c b/src/media.c index 6c7a989..4e14a96 100644 --- a/src/media.c +++ b/src/media.c @@ -10,11 +10,70 @@ #include #include #include +#include +#include #include extern FILE *popen(const char *command, const char *type); extern int pclose(FILE *stream); extern int mkstemp(char *template); +extern int kill(pid_t pid, int sig); + +static int media_audio_enabled(void) { + const char *enabled = getenv("ECEX_MEDIA_AUDIO"); + return !enabled || !enabled[0] || enabled[0] != '0'; +} + +static void media_audio_stop(buffer_t *buffer) { + if (!buffer || buffer->media_audio_pid <= 0) return; + + pid_t pid = (pid_t)buffer->media_audio_pid; + kill(pid, SIGTERM); + + if (waitpid(pid, NULL, WNOHANG) != pid) { + kill(pid, SIGKILL); + waitpid(pid, NULL, 0); + } + buffer->media_audio_pid = 0; +} + +static void media_audio_reap(buffer_t *buffer) { + if (!buffer || buffer->media_audio_pid <= 0) return; + if (waitpid((pid_t)buffer->media_audio_pid, NULL, WNOHANG) > 0) { + buffer->media_audio_pid = 0; + } +} + +static int media_audio_start(buffer_t *buffer) { + if (!buffer || !buffer->media_path || !media_audio_enabled()) return ECEX_ERR; + if (buffer->media_audio_pid > 0) return ECEX_OK; + + const char *player = getenv("ECEX_FFPLAY"); + if (!player || !player[0]) player = "ffplay"; + + pid_t pid = fork(); + if (pid < 0) return ECEX_ERR; + + if (pid == 0) { + execlp(player, + player, + "-nodisp", + "-autoexit", + "-loglevel", + "quiet", + buffer->media_path, + (char *)NULL); + _exit(127); + } + + buffer->media_audio_pid = (int)pid; + return ECEX_OK; +} + +static void media_audio_set_paused(buffer_t *buffer, int paused) { + if (!buffer || buffer->media_audio_pid <= 0) return; + kill((pid_t)buffer->media_audio_pid, paused ? SIGSTOP : SIGCONT); +} static char *shell_quote(const char *path) { if (!path) return NULL; @@ -220,6 +279,7 @@ static void buffer_set_media_text(buffer_t *buffer, const char *path, int video, void ecex_media_buffer_clear(buffer_t *buffer) { if (!buffer) return; + media_audio_stop(buffer); if (buffer->media_pipe) { pclose((FILE *)buffer->media_pipe); buffer->media_pipe = NULL; @@ -236,6 +296,7 @@ void ecex_media_buffer_clear(buffer_t *buffer) { buffer->media_texture_height = 0; buffer->media_last_frame_time = 0.0; buffer->media_playing = 0; + buffer->media_audio_pid = 0; buffer->media_status[0] = '\0'; } @@ -307,7 +368,11 @@ int ecex_media_load_into_buffer(ecex_t *ed, const char *path, buffer_t *buffer) if (video) { buffer->media_pipe = pipe; buffer->media_playing = 1; - snprintf(buffer->media_status, sizeof(buffer->media_status), "Playing at decoded 60fps stream"); + if (media_audio_start(buffer) == ECEX_OK) { + snprintf(buffer->media_status, sizeof(buffer->media_status), "Playing decoded 60fps stream with ffplay audio"); + } else { + snprintf(buffer->media_status, sizeof(buffer->media_status), "Playing decoded 60fps stream; audio unavailable"); + } } else { pclose(pipe); snprintf(buffer->media_status, sizeof(buffer->media_status), "Image decoded via ffmpeg"); @@ -345,6 +410,11 @@ int ecex_media_toggle_playback(ecex_t *ed) { buffer_t *buffer = ecex_current_buffer(ed); if (!buffer || buffer->media_kind != ECEX_MEDIA_VIDEO) return ECEX_ERR; buffer->media_playing = !buffer->media_playing; + if (buffer->media_playing && buffer->media_audio_pid <= 0) { + media_audio_start(buffer); + } else { + media_audio_set_paused(buffer, !buffer->media_playing); + } snprintf(buffer->media_status, sizeof(buffer->media_status), "%s", @@ -358,6 +428,7 @@ int ecex_media_tick(ecex_t *ed, double now_seconds) { for (size_t i = 0; i < ed->buffer_count; i++) { buffer_t *buffer = ed->buffers[i]; if (!buffer || buffer->media_kind != ECEX_MEDIA_VIDEO || !buffer->media_pipe || !buffer->media_playing) continue; + media_audio_reap(buffer); if (buffer->media_last_frame_time > 0.0 && now_seconds - buffer->media_last_frame_time < (1.0 / 60.0)) continue; int w = 0, h = 0; @@ -370,6 +441,7 @@ int ecex_media_tick(ecex_t *ed, double now_seconds) { pclose((FILE *)buffer->media_pipe); buffer->media_pipe = NULL; buffer->media_playing = 0; + media_audio_stop(buffer); snprintf(buffer->media_status, sizeof(buffer->media_status), "Playback finished"); dirty = 1; } -- cgit v1.2.3