~q3cpma/mus

ref: cf29c2237d0c99e5240a55895c07564ef4635392 mus/mus_player/status.c -rw-r--r-- 2.6 KiB
cf29c223q3cpma Add a #pragma once to the new xoshiro128plus.h header 1 year, 7 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include <signal.h>
#include <spawn.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>

#include "log.h"
#include "misc.h"
#include "status.h"


static const char *const state_str[] =
{
	"playing",
	"paused",
	"quitting",
};

void status_fprint(FILE *stream, Player_state state, const Track_info *tinfo)
{
	char *abs_path = realpath(tinfo->path, NULL);

	fprintf(stream,
		"status %s\n"
		"path %s\n"
		"format nb_channels %d sample_rate %d bit_depth %d "
			"bit_rate %"PRIu64"k\n"
		"duration %s\n"
		"position %s\n",
		state_str[state],
		abs_path ? abs_path : strerror(errno),
		tinfo->format.channels, tinfo->format.rate, tinfo->format.bits,
			tinfo->bitrate / 1000,
		duration_get_formatted(tinfo->duration),
		duration_get_formatted(tinfo->position));
	tags_fprint(stream, tinfo->tags);

	duration_invalid_formatted_cache(tinfo->position);
	free(abs_path);
}

extern char **environ;

void status_exec_notify_cmd(const char *cmd, Player_state state,
	const Track_info *tinfo)
{
	if (!cmd)
		return;

	static pid_t status_cmd_pid = -1;

	if (status_cmd_pid != -1)
	{
		bool timedout = false;
		int wait_status;

		if (waitpid(status_cmd_pid, &wait_status, WNOHANG) == 0)
		{
			if (kill(status_cmd_pid, SIGTERM) != -1)
				timedout = true;
			else /* waitpid guarantees it's not ESRCH */
				LOG_DIE("%s: %s", cmd, strerror(errno));
			wait(&wait_status);
		}

		if (timedout)
			log_append(LOG_ERR, "Status cmd (\"%s\") timed out", cmd);
		else if (WIFEXITED(wait_status) && WEXITSTATUS(wait_status))
		{
			log_append(LOG_ERR, "Status cmd (\"%s\") exited with non-zero "
				"status (%d)", cmd, WEXITSTATUS(wait_status));
		}
	}

	int fd[2];
	if (pipe(fd) != 0)
		LOG_DIE("Creating pipe: %s", strerror(errno));
	FILE *pipe_wr_stream = fdopen(fd[1], "w");

	posix_spawn_file_actions_t actions;
	int ret;
	if ((ret = posix_spawn_file_actions_init(&actions)) != 0)
		LOG_DIE("posix_spawn_file_actions_init: %s", strerror(ret));
	if ((ret = posix_spawn_file_actions_adddup2(&actions, fd[0], STDIN_FILENO)) != 0)
		LOG_DIE("posix_spawn_file_actions_adddup2: %s", strerror(ret));
	if ((ret = posix_spawn_file_actions_addclose(&actions, fd[0])) != 0)
		LOG_DIE("posix_spawn_file_actions_addclose: %s", strerror(ret));
	if ((ret = posix_spawn_file_actions_addclose(&actions, fd[1])) != 0)
		LOG_DIE("posix_spawn_file_actions_addclose: %s", strerror(ret));
	ret = posix_spawn(&status_cmd_pid, "/bin/sh", &actions, NULL,
		(char *const[]){"sh", "-c", (char *)cmd, NULL}, environ);
	if (ret != 0)
		LOG_DIE("posix_spawn: %s", strerror(ret));
	posix_spawn_file_actions_destroy(&actions);

	xclose(fd[0]);
	status_fprint(pipe_wr_stream, state, tinfo);
	xfclose(pipe_wr_stream);
}