Merge branch 'ni/mp' into ni/cst-next

Conflicts:
	data/icons/shutdown.jpg
	data/icons/start.jpg
	data/locale/Makefile.am
	data/locale/deutsch.locale
	data/locale/english.locale
	lib/libdvbsub/dvbsub.cpp
	lib/libdvbsub/dvbsubtitle.cpp
	lib/libtuxtxt/tuxtxt.cpp
	lib/libtuxtxt/tuxtxt.h
	src/gui/dboxinfo.cpp
	src/gui/movieplayer.cpp
	src/gui/streaminfo2.cpp
	src/gui/themes.cpp
	src/neutrino.cpp
	src/neutrino_menue.cpp
	src/nhttpd/Makefile.am
	src/system/flashtool.cpp


Origin commit data
------------------
Branch: ni/coolstream
Commit: 161347db29
Author: vanhofen <vanhofen@gmx.de>
Date: 2016-08-26 (Fri, 26 Aug 2016)



------------------
This commit was generated by Migit
This commit is contained in:
vanhofen
2016-08-26 19:13:47 +02:00
220 changed files with 7577 additions and 1615 deletions

View File

@@ -5,7 +5,7 @@
* Copyright (C) 2001 by fnbrd (fnbrd@gmx.de)
* Homepage: http://dbox2.elxsi.de
*
* Copyright (C) 2008-2013 Stefan Seyfried
* Copyright (C) 2008-2016 Stefan Seyfried
*
* Copyright (C) 2011-2012 CoolStream International Ltd
*
@@ -46,6 +46,7 @@
#include <eventserver.h>
#include <driver/abstime.h>
#include <system/helpers.h>
#include <system/set_threadname.h>
#include <OpenThreads/ScopedLock>
#include "eitd.h"
@@ -59,7 +60,7 @@
//#define DEBUG_SDT_THREAD
//#define DEBUG_TIME_THREAD
#define DEBUG_SECTION_THREADS
//#define DEBUG_SECTION_THREADS
//#define DEBUG_CN_THREAD
/*static*/ bool reader_ready = true;
@@ -149,10 +150,15 @@ static CFreeSatThread threadFSEIT;
CSdtThread threadSDT;
#endif
#ifdef DEBUG_EVENT_LOCK
static time_t lockstart = 0;
#endif
static int sectionsd_stop = 0;
static bool slow_addevent = true;
inline void readLockServices(void)
{
pthread_rwlock_rdlock(&servicesLock);
@@ -191,10 +197,21 @@ inline void readLockEvents(void)
inline void writeLockEvents(void)
{
pthread_rwlock_wrlock(&eventsLock);
#ifdef DEBUG_EVENT_LOCK
lockstart = time_monotonic_ms();
#endif
}
inline void unlockEvents(void)
{
#ifdef DEBUG_EVENT_LOCK
if (lockstart) {
time_t tmp = time_monotonic_ms() - lockstart;
if (tmp > 50)
xprintf("locked ms %d\n", tmp);
lockstart = 0;
}
#endif
pthread_rwlock_unlock(&eventsLock);
}
@@ -215,10 +232,11 @@ static MySIeventUniqueKeysMetaOrderServiceUniqueKey mySIeventUniqueKeysMetaOrder
static MySIservicesOrderUniqueKey mySIservicesOrderUniqueKey;
static MySIservicesNVODorderUniqueKey mySIservicesNVODorderUniqueKey;
/* needs write lock held! */
static bool deleteEvent(const event_id_t uniqueKey)
{
bool ret = false;
writeLockEvents();
// writeLockEvents();
MySIeventsOrderUniqueKey::iterator e = mySIeventsOrderUniqueKey.find(uniqueKey);
if (e != mySIeventsOrderUniqueKey.end()) {
@@ -234,7 +252,7 @@ static bool deleteEvent(const event_id_t uniqueKey)
mySIeventsNVODorderUniqueKey.erase(uniqueKey);
ret = true;
}
unlockEvents();
// unlockEvents();
return ret;
}
@@ -321,7 +339,7 @@ xprintf("addEvent: ch %012" PRIx64 " running %d (%s) got_CN %d\n", evt.get_chann
unlockMessaging();
}
readLockEvents();
writeLockEvents();
MySIeventsOrderUniqueKey::iterator si = mySIeventsOrderUniqueKey.find(evt.uniqueKey());
bool already_exists = (si != mySIeventsOrderUniqueKey.end());
if (already_exists && (evt.table_id < si->second->table_id))
@@ -444,26 +462,29 @@ xprintf("addEvent: ch %012" PRIx64 " running %d (%s) got_CN %d\n", evt.get_chann
delete eptr;
return;
}
/* SRF special case: advertising is inserted with start time of
* an existing event. Duration may differ. To avoid holes in EPG caused
* by the (not useful) advertising event, don't delete the (useful)
* original event */
if ((*x)->table_id == e->table_id && (e->table_id & 0xFE) == 0x4e &&
(*x)->times.begin()->startzeit == start_time)
continue;
/* here we have an overlapping event */
dprintf("%s: delete 0x%012" PRIx64 ".%02x time = 0x%012" PRIx64 ".%02x\n", __func__,
x_key, (*x)->table_id, e_key, e->table_id);
to_delete.push_back(x_key);
}
}
unlockEvents();
while (! to_delete.empty())
{
deleteEvent(to_delete.back());
to_delete.pop_back();
}
} else {
// Damit in den nicht nach Event-ID sortierten Mengen
// Mehrere Events mit gleicher ID sind, diese vorher loeschen
unlockEvents();
}
// Damit in den nicht nach Event-ID sortierten Mengen
// Mehrere Events mit gleicher ID sind, diese vorher loeschen
deleteEvent(e->uniqueKey());
readLockEvents();
if ( !mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.empty() && mySIeventsOrderUniqueKey.size() >= max_events && max_events != 0 ) {
MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey::iterator lastEvent =
mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.begin();
@@ -498,12 +519,8 @@ xprintf("addEvent: ch %012" PRIx64 " running %d (%s) got_CN %d\n", evt.get_chann
}
event_id_t uniqueKey = (*lastEvent)->uniqueKey();
// else fprintf(stderr, ">");
unlockEvents();
deleteEvent(uniqueKey);
}
else
unlockEvents();
readLockEvents();
// Pruefen ob es ein Meta-Event ist
MySIeventUniqueKeysMetaOrderServiceUniqueKey::iterator i = mySIeventUniqueKeysMetaOrderServiceUniqueKey.find(e->get_channel_id());
@@ -523,9 +540,6 @@ xprintf("addEvent: ch %012" PRIx64 " running %d (%s) got_CN %d\n", evt.get_chann
// Falls das Event in den beiden Mengen mit Zeiten nicht vorhanden
// ist, dieses dort einfuegen
MySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey::iterator i2 = mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.find(ie->second);
unlockEvents();
writeLockEvents();
if (i2 == mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.end())
{
// nicht vorhanden -> einfuegen
@@ -538,8 +552,6 @@ xprintf("addEvent: ch %012" PRIx64 " running %d (%s) got_CN %d\n", evt.get_chann
}
}
}
unlockEvents();
writeLockEvents();
// printf("Adding: %04x\n", (int) e->uniqueKey());
// normales Event
@@ -567,22 +579,18 @@ static void addNVODevent(const SIevent &evt)
SIeventPtr e(eptr);
readLockEvents();
writeLockEvents();
MySIeventsOrderUniqueKey::iterator e2 = mySIeventsOrderUniqueKey.find(e->uniqueKey());
if (e2 != mySIeventsOrderUniqueKey.end())
{
// bisher gespeicherte Zeiten retten
unlockEvents();
writeLockEvents();
e->times.insert(e2->second->times.begin(), e2->second->times.end());
}
unlockEvents();
// Damit in den nicht nach Event-ID sortierten Mengen
// mehrere Events mit gleicher ID sind, diese vorher loeschen
deleteEvent(e->uniqueKey());
readLockEvents();
if ( !mySIeventsOrderUniqueKey.empty() && mySIeventsOrderUniqueKey.size() >= max_events && max_events != 0 ) {
//TODO: Set Old Events to 0 if limit is reached...
MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey::iterator lastEvent =
@@ -596,24 +604,18 @@ static void addNVODevent(const SIevent &evt)
--lastEvent;
}
unlockMessaging();
unlockEvents();
deleteEvent((*lastEvent)->uniqueKey());
}
else
unlockEvents();
writeLockEvents();
mySIeventsOrderUniqueKey.insert(std::make_pair(e->uniqueKey(), e));
mySIeventsNVODorderUniqueKey.insert(std::make_pair(e->uniqueKey(), e));
unlockEvents();
if (!e->times.empty())
{
// diese beiden Mengen enthalten nur Events mit Zeiten
writeLockEvents();
mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.insert(e);
mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.insert(e);
unlockEvents();
}
unlockEvents();
}
static void removeOldEvents(const long seconds)
@@ -623,7 +625,7 @@ static void removeOldEvents(const long seconds)
// Alte events loeschen
time_t zeit = time(NULL);
readLockEvents();
writeLockEvents();
unsigned total_events = mySIeventsOrderUniqueKey.size();
MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey::iterator e = mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.begin();
@@ -642,10 +644,9 @@ static void removeOldEvents(const long seconds)
to_delete.push_back((*e)->uniqueKey());
++e;
}
unlockEvents();
for (std::vector<event_id_t>::iterator i = to_delete.begin(); i != to_delete.end(); ++i)
deleteEvent(*i);
unlockEvents();
readLockEvents();
xprintf("[sectionsd] Removed %d old events (%d left), zap detected %d.\n", (int)(total_events - mySIeventsOrderUniqueKey.size()), (int)mySIeventsOrderUniqueKey.size(), messaging_zap_detected);
@@ -1381,7 +1382,7 @@ void CTimeThread::waitForTimeset(void)
time_mutex.unlock();
}
void CTimeThread::setSystemTime(time_t tim)
bool CTimeThread::setSystemTime(time_t tim, bool force)
{
struct timeval tv;
struct tm t;
@@ -1389,6 +1390,7 @@ void CTimeThread::setSystemTime(time_t tim)
gettimeofday(&tv, NULL);
timediff = int64_t(tim * 1000000 - (tv.tv_usec + tv.tv_sec * 1000000));
localtime_r(&tv.tv_sec, &t);
int absdiff = abs(tim - tv.tv_sec);
xprintf("%s: timediff %" PRId64 ", current: %02d.%02d.%04d %02d:%02d:%02d, dvb: %s",
name.c_str(), timediff,
@@ -1400,9 +1402,9 @@ void CTimeThread::setSystemTime(time_t tim)
return;
}
#endif
if (timediff == 0) /* very unlikely... :-) */
return;
if (timeset && abs(tim - tv.tv_sec) < 120) { /* abs() is int */
if (absdiff < 1) /* do not bother for differences less than one second */
return true;
if (absdiff < 120) {
struct timeval oldd;
tv.tv_sec = time_t(timediff / 1000000LL);
tv.tv_usec = suseconds_t(timediff % 1000000LL);
@@ -1412,14 +1414,21 @@ void CTimeThread::setSystemTime(time_t tim)
xprintf("difference is < 120s, using adjtime(%d, %d). oldd(%d, %d)\n",
(int)tv.tv_sec, (int)tv.tv_usec, (int)oldd.tv_sec, (int)oldd.tv_usec);
timediff = 0;
return;
return true;
}
} else if (timeset && ! force) {
xprintf("difference is > 120s, try again and set 'force=true'\n");
return false;
}
/* still fall through if adjtime() failed */
tv.tv_sec = tim;
tv.tv_usec = 0;
if (settimeofday(&tv, NULL) < 0)
perror("[sectionsd] settimeofday");
if (settimeofday(&tv, NULL) == 0)
return true;
perror("[sectionsd] settimeofday");
return false;
}
void CTimeThread::addFilters()
@@ -1431,8 +1440,10 @@ void CTimeThread::addFilters()
void CTimeThread::run()
{
time_t dvb_time = 0;
bool retry = false; /* if time seems fishy, set to true and try again */
xprintf("%s::run:: starting, pid %d (%lu)\n", name.c_str(), getpid(), pthread_self());
threadName = "sd:" + name;
set_threadname(threadName.c_str());
addFilters();
DMX::start();
@@ -1474,7 +1485,21 @@ void CTimeThread::run()
xprintf("%s: get DVB time ch 0x%012" PRIx64 " (isOpen %d)\n",
name.c_str(), current_service, isOpen());
int rc = dmx->Read(static_buf, MAX_SECTION_LENGTH, timeoutInMSeconds);
int rc;
#if HAVE_COOL_HARDWARE
/* libcoolstream does not like the repeated read if the dmx is not yet running
* (e.g. during neutrino start) and causes strange openthreads errors which in
* turn cause complete malfunction of the dmx, so we cannot use the "speed up
* shutdown" hack on with libcoolstream... :-( */
rc = dmx->Read(static_buf, MAX_SECTION_LENGTH, timeoutInMSeconds);
#else
time_t start = time_monotonic_ms();
/* speed up shutdown by looping around Read() */
do {
rc = dmx->Read(static_buf, MAX_SECTION_LENGTH, timeoutInMSeconds / 12);
} while (running && rc == 0
&& (time_monotonic_ms() - start) < (time_t)timeoutInMSeconds);
#endif
xprintf("%s: get DVB time ch 0x%012" PRIx64 " rc: %d neutrino_sets_time %d\n",
name.c_str(), current_service, rc, messaging_neutrino_sets_time);
if (rc > 0) {
@@ -1489,7 +1514,14 @@ void CTimeThread::run()
sleep_time = ntprefresh * 60;
if(success) {
if(dvb_time) {
setSystemTime(dvb_time);
bool ret = setSystemTime(dvb_time, retry);
if (! ret) {
xprintf("%s: time looks wrong, trying again\n", name.c_str());
sendToSleepNow = false;
retry = true;
continue;
}
retry = false;
/* retry a second time immediately after start, to get TOT ? */
if(first_time)
sleep_time = 5;
@@ -1546,6 +1578,8 @@ int CSectionThread::Sleep()
void CSectionThread::run()
{
xprintf("%s::run:: starting, pid %d (%lu)\n", name.c_str(), getpid(), pthread_self());
threadName = "sd:" + name;
set_threadname(threadName.c_str());
if (sections_debug)
dump_sched_info(name);
@@ -2078,10 +2112,14 @@ static void *houseKeepingThread(void *)
count = 0;
}
int rc = HOUSEKEEPING_SLEEP;
int i = HOUSEKEEPING_SLEEP;
while (rc)
rc = sleep(rc);
while (i > 0 && !sectionsd_stop) {
sleep(1);
i--;
}
if (sectionsd_stop)
break;
if (!scanning) {
scount++;
@@ -2210,6 +2248,7 @@ void CEitManager::run()
int rc;
xprintf("[sectionsd] starting\n");
set_threadname("sd:eitmanager");
printf("SIevent size: %d\n", (int)sizeof(SIevent));
/* "export NO_SLOW_ADDEVENT=true" to disable this */
@@ -2292,7 +2331,12 @@ printf("SIevent size: %d\n", (int)sizeof(SIevent));
xprintf("pausing...\n");
/* sometimes, pthread_cancel seems to not work, maybe it is a bad idea to mix
* plain pthread and OpenThreads? */
sectionsd_stop = 1;
pthread_cancel(threadHouseKeeping);
xprintf("join Housekeeping\n");
pthread_join(threadHouseKeeping, NULL);
xprintf("join TOT\n");
threadTIME.Stop();
@@ -2789,7 +2833,7 @@ void CEitManager::getChannelEvents(CChannelEventList &eList, t_channel_id *chidl
bool found_already = true;
time_t azeit = time(NULL);
showProfiling("sectionsd_getChannelEvents start");
// showProfiling("sectionsd_getChannelEvents start");
readLockEvents();
/* !!! FIX ME: if the box starts on a channel where there is no EPG sent, it hangs!!! */
@@ -2833,7 +2877,7 @@ showProfiling("sectionsd_getChannelEvents start");
}
}
showProfiling("sectionsd_getChannelEvents end");
// showProfiling("sectionsd_getChannelEvents end");
unlockEvents();
}