Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Ian 2014-05-26 23:13:28 +01:00
commit 5fd473dbad
28 changed files with 1703 additions and 92 deletions

View file

@ -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
View file

@ -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

View file

@ -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.

View file

@ -126,6 +126,7 @@ void api_init ( void )
api_status_init();
api_imagecache_init();
api_esfilter_init();
api_intlconv_init();
}
void api_done ( void )

View file

@ -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
View 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__ */

View file

@ -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 ? */

View file

@ -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);

View file

@ -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);
}
/**
*
*/

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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

File diff suppressed because it is too large Load diff

39
src/intlconv.h Normal file
View 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_ */

View file

@ -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");

View file

@ -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();

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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);

View file

@ -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 */

View file

@ -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);

View file

@ -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);

View file

@ -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