mirror of
https://github.com/tuxbox-neutrino/neutrino.git
synced 2025-08-31 17:31:20 +02:00
Merge remote-tracking branch 'check/next-cc'
build-tested only, needs fixing Conflicts: data/locale/deutsch.locale data/locale/english.locale src/Makefile.am src/driver/rcinput.cpp src/driver/streamts.cpp src/eitd/sectionsd.cpp src/gui/Makefile.am src/gui/bouquetlist.cpp src/gui/hdd_menu.cpp src/gui/luainstance.cpp src/gui/luainstance.h src/gui/moviebrowser.cpp src/gui/movieplayer.cpp src/gui/pluginlist.cpp src/gui/plugins.cpp src/gui/plugins.h src/gui/scan.cpp src/gui/scan_setup.cpp src/gui/user_menue.cpp src/gui/videosettings.cpp src/gui/widget/menue.cpp src/neutrino.cpp src/neutrinoMessages.h src/system/locals.h src/system/locals_intern.h src/zapit/include/zapit/scan.h src/zapit/src/femanager.cpp src/zapit/src/frontend.cpp src/zapit/src/getservices.cpp src/zapit/src/transponder.cpp
This commit is contained in:
@@ -43,7 +43,7 @@
|
||||
const char * const file_extension_list[] =
|
||||
{
|
||||
"aac", "asf", "avi", "bmp", "cdr", "crw",
|
||||
"dts", "flac", "gif", "imu", "jpeg", "jpg",
|
||||
"dts", "flac", "gif", "imu", "iso", "jpeg", "jpg",
|
||||
"m2a", "m3u", "m4a", "mkv", "mp2", "mp3",
|
||||
"mpa", "ogg", "pls", "png", "sh",
|
||||
"txt", "url", "wav", "xml"
|
||||
@@ -53,7 +53,7 @@ const char * const file_extension_list[] =
|
||||
const CFile::FileType file_type_list[] =
|
||||
{
|
||||
CFile::FILE_AAC , CFile::FILE_ASF , CFile::FILE_AVI , CFile::FILE_PICTURE , CFile::FILE_CDR , CFile::FILE_PICTURE ,
|
||||
CFile::FILE_WAV , CFile::FILE_FLAC , CFile::FILE_PICTURE , CFile::STREAM_PICTURE, CFile::FILE_PICTURE , CFile::FILE_PICTURE ,
|
||||
CFile::FILE_WAV , CFile::FILE_FLAC , CFile::FILE_PICTURE , CFile::STREAM_PICTURE, CFile::FILE_ISO , CFile::FILE_PICTURE , CFile::FILE_PICTURE ,
|
||||
CFile::FILE_MP3 , CFile::FILE_PLAYLIST , CFile::FILE_AAC , CFile::FILE_MKV , CFile::FILE_MP3 , CFile::FILE_MP3 ,
|
||||
CFile::FILE_MP3 , CFile::FILE_OGG , CFile::FILE_PLAYLIST, CFile::FILE_PICTURE , CFile::FILE_TEXT ,
|
||||
CFile::FILE_TEXT , CFile::STREAM_AUDIO , CFile::FILE_WAV , CFile::FILE_XML
|
||||
|
@@ -60,6 +60,7 @@ public:
|
||||
FILE_AVI,
|
||||
FILE_ASF,
|
||||
FILE_DIR,
|
||||
FILE_ISO,
|
||||
FILE_TEXT,
|
||||
FILE_CDR,
|
||||
FILE_MP3,
|
||||
|
@@ -102,6 +102,29 @@ CPictureViewer::CFormathandler * CPictureViewer::fh_getsize (const char *name, i
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
std::string CPictureViewer::DownloadImage(std::string url)
|
||||
{
|
||||
if (strstr(url.c_str(), "://")) {
|
||||
std::string tmpname = "/tmp/pictureviewer" + url.substr(url.find_last_of("."));
|
||||
FILE *tmpFile = fopen(tmpname.c_str(), "wb");
|
||||
if (tmpFile) {
|
||||
CURL *ch = curl_easy_init();
|
||||
curl_easy_setopt(ch, CURLOPT_VERBOSE, 0L);
|
||||
curl_easy_setopt(ch, CURLOPT_NOPROGRESS, 1L);
|
||||
curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1L);
|
||||
curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, NULL);
|
||||
curl_easy_setopt(ch, CURLOPT_WRITEDATA, tmpFile);
|
||||
curl_easy_setopt(ch, CURLOPT_FAILONERROR, 1L);
|
||||
curl_easy_setopt(ch, CURLOPT_URL, url.c_str());
|
||||
curl_easy_perform(ch);
|
||||
curl_easy_cleanup(ch);
|
||||
fclose(tmpFile);
|
||||
url = true;
|
||||
}
|
||||
url = tmpname;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
bool CPictureViewer::DecodeImage (const std::string & _name, bool showBusySign, bool unscaled)
|
||||
{
|
||||
@@ -121,29 +144,9 @@ bool CPictureViewer::DecodeImage (const std::string & _name, bool showBusySign,
|
||||
if (showBusySign)
|
||||
showBusy (m_startx + 3, m_starty + 3, 10, 0xff, 00, 00);
|
||||
|
||||
std::string name = _name;
|
||||
bool url = false;
|
||||
|
||||
if (strstr(name.c_str(), "://")) {
|
||||
std::string tmpname;
|
||||
tmpname = "/tmp/pictureviewer" + name.substr(name.find_last_of("."));
|
||||
FILE *tmpFile = fopen(tmpname.c_str(), "wb");
|
||||
if (tmpFile) {
|
||||
CURL *ch = curl_easy_init();
|
||||
curl_easy_setopt(ch, CURLOPT_VERBOSE, 0L);
|
||||
curl_easy_setopt(ch, CURLOPT_NOPROGRESS, 1L);
|
||||
curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1L);
|
||||
curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, NULL);
|
||||
curl_easy_setopt(ch, CURLOPT_WRITEDATA, tmpFile);
|
||||
curl_easy_setopt(ch, CURLOPT_FAILONERROR, 1L);
|
||||
curl_easy_setopt(ch, CURLOPT_URL, name.c_str());
|
||||
curl_easy_perform(ch);
|
||||
curl_easy_cleanup(ch);
|
||||
fclose(tmpFile);
|
||||
url = true;
|
||||
}
|
||||
name = tmpname;
|
||||
}
|
||||
std::string name = DownloadImage(_name);
|
||||
|
||||
CFormathandler *fh;
|
||||
if (unscaled)
|
||||
@@ -499,6 +502,7 @@ void CPictureViewer::getSize(const char* name, int* width, int *height)
|
||||
}
|
||||
|
||||
#define LOGO_FLASH_DIR DATADIR "/neutrino/icons/logo"
|
||||
#define LOGO_FLASH_DIR_VAR "/var/tuxbox/icons/logo"
|
||||
|
||||
bool CPictureViewer::GetLogoName(const uint64_t& channel_id, const std::string& ChannelName, std::string & name, int *width, int *height)
|
||||
{
|
||||
@@ -523,6 +527,16 @@ bool CPictureViewer::GetLogoName(const uint64_t& channel_id, const std::string&
|
||||
id_tmp_path += strChnId + fileType[i];
|
||||
v_path.push_back(id_tmp_path);
|
||||
|
||||
//create filename with channel name (LOGO_FLASH_DIR_VAR)
|
||||
id_tmp_path = LOGO_FLASH_DIR_VAR "/";
|
||||
id_tmp_path += ChannelName + fileType[i];
|
||||
v_path.push_back(id_tmp_path);
|
||||
|
||||
//create filename with id (LOGO_FLASH_DIR_VAR)
|
||||
id_tmp_path = LOGO_FLASH_DIR_VAR "/";
|
||||
id_tmp_path += strChnId + fileType[i];
|
||||
v_path.push_back(id_tmp_path);
|
||||
|
||||
//create filename with channel name (LOGO_FLASH_DIR)
|
||||
id_tmp_path = LOGO_FLASH_DIR "/";
|
||||
id_tmp_path += ChannelName + fileType[i];
|
||||
|
@@ -54,6 +54,7 @@ class CPictureViewer
|
||||
bool ShowImage(const std::string & filename, bool unscaled=false);
|
||||
bool DecodeImage(const std::string & name, bool showBusySign=false, bool unscaled=false);
|
||||
bool DisplayNextImage();
|
||||
std::string DownloadImage(std::string url);
|
||||
void SetScaling(ScalingMode s){m_scaling=s;}
|
||||
void SetAspectRatio(float aspect_ratio) {m_aspect=aspect_ratio;}
|
||||
void showBusy(int sx, int sy, int width, char r, char g, char b);
|
||||
|
@@ -5,6 +5,7 @@
|
||||
2003 thegoodguy
|
||||
|
||||
Copyright (C) 2008-2012 Stefan Seyfried
|
||||
Copyright (C) 2013-2014 martii
|
||||
|
||||
License: GPL
|
||||
|
||||
@@ -29,6 +30,7 @@
|
||||
|
||||
#include <driver/rcinput.h>
|
||||
#include <driver/abstime.h>
|
||||
#include <system/helpers.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <asm/types.h>
|
||||
@@ -52,13 +54,14 @@
|
||||
|
||||
#include <global.h>
|
||||
#include <driver/shutdown_count.h>
|
||||
#include <neutrino.h>
|
||||
//#include <neutrino.h>
|
||||
#include <neutrinoMessages.h>
|
||||
#include <timerd/timermanager.h>
|
||||
#include <timerdclient/timerdclient.h>
|
||||
#include <sectionsdclient/sectionsdclient.h>
|
||||
#include <cs_api.h>
|
||||
|
||||
//#define RCDEBUG
|
||||
//#define USE_GETTIMEOFDAY
|
||||
|
||||
#define ENABLE_REPEAT_CHECK
|
||||
|
||||
@@ -88,6 +91,8 @@ static bool input_stopped = false;
|
||||
CRCInput::CRCInput()
|
||||
{
|
||||
timerid= 1;
|
||||
repeatkeys = NULL;
|
||||
longPressAny = false;
|
||||
|
||||
// pipe for internal event-queue
|
||||
// -----------------------------
|
||||
@@ -119,7 +124,7 @@ CRCInput::CRCInput()
|
||||
int clilen;
|
||||
memset(&servaddr, 0, sizeof(struct sockaddr_un));
|
||||
servaddr.sun_family = AF_UNIX;
|
||||
strcpy(servaddr.sun_path, NEUTRINO_UDS_NAME);
|
||||
cstrncpy(servaddr.sun_path, NEUTRINO_UDS_NAME, sizeof(servaddr.sun_path));
|
||||
clilen = sizeof(servaddr.sun_family) + strlen(servaddr.sun_path);
|
||||
unlink(NEUTRINO_UDS_NAME);
|
||||
|
||||
@@ -150,7 +155,7 @@ CRCInput::CRCInput()
|
||||
repeat_block = repeat_block_generic = 0;
|
||||
open();
|
||||
rc_last_key = KEY_MAX;
|
||||
firstKey = true;
|
||||
longPressEnd = 0;
|
||||
|
||||
//select and setup remote control hardware
|
||||
set_rc_hw();
|
||||
@@ -176,6 +181,8 @@ void CRCInput::open(int dev)
|
||||
//+++++++++++++++++++++++++++++++++++++++
|
||||
#ifdef KEYBOARD_INSTEAD_OF_REMOTE_CONTROL
|
||||
fd_keyb = STDIN_FILENO;
|
||||
if (fd_rc[0] < 0)
|
||||
fd_rc[0] = fd_keyb;
|
||||
#else
|
||||
fd_keyb = 0;
|
||||
#endif /* KEYBOARD_INSTEAD_OF_REMOTE_CONTROL */
|
||||
@@ -352,13 +359,7 @@ int CRCInput::messageLoop( bool anyKeyCancels, int timeout )
|
||||
|
||||
int CRCInput::addTimer(uint64_t Interval, bool oneshot, bool correct_time )
|
||||
{
|
||||
#ifdef USE_GETTIMEOFDAY
|
||||
struct timeval tv;
|
||||
gettimeofday( &tv, NULL );
|
||||
uint64_t timeNow = (uint64_t) tv.tv_usec + (uint64_t)((uint64_t) tv.tv_sec * (uint64_t) 1000000);
|
||||
#else
|
||||
uint64_t timeNow = time_monotonic_us();
|
||||
#endif
|
||||
|
||||
timer _newtimer;
|
||||
if (!oneshot)
|
||||
@@ -390,19 +391,6 @@ int CRCInput::addTimer(uint64_t Interval, bool oneshot, bool correct_time )
|
||||
return _newtimer.id;
|
||||
}
|
||||
|
||||
#ifdef USE_GETTIMEOFDAY
|
||||
int CRCInput::addTimer(struct timeval Timeout)
|
||||
{
|
||||
uint64_t timesout = (uint64_t) Timeout.tv_usec + (uint64_t)((uint64_t) Timeout.tv_sec * (uint64_t) 1000000);
|
||||
return addTimer( timesout, true, false );
|
||||
}
|
||||
|
||||
int CRCInput::addTimer(const time_t *Timeout)
|
||||
{
|
||||
return addTimer( (uint64_t)*Timeout* (uint64_t) 1000000, true, false );
|
||||
}
|
||||
#endif
|
||||
|
||||
void CRCInput::killTimer(uint32_t &id)
|
||||
{
|
||||
//printf("killing timer %d\n", id);
|
||||
@@ -422,13 +410,7 @@ void CRCInput::killTimer(uint32_t &id)
|
||||
int CRCInput::checkTimers()
|
||||
{
|
||||
int _id = 0;
|
||||
#ifdef USE_GETTIMEOFDAY
|
||||
struct timeval tv;
|
||||
gettimeofday( &tv, NULL );
|
||||
uint64_t timeNow = (uint64_t) tv.tv_usec + (uint64_t)((uint64_t) tv.tv_sec * (uint64_t) 1000000);
|
||||
#else
|
||||
uint64_t timeNow = time_monotonic_us();
|
||||
#endif
|
||||
std::vector<timer>::iterator e;
|
||||
for ( e= timers.begin(); e!= timers.end(); ++e )
|
||||
if ( e->times_out< timeNow+ 2000 )
|
||||
@@ -468,36 +450,18 @@ int CRCInput::checkTimers()
|
||||
|
||||
int64_t CRCInput::calcTimeoutEnd(const int timeout_in_seconds)
|
||||
{
|
||||
#ifdef USE_GETTIMEOFDAY
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return (uint64_t) tv.tv_usec + (uint64_t)((uint64_t) tv.tv_sec + (uint64_t)timeout_in_seconds) * (uint64_t) 1000000;
|
||||
#else
|
||||
return time_monotonic_us() + ((uint64_t)timeout_in_seconds * (uint64_t) 1000000);
|
||||
#endif
|
||||
}
|
||||
|
||||
int64_t CRCInput::calcTimeoutEnd_MS(const int timeout_in_milliseconds)
|
||||
{
|
||||
#ifdef USE_GETTIMEOFDAY
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
uint64_t timeNow = (uint64_t) tv.tv_usec + (uint64_t)((uint64_t) tv.tv_sec * (uint64_t) 1000000);
|
||||
#else
|
||||
uint64_t timeNow = time_monotonic_us();
|
||||
#endif
|
||||
return ( timeNow + timeout_in_milliseconds * 1000 );
|
||||
}
|
||||
|
||||
void CRCInput::getMsgAbsoluteTimeout(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint64_t *TimeoutEnd, bool bAllowRepeatLR)
|
||||
{
|
||||
#ifdef USE_GETTIMEOFDAY
|
||||
struct timeval tv;
|
||||
gettimeofday( &tv, NULL );
|
||||
uint64_t timeNow = (uint64_t) tv.tv_usec + (uint64_t)((uint64_t) tv.tv_sec * (uint64_t) 1000000);
|
||||
#else
|
||||
uint64_t timeNow = time_monotonic_us();
|
||||
#endif
|
||||
uint64_t diff;
|
||||
|
||||
if ( *TimeoutEnd < timeNow+ 100 )
|
||||
@@ -507,16 +471,6 @@ void CRCInput::getMsgAbsoluteTimeout(neutrino_msg_t * msg, neutrino_msg_data_t *
|
||||
|
||||
//printf("CRCInput::getMsgAbsoluteTimeout diff %llx TimeoutEnd %llx now %llx\n", diff, *TimeoutEnd, timeNow);
|
||||
getMsg_us( msg, data, diff, bAllowRepeatLR );
|
||||
#ifdef USE_GETTIMEOFDAY
|
||||
if ( *msg == NeutrinoMessages::EVT_TIMESET )
|
||||
{
|
||||
// recalculate timeout....
|
||||
//uint64_t ta= *TimeoutEnd;
|
||||
*TimeoutEnd= *TimeoutEnd + *(int64_t*) *data;
|
||||
|
||||
//printf("[getMsgAbsoluteTimeout]: EVT_TIMESET - recalculate timeout\n%llx/%llx - %llx/%llx\n", timeNow, *(int64_t*) *data, *TimeoutEnd, ta );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CRCInput::getMsg(neutrino_msg_t * msg, neutrino_msg_data_t * data, int Timeout, bool bAllowRepeatLR)
|
||||
@@ -529,6 +483,43 @@ void CRCInput::getMsg_ms(neutrino_msg_t * msg, neutrino_msg_data_t * data, int T
|
||||
getMsg_us(msg, data, (uint64_t) Timeout * 1000, bAllowRepeatLR);
|
||||
}
|
||||
|
||||
uint32_t *CRCInput::setAllowRepeat(uint32_t *rk) {
|
||||
uint32_t *r = repeatkeys;
|
||||
repeatkeys = rk;
|
||||
return r;
|
||||
}
|
||||
|
||||
bool checkLongPress(uint32_t key); // keybind_setup.cpp
|
||||
|
||||
bool CRCInput::mayLongPress(uint32_t key, bool bAllowRepeatLR)
|
||||
{
|
||||
if (mayRepeat(key, bAllowRepeatLR))
|
||||
return false;
|
||||
if (longPressAny)
|
||||
return true;
|
||||
return checkLongPress(key);
|
||||
}
|
||||
|
||||
bool CRCInput::mayRepeat(uint32_t key, bool bAllowRepeatLR)
|
||||
{
|
||||
if((key == RC_up) || (key == RC_down)
|
||||
|| (key == RC_plus) || (key == RC_minus)
|
||||
|| (key == RC_page_down) || (key == RC_page_up)
|
||||
|| ((bAllowRepeatLR) && ((key == RC_left ) || (key == RC_right))))
|
||||
return true;
|
||||
|
||||
if (repeatkeys) {
|
||||
uint32_t *k = repeatkeys;
|
||||
while (*k != RC_nokey) {
|
||||
if (*k == key) {
|
||||
return true;
|
||||
}
|
||||
k++;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint64_t Timeout, bool bAllowRepeatLR)
|
||||
{
|
||||
static uint64_t last_keypress = 0ULL;
|
||||
@@ -544,7 +535,6 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6
|
||||
|
||||
int timer_id;
|
||||
fd_set rfds;
|
||||
t_input_event ev;
|
||||
|
||||
*data = 0;
|
||||
|
||||
@@ -559,25 +549,13 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6
|
||||
}
|
||||
|
||||
// wiederholung reinmachen - dass wirklich die ganze zeit bis timeout gewartet wird!
|
||||
#ifdef USE_GETTIMEOFDAY
|
||||
gettimeofday( &tv, NULL );
|
||||
uint64_t getKeyBegin = (uint64_t) tv.tv_usec + (uint64_t)((uint64_t) tv.tv_sec * (uint64_t) 1000000);
|
||||
#else
|
||||
uint64_t getKeyBegin = time_monotonic_us();
|
||||
#endif
|
||||
|
||||
while(1) {
|
||||
/* we later check for ev.type = EV_SYN which is 0x00, so set something invalid here... */
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
ev.type = EV_MAX;
|
||||
timer_id = 0;
|
||||
if ( !timers.empty() )
|
||||
{
|
||||
#ifdef USE_GETTIMEOFDAY
|
||||
gettimeofday( &tv, NULL );
|
||||
uint64_t t_n= (uint64_t) tv.tv_usec + (uint64_t)((uint64_t) tv.tv_sec * (uint64_t) 1000000);
|
||||
#else
|
||||
uint64_t t_n = time_monotonic_us();
|
||||
#endif
|
||||
if ( timers[0].times_out< t_n )
|
||||
{
|
||||
timer_id = checkTimers();
|
||||
@@ -950,12 +928,6 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6
|
||||
if ((int64_t)last_keypress > *(int64_t*)p)
|
||||
last_keypress += *(int64_t *)p;
|
||||
|
||||
#ifdef USE_GETTIMEOFDAY
|
||||
// Timer anpassen
|
||||
for(std::vector<timer>::iterator e = timers.begin(); e != timers.end(); ++e)
|
||||
if (e->correct_time)
|
||||
e->times_out+= *(int64_t*) p;
|
||||
#endif
|
||||
*msg = NeutrinoMessages::EVT_TIMESET;
|
||||
*data = (neutrino_msg_data_t) p;
|
||||
dont_delete_p = true;
|
||||
@@ -1197,7 +1169,6 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6
|
||||
*data = (unsigned long) p;
|
||||
dont_delete_p = true;
|
||||
break;
|
||||
|
||||
default :
|
||||
printf("[neutrino] event INITID_TIMERD - unknown eventID 0x%x\n", emsg.eventID );
|
||||
|
||||
@@ -1205,6 +1176,13 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6
|
||||
}
|
||||
else if (emsg.initiatorID == CEventServer::INITID_NEUTRINO)
|
||||
{
|
||||
printf("CRCInput::getMsg_us: INITID_NEUTRINO: msg %x size %d data %x\n", (int) emsg.eventID, emsg.dataSize, (int) p);
|
||||
if (emsg.eventID == NeutrinoMessages::EVT_HOTPLUG) {
|
||||
printf("EVT_HOTPLUG: [%s]\n", (char *) p);
|
||||
*msg = emsg.eventID;
|
||||
*data = (neutrino_msg_data_t) p;
|
||||
dont_delete_p = true;
|
||||
}
|
||||
#if 0
|
||||
if ((emsg.eventID == NeutrinoMessages::EVT_RECORDING_ENDED) &&
|
||||
(read_bytes == sizeof(stream2file_status2_t)))
|
||||
@@ -1225,10 +1203,21 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6
|
||||
}
|
||||
else
|
||||
printf("[neutrino] event - unknown initiatorID 0x%x\n", emsg.initiatorID);
|
||||
if ( !dont_delete_p )
|
||||
{
|
||||
delete[] p;//new [] delete []
|
||||
p= NULL;
|
||||
|
||||
switch (emsg.eventID) {
|
||||
case NeutrinoMessages::EVT_CURRENTEPG:
|
||||
case NeutrinoMessages::EVT_NEXTEPG:
|
||||
{
|
||||
CSectionsdClient::CurrentNextInfo *cn = (CSectionsdClient::CurrentNextInfo *) p;
|
||||
delete cn;
|
||||
p = NULL;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (!dont_delete_p) {
|
||||
delete[] p;
|
||||
p = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1249,8 +1238,11 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6
|
||||
|
||||
for (int i = 0; i < NUMBER_OF_EVENT_DEVICES; i++) {
|
||||
if ((fd_rc[i] != -1) && (FD_ISSET(fd_rc[i], &rfds))) {
|
||||
int ret;
|
||||
ret = read(fd_rc[i], &ev, sizeof(t_input_event));
|
||||
t_input_event ev;
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
/* we later check for ev.type = EV_SYN = 0x00, so set something invalid here... */
|
||||
ev.type = EV_MAX;
|
||||
int ret = read(fd_rc[i], &ev, sizeof(t_input_event));
|
||||
if (ret != sizeof(t_input_event)) {
|
||||
if (errno == ENODEV) {
|
||||
/* hot-unplugged? */
|
||||
@@ -1262,19 +1254,44 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6
|
||||
if (ev.type == EV_SYN)
|
||||
continue; /* ignore... */
|
||||
SHTDCNT::getInstance()->resetSleepTimer();
|
||||
if (firstKey) {
|
||||
firstKey = false;
|
||||
CTimerManager::getInstance()->cancelShutdownOnWakeup();
|
||||
}
|
||||
uint32_t trkey = translate(ev.code);
|
||||
#ifdef _DEBUG
|
||||
printf("key: %04x value %d, translate: %04x -%s-\n", ev.code, ev.value, trkey, getKeyName(trkey).c_str());
|
||||
#endif
|
||||
if (trkey == RC_nokey)
|
||||
continue;
|
||||
|
||||
if (g_settings.longkeypress_duration > LONGKEYPRESS_OFF) {
|
||||
uint64_t longPressNow = time_monotonic_us();
|
||||
if (ev.value == 0 && longPressEnd) {
|
||||
if (longPressNow < longPressEnd) {
|
||||
// Key was a potential long press, but wasn't pressed long enough
|
||||
longPressEnd = 0;
|
||||
ev.value = 1;
|
||||
} else {
|
||||
// Long-press, key released after time limit
|
||||
longPressEnd = 0;
|
||||
continue;
|
||||
}
|
||||
} else if (ev.value == 1 && mayLongPress(trkey, bAllowRepeatLR)) {
|
||||
// A long-press may start here.
|
||||
longPressEnd = longPressNow + 1000 * g_settings.longkeypress_duration;
|
||||
rc_last_key = KEY_MAX;
|
||||
continue;
|
||||
} else if (ev.value == 2 && longPressEnd) {
|
||||
if (longPressEnd < longPressNow) {
|
||||
// Key was pressed long enough.
|
||||
ev.value = 1;
|
||||
trkey |= RC_Repeat;
|
||||
} else {
|
||||
// Long-press, but key still not released. Skip.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ev.value) {
|
||||
#ifdef RCDEBUG
|
||||
printf("got keydown native key: %04x %04x, translate: %04x -%s-\n", ev.code, ev.code&0x1f, translate(ev.code, 0), getKeyName(translate(ev.code, 0)).c_str());
|
||||
printf("rc_last_key %04x rc_last_repeat_key %04x\n\n", rc_last_key, rc_last_repeat_key);
|
||||
#endif
|
||||
uint64_t now_pressed;
|
||||
@@ -1282,21 +1299,17 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6
|
||||
|
||||
tv = ev.time;
|
||||
now_pressed = (uint64_t) tv.tv_usec + (uint64_t)((uint64_t) tv.tv_sec * (uint64_t) 1000000);
|
||||
if (ev.code == rc_last_key) {
|
||||
if (trkey == rc_last_key) {
|
||||
/* only allow selected keys to be repeated */
|
||||
/* (why?) */
|
||||
if( (trkey == RC_up) || (trkey == RC_down ) ||
|
||||
(trkey == RC_plus ) || (trkey == RC_minus ) ||
|
||||
(trkey == RC_page_down ) || (trkey == RC_page_up ) ||
|
||||
((bAllowRepeatLR) && ((trkey == RC_left ) || (trkey == RC_right))) ||
|
||||
(g_settings.shutdown_real_rcdelay && ((trkey == RC_standby) && (g_info.hw_caps->can_shutdown))))
|
||||
if (mayRepeat(trkey, bAllowRepeatLR) ||
|
||||
(g_settings.shutdown_real_rcdelay && ((trkey == RC_standby) && (g_info.hw_caps->can_shutdown))))
|
||||
{
|
||||
#ifdef ENABLE_REPEAT_CHECK
|
||||
if (rc_last_repeat_key != ev.code) {
|
||||
if (rc_last_repeat_key != trkey) {
|
||||
if ((now_pressed > last_keypress + repeat_block) ||
|
||||
/* accept all keys after time discontinuity: */
|
||||
(now_pressed < last_keypress))
|
||||
rc_last_repeat_key = ev.code;
|
||||
rc_last_repeat_key = trkey;
|
||||
else
|
||||
keyok = false;
|
||||
}
|
||||
@@ -1308,7 +1321,7 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6
|
||||
else
|
||||
rc_last_repeat_key = KEY_MAX;
|
||||
|
||||
rc_last_key = ev.code;
|
||||
rc_last_key = trkey;
|
||||
|
||||
if (keyok) {
|
||||
#ifdef ENABLE_REPEAT_CHECK
|
||||
@@ -1329,9 +1342,6 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6
|
||||
} /* if (ev.value) */
|
||||
else {
|
||||
// clear rc_last_key on keyup event
|
||||
#ifdef RCDEBUG
|
||||
printf("got keyup native key: %04x %04x, translate: %04x -%s-\n", ev.code, ev.code&0x1f, translate(ev.code, 0), getKeyName(translate(ev.code, 0)).c_str() );
|
||||
#endif
|
||||
rc_last_key = KEY_MAX;
|
||||
if (trkey == RC_standby) {
|
||||
*msg = RC_standby;
|
||||
@@ -1341,8 +1351,6 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6
|
||||
}
|
||||
}/* if FDSET */
|
||||
} /* for NUMBER_OF_EVENT_DEVICES */
|
||||
if (ev.type == EV_SYN)
|
||||
continue; /* ignore... */
|
||||
|
||||
if(FD_ISSET(fd_pipe_low_priority[0], &rfds))
|
||||
{
|
||||
@@ -1368,12 +1376,7 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6
|
||||
else
|
||||
{
|
||||
//timeout neu kalkulieren
|
||||
#ifdef USE_GETTIMEOFDAY
|
||||
gettimeofday( &tv, NULL );
|
||||
int64_t getKeyNow = (int64_t) tv.tv_usec + (int64_t)((int64_t) tv.tv_sec * (int64_t) 1000000);
|
||||
#else
|
||||
int64_t getKeyNow = time_monotonic_us();
|
||||
#endif
|
||||
int64_t diff = (getKeyNow - getKeyBegin);
|
||||
if( Timeout <= (uint64_t) diff )
|
||||
{
|
||||
@@ -1447,21 +1450,21 @@ unsigned int CRCInput::convertDigitToKey(const unsigned int digit)
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* getUnicodeValue - return unicode value of the key or -1
|
||||
* getUnicodeValue - return unicode value of the key or \0
|
||||
*
|
||||
**************************************************************************/
|
||||
#define UNICODE_VALUE_SIZE 58
|
||||
static const int unicode_value[UNICODE_VALUE_SIZE] = {-1 , -1 , '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', -1 , -1 ,
|
||||
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', -1 , -1 , 'A', 'S',
|
||||
'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', -1 /* FIXME */, -1 /* FIXME */, -1 , '\\', 'Z', 'X', 'C', 'V',
|
||||
'B', 'N', 'M', ',', '.', '/', -1, -1, -1, ' '};
|
||||
static const char unicode_value[UNICODE_VALUE_SIZE * 2] =
|
||||
"\0\0" "\0\0" "1\0" "2\0" "3\0" "4\0" "5\0" "6\0" "7\0" "8\0" "9\0" "0\0" "-\0" "=\0" "\0\0" "\0\0"
|
||||
"Q\0" "W\0" "E\0" "R\0" "T\0" "Y\0" "U\0" "I\0" "O\0" "P\0" "{\0" "}\0" "\0\0" "\0\0" "A\0" "S\0"
|
||||
"D\0" "F\0" "G\0" "H\0" "J\0" "K\0" "L\0" ";\0" "'\0" "\140\0" "\0\0" "\\\0" "Z\0" "X\0" "C\0" "V\0"
|
||||
"B\0" "N\0" "M\0" "\0\0" ".\0" "/\0" "\0\0" "\0\0" "\0\0" " ";
|
||||
|
||||
int CRCInput::getUnicodeValue(const neutrino_msg_t key)
|
||||
const char *CRCInput::getUnicodeValue(const neutrino_msg_t key)
|
||||
{
|
||||
if (key < UNICODE_VALUE_SIZE)
|
||||
return unicode_value[key];
|
||||
else
|
||||
return -1;
|
||||
return unicode_value + key * 2;
|
||||
return "";
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
@@ -1524,20 +1527,6 @@ const char * CRCInput::getSpecialKeyName(const unsigned int key)
|
||||
return "radio";
|
||||
case RC_text:
|
||||
return "text";
|
||||
#if 0
|
||||
case RC_shift_red:
|
||||
return "shift-red";
|
||||
case RC_shift_green:
|
||||
return "shift-green";
|
||||
case RC_shift_yellow:
|
||||
return "shift-yellow";
|
||||
case RC_shift_blue:
|
||||
return "shift-blue";
|
||||
case RC_shift_tv:
|
||||
return "shift-tv";
|
||||
case RC_shift_radio:
|
||||
return "shift-radio";
|
||||
#endif
|
||||
case RC_epg:
|
||||
return "epg";
|
||||
case RC_recall:
|
||||
@@ -1606,21 +1595,18 @@ const char * CRCInput::getSpecialKeyName(const unsigned int key)
|
||||
|
||||
std::string CRCInput::getKeyName(const unsigned int key)
|
||||
{
|
||||
return (std::string)getKeyNameC(key);
|
||||
std::string res(getKeyNameC(key & ~RC_Repeat));
|
||||
if ((key & RC_Repeat) && res != "unknown")
|
||||
res += " (long)";
|
||||
return res;
|
||||
}
|
||||
|
||||
const char *CRCInput::getKeyNameC(const unsigned int key)
|
||||
{
|
||||
int lunicode_value = getUnicodeValue(key);
|
||||
if (lunicode_value == -1)
|
||||
return getSpecialKeyName(key);
|
||||
else
|
||||
{
|
||||
static char tmp[2];
|
||||
tmp[0] = lunicode_value;
|
||||
tmp[1] = 0;
|
||||
return tmp;
|
||||
}
|
||||
const char *lunicode_value = getUnicodeValue(key);
|
||||
if (*lunicode_value)
|
||||
return lunicode_value;
|
||||
return getSpecialKeyName(key);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
@@ -1631,9 +1617,9 @@ int CRCInput::translate(int code)
|
||||
{
|
||||
switch(code)
|
||||
{
|
||||
case 0x100:
|
||||
case 0x100: // FIXME -- needed?
|
||||
return RC_up;
|
||||
case 0x101:
|
||||
case 0x101: // FIXME -- needed?
|
||||
return RC_down;
|
||||
#ifdef HAVE_AZBOX_HARDWARE
|
||||
case KEY_HOME:
|
||||
|
@@ -141,6 +141,9 @@ class CRCInput
|
||||
uint32_t timerid;
|
||||
std::vector<timer> timers;
|
||||
|
||||
uint32_t *repeatkeys;
|
||||
uint64_t longPressEnd;
|
||||
bool longPressAny;
|
||||
int fd_pipe_high_priority[2];
|
||||
int fd_pipe_low_priority[2];
|
||||
int fd_gamerc;
|
||||
@@ -155,7 +158,6 @@ class CRCInput
|
||||
|
||||
int fd_max;
|
||||
int clickfd;
|
||||
bool firstKey;
|
||||
__u16 rc_last_key;
|
||||
void set_dsp();
|
||||
|
||||
@@ -164,6 +166,8 @@ class CRCInput
|
||||
int translate(int code);
|
||||
void calculateMaxFd(void);
|
||||
int checkTimers();
|
||||
bool mayRepeat(uint32_t key, bool bAllowRepeatLR = false);
|
||||
bool mayLongPress(uint32_t key, bool bAllowRepeatLR = false);
|
||||
#ifdef IOC_IR_SET_PRI_PROTOCOL
|
||||
void set_rc_hw(ir_protocol_t ir_protocol, unsigned int ir_address);
|
||||
#endif
|
||||
@@ -290,7 +294,8 @@ class CRCInput
|
||||
static bool isNumeric(const neutrino_msg_t key);
|
||||
static int getNumericValue(const neutrino_msg_t key);
|
||||
static unsigned int convertDigitToKey(const unsigned int digit);
|
||||
static int getUnicodeValue(const neutrino_msg_t key);
|
||||
static const char *getUnicodeValue(const neutrino_msg_t key);
|
||||
uint32_t *setAllowRepeat(uint32_t *);
|
||||
|
||||
static const char * getSpecialKeyName(const unsigned int key);
|
||||
static const char *getKeyNameC(const unsigned int key);
|
||||
@@ -317,6 +322,8 @@ class CRCInput
|
||||
void close_click();
|
||||
void play_click();
|
||||
void reset_dsp(int rate);
|
||||
|
||||
void setLongPressAny(bool b) { longPressAny = b; };
|
||||
};
|
||||
|
||||
|
||||
|
@@ -97,7 +97,6 @@ CRecordInstance::CRecordInstance(const CTimerd::RecordingInfo * const eventinfo,
|
||||
cMovieInfo = new CMovieInfo();
|
||||
recMovieInfo = new MI_MOVIE_INFO();
|
||||
record = NULL;
|
||||
tshift_mode = TSHIFT_MODE_OFF;
|
||||
rec_stop_msg = g_Locale->getText(LOCALE_RECORDING_STOP);
|
||||
}
|
||||
|
||||
@@ -260,6 +259,7 @@ bool CRecordInstance::Stop(bool remove_event)
|
||||
hintBox.paint();
|
||||
|
||||
printf("%s: channel %" PRIx64 " recording_id %d\n", __func__, channel_id, recording_id);
|
||||
printf("%s: file %s.ts\n", __FUNCTION__, filename);
|
||||
SaveXml();
|
||||
/* Stop do close fd - if started */
|
||||
record->Stop();
|
||||
@@ -450,15 +450,19 @@ record_error_msg_t CRecordInstance::Record()
|
||||
//FIXME recording_id (timerd eventID) is 0 means its user recording, in this case timer always added ?
|
||||
if(ret == RECORD_OK && recording_id == 0) {
|
||||
time_t now = time(NULL);
|
||||
int record_end = now+g_settings.record_hours*60*60;
|
||||
if (g_settings.recording_epg_for_end)
|
||||
{
|
||||
int pre=0, post=0;
|
||||
CEPGData epgData;
|
||||
if (CEitManager::getInstance()->getActualEPGServiceKey(channel_id, &epgData )) {
|
||||
g_Timerd->getRecordingSafety(pre, post);
|
||||
if (epgData.epg_times.startzeit > 0)
|
||||
record_end = epgData.epg_times.startzeit + epgData.epg_times.dauer + post;
|
||||
int record_end;
|
||||
if (autoshift) {
|
||||
record_end = now+g_settings.timeshift_hours*60*60;
|
||||
} else {
|
||||
record_end = now+g_settings.record_hours*60*60;
|
||||
if (g_settings.recording_epg_for_end) {
|
||||
int pre=0, post=0;
|
||||
CEPGData epgData;
|
||||
if (CEitManager::getInstance()->getActualEPGServiceKey(channel_id, &epgData )) {
|
||||
g_Timerd->getRecordingSafety(pre, post);
|
||||
if (epgData.epg_times.startzeit > 0)
|
||||
record_end = epgData.epg_times.startzeit + epgData.epg_times.dauer + post;
|
||||
}
|
||||
}
|
||||
}
|
||||
recording_id = g_Timerd->addImmediateRecordTimerEvent(channel_id, now, record_end, epgid, epg_time, apidmode);
|
||||
@@ -676,25 +680,13 @@ record_error_msg_t CRecordInstance::MakeFileName(CZapitChannel * channel)
|
||||
strncat(filename, "_",FILENAMEBUFFERSIZE - strlen(filename)-1);
|
||||
}
|
||||
|
||||
pos = strlen(filename);
|
||||
if (g_settings.recording_epg_for_filename) {
|
||||
if(epgid != 0) {
|
||||
CShortEPGData epgdata;
|
||||
if(CEitManager::getInstance()->getEPGidShort(epgid, &epgdata)) {
|
||||
if (!(epgdata.title.empty())) {
|
||||
strcpy(&(filename[pos]), epgdata.title.c_str());
|
||||
ZapitTools::replace_char(&filename[pos]);
|
||||
}
|
||||
}
|
||||
} else if (!epgTitle.empty()) {
|
||||
strcpy(&(filename[pos]), epgTitle.c_str());
|
||||
ZapitTools::replace_char(&filename[pos]);
|
||||
}
|
||||
}
|
||||
pos = strlen(filename) - ((!autoshift && g_settings.recording_save_in_channeldir) ? 0 : (ext_channel_name.length() /*remove last "_"*/ +1));
|
||||
|
||||
std::string ext_file_name = g_settings.recording_filename_template;
|
||||
MakeExtFileName(channel, ext_file_name);
|
||||
strcpy(&(filename[pos]), UTF8_TO_FILESYSTEM_ENCODING(ext_file_name.c_str()));
|
||||
|
||||
pos = strlen(filename);
|
||||
time_t t = time(NULL);
|
||||
pos += strftime(&(filename[pos]), sizeof(filename) - pos - 1, "%Y%m%d_%H%M%S", localtime(&t));
|
||||
|
||||
if(autoshift)
|
||||
strncat(filename, "_temp",FILENAMEBUFFERSIZE - strlen(filename)-1);
|
||||
@@ -702,6 +694,60 @@ record_error_msg_t CRecordInstance::MakeFileName(CZapitChannel * channel)
|
||||
return RECORD_OK;
|
||||
}
|
||||
|
||||
void CRecordInstance::StringReplace(std::string &str, const std::string search, const std::string rstr)
|
||||
{
|
||||
std::string::size_type ptr = 0;
|
||||
std::string::size_type pos = 0;
|
||||
while((ptr = str.find(search,pos)) != std::string::npos){
|
||||
str.replace(ptr,search.length(),rstr);
|
||||
pos = ptr + rstr.length();
|
||||
}
|
||||
}
|
||||
|
||||
void CRecordInstance::MakeExtFileName(CZapitChannel * channel, std::string &FilenameTemplate)
|
||||
{
|
||||
char buf[256];
|
||||
|
||||
// %C == channel, %T == title, %I == info1, %d == date, %t == time_t
|
||||
if (FilenameTemplate.empty())
|
||||
FilenameTemplate = "%C_%T_%d_%t";
|
||||
|
||||
time_t t = time(NULL);
|
||||
strftime(buf,sizeof(buf),"%Y%m%d",localtime(&t));
|
||||
StringReplace(FilenameTemplate,"%d",buf);
|
||||
|
||||
strftime(buf,sizeof(buf),"%H%M%S",localtime(&t));
|
||||
StringReplace(FilenameTemplate,"%t",buf);
|
||||
|
||||
std::string channel_name = channel->getName();
|
||||
if (!(channel_name.empty())) {
|
||||
strcpy(buf, UTF8_TO_FILESYSTEM_ENCODING(channel_name.c_str()));
|
||||
ZapitTools::replace_char(buf);
|
||||
StringReplace(FilenameTemplate,"%C",buf);
|
||||
}
|
||||
else
|
||||
StringReplace(FilenameTemplate,"%C","no_channel");
|
||||
|
||||
CShortEPGData epgdata;
|
||||
if(CEitManager::getInstance()->getEPGidShort(epgid, &epgdata)) {
|
||||
if (!(epgdata.title.empty())) {
|
||||
strcpy(buf, epgdata.title.c_str());
|
||||
ZapitTools::replace_char(buf);
|
||||
StringReplace(FilenameTemplate,"%T",buf);
|
||||
}
|
||||
else
|
||||
StringReplace(FilenameTemplate,"%T","no_title");
|
||||
|
||||
if (!(epgdata.info1.empty())) {
|
||||
strcpy(buf, epgdata.info1.c_str());
|
||||
ZapitTools::replace_char(buf);
|
||||
StringReplace(FilenameTemplate,"%I",buf);
|
||||
}
|
||||
else
|
||||
StringReplace(FilenameTemplate,"%I","no_info");
|
||||
}
|
||||
}
|
||||
|
||||
void CRecordInstance::GetRecordString(std::string &str, std::string &dur)
|
||||
{
|
||||
CZapitChannel * channel = CServiceManager::getInstance()->FindChannel(channel_id);
|
||||
@@ -832,28 +878,6 @@ const std::string CRecordManager::GetFileName(t_channel_id channel_id, bool time
|
||||
/* return record mode mask, for channel_id not 0, or global */
|
||||
int CRecordManager::GetRecordMode(const t_channel_id channel_id)
|
||||
{
|
||||
#if 0
|
||||
if (RecordingStatus(channel_id) || IsTimeshift(channel_id))
|
||||
{
|
||||
if (RecordingStatus(channel_id) && !IsTimeshift(channel_id))
|
||||
return RECMODE_REC;
|
||||
if (channel_id == 0)
|
||||
{
|
||||
int records = GetRecordCount();
|
||||
if (IsTimeshift(channel_id) && (records == 1))
|
||||
return RECMODE_TSHIFT;
|
||||
else if (IsTimeshift(channel_id) && (records > 1))
|
||||
return RECMODE_REC_TSHIFT;
|
||||
else
|
||||
return RECMODE_OFF;
|
||||
} else
|
||||
{
|
||||
if (IsTimeshift(channel_id))
|
||||
return RECMODE_TSHIFT;
|
||||
}
|
||||
}
|
||||
return RECMODE_OFF;
|
||||
#endif
|
||||
int recmode = RECMODE_OFF;
|
||||
mutex.lock();
|
||||
if (channel_id == 0) {
|
||||
@@ -913,10 +937,6 @@ bool CRecordManager::Record(const CTimerd::RecordingInfo * const eventinfo, cons
|
||||
|
||||
if (g_settings.recording_type == CNeutrinoApp::RECORDING_OFF)
|
||||
return false;
|
||||
#if 0
|
||||
if(!CheckRecording(eventinfo))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
#if 1 // FIXME test
|
||||
StopSectionsd = false;
|
||||
@@ -926,18 +946,6 @@ bool CRecordManager::Record(const CTimerd::RecordingInfo * const eventinfo, cons
|
||||
RunStartScript();
|
||||
|
||||
mutex.lock();
|
||||
#if 0
|
||||
inst = FindInstance(eventinfo->channel_id);
|
||||
if(inst) {
|
||||
if(direct_record) {
|
||||
error_msg = RECORD_BUSY;
|
||||
} else {
|
||||
CTimerd::RecordingInfo * evt = new CTimerd::RecordingInfo(*eventinfo);
|
||||
printf("%s add %llx : %s to pending\n", __FUNCTION__, evt->channel_id, evt->epgTitle);
|
||||
nextmap.push_back((CTimerd::RecordingInfo *)evt);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if(recmap.size() < RECORD_MAX_COUNT) {
|
||||
CFrontend * frontend = NULL;
|
||||
if(CutBackNeutrino(eventinfo->channel_id, frontend)) {
|
||||
@@ -1034,18 +1042,6 @@ bool CRecordManager::StopAutoRecord(bool lock)
|
||||
return (inst != NULL);
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool CRecordManager::CheckRecording(const CTimerd::RecordingInfo * const eventinfo)
|
||||
{
|
||||
t_channel_id live_channel_id = CZapit::getInstance()->GetCurrentChannelID();
|
||||
/* FIXME check if frontend used for timeshift the same and will zap ?? */
|
||||
if(/*(eventinfo->channel_id == live_channel_id) ||*/ !SAME_TRANSPONDER(eventinfo->channel_id, live_channel_id))
|
||||
StopAutoRecord();
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void CRecordManager::StartNextRecording()
|
||||
{
|
||||
CTimerd::RecordingInfo * eventinfo = NULL;
|
||||
@@ -1053,25 +1049,6 @@ void CRecordManager::StartNextRecording()
|
||||
|
||||
for(nextmap_iterator_t it = nextmap.begin(); it != nextmap.end(); it++) {
|
||||
eventinfo = *it;
|
||||
#if 0
|
||||
bool tested = true;
|
||||
if( !recmap.empty() ) {
|
||||
CRecordInstance * inst = FindInstance(eventinfo->channel_id);
|
||||
/* same channel recording and not auto - skip */
|
||||
if(inst && !inst->Timeshift())
|
||||
tested = false;
|
||||
/* there is only auto-record which can be stopped */
|
||||
else if(recmap.size() == 1 && autoshift)
|
||||
tested = true;
|
||||
else {
|
||||
/* there are some recordings, test any (first) for now */
|
||||
recmap_iterator_t fit = recmap.begin();
|
||||
t_channel_id channel_id = fit->second->GetChannelId();
|
||||
tested = (SAME_TRANSPONDER(channel_id, eventinfo->channel_id));
|
||||
}
|
||||
}
|
||||
if(tested)
|
||||
#endif
|
||||
CZapitChannel * channel = CServiceManager::getInstance()->FindChannel(eventinfo->channel_id);
|
||||
if (channel && CFEManager::getInstance()->canTune(channel))
|
||||
{
|
||||
@@ -1140,11 +1117,6 @@ void CRecordManager::StopInstance(CRecordInstance * inst, bool remove_event)
|
||||
if(inst->Timeshift())
|
||||
autoshift = false;
|
||||
|
||||
#if 0
|
||||
t_channel_id live_channel_id = CZapit::getInstance()->GetCurrentChannelID();
|
||||
if(inst->GetChannelId() == live_channel_id)
|
||||
recordingstatus = 0;
|
||||
#endif
|
||||
delete inst;
|
||||
}
|
||||
|
||||
@@ -1278,47 +1250,6 @@ int CRecordManager::handleMsg(const neutrino_msg_t msg, neutrino_msg_data_t data
|
||||
return messages_return::unhandled;
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool CRecordManager::IsTimeshift(t_channel_id channel_id)
|
||||
{
|
||||
bool ret = false;
|
||||
CRecordInstance * inst;
|
||||
mutex.lock();
|
||||
if (channel_id != 0)
|
||||
{
|
||||
inst = FindInstance(channel_id);
|
||||
if(inst && inst->tshift_mode)
|
||||
ret = true;
|
||||
else
|
||||
ret = false;
|
||||
} else
|
||||
{
|
||||
for(recmap_iterator_t it = recmap.begin(); it != recmap.end(); it++)
|
||||
{
|
||||
if(it->second->tshift_mode)
|
||||
{
|
||||
mutex.unlock();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
mutex.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CRecordManager::SetTimeshiftMode(CRecordInstance * inst, int mode)
|
||||
{
|
||||
mutex.lock();
|
||||
/* reset all instances mode ? */
|
||||
for(recmap_iterator_t it = recmap.begin(); it != recmap.end(); it++)
|
||||
it->second->tshift_mode = TSHIFT_MODE_OFF;
|
||||
|
||||
mutex.unlock();
|
||||
if (inst)
|
||||
inst->tshift_mode = mode;
|
||||
}
|
||||
#endif
|
||||
|
||||
void CRecordManager::StartTimeshift()
|
||||
{
|
||||
if(g_RemoteControl->is_video_started)
|
||||
@@ -1326,26 +1257,6 @@ void CRecordManager::StartTimeshift()
|
||||
std::string tmode = "ptimeshift"; // already recording, pause
|
||||
bool res = true;
|
||||
t_channel_id live_channel_id = CZapit::getInstance()->GetCurrentChannelID();
|
||||
#if 0
|
||||
if(RecordingStatus(live_channel_id))
|
||||
{
|
||||
tmode = "ptimeshift"; // already recording, pause
|
||||
if(GetRecordMode(live_channel_id) == RECMODE_TSHIFT)
|
||||
SetTimeshiftMode(FindInstance(live_channel_id), TSHIFT_MODE_PAUSE);
|
||||
} else
|
||||
{
|
||||
if(g_settings.temp_timeshift)
|
||||
{
|
||||
res = StartAutoRecord();
|
||||
SetTimeshiftMode(FindInstance(live_channel_id), TSHIFT_MODE_TEMPORAER);
|
||||
} else
|
||||
{
|
||||
res = Record(live_channel_id);
|
||||
SetTimeshiftMode(FindInstance(live_channel_id), TSHIFT_MODE_PERMANET);
|
||||
}
|
||||
tmode = "timeshift"; // record just started
|
||||
}
|
||||
#endif
|
||||
/* start temporary timeshift if enabled and not running, but dont start second record */
|
||||
if (g_settings.temp_timeshift) {
|
||||
if (!FindTimeshift()) {
|
||||
@@ -1427,10 +1338,6 @@ int CRecordManager::exec(CMenuTarget* parent, const std::string & actionKey )
|
||||
|
||||
return menu_return::RETURN_EXIT_ALL;
|
||||
}
|
||||
#if 0
|
||||
else
|
||||
DisplayInfoMessage(g_Locale->getText(LOCALE_RECORDING_IS_RUNNING));
|
||||
#endif
|
||||
} else if(actionKey == "Timeshift")
|
||||
{
|
||||
StartTimeshift();
|
||||
@@ -1497,7 +1404,6 @@ bool CRecordManager::ShowMenu(void)
|
||||
durations.push_back(duration);
|
||||
|
||||
const char* mode_icon = NEUTRINO_ICON_REC;
|
||||
//if (inst->tshift_mode)
|
||||
if (inst->Timeshift())
|
||||
mode_icon = NEUTRINO_ICON_AUTO_SHIFT;
|
||||
|
||||
@@ -1551,7 +1457,6 @@ bool CRecordManager::ShowMenu(void)
|
||||
|
||||
bool CRecordManager::AskToStop(const t_channel_id channel_id, const int recid)
|
||||
{
|
||||
//int recording_id = 0;
|
||||
std::string title, duration;
|
||||
CRecordInstance * inst;
|
||||
|
||||
@@ -1562,7 +1467,6 @@ bool CRecordManager::AskToStop(const t_channel_id channel_id, const int recid)
|
||||
inst = FindInstance(channel_id);
|
||||
|
||||
if(inst) {
|
||||
//recording_id = inst->GetRecordingId();
|
||||
inst->GetRecordString(title, duration);
|
||||
title += duration;
|
||||
}
|
||||
@@ -1572,9 +1476,6 @@ bool CRecordManager::AskToStop(const t_channel_id channel_id, const int recid)
|
||||
|
||||
if(ShowMsg(LOCALE_SHUTDOWN_RECODING_QUERY, title.c_str(),
|
||||
CMessageBox::mbrYes, CMessageBox::mbYes | CMessageBox::mbNo, NULL, 450, 30, false) == CMessageBox::mbrYes) {
|
||||
#if 0
|
||||
g_Timerd->stopTimerEvent(recording_id);
|
||||
#endif
|
||||
mutex.lock();
|
||||
if (recid)
|
||||
inst = FindInstanceID(recid);
|
||||
|
@@ -82,6 +82,7 @@ class CRecordInstance
|
||||
t_channel_id channel_id;
|
||||
event_id_t epgid;
|
||||
std::string epgTitle;
|
||||
std::string epgInfo1;
|
||||
unsigned char apidmode;
|
||||
time_t epg_time;
|
||||
time_t start_time;
|
||||
@@ -110,7 +111,9 @@ class CRecordInstance
|
||||
bool SaveXml();
|
||||
record_error_msg_t Start(CZapitChannel * channel);
|
||||
void WaitRecMsg(time_t StartTime, time_t WaitTime);
|
||||
public:
|
||||
void MakeExtFileName(CZapitChannel * channel, std::string &FilenameTemplate);
|
||||
void StringReplace(std::string &str, const std::string search, const std::string rstr);
|
||||
public:
|
||||
CRecordInstance(const CTimerd::RecordingInfo * const eventinfo, std::string &dir, bool timeshift = false, bool stream_vtxt_pid = false, bool stream_pmt_pid = false, bool stream_subtitle_pids = false);
|
||||
~CRecordInstance();
|
||||
|
||||
@@ -166,14 +169,12 @@ class CRecordManager : public CMenuTarget /*, public CChangeObserver*/
|
||||
|
||||
bool CutBackNeutrino(const t_channel_id channel_id, CFrontend * &frontend);
|
||||
void RestoreNeutrino(void);
|
||||
bool CheckRecording(const CTimerd::RecordingInfo * const eventinfo);
|
||||
void StartNextRecording();
|
||||
void StopPostProcess();
|
||||
void StopInstance(CRecordInstance * inst, bool remove_event = true);
|
||||
CRecordInstance * FindInstance(t_channel_id);
|
||||
CRecordInstance * FindInstanceID(int recid);
|
||||
CRecordInstance * FindTimeshift();
|
||||
//void SetTimeshiftMode(CRecordInstance * inst=NULL, int mode=TSHIFT_MODE_OFF);
|
||||
|
||||
public:
|
||||
enum record_modes_t
|
||||
@@ -228,7 +229,6 @@ class CRecordManager : public CMenuTarget /*, public CChangeObserver*/
|
||||
CRecordInstance* getRecordInstance(std::string file);
|
||||
// old code
|
||||
#if 0
|
||||
bool IsTimeshift(t_channel_id channel_id=0);
|
||||
bool MountDirectory(const char *recordingDir);
|
||||
bool ChooseRecDir(std::string &dir);
|
||||
int recordingstatus;
|
||||
|
@@ -37,11 +37,13 @@
|
||||
|
||||
#include <driver/scanepg.h>
|
||||
#include <driver/record.h>
|
||||
#include <driver/streamts.h>
|
||||
|
||||
#define EPG_RESCAN_TIME (24*60*60)
|
||||
|
||||
extern CBouquetList * bouquetList;
|
||||
extern CBouquetList * TVfavList;
|
||||
extern CBouquetList * TVbouquetList;
|
||||
|
||||
CEpgScan::CEpgScan()
|
||||
{
|
||||
@@ -71,11 +73,12 @@ void CEpgScan::Clear()
|
||||
current_bmode = -1;
|
||||
next_chid = 0;
|
||||
allfav_done = false;
|
||||
selected_done = false;
|
||||
}
|
||||
|
||||
bool CEpgScan::Running()
|
||||
{
|
||||
return (g_settings.epg_scan && !scanmap.empty());
|
||||
return (CheckMode() && !scanmap.empty());
|
||||
}
|
||||
|
||||
void CEpgScan::AddBouquet(CChannelList * clist)
|
||||
@@ -90,7 +93,7 @@ void CEpgScan::AddBouquet(CChannelList * clist)
|
||||
bool CEpgScan::AddFavorites()
|
||||
{
|
||||
INFO("allfav_done: %d", allfav_done);
|
||||
if ((g_settings.epg_scan != 2) || allfav_done)
|
||||
if ((g_settings.epg_scan != SCAN_FAV) || allfav_done)
|
||||
return false;
|
||||
|
||||
allfav_done = true;
|
||||
@@ -103,6 +106,30 @@ bool CEpgScan::AddFavorites()
|
||||
return (old_size != scanmap.size());
|
||||
}
|
||||
|
||||
bool CEpgScan::AddSelected()
|
||||
{
|
||||
INFO("selected_done: %d", selected_done);
|
||||
if ((g_settings.epg_scan != SCAN_SEL) || selected_done)
|
||||
return false;
|
||||
|
||||
selected_done = true;
|
||||
unsigned old_size = scanmap.size();
|
||||
for (unsigned j = 0; j < TVfavList->Bouquets.size(); ++j) {
|
||||
if (TVfavList->Bouquets[j]->zapitBouquet && TVfavList->Bouquets[j]->zapitBouquet->bScanEpg) {
|
||||
CChannelList * clist = TVfavList->Bouquets[j]->channelList;
|
||||
AddBouquet(clist);
|
||||
}
|
||||
}
|
||||
for (unsigned j = 0; j < TVbouquetList->Bouquets.size(); ++j) {
|
||||
if (TVbouquetList->Bouquets[j]->zapitBouquet && TVbouquetList->Bouquets[j]->zapitBouquet->bScanEpg) {
|
||||
CChannelList * clist = TVbouquetList->Bouquets[j]->channelList;
|
||||
AddBouquet(clist);
|
||||
}
|
||||
}
|
||||
INFO("scan map size: %d -> %d\n", old_size, scanmap.size());
|
||||
return (old_size != scanmap.size());
|
||||
}
|
||||
|
||||
void CEpgScan::AddTransponders()
|
||||
{
|
||||
if(bouquetList->Bouquets.empty())
|
||||
@@ -114,7 +141,25 @@ void CEpgScan::AddTransponders()
|
||||
}
|
||||
|
||||
int mode = CNeutrinoApp::getInstance()->GetChannelMode();
|
||||
if ((g_settings.epg_scan == 1) || (mode == LIST_MODE_FAV)) {
|
||||
if (g_settings.epg_scan == SCAN_SEL) {
|
||||
if (current_bmode != mode) {
|
||||
current_bmode = mode;
|
||||
current_bnum = -1;
|
||||
}
|
||||
int bnum = bouquetList->getActiveBouquetNumber();
|
||||
bool bscan = bouquetList->Bouquets[bnum]->zapitBouquet &&
|
||||
bouquetList->Bouquets[bnum]->zapitBouquet->bScanEpg;
|
||||
|
||||
if ((current_bnum != bnum) && bscan) {
|
||||
current_bnum = bnum;
|
||||
AddBouquet(bouquetList->Bouquets[current_bnum]->channelList);
|
||||
} else {
|
||||
AddSelected();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ((g_settings.epg_scan == SCAN_CURRENT) || (mode == LIST_MODE_FAV)) {
|
||||
/* current bouquet mode */
|
||||
if (current_bmode != mode) {
|
||||
current_bmode = mode;
|
||||
@@ -132,17 +177,23 @@ void CEpgScan::AddTransponders()
|
||||
}
|
||||
}
|
||||
|
||||
bool CEpgScan::CheckMode()
|
||||
{
|
||||
if (!g_settings.epg_scan
|
||||
|| (standby && !(g_settings.epg_scan_mode & MODE_STANDBY))
|
||||
|| (!standby && !(g_settings.epg_scan_mode & MODE_LIVE))
|
||||
|| (!standby && (CFEManager::getInstance()->getEnabledCount() <= 1))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
void CEpgScan::Start(bool instandby)
|
||||
{
|
||||
if (!g_settings.epg_scan)
|
||||
return;
|
||||
if (!instandby && (CFEManager::getInstance()->getEnabledCount() <= 1))
|
||||
return;
|
||||
|
||||
standby = instandby;
|
||||
live_channel_id = CZapit::getInstance()->GetCurrentChannelID();
|
||||
AddTransponders();
|
||||
standby = instandby;
|
||||
//g_RCInput->killTimer(rescan_timer);
|
||||
INFO("starting %s scan, scanning %d, scan map size: %d", standby ? "standby" : "live", scan_in_progress, scanmap.size());
|
||||
if (standby || !scan_in_progress)
|
||||
Next();
|
||||
@@ -167,14 +218,16 @@ int CEpgScan::handleMsg(const neutrino_msg_t msg, neutrino_msg_data_t data)
|
||||
scanned.clear();
|
||||
Clear();
|
||||
g_RCInput->killTimer(rescan_timer);
|
||||
if (standby || (CFEManager::getInstance()->getEnabledCount() > 1)) {
|
||||
if (CheckMode()) {
|
||||
if (standby)
|
||||
g_Zapit->setStandby(false);
|
||||
CNeutrinoApp::getInstance()->wakeupFromStandby();
|
||||
Start(standby);
|
||||
} else {
|
||||
AddTimer();
|
||||
}
|
||||
return messages_return::handled;
|
||||
}
|
||||
if (!g_settings.epg_scan || (!standby && (CFEManager::getInstance()->getEnabledCount() <= 1))) {
|
||||
if (!CheckMode()) {
|
||||
int ret = messages_return::handled;
|
||||
if (msg == NeutrinoMessages::EVT_EIT_COMPLETE)
|
||||
scan_in_progress = false;
|
||||
@@ -232,36 +285,44 @@ int CEpgScan::handleMsg(const neutrino_msg_t msg, neutrino_msg_data_t data)
|
||||
return messages_return::unhandled;
|
||||
}
|
||||
|
||||
void CEpgScan::EnterStandby()
|
||||
void CEpgScan::AddTimer()
|
||||
{
|
||||
if (standby) {
|
||||
CZapit::getInstance()->SetCurrentChannelID(live_channel_id);
|
||||
//CZapit::getInstance()->EnablePlayback(true);
|
||||
g_Zapit->setStandby(true);
|
||||
g_Sectionsd->setPauseScanning(true);
|
||||
}
|
||||
//g_RCInput->killTimer(rescan_timer);
|
||||
if (rescan_timer == 0)
|
||||
rescan_timer = g_RCInput->addTimer(EPG_RESCAN_TIME*1000ULL*1000ULL, true);
|
||||
INFO("rescan timer id %d", rescan_timer);
|
||||
}
|
||||
|
||||
void CEpgScan::EnterStandby()
|
||||
{
|
||||
AddTimer();
|
||||
if (standby) {
|
||||
CZapit::getInstance()->SetCurrentChannelID(live_channel_id);
|
||||
CNeutrinoApp::getInstance()->standbyToStandby();
|
||||
}
|
||||
}
|
||||
|
||||
void CEpgScan::Next()
|
||||
{
|
||||
bool locked = false;
|
||||
|
||||
next_chid = 0;
|
||||
#if 0
|
||||
if (!g_settings.epg_scan)
|
||||
return;
|
||||
if (!CheckMode())
|
||||
return;
|
||||
#endif
|
||||
if (!standby && CNeutrinoApp::getInstance()->getMode() == NeutrinoMessages::mode_standby)
|
||||
return;
|
||||
if (CRecordManager::getInstance()->RecordingStatus())
|
||||
if (CRecordManager::getInstance()->RecordingStatus() || CStreamManager::getInstance()->StreamStatus())
|
||||
return;
|
||||
|
||||
if (g_settings.epg_scan == 2 && scanmap.empty())
|
||||
if (g_settings.epg_scan == SCAN_FAV && scanmap.empty())
|
||||
AddFavorites();
|
||||
if (g_settings.epg_scan == SCAN_SEL && scanmap.empty())
|
||||
AddSelected();
|
||||
|
||||
if (scanmap.empty()) {
|
||||
if (!CheckMode() || scanmap.empty()) {
|
||||
EnterStandby();
|
||||
return;
|
||||
}
|
||||
@@ -299,7 +360,9 @@ _repeat:
|
||||
INFO("skip [%s], cannot tune", newchan->getName().c_str());
|
||||
++it;
|
||||
}
|
||||
if (!next_chid && AddFavorites())
|
||||
if (!next_chid && ((g_settings.epg_scan == SCAN_FAV) && AddFavorites()))
|
||||
goto _repeat;
|
||||
if (!next_chid && ((g_settings.epg_scan == SCAN_SEL) && AddSelected()))
|
||||
goto _repeat;
|
||||
|
||||
if (locked) {
|
||||
|
@@ -28,11 +28,24 @@ typedef eit_scanmap_t::iterator eit_scanmap_iterator_t;
|
||||
|
||||
class CEpgScan
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
SCAN_OFF,
|
||||
SCAN_CURRENT,
|
||||
SCAN_FAV,
|
||||
SCAN_SEL
|
||||
};
|
||||
enum {
|
||||
MODE_LIVE = 0x1,
|
||||
MODE_STANDBY = 0x2,
|
||||
MODE_ALWAYS = 0x3
|
||||
};
|
||||
private:
|
||||
int current_bnum;
|
||||
int current_mode;
|
||||
int current_bmode;
|
||||
bool allfav_done;
|
||||
bool selected_done;
|
||||
bool standby;
|
||||
eit_scanmap_t scanmap;
|
||||
t_channel_id next_chid;
|
||||
@@ -43,8 +56,11 @@ class CEpgScan
|
||||
|
||||
void AddBouquet(CChannelList * clist);
|
||||
bool AddFavorites();
|
||||
bool AddSelected();
|
||||
void AddTransponders();
|
||||
void EnterStandby();
|
||||
bool CheckMode();
|
||||
void AddTimer();
|
||||
|
||||
CEpgScan();
|
||||
public:
|
||||
|
@@ -1,9 +1,7 @@
|
||||
/*
|
||||
Neutrino-GUI - DBoxII-Project
|
||||
|
||||
Copyright (C) 2011-2012 CoolStream International Ltd
|
||||
|
||||
Copyright (C) 2010-2012, 2014 Stefan Seyfried
|
||||
Copyright (C) 2011-2014 CoolStream International Ltd
|
||||
|
||||
based on code which is
|
||||
Copyright (C) 2002 Andreas Oberritter <obi@tuxbox.org>
|
||||
@@ -58,17 +56,12 @@
|
||||
#include <driver/streamts.h>
|
||||
#include <driver/record.h>
|
||||
#include <driver/genpsi.h>
|
||||
#include <pwrmngr.h>
|
||||
|
||||
/* defined in neutrino.cpp */
|
||||
extern cCpuFreqManager * cpuFreq;
|
||||
|
||||
/* experimental mode:
|
||||
* stream not possible, if record running
|
||||
* pids in url ignored, and added from channel, with fake PAT/PMT
|
||||
* different channels supported, only from the same transponder - no zap is done,
|
||||
* different channels supported,
|
||||
* with url like http://coolstream:31339/id=c32400030070283e (channel id)
|
||||
* TODO: multi-tuner support
|
||||
*/
|
||||
#define ENABLE_MULTI_CHANNEL
|
||||
|
||||
@@ -120,23 +113,28 @@ bool CStreamInstance::Stop()
|
||||
|
||||
bool CStreamInstance::Send(ssize_t r)
|
||||
{
|
||||
//OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||
stream_fds_t cfds;
|
||||
mutex.lock();
|
||||
for (stream_fds_t::iterator it = fds.begin(); it != fds.end(); ++it) {
|
||||
int ret, i = 10;
|
||||
do {
|
||||
ret = send(*it, buf, r, MSG_DONTWAIT);
|
||||
#if 0
|
||||
if (ret != r)
|
||||
usleep(100);
|
||||
#endif
|
||||
} while ((ret != r) && (i-- > 0));
|
||||
if (ret != r) {
|
||||
if (r < 0)
|
||||
perror("send");
|
||||
printf("send err, fd %d: (%d from %d)\n", *it, ret, (int)r);
|
||||
}
|
||||
}
|
||||
cfds = fds;
|
||||
mutex.unlock();
|
||||
int flags = 0;
|
||||
if (cfds.size() > 1)
|
||||
flags = MSG_DONTWAIT;
|
||||
for (stream_fds_t::iterator it = cfds.begin(); it != cfds.end(); ++it) {
|
||||
int i = 10;
|
||||
unsigned char *b = buf;
|
||||
ssize_t count = r;
|
||||
do {
|
||||
int ret = send(*it, b, count, flags);
|
||||
if (ret > 0) {
|
||||
b += ret;
|
||||
count -= ret;
|
||||
}
|
||||
} while ((count > 0) && (i-- > 0));
|
||||
if (count)
|
||||
printf("send err, fd %d: (%d from %d)\n", *it, r-count, r);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -149,35 +147,23 @@ void CStreamInstance::Close()
|
||||
|
||||
void CStreamInstance::AddClient(int clientfd)
|
||||
{
|
||||
mutex.lock();
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||
fds.insert(clientfd);
|
||||
printf("CStreamInstance::AddClient: %d (count %d)\n", clientfd, (int)fds.size());
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
void CStreamInstance::RemoveClient(int clientfd)
|
||||
{
|
||||
mutex.lock();
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||
fds.erase(clientfd);
|
||||
close(clientfd);
|
||||
printf("CStreamInstance::RemoveClient: %d (count %d)\n", clientfd, (int)fds.size());
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
void CStreamInstance::run()
|
||||
{
|
||||
printf("CStreamInstance::run: %" PRIx64 "\n", channel_id);
|
||||
|
||||
#if 0
|
||||
// TODO: check if this works... #ifndef HAVE_COOL_HARDWARE
|
||||
/* right now, only one stream is possible anyway and it is not possible
|
||||
* to stream a different channel than the live channel AFAICT, so we can
|
||||
* as well use the live demux */
|
||||
dmx = new cDemux(0);
|
||||
#endif
|
||||
#if 0
|
||||
dmx = new cDemux(STREAM_DEMUX);//FIXME
|
||||
#endif
|
||||
CZapitChannel * tmpchan = CServiceManager::getInstance()->FindChannel(channel_id);
|
||||
if (!tmpchan)
|
||||
return;
|
||||
@@ -204,7 +190,7 @@ void CStreamInstance::run()
|
||||
|
||||
while (running) {
|
||||
ssize_t r = dmx->Read(buf, IN_SIZE, 100);
|
||||
if(r > 0)
|
||||
if (r > 0)
|
||||
Send(r);
|
||||
}
|
||||
|
||||
@@ -265,7 +251,10 @@ bool CStreamManager::Stop()
|
||||
if (!running)
|
||||
return false;
|
||||
running = false;
|
||||
return (OpenThreads::Thread::join() == 0);
|
||||
cancel();
|
||||
bool ret = (OpenThreads::Thread::join() == 0);
|
||||
StopAll();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CStreamManager::SetPort(int newport)
|
||||
@@ -286,13 +275,83 @@ bool CStreamManager::SetPort(int newport)
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CStreamManager::Parse(int fd, stream_pids_t &pids, t_channel_id &chid)
|
||||
CFrontend * CStreamManager::FindFrontend(CZapitChannel * channel)
|
||||
{
|
||||
std::set<CFrontend*> frontends;
|
||||
CFrontend * frontend = NULL;
|
||||
|
||||
t_channel_id chid = channel->getChannelID();
|
||||
if (CRecordManager::getInstance()->RecordingStatus(chid)) {
|
||||
printf("CStreamManager::Parse: channel %llx recorded, aborting..\n", chid);
|
||||
return frontend;
|
||||
}
|
||||
|
||||
t_channel_id live_channel_id = CZapit::getInstance()->GetCurrentChannelID();
|
||||
CFrontend *live_fe = CZapit::getInstance()->GetLiveFrontend();
|
||||
|
||||
if (live_channel_id == chid)
|
||||
return live_fe;
|
||||
|
||||
CFEManager::getInstance()->Lock();
|
||||
|
||||
bool unlock = true;
|
||||
CFEManager::getInstance()->lockFrontend(live_fe);
|
||||
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||
for (streammap_iterator_t it = streams.begin(); it != streams.end(); ++it)
|
||||
frontends.insert(it->second->frontend);
|
||||
|
||||
for (std::set<CFrontend*>::iterator ft = frontends.begin(); ft != frontends.end(); ft++)
|
||||
CFEManager::getInstance()->lockFrontend(*ft);
|
||||
|
||||
frontend = CFEManager::getInstance()->allocateFE(channel, true);
|
||||
|
||||
if (frontend == NULL) {
|
||||
unlock = false;
|
||||
CFEManager::getInstance()->unlockFrontend(live_fe);
|
||||
frontend = CFEManager::getInstance()->allocateFE(channel, true);
|
||||
}
|
||||
|
||||
CFEManager::getInstance()->Unlock();
|
||||
|
||||
if (frontend) {
|
||||
bool found = (live_fe != frontend) || SAME_TRANSPONDER(live_channel_id, chid);
|
||||
bool ret = false;
|
||||
if (found)
|
||||
ret = zapit.zapTo_record(chid) > 0;
|
||||
else
|
||||
ret = zapit.zapTo_serviceID(chid) > 0;
|
||||
|
||||
if (ret) {
|
||||
#ifdef ENABLE_PIP
|
||||
/* FIXME until proper demux management */
|
||||
t_channel_id pip_channel_id = CZapit::getInstance()->GetPipChannelID();
|
||||
if ((pip_channel_id == chid) && (channel->getRecordDemux() == channel->getPipDemux()))
|
||||
zapit.stopPip();
|
||||
#endif
|
||||
} else {
|
||||
frontend = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
CFEManager::getInstance()->Lock();
|
||||
for (std::set<CFrontend*>::iterator ft = frontends.begin(); ft != frontends.end(); ft++)
|
||||
CFEManager::getInstance()->unlockFrontend(*ft);
|
||||
|
||||
if (unlock)
|
||||
CFEManager::getInstance()->unlockFrontend(live_fe);
|
||||
|
||||
CFEManager::getInstance()->Unlock();
|
||||
return frontend;
|
||||
}
|
||||
|
||||
bool CStreamManager::Parse(int fd, stream_pids_t &pids, t_channel_id &chid, CFrontend * &frontend)
|
||||
{
|
||||
char cbuf[512];
|
||||
char *bp;
|
||||
|
||||
FILE * fp = fdopen(fd, "r+");
|
||||
if(fp == NULL) {
|
||||
if (fp == NULL) {
|
||||
perror("fdopen");
|
||||
return false;
|
||||
}
|
||||
@@ -303,7 +362,7 @@ bool CStreamManager::Parse(int fd, stream_pids_t &pids, t_channel_id &chid)
|
||||
while (bp - &cbuf[0] < (int) sizeof(cbuf)) {
|
||||
unsigned char c;
|
||||
int res = read(fd, &c, 1);
|
||||
if(res < 0) {
|
||||
if (res < 0) {
|
||||
perror("read");
|
||||
return false;
|
||||
}
|
||||
@@ -326,74 +385,54 @@ bool CStreamManager::Parse(int fd, stream_pids_t &pids, t_channel_id &chid)
|
||||
return false;
|
||||
}
|
||||
|
||||
chid = CZapit::getInstance()->GetCurrentChannelID();
|
||||
CZapitChannel * channel = CZapit::getInstance()->GetCurrentChannel();
|
||||
|
||||
#ifndef ENABLE_MULTI_CHANNEL
|
||||
/* parse stdin / url path, start dmx filters */
|
||||
do {
|
||||
int pid;
|
||||
int res = sscanf(bp, "%x", &pid);
|
||||
if(res == 1) {
|
||||
printf("New pid: 0x%x\n", pid);
|
||||
if (res == 1) {
|
||||
printf("CStreamManager::Parse: pid: 0x%x\n", pid);
|
||||
pids.insert(pid);
|
||||
}
|
||||
} while ((bp = strchr(bp, ',')) && (bp++));
|
||||
#else
|
||||
t_channel_id tmpid;
|
||||
bp = &cbuf[5];
|
||||
if (sscanf(bp, "id=%llx", &tmpid) == 1) {
|
||||
channel = CServiceManager::getInstance()->FindChannel(tmpid);
|
||||
chid = tmpid;
|
||||
}
|
||||
while ((bp = strchr(bp, ',')) && (bp++));
|
||||
#endif
|
||||
if (!channel)
|
||||
return false;
|
||||
|
||||
chid = CZapit::getInstance()->GetCurrentChannelID();
|
||||
CZapitChannel * channel = CZapit::getInstance()->GetCurrentChannel();
|
||||
printf("CStreamManager::Parse: channel_id %llx [%s]\n", chid, channel->getName().c_str());
|
||||
|
||||
int mode = CNeutrinoApp::getInstance()->getMode();
|
||||
if (mode == NeutrinoMessages::mode_standby && streams.empty()) {
|
||||
printf("CStreamManager::Parse: wakeup zapit..\n");
|
||||
cpuFreq->SetCpuFreq(g_settings.cpufreq * 1000 * 1000);
|
||||
g_Zapit->setStandby(false);
|
||||
g_Zapit->getMode();
|
||||
frontend = FindFrontend(channel);
|
||||
if (!frontend) {
|
||||
printf("CStreamManager::Parse: no free frontend\n");
|
||||
return false;
|
||||
}
|
||||
if(pids.empty()) {
|
||||
#ifdef ENABLE_MULTI_CHANNEL
|
||||
t_channel_id tmpid;
|
||||
bp = &cbuf[5];
|
||||
if (sscanf(bp, "id=%" SCNx64, &tmpid) == 1) {
|
||||
printf("############################# channel_id %" PRIx64 "\n", tmpid);
|
||||
|
||||
CZapitChannel * tmpchan = CServiceManager::getInstance()->FindChannel(tmpid);
|
||||
/* we may switch channels if neutrino is in standby and we are not recording
|
||||
* the current channel TODO: check interaction with recording */
|
||||
bool may_switch =
|
||||
(CNeutrinoApp::getInstance()->getMode() == NeutrinoMessages::mode_standby) &&
|
||||
!CRecordManager::getInstance()->RecordingStatus(chid);
|
||||
if (tmpchan && (tmpid != chid) && (may_switch || SAME_TRANSPONDER(tmpid, chid))) {
|
||||
printf("############################# channel_id %" PRIx64 " -> zap\n", tmpid);
|
||||
bool ret = g_Zapit->zapTo_record(tmpid) > 0;
|
||||
if (ret) {
|
||||
channel = tmpchan;
|
||||
chid = tmpid;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(CRecordManager::getInstance()->RecordingStatus(chid)) {
|
||||
printf("CStreamManager::Parse: channel %" PRIx64 " recorded, aborting..\n", chid);
|
||||
return false;
|
||||
}
|
||||
#ifdef ENABLE_PIP
|
||||
t_channel_id pip_channel_id = CZapit::getInstance()->GetPipChannelID();
|
||||
if ((chid == pip_channel_id) && (channel->getRecordDemux() == channel->getPipDemux())) {
|
||||
printf("CStreamManager::Parse: channel %llx used for pip, aborting..\n", chid);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
AddPids(fd, channel, pids);
|
||||
|
||||
printf("CStreamManager::Parse: no pids in url, using channel %" PRIx64 " pids\n", chid);
|
||||
if(!channel)
|
||||
return false;
|
||||
//pids.insert(0);
|
||||
//pids.insert(channel->getPmtPid());
|
||||
pids.insert(channel->getVideoPid());
|
||||
return !pids.empty();
|
||||
}
|
||||
|
||||
void CStreamManager::AddPids(int fd, CZapitChannel *channel, stream_pids_t &pids)
|
||||
{
|
||||
if (pids.empty()) {
|
||||
printf("CStreamManager::AddPids: no pids in url, using channel %llx pids\n", channel->getChannelID());
|
||||
if (channel->getVideoPid())
|
||||
pids.insert(channel->getVideoPid());
|
||||
for (int i = 0; i < channel->getAudioChannelCount(); i++)
|
||||
pids.insert(channel->getAudioChannel(i)->pid);
|
||||
|
||||
}
|
||||
|
||||
CGenPsi psi;
|
||||
for (stream_pids_t::iterator it = pids.begin(); it != pids.end(); ++it) {
|
||||
if (*it == channel->getVideoPid()) {
|
||||
@@ -404,9 +443,9 @@ bool CStreamManager::Parse(int fd, stream_pids_t &pids, t_channel_id &chid)
|
||||
if (*it == channel->getAudioChannel(i)->pid) {
|
||||
CZapitAudioChannel::ZapitAudioChannelType atype = channel->getAudioChannel(i)->audioChannelType;
|
||||
printf("CStreamManager::Parse: genpsi apid %x (%d)\n", *it, atype);
|
||||
if(channel->getAudioChannel(i)->audioChannelType == CZapitAudioChannel::EAC3){
|
||||
if (channel->getAudioChannel(i)->audioChannelType == CZapitAudioChannel::EAC3) {
|
||||
psi.addPid(*it, EN_TYPE_AUDIO_EAC3, atype, channel->getAudioChannel(i)->description.c_str());
|
||||
}else{
|
||||
} else {
|
||||
psi.addPid(*it, EN_TYPE_AUDIO, atype, channel->getAudioChannel(i)->description.c_str());
|
||||
}
|
||||
}
|
||||
@@ -414,43 +453,85 @@ bool CStreamManager::Parse(int fd, stream_pids_t &pids, t_channel_id &chid)
|
||||
}
|
||||
}
|
||||
//add pcr pid
|
||||
if(channel->getPcrPid() != channel->getVideoPid()){
|
||||
if (channel->getPcrPid() && (channel->getPcrPid() != channel->getVideoPid())) {
|
||||
pids.insert(channel->getPcrPid());
|
||||
psi.addPid(channel->getPcrPid(), EN_TYPE_PCR, 0);
|
||||
}
|
||||
//add teletext pid
|
||||
if (g_settings.recording_stream_vtxt_pid && channel->getTeletextPid() != 0){
|
||||
if (g_settings.recording_stream_vtxt_pid && channel->getTeletextPid() != 0) {
|
||||
pids.insert(channel->getTeletextPid());
|
||||
psi.addPid(channel->getTeletextPid(), EN_TYPE_TELTEX, 0, channel->getTeletextLang());
|
||||
}
|
||||
//add dvb sub pid
|
||||
if (g_settings.recording_stream_subtitle_pids){
|
||||
if (g_settings.recording_stream_subtitle_pids) {
|
||||
for (int i = 0 ; i < (int)channel->getSubtitleCount() ; ++i) {
|
||||
CZapitAbsSub* s = channel->getChannelSub(i);
|
||||
if (s->thisSubType == CZapitAbsSub::DVB) {
|
||||
if(i>9)//max sub pids
|
||||
if (i>9)//max sub pids
|
||||
break;
|
||||
|
||||
CZapitDVBSub* sd = reinterpret_cast<CZapitDVBSub*>(s);
|
||||
pids.insert(sd->pId);
|
||||
psi.addPid( sd->pId, EN_TYPE_DVBSUB, 0, sd->ISO639_language_code.c_str() );
|
||||
psi.addPid(sd->pId, EN_TYPE_DVBSUB, 0, sd->ISO639_language_code.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
psi.genpsi(fd);
|
||||
}
|
||||
|
||||
return !pids.empty();
|
||||
bool CStreamManager::AddClient(int connfd)
|
||||
{
|
||||
stream_pids_t pids;
|
||||
t_channel_id channel_id;
|
||||
CFrontend *frontend;
|
||||
|
||||
if (Parse(connfd, pids, channel_id, frontend)) {
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||
streammap_iterator_t it = streams.find(channel_id);
|
||||
if (it != streams.end()) {
|
||||
it->second->AddClient(connfd);
|
||||
} else {
|
||||
CStreamInstance * stream = new CStreamInstance(connfd, channel_id, pids);
|
||||
stream->frontend = frontend;
|
||||
|
||||
int sendsize = 10*IN_SIZE;
|
||||
unsigned int m = sizeof(sendsize);
|
||||
setsockopt(listenfd, SOL_SOCKET, SO_SNDBUF, (void *)&sendsize, m);
|
||||
if (stream->Start())
|
||||
streams.insert(streammap_pair_t(channel_id, stream));
|
||||
else
|
||||
delete stream;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CStreamManager::RemoveClient(int fd)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||
for (streammap_iterator_t it = streams.begin(); it != streams.end(); ++it) {
|
||||
if (it->second->HasFd(fd)) {
|
||||
CStreamInstance *stream = it->second;
|
||||
stream->RemoveClient(fd);
|
||||
if (stream->GetFds().empty()) {
|
||||
streams.erase(stream->GetChannelId());
|
||||
delete stream;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CStreamManager::run()
|
||||
{
|
||||
struct sockaddr_in servaddr;
|
||||
int clilen = sizeof(servaddr);;
|
||||
int clilen = sizeof(servaddr);
|
||||
|
||||
struct pollfd pfd[128];
|
||||
int poll_cnt;
|
||||
int poll_timeout = -1;
|
||||
|
||||
printf("Starting STREAM thread keeper, tid %ld\n", syscall(__NR_gettid));
|
||||
|
||||
@@ -471,67 +552,36 @@ void CStreamManager::run()
|
||||
}
|
||||
mutex.unlock();
|
||||
//printf("polling, count= %d\n", poll_cnt);
|
||||
int pollres = poll (pfd, poll_cnt, 1000);
|
||||
if (pollres < 0) {
|
||||
perror("CStreamManager::run(): poll");
|
||||
int pollres = poll (pfd, poll_cnt, poll_timeout);
|
||||
if (pollres <= 0) {
|
||||
if (pollres < 0)
|
||||
perror("CStreamManager::run(): poll");
|
||||
continue;
|
||||
}
|
||||
if(pollres == 0)
|
||||
continue;
|
||||
for (int i = poll_cnt - 1; i >= 0; i--) {
|
||||
if (pfd[i].revents & (POLLIN | POLLPRI | POLLHUP | POLLRDHUP)) {
|
||||
printf("fd %d has events %x\n", pfd[i].fd, pfd[i].revents);
|
||||
if (pfd[i].fd == listenfd) {
|
||||
int connfd = accept (listenfd, (struct sockaddr *) &servaddr, (socklen_t *) & clilen);
|
||||
int connfd = accept(listenfd, (struct sockaddr *) &servaddr, (socklen_t *) & clilen);
|
||||
printf("CStreamManager::run(): connection, fd %d\n", connfd);
|
||||
if(connfd < 0) {
|
||||
if (connfd < 0) {
|
||||
perror("CStreamManager::run(): accept");
|
||||
continue;
|
||||
}
|
||||
stream_pids_t pids;
|
||||
t_channel_id channel_id;
|
||||
if (Parse(connfd, pids, channel_id)) {
|
||||
mutex.lock();
|
||||
streammap_iterator_t it = streams.find(channel_id);
|
||||
if (it != streams.end()) {
|
||||
it->second->AddClient(connfd);
|
||||
} else {
|
||||
CStreamInstance * stream = new CStreamInstance(connfd, channel_id, pids);
|
||||
if (stream->Start())
|
||||
streams.insert(streammap_pair_t(channel_id, stream));
|
||||
else
|
||||
delete stream;
|
||||
}
|
||||
mutex.unlock();
|
||||
} else {
|
||||
#if 0
|
||||
if (!AddClient(connfd))
|
||||
close(connfd);
|
||||
}
|
||||
#endif
|
||||
g_RCInput->postMsg(NeutrinoMessages::EVT_STREAM_START, connfd);
|
||||
poll_timeout = 1000;
|
||||
} else {
|
||||
if (pfd[i].revents & (POLLHUP | POLLRDHUP)) {
|
||||
printf("CStreamManager::run(): POLLHUP, fd %d\n", pfd[i].fd);
|
||||
mutex.lock();
|
||||
for (streammap_iterator_t it = streams.begin(); it != streams.end(); ++it) {
|
||||
if (it->second->HasFd(pfd[i].fd)) {
|
||||
CStreamInstance *stream = it->second;
|
||||
stream->RemoveClient(pfd[i].fd);
|
||||
if (stream->GetFds().empty()) {
|
||||
streams.erase(stream->GetChannelId());
|
||||
delete stream;
|
||||
}
|
||||
break;
|
||||
}
|
||||
RemoveClient(pfd[i].fd);
|
||||
if (streams.empty()) {
|
||||
poll_timeout = -1;
|
||||
g_RCInput->postMsg(NeutrinoMessages::EVT_STREAM_STOP, 0);
|
||||
}
|
||||
mutex.unlock();
|
||||
}
|
||||
}
|
||||
/* this is a cheap check */
|
||||
if (streams.empty() &&
|
||||
CNeutrinoApp::getInstance()->getMode() == NeutrinoMessages::mode_standby) {
|
||||
/* this check is more expensive (goes through the socket) */
|
||||
if (g_Zapit->getMode() != 0) {
|
||||
printf("CStreamManager::run: put zapit into standby...\n");
|
||||
g_Zapit->setStandby(true);
|
||||
cpuFreq->SetCpuFreq(g_settings.standby_cpufreq * 1000 * 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -588,8 +638,6 @@ bool CStreamManager::Listen()
|
||||
{
|
||||
struct sockaddr_in socketAddr;
|
||||
int socketOptActive = 1;
|
||||
int sendsize = 10*IN_SIZE;
|
||||
unsigned int m = sizeof(sendsize);
|
||||
|
||||
if ((listenfd = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
fprintf (stderr, "network port %u open: ", port);
|
||||
@@ -619,12 +667,7 @@ bool CStreamManager::Listen()
|
||||
goto _error;
|
||||
}
|
||||
|
||||
#if 1
|
||||
setsockopt(listenfd, SOL_SOCKET, SO_SNDBUF, (void *)&sendsize, m);
|
||||
sendsize = 0;
|
||||
getsockopt(listenfd, SOL_SOCKET, SO_SNDBUF, (void *)&sendsize, &m);
|
||||
printf("CStreamManager::Listen: on %d, fd %d (%d)\n", port, listenfd, sendsize);
|
||||
#endif
|
||||
printf("CStreamManager::Listen: on %d, fd %d\n", port, listenfd);
|
||||
return true;
|
||||
_error:
|
||||
close (listenfd);
|
||||
|
@@ -27,6 +27,7 @@
|
||||
|
||||
#include <dmx.h>
|
||||
#include <zapit/client/zapittypes.h>
|
||||
#include <zapit/femanager.h>
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
@@ -38,6 +39,7 @@ class CStreamInstance : public OpenThreads::Thread
|
||||
private:
|
||||
bool running;
|
||||
cDemux * dmx;
|
||||
CFrontend * frontend;
|
||||
OpenThreads::Mutex mutex;
|
||||
unsigned char * buf;
|
||||
|
||||
@@ -48,6 +50,7 @@ class CStreamInstance : public OpenThreads::Thread
|
||||
bool Send(ssize_t r);
|
||||
void Close();
|
||||
void run();
|
||||
friend class CStreamManager;
|
||||
public:
|
||||
CStreamInstance(int clientfd, t_channel_id chid, stream_pids_t &pids);
|
||||
~CStreamInstance();
|
||||
@@ -74,12 +77,17 @@ class CStreamManager : public OpenThreads::Thread
|
||||
|
||||
OpenThreads::Mutex mutex;
|
||||
static CStreamManager * sm;
|
||||
CZapitClient zapit;
|
||||
|
||||
streammap_t streams;
|
||||
|
||||
bool Listen();
|
||||
bool Parse(int fd, stream_pids_t &pids, t_channel_id &chid);
|
||||
bool Parse(int fd, stream_pids_t &pids, t_channel_id &chid, CFrontend * &frontend);
|
||||
void AddPids(int fd, CZapitChannel * channel, stream_pids_t &pids);
|
||||
void CheckStandby(bool enter);
|
||||
CFrontend * FindFrontend(CZapitChannel * channel);
|
||||
bool StopAll();
|
||||
void RemoveClient(int fd);
|
||||
void run();
|
||||
CStreamManager();
|
||||
public:
|
||||
@@ -91,6 +99,7 @@ class CStreamManager : public OpenThreads::Thread
|
||||
bool StreamStatus(t_channel_id channel_id = 0);
|
||||
bool SetPort(int newport);
|
||||
int GetPort() { return port; }
|
||||
bool AddClient(int fd);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user