recording: testing support for multi-record of the same channel, new libs required

Origin commit data
------------------
Branch: ni/coolstream
Commit: f8aa4262cb
Author: [CST] Focus <focus.cst@gmail.com>
Date: 2012-08-03 (Fri, 03 Aug 2012)


------------------
No further description and justification available within origin commit message!

------------------
This commit was generated by Migit
This commit is contained in:
[CST] Focus
2012-08-03 19:57:45 +04:00
parent 8d25783591
commit b0d70e11e4
4 changed files with 133 additions and 114 deletions

View File

@@ -1455,7 +1455,7 @@ rclock.lockmsg Your box remote control will be locked.\n To unlock it, press <RE
rclock.menueadd Lock RC
rclock.title Lock Remote Control
rclock.unlockmsg Remote control reactivated.
recording.is_running Recording on this channel is already running!
recording.is_running This channel already recorging. Start new record ?
recordingmenu.apids_ac3 record AC3 streams
recordingmenu.apids_alt record alternative streams
recordingmenu.apids Audio streams

View File

@@ -5,6 +5,7 @@
/* */
/* (C) 2008 CoolStream International */
/* */
/* $Id:: $ */
/*******************************************************************************/
#ifndef __RECORD_CS_H_
#define __RECORD_CS_H_
@@ -17,9 +18,7 @@ class cRecord {
private:
cRecordData * rd;
bool enabled;
int num_apids;
int unit;
int nRecordFD;
public:
cRecord(int num = 0);
@@ -27,11 +26,9 @@ public:
bool Open();
void Close(void);
bool Start(int fd, unsigned short vpid, unsigned short * apids, int numapids);
bool Start(int fd, unsigned short vpid, unsigned short * apids, int numapids, uint64_t chid);
bool Stop(void);
bool AddPid(unsigned short pid);
/* not tested */
bool ChangePids(unsigned short vpid, unsigned short * apids, int numapids);
};
#endif // __RECORD_CS_H_

View File

