1 /*****************************************************************
2 * gmerlin - a general purpose multimedia framework and applications
3 *
4 * Copyright (c) 2001 - 2011 Members of the Gmerlin project
5 * gmerlin-general@lists.sourceforge.net
6 * http://gmerlin.sourceforge.net
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * *****************************************************************/
21
22 #include <string.h>
23 #include <pthread.h>
24 #include <signal.h>
25
26
27 #include <config.h>
28 #include <gmerlin/plugin.h>
29 #include <gmerlin/utils.h>
30 #include <gmerlin/log.h>
31 #include <gmerlin/subprocess.h>
32 #include "cdrdao_common.h"
33
34 #define LOG_DOMAIN "cdrdao"
35
36 struct bg_cdrdao_s
37 {
38 int run;
39 char * device;
40 char * driver;
41 int eject;
42 int simulate;
43 int speed;
44 int nopause;
45 bg_e_pp_callbacks_t * callbacks;
46 pthread_mutex_t stop_mutex;
47 int do_stop;
48 };
49
bg_cdrdao_create()50 bg_cdrdao_t * bg_cdrdao_create()
51 {
52 bg_cdrdao_t * ret;
53 ret = calloc(1, sizeof(*ret));
54 pthread_mutex_init(&ret->stop_mutex, NULL);
55 return ret;
56 }
57
bg_cdrdao_destroy(bg_cdrdao_t * cdrdao)58 void bg_cdrdao_destroy(bg_cdrdao_t * cdrdao)
59 {
60 if(cdrdao->device)
61 free(cdrdao->device);
62 free(cdrdao);
63 }
64
bg_cdrdao_set_parameter(void * data,const char * name,const bg_parameter_value_t * val)65 void bg_cdrdao_set_parameter(void * data, const char * name,
66 const bg_parameter_value_t * val)
67 {
68 bg_cdrdao_t * c;
69 if(!name)
70 return;
71 c = data;
72 if(!strcmp(name, "cdrdao_run"))
73 c->run = val->val_i;
74 else if(!strcmp(name, "cdrdao_device"))
75 c->device = bg_strdup(c->device, val->val_str);
76 else if(!strcmp(name, "cdrdao_driver"))
77 c->driver = bg_strdup(c->driver, val->val_str);
78 else if(!strcmp(name, "cdrdao_eject"))
79 c->eject = val->val_i;
80 else if(!strcmp(name, "cdrdao_simulate"))
81 c->simulate = val->val_i;
82 else if(!strcmp(name, "cdrdao_speed"))
83 c->speed = val->val_i;
84 else if(!strcmp(name, "cdrdao_nopause"))
85 c->nopause = val->val_i;
86 }
87
check_stop(bg_cdrdao_t * c)88 static int check_stop(bg_cdrdao_t * c)
89 {
90 int ret;
91 pthread_mutex_lock(&c->stop_mutex);
92 ret = c->do_stop;
93 c->do_stop = 0;
94 pthread_mutex_unlock(&c->stop_mutex);
95 return ret;
96 }
97
bg_cdrdao_run(bg_cdrdao_t * c,const char * toc_file)98 int bg_cdrdao_run(bg_cdrdao_t * c, const char * toc_file)
99 {
100 bg_subprocess_t * cdrdao;
101 char * str;
102 char * commandline = NULL;
103
104 char * line = NULL;
105 int line_alloc = 0;
106
107 int mb_written, mb_total;
108
109 if(!c->run)
110 {
111 bg_log(BG_LOG_INFO, LOG_DOMAIN, "Not running cdrdao (disabled by user)");
112 return 0;
113 }
114 if(!bg_search_file_exec("cdrdao", &commandline))
115 {
116 bg_log(BG_LOG_ERROR, LOG_DOMAIN, "cdrdao executable not found");
117 return 0;
118 }
119 commandline = bg_strcat(commandline, " write");
120
121 /* Device */
122 if(c->device)
123 {
124 str = bg_sprintf(" --device %s", c->device);
125 commandline = bg_strcat(commandline, str);
126 free(str);
127 }
128 /* Driver */
129 if(c->driver)
130 {
131 str = bg_sprintf(" --driver %s", c->driver);
132 commandline = bg_strcat(commandline, str);
133 free(str);
134 }
135 /* Eject */
136 if(c->eject)
137 commandline = bg_strcat(commandline, " --eject");
138 /* Skip pause */
139 if(c->nopause)
140 commandline = bg_strcat(commandline, " -n");
141
142 /* Simulate */
143 if(c->simulate)
144 commandline = bg_strcat(commandline, " --simulate");
145
146 /* Speed */
147 if(c->speed > 0)
148 {
149 str = bg_sprintf(" --speed %d", c->speed);
150 commandline = bg_strcat(commandline, str);
151 free(str);
152 }
153
154 /* TOC-File and stderr redirection */
155 str = bg_sprintf(" \"%s\"", toc_file);
156 commandline = bg_strcat(commandline, str);
157 free(str);
158
159 if(check_stop(c))
160 {
161 free(commandline);
162 return 0;
163 }
164
165 /* Launching command (cdrdao sends everything to stderr) */
166 cdrdao = bg_subprocess_create(commandline, 0, 0, 1);
167 free(commandline);
168 /* Read lines */
169
170 while(bg_subprocess_read_line(cdrdao->stderr_fd, &line, &line_alloc, -1))
171 {
172 if(check_stop(c))
173 {
174 bg_subprocess_kill(cdrdao, SIGQUIT);
175 bg_subprocess_close(cdrdao);
176 return 0;
177 }
178
179 if(!strncmp(line, "ERROR", 5))
180 {
181 bg_log(BG_LOG_ERROR, LOG_DOMAIN, "%s", line);
182 // break;
183 }
184 else if(!strncmp(line, "WARNING", 7))
185 {
186 bg_log(BG_LOG_WARNING, LOG_DOMAIN, "%s", line);
187 // break;
188 }
189 else if(!strncmp(line, "Writing", 7))
190 {
191 if(c->callbacks && c->callbacks->action_callback)
192 c->callbacks->action_callback(c->callbacks->data,
193 line);
194 bg_log(BG_LOG_INFO, LOG_DOMAIN, "%s", line);
195
196 if(c->callbacks && c->callbacks->progress_callback)
197 {
198 if(!strncmp(line, "Writing track 01", 16) ||
199 strncmp(line, "Writing track", 13))
200 c->callbacks->progress_callback(c->callbacks->data, 0.0);
201 }
202 }
203 else if(sscanf(line, "Wrote %d of %d", &mb_written, &mb_total) == 2)
204 {
205 if(c->callbacks && c->callbacks->progress_callback)
206 c->callbacks->progress_callback(c->callbacks->data,
207 (float)mb_written/(float)mb_total);
208 else
209 bg_log(BG_LOG_INFO, LOG_DOMAIN, "%s", line);
210 }
211 else
212 bg_log(BG_LOG_INFO, LOG_DOMAIN, "%s", line);
213 }
214 bg_subprocess_close(cdrdao);
215
216 if(c->simulate)
217 return 0;
218 else
219 return 1;
220 }
221
bg_cdrdao_set_callbacks(bg_cdrdao_t * c,bg_e_pp_callbacks_t * callbacks)222 void bg_cdrdao_set_callbacks(bg_cdrdao_t * c, bg_e_pp_callbacks_t * callbacks)
223 {
224 c->callbacks = callbacks;
225 }
226
bg_cdrdao_stop(bg_cdrdao_t * c)227 void bg_cdrdao_stop(bg_cdrdao_t * c)
228 {
229 pthread_mutex_lock(&c->stop_mutex);
230 c->do_stop = 1;
231 pthread_mutex_unlock(&c->stop_mutex);
232
233 }
234