add existing source
[uwplayer.git] / application / player.c
1 /*
2  * Copyright 2022 Olaf Wintermann
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a 
5  * copy of this software and associated documentation files (the "Software"), 
6  * to deal in the Software without restriction, including without limitation 
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense, 
8  * and/or sell copies of the Software, and to permit persons to whom the 
9  * Software is furnished to do so, subject to the following conditions:
10  * 
11  * The above copyright notice and this permission notice shall be included in 
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
20  * DEALINGS IN THE SOFTWARE.
21  */
22
23 #include "player.h"
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <sys/fcntl.h>
29 #include <spawn.h>
30 #include <sys/wait.h>
31
32 #include <pthread.h>
33
34 extern char **environ;
35
36 #define WID_ARG_BUFSIZE 24
37
38 static void* start_player(void *data);
39
40 void PlayerOpenFile(MainWindow *win) {
41     pthread_t tid;
42     if(pthread_create(&tid, NULL, start_player, win)) {
43         perror("pthread_create");
44     }
45 }
46
47 static void* start_player(void *data) {
48     MainWindow *win = data;
49     
50     char *player_bin = "/usr/local/bin/mpv"; // TODO: get bin from settings
51     
52     // -wid parameter value for embedding the player in the player_widget
53     Window wid = XtWindow(win->player_widget);
54     char wid_arg[WID_ARG_BUFSIZE];
55     if(snprintf(wid_arg, WID_ARG_BUFSIZE, "%lu", wid) >= WID_ARG_BUFSIZE) {
56         return NULL;
57     }
58     
59     // create player arg list
60     char *args[32];
61     args[0] = player_bin;
62     args[1] = "-wid";
63     args[2] = wid_arg;
64     args[3] = win->file;
65     args[4] = NULL;
66     
67     // redirect stdin/stdout
68     int pout[2];
69     int pin[2];
70     if(pipe(pout)) {
71         perror("pipe");
72         return NULL;
73     }
74     if(pipe(pin)) {
75         perror("pipe");
76         return NULL;
77     }
78     
79     posix_spawn_file_actions_t actions;
80     posix_spawn_file_actions_init(&actions);
81     
82     posix_spawn_file_actions_adddup2(&actions, pin[0], STDIN_FILENO);
83     posix_spawn_file_actions_adddup2(&actions, pout[1], STDOUT_FILENO);
84     
85     // start player
86     pid_t player_pid;
87     if(posix_spawn(&player_pid, player_bin, &actions, NULL, args, environ)) {
88         perror("posix_spawn");
89         return NULL;
90     }
91     posix_spawn_file_actions_destroy(&actions);
92     
93     Player *player = malloc(sizeof(Player));
94     memset(player, 0, sizeof(Player));
95     
96     player->in = pin[1];
97     player->out = pout[0];
98     close(pin[0]);
99     close(pout[1]);
100     player->process = player_pid;
101     
102     if(win->player) {
103         PlayerDestroy(win->player);
104     }
105     win->player = player;
106     
107     return NULL;
108 }
109
110 void PlayerDestroy(Player *p) {
111     free(p);
112 }