aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/VideoPlayer.hpp6
-rw-r--r--src/VideoPlayer.cpp77
2 files changed, 53 insertions, 30 deletions
diff --git a/include/VideoPlayer.hpp b/include/VideoPlayer.hpp
index 97e4b61..bdf3344 100644
--- a/include/VideoPlayer.hpp
+++ b/include/VideoPlayer.hpp
@@ -5,6 +5,7 @@
#include <SFML/System/Clock.hpp>
#include <functional>
#include <json/value.h>
+#include <sys/un.h>
#include <X11/Xlib.h>
namespace QuickMedia {
@@ -16,6 +17,7 @@ namespace QuickMedia {
public:
enum class Error {
OK,
+ FAIL_TO_GENERATE_IPC_FILENAME,
FAIL_TO_LAUNCH_PROCESS,
FAIL_TO_CREATE_SOCKET,
FAIL_TO_CONNECT_TIMEOUT,
@@ -65,7 +67,9 @@ namespace QuickMedia {
int connect_tries;
int find_window_tries;
int monitor_height;
- int sockets[2];
+ int ipc_socket = -1;
+ struct sockaddr_un ipc_addr;
+ char ipc_server_path[L_tmpnam];
EventCallbackFunc event_callback;
VideoPlayerWindowCreateCallback window_create_callback;
sf::WindowHandle window_handle;
diff --git a/src/VideoPlayer.cpp b/src/VideoPlayer.cpp
index eb2e7d5..d4e27d1 100644
--- a/src/VideoPlayer.cpp
+++ b/src/VideoPlayer.cpp
@@ -93,8 +93,7 @@ namespace QuickMedia {
abort();
}
fprintf(stderr, "Video max height: %d\n", monitor_height);
- for(int i = 0; i < 2; ++i)
- sockets[i] = -1;
+ ipc_server_path[0] = '\0';
}
VideoPlayer::~VideoPlayer() {
@@ -103,10 +102,11 @@ namespace QuickMedia {
wait_program(video_process_id);
}
- for(int i = 0; i < 2; ++i) {
- if(sockets[i] != -1)
- close(sockets[i]);
- }
+ if(ipc_socket != -1)
+ close(ipc_socket);
+
+ if(video_process_id != -1 && ipc_server_path[0] != '\0')
+ remove(ipc_server_path);
if(display)
XCloseDisplay(display);
@@ -118,18 +118,16 @@ namespace QuickMedia {
VideoPlayer::Error VideoPlayer::launch_video_process(const char *path, const char *audio_path, sf::WindowHandle _parent_window, bool is_youtube, const std::string &title, const std::string &start_time) {
parent_window = _parent_window;
- if(socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1) {
- sockets[0] = -1;
- sockets[1] = -1;
- perror("Failed to create socketpair to mpv");
- return Error::FAIL_TO_CREATE_SOCKET;
+ if(!tmpnam(ipc_server_path)) {
+ perror("Failed to generate ipc file name");
+ return Error::FAIL_TO_GENERATE_IPC_FILENAME;
}
const std::string parent_window_str = std::to_string(parent_window);
std::vector<const char*> args;
- std::string input_ipc_client_fd_arg = "--input-ipc-client=fd://";
- input_ipc_client_fd_arg += std::to_string(sockets[1]);
+ std::string input_ipc_server_arg = "--input-ipc-server=";
+ input_ipc_server_arg += ipc_server_path;
std::string wid_arg = "--wid=";
wid_arg += parent_window_str;
@@ -138,7 +136,7 @@ namespace QuickMedia {
// TODO: Resume playback if the last video played matches the first video played next time QuickMedia is launched
args.insert(args.end(), {
"mpv",
- input_ipc_client_fd_arg.c_str(),
+ input_ipc_server_arg.c_str(),
"--cursor-autohide=no", /* "--no-input-default-bindings", "--input-vo-keyboard=no", "--no-input-cursor", */
"--no-terminal",
"--save-position-on-quit=no",
@@ -211,19 +209,25 @@ namespace QuickMedia {
args.insert(args.end(), { "--", path, nullptr });
- if(exec_program_async(args.data(), &video_process_id) != 0) {
- for(int i = 0; i < 2; ++i) {
- if(sockets[i] != -1)
- close(sockets[i]);
- sockets[i] = -1;
- }
- return Error::FAIL_TO_LAUNCH_PROCESS;
+ fprintf(stderr, "mpv input ipc server: %s\n", ipc_server_path);
+
+ if((ipc_socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+ perror("Failed to create socket for video player");
+ return Error::FAIL_TO_CREATE_SOCKET;
}
- int flags = fcntl(sockets[0], F_GETFL, 0);
+ ipc_addr.sun_family = AF_UNIX;
+ strcpy(ipc_addr.sun_path, ipc_server_path);
+
+ int flags = fcntl(ipc_socket, F_GETFL, 0);
if(flags != -1) // TODO: Proper error handling
- fcntl(sockets[0], F_SETFL, flags | O_NONBLOCK);
- connected_to_ipc = true;
+ fcntl(ipc_socket, F_SETFL, flags | O_NONBLOCK);
+
+ if(exec_program_async(args.data(), &video_process_id) != 0) {
+ close(ipc_socket);
+ ipc_socket = -1;
+ return Error::FAIL_TO_LAUNCH_PROCESS;
+ }
return Error::OK;
}
@@ -271,7 +275,7 @@ namespace QuickMedia {
VideoPlayer::Error VideoPlayer::update() {
const int max_retries_find_window = 1000;
- if(sockets[0] == -1)
+ if(ipc_socket == -1)
return Error::INIT_FAILED;
if(connect_tries == MAX_RETRIES_CONNECT)
@@ -280,6 +284,19 @@ namespace QuickMedia {
if(find_window_tries == max_retries_find_window)
return Error::FAIL_TO_FIND_WINDOW;
+ if(!connected_to_ipc && retry_timer.getElapsedTime().asMilliseconds() >= RETRY_TIME_MS) {
+ retry_timer.restart();
+ if(connect(ipc_socket, (struct sockaddr*)&ipc_addr, sizeof(ipc_addr)) == -1) {
+ ++connect_tries;
+ if(connect_tries == MAX_RETRIES_CONNECT) {
+ fprintf(stderr, "Failed to connect to mpv ipc after %d seconds, last error: %s\n", (RETRY_TIME_MS * MAX_RETRIES_CONNECT)/1000, strerror(errno));
+ return Error::FAIL_TO_CONNECT_TIMEOUT;
+ }
+ } else {
+ connected_to_ipc = true;
+ }
+ }
+
if(connected_to_ipc && window_handle == 0 && retry_timer.getElapsedTime().asMilliseconds() >= RETRY_TIME_MS) {
retry_timer.restart();
std::vector<Window> child_windows = get_child_window(display, parent_window);
@@ -303,9 +320,11 @@ namespace QuickMedia {
if(video_process_id != -1) {
if(wait_program_non_blocking(video_process_id, &exit_status)) {
fprintf(stderr, "The video player exited!, status: %d\n", exit_status);
- close(sockets[0]);
+ close(ipc_socket);
+ remove(ipc_server_path);
+ ipc_server_path[0] = '\0';
video_process_id = -1;
- sockets[0] = -1;
+ ipc_socket = -1;
window_handle = None;
connected_to_ipc = false;
return Error::EXITED;
@@ -329,7 +348,7 @@ namespace QuickMedia {
std::string json_errors;
char buffer[2048];
- ssize_t bytes_read = read(sockets[0], buffer, sizeof(buffer));
+ ssize_t bytes_read = read(ipc_socket, buffer, sizeof(buffer));
if(bytes_read == -1) {
int err = errno;
if(err != EAGAIN && err != EWOULDBLOCK) {
@@ -450,7 +469,7 @@ namespace QuickMedia {
if(!connected_to_ipc)
return Error::FAIL_NOT_CONNECTED;
- if(send(sockets[0], cmd, size, 0) == -1) {
+ if(send(ipc_socket, cmd, size, 0) == -1) {
fprintf(stderr, "Failed to send to ipc socket, error: %s, command: %.*s\n", strerror(errno), (int)size, cmd);
return Error::FAIL_TO_SEND;
}