aboutsummaryrefslogtreecommitdiff
path: root/video_player/include/Args.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'video_player/include/Args.hpp')
-rw-r--r--video_player/include/Args.hpp136
1 files changed, 136 insertions, 0 deletions
diff --git a/video_player/include/Args.hpp b/video_player/include/Args.hpp
new file mode 100644
index 0000000..610f0b0
--- /dev/null
+++ b/video_player/include/Args.hpp
@@ -0,0 +1,136 @@
+#pragma once
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <string>
+#include <vector>
+
+struct MpvProperty {
+ std::string key;
+ std::string value;
+};
+
+struct Args {
+ long wid_num = 0;
+ long ipc_fd_num = 0;
+
+ const char *ipc_fd = nullptr;
+ const char *audio_file = nullptr;
+ const char *file_to_play = nullptr;
+
+ std::vector<MpvProperty> mpv_properties;
+};
+
+static void usage() {
+ fprintf(stderr, "usage: quickmedia-video-player [--ipc-fd <fd>] [--audio-file <audio_file>] [--key=value...] <file>\n");
+ fprintf(stderr, " --ipc-fd <fd> A bi-directional (socketpair) file descriptor to receive commands from. Optional\n");
+ fprintf(stderr, " --audio-file <audio_file> Load the given audio file. Optional\n");
+ fprintf(stderr, " --key=value Additional options in the format --key=value are passed directly to mpv as string properties. Optional\n");
+ fprintf(stderr, "examples:\n");
+ fprintf(stderr, " quickmedia-video-player video.mp4\n");
+ fprintf(stderr, " quickmedia-video-player --wid 30481231 -- video.mp4\n");
+ exit(1);
+}
+
+static bool string_to_long(const char *str, long &result) {
+ errno = 0;
+ char *endptr = NULL;
+ result = strtol(str, &endptr, 0);
+ return endptr != str && errno == 0;
+}
+
+static bool string_to_double(const char *str, double &result) {
+ errno = 0;
+ char *endptr = NULL;
+ result = strtod(str, &endptr);
+ return endptr != str && errno == 0;
+}
+
+static bool fd_is_valid(int fd) {
+ errno = 0;
+ return fcntl(fd, F_GETFD) != -1 && errno != EBADF;
+}
+
+static Args parse_args(int argc, char **argv) {
+ Args args;
+
+ for(int i = 1; i < argc; ++i) {
+ const char *arg = argv[i];
+ if(strcmp(arg, "--audio-file") == 0) {
+ if(args.audio_file) {
+ fprintf(stderr, "Error: option --audio-file was specified multiple times\n");
+ usage();
+ }
+
+ if(i + 1 == argc) {
+ fprintf(stderr, "Error: missing audio file after option --audio-file\n");
+ usage();
+ }
+
+ args.audio_file = argv[i + 1];
+ ++i;
+ } else if(strcmp(arg, "--ipc-fd") == 0) {
+ if(args.ipc_fd) {
+ fprintf(stderr, "Error: option --ipc-fd was specified multiple times\n");
+ usage();
+ }
+
+ if(i + 1 == argc) {
+ fprintf(stderr, "Error: missing fd after option --ipc-fd\n");
+ usage();
+ }
+
+ args.ipc_fd = argv[i + 1];
+ ++i;
+ } else if(strcmp(arg, "--") == 0) {
+ if(i + 1 == argc) {
+ fprintf(stderr, "Error: missing file option after --\n");
+ usage();
+ } else if(i + 1 != argc - 1) {
+ fprintf(stderr, "Error: more than one option was specified after --\n");
+ usage();
+ }
+
+ args.file_to_play = argv[i + 1];
+ ++i;
+ } else if(strncmp(arg, "--", 2) == 0) {
+ const char *equal_p = strchr(arg, '=');
+ if(!equal_p) {
+ fprintf(stderr, "Error: mpv option %s is missing \"=\"\n", arg);
+ usage();
+ }
+
+ args.mpv_properties.push_back({ std::string(arg + 2, equal_p - (arg + 2)), equal_p + 1 });
+ } else {
+ if(args.file_to_play) {
+ fprintf(stderr, "Error: file option was specified multiple times\n");
+ usage();
+ }
+
+ args.file_to_play = arg;
+ }
+ }
+
+ if(!args.file_to_play) {
+ fprintf(stderr, "Error: missing file option\n");
+ usage();
+ }
+
+ if(args.ipc_fd) {
+ if(!string_to_long(args.ipc_fd, args.ipc_fd_num)) {
+ fprintf(stderr, "Error: invalid number %s was specified for option --ipc-fd\n", args.ipc_fd);
+ usage();
+ }
+
+ if(!fd_is_valid(args.ipc_fd_num)) {
+ fprintf(stderr, "Error: invalid fd %s was specified for option --ipc-fd\n", args.ipc_fd);
+ usage();
+ }
+ }
+
+ return args;
+} \ No newline at end of file