8e03fbc00a0657dc2e1275c45b1bf715e8f26327
[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 #include <signal.h>
32
33 #include <pthread.h>
34
35 extern char **environ;
36
37 #define WID_ARG_BUFSIZE 24
38
39 static void* start_player(void *data);
40 static void* player_io_thread(void *data);
41
42 void PlayerOpenFile(MainWindow *win) {
43     pthread_t tid;
44     if(pthread_create(&tid, NULL, start_player, win)) {
45         perror("pthread_create");
46     }
47 }
48
49 static void* start_player(void *data) {
50     MainWindow *win = data;
51     
52     char *player_bin = "/usr/local/bin/mpv"; // TODO: get bin from settings
53     
54     // -wid parameter value for embedding the player in the player_widget
55     Window wid = XtWindow(win->player_widget);
56     char wid_arg[WID_ARG_BUFSIZE];
57     if(snprintf(wid_arg, WID_ARG_BUFSIZE, "%lu", wid) >= WID_ARG_BUFSIZE) {
58         return NULL;
59     }
60     
61     // create player arg list
62     char *args[32];
63     args[0] = player_bin;
64     args[1] = "-wid";
65     args[2] = wid_arg;
66     args[3] = win->file;
67     args[4] = NULL;
68     
69     // redirect stdin/stdout
70     int pout[2];
71     int pin[2];
72     if(pipe(pout)) {
73         perror("pipe");
74         return NULL;
75     }
76     if(pipe(pin)) {
77         perror("pipe");
78         return NULL;
79     }
80     
81     posix_spawn_file_actions_t actions;
82     posix_spawn_file_actions_init(&actions);
83     
84     posix_spawn_file_actions_adddup2(&actions, pin[0], STDIN_FILENO);
85     posix_spawn_file_actions_adddup2(&actions, pout[1], STDOUT_FILENO);
86     
87     // start player
88     pid_t player_pid;
89     if(posix_spawn(&player_pid, player_bin, &actions, NULL, args, environ)) {
90         perror("posix_spawn");
91         return NULL;
92     }
93     posix_spawn_file_actions_destroy(&actions);
94     
95     Player *player = malloc(sizeof(Player));
96     memset(player, 0, sizeof(Player));
97     
98     player->in = pin[1];
99     player->out = pout[0];
100     close(pin[0]);
101     close(pout[1]);
102     player->process = player_pid;
103     player->isactive = TRUE;
104     
105     if(win->player) {
106         PlayerDestroy(win->player);
107     }
108     win->player = player;
109     
110     // start thread for mplayer IO
111     pthread_t tid;
112     if(pthread_create(&tid, NULL, player_io_thread, player)) {
113         perror("pthread_create");
114     }
115     
116     return NULL;
117 }
118
119 void PlayerDestroy(Player *p) {
120     if(p->isactive) {
121         close(p->in);
122         close(p->out);
123         kill(p->process, SIGTERM);
124     }
125     free(p);
126 }
127
128 static void* player_io_thread(void *data) {
129     Player *player = data;
130     
131     return NULL;
132 }