Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
5fd473dbad
28 changed files with 1703 additions and 92 deletions
17
Makefile
17
Makefile
|
@ -32,7 +32,16 @@ CFLAGS += -Wmissing-prototypes -fms-extensions
|
|||
CFLAGS += -g -funsigned-char -O2
|
||||
CFLAGS += -D_FILE_OFFSET_BITS=64
|
||||
CFLAGS += -I${BUILDDIR} -I${ROOTDIR}/src -I${ROOTDIR}
|
||||
LDFLAGS += -lrt -ldl -lpthread -lm
|
||||
LDFLAGS += -ldl -lpthread -lm
|
||||
ifneq ($(PLATFORM), darwin)
|
||||
LDFLAGS += -lrt
|
||||
endif
|
||||
|
||||
ifeq ($(COMPILER), clang)
|
||||
CFLAGS += -Wno-microsoft -Qunused-arguments -Wno-unused-function
|
||||
CFLAGS += -Wno-unused-value -Wno-tautological-constant-out-of-range-compare
|
||||
CFLAGS += -Wno-parentheses-equality -Wno-incompatible-pointer-types
|
||||
endif
|
||||
|
||||
vpath %.c $(ROOTDIR)
|
||||
vpath %.h $(ROOTDIR)
|
||||
|
@ -117,7 +126,8 @@ SRCS = src/version.c \
|
|||
src/rtsp.c \
|
||||
src/fsmonitor.c \
|
||||
src/cron.c \
|
||||
src/esfilter.c
|
||||
src/esfilter.c \
|
||||
src/intlconv.c
|
||||
|
||||
SRCS-${CONFIG_UPNP} += \
|
||||
src/upnp.c
|
||||
|
@ -133,7 +143,8 @@ SRCS += \
|
|||
src/api/api_epg.c \
|
||||
src/api/api_epggrab.c \
|
||||
src/api/api_imagecache.c \
|
||||
src/api/api_esfilter.c
|
||||
src/api/api_esfilter.c \
|
||||
src/api/api_intlconv.c
|
||||
|
||||
SRCS += \
|
||||
src/parsers/parsers.c \
|
||||
|
|
19
configure
vendored
19
configure
vendored
|
@ -72,6 +72,16 @@ check_cc_header execinfo
|
|||
check_cc_option mmx
|
||||
check_cc_option sse2
|
||||
|
||||
if check_cc '
|
||||
#if !defined(__clang__)
|
||||
#error this is not clang
|
||||
#endif
|
||||
'; then
|
||||
COMPILER=clang
|
||||
else
|
||||
COMPILER=gcc
|
||||
fi
|
||||
|
||||
check_cc_snippet getloadavg '#include <stdlib.h>
|
||||
void test() { getloadavg(NULL,0); }'
|
||||
|
||||
|
@ -147,6 +157,13 @@ else
|
|||
die "SSL development support not found"
|
||||
fi
|
||||
|
||||
#
|
||||
# OS X
|
||||
#
|
||||
if [ ${PLATFORM} = "darwin" ]; then
|
||||
disable linuxdvb
|
||||
fi
|
||||
|
||||
#
|
||||
# DVB API
|
||||
#
|
||||
|
@ -296,7 +313,7 @@ fi
|
|||
#
|
||||
# kqueue
|
||||
#
|
||||
if [ ${PLATFORM} = "freebsd" ]; then
|
||||
if [ ${PLATFORM} = "freebsd" ] || [ ${PLATFORM} = "darwin" ]; then
|
||||
enable kqueue
|
||||
fi
|
||||
|
||||
|
|
|
@ -95,6 +95,9 @@
|
|||
|
||||
See also <i>Directory permissions</i> in <i>Subdirectory Options</i>.
|
||||
|
||||
<dt>Filename charset
|
||||
<dd>Character set for the created filename. Tvheadend will try to approximate characters to similarly looking ones.
|
||||
|
||||
<dt>Rewrite PAT in passthrough mode
|
||||
<dd>Rewrite the original Program Association Table to only include the active service. When this option is disabled, Tvheadend will write the original PAT as broadcast, which lists all services from the original multiplex.
|
||||
|
||||
|
|
|
@ -126,6 +126,7 @@ void api_init ( void )
|
|||
api_status_init();
|
||||
api_imagecache_init();
|
||||
api_esfilter_init();
|
||||
api_intlconv_init();
|
||||
}
|
||||
|
||||
void api_done ( void )
|
||||
|
|
|
@ -68,6 +68,7 @@ void api_epggrab_init ( void );
|
|||
void api_status_init ( void );
|
||||
void api_imagecache_init ( void );
|
||||
void api_esfilter_init ( void );
|
||||
void api_intlconv_init ( void );
|
||||
|
||||
/*
|
||||
* IDnode
|
||||
|
|
68
src/api/api_intlconv.c
Normal file
68
src/api/api_intlconv.c
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* API - international character conversions
|
||||
*
|
||||
* Copyright (C) 2014 Jaroslav Kysela
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __TVH_API_INTLCONV_H__
|
||||
#define __TVH_API_INTLCONV_H__
|
||||
|
||||
#include "tvheadend.h"
|
||||
#include "access.h"
|
||||
#include "api.h"
|
||||
#include "intlconv.h"
|
||||
|
||||
static int
|
||||
api_intlconv_charset_enum
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
const char **chrst;
|
||||
htsmsg_t *l, *e;
|
||||
|
||||
int _enum = htsmsg_get_bool_or_default(args, "enum", 0);
|
||||
|
||||
if (_enum) {
|
||||
l = htsmsg_create_list();
|
||||
chrst = intlconv_charsets;
|
||||
while (*chrst) {
|
||||
e = htsmsg_create_map();
|
||||
htsmsg_add_str(e, "key", *chrst);
|
||||
htsmsg_add_str(e, "val", *chrst);
|
||||
htsmsg_add_msg(l, NULL, e);
|
||||
chrst++;
|
||||
}
|
||||
*resp = htsmsg_create_map();
|
||||
htsmsg_add_msg(*resp, "entries", l);
|
||||
} else {
|
||||
// TODO: support full listing v enum
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void api_intlconv_init ( void )
|
||||
{
|
||||
static api_hook_t ah[] = {
|
||||
|
||||
{ "intlconv/charsets", ACCESS_ANONYMOUS, api_intlconv_charset_enum, NULL },
|
||||
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
api_register_all(ah);
|
||||
}
|
||||
|
||||
|
||||
#endif /* __TVH_API_INTLCONV_H__ */
|
|
@ -89,7 +89,7 @@ static void
|
|||
config_migrate_v1_dvb_svcs
|
||||
( const char *name, const char *netu, const char *muxu, htsmsg_t *channels )
|
||||
{
|
||||
uuid_t svcu;
|
||||
tvh_uuid_t svcu;
|
||||
htsmsg_t *c, *e, *svc;
|
||||
htsmsg_field_t *f;
|
||||
const char *str;
|
||||
|
@ -139,7 +139,7 @@ config_migrate_v1_dvb_network
|
|||
( const char *name, htsmsg_t *c, htsmsg_t *channels )
|
||||
{
|
||||
int i;
|
||||
uuid_t netu, muxu;
|
||||
tvh_uuid_t netu, muxu;
|
||||
htsmsg_t *e, *net, *mux, *tun;
|
||||
htsmsg_field_t *f;
|
||||
const char *str, *type;
|
||||
|
@ -321,7 +321,7 @@ config_migrate_v1_epggrab ( const char *path, htsmsg_t *channels )
|
|||
static void
|
||||
config_migrate_v1 ( void )
|
||||
{
|
||||
uuid_t netu, muxu, svcu, chnu;
|
||||
tvh_uuid_t netu, muxu, svcu, chnu;
|
||||
htsmsg_t *c, *m, *e, *l;
|
||||
htsmsg_field_t *f;
|
||||
uint32_t u32;
|
||||
|
@ -450,7 +450,7 @@ static void
|
|||
config_migrate_v2 ( void )
|
||||
{
|
||||
htsmsg_t *m;
|
||||
uuid_t u;
|
||||
tvh_uuid_t u;
|
||||
char src[1024], dst[1024];
|
||||
|
||||
/* Do we have IPTV config to migrate ? */
|
||||
|
|
|
@ -31,6 +31,8 @@ typedef struct dvr_config {
|
|||
char *dvr_storage;
|
||||
uint32_t dvr_retention_days;
|
||||
int dvr_flags;
|
||||
char *dvr_charset;
|
||||
char *dvr_charset_id;
|
||||
char *dvr_postproc;
|
||||
int dvr_extra_time_pre;
|
||||
int dvr_extra_time_post;
|
||||
|
@ -330,6 +332,8 @@ void dvr_entry_dec_ref(dvr_entry_t *de);
|
|||
|
||||
void dvr_storage_set(dvr_config_t *cfg, const char *storage);
|
||||
|
||||
void dvr_charset_set(dvr_config_t *cfg, const char *charset);
|
||||
|
||||
void dvr_container_set(dvr_config_t *cfg, const char *container);
|
||||
|
||||
void dvr_file_permissions_set(dvr_config_t *cfg, int permissions);
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "notify.h"
|
||||
#include "htsp_server.h"
|
||||
#include "streaming.h"
|
||||
#include "intlconv.h"
|
||||
|
||||
static int de_tally;
|
||||
|
||||
|
@ -163,6 +164,22 @@ dvr_entry_notify(dvr_entry_t *de)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
dvr_charset_update(dvr_config_t *cfg, const char *charset)
|
||||
{
|
||||
const char *s, *id;
|
||||
|
||||
free(cfg->dvr_charset);
|
||||
free(cfg->dvr_charset_id);
|
||||
s = charset ? charset : "ASCII";
|
||||
id = intlconv_charset_id(s, 1, 1);
|
||||
cfg->dvr_charset = strdup(s);
|
||||
cfg->dvr_charset_id = id ? strdup(id) : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -171,7 +188,6 @@ dvr_make_title(char *output, size_t outlen, dvr_entry_t *de)
|
|||
{
|
||||
struct tm tm;
|
||||
char buf[40];
|
||||
int i;
|
||||
dvr_config_t *cfg = dvr_config_find_by_name_default(de->de_config_name);
|
||||
|
||||
if(cfg->dvr_flags & DVR_CHANNEL_IN_TITLE)
|
||||
|
@ -219,19 +235,6 @@ dvr_make_title(char *output, size_t outlen, dvr_entry_t *de)
|
|||
".", "S%02d", NULL, "E%02d", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if(cfg->dvr_flags & DVR_CLEAN_TITLE) {
|
||||
for (i=0;i<strlen(output);i++) {
|
||||
if (
|
||||
output[i]<32 ||
|
||||
output[i]>122 ||
|
||||
output[i]==34 ||
|
||||
output[i]==39 ||
|
||||
output[i]==92 ||
|
||||
output[i]==58
|
||||
) output[i]='_';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1190,7 +1193,9 @@ dvr_init(void)
|
|||
if(!htsmsg_get_u32(m, "episode-before-date", &u32) && u32)
|
||||
cfg->dvr_flags |= DVR_EPISODE_BEFORE_DATE;
|
||||
|
||||
tvh_str_set(&cfg->dvr_postproc, htsmsg_get_str(m, "postproc"));
|
||||
dvr_charset_update(cfg, htsmsg_get_str(m, "charset"));
|
||||
|
||||
tvh_str_set(&cfg->dvr_postproc, htsmsg_get_str(m, "postproc"));
|
||||
}
|
||||
|
||||
htsmsg_destroy(l);
|
||||
|
@ -1245,6 +1250,8 @@ dvr_done(void)
|
|||
pthread_mutex_lock(&global_lock);
|
||||
while ((cfg = LIST_FIRST(&dvrconfigs)) != NULL) {
|
||||
LIST_REMOVE(cfg, config_link);
|
||||
free(cfg->dvr_charset_id);
|
||||
free(cfg->dvr_charset);
|
||||
free(cfg->dvr_storage);
|
||||
free(cfg->dvr_config_name);
|
||||
free(cfg);
|
||||
|
@ -1314,6 +1321,7 @@ dvr_config_create(const char *name)
|
|||
cfg->dvr_retention_days = 31;
|
||||
cfg->dvr_mc = MC_MATROSKA;
|
||||
cfg->dvr_flags = DVR_TAG_FILES | DVR_SKIP_COMMERCIALS;
|
||||
dvr_charset_update(cfg, "ASCII");
|
||||
|
||||
/* series link support */
|
||||
cfg->dvr_sl_brand_lock = 1; // use brand linking
|
||||
|
@ -1359,6 +1367,9 @@ dvr_config_delete(const char *name)
|
|||
cfg->dvr_config_name);
|
||||
hts_settings_remove("dvr/config%s", cfg->dvr_config_name);
|
||||
LIST_REMOVE(cfg, config_link);
|
||||
free(cfg->dvr_charset_id);
|
||||
free(cfg->dvr_charset);
|
||||
free(cfg->dvr_storage);
|
||||
free(cfg->dvr_config_name);
|
||||
free(cfg);
|
||||
|
||||
|
@ -1409,7 +1420,9 @@ dvr_save(dvr_config_t *cfg)
|
|||
htsmsg_add_u32(m, "skip-commercials", !!(cfg->dvr_flags & DVR_SKIP_COMMERCIALS));
|
||||
htsmsg_add_u32(m, "subtitle-in-title", !!(cfg->dvr_flags & DVR_SUBTITLE_IN_TITLE));
|
||||
htsmsg_add_u32(m, "episode-before-date", !!(cfg->dvr_flags & DVR_EPISODE_BEFORE_DATE));
|
||||
if(cfg->dvr_postproc != NULL)
|
||||
if (cfg->dvr_charset != NULL)
|
||||
htsmsg_add_str(m, "charset", cfg->dvr_charset);
|
||||
if (cfg->dvr_postproc != NULL)
|
||||
htsmsg_add_str(m, "postproc", cfg->dvr_postproc);
|
||||
|
||||
hts_settings_save(m, "dvr/config%s", cfg->dvr_config_name);
|
||||
|
@ -1431,6 +1444,19 @@ dvr_storage_set(dvr_config_t *cfg, const char *storage)
|
|||
dvr_save(cfg);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
dvr_charset_set(dvr_config_t *cfg, const char *charset)
|
||||
{
|
||||
if(cfg->dvr_charset != NULL && !strcmp(cfg->dvr_charset, charset))
|
||||
return;
|
||||
|
||||
dvr_charset_update(cfg, charset);
|
||||
dvr_save(cfg);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "plumbing/globalheaders.h"
|
||||
#include "htsp_server.h"
|
||||
#include "atomic.h"
|
||||
#include "intlconv.h"
|
||||
|
||||
#include "muxer.h"
|
||||
|
||||
|
@ -122,11 +123,27 @@ dvr_rec_unsubscribe(dvr_entry_t *de, int stopcode)
|
|||
/**
|
||||
* Replace various chars with a dash
|
||||
*/
|
||||
static void
|
||||
cleanupfilename(char *s, int dvr_flags)
|
||||
static char *
|
||||
cleanup_filename(char *s, dvr_config_t *cfg)
|
||||
{
|
||||
int i, len = strlen(s);
|
||||
for(i = 0; i < len; i++) {
|
||||
int i, len = strlen(s), dvr_flags = cfg->dvr_flags;
|
||||
char *s1;
|
||||
|
||||
s1 = intlconv_utf8safestr(cfg->dvr_charset_id, s, len * 2);
|
||||
if (s1 == NULL) {
|
||||
tvherror("dvr", "Unsupported charset %s using ASCII", cfg->dvr_charset);
|
||||
s1 = intlconv_utf8safestr(intlconv_charset_id("ASCII", 1, 1),
|
||||
s, len * 2);
|
||||
if (s1 == NULL)
|
||||
return NULL;
|
||||
}
|
||||
s = s1;
|
||||
|
||||
/* Do not create hidden files */
|
||||
if (s[0] == '.')
|
||||
s[0] = '_';
|
||||
|
||||
for (i = 0, len = strlen(s); i < len; i++) {
|
||||
|
||||
if(s[i] == '/')
|
||||
s[i] = '-';
|
||||
|
@ -138,8 +155,10 @@ cleanupfilename(char *s, int dvr_flags)
|
|||
else if((dvr_flags & DVR_CLEAN_TITLE) &&
|
||||
((s[i] < 32) || (s[i] > 122) ||
|
||||
(strchr("/:\\<>|*?'\"", s[i]) != NULL)))
|
||||
s[i] = '-';
|
||||
s[i] = '_';
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -152,65 +171,64 @@ cleanupfilename(char *s, int dvr_flags)
|
|||
static int
|
||||
pvr_generate_filename(dvr_entry_t *de, const streaming_start_t *ss)
|
||||
{
|
||||
char fullname[1000];
|
||||
char path[500];
|
||||
char fullname[PATH_MAX];
|
||||
char path[PATH_MAX];
|
||||
int tally = 0;
|
||||
struct stat st;
|
||||
char filename[1000];
|
||||
char *filename, *s;
|
||||
struct tm tm;
|
||||
dvr_config_t *cfg = dvr_config_find_by_name_default(de->de_config_name);
|
||||
|
||||
dvr_make_title(filename, sizeof(filename), de);
|
||||
cleanupfilename(filename,cfg->dvr_flags);
|
||||
|
||||
snprintf(path, sizeof(path), "%s", cfg->dvr_storage);
|
||||
strncpy(path, cfg->dvr_storage, sizeof(path));
|
||||
path[sizeof(path)-1] = '\0';
|
||||
|
||||
/* Remove trailing slash */
|
||||
|
||||
if (path[strlen(path)-1] == '/')
|
||||
path[strlen(path)-1] = '\0';
|
||||
|
||||
/* Append per-day directory */
|
||||
|
||||
if(cfg->dvr_flags & DVR_DIR_PER_DAY) {
|
||||
if (cfg->dvr_flags & DVR_DIR_PER_DAY) {
|
||||
localtime_r(&de->de_start, &tm);
|
||||
strftime(fullname, sizeof(fullname), "%F", &tm);
|
||||
cleanupfilename(fullname,cfg->dvr_flags);
|
||||
snprintf(path + strlen(path), sizeof(path) - strlen(path),
|
||||
"/%s", fullname);
|
||||
s = cleanup_filename(fullname, cfg);
|
||||
if (s == NULL)
|
||||
return -1;
|
||||
snprintf(path + strlen(path), sizeof(path) - strlen(path), "/%s", s);
|
||||
free(s);
|
||||
}
|
||||
|
||||
/* Append per-channel directory */
|
||||
|
||||
if(cfg->dvr_flags & DVR_DIR_PER_CHANNEL) {
|
||||
|
||||
if (cfg->dvr_flags & DVR_DIR_PER_CHANNEL) {
|
||||
char *chname = strdup(DVR_CH_NAME(de));
|
||||
cleanupfilename(chname,cfg->dvr_flags);
|
||||
snprintf(path + strlen(path), sizeof(path) - strlen(path),
|
||||
"/%s", chname);
|
||||
s = cleanup_filename(chname, cfg);
|
||||
free(chname);
|
||||
if (s == NULL)
|
||||
return -1;
|
||||
snprintf(path + strlen(path), sizeof(path) - strlen(path), "/%s", s);
|
||||
free(s);
|
||||
}
|
||||
|
||||
// TODO: per-brand, per-season
|
||||
|
||||
/* Append per-title directory */
|
||||
|
||||
if(cfg->dvr_flags & DVR_DIR_PER_TITLE) {
|
||||
|
||||
if (cfg->dvr_flags & DVR_DIR_PER_TITLE) {
|
||||
char *title = strdup(lang_str_get(de->de_title, NULL));
|
||||
cleanupfilename(title,cfg->dvr_flags);
|
||||
snprintf(path + strlen(path), sizeof(path) - strlen(path),
|
||||
"/%s", title);
|
||||
s = cleanup_filename(title, cfg);
|
||||
free(title);
|
||||
if (s == NULL)
|
||||
return -1;
|
||||
snprintf(path + strlen(path), sizeof(path) - strlen(path), "/%s", s);
|
||||
free(s);
|
||||
}
|
||||
|
||||
if(makedirs(path, cfg->dvr_muxcnf.m_directory_permissions) != 0) {
|
||||
if (makedirs(path, cfg->dvr_muxcnf.m_directory_permissions) != 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Construct final name */
|
||||
|
||||
dvr_make_title(fullname, sizeof(fullname), de);
|
||||
filename = cleanup_filename(fullname, cfg);
|
||||
if (filename == NULL)
|
||||
return -1;
|
||||
snprintf(fullname, sizeof(fullname), "%s/%s.%s",
|
||||
path, filename, muxer_suffix(de->de_mux, ss));
|
||||
|
||||
|
@ -229,6 +247,7 @@ pvr_generate_filename(dvr_entry_t *de, const streaming_start_t *ss)
|
|||
snprintf(fullname, sizeof(fullname), "%s/%s-%d.%s",
|
||||
path, filename, tally, muxer_suffix(de->de_mux, ss));
|
||||
}
|
||||
free(filename);
|
||||
|
||||
tvh_str_set(&de->de_filename, fullname);
|
||||
|
||||
|
|
|
@ -766,9 +766,9 @@ http_client_data_received( http_client_t *hc, char *buf, ssize_t len, int hdr )
|
|||
return 0;
|
||||
}
|
||||
|
||||
csize = hc->hc_csize < 0 ? 0 : hc->hc_csize;
|
||||
csize = hc->hc_csize == (size_t) -1 ? 0 : hc->hc_csize;
|
||||
l = len;
|
||||
if (hc->hc_csize && hc->hc_csize != -1 && hc->hc_rpos > csize) {
|
||||
if (hc->hc_csize && hc->hc_csize != (size_t) -1 && hc->hc_rpos > csize) {
|
||||
l2 = hc->hc_rpos - csize;
|
||||
if (l2 < l)
|
||||
l = l2;
|
||||
|
@ -801,7 +801,7 @@ int
|
|||
http_client_run( http_client_t *hc )
|
||||
{
|
||||
char *buf, *saveptr, *argv[3], *d, *p;
|
||||
http_ver_t ver;
|
||||
int ver;
|
||||
ssize_t r;
|
||||
size_t len;
|
||||
int res;
|
||||
|
|
|
@ -102,7 +102,7 @@ idnode_insert(idnode_t *in, const char *uuid, const idclass_t *class)
|
|||
{
|
||||
idnode_t *c;
|
||||
lock_assert(&global_lock);
|
||||
uuid_t u;
|
||||
tvh_uuid_t u;
|
||||
if (uuid_init_bin(&u, uuid))
|
||||
return -1;
|
||||
memcpy(in->in_uuid, u.bin, sizeof(in->in_uuid));
|
||||
|
@ -192,7 +192,7 @@ idnode_get_short_uuid (const idnode_t *in)
|
|||
const char *
|
||||
idnode_uuid_as_str(const idnode_t *in)
|
||||
{
|
||||
static uuid_t ret[16];
|
||||
static tvh_uuid_t ret[16];
|
||||
static uint8_t p = 0;
|
||||
bin2hex(ret[p].hex, sizeof(ret[p].hex), in->in_uuid, sizeof(in->in_uuid));
|
||||
const char *s = ret[p].hex;
|
||||
|
|
|
@ -187,7 +187,7 @@ linuxdvb_adapter_add ( const char *path )
|
|||
extern int linuxdvb_adapter_mask;
|
||||
int a, i, j, r, fd;
|
||||
char fe_path[512], dmx_path[512], dvr_path[512];
|
||||
uuid_t uuid;
|
||||
tvh_uuid_t uuid;
|
||||
linuxdvb_adapter_t *la = NULL;
|
||||
struct dvb_frontend_info dfi;
|
||||
SHA_CTX sha1;
|
||||
|
|
|
@ -256,7 +256,7 @@ satip_device_calc_bin_uuid( uint8_t *uuid, const char *satip_uuid )
|
|||
}
|
||||
|
||||
static void
|
||||
satip_device_calc_uuid( uuid_t *uuid, const char *satip_uuid )
|
||||
satip_device_calc_uuid( tvh_uuid_t *uuid, const char *satip_uuid )
|
||||
{
|
||||
uint8_t uuidbin[20];
|
||||
|
||||
|
@ -287,7 +287,7 @@ static satip_device_t *
|
|||
satip_device_create( satip_device_info_t *info )
|
||||
{
|
||||
satip_device_t *sd = calloc(1, sizeof(satip_device_t));
|
||||
uuid_t uuid;
|
||||
tvh_uuid_t uuid;
|
||||
htsmsg_t *conf = NULL, *feconf = NULL;
|
||||
char *argv[10];
|
||||
int i, j, n, m, fenum, t2, save = 0;
|
||||
|
|
1336
src/intlconv.c
Normal file
1336
src/intlconv.c
Normal file
File diff suppressed because it is too large
Load diff
39
src/intlconv.h
Normal file
39
src/intlconv.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* tvheadend, iconv interface
|
||||
* Copyright (C) 2014 Jaroslav Kysela
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef INTLCONV_H_
|
||||
#define INTLCONV_H_
|
||||
|
||||
extern const char *intlconv_charsets[];
|
||||
|
||||
void intlconv_init( void );
|
||||
void intlconv_done( void );
|
||||
char *
|
||||
intlconv_charset_id( const char *charset,
|
||||
int transil,
|
||||
int ignore_bad_chars );
|
||||
ssize_t
|
||||
intlconv_utf8( char *dst, size_t dst_size,
|
||||
const char *dst_charset_id,
|
||||
const char *src_utf8 );
|
||||
char *
|
||||
intlconv_utf8safestr( const char *dst_charset_id,
|
||||
const char *src_utf8,
|
||||
size_t max_size );
|
||||
|
||||
#endif /* INTLCONV_H_ */
|
|
@ -62,6 +62,7 @@
|
|||
#include "fsmonitor.h"
|
||||
#include "lang_codes.h"
|
||||
#include "esfilter.h"
|
||||
#include "intlconv.h"
|
||||
#if ENABLE_LIBAV
|
||||
#include "libav.h"
|
||||
#include "plumbing/transcoding.h"
|
||||
|
@ -755,6 +756,8 @@ main(int argc, char **argv)
|
|||
/**
|
||||
* Initialize subsystems
|
||||
*/
|
||||
|
||||
intlconv_init();
|
||||
|
||||
api_init();
|
||||
|
||||
|
@ -880,6 +883,7 @@ main(int argc, char **argv)
|
|||
tvhftrace("main", dvb_done);
|
||||
tvhftrace("main", lang_str_done);
|
||||
tvhftrace("main", esfilter_done);
|
||||
tvhftrace("main", intlconv_done);
|
||||
tvhftrace("main", urlparse_done);
|
||||
|
||||
tvhlog(LOG_NOTICE, "STOP", "Exiting HTS Tvheadend");
|
||||
|
|
|
@ -28,6 +28,10 @@
|
|||
#include "muxer/muxer_libav.h"
|
||||
#endif
|
||||
|
||||
#if defined(PLATFORM_DARWIN)
|
||||
#define fdatasync(fd) fcntl(fd, F_FULLFSYNC)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Mime type for containers containing only audio
|
||||
*/
|
||||
|
@ -458,7 +462,11 @@ muxer_cache_update(muxer_t *m, int fd, off_t pos, size_t size)
|
|||
fdatasync(fd);
|
||||
/* fall through */
|
||||
case MC_CACHE_DONTKEEP:
|
||||
#if defined(PLATFORM_DARWIN)
|
||||
fcntl(fd, F_NOCACHE, 1);
|
||||
#else
|
||||
posix_fadvise(fd, pos, size, POSIX_FADV_DONTNEED);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
|
|
22
src/trap.c
22
src/trap.c
|
@ -20,7 +20,7 @@
|
|||
|
||||
char tvh_binshasum[20];
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
#if (defined(__i386__) || defined(__x86_64__)) && !defined(PLATFORM_DARWIN)
|
||||
|
||||
// Only do this on x86 for now
|
||||
|
||||
|
@ -315,6 +315,26 @@ trap_init(const char *ver)
|
|||
sigprocmask(SIG_UNBLOCK, &m, NULL);
|
||||
}
|
||||
|
||||
#elif defined(PLATFORM_DARWIN)
|
||||
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
void
|
||||
trap_init(const char *ver)
|
||||
{
|
||||
sigset_t m;
|
||||
|
||||
sigemptyset(&m);
|
||||
sigaddset(&m, SIGSEGV);
|
||||
sigaddset(&m, SIGBUS);
|
||||
sigaddset(&m, SIGILL);
|
||||
sigaddset(&m, SIGABRT);
|
||||
sigaddset(&m, SIGFPE);
|
||||
|
||||
sigprocmask(SIG_UNBLOCK, &m, NULL);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void
|
||||
|
|
|
@ -500,6 +500,20 @@ int tvh_str_update(char **strp, const char *src);
|
|||
#define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_DARWIN
|
||||
#define CLOCK_MONOTONIC 0
|
||||
#define CLOCK_REALTIME 0
|
||||
|
||||
static inline int clock_gettime(int clk_id, struct timespec* t) {
|
||||
struct timeval now;
|
||||
int rv = gettimeofday(&now, NULL);
|
||||
if (rv) return rv;
|
||||
t->tv_sec = now.tv_sec;
|
||||
t->tv_nsec = now.tv_usec * 1000;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int64_t
|
||||
getmonoclock(void)
|
||||
{
|
||||
|
@ -677,8 +691,13 @@ void tvh_qsort_r(void *base, size_t nmemb, size_t size, int (*compar)(const void
|
|||
#endif
|
||||
#define PRIslongword_t "ld"
|
||||
#define PRIulongword_t "lu"
|
||||
#if defined(PLATFORM_DARWIN)
|
||||
#define PRIsize_t PRIulongword_t
|
||||
#define PRIssize_t PRIslongword_t
|
||||
#else
|
||||
#define PRIsize_t PRIuword_t
|
||||
#define PRIssize_t PRIsword_t
|
||||
#endif
|
||||
#if __WORDSIZE == 32 && defined(PLATFORM_FREEBSD)
|
||||
#define PRItime_t PRIsword_t
|
||||
#else
|
||||
|
|
|
@ -147,7 +147,7 @@ upnp_thread( void *aux )
|
|||
inet_ntop(ip.ss_family, IP_IN_ADDR(ip), tbuf, sizeof(tbuf));
|
||||
tvhtrace("upnp", "%s - received data from %s:%hu [size=%zi]",
|
||||
conn == multicast ? "multicast" : "unicast",
|
||||
tbuf, IP_PORT(ip), size);
|
||||
tbuf, (unsigned short) IP_PORT(ip), size);
|
||||
tvhlog_hexdump("upnp", buf, size);
|
||||
}
|
||||
#endif
|
||||
|
|
16
src/uuid.c
16
src/uuid.c
|
@ -103,9 +103,9 @@ uuid_init ( void )
|
|||
|
||||
/* Initialise binary */
|
||||
int
|
||||
uuid_init_bin ( uuid_t *u, const char *str )
|
||||
uuid_init_bin ( tvh_uuid_t *u, const char *str )
|
||||
{
|
||||
memset(u, 0, sizeof(uuid_t));
|
||||
memset(u, 0, sizeof(tvh_uuid_t));
|
||||
if (str) {
|
||||
return hex2bin(u->bin, sizeof(u->bin), str);
|
||||
} else if (read(fd, u->bin, sizeof(u->bin)) != sizeof(u->bin)) {
|
||||
|
@ -117,9 +117,9 @@ uuid_init_bin ( uuid_t *u, const char *str )
|
|||
|
||||
/* Initialise hex string */
|
||||
int
|
||||
uuid_init_hex ( uuid_t *u, const char *str )
|
||||
uuid_init_hex ( tvh_uuid_t *u, const char *str )
|
||||
{
|
||||
uuid_t tmp;
|
||||
tvh_uuid_t tmp;
|
||||
if (uuid_init_bin(&tmp, str))
|
||||
return 1;
|
||||
return uuid_bin2hex(&tmp, u);
|
||||
|
@ -127,9 +127,9 @@ uuid_init_hex ( uuid_t *u, const char *str )
|
|||
|
||||
/* Convert bin to hex string */
|
||||
int
|
||||
uuid_bin2hex ( const uuid_t *a, uuid_t *b )
|
||||
uuid_bin2hex ( const tvh_uuid_t *a, tvh_uuid_t *b )
|
||||
{
|
||||
uuid_t tmp;
|
||||
tvh_uuid_t tmp;
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
bin2hex(tmp.hex, sizeof(tmp.hex), a->bin, sizeof(a->bin));
|
||||
memcpy(b, &tmp, sizeof(tmp));
|
||||
|
@ -138,9 +138,9 @@ uuid_bin2hex ( const uuid_t *a, uuid_t *b )
|
|||
|
||||
/* Convert hex string to bin (in place) */
|
||||
int
|
||||
uuid_hex2bin ( const uuid_t *a, uuid_t *b )
|
||||
uuid_hex2bin ( const tvh_uuid_t *a, tvh_uuid_t *b )
|
||||
{
|
||||
uuid_t tmp;
|
||||
tvh_uuid_t tmp;
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
if (hex2bin(tmp.bin, sizeof(tmp.bin), a->hex))
|
||||
return 1;
|
||||
|
|
10
src/uuid.h
10
src/uuid.h
|
@ -31,30 +31,30 @@ typedef struct uuid {
|
|||
uint8_t bin[UUID_BIN_SIZE];
|
||||
char hex[UUID_HEX_SIZE];
|
||||
};
|
||||
} uuid_t;
|
||||
} tvh_uuid_t;
|
||||
|
||||
/* Initialise subsystem */
|
||||
void uuid_init ( void );
|
||||
|
||||
/* Initialise binary */
|
||||
int uuid_init_bin ( uuid_t *u, const char *str );
|
||||
int uuid_init_bin ( tvh_uuid_t *u, const char *str );
|
||||
|
||||
/* Initialise hex string */
|
||||
int uuid_init_hex ( uuid_t *u, const char *str );
|
||||
int uuid_init_hex ( tvh_uuid_t *u, const char *str );
|
||||
|
||||
/**
|
||||
* Convert bin to hex string
|
||||
*
|
||||
* Note: conversion is done such that a and b can be the same
|
||||
*/
|
||||
int uuid_bin2hex ( const uuid_t *a, uuid_t *b );
|
||||
int uuid_bin2hex ( const tvh_uuid_t *a, tvh_uuid_t *b );
|
||||
|
||||
/**
|
||||
* Convert hex string to bin (in place)
|
||||
*
|
||||
* Note: conversion is done such that a and b can be the same
|
||||
*/
|
||||
int uuid_hex2bin ( const uuid_t *a, uuid_t *b );
|
||||
int uuid_hex2bin ( const tvh_uuid_t *a, tvh_uuid_t *b );
|
||||
|
||||
/**
|
||||
* Hex string to binary
|
||||
|
|
|
@ -1127,6 +1127,7 @@ extjs_dvr(http_connection_t *hc, const char *remain, void *opaque)
|
|||
|
||||
r = htsmsg_create_map();
|
||||
htsmsg_add_str(r, "storage", cfg->dvr_storage);
|
||||
htsmsg_add_str(r, "charset", cfg->dvr_charset);
|
||||
htsmsg_add_str(r, "container", muxer_container_type2txt(cfg->dvr_mc));
|
||||
|
||||
/* Convert integer permissions to an octal-format 0xxx string and store it in the config file */
|
||||
|
@ -1174,7 +1175,10 @@ extjs_dvr(http_connection_t *hc, const char *remain, void *opaque)
|
|||
if((s = http_arg_get(&hc->hc_req_args, "storage")) != NULL)
|
||||
dvr_storage_set(cfg,s);
|
||||
|
||||
if((s = http_arg_get(&hc->hc_req_args, "container")) != NULL)
|
||||
if((s = http_arg_get(&hc->hc_req_args, "charset")) != NULL)
|
||||
dvr_charset_set(cfg,s);
|
||||
|
||||
if((s = http_arg_get(&hc->hc_req_args, "container")) != NULL)
|
||||
dvr_container_set(cfg,s);
|
||||
|
||||
/*
|
||||
|
@ -1182,13 +1186,13 @@ extjs_dvr(http_connection_t *hc, const char *remain, void *opaque)
|
|||
* Note no checking that strtol won't overflow int - this should never happen with three-digit numbers
|
||||
*/
|
||||
|
||||
if((s = http_arg_get(&hc->hc_req_args, "filePermissions")) != NULL)
|
||||
if((s = http_arg_get(&hc->hc_req_args, "filePermissions")) != NULL)
|
||||
dvr_file_permissions_set(cfg,(int)strtol(s,NULL,0));
|
||||
|
||||
if((s = http_arg_get(&hc->hc_req_args, "dirPermissions")) != NULL)
|
||||
if((s = http_arg_get(&hc->hc_req_args, "dirPermissions")) != NULL)
|
||||
dvr_directory_permissions_set(cfg,(int)strtol(s,NULL,0));
|
||||
|
||||
if((s = http_arg_get(&hc->hc_req_args, "cache")) != NULL)
|
||||
if((s = http_arg_get(&hc->hc_req_args, "cache")) != NULL)
|
||||
dvr_mux_cache_set(cfg,atoi(s));
|
||||
|
||||
if((s = http_arg_get(&hc->hc_req_args, "postproc")) != NULL)
|
||||
|
@ -1197,11 +1201,11 @@ extjs_dvr(http_connection_t *hc, const char *remain, void *opaque)
|
|||
if((s = http_arg_get(&hc->hc_req_args, "retention")) != NULL)
|
||||
dvr_retention_set(cfg,atoi(s));
|
||||
|
||||
if((s = http_arg_get(&hc->hc_req_args, "preExtraTime")) != NULL)
|
||||
dvr_extra_time_pre_set(cfg,atoi(s));
|
||||
if((s = http_arg_get(&hc->hc_req_args, "preExtraTime")) != NULL)
|
||||
dvr_extra_time_pre_set(cfg,atoi(s));
|
||||
|
||||
if((s = http_arg_get(&hc->hc_req_args, "postExtraTime")) != NULL)
|
||||
dvr_extra_time_post_set(cfg,atoi(s));
|
||||
if((s = http_arg_get(&hc->hc_req_args, "postExtraTime")) != NULL)
|
||||
dvr_extra_time_post_set(cfg,atoi(s));
|
||||
|
||||
if(http_arg_get(&hc->hc_req_args, "dayDirs") != NULL)
|
||||
flags |= DVR_DIR_PER_DAY;
|
||||
|
@ -1319,6 +1323,7 @@ extjs_dvrlist(http_connection_t *hc, const char *remain, void *opaque,
|
|||
|
||||
htsmsg_add_str(m, "channel", DVR_CH_NAME(de));
|
||||
if(de->de_channel != NULL) {
|
||||
htsmsg_add_str(m, "channelid", channel_get_uuid(de->de_channel));
|
||||
if (de->de_channel->ch_icon)
|
||||
htsmsg_add_imageurl(m, "chicon", "imagecache/%d",
|
||||
de->de_channel->ch_icon);
|
||||
|
|
|
@ -27,6 +27,18 @@ tvheadend.containers = new Ext.data.JsonStore({
|
|||
});
|
||||
|
||||
//For the cache configuration
|
||||
tvheadend.charsets = new Ext.data.JsonStore({
|
||||
autoLoad: true,
|
||||
root: 'entries',
|
||||
fields: ['key', 'val'],
|
||||
id: 'key',
|
||||
url: 'api/intlconv/charsets',
|
||||
baseParams: {
|
||||
enum: 1
|
||||
}
|
||||
});
|
||||
|
||||
//For the charset configuration
|
||||
tvheadend.caches = new Ext.data.JsonStore({
|
||||
autoLoad: true,
|
||||
root: 'entries',
|
||||
|
@ -784,7 +796,7 @@ tvheadend.dvrsettings = function() {
|
|||
var confreader = new Ext.data.JsonReader({
|
||||
root: 'dvrSettings'
|
||||
}, ['storage', 'filePermissions', 'dirPermissions', 'postproc', 'retention', 'dayDirs', 'channelDirs',
|
||||
'channelInTitle', 'container', 'cache', 'dateInTitle', 'timeInTitle',
|
||||
'channelInTitle', 'container', 'cache', 'charset', 'dateInTitle', 'timeInTitle',
|
||||
'preExtraTime', 'postExtraTime', 'whitespaceInTitle', 'titleDirs',
|
||||
'episodeInTitle', 'cleanTitle', 'tagFiles', 'commSkip', 'subtitleInTitle',
|
||||
'episodeBeforeDate', 'rewritePAT', 'rewritePMT']);
|
||||
|
@ -880,6 +892,17 @@ tvheadend.dvrsettings = function() {
|
|||
name: 'filePermissions'
|
||||
});
|
||||
|
||||
var charset = new Ext.form.ComboBox({
|
||||
store: tvheadend.charsets,
|
||||
fieldLabel: 'Filename charset',
|
||||
triggerAction: 'all',
|
||||
displayField: 'val',
|
||||
valueField: 'key',
|
||||
editable: false,
|
||||
width: 200,
|
||||
hiddenName: 'charset'
|
||||
});
|
||||
|
||||
/* TO DO - Add 'override user umask?' option, then trigger fchmod in mkmux.c, muxer_pass.c after file created */
|
||||
|
||||
var PATrewrite = new Ext.form.Checkbox({
|
||||
|
@ -992,7 +1015,7 @@ tvheadend.dvrsettings = function() {
|
|||
autoHeight: true,
|
||||
collapsible: true,
|
||||
animCollapse: true,
|
||||
items: [recordingPath, recordingPermissions, PATrewrite, PMTrewrite, tagMetadata, skipCommercials]
|
||||
items: [recordingPath, recordingPermissions, charset, PATrewrite, PMTrewrite, tagMetadata, skipCommercials]
|
||||
});
|
||||
|
||||
/* Sub-Panel - Directory operations */
|
||||
|
|
|
@ -930,7 +930,7 @@ page_dvrfile(http_connection_t *hc, const char *remain, void *opaque)
|
|||
off_t content_len, file_start, file_end, chunk;
|
||||
#if defined(PLATFORM_LINUX)
|
||||
ssize_t r;
|
||||
#elif defined(PLATFORM_FREEBSD)
|
||||
#elif defined(PLATFORM_FREEBSD) || defined(PLATFORM_DARWIN)
|
||||
off_t r;
|
||||
#endif
|
||||
|
||||
|
@ -1017,6 +1017,9 @@ page_dvrfile(http_connection_t *hc, const char *remain, void *opaque)
|
|||
r = sendfile(hc->hc_fd, fd, NULL, chunk);
|
||||
#elif defined(PLATFORM_FREEBSD)
|
||||
sendfile(fd, hc->hc_fd, 0, chunk, NULL, &r, 0);
|
||||
#elif defined(PLATFORM_DARWIN)
|
||||
r = chunk;
|
||||
sendfile(fd, hc->hc_fd, 0, NULL, &r, 0);
|
||||
#endif
|
||||
if(r == -1) {
|
||||
close(fd);
|
||||
|
|
|
@ -109,6 +109,8 @@ thread_wrapper ( void *p )
|
|||
#elif defined(PLATFORM_FREEBSD)
|
||||
/* Set name of thread */
|
||||
pthread_set_name_np(pthread_self(), ts->name);
|
||||
#elif defined(PLATFORM_DARWIN)
|
||||
pthread_setname_np(ts->name);
|
||||
#endif
|
||||
|
||||
sigemptyset(&set);
|
||||
|
|
|
@ -470,9 +470,11 @@ function write_config
|
|||
CONFIGURE_ARGS = ${CONFIGURE_ARGS}
|
||||
ROOTDIR ?= ${ROOTDIR}
|
||||
BUILDDIR ?= ${BUILDDIR}
|
||||
PLATFORM ?= ${PLATFORM}
|
||||
OSENV ?= ${OSENV}
|
||||
ARCH ?= ${ARCH}
|
||||
CPU ?= ${CPU}
|
||||
COMPILER ?= ${COMPILER}
|
||||
ifeq (\$(origin CC),default)
|
||||
CC = ${CC}
|
||||
endif
|
||||
|
|
Loading…
Add table
Reference in a new issue