1 /*
2  *  Digital Video Recorder
3  *  Copyright (C) 2008 Andreas Öman
4  *  Copyright (C) 2014,2015 Jaroslav Kysela
5  *
6  *  This program is free software: you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation, either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <stdarg.h>
21 #include <pthread.h>
22 #include <assert.h>
23 #include <string.h>
24 #include <ctype.h>
25 #include <sys/stat.h>
26 #include <libgen.h> /* basename */
27 
28 #include "htsstr.h"
29 
30 #include "tvheadend.h"
31 #include "streaming.h"
32 #include "tcp.h"
33 #include "dvr.h"
34 #include "spawn.h"
35 #include "service.h"
36 #include "htsp_server.h"
37 #include "atomic.h"
38 #include "intlconv.h"
39 #include "notify.h"
40 
41 #include "muxer.h"
42 
43 /**
44  *
45  */
46 static void *dvr_thread(void *aux);
47 static void dvr_thread_epilog(dvr_entry_t *de, const char *dvr_postproc);
48 
49 
50 static const int prio2weight[6] = {
51   [DVR_PRIO_IMPORTANT]   = 500,
52   [DVR_PRIO_HIGH]        = 400,
53   [DVR_PRIO_NORMAL]      = 300,
54   [DVR_PRIO_LOW]         = 200,
55   [DVR_PRIO_UNIMPORTANT] = 100,
56   [DVR_PRIO_NOTSET]      = 300, /* as DVR_PRIO_NORMAL */
57 };
58 
59 /**
60  *
61  */
62 int
dvr_rec_subscribe(dvr_entry_t * de)63 dvr_rec_subscribe(dvr_entry_t *de)
64 {
65   char buf[100];
66   int weight;
67   profile_t *pro;
68   profile_chain_t *prch = NULL;
69   struct sockaddr_storage sa;
70   access_t *aa = NULL;
71   uint32_t rec_count, net_count;
72   int ret = 0, c1, c2;
73   struct stat st;
74 
75   assert(de->de_s == NULL);
76   assert(de->de_chain == NULL);
77 
78   if(de->de_pri >= 0 && de->de_pri < ARRAY_SIZE(prio2weight))
79     weight = prio2weight[de->de_pri];
80   else
81     weight = 300;
82 
83   snprintf(buf, sizeof(buf), "DVR: %s", lang_str_get(de->de_title, NULL));
84 
85   if (de->de_owner && de->de_owner[0] != '\0') {
86     aa = access_get_by_username(de->de_owner);
87   } else if (de->de_creator && de->de_creator[0] != '\0' &&
88            tcp_get_ip_from_str(de->de_creator, &sa) != NULL) {
89     aa = access_get_by_addr(&sa);
90   } else {
91     tvherror(LS_DVR, "unable to find access (owner '%s', creator '%s')",
92              de->de_owner, de->de_creator);
93     ret = -EPERM;
94     goto _return;
95   }
96 
97   if (aa->aa_conn_limit || aa->aa_conn_limit_dvr) {
98     rec_count = dvr_usage_count(aa);
99     net_count = aa->aa_conn_limit ? tcp_connection_count(aa) : 0;
100     /* the rule is: allow if one condition is OK */
101     c1 = aa->aa_conn_limit ? rec_count + net_count >= aa->aa_conn_limit : -1;
102     c2 = aa->aa_conn_limit_dvr ? rec_count >= aa->aa_conn_limit_dvr : -1;
103     if (c1 && c2) {
104       tvherror(LS_DVR, "multiple connections are not allowed for user '%s' from '%s' "
105                       "(limit %u, dvr limit %u, active DVR %u, streaming %u)",
106                aa->aa_username ?: "", aa->aa_representative ?: "",
107                aa->aa_conn_limit, aa->aa_conn_limit_dvr, rec_count, net_count);
108       ret = -EOVERFLOW;
109       goto _return;
110     }
111   }
112 
113   if(stat(de->de_config->dvr_storage, &st) || !S_ISDIR(st.st_mode)) {
114     tvherror(LS_DVR, "the directory '%s' is not accessible", de->de_config->dvr_storage);
115     ret = -EIO;
116     goto _return;
117   }
118 
119   pro = de->de_config->dvr_profile;
120   prch = malloc(sizeof(*prch));
121   profile_chain_init(prch, pro, de->de_channel, 1);
122   if (profile_chain_open(prch, &de->de_config->dvr_muxcnf, 0, 0)) {
123     profile_chain_close(prch);
124     tvherror(LS_DVR, "unable to create new channel streaming chain '%s' for '%s', using default",
125              profile_get_name(pro), channel_get_name(de->de_channel));
126     pro = profile_find_by_name(NULL, NULL);
127     profile_chain_init(prch, pro, de->de_channel, 1);
128     if (profile_chain_open(prch, &de->de_config->dvr_muxcnf, 0, 0)) {
129       tvherror(LS_DVR, "unable to create channel streaming default chain '%s' for '%s'",
130                profile_get_name(pro), channel_get_name(de->de_channel));
131       profile_chain_close(prch);
132       ret = -EINVAL;
133       goto _return;
134     }
135   }
136 
137   de->de_s = subscription_create_from_channel(prch, NULL, weight,
138 					      buf, prch->prch_flags,
139 					      NULL, NULL, NULL, NULL);
140   if (de->de_s == NULL) {
141     tvherror(LS_DVR, "unable to create new channel subcription for '%s' profile '%s'",
142              channel_get_name(de->de_channel), profile_get_name(pro));
143     ret = -EINVAL;
144     goto _return;
145   }
146 
147   de->de_chain = prch;
148 
149   atomic_set(&de->de_thread_shutdown, 0);
150   tvhthread_create(&de->de_thread, NULL, dvr_thread, de, "dvr");
151 
152   if (de->de_config->dvr_preproc)
153     dvr_spawn_cmd(de, de->de_config->dvr_preproc, NULL, 1);
154   access_destroy(aa);
155   return ret;
156 
157 _return:
158   profile_chain_close(prch);
159   free(prch);
160   access_destroy(aa);
161   return ret;
162 }
163 
164 /**
165  *
166  */
167 void
dvr_rec_unsubscribe(dvr_entry_t * de)168 dvr_rec_unsubscribe(dvr_entry_t *de)
169 {
170   profile_chain_t *prch = de->de_chain;
171   char *postproc = NULL;
172 
173   assert(de->de_s != NULL);
174   assert(prch != NULL);
175 
176   de->de_in_unsubscribe = 1;
177 
178   streaming_target_deliver(prch->prch_st, streaming_msg_create(SMT_EXIT));
179 
180   atomic_add(&de->de_thread_shutdown, 1);
181 
182   pthread_join(de->de_thread, (void **)&postproc);
183 
184   if (prch->prch_muxer)
185     dvr_thread_epilog(de, postproc);
186 
187   free(postproc);
188 
189   subscription_unsubscribe(de->de_s, UNSUBSCRIBE_FINAL);
190   de->de_s = NULL;
191 
192   de->de_chain = NULL;
193   profile_chain_close(prch);
194   free(prch);
195 
196   dvr_vfs_refresh_entry(de);
197 
198   de->de_in_unsubscribe = 0;
199 }
200 
201 /**
202  *
203  */
204 void
dvr_rec_migrate(dvr_entry_t * de_old,dvr_entry_t * de_new)205 dvr_rec_migrate(dvr_entry_t *de_old, dvr_entry_t *de_new)
206 {
207   lock_assert(&global_lock);
208 
209   de_new->de_s = de_old->de_s;
210   de_new->de_chain = de_old->de_chain;
211   de_new->de_thread = de_old->de_thread;
212   de_old->de_s = NULL;
213   de_old->de_chain = NULL;
214   de_old->de_thread = 0;
215 }
216 
217 /**
218  * Replace various chars with a dash
219  * - dosubs specifies if user demanded substitutions are performed
220  */
221 static char *
cleanup_filename(dvr_config_t * cfg,char * s,int dosubs)222 cleanup_filename(dvr_config_t *cfg, char *s, int dosubs)
223 {
224   int len = strlen(s);
225   char *s1, *p;
226 
227   s1 = intlconv_utf8safestr(cfg->dvr_charset_id, s, (len * 2) + 1);
228   if (s1 == NULL) {
229     tvherror(LS_DVR, "Unsupported charset %s using ASCII", cfg->dvr_charset);
230     s1 = intlconv_utf8safestr(intlconv_charset_id("ASCII", 1, 1),
231                              s, len * 2);
232     if (s1 == NULL)
233       return NULL;
234   }
235 
236   /* Do not create hidden files */
237   if (s1[0] == '.')
238     s1[0] = '_';
239   if (s1[0] == '\\' && s1[1] == '.')
240     s1[1] = '_';
241 
242   for (s = s1 ; *s; s++) {
243 
244     if (*s == '\\') {
245       s++;
246       if (*s == '\0')
247         break;
248     }
249 
250     if (*s == '/')
251       *s = '-';
252 
253     else if (cfg->dvr_whitespace_in_title &&
254              (*s == ' ' || *s == '\t') &&
255              dosubs)
256       *s = '-';
257 
258     else if (cfg->dvr_clean_title &&
259              ((*s < 32) || (*s > 122) ||
260              (strchr("/:\\<>|*?\"", *s) != NULL)) &&
261              dosubs)
262       *s = '_';
263 
264     else if (cfg->dvr_windows_compatible_filenames &&
265              (strchr("/:\\<>|*?\"", *s) != NULL) &&
266              dosubs)
267       *s = '_';
268   }
269 
270   if (cfg->dvr_windows_compatible_filenames) {
271     /* trim trailing spaces and dots */
272     for (s = p = s1; *s; s++) {
273       if (*s == '\\')
274         s++;
275       if (*s != ' ' && *s != '.')
276         p = s + 1;
277     }
278     *p = '\0';
279   }
280 
281   return s1;
282 }
283 
284 /**
285  *
286  */
287 static char *
dvr_clean_directory_separator(char * s,char * tmp,size_t tmplen)288 dvr_clean_directory_separator(char *s, char *tmp, size_t tmplen)
289 {
290   char *p, *end;
291 
292   if (s != tmp) {
293     end = tmp + tmplen - 1;
294     /* replace directory separator */
295     for (p = tmp; *s && p != end; s++, p++)
296       if (*s == '/')
297         *p = '-';
298       else if (*s == '"')
299         *p = '\'';
300       else
301         *p = *s;
302     *p = '\0';
303     return tmp;
304   } else  {
305     for (; *s; s++)
306       if (*s == '/')
307         *s = '-';
308       else if (*s == '"')
309         *s = '\'';
310     return tmp;
311   }
312 }
313 
314 static const char *
dvr_do_prefix(const char * id,const char * fmt,const char * s,char * tmp,size_t tmplen)315 dvr_do_prefix(const char *id, const char *fmt, const char *s, char *tmp, size_t tmplen)
316 {
317   if (id[0] == '?') {
318     id++;
319     if (fmt && *fmt >= '0' && *fmt <= '9') {
320       long l = strtol(fmt, NULL, 10);
321       if (l && tmplen > l)
322         tmplen = l;
323     }
324   }
325   if (s == NULL) {
326     tmp[0] = '\0';
327   } else if (s[0] && !isalpha(id[0])) {
328     snprintf(tmp, tmplen, "%c%s", id[0], s);
329   } else {
330     strlcpy(tmp, s, tmplen);
331   }
332   return dvr_clean_directory_separator(tmp, tmp, tmplen);
333 }
334 
335 
336 static const char *
dvr_sub_title(const char * id,const char * fmt,const void * aux,char * tmp,size_t tmplen)337 dvr_sub_title(const char *id, const char *fmt, const void *aux, char *tmp, size_t tmplen)
338 {
339   return dvr_do_prefix(id, fmt, lang_str_get(((dvr_entry_t *)aux)->de_title, NULL), tmp, tmplen);
340 }
341 
342 static const char *
dvr_sub_subtitle(const char * id,const char * fmt,const void * aux,char * tmp,size_t tmplen)343 dvr_sub_subtitle(const char *id, const char *fmt, const void *aux, char *tmp, size_t tmplen)
344 {
345   return dvr_do_prefix(id, fmt, lang_str_get(((dvr_entry_t *)aux)->de_subtitle, NULL), tmp, tmplen);
346 }
347 
348 static const char *
dvr_sub_description(const char * id,const char * fmt,const void * aux,char * tmp,size_t tmplen)349 dvr_sub_description(const char *id, const char *fmt, const void *aux, char *tmp, size_t tmplen)
350 {
351   return dvr_do_prefix(id, fmt, lang_str_get(((dvr_entry_t *)aux)->de_desc, NULL), tmp, tmplen);
352 }
353 
354 static const char *
dvr_sub_episode(const char * id,const char * fmt,const void * aux,char * tmp,size_t tmplen)355 dvr_sub_episode(const char *id, const char *fmt, const void *aux, char *tmp, size_t tmplen)
356 {
357   const dvr_entry_t *de = aux;
358   char buf[64];
359 
360   if (de->de_bcast == NULL || de->de_bcast->episode == NULL)
361     return "";
362   epg_episode_number_format(de->de_bcast->episode,
363                             buf, sizeof(buf),
364                             NULL, "S%02d", NULL, "E%02d", NULL);
365   return dvr_do_prefix(id, fmt, buf, tmp, tmplen);
366 }
367 
368 static const char *
dvr_sub_channel(const char * id,const char * fmt,const void * aux,char * tmp,size_t tmplen)369 dvr_sub_channel(const char *id, const char *fmt, const void *aux, char *tmp, size_t tmplen)
370 {
371   return dvr_do_prefix(id, fmt, DVR_CH_NAME((dvr_entry_t *)aux), tmp, tmplen);
372 }
373 
374 static const char *
dvr_sub_genre(const char * id,const char * fmt,const void * aux,char * tmp,size_t tmplen)375 dvr_sub_genre(const char *id, const char *fmt, const void *aux, char *tmp, size_t tmplen)
376 {
377   const dvr_entry_t *de = aux;
378   epg_genre_t *genre;
379   char buf[64];
380 
381   if (de->de_bcast == NULL || de->de_bcast->episode == NULL)
382     return "";
383   genre = LIST_FIRST(&de->de_bcast->episode->genre);
384   if (!genre || !genre->code)
385     return "";
386   epg_genre_get_str(genre, 0, 1, buf, sizeof(buf), "en");
387   return dvr_do_prefix(id, fmt, buf, tmp, tmplen);
388 }
389 
390 static const char *
dvr_sub_owner(const char * id,const char * fmt,const void * aux,char * tmp,size_t tmplen)391 dvr_sub_owner(const char *id, const char *fmt, const void *aux, char *tmp, size_t tmplen)
392 {
393   return dvr_do_prefix(id, fmt, ((dvr_entry_t *)aux)->de_owner, tmp, tmplen);
394 }
395 
396 static const char *
dvr_sub_creator(const char * id,const char * fmt,const void * aux,char * tmp,size_t tmplen)397 dvr_sub_creator(const char *id, const char *fmt, const void *aux, char *tmp, size_t tmplen)
398 {
399   return dvr_do_prefix(id, fmt, ((dvr_entry_t *)aux)->de_creator, tmp, tmplen);
400 }
401 
402 static const char *
dvr_sub_last_error(const char * id,const char * fmt,const void * aux,char * tmp,size_t tmplen)403 dvr_sub_last_error(const char *id, const char *fmt, const void *aux, char *tmp, size_t tmplen)
404 {
405   return dvr_do_prefix(id, fmt, streaming_code2txt(((dvr_entry_t *)aux)->de_last_error), tmp, tmplen);
406 }
407 
408 static const char *
dvr_sub_start(const char * id,const char * fmt,const void * aux,char * tmp,size_t tmplen)409 dvr_sub_start(const char *id, const char *fmt, const void *aux, char *tmp, size_t tmplen)
410 {
411   char buf[16];
412   snprintf(buf, sizeof(buf), "%"PRItime_t, (time_t)dvr_entry_get_start_time((dvr_entry_t *)aux, 0));
413   return dvr_do_prefix(id, fmt, buf, tmp, tmplen);
414 }
415 
416 static const char *
dvr_sub_errors(const char * id,const char * fmt,const void * aux,char * tmp,size_t tmplen)417 dvr_sub_errors(const char *id, const char *fmt, const void *aux, char *tmp, size_t tmplen)
418 {
419   char buf[16];
420   snprintf(buf, sizeof(buf), "%"PRIu32, (uint32_t)((dvr_entry_t *)aux)->de_errors);
421   return dvr_do_prefix(id, fmt, buf, tmp, tmplen);
422 }
423 
424 static const char *
dvr_sub_data_errors(const char * id,const char * fmt,const void * aux,char * tmp,size_t tmplen)425 dvr_sub_data_errors(const char *id, const char *fmt, const void *aux, char *tmp, size_t tmplen)
426 {
427   char buf[16];
428   snprintf(buf, sizeof(buf), "%"PRIu32, (uint32_t)((dvr_entry_t *)aux)->de_data_errors);
429   return dvr_do_prefix(id, fmt, buf, tmp, tmplen);
430 }
431 
432 static const char *
dvr_sub_stop(const char * id,const char * fmt,const void * aux,char * tmp,size_t tmplen)433 dvr_sub_stop(const char *id, const char *fmt, const void *aux, char *tmp, size_t tmplen)
434 {
435   char buf[16];
436   snprintf(buf, sizeof(buf), "%"PRItime_t, (time_t)dvr_entry_get_stop_time((dvr_entry_t *)aux));
437   return dvr_do_prefix(id, fmt, buf, tmp, tmplen);
438 }
439 
440 static const char *
dvr_sub_comment(const char * id,const char * fmt,const void * aux,char * tmp,size_t tmplen)441 dvr_sub_comment(const char *id, const char *fmt, const void *aux, char *tmp, size_t tmplen)
442 {
443   return dvr_do_prefix(id, fmt, ((dvr_entry_t *)aux)->de_comment, tmp, tmplen);
444 }
445 
446 static htsstr_substitute_t dvr_subs_entry[] = {
447   { .id = "?t",  .getval = dvr_sub_title },
448   { .id = "? t", .getval = dvr_sub_title },
449   { .id = "?-t", .getval = dvr_sub_title },
450   { .id = "?_t", .getval = dvr_sub_title },
451   { .id = "?.t", .getval = dvr_sub_title },
452   { .id = "?,t", .getval = dvr_sub_title },
453   { .id = "?;t", .getval = dvr_sub_title },
454   { .id = "?s",  .getval = dvr_sub_subtitle },
455   { .id = "? s", .getval = dvr_sub_subtitle },
456   { .id = "?-s", .getval = dvr_sub_subtitle },
457   { .id = "?_s", .getval = dvr_sub_subtitle },
458   { .id = "?.s", .getval = dvr_sub_subtitle },
459   { .id = "?,s", .getval = dvr_sub_subtitle },
460   { .id = "?;s", .getval = dvr_sub_subtitle },
461   { .id = "e",   .getval = dvr_sub_episode },
462   { .id = " e",  .getval = dvr_sub_episode },
463   { .id = "-e",  .getval = dvr_sub_episode },
464   { .id = "_e",  .getval = dvr_sub_episode },
465   { .id = ".e",  .getval = dvr_sub_episode },
466   { .id = ",e",  .getval = dvr_sub_episode },
467   { .id = ";e",  .getval = dvr_sub_episode },
468   { .id = "c",   .getval = dvr_sub_channel },
469   { .id = " c",  .getval = dvr_sub_channel },
470   { .id = "-c",  .getval = dvr_sub_channel },
471   { .id = "_c",  .getval = dvr_sub_channel },
472   { .id = ".c",  .getval = dvr_sub_channel },
473   { .id = ",c",  .getval = dvr_sub_channel },
474   { .id = ";c",  .getval = dvr_sub_channel },
475   { .id = "g",   .getval = dvr_sub_genre },
476   { .id = " g",  .getval = dvr_sub_genre },
477   { .id = "-g",  .getval = dvr_sub_genre },
478   { .id = "_g",  .getval = dvr_sub_genre },
479   { .id = ".g",  .getval = dvr_sub_genre },
480   { .id = ",g",  .getval = dvr_sub_genre },
481   { .id = ";g",  .getval = dvr_sub_genre },
482   { .id = NULL,  .getval = NULL }
483 };
484 
485 static const char *
dvr_sub_strftime(const char * id,const char * fmt,const void * aux,char * tmp,size_t tmplen)486 dvr_sub_strftime(const char *id, const char *fmt, const void *aux, char *tmp, size_t tmplen)
487 {
488   char fid[8], *p;
489   snprintf(fid, sizeof(fid), "%%%s", id);
490   strftime(tmp, tmplen, fid, (struct tm *)aux);
491   for (p = tmp; *p; p++)
492     if (*p == ':')
493       *p = '-';
494   return dvr_clean_directory_separator(tmp, tmp, tmplen);
495 }
496 
497 static htsstr_substitute_t dvr_subs_time[] = {
498   { .id = "a", .getval = dvr_sub_strftime }, /* The abbreviated name of the day of the week */
499   { .id = "A", .getval = dvr_sub_strftime }, /* The full name of the day of the week */
500   { .id = "b", .getval = dvr_sub_strftime }, /* The abbreviated month name */
501   { .id = "B", .getval = dvr_sub_strftime }, /* The full month name */
502   { .id = "c", .getval = dvr_sub_strftime }, /* The preferred date and time representation */
503   { .id = "C", .getval = dvr_sub_strftime }, /* The century number (year/100) as a 2-digit integer */
504   { .id = "d", .getval = dvr_sub_strftime }, /* The day of the month as a decimal number (range 01 to 31) */
505   { .id = "D", .getval = dvr_sub_strftime }, /* Equivalent to %m/%d/%y */
506   { .id = "e", .getval = dvr_sub_strftime }, /* The day of the month as a decimal number (range 01 to 31) */
507 
508   { .id = "Ec", .getval = dvr_sub_strftime }, /* alternatives */
509   { .id = "EC", .getval = dvr_sub_strftime },
510   { .id = "Ex", .getval = dvr_sub_strftime },
511   { .id = "EX", .getval = dvr_sub_strftime },
512   { .id = "Ey", .getval = dvr_sub_strftime },
513   { .id = "EY", .getval = dvr_sub_strftime },
514 
515   { .id = "F", .getval = dvr_sub_strftime }, /* Equivalent to %m/%d/%y */
516   { .id = "G", .getval = dvr_sub_strftime }, /* The ISO 8601 week-based year with century */
517   { .id = "g", .getval = dvr_sub_strftime }, /* Like %G, but without century */
518   { .id = "h", .getval = dvr_sub_strftime }, /* Equivalent to %b */
519   { .id = "H", .getval = dvr_sub_strftime }, /* The hour (range 00 to 23) */
520   { .id = "j", .getval = dvr_sub_strftime }, /* The day of the year (range 000 to 366) */
521   { .id = "k", .getval = dvr_sub_strftime }, /* The hour (range 0 to 23) - with space */
522   { .id = "l", .getval = dvr_sub_strftime }, /* The hour (range 1 to 12) - with space */
523   { .id = "m", .getval = dvr_sub_strftime }, /* The month (range 01 to 12) */
524   { .id = "M", .getval = dvr_sub_strftime }, /* The minute (range 00 to 59) */
525 
526   { .id = "Od", .getval = dvr_sub_strftime }, /* alternatives */
527   { .id = "Oe", .getval = dvr_sub_strftime },
528   { .id = "OH", .getval = dvr_sub_strftime },
529   { .id = "OI", .getval = dvr_sub_strftime },
530   { .id = "Om", .getval = dvr_sub_strftime },
531   { .id = "OM", .getval = dvr_sub_strftime },
532   { .id = "OS", .getval = dvr_sub_strftime },
533   { .id = "Ou", .getval = dvr_sub_strftime },
534   { .id = "OU", .getval = dvr_sub_strftime },
535   { .id = "OV", .getval = dvr_sub_strftime },
536   { .id = "Ow", .getval = dvr_sub_strftime },
537   { .id = "OW", .getval = dvr_sub_strftime },
538   { .id = "Oy", .getval = dvr_sub_strftime },
539 
540   { .id = "p", .getval = dvr_sub_strftime }, /* AM/PM */
541   { .id = "P", .getval = dvr_sub_strftime }, /* am/pm */
542   { .id = "r", .getval = dvr_sub_strftime }, /* a.m./p.m. */
543   { .id = "R", .getval = dvr_sub_strftime }, /* %H:%M */
544   { .id = "s", .getval = dvr_sub_strftime }, /* The number of seconds since the Epoch */
545   { .id = "S", .getval = dvr_sub_strftime }, /* The seconds (range 00 to 60) */
546   { .id = "T", .getval = dvr_sub_strftime }, /* %H:%M:%S */
547   { .id = "u", .getval = dvr_sub_strftime }, /* The day of the week as a decimal, range 1 to 7, Monday being 1 */
548   { .id = "U", .getval = dvr_sub_strftime }, /* The week number of the current year as a decimal number, range 00 to 53 (Sunday) */
549   { .id = "V", .getval = dvr_sub_strftime }, /* The  ISO 8601  week  number (range 01 to 53) */
550   { .id = "w", .getval = dvr_sub_strftime }, /* The day of the week as a decimal, range 0 to 6, Sunday being 0 */
551   { .id = "W", .getval = dvr_sub_strftime }, /* The week number of the current year as a decimal number, range 00 to 53 (Monday) */
552   { .id = "x", .getval = dvr_sub_strftime }, /* The preferred date representation */
553   { .id = "X", .getval = dvr_sub_strftime }, /* The preferred time representation */
554   { .id = "y", .getval = dvr_sub_strftime }, /* The year as a decimal number without a century (range 00 to 99) */
555   { .id = "Y", .getval = dvr_sub_strftime }, /* The year as a decimal number including the century */
556   { .id = "z", .getval = dvr_sub_strftime }, /* The +hhmm or -hhmm numeric timezone */
557   { .id = "Z", .getval = dvr_sub_strftime }, /* The timezone name or abbreviation */
558 
559   { .id = NULL, .getval = NULL }
560 };
561 
562 static const char *
dvr_sub_str(const char * id,const char * fmt,const void * aux,char * tmp,size_t tmplen)563 dvr_sub_str(const char *id, const char *fmt, const void *aux, char *tmp, size_t tmplen)
564 {
565   return (const char *)aux;
566 }
567 
568 static const char *
dvr_sub_str_separator(const char * id,const char * fmt,const void * aux,char * tmp,size_t tmplen)569 dvr_sub_str_separator(const char *id, const char *fmt, const void *aux, char *tmp, size_t tmplen)
570 {
571   strlcpy(tmp, (const char *)aux, tmplen);
572   return dvr_clean_directory_separator(tmp, tmp, tmplen);
573 }
574 
575 static htsstr_substitute_t dvr_subs_extension[] = {
576   { .id = "x", .getval = dvr_sub_str_separator },
577   { .id = NULL, .getval = NULL }
578 };
579 
580 static htsstr_substitute_t dvr_subs_tally[] = {
581   { .id = "n", .getval = dvr_sub_str_separator },
582   { .id = NULL, .getval = NULL }
583 };
584 
585 static htsstr_substitute_t dvr_subs_postproc_entry[] = {
586   { .id = "t",  .getval = dvr_sub_title },
587   { .id = "s",  .getval = dvr_sub_subtitle },
588   { .id = "p",  .getval = dvr_sub_episode },
589   { .id = "d",  .getval = dvr_sub_description },
590   { .id = "g",  .getval = dvr_sub_genre },
591   { .id = "c",  .getval = dvr_sub_channel },
592   { .id = "e",  .getval = dvr_sub_last_error },
593   { .id = "C",  .getval = dvr_sub_creator },
594   { .id = "O",  .getval = dvr_sub_owner },
595   { .id = "S",  .getval = dvr_sub_start },
596   { .id = "E",  .getval = dvr_sub_stop },
597   { .id = "r",  .getval = dvr_sub_errors },
598   { .id = "R",  .getval = dvr_sub_data_errors },
599   { .id = "Z",  .getval = dvr_sub_comment },
600   { .id = NULL, .getval = NULL }
601 };
602 
603 static const char *
dvr_sub_basename(const char * id,const char * fmt,const void * aux,char * tmp,size_t tmplen)604 dvr_sub_basename(const char *id, const char *fmt, const void *aux, char *tmp, size_t tmplen)
605 {
606   strlcpy(tmp, (const char *)aux, tmplen);
607   return basename(tmp);
608 }
609 
610 static htsstr_substitute_t dvr_subs_postproc_filename[] = {
611   { .id = "f",  .getval = dvr_sub_str },
612   { .id = "b",  .getval = dvr_sub_basename },
613   { .id = NULL, .getval = NULL }
614 };
615 
616 static const char *
dvr_sub_basic_info(const char * id,const char * fmt,const void * aux,char * tmp,size_t tmplen)617 dvr_sub_basic_info(const char *id, const char *fmt, const void *aux, char *tmp, size_t tmplen)
618 {
619   htsmsg_t *info = (htsmsg_t *)aux, *e;
620   htsmsg_field_t *f;
621   const char *s;
622   size_t l = 0;
623 
624   if (info)
625     info = htsmsg_get_list(info, "info");
626   if (!info)
627     return "";
628 
629   tmp[0] = '\0';
630   HTSMSG_FOREACH(f, info) {
631     if (!(e = htsmsg_field_get_map(f))) continue;
632     if ((s = htsmsg_get_str(e, "type")) != NULL)
633       tvh_strlcatf(tmp, tmplen, l, "%s%s", l > 0 ? "," : "", s);
634   }
635   return tmp;
636 }
637 
638 static htsstr_substitute_t dvr_subs_postproc_info[] = {
639   { .id = "i",  .getval = dvr_sub_basic_info },
640   { .id = NULL, .getval = NULL }
641 };
642 
dvr_find_last_path_component(char * path)643 static char *dvr_find_last_path_component(char *path)
644 {
645   char *res, *p;
646   for (p = path, res = NULL; *p; p++) {
647     if (*p == '\\') {
648       p++;
649     } else {
650       if (*p == '/')
651         res = p;
652     }
653   }
654   return res;
655 }
656 
dvr_find_next_path_component(char * path)657 static char *dvr_find_next_path_component(char *path)
658 {
659   char *res, *p;
660   for (p = res = path; *p; p++) {
661     if (*p == '\\') {
662       p++;
663     } else {
664       if (*p == '/')
665         return p + 1;
666     }
667   }
668   return NULL;
669 }
670 
671 /**
672  * Filename generator
673  *
674  * - convert from utf8
675  * - avoid duplicate filenames
676  *
677  */
678 static int
pvr_generate_filename(dvr_entry_t * de,const streaming_start_t * ss)679 pvr_generate_filename(dvr_entry_t *de, const streaming_start_t *ss)
680 {
681   char filename[PATH_MAX];
682   char path[PATH_MAX + 1];
683   char ptmp[PATH_MAX];
684   char number[16];
685   char tmp[MAX(PATH_MAX, 512)];
686   char *lastpath = NULL;
687   int tally = 0;
688   struct stat st;
689   char *s, *x, *fmtstr, *dirsep;
690   struct tm tm;
691   dvr_config_t *cfg;
692   htsmsg_t *m;
693   size_t l, j, k;
694   long max;
695   int dir_dosubs;
696 
697   if (de == NULL)
698     return -1;
699 
700   cfg = de->de_config;
701   if (tvh_str_default(cfg->dvr_storage, NULL) == NULL)
702     return -1;
703 
704   dir_dosubs = de->de_directory == NULL ||
705               (de->de_directory[0] == '$' &&
706                de->de_directory[1] == '$');
707 
708   localtime_r(&de->de_start, &tm);
709 
710   strlcpy(path, cfg->dvr_storage, sizeof(path));
711   l = strlen(path);
712   if (l + 1 >= sizeof(path)) {
713     tvherror(LS_DVR, "wrong storage path");
714     return -1;
715   }
716 
717   /* Remove trailing slash */
718   while (l > 0 && path[l-1] == '/')
719     path[--l] = '\0';
720   if (l + 1 >= sizeof(path))
721     l--;
722   path[l++] = '/';
723   path[l] = '\0';
724 
725   fmtstr = cfg->dvr_pathname;
726   while (*fmtstr == '/')
727     fmtstr++;
728 
729   /* Substitute DVR entry formatters */
730   htsstr_substitute(fmtstr, path + l, sizeof(path) - l, '$', dvr_subs_entry, de, tmp, sizeof(tmp));
731 
732   /* Own directory? */
733   if (de->de_directory) {
734     dirsep = dvr_find_last_path_component(path + l);
735     if (dirsep)
736       strcpy(filename, dirsep + 1);
737     else
738       strcpy(filename, path + l);
739     if (dir_dosubs) {
740       htsstr_substitute(de->de_directory+2, ptmp, sizeof(ptmp), '$', dvr_subs_entry, de, tmp, sizeof(tmp));
741     } else {
742       strlcpy(ptmp, de->de_directory, sizeof(ptmp));
743     }
744     s = ptmp;
745     while (*s == '/')
746       s++;
747     j = strlen(s);
748     while (j > 0 && s[j-1] == '/')
749       j--;
750     s[j] = '\0';
751     snprintf(path + l, sizeof(path) - l, "%s", s);
752     snprintf(path + l + j, sizeof(path) - l + j, "/%s", filename);
753   }
754 
755   /* Substitute time formatters */
756   htsstr_substitute(path + l, filename, sizeof(filename), '%', dvr_subs_time, &tm, tmp, sizeof(tmp));
757 
758   /* Substitute extension */
759   htsstr_substitute(filename, path + l, sizeof(path) - l, '$', dvr_subs_extension,
760                     muxer_suffix(de->de_chain->prch_muxer, ss) ?: "", tmp, sizeof(tmp));
761 
762   /* Cleanup all directory names */
763   x = path + l;
764   filename[j = 0] = '\0';
765   while (1) {
766     dirsep = dvr_find_next_path_component(x);
767     if (tvh_str_default(dirsep, NULL) == NULL)
768       break;
769     *(dirsep - 1) = '\0';
770     if (*x) {
771       s = cleanup_filename(cfg, x, dir_dosubs);
772       tvh_strlcatf(filename, sizeof(filename), j, "%s/", s);
773       free(s);
774     }
775     x = dirsep;
776   }
777   tvh_strlcatf(filename, sizeof(filename), j, "%s", x);
778   snprintf(path + l, sizeof(path) - l, "%s", filename);
779 
780   /* Deescape directory path and create directory tree */
781   dirsep = dvr_find_last_path_component(path + l);
782   if (dirsep) {
783     *dirsep = '\0';
784     dirsep++;
785   } else {
786     if (l > 0) {
787       assert(path[l-1] == '/');
788       path[l-1] = '\0';
789     }
790     dirsep = path + l;
791   }
792   htsstr_unescape_to(path, filename, sizeof(filename));
793   if (makedirs(LS_DVR, filename,
794                cfg->dvr_muxcnf.m_directory_permissions, 0, -1, -1) != 0)
795     return -1;
796   max = pathconf(filename, _PC_NAME_MAX);
797   if (max < 8)
798     max = NAME_MAX;
799   if (max > 255 && cfg->dvr_windows_compatible_filenames)
800     max = 255;
801   max -= 2;
802   j = strlen(filename);
803   snprintf(filename + j, sizeof(filename) - j, "/%s", dirsep);
804   if (filename[j] == '/')
805     j++;
806 
807   /* Unique filename loop */
808   while (1) {
809 
810     /* Prepare the name portion */
811     if (tally > 0) {
812       snprintf(number, sizeof(number), "-%d", tally);
813     } else {
814       number[0] = '\0';
815     }
816     /* Check the maximum filename length */
817     l = strlen(number);
818     k = strlen(filename + j);
819     if (l + k > max) {
820       s = (char *)htsstr_substitute_find(filename + j, '$');
821       if (s == NULL || s - (filename + j) < (l + k) - max) {
822 cut1:
823         l = j + (max - l);
824         if (filename[l - 1] == '$') /* not optimal */
825           filename[l + 1] = '\0';
826         else
827           filename[l] = '\0';
828       } else {
829         x = (char *)htsstr_escape_find(filename + j, s - (filename + j) - ((l + k) - max));
830         if (x == NULL)
831           goto cut1;
832         k = strlen(s);
833         memmove(x, s, k);
834         x[k] = '\0';
835       }
836     }
837 
838     htsstr_substitute(filename + j, ptmp, sizeof(ptmp), '$', dvr_subs_tally, number, tmp, sizeof(tmp));
839     s = cleanup_filename(cfg, ptmp, 1);
840     if (s == NULL) {
841       free(lastpath);
842       return -1;
843     }
844 
845     /* Construct the final filename */
846     memcpy(path, filename, j);
847     path[j] = '\0';
848     htsstr_unescape_to(s, path + j, sizeof(path) - j);
849     free(s);
850 
851     if (lastpath) {
852       if (strcmp(path, lastpath) == 0) {
853         free(lastpath);
854         tvherror(LS_DVR, "unable to create unique name (missing $n in format string?)");
855         return -1;
856       }
857     }
858 
859     if (stat(path, &st) == -1) {
860       tvhdebug(LS_DVR, "File \"%s\" -- %s -- Using for recording",
861 	       path, strerror(errno));
862       break;
863     }
864 
865     tvhdebug(LS_DVR, "Overwrite protection, file \"%s\" exists", path);
866 
867     free(lastpath);
868     lastpath = strdup(path);
869     tally++;
870   }
871 
872   free(lastpath);
873   if (de->de_files == NULL)
874     de->de_files = htsmsg_create_list();
875   m = htsmsg_create_map();
876   htsmsg_add_str(m, "filename", path);
877   htsmsg_add_msg(de->de_files, NULL, m);
878 
879   return 0;
880 }
881 
882 /**
883  *
884  */
885 static void
dvr_rec_fatal_error(dvr_entry_t * de,const char * fmt,...)886 dvr_rec_fatal_error(dvr_entry_t *de, const char *fmt, ...)
887 {
888   char msgbuf[256];
889 
890   va_list ap;
891   va_start(ap, fmt);
892 
893   vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
894   va_end(ap);
895 
896   tvherror(LS_DVR, "Recording error: \"%s\": %s",
897 	   dvr_get_filename(de) ?: lang_str_get(de->de_title, NULL), msgbuf);
898 }
899 
900 /**
901  *
902  */
903 static void
dvr_notify(dvr_entry_t * de)904 dvr_notify(dvr_entry_t *de)
905 {
906   if (de->de_last_notify + sec2mono(5) < mclk()) {
907     idnode_notify_changed(&de->de_id);
908     de->de_last_notify = mclk();
909     htsp_dvr_entry_update_stats(de);
910   }
911 }
912 
913 /**
914  *
915  */
916 static void
dvr_rec_set_state(dvr_entry_t * de,dvr_rs_state_t newstate,int error)917 dvr_rec_set_state(dvr_entry_t *de, dvr_rs_state_t newstate, int error)
918 {
919   if (de->de_last_error != error && error)
920     de->de_errors++;
921   dvr_entry_set_state(de, de->de_sched_state, newstate, error);
922 }
923 
924 /**
925  *
926  */
927 static int
dvr_rec_start(dvr_entry_t * de,const streaming_start_t * ss)928 dvr_rec_start(dvr_entry_t *de, const streaming_start_t *ss)
929 {
930   const source_info_t *si = &ss->ss_si;
931   streaming_start_t *ss_copy;
932   const streaming_start_component_t *ssc;
933   char res[14], asp[14], sr[6], ch[7];
934   dvr_config_t *cfg = de->de_config;
935   profile_chain_t *prch = de->de_chain;
936   htsmsg_t *info, *e;
937   htsmsg_field_t *f;
938   muxer_t *muxer;
939   struct stat st;
940   int i;
941 
942   if (!cfg) {
943     dvr_rec_fatal_error(de, "Unable to determine config profile");
944     return -1;
945   }
946 
947   if (!prch) {
948     dvr_rec_fatal_error(de, "Unable to determine stream profile");
949     return -1;
950   }
951 
952   if (stat(cfg->dvr_storage, &st) || !S_ISDIR(st.st_mode)) {
953     dvr_rec_fatal_error(de, "Unable to create file in directory '%s", cfg->dvr_storage);
954     return -1;
955   }
956 
957   if (!dvr_vfs_rec_start_check(cfg)) {
958     dvr_rec_fatal_error(de, "Not enough free disk space");
959     return SM_CODE_NO_SPACE;
960   }
961 
962   if (!(muxer = prch->prch_muxer)) {
963     if (profile_chain_reopen(prch, &cfg->dvr_muxcnf, 0)) {
964       dvr_rec_fatal_error(de, "Unable to reopen muxer");
965       return -1;
966     }
967     muxer = prch->prch_muxer;
968   }
969 
970   if(!muxer) {
971     dvr_rec_fatal_error(de, "Unable to create muxer");
972     return -1;
973   }
974 
975   if(pvr_generate_filename(de, ss) != 0) {
976     dvr_rec_fatal_error(de, "Unable to create file");
977     return -1;
978   }
979 
980   if(muxer_open_file(muxer, dvr_get_filename(de))) {
981     dvr_rec_fatal_error(de, "Unable to open file");
982     return -1;
983   }
984 
985   dvr_vfs_refresh_entry(de);
986 
987   ss_copy = streaming_start_copy(ss);
988 
989   if(muxer_init(muxer, ss_copy, lang_str_get(de->de_title, NULL))) {
990     dvr_rec_fatal_error(de, "Unable to init file");
991     goto _err;
992   }
993 
994   if(cfg->dvr_tag_files) {
995     if(muxer_write_meta(muxer, de->de_bcast, de->de_comment)) {
996       dvr_rec_fatal_error(de, "Unable to write meta data");
997       goto _err;
998     }
999   }
1000 
1001   tvhinfo(LS_DVR, "%s from "
1002 	 "adapter: \"%s\", "
1003 	 "network: \"%s\", mux: \"%s\", provider: \"%s\", "
1004 	 "service: \"%s\"",
1005 
1006 	 dvr_get_filename(de) ?: lang_str_get(de->de_title, NULL),
1007 	 si->si_adapter  ?: "<N/A>",
1008 	 si->si_network  ?: "<N/A>",
1009 	 si->si_mux      ?: "<N/A>",
1010 	 si->si_provider ?: "<N/A>",
1011 	 si->si_service  ?: "<N/A>");
1012 
1013 
1014   tvhinfo(LS_DVR,
1015 	 " #  %-16s  %-4s  %-10s  %-12s  %-11s  %-8s",
1016 	 "type",
1017 	 "lang",
1018 	 "resolution",
1019 	 "aspect ratio",
1020 	 "sample rate",
1021 	 "channels");
1022 
1023   info = htsmsg_create_list();
1024   for(i = 0; i < ss_copy->ss_num_components; i++) {
1025     ssc = &ss_copy->ss_components[i];
1026 
1027     if(ssc->ssc_muxer_disabled)
1028       continue;
1029 
1030     e = htsmsg_create_map();
1031     htsmsg_add_str(e, "type", streaming_component_type2txt(ssc->ssc_type));
1032     if (ssc->ssc_lang[0])
1033        htsmsg_add_str(e, "language", ssc->ssc_lang);
1034 
1035     if(SCT_ISAUDIO(ssc->ssc_type)) {
1036       htsmsg_add_u32(e, "audio_type", ssc->ssc_audio_type);
1037       if(ssc->ssc_audio_version)
1038         htsmsg_add_u32(e, "audio_version", ssc->ssc_audio_version);
1039       if(ssc->ssc_sri)
1040 	snprintf(sr, sizeof(sr), "%d", sri_to_rate(ssc->ssc_sri));
1041       else
1042 	strcpy(sr, "?");
1043 
1044       if(ssc->ssc_channels == 6)
1045 	snprintf(ch, sizeof(ch), "5.1");
1046       else if(ssc->ssc_channels == 0)
1047 	strcpy(ch, "?");
1048       else
1049 	snprintf(ch, sizeof(ch), "%d", ssc->ssc_channels);
1050     } else {
1051       sr[0] = ch[0] = 0;
1052     }
1053 
1054     if(SCT_ISVIDEO(ssc->ssc_type)) {
1055       if(ssc->ssc_width && ssc->ssc_height)
1056 	snprintf(res, sizeof(res), "%dx%d",
1057 		 ssc->ssc_width, ssc->ssc_height);
1058       else
1059 	strcpy(res, "?");
1060 
1061       if(ssc->ssc_aspect_num &&  ssc->ssc_aspect_den)
1062 	snprintf(asp, sizeof(asp), "%d:%d",
1063 		 ssc->ssc_aspect_num, ssc->ssc_aspect_den);
1064       else
1065 	strcpy(asp, "?");
1066 
1067       htsmsg_add_u32(e, "width",      ssc->ssc_width);
1068       htsmsg_add_u32(e, "height",     ssc->ssc_height);
1069       htsmsg_add_u32(e, "duration",   ssc->ssc_frameduration);
1070       htsmsg_add_u32(e, "aspect_num", ssc->ssc_aspect_num);
1071       htsmsg_add_u32(e, "aspect_den", ssc->ssc_aspect_den);
1072     } else {
1073       res[0] = asp[0] = 0;
1074     }
1075 
1076     if (SCT_ISSUBTITLE(ssc->ssc_type)) {
1077       htsmsg_add_u32(e, "composition_id", ssc->ssc_composition_id);
1078       htsmsg_add_u32(e, "ancillary_id",   ssc->ssc_ancillary_id);
1079     }
1080 
1081     tvhinfo(LS_DVR,
1082 	   "%2d  %-16s  %-4s  %-10s  %-12s  %-11s  %-8s  %s",
1083 	   ssc->ssc_index,
1084 	   streaming_component_type2txt(ssc->ssc_type),
1085 	   ssc->ssc_lang,
1086 	   res,
1087 	   asp,
1088 	   sr,
1089 	   ch,
1090 	   ssc->ssc_disabled ? "<disabled, no valid input>" : "");
1091     htsmsg_add_msg(info, NULL, e);
1092   }
1093 
1094   streaming_start_unref(ss_copy);
1095 
1096   /* update the info field for a filename */
1097   if ((f = htsmsg_field_last(de->de_files)) != NULL &&
1098       (e = htsmsg_field_get_map(f)) != NULL) {
1099     htsmsg_set_msg(e, "info", info);
1100     htsmsg_set_s64(e, "start", gclk());
1101   } else {
1102     htsmsg_destroy(info);
1103   }
1104   return 0;
1105 
1106 _err:
1107   streaming_start_unref(ss_copy);
1108   return -1;
1109 }
1110 
1111 /**
1112  *
1113  */
1114 static inline int
dvr_thread_global_lock(dvr_entry_t * de,int * run)1115 dvr_thread_global_lock(dvr_entry_t *de, int *run)
1116 {
1117   if (atomic_add(&de->de_thread_shutdown, 1) > 0) {
1118     *run = 0;
1119     return 0;
1120   }
1121   pthread_mutex_lock(&global_lock);
1122   return 1;
1123 }
1124 
1125 /**
1126  *
1127  */
1128 static inline void
dvr_thread_global_unlock(dvr_entry_t * de)1129 dvr_thread_global_unlock(dvr_entry_t *de)
1130 {
1131   pthread_mutex_unlock(&global_lock);
1132   atomic_dec(&de->de_thread_shutdown, 1);
1133 }
1134 
1135 /**
1136  *
1137  */
1138 static void
dvr_streaming_restart(dvr_entry_t * de,int * run)1139 dvr_streaming_restart(dvr_entry_t *de, int *run)
1140 {
1141   if (dvr_thread_global_lock(de, run)) {
1142     service_restart(de->de_s->ths_service);
1143     dvr_thread_global_unlock(de);
1144   }
1145 }
1146 
1147 /**
1148  *
1149  */
1150 static int
dvr_thread_pkt_stats(dvr_entry_t * de,th_pkt_t * pkt,int payload)1151 dvr_thread_pkt_stats(dvr_entry_t *de, th_pkt_t *pkt, int payload)
1152 {
1153   th_subscription_t *ts;
1154   int ret = 0;
1155 
1156   if ((ts = de->de_s) != NULL) {
1157     if (pkt->pkt_err) {
1158       de->de_data_errors += pkt->pkt_err;
1159       ret = 1;
1160     }
1161     if (payload && pkt->pkt_payload)
1162       subscription_add_bytes_out(ts, pktbuf_len(pkt->pkt_payload));
1163   }
1164   return ret;
1165 }
1166 
1167 /**
1168  *
1169  */
1170 static int
dvr_thread_mpegts_stats(dvr_entry_t * de,void * sm_data)1171 dvr_thread_mpegts_stats(dvr_entry_t *de, void *sm_data)
1172 {
1173   th_subscription_t *ts;
1174   pktbuf_t *pb = sm_data;
1175   int ret = 0;
1176 
1177   if (pb) {
1178     if ((ts = de->de_s) != NULL) {
1179       if (pb->pb_err) {
1180         de->de_data_errors += pb->pb_err;
1181         ret = 1;
1182       }
1183       subscription_add_bytes_out(ts, pktbuf_len(pb));
1184     }
1185   }
1186   return ret;
1187 }
1188 
1189 /**
1190  *
1191  */
1192 static int
dvr_thread_rec_start(dvr_entry_t ** _de,streaming_start_t * ss,int * run,int * started,int64_t * dts_offset,const char * postproc)1193 dvr_thread_rec_start(dvr_entry_t **_de, streaming_start_t *ss,
1194                      int *run, int *started, int64_t *dts_offset,
1195                      const char *postproc)
1196 {
1197   dvr_entry_t *de = *_de;
1198   profile_chain_t *prch = de->de_chain;
1199   int ret = 0;
1200 
1201   if (*started) {
1202     if (muxer_reconfigure(prch->prch_muxer, ss) >= 0)
1203       return 1;
1204     tvhwarn(LS_DVR, "Unable to reconfigure \"%s\"",
1205             dvr_get_filename(de) ?: lang_str_get(de->de_title, NULL));
1206 
1207     // Try to restart the recording if the muxer doesn't
1208     // support reconfiguration of the streams.
1209     if (!dvr_thread_global_lock(de, run)) {
1210       *dts_offset = PTS_UNSET;
1211       *started = 0;
1212       return 0;
1213     }
1214     dvr_thread_epilog(de, postproc);
1215     *dts_offset = PTS_UNSET;
1216     *started = 0;
1217     if (de->de_config->dvr_clone)
1218       *_de = dvr_entry_clone(de);
1219     dvr_thread_global_unlock(de);
1220     de = *_de;
1221   }
1222 
1223   if (!*started) {
1224     if (!dvr_thread_global_lock(de, run))
1225       return 0;
1226     dvr_rec_set_state(de, DVR_RS_WAIT_PROGRAM_START, 0);
1227     int code = dvr_rec_start(de, ss);
1228     if(code == 0) {
1229       ret = 1;
1230       *started = 1;
1231     } else
1232       dvr_stop_recording(de, code == SM_CODE_NO_SPACE ? SM_CODE_NO_SPACE : SM_CODE_INVALID_TARGET, 1, 0);
1233     dvr_thread_global_unlock(de);
1234   }
1235   return ret;
1236 }
1237 
1238 /**
1239  *
1240  */
1241 static inline int
dts_pts_valid(th_pkt_t * pkt,int64_t dts_offset)1242 dts_pts_valid(th_pkt_t *pkt, int64_t dts_offset)
1243 {
1244   if (pkt->pkt_dts == PTS_UNSET ||
1245       pkt->pkt_pts == PTS_UNSET ||
1246       dts_offset == PTS_UNSET ||
1247       pkt->pkt_dts < dts_offset ||
1248       pkt->pkt_pts < dts_offset)
1249     return 0;
1250   return 1;
1251 }
1252 
1253 /**
1254  *
1255  */
1256 static int64_t
get_dts_ref(th_pkt_t * pkt,streaming_start_t * ss)1257 get_dts_ref(th_pkt_t *pkt, streaming_start_t *ss)
1258 {
1259   const streaming_start_component_t *ssc;
1260   int64_t audio = PTS_UNSET;
1261   int i;
1262 
1263   if (pkt->pkt_dts == PTS_UNSET)
1264     return PTS_UNSET;
1265   for (i = 0; i < ss->ss_num_components; i++) {
1266     ssc = &ss->ss_components[i];
1267     if (ssc->ssc_index == pkt->pkt_componentindex) {
1268       if (SCT_ISVIDEO(ssc->ssc_type))
1269         return pkt->pkt_dts;
1270       if (audio == PTS_UNSET && SCT_ISAUDIO(ssc->ssc_type))
1271         audio = pkt->pkt_dts;
1272     }
1273   }
1274   return audio;
1275 }
1276 
1277 /**
1278  *
1279  */
1280 static void *
dvr_thread(void * aux)1281 dvr_thread(void *aux)
1282 {
1283   dvr_entry_t *de = aux;
1284   profile_chain_t *prch = de->de_chain;
1285   streaming_queue_t *sq = &prch->prch_sq;
1286   struct streaming_message_queue backlog;
1287   streaming_message_t *sm, *sm2;
1288   th_pkt_t *pkt, *pkt2, *pkt3;
1289   streaming_start_t *ss = NULL;
1290   int run = 1, started = 0, muxing = 0, comm_skip, rs;
1291   int epg_running = 0, old_epg_running, epg_pause = 0;
1292   int commercial = COMMERCIAL_UNKNOWN;
1293   int running_disabled;
1294   int64_t packets = 0, dts_offset = PTS_UNSET;
1295   time_t real_start, start_time = 0, running_start = 0, running_stop = 0;
1296   char *postproc;
1297   char ubuf[UUID_HEX_SIZE];
1298 
1299   if (!dvr_thread_global_lock(de, &run))
1300     return NULL;
1301   comm_skip = de->de_config->dvr_skip_commercials;
1302   postproc  = de->de_config->dvr_postproc ? strdup(de->de_config->dvr_postproc) : NULL;
1303   running_disabled = dvr_entry_get_epg_running(de) <= 0;
1304   real_start = dvr_entry_get_start_time(de, 0);
1305   tvhtrace(LS_DVR, "%s - recoding thread started for \"%s\"",
1306            idnode_uuid_as_str(&de->de_id, ubuf), lang_str_get(de->de_title, NULL));
1307   dvr_thread_global_unlock(de);
1308 
1309   TAILQ_INIT(&backlog);
1310 
1311   pthread_mutex_lock(&sq->sq_mutex);
1312   while(run) {
1313     sm = TAILQ_FIRST(&sq->sq_queue);
1314     if(sm == NULL) {
1315       tvh_cond_wait(&sq->sq_cond, &sq->sq_mutex);
1316       continue;
1317     }
1318     streaming_queue_remove(sq, sm);
1319 
1320     old_epg_running = epg_running;
1321     if (running_disabled) {
1322       epg_running = real_start <= gclk();
1323     } else if (sm->sm_type == SMT_PACKET || sm->sm_type == SMT_MPEGTS) {
1324       running_start = atomic_get_time_t(&de->de_running_start);
1325       running_stop  = atomic_get_time_t(&de->de_running_stop);
1326       if (running_start > 0) {
1327         epg_running = running_start >= running_stop ? 1 : 0;
1328         if (epg_running && atomic_get_time_t(&de->de_running_pause) >= running_start)
1329           epg_running = 2;
1330       } else if (running_stop == 0) {
1331         if (start_time + 2 >= gclk()) {
1332           TAILQ_INSERT_TAIL(&backlog, sm, sm_link);
1333           continue;
1334         } else {
1335           if (TAILQ_FIRST(&backlog))
1336             streaming_queue_clear(&backlog);
1337           epg_running = real_start <= gclk();
1338         }
1339       } else {
1340         epg_running = 0;
1341       }
1342     }
1343     if (epg_running != old_epg_running)
1344       tvhtrace(LS_DVR, "%s - running flag changed from %d to %d",
1345                idnode_uuid_as_str(&de->de_id, ubuf), old_epg_running, epg_running);
1346 
1347     pthread_mutex_unlock(&sq->sq_mutex);
1348 
1349     switch(sm->sm_type) {
1350 
1351     case SMT_PACKET:
1352       pkt = sm->sm_data;
1353 
1354       rs = DVR_RS_RUNNING;
1355       if (!epg_running)
1356         rs = DVR_RS_EPG_WAIT;
1357       else if (pkt->pkt_commercial == COMMERCIAL_YES || epg_running == 2)
1358         rs = DVR_RS_COMMERCIAL;
1359       dvr_rec_set_state(de, rs, 0);
1360 
1361       if ((rs == DVR_RS_COMMERCIAL && comm_skip) || !epg_running) {
1362         if (ss && packets && running_start == 0) {
1363           dvr_streaming_restart(de, &run);
1364           packets = 0;
1365           started = 0;
1366         }
1367         break;
1368       }
1369 
1370       if (epg_pause != (epg_running == 2)) {
1371         epg_pause = epg_running == 2;
1372 	if (muxing) muxer_add_marker(prch->prch_muxer);
1373       } else if (commercial != pkt->pkt_commercial) {
1374         commercial = pkt->pkt_commercial;
1375         if (muxing) muxer_add_marker(prch->prch_muxer);
1376       } else if (atomic_exchange(&de->de_running_change, 0)) {
1377         if (muxing) muxer_add_marker(prch->prch_muxer);
1378       }
1379 
1380       if (ss == NULL)
1381         break;
1382 
1383       if (muxing == 0) {
1384         if (!dvr_thread_rec_start(&de, ss, &run, &started, &dts_offset, postproc))
1385           break;
1386         tvhtrace(LS_DVR, "%s - muxing activated", idnode_uuid_as_str(&de->de_id, ubuf));
1387       }
1388 
1389       muxing = 1;
1390       while ((sm2 = TAILQ_FIRST(&backlog)) != NULL) {
1391         TAILQ_REMOVE(&backlog, sm2, sm_link);
1392         pkt2 = sm2->sm_data;
1393         if (pkt2->pkt_dts != PTS_UNSET) {
1394           if (dts_offset == PTS_UNSET)
1395             dts_offset = get_dts_ref(pkt2, ss);
1396           if (dts_pts_valid(pkt2, dts_offset)) {
1397             pkt3 = pkt_copy_shallow(pkt2);
1398             pkt3->pkt_dts -= dts_offset;
1399             if (pkt3->pkt_pts != PTS_UNSET)
1400               pkt3->pkt_pts -= dts_offset;
1401             dvr_thread_pkt_stats(de, pkt3, 1);
1402             muxer_write_pkt(prch->prch_muxer, sm2->sm_type, pkt3);
1403           } else {
1404             dvr_thread_pkt_stats(de, pkt2, 0);
1405           }
1406         }
1407         streaming_msg_free(sm2);
1408       }
1409       if (dts_offset == PTS_UNSET)
1410         dts_offset = get_dts_ref(pkt, ss);
1411       if (dts_pts_valid(pkt, dts_offset)) {
1412         pkt3 = pkt_copy_shallow(pkt);
1413         pkt3->pkt_dts -= dts_offset;
1414         if (pkt3->pkt_pts != PTS_UNSET)
1415           pkt3->pkt_pts -= dts_offset;
1416         dvr_thread_pkt_stats(de, pkt3, 1);
1417         muxer_write_pkt(prch->prch_muxer, sm->sm_type, pkt3);
1418       } else {
1419         dvr_thread_pkt_stats(de, pkt, 0);
1420       }
1421       dvr_notify(de);
1422       packets++;
1423       break;
1424 
1425     case SMT_MPEGTS:
1426       rs = DVR_RS_RUNNING;
1427       if (!epg_running)
1428         rs = DVR_RS_EPG_WAIT;
1429       else if (epg_running == 2)
1430         rs = DVR_RS_COMMERCIAL;
1431       dvr_rec_set_state(de, rs, 0);
1432 
1433       if (ss == NULL)
1434         break;
1435 
1436       if ((rs == DVR_RS_COMMERCIAL && comm_skip) || !epg_running) {
1437         if (packets && running_start == 0) {
1438           dvr_streaming_restart(de, &run);
1439           packets = 0;
1440           started = 0;
1441         }
1442         break;
1443       }
1444 
1445       if (epg_pause != (epg_running == 2)) {
1446         epg_pause = epg_running == 2;
1447 	if (muxing) muxer_add_marker(prch->prch_muxer);
1448       } else if (atomic_exchange(&de->de_running_change, 0)) {
1449         if (muxing) muxer_add_marker(prch->prch_muxer);
1450       }
1451 
1452       if (muxing == 0) {
1453         if (!dvr_thread_rec_start(&de, ss, &run, &started, &dts_offset, postproc))
1454           break;
1455         tvhtrace(LS_DVR, "%s - muxing activated", idnode_uuid_as_str(&de->de_id, ubuf));
1456       }
1457 
1458       muxing = 1;
1459       while ((sm2 = TAILQ_FIRST(&backlog)) != NULL) {
1460         TAILQ_REMOVE(&backlog, sm2, sm_link);
1461         dvr_thread_mpegts_stats(de, sm2->sm_data);
1462         muxer_write_pkt(prch->prch_muxer, sm2->sm_type, sm2->sm_data);
1463         sm2->sm_data = NULL;
1464         streaming_msg_free(sm2);
1465       }
1466       dvr_thread_mpegts_stats(de, sm->sm_data);
1467       muxer_write_pkt(prch->prch_muxer, sm->sm_type, sm->sm_data);
1468       sm->sm_data = NULL;
1469       dvr_notify(de);
1470       packets++;
1471       break;
1472 
1473     case SMT_START:
1474       start_time = gclk();
1475       packets = 0;
1476       if (ss)
1477 	streaming_start_unref(ss);
1478       ss = streaming_start_copy((streaming_start_t *)sm->sm_data);
1479       break;
1480 
1481     case SMT_STOP:
1482        if (sm->sm_code == SM_CODE_SOURCE_RECONFIGURED) {
1483 	 // Subscription is restarting, wait for SMT_START
1484 	 if (muxing)
1485            tvhtrace(LS_DVR, "%s - source reconfigured", idnode_uuid_as_str(&de->de_id, ubuf));
1486 	 muxing = 0; // reconfigure muxer
1487 
1488        } else if(sm->sm_code == 0) {
1489 	 // Recording is completed
1490 
1491 	dvr_entry_set_state(de, de->de_sched_state, de->de_rec_state, SM_CODE_OK);
1492 	tvhinfo(LS_DVR, "Recording completed: \"%s\"",
1493 	        dvr_get_filename(de) ?: lang_str_get(de->de_title, NULL));
1494 
1495         goto fin;
1496 
1497       } else if (de->de_last_error != sm->sm_code) {
1498 	 // Error during recording
1499 
1500 	dvr_rec_set_state(de, DVR_RS_ERROR, sm->sm_code);
1501 	tvherror(LS_DVR, "Recording stopped: \"%s\": %s",
1502                 dvr_get_filename(de) ?: lang_str_get(de->de_title, NULL),
1503                 streaming_code2txt(sm->sm_code));
1504 
1505 fin:
1506         streaming_queue_clear(&backlog);
1507         if (!dvr_thread_global_lock(de, &run))
1508           break;
1509         dvr_thread_epilog(de, postproc);
1510         dvr_thread_global_unlock(de);
1511 	start_time = 0;
1512 	started = 0;
1513 	muxing = 0;
1514 	if (ss) {
1515 	  streaming_start_unref(ss);
1516 	  ss = NULL;
1517         }
1518       }
1519       break;
1520 
1521     case SMT_SERVICE_STATUS:
1522       if (sm->sm_code & TSS_PACKETS) {
1523 
1524       } else if (sm->sm_code & TSS_ERRORS) {
1525 
1526 	int code = tss2errcode(sm->sm_code);
1527 
1528 	if(de->de_last_error != code) {
1529 	  dvr_rec_set_state(de, DVR_RS_ERROR, code);
1530 	  tvherror(LS_DVR, "Streaming error: \"%s\": %s",
1531 		   dvr_get_filename(de) ?: lang_str_get(de->de_title, NULL),
1532 		   streaming_code2txt(code));
1533 	}
1534       }
1535       break;
1536 
1537     case SMT_NOSTART:
1538 
1539       if (de->de_last_error != sm->sm_code) {
1540 	dvr_rec_set_state(de, DVR_RS_PENDING, sm->sm_code);
1541 
1542 	tvherror(LS_DVR, "Recording unable to start: \"%s\": %s",
1543 	         dvr_get_filename(de) ?: lang_str_get(de->de_title, NULL),
1544 	         streaming_code2txt(sm->sm_code));
1545       }
1546       break;
1547 
1548     case SMT_GRACE:
1549     case SMT_NOSTART_WARN:
1550     case SMT_SPEED:
1551     case SMT_SKIP:
1552     case SMT_SIGNAL_STATUS:
1553     case SMT_TIMESHIFT_STATUS:
1554     case SMT_DESCRAMBLE_INFO:
1555       break;
1556 
1557     case SMT_EXIT:
1558       run = 0;
1559       break;
1560     }
1561 
1562     streaming_msg_free(sm);
1563     pthread_mutex_lock(&sq->sq_mutex);
1564   }
1565   pthread_mutex_unlock(&sq->sq_mutex);
1566 
1567   streaming_queue_clear(&backlog);
1568 
1569   if (ss)
1570     streaming_start_unref(ss);
1571 
1572   return postproc;
1573 }
1574 
1575 /**
1576  *
1577  */
1578 void
dvr_spawn_cmd(dvr_entry_t * de,const char * cmd,const char * filename,int pre)1579 dvr_spawn_cmd(dvr_entry_t *de, const char *cmd, const char *filename, int pre)
1580 {
1581   char buf1[MAX(PATH_MAX, 2048)], *buf2;
1582   char tmp[MAX(PATH_MAX, 512)];
1583   htsmsg_t *info = NULL, *e;
1584   htsmsg_field_t *f;
1585   char **args;
1586 
1587   if (!pre) {
1588     if ((f = htsmsg_field_last(de->de_files)) != NULL &&
1589         (e = htsmsg_field_get_map(f)) != NULL) {
1590       if (filename == NULL) {
1591         filename = htsmsg_get_str(e, "filename");
1592         if (filename == NULL)
1593           return;
1594       }
1595       info = htsmsg_get_list(e, "info");
1596     } else {
1597       return;
1598     }
1599   }
1600 
1601   /* Substitute DVR entry formatters */
1602   htsstr_substitute(cmd, buf1, sizeof(buf1), '%', dvr_subs_postproc_entry, de, tmp, sizeof(tmp));
1603   buf2 = tvh_strdupa(buf1);
1604   /* Substitute filename formatters */
1605   if (!pre) {
1606     htsstr_substitute(buf2, buf1, sizeof(buf1), '%', dvr_subs_postproc_filename, filename, tmp, sizeof(tmp));
1607     buf2 = tvh_strdupa(buf1);
1608   }
1609   /* Substitute info formatters */
1610   if (info)
1611     htsstr_substitute(buf2, buf1, sizeof(buf1), '%', dvr_subs_postproc_info, info, tmp, sizeof(tmp));
1612 
1613   args = htsstr_argsplit(buf1);
1614   if(args[0])
1615     spawnv(args[0], (void *)args, NULL, 1, 1);
1616 
1617   htsstr_argsplit_free(args);
1618 }
1619 
1620 /**
1621  *
1622  */
1623 static void
dvr_thread_epilog(dvr_entry_t * de,const char * dvr_postproc)1624 dvr_thread_epilog(dvr_entry_t *de, const char *dvr_postproc)
1625 {
1626   profile_chain_t *prch = de->de_chain;
1627   htsmsg_t *e;
1628   htsmsg_field_t *f;
1629 
1630   lock_assert(&global_lock);
1631 
1632   if (prch == NULL)
1633     return;
1634 
1635   muxer_close(prch->prch_muxer);
1636   muxer_destroy(prch->prch_muxer);
1637   prch->prch_muxer = NULL;
1638 
1639   if ((f = htsmsg_field_last(de->de_files)) != NULL &&
1640       (e = htsmsg_field_get_map(f)) != NULL)
1641     htsmsg_set_s64(e, "stop", gclk());
1642 
1643   if(dvr_postproc && dvr_postproc[0])
1644     dvr_spawn_cmd(de, dvr_postproc, NULL, 0);
1645 
1646   idnode_changed(&de->de_id);
1647 }
1648