[PR-174] - Icon caching support to reduce overhead on upstream providers.
This commit is contained in:
parent
2b0e495b7b
commit
acdc094fe7
15 changed files with 545 additions and 21 deletions
4
Makefile
4
Makefile
|
@ -32,7 +32,7 @@ CFLAGS += -Wmissing-prototypes -fms-extensions
|
|||
CFLAGS += -g -funsigned-char -O2
|
||||
CFLAGS += -D_FILE_OFFSET_BITS=64
|
||||
CFLAGS += -I${BUILDDIR} -I${CURDIR}/src -I${CURDIR}
|
||||
LDFLAGS += -lrt -ldl -lpthread -lm
|
||||
LDFLAGS += -lrt -ldl -lpthread -lm -lcurl
|
||||
|
||||
#
|
||||
# Other config
|
||||
|
@ -140,6 +140,8 @@ SRCS += src/muxer.c \
|
|||
src/muxer_pass.c \
|
||||
src/muxer_tvh.c \
|
||||
|
||||
SRCS += src/iconserve.c \
|
||||
|
||||
#
|
||||
# Optional code
|
||||
#
|
||||
|
|
|
@ -20,5 +20,19 @@
|
|||
dvb-apps stores these in /usr/share/dvb/. Leave blank to use TVH's internal
|
||||
file set.
|
||||
|
||||
<dt>Cache channel icons:
|
||||
<dd>
|
||||
Enable the caching of channel icons. This will cause TVH to download channel
|
||||
icons locally, and then when requested via HTSP clients the URL for the icon
|
||||
(or logo) will be retrieved from the TVH web server rather than fetched each
|
||||
time by the HTSP client.
|
||||
This REQUIRES the TVH server IP address field to also be populated
|
||||
|
||||
<dt>TVH Server IP Address:
|
||||
<dd>
|
||||
Enter the IP address of the TVH server used for HTSP clients. This permits the
|
||||
above cache channel icons to work (TVH Clients are directed to the IP address
|
||||
entered here to retrieve channel icons from)
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
|
|
|
@ -74,3 +74,50 @@ int config_set_muxconfpath ( const char *path )
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *config_get_iconserve ( void )
|
||||
{
|
||||
return htsmsg_get_str(config, "iconserve");
|
||||
}
|
||||
|
||||
int config_set_iconserve ( const char *setting )
|
||||
{
|
||||
const char *c = config_get_iconserve();
|
||||
if (!c || strcmp(c, setting)) {
|
||||
if (c) htsmsg_delete_field(config, "iconserve");
|
||||
htsmsg_add_str(config, "iconserve", setting);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
const char *config_get_iconserve_periodicdownload ( void )
|
||||
{
|
||||
return htsmsg_get_str(config, "iconserve_periodicdownload");
|
||||
}
|
||||
|
||||
int config_set_iconserve_periodicdownload ( const char *setting )
|
||||
{
|
||||
const char *c = config_get_iconserve_periodicdownload();
|
||||
if (!c || strcmp(c, setting)) {
|
||||
if (c) htsmsg_delete_field(config, "iconserve_periodicdownload");
|
||||
htsmsg_add_str(config, "iconserve_periodicdownload", setting);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *config_get_serverip ( void )
|
||||
{
|
||||
return htsmsg_get_str(config, "serverip");
|
||||
};
|
||||
|
||||
int config_set_serverip ( const char *setting )
|
||||
{
|
||||
const char *c = config_get_serverip();
|
||||
if (!c || strcmp(c, setting)) {
|
||||
if (c) htsmsg_delete_field(config, "serverip");
|
||||
htsmsg_add_str(config, "serverip", setting);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
|
|
@ -32,6 +32,18 @@ const char *config_get_muxconfpath ( void );
|
|||
int config_set_muxconfpath ( const char *str )
|
||||
__attribute__((warn_unused_result));
|
||||
|
||||
const char *config_get_iconserve ( void );
|
||||
int config_set_iconserve ( const char *str )
|
||||
__attribute__((warn_unused_result));
|
||||
|
||||
const char *config_get_iconserve_periodicdownload ( void );
|
||||
int config_set_iconserve_periodicdownload ( const char *str )
|
||||
__attribute__((warn_unused_result));
|
||||
|
||||
const char *config_get_serverip ( void );
|
||||
int config_set_serverip ( const char *str )
|
||||
__attribute__((warn_unused_result));
|
||||
|
||||
const char *config_get_language ( void );
|
||||
int config_set_language ( const char *str )
|
||||
__attribute__((warn_unused_result));
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
#include "htsmsg_binary.h"
|
||||
#include "epg.h"
|
||||
#include "plumbing/tsfix.h"
|
||||
#include "iconserve.h"
|
||||
#include "config2.h"
|
||||
|
||||
#include <sys/statvfs.h>
|
||||
#include "settings.h"
|
||||
|
@ -447,8 +449,10 @@ htsp_build_channel(channel_t *ch, const char *method)
|
|||
htsmsg_add_u32(out, "channelNumber", ch->ch_number);
|
||||
|
||||
htsmsg_add_str(out, "channelName", ch->ch_name);
|
||||
if(ch->ch_icon != NULL)
|
||||
htsmsg_add_str(out, "channelIcon", ch->ch_icon);
|
||||
|
||||
if(ch->ch_icon != NULL) {
|
||||
htsmsg_add_str(out, "channelIcon", logo_query(ch->ch_id, ch->ch_icon));
|
||||
};
|
||||
|
||||
now = ch->ch_epg_now;
|
||||
next = ch->ch_epg_next;
|
||||
|
|
14
src/http.c
14
src/http.c
|
@ -173,18 +173,18 @@ http_send_header(http_connection_t *hc, int rc, const char *content,
|
|||
|
||||
tm = gmtime_r(&t, &tm0);
|
||||
htsbuf_qprintf(&hdrs,
|
||||
"Last-Modified: %s, %02d %s %d %02d:%02d:%02d GMT\r\n",
|
||||
cachedays[tm->tm_wday], tm->tm_year + 1900,
|
||||
cachemonths[tm->tm_mon], tm->tm_mday,
|
||||
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||
"Last-Modified: %s, %d %s %02d %02d:%02d:%02d GMT\r\n",
|
||||
cachedays[tm->tm_wday], tm->tm_mday,
|
||||
cachemonths[tm->tm_mon], tm->tm_year + 1900,
|
||||
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||
|
||||
t += maxage;
|
||||
|
||||
tm = gmtime_r(&t, &tm0);
|
||||
htsbuf_qprintf(&hdrs,
|
||||
"Expires: %s, %02d %s %d %02d:%02d:%02d GMT\r\n",
|
||||
cachedays[tm->tm_wday], tm->tm_year + 1900,
|
||||
cachemonths[tm->tm_mon], tm->tm_mday,
|
||||
"Expires: %s, %d %s %02d %02d:%02d:%02d GMT\r\n",
|
||||
cachedays[tm->tm_wday], tm->tm_mday,
|
||||
cachemonths[tm->tm_mon], tm->tm_year + 1900,
|
||||
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||
|
||||
htsbuf_qprintf(&hdrs, "Cache-Control: max-age=%d\r\n", maxage);
|
||||
|
|
358
src/iconserve.c
Normal file
358
src/iconserve.c
Normal file
|
@ -0,0 +1,358 @@
|
|||
/*
|
||||
* Icon file server operations
|
||||
* Copyright (C) 2012 Andy Brown
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#define CURL_STATICLIB
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <curl/curl.h>
|
||||
#include <curl/easy.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "settings.h"
|
||||
#include "tvheadend.h"
|
||||
#include "channels.h"
|
||||
#include "http.h"
|
||||
#include "webui/webui.h"
|
||||
#include "filebundle.h"
|
||||
#include "iconserve.h"
|
||||
#include "config2.h"
|
||||
#include "queue.h"
|
||||
#include "spawn.h"
|
||||
|
||||
/* Queue, Cond to signal data and Mutex to protect it */
|
||||
static TAILQ_HEAD(,iconserve_grab_queue) iconserve_queue;
|
||||
static pthread_mutex_t iconserve_mutex;
|
||||
static pthread_cond_t iconserve_cond;
|
||||
|
||||
/**
|
||||
* https://github.com/andyb2000 Function to provide local icon files
|
||||
*/
|
||||
int
|
||||
page_logo(http_connection_t *hc, const char *remain, void *opaque)
|
||||
{
|
||||
const char *homedir = hts_settings_get_root();
|
||||
channel_t *ch = NULL;
|
||||
char *inpath, *inpath2;
|
||||
const char *outpath = "none";
|
||||
char homepath[254];
|
||||
char iconpath[100];
|
||||
pthread_mutex_lock(&global_lock);
|
||||
fb_file *fp;
|
||||
ssize_t size;
|
||||
char buf[4096];
|
||||
char *mimetest_outbuf;
|
||||
|
||||
if(remain == NULL) {
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
return 404;
|
||||
};
|
||||
|
||||
if(strstr(remain, "..")) {
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
return HTTP_STATUS_BAD_REQUEST;
|
||||
};
|
||||
|
||||
ch = channel_find_by_identifier(atoi(remain));
|
||||
if (ch == NULL || ch->ch_icon == NULL) {
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
return 404;
|
||||
};
|
||||
|
||||
snprintf(homepath, sizeof(homepath), "%s/icons", homedir);
|
||||
inpath = NULL;
|
||||
inpath2 = NULL;
|
||||
outpath = NULL;
|
||||
/* split icon to last component */
|
||||
inpath = strdup(ch->ch_icon);
|
||||
inpath2 = strtok(inpath, "/");
|
||||
while (inpath2 != NULL) {
|
||||
inpath2 = strtok(NULL, "/");
|
||||
if (inpath2 != NULL) {
|
||||
outpath = strdup(inpath2);
|
||||
};
|
||||
};
|
||||
snprintf(iconpath, sizeof(iconpath), "%s/%s", homepath, outpath);
|
||||
fp = fb_open(iconpath, 1, 0);
|
||||
if (!fp) {
|
||||
tvhlog(LOG_DEBUG, "page_logo",
|
||||
"failed to open %s redirecting to http link for icon (%s)",
|
||||
iconpath, ch->ch_icon);
|
||||
http_redirect(hc, ch->ch_icon);
|
||||
iconserve_queue_add ( ch->ch_id, ch->ch_icon );
|
||||
} else {
|
||||
tvhlog(LOG_DEBUG, "page_logo", "File %s opened", iconpath);
|
||||
size = fb_size(fp);
|
||||
mimetest_outbuf = strdup("image/jpeg");
|
||||
http_send_header(hc, 200, mimetest_outbuf, size, NULL, NULL, 300, 0, NULL);
|
||||
while (!fb_eof(fp)) {
|
||||
ssize_t c = fb_read(fp, buf, sizeof(buf));
|
||||
if (c < 0) {
|
||||
break;
|
||||
};
|
||||
if (write(hc->hc_fd, buf, c) != c) {
|
||||
break;
|
||||
};
|
||||
};
|
||||
fb_close(fp);
|
||||
};
|
||||
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Logo loader functions, called from http htsp
|
||||
* Will return local cache url instead of icon stored
|
||||
*/
|
||||
const char
|
||||
*logo_query(int ch_id, const char *ch_icon)
|
||||
{
|
||||
const char *setting = config_get_iconserve();
|
||||
const char *serverip = config_get_serverip();
|
||||
char outiconpath[255];
|
||||
char *return_icon = strdup(ch_icon);
|
||||
|
||||
if (!setting || !*setting || (strcmp(setting, "off") == 0)) {
|
||||
return return_icon;
|
||||
};
|
||||
|
||||
if (!serverip || !*serverip) {
|
||||
return return_icon;
|
||||
};
|
||||
|
||||
snprintf(outiconpath, sizeof(outiconpath),
|
||||
"http://%s:%d/channellogo/%d", serverip, webui_port, ch_id);
|
||||
return_icon = strdup(outiconpath);
|
||||
return return_icon;
|
||||
};
|
||||
|
||||
/*
|
||||
* Icon grabber queue thread
|
||||
*/
|
||||
void *iconserve_thread ( void *aux )
|
||||
{
|
||||
iconserve_grab_queue_t *qe;
|
||||
pthread_mutex_lock(&iconserve_mutex);
|
||||
char *inpath, *inpath2;
|
||||
const char *header_parse = NULL, *header_maxage = NULL;
|
||||
const char *outpath = "none";
|
||||
CURL *curl;
|
||||
FILE *curl_fp, *curl_fp_header;
|
||||
CURLcode res;
|
||||
fb_file *fp;
|
||||
char iconpath[100], iconpath_header[100];
|
||||
char homepath[254];
|
||||
const char *homedir = hts_settings_get_root();
|
||||
struct stat fileStat;
|
||||
int trigger_download = 0;
|
||||
char buf[256];
|
||||
int file = 0;
|
||||
time_t seconds;
|
||||
int dif, compare_seconds, rc;
|
||||
const char *periodicdownload = config_get_iconserve_periodicdownload();
|
||||
struct timespec timertrigger;
|
||||
channel_t *ch;
|
||||
|
||||
tvhlog(LOG_INFO, "iconserve_thread", "Thread startup");
|
||||
curl = curl_easy_init();
|
||||
snprintf(homepath, sizeof(homepath), "%s/icons", homedir);
|
||||
if(stat(homepath, &fileStat) == 0 || mkdir(homepath, 0700) == 0) {
|
||||
if (curl) {
|
||||
while (1) {
|
||||
|
||||
/* Get entry from queue */
|
||||
qe = TAILQ_FIRST(&iconserve_queue);
|
||||
/* Check for queue data */
|
||||
if (!qe) { /* Queue Empty */
|
||||
periodicdownload = config_get_iconserve_periodicdownload();
|
||||
if (!periodicdownload || !*periodicdownload ||
|
||||
(strcmp(periodicdownload, "off") == 0)) {
|
||||
tvhlog(LOG_DEBUG, "iconserve_thread", "Non-timer wakeup");
|
||||
rc = pthread_cond_wait(&iconserve_cond, &iconserve_mutex);
|
||||
} else {
|
||||
tvhlog(LOG_DEBUG, "iconserve_thread", "Timer wakeup set");
|
||||
timertrigger.tv_sec = time(NULL) + 86400;
|
||||
timertrigger.tv_nsec = 0;
|
||||
rc = pthread_cond_timedwait(&iconserve_cond,
|
||||
&iconserve_mutex, &timertrigger);
|
||||
};
|
||||
if (rc == ETIMEDOUT) {
|
||||
tvhlog(LOG_INFO, "iconserve_thread", "Thread wakeup by timer");
|
||||
RB_FOREACH(ch, &channel_name_tree, ch_name_link) {
|
||||
if (ch->ch_icon != NULL) {
|
||||
iconserve_grab_queue_t *qe = calloc(1, sizeof(iconserve_grab_queue_t));
|
||||
qe->chan_number = ch->ch_id;
|
||||
qe->icon_url = ch->ch_icon;
|
||||
TAILQ_INSERT_TAIL(&iconserve_queue, qe, iconserve_link);
|
||||
};
|
||||
};
|
||||
};
|
||||
continue;
|
||||
}
|
||||
TAILQ_REMOVE(&iconserve_queue, qe, iconserve_link);
|
||||
pthread_mutex_unlock(&iconserve_mutex);
|
||||
|
||||
inpath = NULL;
|
||||
inpath2 = NULL;
|
||||
outpath = NULL;
|
||||
curl_fp = NULL;
|
||||
/* split icon to last component */
|
||||
inpath = strdup(qe->icon_url);
|
||||
inpath2 = strtok(inpath, "/");
|
||||
while (inpath2 != NULL) {
|
||||
inpath2 = strtok(NULL, "/");
|
||||
if (inpath2 != NULL)
|
||||
outpath = strdup(inpath2);
|
||||
};
|
||||
if (outpath != NULL) {
|
||||
snprintf(iconpath, sizeof(iconpath), "%s/%s", homepath, outpath);
|
||||
snprintf(iconpath_header, sizeof(iconpath_header), "%s/%s.head",
|
||||
homepath, outpath);
|
||||
fp = fb_open(iconpath, 0, 1);
|
||||
if (!fp) {
|
||||
/* No file exists so grab immediately */
|
||||
tvhlog(LOG_INFO, "logo_loader", "No logo, downloading file %s", outpath);
|
||||
trigger_download = 1;
|
||||
} else {
|
||||
/* File exists so compare expiry times to re-grab */
|
||||
fb_close(fp);
|
||||
fp = fb_open(iconpath_header, 0, 0);
|
||||
while (!fb_eof(fp)) {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
if (!fb_gets(fp, buf, sizeof(buf) - 1)) break;
|
||||
if (buf[strlen(buf) - 1] == '\n') {
|
||||
buf[strlen(buf) - 1] = '\0';
|
||||
};
|
||||
if(strstr(buf, "Cache-Control: ")) {
|
||||
header_parse = strtok(buf, "=");
|
||||
header_parse = strtok ( NULL, "=");
|
||||
header_maxage = strdup(header_parse);
|
||||
};
|
||||
};
|
||||
fb_close(fp);
|
||||
file=open(iconpath, O_RDONLY);
|
||||
fstat(file,&fileStat);
|
||||
seconds = time (NULL);
|
||||
dif = difftime (seconds,fileStat.st_mtime);
|
||||
compare_seconds=atoi(header_maxage);
|
||||
if (dif > compare_seconds) {
|
||||
tvhlog(LOG_DEBUG, "logo_loader", "Logo expired, downloading %s", outpath);
|
||||
trigger_download = 1;
|
||||
} else {
|
||||
tvhlog(LOG_INFO, "logo_loader", "Logo not expired %s", outpath);
|
||||
};
|
||||
close(file);
|
||||
};
|
||||
if (trigger_download == 1) {
|
||||
curl_fp=fopen(iconpath,"wb");
|
||||
curl_fp_header=fopen(iconpath_header,"w");
|
||||
curl_easy_setopt(curl, CURLOPT_URL, qe->icon_url);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, curl_fp);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEHEADER, curl_fp_header);
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, "TVHeadend");
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 120);
|
||||
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L);
|
||||
res = curl_easy_perform(curl);
|
||||
if (res == 0) {
|
||||
tvhlog(LOG_INFO, "logo_loader", "Downloaded icon via curl (%s)",
|
||||
qe->icon_url);
|
||||
} else {
|
||||
tvhlog(LOG_WARNING, "logo_loader", "Error with curl download (%s)",
|
||||
qe->icon_url);
|
||||
};
|
||||
fclose(curl_fp);
|
||||
fclose(curl_fp_header);
|
||||
trigger_download = 0;
|
||||
};
|
||||
};
|
||||
}; /* while loop */
|
||||
curl_easy_cleanup(curl);
|
||||
} else {
|
||||
tvhlog(LOG_WARNING, "iconserve", "CURL cannot initialise");
|
||||
};
|
||||
};
|
||||
return NULL;
|
||||
};
|
||||
|
||||
/*
|
||||
* Add data to the queue
|
||||
*/
|
||||
void iconserve_queue_add ( int chan_number, char *icon_url )
|
||||
{
|
||||
/* Create entry */
|
||||
tvhlog(LOG_DEBUG, "iconserve_queue_add", "Adding chan_number to queue: %i",
|
||||
chan_number);
|
||||
iconserve_grab_queue_t *qe = calloc(1, sizeof(iconserve_grab_queue_t));
|
||||
qe->chan_number = chan_number;
|
||||
qe->icon_url = strdup(icon_url);
|
||||
|
||||
pthread_mutex_lock(&iconserve_mutex);
|
||||
TAILQ_INSERT_TAIL(&iconserve_queue, qe, iconserve_link);
|
||||
pthread_cond_signal(&iconserve_cond);
|
||||
pthread_mutex_unlock(&iconserve_mutex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Loader for icons, check config params and pull them in one go
|
||||
*/
|
||||
void
|
||||
logo_loader(void)
|
||||
{
|
||||
channel_t *ch;
|
||||
const char *setting = config_get_iconserve();
|
||||
const char *serverip = config_get_serverip();
|
||||
|
||||
if (!setting || !*setting || (strcmp(setting, "off") == 0)) {
|
||||
tvhlog(LOG_DEBUG, "logo_loader", "Disabled by config, skipping");
|
||||
return;
|
||||
};
|
||||
|
||||
if (!serverip || !*serverip) {
|
||||
tvhlog(LOG_ALERT, "logo_loader", "No server IP, skipping icon cache");
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
pthread_t tid;
|
||||
pthread_mutex_init(&iconserve_mutex, NULL);
|
||||
pthread_cond_init(&iconserve_cond, NULL);
|
||||
TAILQ_INIT(&iconserve_queue);
|
||||
/* Start thread - presumably permanently active */
|
||||
pthread_create(&tid, NULL, iconserve_thread, NULL); // last param is passed as aux
|
||||
// as this is single global
|
||||
// you can probably use global
|
||||
// vars
|
||||
|
||||
tvhlog(LOG_INFO, "logo_loader", "Caching logos locally");
|
||||
/* loop through channels and load logo files */
|
||||
RB_FOREACH(ch, &channel_name_tree, ch_name_link) {
|
||||
if (ch->ch_icon != NULL) {
|
||||
iconserve_queue_add ( ch->ch_id, ch->ch_icon );
|
||||
};
|
||||
};
|
||||
pthread_mutex_lock(&iconserve_mutex);
|
||||
pthread_cond_signal(&iconserve_cond); // tell thread data is available
|
||||
pthread_mutex_unlock(&iconserve_mutex);
|
||||
};
|
47
src/iconserve.h
Normal file
47
src/iconserve.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Icon file serve operations
|
||||
* Copyright (C) 2012 Andy Brown
|
||||
*
|
||||
* 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 ICONSERVE_H
|
||||
#define ICONSERVE_H
|
||||
|
||||
#include "http.h"
|
||||
|
||||
/* Struct of entries for icon grabbing
|
||||
* FIELD: chan_number
|
||||
* FIELD: icon url
|
||||
*/
|
||||
typedef struct iconserve_grab_queue
|
||||
{
|
||||
TAILQ_ENTRY(iconserve_grab_queue) iconserve_link;
|
||||
int chan_number;
|
||||
char *icon_url;
|
||||
} iconserve_grab_queue_t;
|
||||
|
||||
|
||||
int page_logo(http_connection_t *hc, const char *remain, void *opaque);
|
||||
size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream);
|
||||
|
||||
void *iconserve_thread ( void *aux );
|
||||
|
||||
const char *logo_query(int ch_id, const char *ch_icon);
|
||||
|
||||
void iconserve_queue_add ( int chan_number, char *icon_url );
|
||||
|
||||
void logo_loader(void);
|
||||
|
||||
#endif /* ICONSERVE_H */
|
|
@ -60,6 +60,7 @@
|
|||
#include "ffdecsa/FFdecsa.h"
|
||||
#include "muxes.h"
|
||||
#include "config2.h"
|
||||
#include "iconserve.h"
|
||||
|
||||
int running;
|
||||
time_t dispatch_clock;
|
||||
|
@ -488,6 +489,8 @@ main(int argc, char **argv)
|
|||
http_server_init();
|
||||
webui_init();
|
||||
|
||||
logo_loader();
|
||||
|
||||
serviceprobe_init();
|
||||
|
||||
#if ENABLE_CWC
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "config2.h"
|
||||
#include "lang_codes.h"
|
||||
#include "subscriptions.h"
|
||||
#include "iconserve.h"
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -858,7 +859,7 @@ extjs_epg(http_connection_t *hc, const char *remain, void *opaque)
|
|||
htsmsg_add_str(m, "channel", ch->ch_name);
|
||||
htsmsg_add_u32(m, "channelid", ch->ch_id);
|
||||
if(ch->ch_icon != NULL)
|
||||
htsmsg_add_str(m, "chicon", ch->ch_icon);
|
||||
htsmsg_add_str(m, "chicon", logo_query(ch->ch_id, ch->ch_icon));
|
||||
|
||||
if((s = epg_episode_get_title(ee, lang)))
|
||||
htsmsg_add_str(m, "title", s);
|
||||
|
@ -940,7 +941,7 @@ extjs_epgrelated(http_connection_t *hc, const char *remain, void *opaque)
|
|||
m = htsmsg_create_map();
|
||||
htsmsg_add_u32(m, "id", ebc->id);
|
||||
if ( ch->ch_name ) htsmsg_add_str(m, "channel", ch->ch_name);
|
||||
if ( ch->ch_icon ) htsmsg_add_str(m, "chicon", ch->ch_icon);
|
||||
if ( ch->ch_icon ) htsmsg_add_str(m, "chicon", logo_query(ch->ch_id, ch->ch_icon));
|
||||
htsmsg_add_u32(m, "start", ebc->start);
|
||||
htsmsg_add_msg(array, NULL, m);
|
||||
}
|
||||
|
@ -1340,7 +1341,7 @@ extjs_dvrlist(http_connection_t *hc, const char *remain, void *opaque,
|
|||
if(de->de_channel != NULL) {
|
||||
htsmsg_add_str(m, "channel", de->de_channel->ch_name);
|
||||
if(de->de_channel->ch_icon != NULL)
|
||||
htsmsg_add_str(m, "chicon", de->de_channel->ch_icon);
|
||||
htsmsg_add_str(m, "chicon", logo_query(de->de_channel->ch_id, de->de_channel->ch_icon));
|
||||
}
|
||||
|
||||
htsmsg_add_str(m, "config_name", de->de_config_name);
|
||||
|
@ -1930,7 +1931,23 @@ extjs_config(http_connection_t *hc, const char *remain, void *opaque)
|
|||
save |= config_set_muxconfpath(str);
|
||||
if ((str = http_arg_get(&hc->hc_req_args, "language")))
|
||||
save |= config_set_language(str);
|
||||
str = http_arg_get(&hc->hc_req_args, "iconserve");
|
||||
if (str != NULL) {
|
||||
save |= config_set_iconserve(str);
|
||||
} else {
|
||||
save |= config_set_iconserve("off");
|
||||
};
|
||||
str = http_arg_get(&hc->hc_req_args, "iconserve_periodicdownload");
|
||||
if (str != NULL) {
|
||||
save |= config_set_iconserve_periodicdownload(str);
|
||||
} else {
|
||||
save |= config_set_iconserve_periodicdownload("off");
|
||||
};
|
||||
if ((str = http_arg_get(&hc->hc_req_args, "serverip")))
|
||||
save |= config_set_serverip(str);
|
||||
if (save) config_save();
|
||||
/* trigger the iconserve init routine */
|
||||
logo_loader();
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
out = htsmsg_create_map();
|
||||
htsmsg_add_u32(out, "success", 1);
|
||||
|
|
|
@ -482,7 +482,5 @@ simpleui_start(void)
|
|||
http_path_add("/simple.html", NULL, page_simple, ACCESS_SIMPLE);
|
||||
http_path_add("/eventinfo", NULL, page_einfo, ACCESS_SIMPLE);
|
||||
http_path_add("/pvrinfo", NULL, page_pvrinfo, ACCESS_SIMPLE);
|
||||
http_path_add("/status.xml", NULL, page_status, ACCESS_SIMPLE);
|
||||
http_path_add("/status.xml", NULL, page_status, ACCESS_SIMPLE);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "epg.h"
|
||||
#include "psi.h"
|
||||
#include "channels.h"
|
||||
#include "iconserve.h"
|
||||
#if ENABLE_LINUXDVB
|
||||
#include "dvr/dvr.h"
|
||||
#include "dvb/dvb.h"
|
||||
|
@ -72,7 +73,7 @@ dumpchannels(htsbuf_queue_t *hq)
|
|||
ch->ch_refcount,
|
||||
ch->ch_zombie,
|
||||
ch->ch_number,
|
||||
ch->ch_icon ?: "<none set>");
|
||||
logo_query(ch->ch_id, ch->ch_icon) ?: "<none set>");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ tvheadend.miscconf = function() {
|
|||
*/
|
||||
var confreader = new Ext.data.JsonReader({
|
||||
root : 'config'
|
||||
}, [ 'muxconfpath', 'language' ]);
|
||||
}, [ 'muxconfpath', 'language', 'iconserve', 'serverip' ]);
|
||||
|
||||
/* ****************************************************************
|
||||
* Form Fields
|
||||
|
@ -50,6 +50,22 @@ tvheadend.miscconf = function() {
|
|||
width: 400
|
||||
});
|
||||
|
||||
var iconServeConfig = new Ext.form.Checkbox({
|
||||
name : 'iconserve',
|
||||
fieldLabel : 'Cache channel icons'
|
||||
});
|
||||
var iconPeriodicDownload = new Ext.form.Checkbox({
|
||||
name : 'iconserve_periodicdownload',
|
||||
fieldLabel : 'Periodically check for updated icons'
|
||||
});
|
||||
var serveripConfig = new Ext.form.TextField({
|
||||
fieldLabel : 'TVH Server IP address',
|
||||
name : 'serverip',
|
||||
allowBlank : true,
|
||||
width: 150
|
||||
});
|
||||
|
||||
|
||||
var language = new Ext.ux.ItemSelector({
|
||||
name: 'language',
|
||||
fromStore: tvheadend.languages,
|
||||
|
@ -95,7 +111,7 @@ tvheadend.miscconf = function() {
|
|||
layout : 'form',
|
||||
defaultType : 'textfield',
|
||||
autoHeight : true,
|
||||
items : [ language, dvbscanPath ],
|
||||
items : [ language, dvbscanPath, iconServeConfig, iconPeriodicDownload, serveripConfig ],
|
||||
tbar : [ saveButton, '->', helpButton ]
|
||||
});
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "muxer.h"
|
||||
#include "dvb/dvb.h"
|
||||
#include "dvb/dvb_support.h"
|
||||
#include "iconserve.h"
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -95,7 +96,7 @@ page_root2(http_connection_t *hc, const char *remain, void *opaque)
|
|||
/**
|
||||
* Static download of a file from the filesystem
|
||||
*/
|
||||
static int
|
||||
int
|
||||
page_static_file(http_connection_t *hc, const char *remain, void *opaque)
|
||||
{
|
||||
int ret = 0;
|
||||
|
@ -909,6 +910,8 @@ webui_init(void)
|
|||
|
||||
http_path_add("/stream", NULL, http_stream, ACCESS_STREAMING);
|
||||
|
||||
http_path_add("/channellogo", NULL, page_logo, ACCESS_ANONYMOUS);
|
||||
|
||||
webui_static_content("/static", "src/webui/static");
|
||||
webui_static_content("/docs", "docs/html");
|
||||
webui_static_content("/docresources", "docs/docresources");
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#define WEBUI_H_
|
||||
|
||||
#include "htsmsg.h"
|
||||
#include "http.h"
|
||||
|
||||
void webui_init(void);
|
||||
|
||||
|
@ -30,6 +31,8 @@ void extjs_start(void);
|
|||
size_t html_escaped_len(const char *src);
|
||||
const char* html_escape(char *dst, const char *src, size_t len);
|
||||
|
||||
int page_static_file(http_connection_t *hc, const char *remain, void *opaque);
|
||||
|
||||
#if ENABLE_LINUXDVB
|
||||
void extjs_list_dvb_adapters(htsmsg_t *array);
|
||||
void extjs_start_dvb(void);
|
||||
|
@ -54,5 +57,4 @@ void comet_mailbox_add_message(htsmsg_t *m, int isdebug);
|
|||
|
||||
void comet_flush(void);
|
||||
|
||||
|
||||
#endif /* WEBUI_H_ */
|
||||
|
|
Loading…
Add table
Reference in a new issue