@@ -4,12 +4,11 @@
Copyright (C) 2001 Steffen Hehn 'McClean'
Copyright (C) 2011 CoolStream International Ltd
License: GPL
License: GPLv2
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 2 of the License, or
(at your option) any later version.
the Free Software Foundation;
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -50,7 +49,6 @@
#include <gui/nfs.h>
#include <driver/record.h>
#include <ca_cs.h>
#include <zapit/capmt.h>
#include <zapit/channel.h>
#include <zapit/getservices.h>
@@ -64,7 +62,6 @@
*/
extern CRemoteControl * g_RemoteControl; /* neutrino.cpp */
t_channel_id rec_channel_id;
bool sectionsd_getActualEPGServiceKey(const t_channel_id uniqueServiceKey, CEPGData * epgdata);
bool sectionsd_getEPGidShort(event_id_t epgID, CShortEPGData * epgdata);
@@ -134,7 +131,7 @@ void CRecordInstance::WaitRecMsg(time_t StartTime, time_t WaitTime)
usleep(100000);
}
record_error_msg_t CRecordInstance::Start(CZapitChannel * channel /*, APIDList &apid_list*/)
record_error_msg_t CRecordInstance::Start(CZapitChannel * channel)
{
int fd;
std::string tsfile;
@@ -193,11 +190,6 @@ record_error_msg_t CRecordInstance::Start(CZapitChannel * channel /*, APIDList &
CCamManager::getInstance()->Start(channel->getChannelID(), CCamManager::RECORD);
int len;
unsigned char * pmt = channel->getRawPmt(len);
cCA * ca = cCA::GetInstance();
ca->SendPMT(channel->getRecordDemux() /*DEMUX_SOURCE_2*/, pmt, len);
//CVFD::getInstance()->ShowIcon(VFD_ICON_CAM1, true);
WaitRecMsg(msg_start_time, 2);
hintBox.hide();
@@ -652,7 +644,9 @@ void CRecordInstance::GetRecordString(std::string &str)
str = "Unknown channel : " + GetEpgTitle();
return;
}
str = channel->getName() + ": " + GetEpgTitle();
char stime[15];
strftime(stime, sizeof(stime), "%H:%M:%S ", localtime(&start_time));
str = stime + channel->getName() + ": " + GetEpgTitle();
}
//-------------------------------------------------------------------------
@@ -699,9 +693,19 @@ CRecordManager * CRecordManager::getInstance()
CRecordInstance * CRecordManager::FindInstance(t_channel_id channel_id)
{
recmap_iterator_t it = recmap.find(channel_id);
if(it != recmap.end())
for (recmap_iterator_t it = recmap.begin(); it != recmap.end(); it++) {
if (it->second->GetChannelId() == channel_id)
return it->second;
}
return NULL;
}
CRecordInstance * CRecordManager::FindInstanceID(int recid)
{
for (recmap_iterator_t it = recmap.begin(); it != recmap.end(); it++) {
if (it->second->GetRecordingId() == recid)
return it->second;
}
return NULL;
}
@@ -742,7 +746,7 @@ int CRecordManager::GetRecordMode(const t_channel_id channel_id)
return RECMODE_REC_TSHIFT;
else
return RECMODE_OFF;
}else
} else
{
if (IsTimeshift(channel_id))
return RECMODE_TSHIFT;
@@ -797,24 +801,25 @@ bool CRecordManager::Record(const CTimerd::RecordingInfo * const eventinfo, cons
RunStartScript();
mutex.lock();
recmap_iterator_t it = recmap.find(eventinfo->channel_id);
if(it != recmap.end()) {
//inst = it->second;
#if 0
inst = FindInstance(eventinfo->channel_id);
if(inst) {
if(direct_record) {
error_msg = RECORD_BUSY;
} else {
//nextmap.push_back((CTimerd::RecordingInfo *)eventinfo);
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 if(recmap.size() < RECORD_MAX_COUNT) {
#if 1//FIXME test
} else
#endif
if(recmap.size() < RECORD_MAX_COUNT) {
CZapitChannel * channel = CServiceManager::getInstance()->FindChannel(eventinfo->channel_id);
CFrontend * frontend = CFEManager::getInstance()->allocateFE(channel);
int mode = channel->getServiceType() != ST_DIGITAL_RADIO_SOUND_SERVICE ?
NeutrinoMessages::mode_tv : NeutrinoMessages::mode_radio;
#endif
if(frontend && CutBackNeutrino(eventinfo->channel_id, mode)) {
std::string newdir;
if(dir && strlen(dir))
@@ -824,21 +829,18 @@ bool CRecordManager::Record(const CTimerd::RecordingInfo * const eventinfo, cons
else
newdir = Directory;
if (inst == NULL)
inst = new CRecordInstance(eventinfo, newdir, timeshift, StreamVTxtPid, StreamPmtPid);
inst->frontend = frontend;
error_msg = inst->Record();
if(error_msg == RECORD_OK) {
recmap.insert(std::pair<t_channel_id, CRecordInstance*>(eventinfo->channel_id, inst));
recmap.insert(recmap_pair_t(inst->GetRecordingId(), inst));
if(timeshift)
autoshift = true;
// mimic old behavior for start/stop menu option chooser, still actual ?
t_channel_id live_channel_id = CZapit::getInstance()->GetCurrentChannelID();
if(eventinfo->channel_id == live_channel_id) {
if(eventinfo->channel_id == live_channel_id)
recordingstatus = 1;
rec_channel_id = live_channel_id;//FIXME
}
} else {
delete inst;
}
@@ -914,6 +916,7 @@ bool CRecordManager::CheckRecording(const CTimerd::RecordingInfo * const eventin
return true;
}
/* FIXME no check for multi-tuner */
void CRecordManager::StartNextRecording()
{
CTimerd::RecordingInfo * eventinfo = NULL;
@@ -972,6 +975,7 @@ bool CRecordManager::TimeshiftOnly()
return (autoshift && (count == 1));
}
/* FIXME no check for multi-tuner */
bool CRecordManager::SameTransponder(const t_channel_id channel_id)
{
bool same = true;
@@ -990,26 +994,34 @@ bool CRecordManager::SameTransponder(const t_channel_id channel_id)
return same;
}
void CRecordManager::StopInstance(CRecordInstance * inst, bool remove_event)
{
inst->Stop(remove_event);
recmap.erase(inst->GetRecordingId());
if(inst->Timeshift())
autoshift = false;
t_channel_id live_channel_id = CZapit::getInstance()->GetCurrentChannelID();
if(inst->GetChannelId() == live_channel_id)
recordingstatus = 0;
delete inst;
}
bool CRecordManager::Stop(const t_channel_id channel_id)
{
printf("%s: %llx\n", __FUNCTION__, channel_id);
mutex.lock();
/* FIXME stop all ? show list ? */
CRecordInstance * inst = FindInstance(channel_id);
if(inst != NULL) {
inst->Stop();
recmap.erase(channel_id);
if(inst->Timeshift())
autoshift = false;
delete inst;
t_channel_id live_channel_id = CZapit::getInstance()->GetCurrentChannelID();
if(channel_id == live_channel_id) {
recordingstatus = 0;
rec_channel_id = 0;//FIXME
}
} else
if(inst != NULL)
StopInstance(inst);
else
printf("%s: channel %llx not recording\n", __FUNCTION__, channel_id);
mutex.unlock();
StopPostProcess();
@@ -1025,17 +1037,11 @@ bool CRecordManager::Stop(const CTimerd::RecordingStopInfo * recinfo)
mutex.lock();
CRecordInstance * inst = FindInstance(recinfo->channel_id);
//CRecordInstance * inst = FindInstance(recinfo->channel_id);
CRecordInstance * inst = FindInstanceID(recinfo->eventID);
if(inst != NULL && recinfo->eventID == inst->GetRecordingId()) {
inst->Stop(false);
recmap.erase(recinfo->channel_id);
if(inst->Timeshift())
autoshift = false;
delete inst;
StopInstance(inst, false);
ret = true;
t_channel_id live_channel_id = CZapit::getInstance()->GetCurrentChannelID();
if(recinfo->channel_id == live_channel_id)
recordingstatus = 0;
} else {
for(nextmap_iterator_t it = nextmap.begin(); it != nextmap.end(); it++) {
if((*it)->eventID == recinfo->eventID) {
@@ -1111,12 +1117,11 @@ bool CRecordManager::IsTimeshift(t_channel_id channel_id)
ret = true;
else
ret = false;
}else
} else
{
for(recmap_iterator_t it = recmap.begin(); it != recmap.end(); it++)
{
inst = it->second;
if(inst && inst->tshift_mode)
if(it->second->tshift_mode)
{
mutex.unlock();
return true;
@@ -1129,14 +1134,11 @@ bool CRecordManager::IsTimeshift(t_channel_id channel_id)
void CRecordManager::SetTimeshiftMode(CRecordInstance * inst, int mode)
{
CRecordInstance * tmp_inst;
mutex.lock();
/* reset all instances mode ? */
for(recmap_iterator_t it = recmap.begin(); it != recmap.end(); it++)
{
tmp_inst = it->second;
if (tmp_inst)
tmp_inst->tshift_mode = TSHIFT_MODE_OFF;
}
it->second->tshift_mode = TSHIFT_MODE_OFF;
mutex.unlock();
if (inst)
inst->tshift_mode = mode;
@@ -1154,13 +1156,13 @@ void CRecordManager::StartTimeshift()
tmode = "ptimeshift"; // already recording, pause
if(GetRecordMode(live_channel_id) == RECMODE_TSHIFT)
SetTimeshiftMode(FindInstance(live_channel_id), TSHIFT_MODE_PAUSE);
}else
} else
{
if(g_settings.temp_timeshift)
{
res = StartAutoRecord();
SetTimeshiftMode(FindInstance(live_channel_id), TSHIFT_MODE_TEMPORAER);
}else
} else
{
res = Record(live_channel_id);
SetTimeshiftMode(FindInstance(live_channel_id), TSHIFT_MODE_PERMANET);
@@ -1198,8 +1200,9 @@ int CRecordManager::exec(CMenuTarget* parent, const std::string & actionKey )
mutex.lock();
for(recmap_iterator_t it = recmap.begin(); it != recmap.end(); it++)
{
t_channel_id channel_id = it->first;
//t_channel_id channel_id = it->first;
CRecordInstance * inst = it->second;
t_channel_id channel_id = inst->GetChannelId();
snprintf(rec_msg, sizeof(rec_msg)-1, rec_msg1, records-i, records);
inst->SetStopMessage(rec_msg);
@@ -1211,13 +1214,22 @@ int CRecordManager::exec(CMenuTarget* parent, const std::string & actionKey )
mutex.unlock();
}
return menu_return::RETURN_EXIT_ALL;
}else if(actionKey == "Record")
} else if(actionKey == "Record")
{
printf("[neutrino] direct record\n");
t_channel_id live_channel_id = CZapit::getInstance()->GetCurrentChannelID();
if(!CRecordManager::getInstance()->RecordingStatus(live_channel_id))
{
//if(!CRecordManager::getInstance()->RecordingStatus(live_channel_id))
bool tostart = true;
CRecordInstance * inst = FindInstance(live_channel_id);
if (inst) {
std::string title;
inst->GetRecordString(title);
tostart = (ShowMsgUTF(LOCALE_RECORDING_IS_RUNNING, title.c_str(),
CMessageBox::mbrYes, CMessageBox::mbYes | CMessageBox::mbNo, NULL, 450, 30, false) == CMessageBox::mbrYes);
}
if (tostart) {
CRecordManager::getInstance()->Record(live_channel_id);
if(!g_InfoViewer->is_visible) // show Infoviewer
@@ -1225,13 +1237,15 @@ 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));
}else if(actionKey == "Timeshift")
#endif
} else if(actionKey == "Timeshift")
{
StartTimeshift();
return menu_return::RETURN_EXIT_ALL;
}else if(actionKey == "Stop_record")
} else if(actionKey == "Stop_record")
{
if(!CRecordManager::getInstance()->RecordingStatus()) {
ShowHintUTF(LOCALE_MAINMENU_RECORDING_STOP, g_Locale->getText(LOCALE_RECORDINGMENU_RECORD_IS_NOT_RUNNING), 450, 2);
@@ -1239,7 +1253,6 @@ int CRecordManager::exec(CMenuTarget* parent, const std::string & actionKey )
}
}
ShowMenu();
return menu_return::RETURN_REPAINT;
}
@@ -1330,7 +1343,8 @@ bool CRecordManager::ShowMenu(void)
if (select >= 0 && select < RECORD_MAX_COUNT) {
/* in theory, timer event can expire while we in menu ? lock and check again */
mutex.lock();
CRecordInstance * inst = FindInstance(channel_ids[select]);
//CRecordInstance * inst = FindInstance(channel_ids[select]);
CRecordInstance * inst = FindInstanceID(recording_ids[select]);
if(inst == NULL || recording_ids[select] != inst->GetRecordingId()) {
printf("%s: channel %llx event id %d not found\n", __FUNCTION__, channel_ids[select], recording_ids[select]);
mutex.unlock();
@@ -1338,18 +1352,23 @@ bool CRecordManager::ShowMenu(void)
}
mutex.unlock();
//return Stop(channel_ids[select]);
return AskToStop(channel_ids[select]);
return AskToStop(channel_ids[select], recording_ids[select]);
}
return false;
}
bool CRecordManager::AskToStop(const t_channel_id channel_id)
bool CRecordManager::AskToStop(const t_channel_id channel_id, const int recid)
{
int recording_id = 0;
std::string title;
CRecordInstance * inst;
mutex.lock();
CRecordInstance * inst = FindInstance(channel_id);
if (recid)
inst = FindInstanceID(recid);
else
inst = FindInstance(channel_id);
if(inst) {
recording_id = inst->GetRecordingId();
inst->GetRecordString(title);

View File

@@ -4,12 +4,11 @@
Copyright (C) 2001 Steffen Hehn 'McClean'
Copyright (C) 2011 CoolStream International Ltd
License: GPL
License: GPLv2
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 2 of the License, or
(at your option) any later version.
the Free Software Foundation;
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -105,7 +104,7 @@ class CRecordInstance
void FillMovieInfo(CZapitChannel * channel, APIDList & apid_lis);
record_error_msg_t MakeFileName(CZapitChannel * channel);
bool SaveXml();
record_error_msg_t Start(CZapitChannel * channel /*, APIDList &apid_list*/);
record_error_msg_t Start(CZapitChannel * channel);
void WaitRecMsg(time_t StartTime, time_t WaitTime);
public:
CRecordInstance(const CTimerd::RecordingInfo * const eventinfo, std::string &dir, bool timeshift = false, bool stream_vtxt_pid = false, bool stream_pmt_pid = false);
@@ -117,6 +116,7 @@ class CRecordInstance
void SetRecordingId(int id) { recording_id = id; };
int GetRecordingId(void) { return recording_id; };
t_channel_id GetChannelId(void) { return channel_id; };
std::string GetEpgTitle(void) { return epgTitle; };
MI_MOVIE_INFO * GetMovieInfo(void) { return recMovieInfo; };
void GetRecordString(std::string& str);
@@ -128,7 +128,8 @@ class CRecordInstance
CFrontend * frontend;
};
typedef std::map<t_channel_id, CRecordInstance*> recmap_t;
typedef std::pair<int, CRecordInstance*> recmap_pair_t;
typedef std::map<int, CRecordInstance*> recmap_t;
typedef recmap_t::iterator recmap_iterator_t;
typedef std::list<CTimerd::RecordingInfo *> nextmap_t;
@@ -158,7 +159,9 @@ class CRecordManager : public CMenuTarget, public CChangeObserver
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);
void SetTimeshiftMode(CRecordInstance * inst=NULL, int mode=TSHIFT_MODE_OFF);
public:
@@ -181,7 +184,7 @@ class CRecordManager : public CMenuTarget, public CChangeObserver
bool Stop(const CTimerd::RecordingStopInfo * recinfo);
bool Update(const t_channel_id channel_id);
bool ShowMenu(void);
bool AskToStop(const t_channel_id channel_id);
bool AskToStop(const t_channel_id channel_id, const int recid = 0);
int exec(CMenuTarget* parent, const std::string & actionKey);
bool StartAutoRecord();
bool StopAutoRecord();