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 <signal.h>
23 
24 #include <config.h>
25 #include <gmerlin/recorder.h>
26 #include <gmerlin/pluginregistry.h>
27 #include <gavl/gavl.h>
28 #include <gmerlin/utils.h>
29 #include <gmerlin/cmdline.h>
30 #include <gmerlin/log.h>
31 #include <gmerlin/translation.h>
32 
33 static bg_recorder_t * recorder;
34 
35 static bg_cfg_section_t * audio_section;
36 static bg_cfg_section_t * video_section;
37 static bg_cfg_section_t * metadata_section;
38 static bg_cfg_section_t * encoder_section;
39 static bg_cfg_section_t * af_section;
40 static bg_cfg_section_t * vf_section;
41 static bg_cfg_section_t * vm_section;
42 static bg_cfg_section_t * output_section;
43 
44 const bg_parameter_info_t * audio_parameters;
45 const bg_parameter_info_t * video_parameters;
46 const bg_parameter_info_t * af_parameters;
47 const bg_parameter_info_t * vf_parameters;
48 const bg_parameter_info_t * vm_parameters;
49 const bg_parameter_info_t * output_parameters;
50 
51 const bg_parameter_info_t * metadata_parameters;
52 const bg_parameter_info_t * encoder_parameters;
53 
54 
55 static bg_plugin_registry_t * plugin_reg;
56 static bg_cfg_registry_t * cfg_reg;
57 
58 static int do_record = 0;
59 
60 static int do_syslog = 0;
61 
62 #define DELAY_TIME 50
63 #define PING_INTERVAL 20
64 
65 int got_sigint = 0;
66 
sigint_handler(int sig)67 static void sigint_handler(int sig)
68   {
69   fprintf(stderr, "\nCTRL+C caught\n");
70   got_sigint = 1;
71   }
72 
set_sigint_handler()73 static void set_sigint_handler()
74   {
75   struct sigaction sa;
76   sa.sa_flags = 0;
77   sigemptyset(&sa.sa_mask);
78   sa.sa_handler = sigint_handler;
79   if (sigaction(SIGINT, &sa, NULL) == -1)
80     {
81     fprintf(stderr, "sigaction failed\n");
82     }
83   }
84 
opt_aud(void * data,int * argc,char *** _argv,int arg)85 static void opt_aud(void * data, int * argc, char *** _argv, int arg)
86   {
87   if(arg >= *argc)
88     {
89     fprintf(stderr, "Option -aud requires an argument\n");
90     exit(-1);
91     }
92   if(!bg_cmdline_apply_options(audio_section,
93                                bg_recorder_set_audio_parameter,
94                                recorder,
95                                audio_parameters,
96                                (*_argv)[arg]))
97     exit(-1);
98   bg_cmdline_remove_arg(argc, _argv, arg);
99   }
100 
opt_af(void * data,int * argc,char *** _argv,int arg)101 static void opt_af(void * data, int * argc, char *** _argv, int arg)
102   {
103   if(arg >= *argc)
104     {
105     fprintf(stderr, "Option -af requires an argument\n");
106     exit(-1);
107     }
108   if(!bg_cmdline_apply_options(audio_section,
109                                bg_recorder_set_audio_filter_parameter,
110                                recorder,
111                                af_parameters,
112                                (*_argv)[arg]))
113     exit(-1);
114   bg_cmdline_remove_arg(argc, _argv, arg);
115   }
116 
opt_vid(void * data,int * argc,char *** _argv,int arg)117 static void opt_vid(void * data, int * argc, char *** _argv, int arg)
118   {
119   if(arg >= *argc)
120     {
121     fprintf(stderr, "Option -vid requires an argument\n");
122     exit(-1);
123     }
124   if(!bg_cmdline_apply_options(video_section,
125                                bg_recorder_set_video_parameter,
126                                recorder,
127                                video_parameters,
128                                (*_argv)[arg]))
129     exit(-1);
130   bg_cmdline_remove_arg(argc, _argv, arg);
131   }
132 
opt_vf(void * data,int * argc,char *** _argv,int arg)133 static void opt_vf(void * data, int * argc, char *** _argv, int arg)
134   {
135   if(arg >= *argc)
136     {
137     fprintf(stderr, "Option -vf requires an argument\n");
138     exit(-1);
139     }
140   if(!bg_cmdline_apply_options(video_section,
141                                bg_recorder_set_video_filter_parameter,
142                                recorder,
143                                vf_parameters,
144                                (*_argv)[arg]))
145     exit(-1);
146   bg_cmdline_remove_arg(argc, _argv, arg);
147   }
148 
opt_vm(void * data,int * argc,char *** _argv,int arg)149 static void opt_vm(void * data, int * argc, char *** _argv, int arg)
150   {
151   if(arg >= *argc)
152     {
153     fprintf(stderr, "Option -vm requires an argument\n");
154     exit(-1);
155     }
156   if(!bg_cmdline_apply_options(video_section,
157                                bg_recorder_set_video_monitor_parameter,
158                                recorder,
159                                vm_parameters,
160                                (*_argv)[arg]))
161     exit(-1);
162   bg_cmdline_remove_arg(argc, _argv, arg);
163   }
164 
opt_m(void * data,int * argc,char *** _argv,int arg)165 static void opt_m(void * data, int * argc, char *** _argv, int arg)
166   {
167   if(arg >= *argc)
168     {
169     fprintf(stderr, "Option -m requires an argument\n");
170     exit(-1);
171     }
172   if(!bg_cmdline_apply_options(metadata_section,
173                                bg_recorder_set_metadata_parameter,
174                                recorder,
175                                metadata_parameters,
176                                (*_argv)[arg]))
177     exit(-1);
178   bg_cmdline_remove_arg(argc, _argv, arg);
179   }
180 
opt_r(void * data,int * argc,char *** _argv,int arg)181 static void opt_r(void * data, int * argc, char *** _argv, int arg)
182   {
183   do_record = 1;
184   }
185 
opt_enc(void * data,int * argc,char *** _argv,int arg)186 static void opt_enc(void * data, int * argc, char *** _argv, int arg)
187   {
188   if(arg >= *argc)
189     {
190     fprintf(stderr, "Option -enc requires an argument\n");
191     exit(-1);
192     }
193   if(!bg_cmdline_apply_options(encoder_section,
194                                /* bg_recorder_set_metadata_parameter */ NULL,
195                                /* recorder */ NULL,
196                                encoder_parameters,
197                                (*_argv)[arg]))
198     exit(-1);
199   bg_cmdline_remove_arg(argc, _argv, arg);
200   }
201 
opt_o(void * data,int * argc,char *** _argv,int arg)202 static void opt_o(void * data, int * argc, char *** _argv, int arg)
203   {
204   if(arg >= *argc)
205     {
206     fprintf(stderr, "Option -o requires an argument\n");
207     exit(-1);
208     }
209   if(!bg_cmdline_apply_options(encoder_section,
210                                bg_recorder_set_output_parameter,
211                                recorder,
212                                output_parameters,
213                                (*_argv)[arg]))
214     exit(-1);
215   bg_cmdline_remove_arg(argc, _argv, arg);
216   }
217 
opt_syslog(void * data,int * argc,char *** _argv,int arg)218 static void opt_syslog(void * data, int * argc, char *** _argv, int arg)
219   {
220   if(arg >= *argc)
221     {
222     fprintf(stderr, "Option -syslog requires an argument\n");
223     exit(-1);
224     }
225   bg_log_syslog_init((*_argv)[arg]);
226   do_syslog = 1;
227   bg_cmdline_remove_arg(argc, _argv, arg);
228   }
229 
230 static bg_cmdline_arg_t global_options[] =
231   {
232     {
233       .arg =         "-aud",
234       .help_arg =    "<audio_options>",
235       .help_string = "Set audio recording options",
236       .callback =    opt_aud,
237     },
238     {
239       .arg =         "-vid",
240       .help_arg =    "<video_options>",
241       .help_string = "Set video recording options",
242       .callback =    opt_vid,
243     },
244     {
245       .arg =         "-af",
246       .help_arg =    "<audio filter options>",
247       .help_string = "Set audio filter options",
248       .callback =    opt_af,
249     },
250     {
251       .arg =         "-vf",
252       .help_arg =    "<video filter options>",
253       .help_string = "Set video filter options",
254       .callback =    opt_vf,
255     },
256     {
257       .arg =         "-vm",
258       .help_arg =    "<video monitor options>",
259       .help_string = "Set video monitor options",
260       .callback =    opt_vm,
261     },
262     {
263       .arg =         "-m",
264       .help_arg =    "<metadata_options>",
265       .help_string = "Set metadata options",
266       .callback =    opt_m,
267     },
268     {
269       .arg =         "-enc",
270       .help_arg =    "<encoding_options>",
271       .help_string = "Set encoding options",
272       .callback =    opt_enc,
273 
274     },
275     {
276       .arg =         "-o",
277       .help_arg =    "<output_options>",
278       .help_string = "Set output options",
279       .callback =    opt_o,
280 
281     },
282     {
283       .arg =         "-r",
284       .help_string = "Record to file",
285       .callback =    opt_r,
286     },
287     {
288       .arg =         "-syslog",
289       .help_arg =    "<name>",
290       .help_string = "Set log messages to syslog",
291       .callback =    opt_syslog,
292     },
293     {
294       /* End */
295     }
296   };
297 
update_global_options()298 static void update_global_options()
299   {
300   global_options[0].parameters = audio_parameters;
301   global_options[1].parameters = video_parameters;
302   global_options[2].parameters = af_parameters;
303   global_options[3].parameters = vf_parameters;
304   global_options[4].parameters = vm_parameters;
305   global_options[5].parameters = metadata_parameters;
306   global_options[6].parameters = encoder_parameters;
307   global_options[7].parameters = output_parameters;
308   }
309 
310 const bg_cmdline_app_data_t app_data =
311   {
312     .package =  PACKAGE,
313     .version =  VERSION,
314     .name =     "gmerlin-record",
315     .synopsis = TRS("[options]\n"),
316     .help_before = TRS("Commandline recorder\n"),
317     .args = (bg_cmdline_arg_array_t[]) { { TRS("Options"), global_options },
318                                        {  } },
319     .files = (bg_cmdline_ext_doc_t[])
320     { { "~/.gmerlin/plugins.xml",
321         TRS("Cache of the plugin registry (shared by all applicatons)") },
322       { "~/.gmerlin/generic/config.xml",
323         TRS("Default plugin parameters are read from there. Use gmerlin_plugincfg to change them.") },
324       { /* End */ }
325     },
326 
327   };
328 
329 
330 
main(int argc,char ** argv)331 int main(int argc, char ** argv)
332   {
333   bg_cfg_section_t * cfg_section;
334   char * tmp_path;
335   int timeout_counter = 0;
336 
337   gavl_time_t delay_time = DELAY_TIME * 1000;
338 
339   set_sigint_handler();
340 
341   /* We must initialize the random number generator if we want the
342      Vorbis encoder to work */
343   srand(time(NULL));
344 
345   /* Create plugin regsitry */
346   cfg_reg = bg_cfg_registry_create();
347   tmp_path =  bg_search_file_read("generic", "config.xml");
348   bg_cfg_registry_load(cfg_reg, tmp_path);
349   if(tmp_path)
350     free(tmp_path);
351 
352   cfg_section = bg_cfg_registry_find_section(cfg_reg, "plugins");
353   plugin_reg = bg_plugin_registry_create(cfg_section);
354 
355   recorder = bg_recorder_create(plugin_reg);
356 
357   /* Create config sections */
358 
359   audio_parameters = bg_recorder_get_audio_parameters(recorder);
360   audio_section =
361     bg_cfg_section_create_from_parameters("audio", audio_parameters);
362 
363   video_parameters = bg_recorder_get_video_parameters(recorder);
364   video_section =
365     bg_cfg_section_create_from_parameters("video", video_parameters);
366 
367   af_parameters = bg_recorder_get_audio_filter_parameters(recorder);
368   af_section =
369     bg_cfg_section_create_from_parameters("audio_filters", af_parameters);
370 
371   vf_parameters = bg_recorder_get_video_filter_parameters(recorder);
372   vf_section =
373     bg_cfg_section_create_from_parameters("video_filters", vf_parameters);
374 
375   vm_parameters = bg_recorder_get_video_monitor_parameters(recorder);
376   vm_section =
377     bg_cfg_section_create_from_parameters("video_monitor", vm_parameters);
378 
379   metadata_parameters = bg_recorder_get_metadata_parameters(recorder);
380   metadata_section =
381     bg_cfg_section_create_from_parameters("metadata", metadata_parameters);
382 
383   encoder_parameters = bg_recorder_get_encoder_parameters(recorder);
384 
385   encoder_section =
386     bg_cfg_section_create_from_parameters("encoder", encoder_parameters);
387 
388   output_parameters = bg_recorder_get_output_parameters(recorder);
389   output_section =
390     bg_cfg_section_create_from_parameters("output", output_parameters);
391 
392   update_global_options();
393 
394   /* Apply default options */
395 
396   bg_cfg_section_apply(audio_section, audio_parameters,
397                        bg_recorder_set_audio_parameter, recorder);
398   bg_cfg_section_apply(video_section, video_parameters,
399                        bg_recorder_set_video_parameter, recorder);
400   bg_cfg_section_apply(af_section, af_parameters,
401                        bg_recorder_set_audio_filter_parameter, recorder);
402   bg_cfg_section_apply(vf_section, vf_parameters,
403                        bg_recorder_set_video_filter_parameter, recorder);
404   bg_cfg_section_apply(vm_section, vm_parameters,
405                        bg_recorder_set_video_monitor_parameter, recorder);
406   bg_cfg_section_apply(metadata_section, metadata_parameters,
407                        bg_recorder_set_metadata_parameter, recorder);
408   bg_cfg_section_apply(output_section, output_parameters,
409                        bg_recorder_set_output_parameter, recorder);
410 
411   /* Get commandline options */
412   bg_cmdline_init(&app_data);
413   bg_cmdline_parse(global_options, &argc, &argv, NULL);
414 
415   /* Set encoding options */
416   bg_recorder_set_encoder_section(recorder, encoder_section);
417 
418   bg_recorder_record(recorder, do_record);
419   bg_recorder_run(recorder);
420 
421   while(1)
422     {
423     if(!timeout_counter)
424       {
425       if(!bg_recorder_ping(recorder))
426         break;
427       }
428 
429     if(got_sigint)
430       break;
431 
432     timeout_counter++;
433     if(timeout_counter >= PING_INTERVAL)
434       timeout_counter = 0;
435 
436     if(do_syslog)
437       bg_log_syslog_flush();
438 
439     gavl_time_delay(&delay_time);
440     }
441 
442   bg_recorder_destroy(recorder);
443   return 0;
444   }
445