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