1 /*
2 * Tvheadend - structures
3 * Copyright (C) 2007 Andreas Öman
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 #ifndef TVHEADEND_H
19 #define TVHEADEND_H
20
21 #include "build.h"
22
23 #define _GNU_SOURCE
24 #include <pthread.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <errno.h>
28 #include <netinet/in.h>
29 #include <sys/socket.h>
30 #include <sys/time.h>
31 #include <libgen.h>
32 #include <string.h>
33 #include <assert.h>
34 #include <unistd.h>
35 #include <limits.h>
36 #if ENABLE_LOCKOWNER || ENABLE_ANDROID
37 #include <sys/syscall.h>
38 #endif
39 #include "queue.h"
40 #include "tvh_string.h"
41 #include "hts_strtab.h"
42 #include "htsmsg.h"
43 #include "tvhlog.h"
44
45 #include "redblack.h"
46
47 #include "tvh_locale.h"
48
49 #define STRINGIFY(s) # s
50 #define SRCLINEID() SRCLINEID2(__FILE__, __LINE__)
51 #define SRCLINEID2(f,l) f ":" STRINGIFY(l)
52
53 #define ERRNO_AGAIN(e) ((e) == EAGAIN || (e) == EINTR || (e) == EWOULDBLOCK)
54
55 #include "compat.h"
56
57 typedef struct {
58 const char *name;
59 const uint32_t *enabled;
60 } tvh_caps_t;
61
62 extern int tvheadend_running;
63 extern const char *tvheadend_version;
64 extern const char *tvheadend_cwd;
65 extern const char *tvheadend_webroot;
66 extern const tvh_caps_t tvheadend_capabilities[];
67
tvheadend_is_running(void)68 static inline int tvheadend_is_running(void)
69 {
70 return atomic_get(&tvheadend_running);
71 }
72
73 htsmsg_t *tvheadend_capabilities_list(int check);
74
75 typedef struct str_list
76 {
77 int max;
78 int num;
79 char **str;
80 } str_list_t;
81
82 #define PTS_UNSET INT64_C(0x8000000000000000)
83 #define PTS_MASK INT64_C(0x00000001ffffffff)
84
85 extern pthread_mutex_t global_lock;
86 extern pthread_mutex_t tasklet_lock;
87 extern pthread_mutex_t fork_lock;
88
89 extern int tvheadend_webui_port;
90 extern int tvheadend_webui_debug;
91 extern int tvheadend_htsp_port;
92
93 static inline void
lock_assert0(pthread_mutex_t * l,const char * file,int line)94 lock_assert0(pthread_mutex_t *l, const char *file, int line)
95 {
96 #if 0 && ENABLE_LOCKOWNER
97 assert(l->__data.__owner == syscall(SYS_gettid));
98 #else
99 if(pthread_mutex_trylock(l) == EBUSY)
100 return;
101
102 fprintf(stderr, "Mutex not held at %s:%d\n", file, line);
103 abort();
104 #endif
105 }
106
107 #define lock_assert(l) lock_assert0(l, __FILE__, __LINE__)
108
109 #if defined(__has_feature)
110 #if __has_feature(address_sanitizer) || __has_feature(thread_sanitizer)
111 #define CLANG_SANITIZER 1
112 #endif
113 #endif
114
115 /*
116 *
117 */
118
119 typedef struct {
120 pthread_cond_t cond;
121 } tvh_cond_t;
122
123
124 /*
125 * Commercial status
126 */
127 typedef enum {
128 COMMERCIAL_UNKNOWN,
129 COMMERCIAL_YES,
130 COMMERCIAL_NO,
131 } th_commercial_advice_t;
132
133
134 /*
135 *
136 */
137 #define UILEVEL_DEFAULT (-1)
138 #define UILEVEL_BASIC 0
139 #define UILEVEL_ADVANCED 1
140 #define UILEVEL_EXPERT 2
141
142 /*
143 *
144 */
145 #define CHICON_NONE 0
146 #define CHICON_LOWERCASE 1
147 #define CHICON_SVCNAME 2
148
149 /*
150 *
151 */
152 #define PICON_STANDARD 0
153 #define PICON_ISVCTYPE 1
154
155 /*
156 * timer support functions
157 */
158
159 #if ENABLE_GTIMER_CHECK
160 #define GTIMER_TRACEID_ const char *id, const char *fcn,
161 #define GTIMER_FCN(n) check_##n
162 #else
163 #define GTIMER_TRACEID_
164 #define GTIMER_FCN(n) n
165 #endif
166
167 /*
168 * global timer - monotonic
169 */
170
171 typedef void (mti_callback_t)(void *opaque);
172
173 typedef struct mtimer {
174 LIST_ENTRY(mtimer) mti_link;
175 mti_callback_t *mti_callback;
176 void *mti_opaque;
177 int64_t mti_expire;
178 #if ENABLE_GTIMER_CHECK
179 const char *mti_id;
180 const char *mti_fcn;
181 #endif
182 } mtimer_t;
183
184 void GTIMER_FCN(mtimer_arm_rel)
185 (GTIMER_TRACEID_ mtimer_t *mti, mti_callback_t *callback, void *opaque, int64_t delta);
186 void GTIMER_FCN(mtimer_arm_abs)
187 (GTIMER_TRACEID_ mtimer_t *mti, mti_callback_t *callback, void *opaque, int64_t when);
188
189 #if ENABLE_GTIMER_CHECK
190 #define mtimer_arm_rel(a, b, c, d) GTIMER_FCN(mtimer_arm_rel)(SRCLINEID(), __func__, a, b, c, d)
191 #define mtimer_arm_abs(a, b, c, d) GTIMER_FCN(mtimer_arm_abs)(SRCLINEID(), __func__, a, b, c, d)
192 #endif
193
194 void mtimer_disarm(mtimer_t *mti);
195
196
197
198 /*
199 * global timer (based on the current system time - time())
200 */
201
202 typedef void (gti_callback_t)(void *opaque);
203
204 typedef struct gtimer {
205 LIST_ENTRY(gtimer) gti_link;
206 gti_callback_t *gti_callback;
207 void *gti_opaque;
208 time_t gti_expire;
209 #if ENABLE_GTIMER_CHECK
210 const char *gti_id;
211 const char *gti_fcn;
212 #endif
213 } gtimer_t;
214
215 void GTIMER_FCN(gtimer_arm_rel)
216 (GTIMER_TRACEID_ gtimer_t *gti, gti_callback_t *callback, void *opaque, time_t delta);
217 void GTIMER_FCN(gtimer_arm_absn)
218 (GTIMER_TRACEID_ gtimer_t *gti, gti_callback_t *callback, void *opaque, time_t when);
219
220 #if ENABLE_GTIMER_CHECK
221 #define gtimer_arm_rel(a, b, c, d) GTIMER_FCN(gtimer_arm_rel)(SRCLINEID(), __func__, a, b, c, d)
222 #define gtimer_arm_absn(a, b, c, d) GTIMER_FCN(gtimer_arm_absn)(SRCLINEID(), __func__, a, b, c, d)
223 #endif
224
225 void gtimer_disarm(gtimer_t *gti);
226
227
228 /*
229 * tasklet
230 */
231
232 typedef void (tsk_callback_t)(void *opaque, int disarmed);
233
234 typedef struct tasklet {
235 TAILQ_ENTRY(tasklet) tsk_link;
236 tsk_callback_t *tsk_callback;
237 void *tsk_opaque;
238 void (*tsk_free)(void *);
239 } tasklet_t;
240
241 tasklet_t *tasklet_arm_alloc(tsk_callback_t *callback, void *opaque);
242 void tasklet_arm(tasklet_t *tsk, tsk_callback_t *callback, void *opaque);
243 void tasklet_disarm(tasklet_t *gti);
244
245
246 /*
247 * List / Queue header declarations
248 */
249 LIST_HEAD(memoryinfo_list, memoryinfo);
250 LIST_HEAD(access_entry_list, access_entry);
251 LIST_HEAD(th_subscription_list, th_subscription);
252 LIST_HEAD(dvr_vfs_list, dvr_vfs);
253 LIST_HEAD(dvr_config_list, dvr_config);
254 LIST_HEAD(dvr_entry_list, dvr_entry);
255 TAILQ_HEAD(ref_update_queue, ref_update);
256 LIST_HEAD(service_list, service);
257 RB_HEAD(service_tree, service);
258 TAILQ_HEAD(service_queue, service);
259 LIST_HEAD(elementary_stream_list, elementary_stream);
260 TAILQ_HEAD(elementary_stream_queue, elementary_stream);
261 LIST_HEAD(th_muxer_list, th_muxer);
262 LIST_HEAD(th_muxstream_list, th_muxstream);
263 LIST_HEAD(th_descrambler_list, th_descrambler);
264 TAILQ_HEAD(th_refpkt_queue, th_refpkt);
265 TAILQ_HEAD(th_muxpkt_queue, th_muxpkt);
266 LIST_HEAD(dvr_autorec_entry_list, dvr_autorec_entry);
267 LIST_HEAD(dvr_timerec_entry_list, dvr_timerec_entry);
268 TAILQ_HEAD(th_pktref_queue, th_pktref);
269 LIST_HEAD(streaming_target_list, streaming_target);
270
271 /**
272 * Stream component types
273 */
274 typedef enum {
275 SCT_NONE = -1,
276 SCT_UNKNOWN = 0,
277 SCT_RAW = 1,
278 SCT_MPEG2VIDEO,
279 SCT_MPEG2AUDIO,
280 SCT_H264,
281 SCT_AC3,
282 SCT_TELETEXT,
283 SCT_DVBSUB,
284 SCT_CA,
285 SCT_AAC, /* AAC-LATM in MPEG-TS, ADTS + AAC in packet form */
286 SCT_MPEGTS,
287 SCT_TEXTSUB,
288 SCT_EAC3,
289 SCT_MP4A, /* ADTS + AAC in MPEG-TS and packet form */
290 SCT_VP8,
291 SCT_VORBIS,
292 SCT_HEVC,
293 SCT_VP9,
294 SCT_LAST = SCT_VP9
295 } streaming_component_type_t;
296
297 #define SCT_MASK(t) (1 << (t))
298
299 #define SCT_ISVIDEO(t) ((t) == SCT_MPEG2VIDEO || (t) == SCT_H264 || \
300 (t) == SCT_VP8 || (t) == SCT_HEVC || (t) == SCT_VP9)
301
302 #define SCT_ISAUDIO(t) ((t) == SCT_MPEG2AUDIO || (t) == SCT_AC3 || \
303 (t) == SCT_AAC || (t) == SCT_MP4A || \
304 (t) == SCT_EAC3 || (t) == SCT_VORBIS)
305
306 #define SCT_ISAV(t) (SCT_ISVIDEO(t) || SCT_ISAUDIO(t))
307
308 #define SCT_ISSUBTITLE(t) ((t) == SCT_TEXTSUB || (t) == SCT_DVBSUB)
309
310 /*
311 * Scales for signal status values
312 */
313 typedef enum {
314 SIGNAL_STATUS_SCALE_UNKNOWN = 0,
315 SIGNAL_STATUS_SCALE_RELATIVE, // value is unsigned, where 0 means 0% and 65535 means 100%
316 SIGNAL_STATUS_SCALE_DECIBEL // value is measured in dB * 1000
317 } signal_status_scale_t;
318
319 /**
320 * The signal status of a tuner
321 */
322 typedef struct signal_status {
323 const char *status_text; /* adapter status text */
324 int snr; /* signal/noise ratio */
325 signal_status_scale_t snr_scale;
326 int signal; /* signal strength */
327 signal_status_scale_t signal_scale;
328 int ber; /* bit error rate */
329 int unc; /* uncorrected blocks */
330 int ec_bit; /* error bit count */
331 int tc_bit; /* total bit count */
332 int ec_block; /* error block count */
333 int tc_block; /* total block count */
334 } signal_status_t;
335
336 /**
337 * Descramble info
338 */
339 typedef struct descramble_info {
340 uint16_t pid;
341 uint16_t caid;
342 uint32_t provid;
343 uint32_t ecmtime;
344 uint16_t hops;
345 char cardsystem[128];
346 char reader [128];
347 char from [128];
348 char protocol [128];
349 } descramble_info_t;
350
351 /**
352 *
353 */
354 typedef struct timeshift_status
355 {
356 int full;
357 int64_t shift;
358 int64_t pts_start;
359 int64_t pts_end;
360 } timeshift_status_t;
361
362 /**
363 * Streaming skip
364 */
365 typedef struct streaming_skip
366 {
367 enum {
368 SMT_SKIP_ERROR,
369 SMT_SKIP_REL_TIME,
370 SMT_SKIP_ABS_TIME,
371 SMT_SKIP_REL_SIZE,
372 SMT_SKIP_ABS_SIZE,
373 SMT_SKIP_LIVE
374 } type;
375 union {
376 off_t size;
377 int64_t time;
378 };
379 #if ENABLE_TIMESHIFT
380 timeshift_status_t timeshift;
381 #endif
382 } streaming_skip_t;
383
384
385 /**
386 * A streaming pad generates data.
387 * It has one or more streaming targets attached to it.
388 *
389 * We support two different streaming target types:
390 * One is callback driven and the other uses a queue + thread.
391 *
392 * Targets which already has a queueing intrastructure in place (such
393 * as HTSP) does not need any interim queues so it would be a waste. That
394 * is why we have the callback target.
395 *
396 */
397 typedef struct streaming_pad {
398 struct streaming_target_list sp_targets;
399 int sp_ntargets;
400 int sp_reject_filter;
401 } streaming_pad_t;
402
403
404 TAILQ_HEAD(streaming_message_queue, streaming_message);
405
406 /**
407 * Streaming messages types
408 */
409 typedef enum {
410
411 /**
412 * Packet with data.
413 *
414 * sm_data points to a th_pkt. th_pkt will be unref'ed when
415 * the message is destroyed
416 */
417 SMT_PACKET,
418
419 /**
420 * Stream grace period
421 *
422 * sm_code contains number of seconds to settle things down
423 */
424
425 SMT_GRACE,
426
427 /**
428 * Stream start
429 *
430 * sm_data points to a stream_start struct.
431 * See transport_build_stream_start()
432 */
433
434 SMT_START,
435
436 /**
437 * Service status
438 *
439 * Notification about status of source, see TSS_ flags
440 */
441 SMT_SERVICE_STATUS,
442
443 /**
444 * Signal status
445 *
446 * Notification about frontend signal status
447 */
448 SMT_SIGNAL_STATUS,
449
450 /**
451 * Descrambler info message
452 *
453 * Notification about descrambler
454 */
455 SMT_DESCRAMBLE_INFO,
456
457 /**
458 * Streaming stop.
459 *
460 * End of streaming. If sm_code is 0 this was a result to an
461 * unsubscription. Otherwise the reason was external and the
462 * subscription scheduler will attempt to start a new streaming
463 * session.
464 */
465 SMT_STOP,
466
467 /**
468 * Streaming unable to start.
469 *
470 * sm_code indicates reason. Scheduler will try to restart
471 */
472 SMT_NOSTART,
473
474 /**
475 * Streaming unable to start (non-fatal).
476 *
477 * sm_code indicates reason. Scheduler will try to restart
478 */
479 SMT_NOSTART_WARN,
480
481 /**
482 * Raw MPEG TS data
483 */
484 SMT_MPEGTS,
485
486 /**
487 * Internal message to exit receiver
488 */
489 SMT_EXIT,
490
491 /**
492 * Set stream speed
493 */
494 SMT_SPEED,
495
496 /**
497 * Skip the stream
498 */
499 SMT_SKIP,
500
501 /**
502 * Timeshift status
503 */
504 SMT_TIMESHIFT_STATUS,
505
506 } streaming_message_type_t;
507
508 #define SMT_TO_MASK(x) (1 << ((unsigned int)x))
509
510
511 #define SM_CODE_OK 0
512
513 #define SM_CODE_UNDEFINED_ERROR 1
514
515 #define SM_CODE_FORCE_OK 10
516
517 #define SM_CODE_SOURCE_RECONFIGURED 100
518 #define SM_CODE_BAD_SOURCE 101
519 #define SM_CODE_SOURCE_DELETED 102
520 #define SM_CODE_SUBSCRIPTION_OVERRIDDEN 103
521 #define SM_CODE_INVALID_TARGET 104
522 #define SM_CODE_USER_ACCESS 105
523 #define SM_CODE_USER_LIMIT 106
524 #define SM_CODE_WEAK_STREAM 107
525 #define SM_CODE_USER_REQUEST 108
526
527 #define SM_CODE_NO_FREE_ADAPTER 200
528 #define SM_CODE_MUX_NOT_ENABLED 201
529 #define SM_CODE_NOT_FREE 202
530 #define SM_CODE_TUNING_FAILED 203
531 #define SM_CODE_SVC_NOT_ENABLED 204
532 #define SM_CODE_BAD_SIGNAL 205
533 #define SM_CODE_NO_SOURCE 206
534 #define SM_CODE_NO_SERVICE 207
535 #define SM_CODE_NO_VALID_ADAPTER 208
536 #define SM_CODE_NO_ADAPTERS 209
537 #define SM_CODE_INVALID_SERVICE 210
538
539 #define SM_CODE_ABORTED 300
540
541 #define SM_CODE_NO_DESCRAMBLER 400
542 #define SM_CODE_NO_ACCESS 401
543 #define SM_CODE_NO_INPUT 402
544 #define SM_CODE_NO_SPACE 403
545
546 typedef enum
547 {
548 SIGNAL_UNKNOWN,
549 SIGNAL_GOOD,
550 SIGNAL_BAD,
551 SIGNAL_FAINT,
552 SIGNAL_NONE
553 } signal_state_t;
554
555 static struct strtab signal_statetab[] = {
556 { "GOOD", SIGNAL_GOOD },
557 { "BAD", SIGNAL_BAD },
558 { "FAINT", SIGNAL_FAINT },
559 { "NONE", SIGNAL_NONE },
560 };
561
signal2str(signal_state_t st)562 static inline const char * signal2str ( signal_state_t st )
563 {
564 const char *r = val2str(st, signal_statetab);
565 if (!r) r = "UNKNOWN";
566 return r;
567 }
568
569 /**
570 * Streaming messages are sent from the pad to its receivers
571 */
572 typedef struct streaming_message {
573 TAILQ_ENTRY(streaming_message) sm_link;
574 streaming_message_type_t sm_type;
575 #if ENABLE_TIMESHIFT
576 int64_t sm_time;
577 #endif
578 union {
579 void *sm_data;
580 int sm_code;
581 };
582 } streaming_message_t;
583
584 /**
585 * A streaming target receives data.
586 */
587
588 typedef void (st_callback_t)(void *opaque, streaming_message_t *sm);
589
590 typedef struct {
591 st_callback_t *st_cb;
592 htsmsg_t *(*st_info)(void *opaque, htsmsg_t *list);
593 } streaming_ops_t;
594
595 typedef struct streaming_target {
596 LIST_ENTRY(streaming_target) st_link;
597 streaming_pad_t *st_pad; /* Source we are linked to */
598
599 streaming_ops_t st_ops;
600 void *st_opaque;
601 int st_reject_filter;
602 } streaming_target_t;
603
604
605 /**
606 *
607 */
608 typedef struct streaming_queue {
609
610 streaming_target_t sq_st;
611
612 pthread_mutex_t sq_mutex; /* Protects sp_queue */
613 tvh_cond_t sq_cond; /* Condvar for signalling new packets */
614
615 size_t sq_maxsize; /* Max queue size (bytes) */
616 size_t sq_size; /* Actual queue size (bytes) - only data */
617
618 struct streaming_message_queue sq_queue;
619
620 } streaming_queue_t;
621
622
623 /**
624 * Simple dynamically growing buffer
625 */
626 typedef struct sbuf {
627 uint8_t *sb_data;
628 int sb_ptr;
629 int sb_size;
630 uint16_t sb_err;
631 uint8_t sb_bswap;
632 } sbuf_t;
633
634
635 streaming_component_type_t streaming_component_txt2type(const char *str);
636 const char *streaming_component_type2txt(streaming_component_type_t s);
637 streaming_component_type_t streaming_component_txt2type(const char *s);
638 const char *streaming_component_audio_type2desc(int audio_type);
639
640 #define MIN(a,b) ((a) < (b) ? (a) : (b))
641 #define MAX(a,b) ((a) > (b) ? (a) : (b))
642 #define MINMAX(a,mi,ma) MAX(mi, MIN(ma, a))
643 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
644
645 int sri_to_rate(int sri);
646 int rate_to_sri(int rate);
647
648 extern struct service_list all_transports;
649
650 extern void scopedunlock(pthread_mutex_t **mtxp);
651
652 #define scopedlock(mtx) \
653 pthread_mutex_t *scopedlock ## __LINE__ \
654 __attribute__((cleanup(scopedunlock))) = mtx; \
655 pthread_mutex_lock(scopedlock ## __LINE__);
656
657 #define scopedgloballock() scopedlock(&global_lock)
658
659 typedef struct th_pipe
660 {
661 int rd;
662 int wr;
663 } th_pipe_t;
664
665 void doexit(int x);
666
667 int tvhthread_create
668 (pthread_t *thread, const pthread_attr_t *attr,
669 void *(*start_routine) (void *), void *arg,
670 const char *name);
671
672 int tvhthread_renice(int value);
673
674 int tvh_mutex_timedlock(pthread_mutex_t *mutex, int64_t usec);
675
676 int tvh_cond_init(tvh_cond_t *cond);
677
678 int tvh_cond_destroy(tvh_cond_t *cond);
679
680 int tvh_cond_signal(tvh_cond_t *cond, int broadcast);
681
682 int tvh_cond_wait(tvh_cond_t *cond, pthread_mutex_t *mutex);
683
684 int tvh_cond_timedwait(tvh_cond_t *cond, pthread_mutex_t *mutex, int64_t monoclock);
685
686 int tvh_open(const char *pathname, int flags, mode_t mode);
687
688 int tvh_socket(int domain, int type, int protocol);
689
690 int tvh_pipe(int flags, th_pipe_t *pipe);
691
692 void tvh_pipe_close(th_pipe_t *pipe);
693
694 int tvh_write(int fd, const void *buf, size_t len);
695
696 FILE *tvh_fopen(const char *filename, const char *mode);
697
698 void hexdump(const char *pfx, const uint8_t *data, int len);
699
700 uint32_t tvh_crc32(const uint8_t *data, size_t datalen, uint32_t crc);
701
702 int base64_decode(uint8_t *out, const char *in, int out_size);
703
704 char *base64_encode(char *out, int out_size, const uint8_t *in, int in_size);
705
706 /* Calculate the output size needed to base64-encode x bytes. */
707 #define BASE64_SIZE(x) (((x)+2) / 3 * 4 + 1)
708
ts_rescale(int64_t ts,int tb)709 static inline int64_t ts_rescale(int64_t ts, int tb)
710 {
711 // return (ts * tb + (tb / 2)) / 90000LL;
712 return (ts * tb ) / 90000LL;
713 }
714
ts_rescale_inv(int64_t ts,int tb)715 static inline int64_t ts_rescale_inv(int64_t ts, int tb)
716 {
717 return (ts * 90000LL) / tb;
718 }
719
720 void sbuf_init(sbuf_t *sb);
721
722 void sbuf_init_fixed(sbuf_t *sb, int len);
723
724 void sbuf_free(sbuf_t *sb);
725
726 void sbuf_reset(sbuf_t *sb, int max_len);
727
728 void sbuf_reset_and_alloc(sbuf_t *sb, int len);
729
sbuf_steal_data(sbuf_t * sb)730 static inline void sbuf_steal_data(sbuf_t *sb)
731 {
732 sb->sb_data = NULL;
733 sb->sb_ptr = sb->sb_size = sb->sb_err = 0;
734 }
735
sbuf_err(sbuf_t * sb,int errors)736 static inline void sbuf_err(sbuf_t *sb, int errors)
737 {
738 sb->sb_err += errors;
739 }
740
741 void sbuf_alloc_(sbuf_t *sb, int len);
742
sbuf_alloc(sbuf_t * sb,int len)743 static inline void sbuf_alloc(sbuf_t *sb, int len)
744 {
745 if (sb->sb_ptr + len >= sb->sb_size)
746 sbuf_alloc_(sb, len);
747 }
748
749 void sbuf_realloc(sbuf_t *sb, int len);
750
751 void sbuf_append(sbuf_t *sb, const void *data, int len);
752
753 void sbuf_cut(sbuf_t *sb, int off);
754
755 void sbuf_put_be32(sbuf_t *sb, uint32_t u32);
756
757 void sbuf_put_be16(sbuf_t *sb, uint16_t u16);
758
759 void sbuf_put_byte(sbuf_t *sb, uint8_t u8);
760
761 ssize_t sbuf_read(sbuf_t *sb, int fd);
762
sbuf_peek_u8(sbuf_t * sb,int off)763 static inline uint8_t sbuf_peek_u8(sbuf_t *sb, int off) { return sb->sb_data[off]; }
sbuf_peek_s8(sbuf_t * sb,int off)764 static inline int8_t sbuf_peek_s8(sbuf_t *sb, int off) { return sb->sb_data[off]; }
765 uint16_t sbuf_peek_u16(sbuf_t *sb, int off);
sbuf_peek_s16(sbuf_t * sb,int off)766 static inline int16_t sbuf_peek_s16(sbuf_t *sb, int off) { return sbuf_peek_u16(sb, off); }
767 uint16_t sbuf_peek_u16le(sbuf_t *sb, int off);
sbuf_peek_s16le(sbuf_t * sb,int off)768 static inline int16_t sbuf_peek_s16le(sbuf_t *sb, int off) { return sbuf_peek_u16le(sb, off); }
769 uint16_t sbuf_peek_u16be(sbuf_t *sb, int off);
sbuf_peek_s16be(sbuf_t * sb,int off)770 static inline int16_t sbuf_peek_s16be(sbuf_t *sb, int off) { return sbuf_peek_u16be(sb, off); }
771 uint32_t sbuf_peek_u32(sbuf_t *sb, int off);
sbuf_peek_s32(sbuf_t * sb,int off)772 static inline int32_t sbuf_peek_s32(sbuf_t *sb, int off) { return sbuf_peek_u32(sb, off); }
773 uint32_t sbuf_peek_u32le(sbuf_t *sb, int off);
sbuf_peek_s32le(sbuf_t * sb,int off)774 static inline int32_t sbuf_peek_s32le(sbuf_t *sb, int off) { return sbuf_peek_u32le(sb, off); }
775 uint32_t sbuf_peek_u32be(sbuf_t *sb, int off);
sbuf_peek_s32be(sbuf_t * sb,int off)776 static inline int32_t sbuf_peek_s32be(sbuf_t *sb, int off) { return sbuf_peek_u32be(sb, off); }
sbuf_peek(sbuf_t * sb,int off)777 static inline uint8_t *sbuf_peek(sbuf_t *sb, int off) { return sb->sb_data + off; }
778
779 char *md5sum ( const char *str, int lowercase );
780
781 int makedirs ( int subsys, const char *path, int mode, int mstrict, gid_t gid, uid_t uid );
782
783 int rmtree ( const char *path );
784
785 char *regexp_escape ( const char *str );
786
787 #if ENABLE_ZLIB
788 uint8_t *tvh_gzip_inflate ( const uint8_t *data, size_t size, size_t orig );
789 uint8_t *tvh_gzip_deflate ( const uint8_t *data, size_t orig, size_t *size );
790 int tvh_gzip_deflate_fd ( int fd, const uint8_t *data, size_t orig, size_t *size, int speed );
791 int tvh_gzip_deflate_fd_header ( int fd, const uint8_t *data, size_t orig, size_t *size, int speed );
792 #endif
793
794 /* URL decoding */
795 char to_hex(char code);
796 char *url_encode(const char *str);
797 void http_deescape(char *str);
798
799 int mpegts_word_count(const uint8_t *tsb, int len, uint32_t mask);
800
801 int deferred_unlink(const char *filename, const char *rootdir);
802
803 void sha1_calc(uint8_t *dst, const uint8_t *d1, size_t d1_len, const uint8_t *d2, size_t d2_len);
804
805 uint32_t gcdU32(uint32_t a, uint32_t b);
deltaI32(int32_t a,int32_t b)806 static inline int32_t deltaI32(int32_t a, int32_t b) { return (a > b) ? (a - b) : (b - a); }
deltaU32(uint32_t a,uint32_t b)807 static inline uint32_t deltaU32(uint32_t a, uint32_t b) { return (a > b) ? (a - b) : (b - a); }
808
809 #define SKEL_DECLARE(name, type) type *name;
810 #define SKEL_ALLOC(name) do { if (!name) name = calloc(1, sizeof(*name)); } while (0)
811 #define SKEL_USED(name) do { name = NULL; } while (0)
812 #define SKEL_FREE(name) do { free(name); name = NULL; } while (0)
813
814 htsmsg_t *network_interfaces_enum(void *obj, const char *lang);
815
816 const char *gmtime2local(time_t gmt, char *buf, size_t buflen);
817
818 /* glibc wrapper */
819 #if ! ENABLE_QSORT_R
820 void
821 qsort_r(void *base, size_t nmemb, size_t size,
822 int (*cmp)(const void *, const void *, void *), void *aux);
823 #endif /* ENABLE_QSORT_R */
824
825 void tvh_qsort_r(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *, void *), void *arg);
826
827 /* printing */
828 #ifndef __WORDSIZE
829 # if ULONG_MAX == 0xffffffffffffffff
830 # define __WORDSIZE 64
831 # elif ULONG_MAX == 0xffffffff
832 # define __WORDSIZE 32
833 # endif /* ULONG_MAX */
834 #endif /* __WORDSIZE */
835
836 #if __WORDSIZE == 32 && defined(PLATFORM_FREEBSD)
837 #define PRItime_t "d"
838 #else
839 #define PRItime_t "ld"
840 #endif
841
842 #endif /* TVHEADEND_H */
843