aboutsummaryrefslogtreecommitdiff
path: root/src/media.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/media.c')
-rw-r--r--src/media.c74
1 files changed, 73 insertions, 1 deletions
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 <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <signal.h>
+#include <sys/wait.h>
#include <unistd.h>
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;
}